widl [4/4]: Implement complex arrays

Dan Hipschman dsh at linux.ucla.edu
Tue Sep 18 17:29:59 CDT 2007


This implements complex arrays.  It's aim is the same as, and conflicts
with, Rob's patch for complex arrays sent yesterday:
http://www.winehq.org/pipermail/wine-patches/2007-September/043980.html
except it includes tests, and of course, it fits on top of the previous
patches in this set.  I had another test for arrays of unions, but that
is going to require some work to rpcrt4 before it passes (it works on
windows, though).  The tests included here do pass on both wine and
windows.

---
 dlls/rpcrt4/tests/server.c   |   12 ++++++++++++
 dlls/rpcrt4/tests/server.idl |    1 +
 tools/widl/parser.y          |   25 ++++++++++++++++++++++---
 tools/widl/typegen.c         |   25 +++++++++++++++++++------
 tools/widl/typegen.h         |    1 +
 5 files changed, 55 insertions(+), 9 deletions(-)

diff --git a/dlls/rpcrt4/tests/server.c b/dlls/rpcrt4/tests/server.c
index 2ed6de7..40f9a81 100644
--- a/dlls/rpcrt4/tests/server.c
+++ b/dlls/rpcrt4/tests/server.c
@@ -351,6 +351,12 @@ s_sum_padded(padded_t *p)
 }
 
 int
+s_sum_padded2(padded_t ps[2])
+{
+  return s_sum_padded(&ps[0]) + s_sum_padded(&ps[1]);
+}
+
+int
 s_sum_bogus(bogus_t *b)
 {
   return *b->h.p1 + *b->p2 + *b->p3 + b->c;
@@ -405,6 +411,7 @@ basic_tests(void)
   pints_t pints;
   ptypes_t ptypes;
   padded_t padded;
+  padded_t padded2[2];
   bogus_t bogus;
   int i1, i2, i3, *pi2, *pi3, **ppi3;
   double u, v;
@@ -483,6 +490,11 @@ basic_tests(void)
   padded.i = -3;
   padded.c = 8;
   ok(sum_padded(&padded) == 5, "RPC sum_padded\n");
+  padded2[0].i = -5;
+  padded2[0].c = 1;
+  padded2[1].i = 3;
+  padded2[1].c = 7;
+  ok(sum_padded2(padded2) == 6, "RPC sum_padded2\n");
 
   i1 = 14;
   i2 = -7;
diff --git a/dlls/rpcrt4/tests/server.idl b/dlls/rpcrt4/tests/server.idl
index 44bb945..23ca779 100644
--- a/dlls/rpcrt4/tests/server.idl
+++ b/dlls/rpcrt4/tests/server.idl
@@ -207,6 +207,7 @@ interface IServer
   } padded_t;
 
   int sum_padded(padded_t *p);
+  int sum_padded2(padded_t ps[2]);
 
   typedef struct
   {
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index fbaf9a7..46fb439 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -1365,9 +1365,28 @@ static void set_type(var_t *v, type_t *type, int ptr_level, array_dims_t *arr)
     }
   }
 
-  /* if the structure is complex, then so must be the encompassing array */
-  if (is_array(v->type) && (v->type->ref->type == RPC_FC_BOGUS_STRUCT))
-    v->type->type = RPC_FC_BOGUS_ARRAY;
+  if (is_array(v->type))
+  {
+    const type_t *rt = v->type->ref;
+    switch (rt->type)
+    {
+    case RPC_FC_BOGUS_STRUCT:
+    case RPC_FC_NON_ENCAPSULATED_UNION:
+    case RPC_FC_ENCAPSULATED_UNION:
+    case RPC_FC_ENUM16:
+      v->type->type = RPC_FC_BOGUS_ARRAY;
+      break;
+    /* FC_RP should be above, but widl overuses these, and will break things.  */
+    case RPC_FC_UP:
+    case RPC_FC_RP:
+      if (rt->ref->type == RPC_FC_IP)
+        v->type->type = RPC_FC_BOGUS_ARRAY;
+      break;
+    default:
+      if (is_user_type(rt))
+        v->type->type = RPC_FC_BOGUS_ARRAY;
+    }
+  }
 }
 
 static ifref_list_t *append_ifref(ifref_list_t *list, ifref_t *iface)
diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c
index d821065..6625bda 100644
--- a/tools/widl/typegen.c
+++ b/tools/widl/typegen.c
@@ -200,7 +200,7 @@ static type_t *get_user_type(const type_t *t, const char **pname)
     }
 }
 
-static int is_user_type(const type_t *t)
+int is_user_type(const type_t *t)
 {
     return get_user_type(t, NULL) != NULL;
 }
@@ -1448,6 +1448,11 @@ static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type
     size_t start_offset;
     int has_pointer;
     int pointer_type = get_attrv(attrs, ATTR_POINTERTYPE);
+    unsigned int baseoff
+        = type->declarray && current_structure
+        ? type_memsize(current_structure, &align)
+        : 0;
+
     if (!pointer_type)
         pointer_type = RPC_FC_RP;
 
@@ -1470,10 +1475,6 @@ static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type
     if (type->type != RPC_FC_BOGUS_ARRAY)
     {
         unsigned char tc = type->type;
-        unsigned int baseoff
-            = type->declarray && current_structure
-            ? type_memsize(current_structure, &align)
-            : 0;
 
         if (tc == RPC_FC_LGFARRAY || tc == RPC_FC_LGVARRAY)
         {
@@ -1530,7 +1531,19 @@ static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type
         write_end(file, typestring_offset);
     }
     else
-        error("%s: complex arrays unimplemented\n", name);
+    {
+        unsigned int dim = size_is ? 0 : type->dim;
+        print_file(file, 2, "NdrFcShort(0x%x),\t/* %u */\n", dim, dim);
+        *typestring_offset += 2;
+        *typestring_offset
+            += write_conf_or_var_desc(file, current_structure, baseoff,
+                                      size_is);
+        *typestring_offset
+            += write_conf_or_var_desc(file, current_structure, baseoff,
+                                      length_is);
+        write_member_type(file, type, NULL, type->ref, NULL, typestring_offset);
+        write_end(file, typestring_offset);
+    }
 
     return start_offset;
 }
diff --git a/tools/widl/typegen.h b/tools/widl/typegen.h
index 448e503..fc17c19 100644
--- a/tools/widl/typegen.h
+++ b/tools/widl/typegen.h
@@ -56,3 +56,4 @@ int decl_indirect(const type_t *t);
 void write_parameters_init(FILE *file, int indent, const func_t *func);
 void print(FILE *file, int indent, const char *format, va_list ap);
 int get_padding(const var_list_t *fields);
+int is_user_type(const type_t *t);



More information about the wine-patches mailing list