widl: Remove use of type_t "ref" field for base types
Dan Hipschman
dsh at linux.ucla.edu
Thu Aug 24 20:01:18 CDT 2006
Currently, the type_t "ref" field is used for three different purposes.
If the type's a pointer, it gives the pointed to type. If the type's a
base type, it references a static type with the name of the base type.
If the type's a typedef'd type, it points to the original type. This
last case is the hardest to deal with because it requires special case
handling everywhere. Any time you use a type, you must check if it's a
typedef and dereference it to get the real type. A lot of existing code
just doesn't do this and produces the wrong results.
This patch removes the first usage of "ref" and simplifies the code a bit
to boot. More importantly, it sets up elimination of the third usage of
"ref" which I hope to submit a patch for soon if this one gets accepted.
My goal is to use "ref" for only one purpose so we don't need a bunch of
special case handling for typedefs.
ChangeLog:
* Remove usage of type_t ref field for base types; simplify code.
---
tools/widl/header.c | 46 +-----------------------
tools/widl/parser.y | 93 ++++++++++++++++++++++++++++++++++++------------
tools/widl/typelib.c | 29 +++++++++++++--
tools/widl/widl.c | 1 +
tools/widl/widltypes.h | 6 +++
5 files changed, 103 insertions(+), 72 deletions(-)
diff --git a/tools/widl/header.c b/tools/widl/header.c
index 0042c63..1503d33 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -210,42 +210,6 @@ void write_type(FILE *h, type_t *t, cons
if (t->sign > 0) fprintf(h, "signed ");
else if (t->sign < 0) fprintf(h, "unsigned ");
switch (t->type) {
- case RPC_FC_BYTE:
- if (t->ref) fprintf(h, t->ref->name);
- else fprintf(h, "byte");
- break;
- case RPC_FC_CHAR:
- if (t->ref) fprintf(h, t->ref->name);
- else fprintf(h, "char");
- break;
- case RPC_FC_WCHAR:
- fprintf(h, "WCHAR");
- break;
- case RPC_FC_USMALL:
- case RPC_FC_SMALL:
- if (t->ref) fprintf(h, t->ref->name);
- else fprintf(h, "small");
- break;
- case RPC_FC_USHORT:
- case RPC_FC_SHORT:
- if (t->ref) fprintf(h, t->ref->name);
- else fprintf(h, "short");
- break;
- case RPC_FC_ULONG:
- case RPC_FC_LONG:
- if (t->ref) fprintf(h, t->ref->name);
- else fprintf(h, "long");
- break;
- case RPC_FC_HYPER:
- if (t->ref) fprintf(h, t->ref->name);
- else fprintf(h, "hyper");
- break;
- case RPC_FC_FLOAT:
- fprintf(h, "float");
- break;
- case RPC_FC_DOUBLE:
- fprintf(h, "double");
- break;
case RPC_FC_ENUM16:
case RPC_FC_ENUM32:
if (t->defined && !t->written && !t->ignore) {
@@ -259,14 +223,6 @@ void write_type(FILE *h, type_t *t, cons
}
else fprintf(h, "enum %s", t->name);
break;
- case RPC_FC_ERROR_STATUS_T:
- if (t->ref) fprintf(h, t->ref->name);
- else fprintf(h, "error_status_t");
- break;
- case RPC_FC_BIND_PRIMITIVE:
- if (t->ref) fprintf(h, t->ref->name);
- else fprintf(h, "handle_t");
- break;
case RPC_FC_STRUCT:
case RPC_FC_CVSTRUCT:
case RPC_FC_CPSTRUCT:
@@ -302,7 +258,7 @@ void write_type(FILE *h, type_t *t, cons
fprintf(h, "*");
break;
default:
- fprintf(h, "(unknown-type:%d)", t->type);
+ fprintf(h, "%s", t->name);
}
}
else {
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index 745056f..e6a3a8e 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -84,6 +84,8 @@ static var_t *make_var(char *name);
static func_t *make_func(var_t *def, var_t *args);
static type_t *make_class(char *name);
static type_t *make_safearray(void);
+static type_t *make_builtin(char *name);
+static type_t *make_int(int sign);
static type_t *reg_type(type_t *type, const char *name, int t);
static type_t *reg_types(type_t *type, var_t *names, int t);
@@ -107,11 +109,6 @@ #define tsENUM 1
#define tsSTRUCT 2
#define tsUNION 3
-static type_t std_bool = { "boolean" };
-static type_t std_int = { "int" };
-static type_t std_int64 = { "__int64" };
-static type_t std_uhyper = { "MIDL_uhyper" };
-
%}
%union {
attr_t *attr;
@@ -490,10 +487,10 @@ enum_list: enum { if (!$$->eval)
enum: ident '=' expr_const { $$ = reg_const($1);
$$->eval = $3;
- $$->type = make_type(RPC_FC_LONG, &std_int);
+ $$->type = make_int(0);
}
| ident { $$ = reg_const($1);
- $$->type = make_type(RPC_FC_LONG, &std_int);
+ $$->type = make_int(0);
}
;
@@ -609,8 +606,8 @@ ident: aIDENTIFIER { $$ = make_var(
| tVERSION { $$ = make_var($<str>1); }
;
-base_type: tBYTE { $$ = make_type(RPC_FC_BYTE, NULL); }
- | tWCHAR { $$ = make_type(RPC_FC_WCHAR, NULL); }
+base_type: tBYTE { $$ = make_builtin($<str>1); }
+ | tWCHAR { $$ = make_builtin($<str>1); }
| int_std
| tSIGNED int_std { $$ = $2; $$->sign = 1; }
| tUNSIGNED int_std { $$ = $2; $$->sign = -1;
@@ -620,31 +617,35 @@ base_type: tBYTE { $$ = make_type(RPC
case RPC_FC_SHORT: $$->type = RPC_FC_USHORT; break;
case RPC_FC_LONG: $$->type = RPC_FC_ULONG; break;
case RPC_FC_HYPER:
- if (!$$->ref) { $$->ref = &std_uhyper; $$->sign = 0; }
+ if ($$->name[0] == 'h') /* hyper, as opposed to __int64 */
+ {
+ $$ = alias($$, "MIDL_uhyper");
+ $$->sign = 0;
+ }
break;
default: break;
}
}
- | tUNSIGNED { $$ = make_type(RPC_FC_ULONG, &std_int); $$->sign = -1; }
- | tFLOAT { $$ = make_type(RPC_FC_FLOAT, NULL); }
- | tSINGLE { $$ = make_type(RPC_FC_FLOAT, NULL); }
- | tDOUBLE { $$ = make_type(RPC_FC_DOUBLE, NULL); }
- | tBOOLEAN { $$ = make_type(RPC_FC_BYTE, &std_bool); /* ? */ }
- | tERRORSTATUST { $$ = make_type(RPC_FC_ERROR_STATUS_T, NULL); }
- | tHANDLET { $$ = make_type(RPC_FC_BIND_PRIMITIVE, NULL); /* ? */ }
+ | tUNSIGNED { $$ = make_int(-1); }
+ | tFLOAT { $$ = make_builtin($<str>1); }
+ | tSINGLE { $$ = duptype(find_type("float", 0), 1); }
+ | tDOUBLE { $$ = make_builtin($<str>1); }
+ | tBOOLEAN { $$ = make_builtin($<str>1); }
+ | tERRORSTATUST { $$ = make_builtin($<str>1); }
+ | tHANDLET { $$ = make_builtin($<str>1); }
;
m_int:
| tINT
;
-int_std: tINT { $$ = make_type(RPC_FC_LONG, &std_int); } /* win32 only */
- | tSHORT m_int { $$ = make_type(RPC_FC_SHORT, NULL); }
- | tSMALL { $$ = make_type(RPC_FC_SMALL, NULL); }
- | tLONG m_int { $$ = make_type(RPC_FC_LONG, NULL); }
- | tHYPER m_int { $$ = make_type(RPC_FC_HYPER, NULL); }
- | tINT64 { $$ = make_type(RPC_FC_HYPER, &std_int64); }
- | tCHAR { $$ = make_type(RPC_FC_CHAR, NULL); }
+int_std: tINT { $$ = make_builtin($<str>1); }
+ | tSHORT m_int { $$ = make_builtin($<str>1); }
+ | tSMALL { $$ = make_builtin($<str>1); }
+ | tLONG m_int { $$ = make_builtin($<str>1); }
+ | tHYPER m_int { $$ = make_builtin($<str>1); }
+ | tINT64 { $$ = make_builtin($<str>1); }
+ | tCHAR { $$ = make_builtin($<str>1); }
;
coclass: tCOCLASS aIDENTIFIER { $$ = make_class($2); }
@@ -862,6 +863,50 @@ version:
%%
+static void decl_builtin(const char *name, unsigned char type)
+{
+ type_t *t = make_type(type, NULL);
+ t->name = xstrdup(name);
+ reg_type(t, name, 0);
+}
+
+static type_t *make_builtin(char *name)
+{
+ /* NAME is strdup'd in the lexer */
+ type_t *t = duptype(find_type(name, 0), 0);
+ t->name = name;
+ return t;
+}
+
+static type_t *make_int(int sign)
+{
+ type_t *t = duptype(find_type("int", 0), 1);
+
+ t->sign = sign;
+ if (sign < 0)
+ t->type = t->type == RPC_FC_LONG ? RPC_FC_ULONG : RPC_FC_USHORT;
+
+ return t;
+}
+
+void init_types(void)
+{
+ decl_builtin("byte", RPC_FC_BYTE);
+ decl_builtin("wchar_t", RPC_FC_WCHAR);
+ decl_builtin("int", RPC_FC_LONG); /* win32 */
+ decl_builtin("short", RPC_FC_SHORT);
+ decl_builtin("small", RPC_FC_SMALL);
+ decl_builtin("long", RPC_FC_LONG);
+ decl_builtin("hyper", RPC_FC_HYPER);
+ decl_builtin("__int64", RPC_FC_HYPER);
+ decl_builtin("char", RPC_FC_CHAR);
+ decl_builtin("float", RPC_FC_FLOAT);
+ decl_builtin("double", RPC_FC_DOUBLE);
+ decl_builtin("boolean", RPC_FC_BYTE);
+ decl_builtin("error_status_t", RPC_FC_ERROR_STATUS_T);
+ decl_builtin("handle_t", RPC_FC_BIND_PRIMITIVE);
+}
+
static attr_t *make_attr(enum attr_type type)
{
attr_t *a = xmalloc(sizeof(attr_t));
diff --git a/tools/widl/typelib.c b/tools/widl/typelib.c
index 5ff101b..7a1b246 100644
--- a/tools/widl/typelib.c
+++ b/tools/widl/typelib.c
@@ -50,6 +50,29 @@ int in_typelib = 0;
static typelib_t *typelib;
+type_t *duptype(type_t *t, int dupname)
+{
+ type_t *d = xmalloc(sizeof *d);
+
+ *d = *t;
+ if (dupname && t->name)
+ d->name = xstrdup(t->name);
+
+ d->orig = t;
+ return d;
+}
+
+type_t *alias(type_t *t, const char *name)
+{
+ type_t *a = duptype(t, 0);
+
+ a->name = xstrdup(name);
+ a->kind = TKIND_ALIAS;
+ a->attrs = NULL;
+
+ return a;
+}
+
/* List of oleauto types that should be recognized by name.
* (most of) these seem to be intrinsic types in mktyplib. */
@@ -128,14 +151,14 @@ unsigned short get_type_vt(type_t *t)
case RPC_FC_USHORT:
return VT_UI2;
case RPC_FC_LONG:
- if (t->ref && match(t->ref->name, "int")) return VT_INT;
+ if (match(t->name, "int")) return VT_INT;
return VT_I4;
case RPC_FC_ULONG:
- if (t->ref && match(t->ref->name, "int")) return VT_UINT;
+ if (match(t->name, "int")) return VT_UINT;
return VT_UI4;
case RPC_FC_HYPER:
if (t->sign < 0) return VT_UI8;
- if (t->ref && match(t->ref->name, "MIDL_uhyper")) return VT_UI8;
+ if (match(t->name, "MIDL_uhyper")) return VT_UI8;
return VT_I8;
case RPC_FC_FLOAT:
return VT_R4;
diff --git a/tools/widl/widl.c b/tools/widl/widl.c
index aac1d5e..c2456f1 100644
--- a/tools/widl/widl.c
+++ b/tools/widl/widl.c
@@ -379,6 +379,7 @@ #endif
fprintf(idfile, "#endif\n\n");
}
+ init_types();
ret = yyparse();
if(do_header) {
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index d39def3..cf0f246 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -207,6 +207,7 @@ struct _type_t {
func_t *funcs; /* interfaces and modules */
var_t *fields; /* interfaces, structures and enumerations */
ifref_t *ifaces; /* coclasses */
+ type_t *orig; /* dup'd types */
int ignore, is_const, sign;
int defined, written, user_types_registered;
int typelib_idx;
@@ -297,6 +298,11 @@ struct _typelib_t {
importlib_t *importlibs;
};
+void init_types(void);
+
+type_t *duptype(type_t *t, int dupname);
+type_t *alias(type_t *t, const char *name);
+
/* Get the actual type field for a type (chase down typedef references). */
unsigned char ref_type(const type_t *type);
int is_pointer(var_t *v);
More information about the wine-patches
mailing list