widl patch

Ove Kaaven ovehk at ping.uio.no
Wed Nov 27 14:14:47 CST 2002


And here are some widl improvements, it now seems to be able to build
complete headers from objidl.idl and oaidl.idl. Note that regenerating
wtypes.h after applying this will change it slightly.

Log:
Ove Kaaven <ovek at transgaming.com>
Handle encapsulated unions in a cleaner (and less buggy) way. Emit the
names "DUMMYUNIONNAME" and "DUMMYSTRUCTNAME" for anonymous unions and
structs. Support const and extern definitions. Retain tokens (and whether
numbers are hex or not) used for computing constant expressions, so that
the full expression can be written to the header file instead of the
computed integer result of the expression. Parse the sizeof() operator.
Compute and remember constant definitions and enum values so they can be
used in expressions. Improved identifier lookup speed. Fixed some bugs.

Index: tools/widl/header.c
===================================================================
RCS file: /home/wine/wine/tools/widl/header.c,v
retrieving revision 1.6
diff -u -r1.6 header.c
--- tools/widl/header.c	21 Nov 2002 00:02:38 -0000	1.6
+++ tools/widl/header.c	27 Nov 2002 19:43:26 -0000
@@ -78,8 +78,8 @@
   while (NEXT_LINK(v)) v = NEXT_LINK(v);
   fprintf(h, "[");
   while (v) {
-    if (v->type == EXPR_NUM)
-      fprintf(h, "%ld", v->u.lval); /* statically sized array */
+    if (v->is_const)
+      fprintf(h, "%ld", v->cval); /* statically sized array */
     else
       fprintf(h, "1"); /* dynamically sized array */
     if (PREV_LINK(v))
@@ -99,6 +99,21 @@
       fprintf(h, " ");
       write_pident(h, v);
     }
+    else {
+      /* not all C/C++ compilers support anonymous structs and unions */
+      switch (v->type->type) {
+      case RPC_FC_STRUCT:
+      case RPC_FC_ENCAPSULATED_UNION:
+        fprintf(h, " DUMMYSTRUCTNAME");
+        break;
+      case RPC_FC_NON_ENCAPSULATED_UNION:
+        fprintf(h, " DUMMYUNIONNAME");
+        break;
+      default:
+        /* ? */
+        break;
+      }
+    }
     write_array(h, v->array);
     fprintf(h, ";\n");
   }
@@ -124,8 +139,10 @@
     if (get_name(v)) {
       indent(0);
       write_name(h, v);
-      if (v->has_val)
-        fprintf(h, " = %ld", v->lval);
+      if (v->eval) {
+        fprintf(h, " = ");
+        write_expr(h, v->eval);
+      }
     }
     if (PREV_LINK(v))
       fprintf(h, ",\n");
@@ -181,6 +198,7 @@
         if (t->defined && !t->written) {
           if (t->name) fprintf(h, "enum %s {\n", t->name);
           else fprintf(h, "enum {\n");
+          t->written = TRUE;
           indentation++;
           write_enums(h, t->fields);
           indent(-1);
@@ -189,29 +207,13 @@
         else fprintf(h, "enum %s", t->name);
         break;
       case RPC_FC_STRUCT:
-        if (t->defined && !t->written) {
-          if (t->name) fprintf(h, "struct %s {\n", t->name);
-          else fprintf(h, "struct {\n");
-          indentation++;
-          write_fields(h, t->fields);
-          indent(-1);
-          fprintf(h, "}");
-        }
-        else fprintf(h, "struct %s", t->name);
-        break;
       case RPC_FC_ENCAPSULATED_UNION:
         if (t->defined && !t->written) {
-          var_t *d = t->fields;
           if (t->name) fprintf(h, "struct %s {\n", t->name);
           else fprintf(h, "struct {\n");
+          t->written = TRUE;
           indentation++;
-          write_field(h, d);
-          indent(0);
-          fprintf(h, "union {\n");
-          indentation++;
-          write_fields(h, NEXT_LINK(d));
-          indent(-1);
-          fprintf(h, "} u;\n");
+          write_fields(h, t->fields);
           indent(-1);
           fprintf(h, "}");
         }
@@ -221,6 +223,7 @@
         if (t->defined && !t->written) {
           if (t->name) fprintf(h, "union %s {\n", t->name);
           else fprintf(h, "union {\n");
+          t->written = TRUE;
           indentation++;
           write_fields(h, t->fields);
           indent(-1);
@@ -258,6 +261,89 @@
     if (PREV_LINK(names))
       fprintf(header, ", ");
     names = PREV_LINK(names);
+  }
+  fprintf(header, ";\n\n");
+}
+
+static void do_write_expr(FILE *h, expr_t *e, int p)
+{
+  switch (e->type) {
+  case EXPR_VOID:
+    break;
+  case EXPR_NUM:
+    fprintf(h, "%ld", e->u.lval);
+    break;
+  case EXPR_HEXNUM:
+    fprintf(h, "0x%lx", e->u.lval);
+    break;
+  case EXPR_IDENTIFIER:
+    fprintf(h, "%s", e->u.sval);
+    break;
+  case EXPR_NEG:
+    fprintf(h, "-");
+    do_write_expr(h, e->ref, 1);
+    break;
+  case EXPR_PPTR:
+    fprintf(h, "*");
+    do_write_expr(h, e->ref, 1);
+    break;
+  case EXPR_CAST:
+    fprintf(h, "(");
+    write_type(h, e->u.tref->ref, NULL, e->u.tref->name);
+    fprintf(h, ")");
+    do_write_expr(h, e->ref, 1);
+    break;
+  case EXPR_SIZEOF:
+    fprintf(h, "sizeof(");
+    write_type(h, e->u.tref->ref, NULL, e->u.tref->name);
+    fprintf(h, ")");
+    break;
+  case EXPR_SHL:
+  case EXPR_SHR:
+  case EXPR_MUL:
+  case EXPR_DIV:
+  case EXPR_ADD:
+  case EXPR_SUB:
+  case EXPR_AND:
+  case EXPR_OR:
+    if (p) fprintf(h, "(");
+    do_write_expr(h, e->ref, 1);
+    switch (e->type) {
+    case EXPR_SHL: fprintf(h, " << "); break;
+    case EXPR_SHR: fprintf(h, " >> "); break;
+    case EXPR_MUL: fprintf(h, " * "); break;
+    case EXPR_DIV: fprintf(h, " / "); break;
+    case EXPR_ADD: fprintf(h, " + "); break;
+    case EXPR_SUB: fprintf(h, " - "); break;
+    case EXPR_AND: fprintf(h, " & "); break;
+    case EXPR_OR:  fprintf(h, " | "); break;
+    default: break;
+    }
+    do_write_expr(h, e->u.ext, 1);
+    if (p) fprintf(h, ")");
+    break;
+  }
+}
+
+void write_expr(FILE *h, expr_t *e)
+{
+  do_write_expr(h, e, 0);
+}
+
+void write_constdef(var_t *v)
+{
+  fprintf(header, "#define %s (", get_name(v));
+  write_expr(header, v->eval);
+  fprintf(header, ")\n\n");
+}
+
+void write_externdef(var_t *v)
+{
+  fprintf(header, "extern const ");
+  write_type(header, v->type, NULL, v->tname);
+  if (get_name(v)) {
+    fprintf(header, " ");
+    write_pident(header, v);
   }
   fprintf(header, ";\n\n");
 }
Index: tools/widl/header.h
===================================================================
RCS file: /home/wine/wine/tools/widl/header.h,v
retrieving revision 1.1
diff -u -r1.1 header.h
--- tools/widl/header.h	16 Jul 2002 03:20:46 -0000	1.1
+++ tools/widl/header.h	27 Nov 2002 19:43:26 -0000
@@ -32,5 +32,8 @@
 extern void write_forward(type_t *iface);
 extern void write_interface(type_t *iface);
 extern void write_typedef(type_t *type, var_t *names);
+extern void write_expr(FILE *h, expr_t *e);
+extern void write_constdef(var_t *v);
+extern void write_externdef(var_t *v);
 
 #endif
Index: tools/widl/parser.h
===================================================================
RCS file: /home/wine/wine/tools/widl/parser.h,v
retrieving revision 1.1
diff -u -r1.1 parser.h
--- tools/widl/parser.h	16 Jul 2002 03:20:46 -0000	1.1
+++ tools/widl/parser.h	27 Nov 2002 19:43:26 -0000
@@ -31,7 +31,7 @@
 int yylex(void);
 
 extern int import_stack_ptr;
-void do_import(char *fname);
+int do_import(char *fname);
 void abort_import(void);
 
 #define parse_only import_stack_ptr
Index: tools/widl/parser.l
===================================================================
RCS file: /home/wine/wine/tools/widl/parser.l,v
retrieving revision 1.8
diff -u -r1.8 parser.l
--- tools/widl/parser.l	21 Nov 2002 00:02:38 -0000	1.8
+++ tools/widl/parser.l	27 Nov 2002 19:43:26 -0000
@@ -118,7 +118,10 @@
 				yylval.uuid = parse_uuid(yytext);
 				return aUUID;
 			}
-{hex}			|
+{hex}			{
+				yylval.num = strtol(yytext, NULL, 0);
+				return aHEXNUM;
+			}
 {int}			{
 				yylval.num = strtol(yytext, NULL, 0);
 				return aNUM;
@@ -145,7 +148,7 @@
 }
 #endif
 
-static struct {
+static struct keyword {
 	const char *kw;
 	int token;
 	int val;
@@ -241,16 +244,34 @@
 	{"version",			tVERSION},
 	{"void",			tVOID},
 	{"wchar_t",			tWCHAR},
-	{"wire_marshal",		tWIREMARSHAL},
-	{NULL}
+	{"wire_marshal",		tWIREMARSHAL}
 };
+#define NKEYWORDS (sizeof(keywords)/sizeof(keywords[0]))
+#define KWP(p) ((struct keyword *)(p))
+
+static int kw_cmp_func(const void *s1, const void *s2)
+{
+	return strcmp(KWP(s1)->kw, KWP(s2)->kw);
+}
 
+#define KW_BSEARCH
 static int kw_token(const char *kw)
 {
-	int i;
-	for (i=0; keywords[i].kw; i++)
-		if (strcmp(kw, keywords[i].kw) == 0)
-			return keywords[i].token;
+	struct keyword key, *kwp;
+	key.kw = kw;
+#ifdef KW_BSEARCH
+	kwp = bsearch(&key, keywords, NKEYWORDS, sizeof(keywords[0]), kw_cmp_func);
+#else
+	{
+		int i;
+		for (kwp=NULL, i=0; i < NKEYWORDS; i++)
+			if (!kw_cmp_func(&key, &keywords[i])) {
+				kwp = &keywords[i];
+				break;
+			}
+	}
+#endif
+	if (kwp) return kwp->token;
 	yylval.str = xstrdup(kw);
 	return is_type(kw) ? aKNOWNTYPE : aIDENTIFIER;
 }
@@ -293,7 +314,7 @@
 	struct imports *next;
 } *first_import;
 
-void do_import(char *fname)
+int do_import(char *fname)
 {
 	FILE *f;
 	char *hname, *path;
@@ -312,7 +333,7 @@
 	import = first_import;
 	while (import && strcmp(import->name, fname))
 		import = import->next;
-	if (import) return; /* already imported */
+	if (import) return 0; /* already imported */
 
 	import = xmalloc(sizeof(struct imports));
 	import->name = xstrdup(fname);
@@ -334,6 +355,7 @@
 
 	import_stack[ptr].state = YY_CURRENT_BUFFER;
 	yy_switch_to_buffer(yy_create_buffer(f, YY_BUF_SIZE));
+	return 1;
 }
 
 void abort_import(void)
Index: tools/widl/parser.y
===================================================================
RCS file: /home/wine/wine/tools/widl/parser.y,v
retrieving revision 1.6
diff -u -r1.6 parser.y
--- tools/widl/parser.y	24 Nov 2002 22:12:40 -0000	1.6
+++ tools/widl/parser.y	27 Nov 2002 19:43:26 -0000
@@ -67,6 +67,7 @@
 static expr_t *make_expr(enum expr_type type);
 static expr_t *make_exprl(enum expr_type type, long val);
 static expr_t *make_exprs(enum expr_type type, char *val);
+static expr_t *make_exprt(enum expr_type type, typeref_t *tref, expr_t *expr);
 static expr_t *make_expr1(enum expr_type type, expr_t *expr);
 static expr_t *make_expr2(enum expr_type type, expr_t *exp1, expr_t *exp2);
 static type_t *make_type(BYTE type, type_t *ref);
@@ -84,6 +85,9 @@
 static type_t *get_type(BYTE type, char *name, int t);
 static type_t *get_typev(BYTE type, var_t *name, int t);
 
+static var_t *reg_const(var_t *var);
+static var_t *find_const(char *name, int f);
+
 #define tsENUM   1
 #define tsSTRUCT 2
 #define tsUNION  3
@@ -106,7 +110,7 @@
 
 %token <str> aIDENTIFIER
 %token <str> aKNOWNTYPE
-%token <num> aNUM
+%token <num> aNUM aHEXNUM
 %token <str> aSTRING
 %token <uuid> aUUID
 %token aEOF
@@ -154,16 +158,16 @@
 %token tPOINTERTYPE
 
 %type <attr> m_attributes attributes attrib_list attribute
-%type <expr> aexprs aexpr_list aexpr array
+%type <expr> exprs expr_list expr array expr_const
 %type <type> inherit interface interfacehdr interfacedef lib_statements
 %type <type> base_type int_std
 %type <type> enumdef structdef typedef uniondef
 %type <tref> type
 %type <var> m_args no_args args arg
-%type <var> fields field s_field cases case enums enum_list enum constdef
+%type <var> fields field s_field cases case enums enum_list enum constdef externdef
 %type <var> m_ident t_ident ident p_ident pident pident_list
 %type <func> funcdef int_statements
-%type <num> expr pointer_type
+%type <num> pointer_type
 
 %left ','
 %left '|'
@@ -193,10 +197,10 @@
 	;
 
 statement: ';'					{}
-	| constdef				{}
+	| constdef ';'				{ if (!parse_only) { write_constdef($1); } }
 	| cppquote				{}
 	| enumdef ';'				{ if (!parse_only) { write_type(header, $1, NULL, NULL); fprintf(header, ";\n\n"); } }
-	| externdef ';'				{}
+	| externdef ';'				{ if (!parse_only) { write_externdef($1); } }
 	| import				{}
 /*	| interface ';'				{} */
 /*	| interfacedef				{} */
@@ -207,7 +211,8 @@
 
 cppquote:	tCPPQUOTE '(' aSTRING ')'	{ if (!parse_only) fprintf(header, "%s\n", $3); }
 	;
-import_start:	tIMPORT aSTRING ';'		{ do_import($2); }
+import_start:	tIMPORT aSTRING ';'		{ assert(yychar == YYEMPTY);
+						  if (!do_import($2)) yychar = aEOF; }
 	;
 import:		import_start input aEOF		{}
 	;
@@ -234,33 +239,8 @@
 						}
 	;
 
-aexprs:						{ $$ = make_expr(EXPR_VOID); }
-	| aexpr_list
-	;
-
-aexpr_list: aexpr
-	| aexpr_list ',' aexpr			{ LINK($3, $1); $$ = $3; }
-	;
-
-aexpr:	  aNUM					{ $$ = make_exprl(EXPR_NUM, $1); }
-	| aIDENTIFIER				{ $$ = make_exprs(EXPR_IDENTIFIER, $1); }
-	| aexpr '|' aexpr			{ $$ = make_expr2(EXPR_OR , $1, $3); }
-	| aexpr '&' aexpr			{ $$ = make_expr2(EXPR_AND, $1, $3); }
-	| aexpr '+' aexpr			{ $$ = make_expr2(EXPR_ADD, $1, $3); }
-	| aexpr '-' aexpr			{ $$ = make_expr2(EXPR_SUB, $1, $3); }
-	| aexpr '*' aexpr			{ $$ = make_expr2(EXPR_MUL, $1, $3); }
-	| aexpr '/' aexpr			{ $$ = make_expr2(EXPR_DIV, $1, $3); }
-	| aexpr SHL aexpr			{ $$ = make_expr2(EXPR_SHL, $1, $3); }
-	| aexpr SHR aexpr			{ $$ = make_expr2(EXPR_SHR, $1, $3); }
-	| '-' aexpr %prec NEG			{ $$ = make_expr1(EXPR_NEG, $2); }
-	| '*' aexpr %prec PPTR			{ $$ = make_expr1(EXPR_PPTR, $2); }
-	| '(' type ')' aexpr %prec CAST		{ $$ = $4; /* FIXME */ free($2); }
-	| '(' aexpr ')'				{ $$ = $2; }
-	| tSIZEOF '(' type ')'			{ $$ = make_exprl(EXPR_NUM, 0); /* FIXME */ free($3); warning("can't do sizeof() yet\n"); }
-	;
-
 array:						{ $$ = NULL; }
-	| '[' aexprs ']'			{ $$ = $2; }
+	| '[' exprs ']'				{ $$ = $2; }
 	| '[' '*' ']'				{ $$ = make_expr(EXPR_VOID); }
 	;
 
@@ -286,15 +266,15 @@
 	| tDEFAULT				{ $$ = make_attr(ATTR_DEFAULT); }
 	| tIIDIS '(' ident ')'			{ $$ = make_attrp(ATTR_IIDIS, $3); }
 	| tIN					{ $$ = make_attr(ATTR_IN); }
-	| tLENGTHIS '(' aexprs ')'		{ $$ = NULL; }
+	| tLENGTHIS '(' exprs ')'		{ $$ = NULL; }
 	| tLOCAL				{ $$ = make_attr(ATTR_LOCAL); }
 	| tOBJECT				{ $$ = make_attr(ATTR_OBJECT); }
 	| tOLEAUTOMATION			{ $$ = make_attr(ATTR_OLEAUTOMATION); }
 	| tOUT					{ $$ = make_attr(ATTR_OUT); }
 	| tPOINTERDEFAULT '(' pointer_type ')'	{ $$ = make_attrv(ATTR_POINTERDEFAULT, $3); }
-	| tSIZEIS '(' aexprs ')'		{ $$ = NULL; }
+	| tSIZEIS '(' exprs ')'			{ $$ = NULL; }
 	| tSTRING				{ $$ = make_attr(ATTR_STRING); }
-	| tSWITCHIS '(' aexpr ')'		{ $$ = NULL; }
+	| tSWITCHIS '(' expr ')'		{ $$ = NULL; }
 	| tSWITCHTYPE '(' type ')'		{ $$ = NULL; }
 	| tUUID '(' aUUID ')'			{ $$ = make_attrp(ATTR_UUID, $3); }
 	| tV1ENUM				{ $$ = make_attr(ATTR_V1ENUM); }
@@ -308,17 +288,25 @@
 	;
 
 cases:						{ $$ = NULL; }
-	| cases case				{ LINK($2, $1); $$ = $2; }
+	| cases case				{ if ($2) { LINK($2, $1); $$ = $2; }
+						  else { $$ = $1; }
+						}
 	;
 
-case:	  tCASE expr ':' field			{ $$ = $4; }
-	| tDEFAULT ':' field			{ $$ = $3; }
+case:	  tCASE expr ':' field			{ /* attr_t *a = NULL; */ /* FIXME */
+						  $$ = $4; if (!$$) $$ = make_var(NULL);
+						  /* LINK(a, $$->attrs); $$->attrs = a; */
+						}
+	| tDEFAULT ':' field			{ attr_t *a = make_attr(ATTR_DEFAULT);
+						  $$ = $3; if (!$$) $$ = make_var(NULL);
+						  LINK(a, $$->attrs); $$->attrs = a;
+						}
 	;
 
-constdef: tCONST type ident '=' expr		{ $$ = $3;
+constdef: tCONST type ident '=' expr_const	{ $$ = reg_const($3);
 						  set_type($$, $2, NULL);
-						  $$->has_val = TRUE;
-						  $$->lval = $5;
+						  $$->eval = $5;
+						  $$->lval = $5->cval;
 						}
 	;
 
@@ -328,14 +316,19 @@
 	;
 
 enum_list: enum
-	| enum_list ',' enum			{ LINK($3, $1); $$ = $3; }
+	| enum_list ',' enum			{ LINK($3, $1); $$ = $3;
+						  if ($1 && !$3->eval)
+						    $3->lval = $1->lval + 1;
+						}
 	;
 
-enum:	  ident '=' expr			{ $$ = $1;
-						  $$->has_val = TRUE;
-						  $$->lval = $3;
+enum:	  ident '=' expr_const			{ $$ = reg_const($1);
+						  $$->eval = $3;
+						  $$->lval = $3->cval;
+						}
+	| ident					{ $$ = reg_const($1);
+						  $$->lval = 0; /* default for first enum entry */
 						}
-	| ident					{ $$ = $1; }
 	;
 
 enumdef: tENUM t_ident '{' enums '}'		{ $$ = get_typev(RPC_FC_ENUM16, $2, tsENUM);
@@ -344,24 +337,46 @@
 						}
 	;
 
-expr_list: expr					{}
-	| expr_list ',' expr			{}
+exprs:						{ $$ = make_expr(EXPR_VOID); }
+	| expr_list
+	;
+
+expr_list: expr
+	| expr_list ',' expr			{ LINK($3, $1); $$ = $3; }
 	;
 
-expr:	  aNUM
-	| aIDENTIFIER				{ $$ = 0; /* FIXME */ }
-	| expr '|' expr				{ $$ = $1 | $3; }
-	| expr '&' expr				{ $$ = $1 & $3; }
-	| expr SHL expr				{ $$ = $1 << $3; }
-	| expr SHR expr				{ $$ = $1 >> $3; }
-	| '-' expr %prec NEG			{ $$ = -$2; }
+expr:	  aNUM					{ $$ = make_exprl(EXPR_NUM, $1); }
+	| aHEXNUM				{ $$ = make_exprl(EXPR_HEXNUM, $1); }
+	| aIDENTIFIER				{ $$ = make_exprs(EXPR_IDENTIFIER, $1); }
+	| expr '|' expr				{ $$ = make_expr2(EXPR_OR , $1, $3); }
+	| expr '&' expr				{ $$ = make_expr2(EXPR_AND, $1, $3); }
+	| expr '+' expr				{ $$ = make_expr2(EXPR_ADD, $1, $3); }
+	| expr '-' expr				{ $$ = make_expr2(EXPR_SUB, $1, $3); }
+	| expr '*' expr				{ $$ = make_expr2(EXPR_MUL, $1, $3); }
+	| expr '/' expr				{ $$ = make_expr2(EXPR_DIV, $1, $3); }
+	| expr SHL expr				{ $$ = make_expr2(EXPR_SHL, $1, $3); }
+	| expr SHR expr				{ $$ = make_expr2(EXPR_SHR, $1, $3); }
+	| '-' expr %prec NEG			{ $$ = make_expr1(EXPR_NEG, $2); }
+	| '*' expr %prec PPTR			{ $$ = make_expr1(EXPR_PPTR, $2); }
+	| '(' type ')' expr %prec CAST		{ $$ = make_exprt(EXPR_CAST, $2, $4); }
+	| tSIZEOF '(' type ')'			{ $$ = make_exprt(EXPR_SIZEOF, $3, NULL); }
+	| '(' expr ')'				{ $$ = $2; }
 	;
 
-externdef: tEXTERN tCONST type ident
+expr_const: expr				{ $$ = $1;
+						  if (!$$->is_const) yyerror("expression is not constant\n");
+						}
+	;
+
+externdef: tEXTERN tCONST type ident		{ $$ = $4;
+						  set_type($$, $3, NULL);
+						}
 	;
 
 fields:						{ $$ = NULL; }
-	| fields field				{ LINK($2, $1); $$ = $2; }
+	| fields field				{ if ($2) { LINK($2, $1); $$ = $2; }
+						  else { $$ = $1; }
+						}
 	;
 
 field:	  s_field ';'				{ $$ = $1; }
@@ -508,8 +523,13 @@
 						}
 	| tUNION t_ident
 	  tSWITCH '(' s_field ')'
-	  m_ident '{' cases '}'			{ $$ = get_typev(RPC_FC_ENCAPSULATED_UNION, $2, tsUNION);
-						  LINK($5, $9); $$->fields = $5;
+	  m_ident '{' cases '}'			{ var_t *u = $7;
+						  $$ = get_typev(RPC_FC_ENCAPSULATED_UNION, $2, tsUNION);
+						  if (!u) u = make_var("tagged_union");
+						  u->type = make_type(RPC_FC_NON_ENCAPSULATED_UNION, NULL);
+						  u->type->fields = $9;
+						  u->type->defined = TRUE;
+						  LINK(u, $5); $$->fields = u;
 						  $$->defined = TRUE;
 						}
 	;
@@ -554,6 +574,7 @@
   e->type = type;
   e->ref = NULL;
   e->u.lval = 0;
+  e->is_const = FALSE;
   INIT_LINK(e);
   return e;
 }
@@ -564,90 +585,121 @@
   e->type = type;
   e->ref = NULL;
   e->u.lval = val;
+  e->is_const = FALSE;
   INIT_LINK(e);
+  /* check for numeric constant */
+  if (type == EXPR_NUM || type == EXPR_HEXNUM) {
+    e->is_const = TRUE;
+    e->cval = val;
+  }
   return e;
 }
 
 static expr_t *make_exprs(enum expr_type type, char *val)
 {
-  expr_t *e = xmalloc(sizeof(expr_t));
-  /* FIXME: if type is EXPR_IDENTIFIER, we could check for match against const
-   * declaration, and change to appropriate type and value if so */
+  expr_t *e;
+  e = xmalloc(sizeof(expr_t));
   e->type = type;
   e->ref = NULL;
   e->u.sval = val;
+  e->is_const = FALSE;
+  INIT_LINK(e);
+  /* check for predefined constants */
+  if (type == EXPR_IDENTIFIER) {
+    var_t *c = find_const(val, 0);
+    if (c) {
+      e->u.sval = c->name;
+      free(val);
+      e->is_const = TRUE;
+      e->cval = c->lval;
+    }
+  }
+  return e;
+}
+
+static expr_t *make_exprt(enum expr_type type, typeref_t *tref, expr_t *expr)
+{
+  expr_t *e;
+  e = xmalloc(sizeof(expr_t));
+  e->type = type;
+  e->ref = expr;
+  e->u.tref = tref;
+  e->is_const = FALSE;
   INIT_LINK(e);
+  /* check for cast of constant expression */
+  if (type == EXPR_CAST && expr->is_const) {
+    e->is_const = TRUE;
+    e->cval = expr->cval;
+  }
   return e;
 }
 
 static expr_t *make_expr1(enum expr_type type, expr_t *expr)
 {
   expr_t *e;
+  e = xmalloc(sizeof(expr_t));
+  e->type = type;
+  e->ref = expr;
+  e->u.lval = 0;
+  e->is_const = FALSE;
+  INIT_LINK(e);
   /* check for compile-time optimization */
-  if (expr->type == EXPR_NUM) {
+  if (expr->is_const) {
+    e->is_const = TRUE;
     switch (type) {
     case EXPR_NEG:
-      expr->u.lval = -expr->u.lval;
-      return expr;
+      e->cval = -expr->cval;
+      break;
     default:
+      e->is_const = FALSE;
       break;
     }
   }
-  e = xmalloc(sizeof(expr_t));
-  e->type = type;
-  e->ref = expr;
-  e->u.lval = 0;
-  INIT_LINK(e);
   return e;
 }
 
 static expr_t *make_expr2(enum expr_type type, expr_t *expr1, expr_t *expr2)
 {
   expr_t *e;
+  e = xmalloc(sizeof(expr_t));
+  e->type = type;
+  e->ref = expr1;
+  e->u.ext = expr2;
+  e->is_const = FALSE;
+  INIT_LINK(e);
   /* check for compile-time optimization */
-  if (expr1->type == EXPR_NUM && expr2->type == EXPR_NUM) {
+  if (expr1->is_const && expr2->is_const) {
+    e->is_const = TRUE;
     switch (type) {
     case EXPR_ADD:
-      expr1->u.lval += expr2->u.lval;
-      free(expr2);
-      return expr1;
+      e->cval = expr1->cval + expr2->cval;
+      break;
     case EXPR_SUB:
-      expr1->u.lval -= expr2->u.lval;
-      free(expr2);
-      return expr1;
+      e->cval = expr1->cval - expr2->cval;
+      break;
     case EXPR_MUL:
-      expr1->u.lval *= expr2->u.lval;
-      free(expr2);
-      return expr1;
+      e->cval = expr1->cval * expr2->cval;
+      break;
     case EXPR_DIV:
-      expr1->u.lval /= expr2->u.lval;
-      free(expr2);
-      return expr1;
+      e->cval = expr1->cval / expr2->cval;
+      break;
     case EXPR_OR:
-      expr1->u.lval |= expr2->u.lval;
-      free(expr2);
-      return expr1;
+      e->cval = expr1->cval | expr2->cval;
+      break;
     case EXPR_AND:
-      expr1->u.lval &= expr2->u.lval;
-      free(expr2);
-      return expr1;
+      e->cval = expr1->cval & expr2->cval;
+      break;
     case EXPR_SHL:
-      expr1->u.lval <<= expr2->u.lval;
-      free(expr2);
-      return expr1;
+      e->cval = expr1->cval << expr2->cval;
+      break;
     case EXPR_SHR:
-      expr1->u.lval >>= expr2->u.lval;
-      free(expr2);
-      return expr1;
+      e->cval = expr1->cval >> expr2->cval;
+      break;
     default:
+      e->is_const = FALSE;
       break;
     }
   }
-  e = xmalloc(sizeof(expr_t));
-  e->type = type;
-  e->ref = expr1;
-  e->u.ext = expr2;
-  INIT_LINK(e);
   return e;
 }
 
@@ -718,7 +770,7 @@
   v->tname = NULL;
   v->attrs = NULL;
   v->array = NULL;
-  v->has_val = FALSE;
+  v->eval = NULL;
   v->lval = 0;
   INIT_LINK(v);
   return v;
@@ -735,6 +787,22 @@
   return f;
 }
 
+#define HASHMAX 64
+
+static int hash_ident(const char *name)
+{
+  const char *p = name;
+  int sum = 0;
+  /* a simple sum hash is probably good enough */
+  while (*p) {
+    sum += *p;
+    p++;
+  }
+  return sum & (HASHMAX-1);
+}
+
+/***** type repository *****/
+
 struct rtype {
   char *name;
   type_t *type;
@@ -742,21 +810,23 @@
   struct rtype *next;
 };
 
-struct rtype *first_type;
+struct rtype *type_hash[HASHMAX];
 
 static type_t *reg_type(type_t *type, char *name, int t)
 {
   struct rtype *nt;
+  int hash;
   if (!name) {
     yyerror("registering named type without name\n");
     return type;
   }
+  hash = hash_ident(name);
   nt = xmalloc(sizeof(struct rtype));
   nt->name = name;
   nt->type = type;
   nt->t = t;
-  nt->next = first_type;
-  first_type = nt;
+  nt->next = type_hash[hash];
+  type_hash[hash] = nt;
   return type;
 }
 
@@ -791,7 +861,7 @@
 
 static type_t *find_type(char *name, int t)
 {
-  struct rtype *cur = first_type;
+  struct rtype *cur = type_hash[hash_ident(name)];
   while (cur && (cur->t != t || strcmp(cur->name, name)))
     cur = cur->next;
   if (!cur) {
@@ -810,7 +880,7 @@
 
 int is_type(const char *name)
 {
-  struct rtype *cur = first_type;
+  struct rtype *cur = type_hash[hash_ident(name)];
   while (cur && (cur->t || strcmp(cur->name, name)))
     cur = cur->next;
   if (cur) return TRUE;
@@ -822,7 +892,7 @@
   struct rtype *cur = NULL;
   type_t *tp;
   if (name) {
-    cur = first_type;
+    cur = type_hash[hash_ident(name)];
     while (cur && (cur->t != t || strcmp(cur->name, name)))
       cur = cur->next;
   }
@@ -844,4 +914,43 @@
     free(name);
   }
   return get_type(type, sname, t);
+}
+
+/***** constant repository *****/
+
+struct rconst {
+  char *name;
+  var_t *var;
+  struct rconst *next;
+};
+
+struct rconst *const_hash[HASHMAX];
+
+static var_t *reg_const(var_t *var)
+{
+  struct rconst *nc;
+  int hash;
+  if (!var->name) {
+    yyerror("registering constant without name\n");
+    return var;
+  }
+  hash = hash_ident(var->name);
+  nc = xmalloc(sizeof(struct rconst));
+  nc->name = var->name;
+  nc->var = var;
+  nc->next = const_hash[hash];
+  const_hash[hash] = nc;
+  return var;
+}
+
+static var_t *find_const(char *name, int f)
+{
+  struct rconst *cur = const_hash[hash_ident(name)];
+  while (cur && strcmp(cur->name, name))
+    cur = cur->next;
+  if (!cur) {
+    if (f) yyerror("constant %s not found\n", name);
+    return NULL;
+  }
+  return cur->var;
 }
Index: tools/widl/widltypes.h
===================================================================
RCS file: /home/wine/wine/tools/widl/widltypes.h,v
retrieving revision 1.5
diff -u -r1.5 widltypes.h
--- tools/widl/widltypes.h	13 Nov 2002 21:31:01 -0000	1.5
+++ tools/widl/widltypes.h	27 Nov 2002 19:43:26 -0000
@@ -67,10 +67,12 @@
 {
     EXPR_VOID,
     EXPR_NUM,
+    EXPR_HEXNUM,
     EXPR_IDENTIFIER,
     EXPR_NEG,
     EXPR_PPTR,
     EXPR_CAST,
+    EXPR_SIZEOF,
     EXPR_SHL,
     EXPR_SHR,
     EXPR_MUL,
@@ -98,7 +100,10 @@
     long lval;
     char *sval;
     expr_t *ext;
+    typeref_t *tref;
   } u;
+  int is_const;
+  long cval;
   /* parser-internal */
   DECL_LINK(expr_t)
 };
@@ -131,7 +136,7 @@
   type_t *type;
   char *tname;
   attr_t *attrs;
-  int has_val;
+  expr_t *eval;
   long lval;
 
   /* parser-internal */




More information about the wine-patches mailing list