WIDL: determine RPC struct types more exactly

Mike McCormack mike at codeweavers.com
Tue Sep 14 13:51:01 CDT 2004


ChangeLog:
* determine RPC struct types more exactly
-------------- next part --------------
Index: tools/widl/header.c
===================================================================
RCS file: /home/wine/wine/tools/widl/header.c,v
retrieving revision 1.26
diff -u -r1.26 header.c
--- tools/widl/header.c	23 Aug 2004 18:10:02 -0000	1.26
+++ tools/widl/header.c	14 Sep 2004 17:16:39 -0000
@@ -129,6 +129,11 @@
       /* not all C/C++ compilers support anonymous structs and unions */
       switch (v->type->type) {
       case RPC_FC_STRUCT:
+      case RPC_FC_CVSTRUCT:
+      case RPC_FC_CPSTRUCT:
+      case RPC_FC_CSTRUCT:
+      case RPC_FC_PSTRUCT:
+      case RPC_FC_BOGUS_STRUCT:
       case RPC_FC_ENCAPSULATED_UNION:
         fprintf(h, " DUMMYSTRUCTNAME");
         break;
@@ -241,6 +246,11 @@
         else fprintf(h, "handle_t");
         break;
       case RPC_FC_STRUCT:
+      case RPC_FC_CVSTRUCT:
+      case RPC_FC_CPSTRUCT:
+      case RPC_FC_CSTRUCT:
+      case RPC_FC_PSTRUCT:
+      case RPC_FC_BOGUS_STRUCT:
       case RPC_FC_ENCAPSULATED_UNION:
         if (t->defined && !t->written) {
           if (t->name) fprintf(h, "struct %s {\n", t->name);
Index: tools/widl/parser.y
===================================================================
RCS file: /home/wine/wine/tools/widl/parser.y,v
retrieving revision 1.18
diff -u -r1.18 parser.y
--- tools/widl/parser.y	13 Sep 2004 18:05:47 -0000	1.18
+++ tools/widl/parser.y	14 Sep 2004 17:16:39 -0000
@@ -89,6 +89,7 @@
 static type_t *find_type2(char *name, int t);
 static type_t *get_type(unsigned char type, char *name, int t);
 static type_t *get_typev(unsigned char type, var_t *name, int t);
+static int get_struct_type(var_t *fields);
 
 static var_t *reg_const(var_t *var);
 static var_t *find_const(char *name, int f);
@@ -676,6 +677,8 @@
 	;
 
 structdef: tSTRUCT t_ident '{' fields '}'	{ $$ = get_typev(RPC_FC_STRUCT, $2, tsSTRUCT);
+                                                  /* overwrite RPC_FC_STRUCT with a more exact type */
+						  $$->type = get_struct_type( $4 );
 						  $$->fields = $4;
 						  $$->defined = TRUE;
 						}
@@ -1066,10 +1069,8 @@
 /* determine pointer type from attrs */
 static unsigned char get_pointer_type( type_t *type )
 {
-    if( is_attr( type->attrs, ATTR_SIZEIS ) )
-        return RPC_FC_CARRAY;
-    if( type->fields )
-        return RPC_FC_CSTRUCT;
+    int t = get_attrv( type->attrs, ATTR_POINTERTYPE );
+    if( t ) return t;
     return RPC_FC_FP;
 }
 
@@ -1158,6 +1159,112 @@
     free(name);
   }
   return get_type(type, sname, t);
+}
+
+static int get_struct_type(var_t *field)
+{
+  int has_pointer = 0;
+  int has_conformant_array = 0;
+  int has_conformant_string = 0;
+
+  while (field)
+  {
+    type_t *t = field->type;
+
+    /* get the base type */
+    while( (t->type == 0) && t->ref )
+      t = t->ref;
+
+    switch (t->type)
+    {
+    /*
+     * RPC_FC_BYTE, RPC_FC_STRUCT, etc
+     *  Simple types don't effect the type of struct.
+     *  A struct containing a simple struct is still a simple struct.
+     *  So long as we can block copy the data, we return RPC_FC_STRUCT.
+     */
+    case 0: /* void pointer */
+    case RPC_FC_BYTE:
+    case RPC_FC_CHAR:
+    case RPC_FC_SMALL:
+    case RPC_FC_USMALL:
+    case RPC_FC_WCHAR:
+    case RPC_FC_SHORT:
+    case RPC_FC_USHORT:
+    case RPC_FC_LONG:
+    case RPC_FC_ULONG:
+    case RPC_FC_INT3264:
+    case RPC_FC_UINT3264:
+    case RPC_FC_HYPER:
+    case RPC_FC_FLOAT:
+    case RPC_FC_DOUBLE:
+    case RPC_FC_STRUCT:
+    case RPC_FC_ENUM16:
+    case RPC_FC_ENUM32:
+      break;
+
+    case RPC_FC_UP:
+    case RPC_FC_FP:
+      has_pointer = 1;
+      break;
+    case RPC_FC_CARRAY:
+      has_conformant_array = 1;
+      break;
+    case RPC_FC_C_CSTRING:
+    case RPC_FC_C_WSTRING:
+      has_conformant_string = 1;
+      break;
+
+    /*
+     * Propagate member attributes
+     *  a struct should be at least as complex as its member
+     */
+    case RPC_FC_CVSTRUCT:
+      has_conformant_string = 1;
+      has_pointer = 1;
+      break;
+
+    case RPC_FC_CPSTRUCT:
+      has_conformant_array = 1;
+      has_pointer = 1;
+      break;
+
+    case RPC_FC_CSTRUCT:
+      has_conformant_array = 1;
+      break;
+
+    case RPC_FC_PSTRUCT:
+      has_pointer = 1;
+      break;
+
+    default:
+      fprintf(stderr,"Unknown struct member %s with type (0x%02x)\n",
+              field->name, t->type);
+      /* fallthru - treat it as complex */
+
+    /* as soon as we see one of these these members, it's bogus... */
+    case RPC_FC_IP:
+    case RPC_FC_ENCAPSULATED_UNION:
+    case RPC_FC_NON_ENCAPSULATED_UNION:
+    case RPC_FC_TRANSMIT_AS:
+    case RPC_FC_REPRESENT_AS:
+    case RPC_FC_PAD:
+    case RPC_FC_EMBEDDED_COMPLEX:
+    case RPC_FC_BOGUS_STRUCT:
+      return RPC_FC_BOGUS_STRUCT;
+    }
+    field = NEXT_LINK(field);
+  }
+
+  if( has_conformant_string && has_pointer )
+    return RPC_FC_CVSTRUCT;
+  if( has_conformant_array && has_pointer )
+    return RPC_FC_CPSTRUCT;
+  if( has_conformant_array )
+    return RPC_FC_CSTRUCT;
+  if( has_pointer )
+    return RPC_FC_PSTRUCT;
+  return RPC_FC_STRUCT;
 }
 
 /***** constant repository *****/


More information about the wine-patches mailing list