widl #28: add support for enums
Huw D M Davies
h.davies1 at physics.ox.ac.uk
Tue Jan 25 08:54:14 CST 2005
Huw Davies <huw at codeweavers.com>
Add enum support.
Another attempt at getting the alignment bits correct.
--
Huw Davies
huw at codeweavers.com
diff -u -p -X widl/.cvsignore -x '.*' -x '*.o' widl.orig/parser.y widl/parser.y
--- tools/widl/parser.y 2005-01-25 14:18:48.647522829 +0000
+++ tools/widl/parser.y 2005-01-25 14:39:42.022713893 +0000
@@ -428,15 +428,19 @@ enum_list: enum
enum: ident '=' expr_const { $$ = reg_const($1);
$$->eval = $3;
$$->lval = $3->cval;
+ $$->type = make_type(RPC_FC_LONG, &std_int);
}
| ident { $$ = reg_const($1);
$$->lval = 0; /* default for first enum entry */
+ $$->type = make_type(RPC_FC_LONG, &std_int);
}
;
enumdef: tENUM t_ident '{' enums '}' { $$ = get_typev(RPC_FC_ENUM16, $2, tsENUM);
$$->fields = $4;
$$->defined = TRUE;
+ if(in_typelib)
+ add_enum($$);
}
;
diff -u -p -X widl/.cvsignore -x '.*' -x '*.o' widl.orig/typelib.c widl/typelib.c
--- tools/widl/typelib.c 2005-01-18 13:42:34.000000000 +0000
+++ tools/widl/typelib.c 2005-01-25 14:39:42.040709645 +0000
@@ -250,3 +250,16 @@ void add_struct(type_t *structure)
LINK(entry, typelib->entry);
typelib->entry = entry;
}
+
+void add_enum(type_t *enumeration)
+{
+ typelib_entry_t *entry;
+ if (!typelib) return;
+
+ chat("add enum: %s\n", enumeration->name);
+ entry = xmalloc(sizeof(*entry));
+ entry->kind = TKIND_ENUM;
+ entry->u.enumeration = enumeration;
+ LINK(entry, typelib->entry);
+ typelib->entry = entry;
+}
diff -u -p -X widl/.cvsignore -x '.*' -x '*.o' widl.orig/typelib.h widl/typelib.h
--- tools/widl/typelib.h 2005-01-18 13:42:34.000000000 +0000
+++ tools/widl/typelib.h 2005-01-25 14:39:42.041709409 +0000
@@ -28,6 +28,7 @@ extern void add_interface(type_t *iface)
extern void add_coclass(class_t *cls);
extern void add_module(type_t *module);
extern void add_struct(type_t *structure);
+extern void add_enum(type_t *enumeration);
/* Copied from wtypes.h. Not included directly because that would create a
* circular dependency (after all, wtypes.h is generated by widl...) */
diff -u -p -X widl/.cvsignore -x '.*' -x '*.o' widl.orig/widltypes.h widl/widltypes.h
--- tools/widl/widltypes.h 2005-01-18 13:42:34.000000000 +0000
+++ tools/widl/widltypes.h 2005-01-25 14:39:42.041709409 +0000
@@ -240,6 +240,7 @@ struct _typelib_entry_t {
type_t *interface;
type_t *module;
type_t *structure;
+ type_t *enumeration;
} u;
DECL_LINK(typelib_entry_t)
};
diff -u -p -X widl/.cvsignore -x '.*' -x '*.o' widl.orig/write_msft.c widl/write_msft.c
--- tools/widl/write_msft.c 2005-01-25 14:42:24.151444027 +0000
+++ tools/widl/write_msft.c 2005-01-25 14:41:28.105673214 +0000
@@ -1353,9 +1353,9 @@ static HRESULT add_func_desc(msft_typein
typeinfo->names[index] = offset;
namedata = typeinfo->typelib->typelib_segment_data[MSFT_SEG_NAME] + offset;
- namedata[9] &= ~0x10;
if (*((INT *)namedata) == -1) {
*((INT *)namedata) = typeinfo->typelib->typelib_typeinfo_offsets[typeinfo->typeinfo->typekind >> 16];
+ namedata[9] &= ~0x10;
}
for (arg = last_arg, i = 0; arg; arg = PREV_LINK(arg), i++) {
@@ -1369,49 +1369,13 @@ static HRESULT add_func_desc(msft_typein
return S_OK;
}
-
-static void set_alignment(
- msft_typeinfo_t* typeinfo,
- WORD cbAlignment)
-{
-
- if (!cbAlignment) return;
- if (cbAlignment > 16) return;
-
- typeinfo->typeinfo->typekind &= ~0xf800;
-
- /* FIXME: There's probably some way to simplify this. */
- switch (typeinfo->typeinfo->typekind & 15) {
- case TKIND_ALIAS:
- default:
- break;
-
- case TKIND_ENUM:
- case TKIND_INTERFACE:
- case TKIND_DISPATCH:
- case TKIND_COCLASS:
- if (cbAlignment > 4) cbAlignment = 4;
- break;
-
- case TKIND_RECORD:
- case TKIND_MODULE:
- case TKIND_UNION:
- cbAlignment = 1;
- break;
- }
-
- typeinfo->typeinfo->typekind |= cbAlignment << 11;
-
- return;
-}
-
static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var)
{
int offset;
INT *typedata;
int var_datawidth;
int var_alignment;
- int var_type_size;
+ int var_type_size, var_kind = 0 /* VAR_PERINSTANCE */;
int alignment;
int varflags = 0;
attr_t *attr;
@@ -1460,20 +1424,26 @@ static HRESULT add_var_desc(msft_typeinf
/* pad out starting position to data width */
typeinfo->datawidth += var_alignment - 1;
typeinfo->datawidth &= ~(var_alignment - 1);
- typedata[4] = typeinfo->datawidth;
-
- /* add the new variable to the total data width */
- typeinfo->datawidth += var_datawidth;
+
+ if((typeinfo->typeinfo->typekind & 0xf) == TKIND_ENUM) {
+ write_value(typeinfo->typelib, &typedata[4], VT_I4, &var->lval);
+ var_kind = 2; /* VAR_CONST */
+ var_type_size += 16; /* sizeof(VARIANT) */
+ typeinfo->datawidth = var_datawidth;
+ } else {
+ typedata[4] = typeinfo->datawidth;
+ typeinfo->datawidth += var_datawidth;
+ }
/* add type description size to total required allocation */
- typedata[3] += var_type_size << 16;
+ typedata[3] += var_type_size << 16 | var_kind;
/* fix type alignment */
alignment = (typeinfo->typeinfo->typekind >> 11) & 0x1f;
if (alignment < var_alignment) {
alignment = var_alignment;
- typeinfo->typeinfo->typekind &= ~0xf800;
- typeinfo->typeinfo->typekind |= alignment << 11;
+ typeinfo->typeinfo->typekind &= ~0xffc0;
+ typeinfo->typeinfo->typekind |= alignment << 11 | alignment << 6;
}
/* ??? */
@@ -1499,7 +1469,9 @@ static HRESULT add_var_desc(msft_typeinf
if (*((INT *)namedata) == -1) {
*((INT *)namedata) = typeinfo->typelib->typelib_typeinfo_offsets[typeinfo->typeinfo->typekind >> 16];
namedata[9] |= 0x10;
- }
+ } else
+ namedata[9] &= ~0x10;
+
if ((typeinfo->typeinfo->typekind & 15) == TKIND_ENUM) {
namedata[9] |= 0x20;
}
@@ -1544,8 +1516,7 @@ static msft_typeinfo_t *create_msft_type
msft_typeinfo->typeinfo = typeinfo;
- typeinfo->typekind |= kind | 0x220;
- set_alignment(msft_typeinfo, 4);
+ typeinfo->typekind |= kind | 0x20;
for( ; attr; attr = NEXT_LINK(attr)) {
switch(attr->type) {
@@ -1620,6 +1591,7 @@ static void add_interface_typeinfo(msft_
msft_typeinfo = create_msft_typeinfo(typelib, TKIND_INTERFACE, interface->name, interface->attrs,
typelib->typelib_header.nrtypeinfos);
msft_typeinfo->typeinfo->size = 4;
+ msft_typeinfo->typeinfo->typekind |= 0x2200;
if(interface->ref)
add_impl_type(msft_typeinfo, interface->ref);
@@ -1651,6 +1623,25 @@ static void add_structure_typeinfo(msft_
}
}
+static void add_enum_typeinfo(msft_typelib_t *typelib, type_t *enumeration)
+{
+ int idx = 0;
+ var_t *cur = enumeration->fields;
+ msft_typeinfo_t *msft_typeinfo;
+
+ enumeration->typelib_idx = typelib->typelib_header.nrtypeinfos;
+ msft_typeinfo = create_msft_typeinfo(typelib, TKIND_ENUM, enumeration->name, enumeration->attrs,
+ typelib->typelib_header.nrtypeinfos);
+ msft_typeinfo->typeinfo->size = 0;
+
+ while(NEXT_LINK(cur)) cur = NEXT_LINK(cur);
+ while(cur) {
+ add_var_desc(msft_typeinfo, idx, cur);
+ idx++;
+ cur = PREV_LINK(cur);
+ }
+}
+
static void add_entry(msft_typelib_t *typelib, typelib_entry_t *entry)
{
switch(entry->kind) {
@@ -1662,13 +1653,16 @@ static void add_entry(msft_typelib_t *ty
add_structure_typeinfo(typelib, entry->u.structure);
break;
+ case TKIND_ENUM:
+ add_enum_typeinfo(typelib, entry->u.enumeration);
+ break;
+
default:
error("add_entry: unhandled type %d\n", entry->kind);
break;
}
}
-
static void set_name(msft_typelib_t *typelib)
{
int offset;
More information about the wine-patches
mailing list