Rob Shearman : widl: Create a separate type_t object for each structure declaration or defintion .

Alexandre Julliard julliard at winehq.org
Mon Dec 29 08:48:01 CST 2008


Module: wine
Branch: master
Commit: 1a71479fbde0c10ad946334c524c3fdcb7dfab01
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=1a71479fbde0c10ad946334c524c3fdcb7dfab01

Author: Rob Shearman <robertshearman at gmail.com>
Date:   Mon Dec 29 12:05:53 2008 +0000

widl: Create a separate type_t object for each structure declaration or defintion.

Set the details of the structure to the previously defined version if
available, or add it to a list of incomplete types otherwise. Only set
the defined flag when the structure is actually defined in the IDL
file so that the type is written out in the exact order that it is
mentioned in the file.

---

 tools/widl/parser.y |   58 +++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 50 insertions(+), 8 deletions(-)

diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index 75cd63e..1866a1e 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -97,6 +97,7 @@ typelist_t incomplete_types = LIST_INIT(incomplete_types);
 
 static void add_incomplete(type_t *t);
 static void fix_incomplete(void);
+static void fix_incomplete_types(type_t *complete_type);
 
 static str_list_t *append_str(str_list_t *list, char *str);
 static attr_list_t *append_attr(attr_list_t *list, attr_t *attr);
@@ -126,7 +127,7 @@ static typelib_t *make_library(const char *name, const attr_list_t *attrs);
 static type_t *append_ptrchain_type(type_t *ptrchain, type_t *type);
 
 static type_t *type_new_enum(char *name, var_list_t *enums);
-static type_t *type_new_struct(char *name, var_list_t *fields);
+static type_t *type_new_struct(char *name, int defined, var_list_t *fields);
 static type_t *type_new_nonencapsulated_union(char *name, var_list_t *fields);
 static type_t *type_new_encapsulated_union(char *name, var_t *switch_field, var_t *union_field, var_list_t *cases);
 
@@ -1047,7 +1048,7 @@ pointer_type:
 	| tPTR					{ $$ = RPC_FC_FP; }
 	;
 
-structdef: tSTRUCT t_ident '{' fields '}'	{ $$ = type_new_struct($2, $4);
+structdef: tSTRUCT t_ident '{' fields '}'	{ $$ = type_new_struct($2, TRUE, $4);
                                                   if(in_typelib)
                                                       add_typelib_entry($$);
                                                 }
@@ -1059,7 +1060,7 @@ type:	  tVOID					{ $$ = find_type_or_error("void", 0); }
 	| enumdef				{ $$ = $1; }
 	| tENUM aIDENTIFIER			{ $$ = find_type_or_error2($2, tsENUM); }
 	| structdef				{ $$ = $1; }
-	| tSTRUCT aIDENTIFIER			{ $$ = get_type(RPC_FC_STRUCT, $2, tsSTRUCT); }
+	| tSTRUCT aIDENTIFIER			{ $$ = type_new_struct($2, FALSE, NULL); }
 	| uniondef				{ $$ = $1; }
 	| tUNION aIDENTIFIER			{ $$ = find_type_or_error2($2, tsUNION); }
 	| tSAFEARRAY '(' type ')'		{ $$ = make_safearray($3); }
@@ -1385,13 +1386,33 @@ static type_t *type_new_enum(char *name, var_list_t *enums)
     return t;
 }
 
-static type_t *type_new_struct(char *name, var_list_t *fields)
+static type_t *type_new_struct(char *name, int defined, var_list_t *fields)
 {
-  type_t *t = get_type(RPC_FC_STRUCT, name, tsSTRUCT);
+  type_t *tag_type = name ? find_type(name, tsSTRUCT) : NULL;
+  type_t *t = make_type(RPC_FC_STRUCT, NULL);
+  t->name = name;
   t->kind = TKIND_RECORD;
-  t->details.structure = xmalloc(sizeof(*t->details.structure));
-  t->details.structure->fields = fields;
-  t->defined = TRUE;
+  if (defined || (tag_type && tag_type->details.structure))
+  {
+    if (tag_type && tag_type->details.structure)
+    {
+      t->details.structure = tag_type->details.structure;
+      t->type = tag_type->type;
+    }
+    else if (defined)
+    {
+      t->details.structure = xmalloc(sizeof(*t->details.structure));
+      t->details.structure->fields = fields;
+      t->defined = TRUE;
+    }
+  }
+  if (name)
+  {
+    if (fields)
+      reg_type(t, name, tsSTRUCT);
+    else
+      add_incomplete(t);
+  }
   return t;
 }
 
@@ -1807,6 +1828,8 @@ static type_t *reg_type(type_t *type, const char *name, int t)
   nt->t = t;
   nt->next = type_hash[hash];
   type_hash[hash] = nt;
+  if ((t == tsSTRUCT || t == tsUNION))
+    fix_incomplete_types(type);
   return type;
 }
 
@@ -1839,10 +1862,29 @@ static void fix_incomplete(void)
 
   LIST_FOR_EACH_ENTRY_SAFE(tn, next, &incomplete_types, struct typenode, entry) {
     fix_type(tn->type);
+    list_remove(&tn->entry);
     free(tn);
   }
 }
 
+static void fix_incomplete_types(type_t *complete_type)
+{
+  struct typenode *tn, *next;
+
+  LIST_FOR_EACH_ENTRY_SAFE(tn, next, &incomplete_types, struct typenode, entry)
+  {
+    if (((is_struct(complete_type->type) && is_struct(tn->type->type)) ||
+         (is_union(complete_type->type) && is_union(tn->type->type))) &&
+        !strcmp(complete_type->name, tn->type->name))
+    {
+      tn->type->details.structure = complete_type->details.structure;
+      tn->type->type = complete_type->type;
+      list_remove(&tn->entry);
+      free(tn);
+    }
+  }
+}
+
 static type_t *reg_typedefs(decl_spec_t *decl_spec, declarator_list_t *decls, attr_list_t *attrs)
 {
   const declarator_t *decl;




More information about the wine-cvs mailing list