widl #10: better type handling

Huw D M Davies h.davies1 at physics.ox.ac.uk
Wed Jan 12 10:54:08 CST 2005


        Huw Davies <huw at codeweavers.com>
        Better type encoding.  (Interface ptrs still not there yet).
-- 
Huw Davies
huw at codeweavers.com
Index: tools/widl/typelib.c
===================================================================
RCS file: /home/wine/wine/tools/widl/typelib.c,v
retrieving revision 1.5
diff -u -p -r1.5 typelib.c
--- tools/widl/typelib.c	6 Jan 2005 20:45:21 -0000	1.5
+++ tools/widl/typelib.c	12 Jan 2005 16:51:14 -0000
@@ -95,6 +95,7 @@ unsigned short get_type_vt(type_t *t)
 {
   unsigned short vt;
 
+  chat("get_type_vt: %p type->name %s\n", t, t->name);
   if (t->name) {
     vt = builtin_vt(t->name);
     if (vt) return vt;
@@ -139,13 +140,15 @@ unsigned short get_type_vt(type_t *t)
       if (match(t->ref->name, "IUnknown"))
         return VT_UNKNOWN;
     }
-    /* FIXME: should we recurse and add a VT_BYREF? */
-    /* Or just return VT_PTR? */
-    if(t->ref) return get_type_vt(t->ref);
+    if(t->ref)
+      return VT_PTR;
+
     error("get_type_vt: unknown-deref-type: %d\n", t->ref->type);
     break;
   case RPC_FC_STRUCT:
     return VT_USERDEFINED;
+  case 0:
+    return 0;
   default:
     error("get_type_vt: unknown-type: %d\n", t->type);
   }
@@ -156,6 +159,7 @@ unsigned short get_var_vt(var_t *v)
 {
   unsigned short vt;
 
+  chat("get_var_vt: %p tname %s\n", v, v->tname);
   if (v->tname) {
     vt = builtin_vt(v->tname);
     if (vt) return vt;
Index: tools/widl/typelib.h
===================================================================
RCS file: /home/wine/wine/tools/widl/typelib.h,v
retrieving revision 1.3
diff -u -p -r1.3 typelib.h
--- tools/widl/typelib.h	6 Jan 2005 20:45:21 -0000	1.3
+++ tools/widl/typelib.h	12 Jan 2005 16:51:14 -0000
@@ -84,6 +84,7 @@ enum VARENUM {
     VT_TYPEMASK = 0xfff
 };
 extern unsigned short get_type_vt(type_t *t);
+extern unsigned short get_var_vt(var_t *v);
 
 extern int create_msft_typelib(typelib_t *typelib);
 #endif
Index: tools/widl/write_msft.c
===================================================================
RCS file: /home/wine/wine/tools/widl/write_msft.c,v
retrieving revision 1.6
diff -u -p -r1.6 write_msft.c
--- tools/widl/write_msft.c	11 Jan 2005 10:38:51 -0000	1.6
+++ tools/widl/write_msft.c	12 Jan 2005 16:51:14 -0000
@@ -650,7 +650,7 @@ static int ctl2_alloc_importfile(
 
 
 /****************************************************************************
- *	ctl2_encode_type
+ *	encode_type
  *
  *  Encodes a type, storing information in the TYPEDESC and ARRAYDESC
  *  segments as needed.
@@ -660,11 +660,10 @@ static int ctl2_alloc_importfile(
  *  Success: 0.
  *  Failure: -1.
  */
-static int ctl2_encode_type(
+static int encode_type(
 	msft_typelib_t *typelib,   /* [I] The type library in which to encode the TYPEDESC. */
-	type_t *type,              /* [I] The type description to encode. */
-        int ptr_level,             /* [I] ptr level */
-        expr_t *array,             /* [I] arrary description */
+        int vt,                    /* [I] vt to encode */
+	type_t *type,              /* [I] type */
 	int *encoded_type,         /* [O] The encoded type description. */
 	int *width,                /* [O] The width of the type, or NULL. */
 	int *alignment,            /* [O] The alignment of the type, or NULL. */
@@ -673,93 +672,17 @@ static int ctl2_encode_type(
     int default_type;
     int scratch;
     int typeoffset;
-    int arrayoffset;
     int *typedata;
-    int *arraydata;
     int target_type;
     int child_size;
-    unsigned short vt = get_type_vt(type);
 
-    chat("encode_type vt %d ptr_level %d\n", vt, ptr_level);
+    chat("encode_type vt %d type %p\n", vt, type);
 
     default_type = 0x80000000 | (vt << 16) | vt;
     if (!width) width = &scratch;
     if (!alignment) alignment = &scratch;
     if (!decoded_size) decoded_size = &scratch;
 
-    *decoded_size = 0;
-
-    if(ptr_level--) {
-
-	ctl2_encode_type(typelib, type, ptr_level, array, &target_type, NULL, NULL, &child_size);
-
-	for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
-	    typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
-	    if (((typedata[0] & 0xffff) == VT_PTR) && (typedata[1] == target_type)) break;
-	}
-
-	if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
-	    int mix_field;
-	    
-	    if (target_type & 0x80000000) {
-		mix_field = ((target_type >> 16) & 0x3fff) | VT_BYREF;
-	    } else {
-		typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type];
-		mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe;
-	    }
-
-	    typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
-	    typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
-
-	    typedata[0] = (mix_field << 16) | VT_PTR;
-	    typedata[1] = target_type;
-	}
-
-	*encoded_type = typeoffset;
-
-	*width = 4;
-	*alignment = 4;
-	*decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size;
-        return 0;
-    }
-
-    if(array) {
-        expr_t *dim = array;
-        int num_dims = 1, elements = 1;
-
-        while(NEXT_LINK(dim)) {
-            dim = NEXT_LINK(dim);
-            num_dims++;
-        }
-        chat("array with %d dimensions\n", num_dims);
-	ctl2_encode_type(typelib, type, 0, NULL, &target_type, width, alignment, NULL);
-	arrayoffset = ctl2_alloc_segment(typelib, MSFT_SEG_ARRAYDESC, (2 + 2 * num_dims) * sizeof(long), 0);
-	arraydata = (void *)&typelib->typelib_segment_data[MSFT_SEG_ARRAYDESC][arrayoffset];
-
-	arraydata[0] = target_type;
-        arraydata[1] = num_dims;
-        arraydata[1] |= ((num_dims * 2 * sizeof(long)) << 16);
-
-        arraydata += 2;
-        while(dim) {
-            arraydata[0] = dim->cval;
-            arraydata[1] = 0;
-            arraydata += 2;
-            elements *= dim->cval;
-            dim = PREV_LINK(dim);
-        }
-
-	typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
-	typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
-
-	typedata[0] = (0x7ffe << 16) | VT_CARRAY;
-	typedata[1] = arrayoffset;
-
-	*encoded_type = typeoffset;
-	*width = *width * elements;
-	*decoded_size = 20 /*sizeof(ARRAYDESC)*/ + (num_dims - 1) * 8 /*sizeof(SAFEARRAYBOUND)*/;
-        return 0;
-    }
 
     switch (vt) {
     case VT_I1:
@@ -822,6 +745,45 @@ static int ctl2_encode_type(
 	*alignment = 1;
 	break;
 
+    case VT_PTR:
+      {
+        int next_vt;
+        while((next_vt = get_type_vt(type->ref)) == 0) {
+            type = type->ref;
+            if(!type) error("encode_type: type->ref is null\n");
+        }
+
+	encode_type(typelib, next_vt, type->ref, &target_type, NULL, NULL, &child_size);
+
+	for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
+	    typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
+	    if (((typedata[0] & 0xffff) == VT_PTR) && (typedata[1] == target_type)) break;
+	}
+
+	if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
+	    int mix_field;
+	    
+	    if (target_type & 0x80000000) {
+		mix_field = ((target_type >> 16) & 0x3fff) | VT_BYREF;
+	    } else {
+		typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type];
+		mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe;
+	    }
+
+	    typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
+	    typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
+
+	    typedata[0] = (mix_field << 16) | VT_PTR;
+	    typedata[1] = target_type;
+	}
+
+	*encoded_type = typeoffset;
+
+	*width = 4;
+	*alignment = 4;
+	*decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size;
+        break;
+    }
 #if 0
 
 
@@ -903,6 +865,123 @@ static int ctl2_encode_type(
     return 0;
 }
 
+static void dump_type(type_t *t)
+{
+    chat("dump_type: %p name %s type %d ref %p rname %s\n", t, t->name, t->type, t->ref, t->rname);
+    if(t->ref) dump_type(t->ref);
+}
+
+static int encode_var(
+	msft_typelib_t *typelib,   /* [I] The type library in which to encode the TYPEDESC. */
+	var_t *var,                /* [I] The type description to encode. */
+	int *encoded_type,         /* [O] The encoded type description. */
+	int *width,                /* [O] The width of the type, or NULL. */
+	int *alignment,            /* [O] The alignment of the type, or NULL. */
+	int *decoded_size)         /* [O] The total size of the unencoded TYPEDESCs, including nested descs. */
+{
+    int typeoffset;
+    int *typedata;
+    int target_type;
+    int child_size;
+    int vt;
+    int scratch;
+    type_t *type;
+
+    if (!width) width = &scratch;
+    if (!alignment) alignment = &scratch;
+    if (!decoded_size) decoded_size = &scratch;
+    *decoded_size = 0;
+
+    chat("encode_var: var %p var->tname %s var->type %p var->ptr_level %d var->type->ref %p\n", var, var->tname, var->type, var->ptr_level, var->type->ref);
+    if(var->ptr_level--) {
+	encode_var(typelib, var, &target_type, NULL, NULL, &child_size);
+        var->ptr_level++;
+
+	for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
+	    typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
+	    if (((typedata[0] & 0xffff) == VT_PTR) && (typedata[1] == target_type)) break;
+	}
+
+	if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
+	    int mix_field;
+	    
+	    if (target_type & 0x80000000) {
+		mix_field = ((target_type >> 16) & 0x3fff) | VT_BYREF;
+	    } else {
+		typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type];
+		mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe;
+	    }
+
+	    typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
+	    typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
+
+	    typedata[0] = (mix_field << 16) | VT_PTR;
+	    typedata[1] = target_type;
+	}
+
+	*encoded_type = typeoffset;
+
+	*width = 4;
+	*alignment = 4;
+	*decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size;
+        return 0;
+    }
+
+    if(var->array) {
+        expr_t *dim = var->array;
+        expr_t *array_save;
+        int num_dims = 1, elements = 1, arrayoffset;
+        int *arraydata;
+
+        while(NEXT_LINK(dim)) {
+            dim = NEXT_LINK(dim);
+            num_dims++;
+        }
+        chat("array with %d dimensions\n", num_dims);
+        array_save = var->array;
+        var->array = NULL;
+	encode_var(typelib, var, &target_type, width, alignment, NULL);
+        var->array = array_save;
+	arrayoffset = ctl2_alloc_segment(typelib, MSFT_SEG_ARRAYDESC, (2 + 2 * num_dims) * sizeof(long), 0);
+	arraydata = (void *)&typelib->typelib_segment_data[MSFT_SEG_ARRAYDESC][arrayoffset];
+
+	arraydata[0] = target_type;
+        arraydata[1] = num_dims;
+        arraydata[1] |= ((num_dims * 2 * sizeof(long)) << 16);
+
+        arraydata += 2;
+        while(dim) {
+            arraydata[0] = dim->cval;
+            arraydata[1] = 0;
+            arraydata += 2;
+            elements *= dim->cval;
+            dim = PREV_LINK(dim);
+        }
+
+	typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
+	typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
+
+	typedata[0] = (0x7ffe << 16) | VT_CARRAY;
+	typedata[1] = arrayoffset;
+
+	*encoded_type = typeoffset;
+	*width = *width * elements;
+	*decoded_size = 20 /*sizeof(ARRAYDESC)*/ + (num_dims - 1) * 8 /*sizeof(SAFEARRAYBOUND)*/;
+        return 0;
+    }
+    dump_type(var->type);
+
+    vt = get_var_vt(var);
+    type = var->type;
+    while(!vt) {
+        type = type->ref;
+        if(!type) error("encode_var: type->ref is null\n");
+        vt = get_type_vt(type);
+    }
+    return encode_type(typelib, vt, type, encoded_type, width, alignment, decoded_size);
+}
+
+    
 /****************************************************************************
  *	ctl2_find_nth_reference
  *
@@ -1037,7 +1116,7 @@ static HRESULT add_func_desc(msft_typein
 
     /* fill out the basic type information */
     typedata[0] = (0x18 + extra_attr * sizeof(int) + (num_params * (num_defaults ? 16 : 12))) | (index << 16);
-    ctl2_encode_type(typeinfo->typelib, func->def->type, func->def->ptr_level, func->def->array, &typedata[1], NULL, NULL, &decoded_size);
+    encode_var(typeinfo->typelib, func->def, &typedata[1], NULL, NULL, &decoded_size);
     typedata[2] = funcflags;
     typedata[3] = ((52 /*sizeof(FUNCDESC)*/ + decoded_size) << 16) | typeinfo->typeinfo->cbSizeVft;
     typedata[4] = (index << 16) | (callconv << 8) | 9;
@@ -1070,7 +1149,7 @@ static HRESULT add_func_desc(msft_typein
 
         if(defaultdata) *defaultdata = -1;
 
-	ctl2_encode_type(typeinfo->typelib, arg->type, arg->ptr_level, arg->array, paramdata, NULL, NULL, &decoded_size);
+	encode_var(typeinfo->typelib, arg, paramdata, NULL, NULL, &decoded_size);
         for(attr = arg->attrs; attr; attr = NEXT_LINK(attr)) {
             switch(attr->type) {
             case ATTR_DEFAULTVALUE_EXPR:
@@ -1240,9 +1319,8 @@ static HRESULT add_var_desc(msft_typeinf
     typeinfo->offsets[index] = offset;
 
     /* figure out type widths and whatnot */
-    ctl2_encode_type(typeinfo->typelib, var->type, var->ptr_level, var->array,
-                     &typedata[1], &var_datawidth, &var_alignment,
-                     &var_type_size);
+    encode_var(typeinfo->typelib, var, &typedata[1], &var_datawidth,
+               &var_alignment, &var_type_size);
 
     /* pad out starting position to data width */
     typeinfo->datawidth += var_alignment - 1;



More information about the wine-patches mailing list