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

Dan Hipschman dsh at linux.ucla.edu
Mon Sep 17 19:01:35 CDT 2007


This patch implements pointer descriptions for complex structures, which
is going to be needed a lot for oaidl.idl, and other things.

---
 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 c11ebd5..fc02f0c 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;
@@ -912,7 +913,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))
@@ -920,7 +922,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;
@@ -940,7 +942,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))
@@ -1515,7 +1520,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
@@ -1573,7 +1578,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;
         }
     }
@@ -1649,8 +1655,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) ||
@@ -1667,6 +1677,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