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