widl [2/3]: Handle pointers to conformant arrays (e.g., "[size_is(, n)] int **p; ").

Dan Hipschman dsh at linux.ucla.edu
Fri Nov 2 17:24:08 CDT 2007


This patch gets widl to handle pointers to conformant arrays.  For example:

	[size_is(, n)] int **p;

This appears in dcom.idl, so it's going to be needed.

---
 dlls/rpcrt4/tests/server.c   |   10 ++++++++++
 dlls/rpcrt4/tests/server.idl |    2 ++
 tools/widl/header.h          |    3 ++-
 tools/widl/typegen.c         |   37 ++++++++++++++++++++++++++++++++++++-
 4 files changed, 50 insertions(+), 2 deletions(-)

diff --git a/dlls/rpcrt4/tests/server.c b/dlls/rpcrt4/tests/server.c
index a82fe91..b01967d 100644
--- a/dlls/rpcrt4/tests/server.c
+++ b/dlls/rpcrt4/tests/server.c
@@ -481,6 +481,12 @@ s_get_name(name_t *name)
     name->name[name->size - 1] = 0;
 }
 
+int
+s_sum_pcarr2(int n, int **pa)
+{
+  return s_sum_conf_array(*pa, n);
+}
+
 void
 s_stop(void)
 {
@@ -812,6 +818,7 @@ pointer_tests(void)
   bstr_t bstr = &bstr_data[1];
   name_t name;
   void *buffer;
+  int *pa2;
 
   ok(test_list_length(list) == 3, "RPC test_list_length\n");
   ok(square_puint(p1) == 121, "RPC square_puint\n");
@@ -862,6 +869,9 @@ pointer_tests(void)
   todo_wine
   ok(name.name == buffer, "[in,out] pointer should have stayed as %p but instead changed to %p\n", name.name, buffer);
   HeapFree(GetProcessHeap(), 0, name.name);
+
+  pa2 = a;
+  ok(sum_pcarr2(4, &pa2) == 10, "RPC sum_pcarr2\n");
 }
 
 static int
diff --git a/dlls/rpcrt4/tests/server.idl b/dlls/rpcrt4/tests/server.idl
index 15402ee..c566b8f 100644
--- a/dlls/rpcrt4/tests/server.idl
+++ b/dlls/rpcrt4/tests/server.idl
@@ -297,5 +297,7 @@ cpp_quote("#endif")
   } name_t;
   void get_name([in,out] name_t *name);
 
+  int sum_pcarr2(int n, [size_is(, n)] int **pa);
+
   void stop(void);
 }
diff --git a/tools/widl/header.h b/tools/widl/header.h
index 47564de..41784a0 100644
--- a/tools/widl/header.h
+++ b/tools/widl/header.h
@@ -29,6 +29,7 @@ extern void *get_attrp(const attr_list_t *list, enum attr_type t);
 extern unsigned long get_attrv(const attr_list_t *list, enum attr_type t);
 extern int is_void(const type_t *t);
 extern int is_conformant_array(const type_t *t);
+extern int is_declptr(const type_t *t);
 extern void write_name(FILE *h, const var_t *v);
 extern void write_prefix_name(FILE *h, const char *prefix, const var_t *v);
 extern const char* get_name(const var_t *v);
@@ -67,7 +68,7 @@ extern void write_guid(FILE *f, const char *guid_prefix, const char *name,
 
 static inline int last_ptr(const type_t *type)
 {
-    return is_ptr(type) && !is_ptr(type->ref);
+    return is_ptr(type) && !is_declptr(type->ref);
 }
 
 static inline int last_array(const type_t *type)
diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c
index f6d5536..a9cd2eb 100644
--- a/tools/widl/typegen.c
+++ b/tools/widl/typegen.c
@@ -1420,7 +1420,7 @@ static void write_pointer_description(FILE *file, type_t *type,
             &offset_in_memory, &offset_in_buffer, typestring_offset);
 }
 
-static int is_declptr(const type_t *t)
+int is_declptr(const type_t *t)
 {
   return is_ptr(t) || (is_conformant_array(t) && !t->declarray);
 }
@@ -2083,6 +2083,14 @@ static size_t write_typeformatstring_var(FILE *file, int indent, const func_t *f
         size_t off;
         off = write_array_tfs(file, var->attrs, type, var->name, typeformat_offset);
         ptr_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
+        /* Top level pointers to conformant arrays may be handled specially
+           since we can bypass the pointer, but if the array is burried
+           beneath another pointer (e.g., "[size_is(,n)] int **p" then we
+           always need to write the pointer.  */
+        if (!ptr_type && var->type != type)
+          /* FIXME:  This should use pointer_default, but the information
+             isn't kept around for arrays.  */
+          ptr_type = RPC_FC_UP;
         if (ptr_type && ptr_type != RPC_FC_RP)
         {
             unsigned int absoff = type->typestring_offset;
@@ -2711,6 +2719,13 @@ void write_remoting_arguments(FILE *file, int indent, const func_t *func,
         {
             unsigned char tc = type->type;
             const char *array_type = "FixedArray";
+            type_t *st;
+
+            for (st = type->ref; is_ptr(st) || is_array(st); st = st->ref)
+                if (st->size_is)
+                    error("in function %s: multidimensional conformant arrays"
+                          " not supported at the top level\n",
+                          func->def->name);
 
             if (tc == RPC_FC_SMVARRAY || tc == RPC_FC_LGVARRAY)
             {
@@ -2826,8 +2841,28 @@ void write_remoting_arguments(FILE *file, int indent, const func_t *func,
             else
             {
                 const var_t *iid;
+                expr_t *sx = NULL;
+                type_t *st;
+
+                for (st = type->ref; is_ptr(st) || is_array(st); st = st->ref)
+                    if (st->size_is)
+                    {
+                        if (!sx)
+                            sx = st->size_is;
+                        else
+                            error("in function %s: multidimensional conformant"
+                                  " arrays not supported at the top level\n",
+                                  func->def->name);
+                    }
+
                 if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
                     print_file( file, indent, "_StubMsg.MaxCount = (unsigned long)%s;\n", iid->name );
+                else if (sx)
+                {
+                    print_file(file, indent, "_StubMsg.MaxCount = (unsigned long) ");
+                    write_expr(file, sx, 1);
+                    fprintf(file, ";\n\n");
+                }
                 if (var->type->ref->type == RPC_FC_IP)
                     print_phase_function(file, indent, "InterfacePointer", phase, var, start_offset);
                 else



More information about the wine-patches mailing list