widl [2/6]: Fix conformant array test failures

Dan Hipschman dsh at linux.ucla.edu
Mon Sep 24 21:18:23 CDT 2007


This patch gets conformant arrays working in the tests.  Currently, only
the address of some conformant arrays are being marshalled, and this wasn't
showing up in the tests because some storage was static.  This patch fixes
the problem by writing pointers to conformant array types in the format
string.  This also requires handling field pointer conformances, and
expression evaluation routines that expect the containing structure of a
conformant array at the top of the stack, rather than the conformant array
itself.  With this patch, the tests still pass, but correctly this time.

---
 tools/widl/typegen.c |   94 +++++++++++++++++++++++++++++++++++---------------
 1 files changed, 66 insertions(+), 28 deletions(-)

diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c
index 06ebd4f..4d07fee 100644
--- a/tools/widl/typegen.c
+++ b/tools/widl/typegen.c
@@ -51,6 +51,7 @@ struct expr_eval_routine
 {
     struct list entry;
     const type_t *structure;
+    unsigned int baseoff;
     const expr_t *expr;
 };
 
@@ -489,9 +490,12 @@ static int write_base_type(FILE *file, const type_t *type, unsigned int *typestr
 
 /* write conformance / variance descriptor */
 static size_t write_conf_or_var_desc(FILE *file, const type_t *structure,
-                                     unsigned int baseoff, const expr_t *expr)
+                                     unsigned int baseoff, const type_t *type,
+                                     const expr_t *expr)
 {
     unsigned char operator_type = 0;
+    unsigned char conftype = RPC_FC_NORMAL_CONFORMANCE;
+    const char *conftype_string = "";
     const char *operator_string = "no operators";
     const expr_t *subexpr;
 
@@ -526,6 +530,12 @@ static size_t write_conf_or_var_desc(FILE *file, const type_t *structure,
         return 4;
     }
 
+    if (is_ptr(type) || (is_array(type) && !type->declarray))
+    {
+        conftype = RPC_FC_POINTER_CONFORMANCE;
+        conftype_string = "field pointer, ";
+    }
+
     subexpr = expr;
     switch (subexpr->type)
     {
@@ -635,8 +645,8 @@ static size_t write_conf_or_var_desc(FILE *file, const type_t *structure,
                 correlation_variable_type);
         }
 
-        print_file(file, 2, "0x%x, /* Corr desc: %s */\n",
-                   RPC_FC_NORMAL_CONFORMANCE | param_type, string_of_type(param_type));
+        print_file(file, 2, "0x%x, /* Corr desc: %s%s */\n",
+                   conftype | param_type, conftype_string, string_of_type(param_type));
         print_file(file, 2, "0x%x, /* %s */\n", operator_type, operator_string);
         print_file(file, 2, "NdrFcShort(0x%x), /* offset = %d */\n",
                    offset, offset);
@@ -662,6 +672,7 @@ static size_t write_conf_or_var_desc(FILE *file, const type_t *structure,
         {
             eval = xmalloc (sizeof(*eval));
             eval->structure = structure;
+            eval->baseoff = baseoff;
             eval->expr = expr;
             list_add_tail (&expr_eval_routines, &eval->entry);
         }
@@ -669,7 +680,7 @@ static size_t write_conf_or_var_desc(FILE *file, const type_t *structure,
         if (callback_offset > USHRT_MAX)
             error("Maximum number of callback routines reached\n");
 
-        print_file(file, 2, "0x%x, /* Corr desc: */\n", RPC_FC_NORMAL_CONFORMANCE);
+        print_file(file, 2, "0x%x, /* Corr desc: %s */\n", conftype, conftype_string);
         print_file(file, 2, "0x%x, /* %s */\n", RPC_FC_CALLBACK, "FC_CALLBACK");
         print_file(file, 2, "NdrFcShort(0x%x), /* %u */\n", callback_offset, callback_offset);
     }
@@ -910,7 +921,7 @@ 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))
+    if (is_embedded_complex(type) && !is_conformant_array(type))
     {
         size_t absoff;
         short reloff;
@@ -933,7 +944,7 @@ static void write_member_type(FILE *file, const type_t *cont,
                    reloff, reloff, absoff);
         *tfsoff += 4;
     }
-    else if (is_ptr(type))
+    else if (is_ptr(type) || is_conformant_array(type))
     {
         unsigned char fc = (cont->type == RPC_FC_BOGUS_STRUCT
                             ? RPC_FC_POINTER
@@ -973,7 +984,7 @@ static void write_descriptors(FILE *file, type_t *type, unsigned int *tfsoff)
             print_file(file, 0, "/* %d */\n", *tfsoff);
             print_file(file, 2, "0x%x,\t/* %s */\n", ft->type, string_of_type(ft->type));
             print_file(file, 2, "0x%x,\t/* FIXME: always FC_LONG */\n", RPC_FC_LONG);
-            write_conf_or_var_desc(file, current_structure, offset,
+            write_conf_or_var_desc(file, current_structure, offset, ft,
                                    get_attrp(f->attrs, ATTR_SWITCHIS));
             print_file(file, 2, "NdrFcShort(%hd),\t/* Offset= %hd (%u) */\n",
                        reloff, reloff, absoff);
@@ -993,7 +1004,7 @@ static int write_no_repeat_pointer_descriptions(
     int written = 0;
     unsigned int align;
 
-    if (is_ptr(type))
+    if (is_ptr(type) || is_conformant_array(type))
     {
         print_file(file, 2, "0x%02x, /* FC_NO_REPEAT */\n", RPC_FC_NO_REPEAT);
         print_file(file, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD);
@@ -1003,10 +1014,18 @@ static int write_no_repeat_pointer_descriptions(
         print_file(file, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer, *offset_in_buffer);
         *typestring_offset += 6;
 
-        if (processed(type->ref) || is_base_type(type->ref->type))
+        if (is_ptr(type))
             write_pointer_tfs(file, type, typestring_offset);
         else
-            error("write_pointer_description: type format string unknown\n");
+        {
+            unsigned absoff = type->typestring_offset;
+            short reloff = absoff - (*typestring_offset + 2);
+            /* FIXME: get pointer attributes from field */
+            print_file(file, 2, "0x%02x, 0x0,\t/* %s */\n", RPC_FC_UP, "FC_UP");
+            print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
+                       reloff, reloff, absoff);
+            *typestring_offset += 4;
+        }
 
         align = 0;
         *offset_in_memory += type_memsize(type, &align);
@@ -1304,11 +1323,14 @@ static void write_pointer_description(FILE *file, type_t *type,
 
     /* pass 1: search for single instance of a pointer (i.e. don't descend
      * into arrays) */
-    offset_in_memory = 0;
-    offset_in_buffer = 0;
-    write_no_repeat_pointer_descriptions(
-        file, type,
-        &offset_in_memory, &offset_in_buffer, typestring_offset);
+    if (!is_array(type))
+    {
+        offset_in_memory = 0;
+        offset_in_buffer = 0;
+        write_no_repeat_pointer_descriptions(
+            file, type,
+            &offset_in_memory, &offset_in_buffer, typestring_offset);
+    }
 
     /* pass 2: search for pointers in fixed arrays */
     offset_in_memory = 0;
@@ -1408,7 +1430,7 @@ static size_t write_string_tfs(FILE *file, const attr_list_t *attrs,
             (type->declarray && current_structure
              ? type_memsize(current_structure, &align)
              : 0),
-            type->size_is);
+            type, type->size_is);
 
         return start_offset;
     }
@@ -1477,7 +1499,7 @@ static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type
         if (is_conformant_array(type))
             *typestring_offset
                 += write_conf_or_var_desc(file, current_structure, baseoff,
-                                          size_is);
+                                          type, size_is);
 
         if (type->type == RPC_FC_SMVARRAY || type->type == RPC_FC_LGVARRAY)
         {
@@ -1502,7 +1524,7 @@ static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type
         if (length_is)
             *typestring_offset
                 += write_conf_or_var_desc(file, current_structure, baseoff,
-                                          length_is);
+                                          type, length_is);
 
         if (has_pointer)
         {
@@ -1524,10 +1546,10 @@ static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type
         *typestring_offset += 2;
         *typestring_offset
             += write_conf_or_var_desc(file, current_structure, baseoff,
-                                      size_is);
+                                      type, size_is);
         *typestring_offset
             += write_conf_or_var_desc(file, current_structure, baseoff,
-                                      length_is);
+                                      type, length_is);
         write_member_type(file, type, NULL, type->ref, NULL, typestring_offset);
         write_end(file, typestring_offset);
     }
@@ -1882,7 +1904,8 @@ static size_t write_ip_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
         expr.is_const = FALSE;
         print_file(file, 2, "0x2f,  /* FC_IP */\n");
         print_file(file, 2, "0x5c,  /* FC_PAD */\n");
-        *typeformat_offset += write_conf_or_var_desc(file, NULL, 0, &expr) + 2;
+        *typeformat_offset
+            += write_conf_or_var_desc(file, NULL, 0, type, &expr) + 2;
     }
     else
     {
@@ -1954,7 +1977,23 @@ static size_t write_typeformatstring_var(FILE *file, int indent, const func_t *f
         return write_string_tfs(file, var->attrs, type, var->name, typeformat_offset);
 
     if (is_array(type))
-        return write_array_tfs(file, var->attrs, type, var->name, typeformat_offset);
+    {
+        size_t off;
+        off = write_array_tfs(file, var->attrs, type, var->name, typeformat_offset);
+        if (pointer_type != RPC_FC_RP)
+        {
+            unsigned int absoff = type->typestring_offset;
+            short reloff = absoff - (*typeformat_offset + 2);
+            off = *typeformat_offset;
+            print_file(file, 0, "/* %d */\n", off);
+            print_file(file, 2, "0x%x, 0x0,\t/* %s */\n", pointer_type,
+                       string_of_type(pointer_type));
+            print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
+                       reloff, reloff, absoff);
+            *typeformat_offset += 4;
+        }
+        return off;
+    }
 
     if (!is_ptr(type))
     {
@@ -2085,6 +2124,8 @@ static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *ty
     else if (is_array(type))
     {
         write_array_tfs(file, attrs, type, name, tfsoff);
+        if (is_conformant_array(type))
+            retmask |= 1;
     }
     else if (is_struct(type->type))
     {
@@ -2621,10 +2662,8 @@ void write_remoting_arguments(FILE *file, int indent, const func_t *func,
             }
             else if (phase != PHASE_FREE)
             {
-                if (pointer_type == RPC_FC_UP)
-                    print_phase_function(file, indent, "Pointer", phase, var, start_offset);
-                else
-                    print_phase_function(file, indent, array_type, phase, var, start_offset);
+                const char *t = pointer_type == RPC_FC_RP ? array_type : "Pointer";
+                print_phase_function(file, indent, t, phase, var, start_offset);
             }
         }
         else if (!is_ptr(var->type) && is_base_type(rtype))
@@ -2958,14 +2997,13 @@ int write_expr_eval_routines(FILE *file, const char *iface)
     {
         const char *name = eval->structure->name;
         const var_list_t *fields = eval->structure->fields;
-        unsigned align = 0;
         result = 1;
 
         print_file(file, 0, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
                    iface, name, callback_offset);
         print_file(file, 0, "{\n");
         print_file (file, 1, "%s *%s = (%s *)(pStubMsg->StackTop - %u);\n",
-                    name, var_name, name, type_memsize (eval->structure, &align));
+                    name, var_name, name, eval->baseoff);
         print_file(file, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */
         print_file(file, 1, "pStubMsg->MaxCount = (unsigned long)");
         write_struct_expr(file, eval->expr, 1, fields, var_name);



More information about the wine-patches mailing list