widl [2/4]: Implement pointer descriptions for complex structures

Dan Hipschman dsh at linux.ucla.edu
Tue Sep 18 17:28:49 CDT 2007


This patch is also the same as yesterday.  It implements pointer descriptions
for complex structures, needed by lots of stuff, including oaidl.  Tests pass
on wine and windows.  This patch is similar to, and conflicts with, Rob's for
FC_POINTERs from yesterday:
http://www.winehq.org/pipermail/wine-patches/2007-September/043979.html
except it implements the pointer descriptions as well and includes tests.

---
 dlls/rpcrt4/tests/server.c   |   16 ++++++++++++++++
 dlls/rpcrt4/tests/server.idl |   15 +++++++++++++++
 tools/widl/parser.y          |    1 +
 tools/widl/typegen.c         |   38 +++++++++++++++++++++++++++++++-------
 tools/widl/widltypes.h       |    1 +
 5 files changed, 64 insertions(+), 7 deletions(-)

diff --git a/dlls/rpcrt4/tests/server.c b/dlls/rpcrt4/tests/server.c
index 879e0d1..2ed6de7 100644
--- a/dlls/rpcrt4/tests/server.c
+++ b/dlls/rpcrt4/tests/server.c
@@ -350,6 +350,12 @@ s_sum_padded(padded_t *p)
   return p->i + p->c;
 }
 
+int
+s_sum_bogus(bogus_t *b)
+{
+  return *b->h.p1 + *b->p2 + *b->p3 + b->c;
+}
+
 void
 s_stop(void)
 {
@@ -399,6 +405,7 @@ basic_tests(void)
   pints_t pints;
   ptypes_t ptypes;
   padded_t padded;
+  bogus_t bogus;
   int i1, i2, i3, *pi2, *pi3, **ppi3;
   double u, v;
   float s, t;
@@ -476,6 +483,15 @@ basic_tests(void)
   padded.i = -3;
   padded.c = 8;
   ok(sum_padded(&padded) == 5, "RPC sum_padded\n");
+
+  i1 = 14;
+  i2 = -7;
+  i3 = -4;
+  bogus.h.p1 = &i1;
+  bogus.p2 = &i2;
+  bogus.p3 = &i3;
+  bogus.c = 9;
+  ok(sum_bogus(&bogus) == 12, "RPC sum_bogus\n");
 }
 
 static void
diff --git a/dlls/rpcrt4/tests/server.idl b/dlls/rpcrt4/tests/server.idl
index d84637c..44bb945 100644
--- a/dlls/rpcrt4/tests/server.idl
+++ b/dlls/rpcrt4/tests/server.idl
@@ -208,5 +208,20 @@ interface IServer
 
   int sum_padded(padded_t *p);
 
+  typedef struct
+  {
+    int *p1;
+  } bogus_helper_t;
+
+  typedef struct
+  {
+    bogus_helper_t h;
+    int *p2;
+    int *p3;
+    char c;
+  } bogus_t;
+
+  int sum_bogus(bogus_t *b);
+
   void stop(void);
 }
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index ac24038..fbaf9a7 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -1249,6 +1249,7 @@ static type_t *make_type(unsigned char type, type_t *ref)
   t->size_is = NULL;
   t->length_is = NULL;
   t->typestring_offset = 0;
+  t->ptrdesc = 0;
   t->declarray = FALSE;
   t->ignore = (parse_only != 0);
   t->is_const = FALSE;
diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c
index 71885c7..573d88b 100644
--- a/tools/widl/typegen.c
+++ b/tools/widl/typegen.c
@@ -100,6 +100,7 @@ const char *string_of_type(unsigned char type)
     case RPC_FC_BOGUS_ARRAY: return "FC_BOGUS_ARRAY";
     case RPC_FC_ALIGNM4: return "FC_ALIGNM4";
     case RPC_FC_ALIGNM8: return "FC_ALIGNM8";
+    case RPC_FC_POINTER: return "FC_POINTER";
     default:
         error("string_of_type: unknown type 0x%02x\n", type);
         return NULL;
@@ -918,7 +919,8 @@ static void write_user_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
     *tfsoff += 2;
 }
 
-static void write_member_type(FILE *file, type_t *type, const var_t *field,
+static void write_member_type(FILE *file, const type_t *cont,
+                              const attr_list_t *attrs, const type_t *type,
                               unsigned int *corroff, unsigned int *tfsoff)
 {
     if (is_embedded_complex(type))
@@ -926,7 +928,7 @@ static void write_member_type(FILE *file, type_t *type, const var_t *field,
         size_t absoff;
         short reloff;
 
-        if (is_union(type->type) && is_attr(field->attrs, ATTR_SWITCHIS))
+        if (is_union(type->type) && is_attr(attrs, ATTR_SWITCHIS))
         {
             absoff = *corroff;
             *corroff += 8;
@@ -946,7 +948,10 @@ static void write_member_type(FILE *file, type_t *type, const var_t *field,
     }
     else if (is_ptr(type))
     {
-        print_file(file, 2, "0x8,\t/* FC_LONG */\n");
+        unsigned char fc = (cont->type == RPC_FC_BOGUS_STRUCT
+                            ? RPC_FC_POINTER
+                            : RPC_FC_LONG);
+        print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
         *tfsoff += 1;
     }
     else if (!write_base_type(file, type, tfsoff))
@@ -1521,7 +1526,7 @@ static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type
             *typestring_offset += 1;
         }
 
-        write_member_type(file, type->ref, NULL, NULL, typestring_offset);
+        write_member_type(file, type, NULL, type->ref, NULL, typestring_offset);
         write_end(file, typestring_offset);
     }
     else
@@ -1579,7 +1584,8 @@ static void write_struct_members(FILE *file, const type_t *type,
                 offset = (offset + (align - 1)) & ~(align - 1);
                 *typestring_offset += 1;
             }
-            write_member_type(file, ft, field, corroff, typestring_offset);
+            write_member_type(file, type, field->attrs, field->type, corroff,
+                              typestring_offset);
             offset += size;
         }
     }
@@ -1655,8 +1661,12 @@ static size_t write_struct_tfs(FILE *file, type_t *type,
 
     if (type->type == RPC_FC_BOGUS_STRUCT)
     {
-
-        print_file(file, 2, "NdrFcShort(0x0),\t/* FIXME: pointer stuff */\n");
+        /* On the sizing pass, type->ptrdesc may be zero, but it's ok as
+           nothing is written to file yet.  On the actual writing pass,
+           this will have been updated.  */
+        short reloff = type->ptrdesc - *tfsoff;
+        print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
+                   reloff, reloff, type->ptrdesc);
         *tfsoff += 2;
     }
     else if ((type->type == RPC_FC_PSTRUCT) ||
@@ -1673,6 +1683,20 @@ static size_t write_struct_tfs(FILE *file, type_t *type,
 
     write_struct_members(file, type, &corroff, tfsoff);
 
+    if (type->type == RPC_FC_BOGUS_STRUCT)
+    {
+        const var_list_t *fs = type->fields;
+        const var_t *f;
+
+        type->ptrdesc = *tfsoff;
+        if (fs) LIST_FOR_EACH_ENTRY(f, fs, const var_t, entry)
+        {
+            type_t *ft = f->type;
+            if (is_ptr(ft))
+                write_pointer_tfs(file, ft, tfsoff);
+        }
+    }
+
     current_structure = save_current_structure;
     return start_offset;
 }
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index d514d54..2b1aaa9 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -214,6 +214,7 @@ struct _type_t {
   expr_t *size_is, *length_is;
   type_t *orig;                   /* dup'd types */
   unsigned int typestring_offset;
+  unsigned int ptrdesc;           /* used for complex structs */
   int typelib_idx;
   unsigned int declarray : 1;     /* if declared as an array */
   unsigned int ignore : 1;



More information about the wine-patches mailing list