From 277e0617d5d23ba49ec57c75f72923ff55db1f63 Mon Sep 17 00:00:00 2001
From: Rob Shearman <robertshearman@gmail.com>
Date: Thu, 5 Mar 2009 08:22:19 +0000
Subject: [PATCH] widl: Store the abstract identifier of the type in type
 object instead of an NDR format character.

---
 tools/widl/header.c     |  2 +-
 tools/widl/parser.y     | 51 +++++++++++-------------------
 tools/widl/typegen.c    |  2 +-
 tools/widl/typelib.c    |  9 ++++--
 tools/widl/typetree.c   | 24 ++++++++++----
 tools/widl/typetree.h   |  3 +-
 tools/widl/widltypes.h  | 70 ++++++-----------------------------------
 tools/widl/write_msft.c | 14 ++-------
 8 files changed, 58 insertions(+), 117 deletions(-)

diff --git a/tools/widl/header.c b/tools/widl/header.c
index 1633c4b67ab..ed88284cfd7 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -183,7 +183,7 @@ static void write_enums(FILE *h, var_list_t *enums)
 int needs_space_after(type_t *t)
 {
   return (type_is_alias(t) ||
-          (!is_ptr(t) && (!is_conformant_array(t) || !type_array_is_decl_as_ptr(t) || t->name)));
+          (!is_ptr(t) && (!is_array(t) || !type_array_is_decl_as_ptr(t) || t->name)));
 }
 
 void write_type_left(FILE *h, type_t *t, int declonly)
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index c921ab6d877..ed0e4b64682 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -113,7 +113,6 @@ static declarator_list_t *append_declarator(declarator_list_t *list, declarator_
 static declarator_t *make_declarator(var_t *var);
 static func_list_t *append_func(func_list_t *list, func_t *func);
 static func_t *make_func(var_t *def);
-static type_t *make_class(char *name);
 static type_t *make_safearray(type_t *type);
 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);
@@ -127,7 +126,7 @@ static type_t *reg_type(type_t *type, const char *name, int t);
 static type_t *reg_typedefs(decl_spec_t *decl_spec, var_list_t *names, attr_list_t *attrs);
 static type_t *find_type_or_error(const char *name, int t);
 static type_t *find_type_or_error2(char *name, int t);
-static type_t *get_type(unsigned char type, char *name, int t);
+static type_t *get_type(enum type_type type, char *name, int t);
 
 static var_t *reg_const(var_t *var);
 
@@ -792,7 +791,7 @@ int_std:  tINT					{ $$ = type_new_int(TYPE_BASIC_INT, 0); }
 	| tCHAR					{ $$ = type_new_int(TYPE_BASIC_CHAR, 0); }
 	;
 
-coclass:  tCOCLASS aIDENTIFIER			{ $$ = make_class($2); }
+coclass:  tCOCLASS aIDENTIFIER			{ $$ = type_new_coclass($2); }
 	| tCOCLASS aKNOWNTYPE			{ $$ = find_type($2, 0);
 						  if (type_get_type_detect_alias($$) != TYPE_COCLASS)
 						    error_loc("%s was not declared a coclass at %s:%d\n",
@@ -819,8 +818,8 @@ coclass_int:
 	  m_attributes interfacedec		{ $$ = make_ifref($2); $$->attrs = $1; }
 	;
 
-dispinterface: tDISPINTERFACE aIDENTIFIER	{ $$ = get_type(RPC_FC_IP, $2, 0); }
-	|      tDISPINTERFACE aKNOWNTYPE	{ $$ = get_type(RPC_FC_IP, $2, 0); }
+dispinterface: tDISPINTERFACE aIDENTIFIER	{ $$ = get_type(TYPE_INTERFACE, $2, 0); }
+	|      tDISPINTERFACE aKNOWNTYPE	{ $$ = get_type(TYPE_INTERFACE, $2, 0); }
 	;
 
 dispinterfacehdr: attributes dispinterface	{ attr_t *attrs;
@@ -857,8 +856,8 @@ inherit:					{ $$ = NULL; }
 	| ':' aKNOWNTYPE			{ $$ = find_type_or_error2($2, 0); }
 	;
 
-interface: tINTERFACE aIDENTIFIER		{ $$ = get_type(RPC_FC_IP, $2, 0); }
-	|  tINTERFACE aKNOWNTYPE		{ $$ = get_type(RPC_FC_IP, $2, 0); }
+interface: tINTERFACE aIDENTIFIER		{ $$ = get_type(TYPE_INTERFACE, $2, 0); }
+	|  tINTERFACE aKNOWNTYPE		{ $$ = get_type(TYPE_INTERFACE, $2, 0); }
 	;
 
 interfacehdr: attributes interface		{ $$.interface = $2;
@@ -1241,11 +1240,11 @@ void clear_all_offsets(void)
     node->data.typestring_offset = node->data.ptrdesc = 0;
 }
 
-type_t *make_type(unsigned char type, type_t *ref)
+type_t *make_type(enum type_type type, type_t *ref)
 {
   type_t *t = alloc_type();
   t->name = NULL;
-  t->type = type;
+  t->type_type = type;
   t->ref = ref;
   t->attrs = NULL;
   t->orig = NULL;
@@ -1266,7 +1265,7 @@ type_t *make_type(unsigned char type, type_t *ref)
 
 static type_t *type_new_enum(char *name, var_list_t *enums)
 {
-    type_t *t = get_type(RPC_FC_ENUM16, name, tsENUM);
+    type_t *t = get_type(TYPE_ENUM, name, tsENUM);
     if (enums)
     {
         t->details.enumeration = xmalloc(sizeof(*t->details.enumeration));
@@ -1281,15 +1280,12 @@ static type_t *type_new_enum(char *name, var_list_t *enums)
 static type_t *type_new_struct(char *name, int defined, var_list_t *fields)
 {
   type_t *tag_type = name ? find_type(name, tsSTRUCT) : NULL;
-  type_t *t = make_type(RPC_FC_STRUCT, NULL);
+  type_t *t = make_type(TYPE_STRUCT, NULL);
   t->name = name;
   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));
@@ -1309,7 +1305,7 @@ 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)
 {
-  type_t *t = get_type(RPC_FC_NON_ENCAPSULATED_UNION, name, tsUNION);
+  type_t *t = get_type(TYPE_UNION, name, tsUNION);
   t->details.structure = xmalloc(sizeof(*t->details.structure));
   t->details.structure->fields = fields;
   t->defined = TRUE;
@@ -1318,9 +1314,9 @@ 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)
 {
-  type_t *t = get_type(RPC_FC_ENCAPSULATED_UNION, name, tsUNION);
+  type_t *t = get_type(TYPE_ENCAPSULATED_UNION, name, tsUNION);
   if (!union_field) union_field = make_var( xstrdup("tagged_union") );
-  union_field->type = make_type(RPC_FC_NON_ENCAPSULATED_UNION, NULL);
+  union_field->type = make_type(TYPE_UNION, NULL);
   union_field->type->details.structure = xmalloc(sizeof(*union_field->type->details.structure));
   union_field->type->details.structure->fields = cases;
   union_field->type->defined = TRUE;
@@ -1409,7 +1405,7 @@ static void set_type(var_t *v, decl_spec_t *decl_spec, const declarator_t *decl,
                            "pointer type has no effect\n", v->name);
       if (top && !ptr_attr)
         ptr_attr = RPC_FC_RP;
-      if (ptr_attr != (*pt)->type)
+      if (ptr_attr != (*pt)->details.pointer.fc)
       {
         /* create new type to avoid changing original type */
         /* FIXME: this is a horrible hack - we might be changing the pointer
@@ -1418,7 +1414,7 @@ static void set_type(var_t *v, decl_spec_t *decl_spec, const declarator_t *decl,
          * ends up having is context sensitive and so we shouldn't be
          * setting it here, but rather determining it when it is used. */
         *pt = duptype(*pt, 1);
-        (*pt)->type = ptr_attr;
+        (*pt)->details.pointer.fc = ptr_attr;
       }
     }
     else if (ptr_attr)
@@ -1431,9 +1427,7 @@ static void set_type(var_t *v, decl_spec_t *decl_spec, const declarator_t *decl,
 
   if (is_attr(v->attrs, ATTR_V1ENUM))
   {
-    if (type_get_type_detect_alias(v->type) == TYPE_ENUM)
-      v->type->type = RPC_FC_ENUM32;
-    else
+    if (type_get_type_detect_alias(v->type) != TYPE_ENUM)
       error_loc("'%s': [v1_enum] attribute applied to non-enum type\n", v->name);
   }
 
@@ -1661,18 +1655,9 @@ static func_t *make_func(var_t *def)
   return f;
 }
 
-static type_t *make_class(char *name)
-{
-  type_t *c = make_type(RPC_FC_COCLASS, NULL);
-  c->name = name;
-  return c;
-}
-
 static type_t *make_safearray(type_t *type)
 {
-  type_t *sa = find_type_or_error("SAFEARRAY", 0);
-  sa->ref = type;
-  return make_type(pointer_default, sa);
+  return type_new_array(NULL, type_new_alias(type, "SAFEARRAY"), TRUE, 0, NULL, NULL);
 }
 
 static typelib_t *make_library(const char *name, const attr_list_t *attrs)
@@ -1881,7 +1866,7 @@ int is_type(const char *name)
   return find_type(name, 0) != NULL;
 }
 
-static type_t *get_type(unsigned char type, char *name, int t)
+static type_t *get_type(enum type_type type, char *name, int t)
 {
   type_t *tp;
   if (name) {
diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c
index ae46338c007..6782528f33c 100644
--- a/tools/widl/typegen.c
+++ b/tools/widl/typegen.c
@@ -126,7 +126,7 @@ unsigned char get_pointer_fc(const type_t *type)
     /* FIXME: see corresponding hack in set_type - we shouldn't be getting
      * the pointer type from an alias, rather determining it from the
      * position */
-    return type->type;
+    return type->details.pointer.fc;
 }
 
 static unsigned char get_enum_fc(const type_t *type)
diff --git a/tools/widl/typelib.c b/tools/widl/typelib.c
index e6f4716b741..52f48a1aea9 100644
--- a/tools/widl/typelib.c
+++ b/tools/widl/typelib.c
@@ -191,12 +191,15 @@ unsigned short get_type_vt(type_t *t)
     break;
 
   case TYPE_POINTER:
-    if (match(type_pointer_get_ref(t)->name, "SAFEARRAY"))
-      return VT_SAFEARRAY;
     return VT_PTR;
 
   case TYPE_ARRAY:
-    if (!type_array_is_decl_as_ptr(t))
+    if (type_array_is_decl_as_ptr(t))
+    {
+      if (match(type_array_get_element(t)->name, "SAFEARRAY"))
+        return VT_SAFEARRAY;
+    }
+    else
       error("get_type_vt: array types not supported\n");
     return VT_PTR;
 
diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c
index 74cbd5f3b6f..25ccd8fe947 100644
--- a/tools/widl/typetree.c
+++ b/tools/widl/typetree.c
@@ -43,7 +43,7 @@ type_t *duptype(type_t *t, int dupname)
 
 type_t *type_new_function(var_list_t *args)
 {
-    type_t *t = make_type(RPC_FC_FUNCTION, NULL);
+    type_t *t = make_type(TYPE_FUNCTION, NULL);
     t->details.function = xmalloc(sizeof(*t->details.function));
     t->details.function->args = args;
     t->details.function->idx = -1;
@@ -52,7 +52,8 @@ type_t *type_new_function(var_list_t *args)
 
 type_t *type_new_pointer(type_t *ref, attr_list_t *attrs)
 {
-    type_t *t = make_type(pointer_default, ref);
+    type_t *t = make_type(TYPE_POINTER, ref);
+    t->details.pointer.fc = pointer_default;
     t->attrs = attrs;
     return t;
 }
@@ -65,23 +66,34 @@ type_t *type_new_alias(type_t *t, const char *name)
     a->attrs = NULL;
     a->orig = t;
     a->is_alias = TRUE;
+    /* for pointer types */
+    a->details = t->details;
     init_loc_info(&a->loc_info);
 
     return a;
 }
 
-type_t *type_new_module(char *name)
+type_t *type_new_module(const char *name)
 {
-    type_t *type = make_type(RPC_FC_MODULE, NULL);
+    type_t *type = make_type(TYPE_MODULE, NULL);
     type->name = name;
     /* FIXME: register type to detect multiple definitions */
     return type;
 }
 
+type_t *type_new_coclass(const char *name)
+{
+    type_t *c = make_type(TYPE_COCLASS, NULL);
+    c->name = name;
+    /* FIXME: register type to detect multiple definitions */
+    return c;
+}
+
+
 type_t *type_new_array(const char *name, type_t *element, int declptr,
                        unsigned int dim, expr_t *size_is, expr_t *length_is)
 {
-    type_t *t = make_type(RPC_FC_LGFARRAY, element);
+    type_t *t = make_type(TYPE_ARRAY, element);
     if (name) t->name = xstrdup(name);
     t->details.array.declptr = declptr;
     t->details.array.length_is = length_is;
@@ -119,7 +131,7 @@ type_t *type_new_void(void)
 {
     static type_t *void_type = NULL;
     if (!void_type)
-        void_type = make_type(0, NULL);
+        void_type = make_type(TYPE_VOID, NULL);
     return void_type;
 }
 
diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h
index ab83af5243c..63e7a6045c4 100644
--- a/tools/widl/typetree.h
+++ b/tools/widl/typetree.h
@@ -27,12 +27,13 @@
 type_t *type_new_function(var_list_t *args);
 type_t *type_new_pointer(type_t *ref, attr_list_t *attrs);
 type_t *type_new_alias(type_t *t, const char *name);
-type_t *type_new_module(char *name);
+type_t *type_new_module(const char *name);
 type_t *type_new_array(const char *name, type_t *element, int declptr,
                        unsigned int dim, expr_t *size_is, expr_t *length_is);
 type_t *type_new_basic(enum type_basic_type basic_type);
 type_t *type_new_int(enum type_basic_type basic_type, int sign);
 type_t *type_new_void(void);
+type_t *type_new_coclass(const char *name);
 void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stmts);
 void type_dispinterface_define(type_t *iface, var_list_t *props, func_list_t *methods);
 void type_dispinterface_define_from_iface(type_t *dispiface, type_t *iface);
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index 6b5c3b8988c..dbf198b3e4b 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -330,6 +330,11 @@ struct basic_details
   int sign;
 };
 
+struct pointer_details
+{
+  unsigned char fc;
+};
+
 enum type_type
 {
     TYPE_VOID,
@@ -349,7 +354,7 @@ enum type_type
 
 struct _type_t {
   const char *name;
-  unsigned char type;
+  enum type_type type_type;
   struct _type_t *ref;
   attr_list_t *attrs;
   union
@@ -362,6 +367,7 @@ struct _type_t {
     struct array_details array;
     struct coclass_details coclass;
     struct basic_details basic;
+    struct pointer_details pointer;
   } details;
   type_t *orig;                   /* dup'd types */
   unsigned int typestring_offset;
@@ -496,7 +502,7 @@ int is_union(unsigned char tc);
 
 var_t *find_const(const char *name, int f);
 type_t *find_type(const char *name, int t);
-type_t *make_type(unsigned char type, type_t *ref);
+type_t *make_type(enum type_type type, type_t *ref);
 
 void init_loc_info(loc_info_t *);
 
@@ -509,65 +515,7 @@ static inline enum type_type type_get_type_detect_alias(const type_t *type)
 {
     if (type->is_alias)
         return TYPE_ALIAS;
-    switch (type->type)
-    {
-    case 0:
-        return TYPE_VOID;
-    case RPC_FC_BYTE:
-    case RPC_FC_CHAR:
-    case RPC_FC_USMALL:
-    case RPC_FC_SMALL:
-    case RPC_FC_WCHAR:
-    case RPC_FC_USHORT:
-    case RPC_FC_SHORT:
-    case RPC_FC_ULONG:
-    case RPC_FC_LONG:
-    case RPC_FC_HYPER:
-    case RPC_FC_IGNORE:
-    case RPC_FC_FLOAT:
-    case RPC_FC_DOUBLE:
-    case RPC_FC_ERROR_STATUS_T:
-    case RPC_FC_BIND_PRIMITIVE:
-        return TYPE_BASIC;
-    case RPC_FC_ENUM16:
-    case RPC_FC_ENUM32:
-        return TYPE_ENUM;
-    case RPC_FC_RP:
-    case RPC_FC_UP:
-    case RPC_FC_FP:
-    case RPC_FC_OP:
-        return TYPE_POINTER;
-    case RPC_FC_STRUCT:
-    case RPC_FC_PSTRUCT:
-    case RPC_FC_CSTRUCT:
-    case RPC_FC_CPSTRUCT:
-    case RPC_FC_CVSTRUCT:
-    case RPC_FC_BOGUS_STRUCT:
-        return TYPE_STRUCT;
-    case RPC_FC_ENCAPSULATED_UNION:
-        return TYPE_ENCAPSULATED_UNION;
-    case RPC_FC_NON_ENCAPSULATED_UNION:
-        return TYPE_UNION;
-    case RPC_FC_SMFARRAY:
-    case RPC_FC_LGFARRAY:
-    case RPC_FC_SMVARRAY:
-    case RPC_FC_LGVARRAY:
-    case RPC_FC_CARRAY:
-    case RPC_FC_CVARRAY:
-    case RPC_FC_BOGUS_ARRAY:
-        return TYPE_ARRAY;
-    case RPC_FC_FUNCTION:
-        return TYPE_FUNCTION;
-    case RPC_FC_COCLASS:
-        return TYPE_COCLASS;
-    case RPC_FC_IP:
-        return TYPE_INTERFACE;
-    case RPC_FC_MODULE:
-        return TYPE_MODULE;
-    default:
-        assert(0);
-        return 0;
-    }
+    return type->type_type;
 }
 
 #define STATEMENTS_FOR_EACH_FUNC(stmt, stmts) \
diff --git a/tools/widl/write_msft.c b/tools/widl/write_msft.c
index 3ce5f78b249..5fec81187a8 100644
--- a/tools/widl/write_msft.c
+++ b/tools/widl/write_msft.c
@@ -931,18 +931,10 @@ static int encode_type(
 
     case VT_SAFEARRAY:
 	{
-	int next_vt;
+	type_t *element_type = type_alias_get_aliasee(type_array_get_element(type));
+	int next_vt = get_type_vt(element_type);
 
-	/* skip over SAFEARRAY type straight to element type */
-	type = type->ref;
-
-	for(next_vt = 0; type->ref; type = type->ref) {
-	    next_vt = get_type_vt(type->ref);
-	    if (next_vt != 0)
-	        break;
-	}
-
-	encode_type(typelib, next_vt, type->ref, &target_type, NULL, NULL, &child_size);
+	encode_type(typelib, next_vt, type_alias_get_aliasee(type_array_get_element(type)), &target_type, NULL, NULL, &child_size);
 
 	for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
 	    typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
-- 
GitLab