Dan Hipschman : widl: Detect conformant arrays of user types correctly.

Alexandre Julliard julliard at winehq.org
Thu Oct 18 07:59:33 CDT 2007


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

Author: Dan Hipschman <dsh at linux.ucla.edu>
Date:   Wed Oct 17 18:06:26 2007 -0700

widl: Detect conformant arrays of user types correctly.

---

 dlls/rpcrt4/tests/server.c   |   54 ++++++++++++++++++++++++++++++++++++++++++
 dlls/rpcrt4/tests/server.idl |   16 ++++++++++++
 tools/widl/header.c          |    4 ++-
 tools/widl/parser.y          |   41 ++++++++++++++------------------
 tools/widl/typegen.c         |   16 ++++++++++++
 5 files changed, 107 insertions(+), 24 deletions(-)

diff --git a/dlls/rpcrt4/tests/server.c b/dlls/rpcrt4/tests/server.c
index d8ecff0..97f2e23 100644
--- a/dlls/rpcrt4/tests/server.c
+++ b/dlls/rpcrt4/tests/server.c
@@ -48,6 +48,14 @@ midl_user_free(void __RPC_FAR *p)
   free(p);
 }
 
+static char *
+xstrdup(const char *s)
+{
+  char *d = HeapAlloc(GetProcessHeap(), 0, strlen(s) + 1);
+  strcpy(d, s);
+  return d;
+}
+
 int
 s_int_return(void)
 {
@@ -264,6 +272,26 @@ s_square_puint(puint_t p)
 }
 
 int
+s_sum_puints(puints_t *p)
+{
+  int sum = 0;
+  int i;
+  for (i = 0; i < p->n; ++i)
+    sum += atoi(p->ps[i]);
+  return sum;
+}
+
+int
+s_sum_cpuints(cpuints_t *p)
+{
+  int sum = 0;
+  int i;
+  for (i = 0; i < p->n; ++i)
+    sum += atoi(p->ps[i]);
+  return sum;
+}
+
+int
 s_dot_copy_vectors(vector_t u, vector_t v)
 {
   return u.x * v.x + u.y * v.y + u.z * v.z;
@@ -724,9 +752,35 @@ pointer_tests(void)
   test_list_t *list = make_list(make_list(make_list(null_list())));
   test_us_t tus = {{p1}};
   int *pa[4];
+  puints_t pus;
+  cpuints_t cpus;
 
   ok(test_list_length(list) == 3, "RPC test_list_length\n");
   ok(square_puint(p1) == 121, "RPC square_puint\n");
+  pus.n = 4;
+  pus.ps = HeapAlloc(GetProcessHeap(), 0, pus.n * sizeof pus.ps[0]);
+  pus.ps[0] = xstrdup("5");
+  pus.ps[1] = xstrdup("6");
+  pus.ps[2] = xstrdup("7");
+  pus.ps[3] = xstrdup("8");
+  ok(sum_puints(&pus) == 26, "RPC sum_puints\n");
+  HeapFree(GetProcessHeap(), 0, pus.ps[0]);
+  HeapFree(GetProcessHeap(), 0, pus.ps[1]);
+  HeapFree(GetProcessHeap(), 0, pus.ps[2]);
+  HeapFree(GetProcessHeap(), 0, pus.ps[3]);
+  HeapFree(GetProcessHeap(), 0, pus.ps);
+  cpus.n = 4;
+  cpus.ps = HeapAlloc(GetProcessHeap(), 0, cpus.n * sizeof cpus.ps[0]);
+  cpus.ps[0] = xstrdup("5");
+  cpus.ps[1] = xstrdup("6");
+  cpus.ps[2] = xstrdup("7");
+  cpus.ps[3] = xstrdup("8");
+  ok(sum_cpuints(&cpus) == 26, "RPC sum_puints\n");
+  HeapFree(GetProcessHeap(), 0, cpus.ps[0]);
+  HeapFree(GetProcessHeap(), 0, cpus.ps[1]);
+  HeapFree(GetProcessHeap(), 0, cpus.ps[2]);
+  HeapFree(GetProcessHeap(), 0, cpus.ps[3]);
+  HeapFree(GetProcessHeap(), 0, cpus.ps);
   ok(square_test_us(&tus) == 121, "RPC square_test_us\n");
 
   pa[0] = &a[0];
diff --git a/dlls/rpcrt4/tests/server.idl b/dlls/rpcrt4/tests/server.idl
index 6233a1f..807bf44 100644
--- a/dlls/rpcrt4/tests/server.idl
+++ b/dlls/rpcrt4/tests/server.idl
@@ -153,6 +153,22 @@ cpp_quote("#endif")
 
   typedef [wire_marshal(int)] void *puint_t;
   int square_puint(puint_t p);
+
+  typedef struct
+  {
+    [size_is(n)] puint_t *ps;
+    int n;
+  } puints_t;
+
+  /* Same thing as puints_t, but make it complex (needs padding).  */
+  typedef struct
+  {
+    [size_is(n)] puint_t *ps;
+    char n;
+  } cpuints_t;
+
+  int sum_puints(puints_t *p);
+  int sum_cpuints(cpuints_t *p);
   int dot_copy_vectors(vector_t u, vector_t v);
 
   typedef struct wire_us *wire_us_t;
diff --git a/tools/widl/header.c b/tools/widl/header.c
index 2643f49..8de9b9f 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -101,7 +101,9 @@ int is_void(const type_t *t)
 
 int is_conformant_array(const type_t *t)
 {
-    return t->type == RPC_FC_CARRAY || t->type == RPC_FC_CVARRAY;
+    return t->type == RPC_FC_CARRAY
+        || t->type == RPC_FC_CVARRAY
+        || (t->type == RPC_FC_BOGUS_ARRAY && t->size_is);
 }
 
 void write_guid(FILE *f, const char *guid_prefix, const char *name, const UUID *uuid)
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index 96e9891..6a93995 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -1434,24 +1434,24 @@ static void set_type(var_t *v, type_t *type, int ptr_level, array_dims_t *arr,
   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:
+    if (is_user_type(rt))
       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;
-    }
+    else
+      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;
+        }
   }
 }
 
@@ -1859,6 +1859,7 @@ static int get_struct_type(var_list_t *fields)
     case RPC_FC_OP:
     case RPC_FC_CARRAY:
     case RPC_FC_CVARRAY:
+    case RPC_FC_BOGUS_ARRAY:
       has_pointer = 1;
       break;
 
@@ -1897,15 +1898,9 @@ static int get_struct_type(var_list_t *fields)
       /* 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:
-    case RPC_FC_BOGUS_ARRAY:
       return RPC_FC_BOGUS_STRUCT;
     }
   }
diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c
index 53ec78c..2245524 100644
--- a/tools/widl/typegen.c
+++ b/tools/widl/typegen.c
@@ -1744,6 +1744,22 @@ static size_t write_struct_tfs(FILE *file, type_t *type,
             type_t *ft = f->type;
             if (is_ptr(ft))
                 write_pointer_tfs(file, ft, tfsoff);
+            else if (!ft->declarray && is_conformant_array(ft))
+            {
+                unsigned int absoff = ft->typestring_offset;
+                short reloff = absoff - (*tfsoff + 2);
+                int ptr_type = get_attrv(f->attrs, ATTR_POINTERTYPE);
+                /* FIXME: We need to store pointer attributes for arrays
+                   so we don't lose pointer_default info.  */
+                if (ptr_type == 0)
+                    ptr_type = RPC_FC_UP;
+                print_file(file, 0, "/* %d */\n", *tfsoff);
+                print_file(file, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type,
+                           string_of_type(ptr_type));
+                print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
+                           reloff, reloff, absoff);
+                *tfsoff += 4;
+            }
         }
         if (type->ptrdesc == *tfsoff)
             type->ptrdesc = 0;




More information about the wine-cvs mailing list