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