widl [1/3]: Fix problems with conformant arrays

Dan Hipschman dsh at linux.ucla.edu
Fri Sep 21 18:17:11 CDT 2007


This patch fixes a problem widl has with conformant arrays.  When MIDL
outputs a conformant array, it usually outputs a pointer to CARRAY.
By not doing this, widl generates incorrect code, which results in
some weird testcase failures reported by Alexandre off the list, and a
crash if the array had a "unique" attribute at the top-level,
reported, also off the list, by Mikolaj.  Both these problems should
be fixed now.  The next patch removes some static storage specifiers
from the test cases, which causes the errors to show up if there is a
regression.

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

diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c
index 288de10..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)
     {
@@ -575,7 +585,6 @@ static size_t write_conf_or_var_desc(FILE *file, const type_t *structure,
         const type_t *correlation_variable = NULL;
         unsigned char correlation_variable_type;
         unsigned char param_type = 0;
-        const char *param_type_string = NULL;
         size_t offset = 0;
         const var_t *var;
 
@@ -602,54 +611,42 @@ static size_t write_conf_or_var_desc(FILE *file, const type_t *structure,
         case RPC_FC_CHAR:
         case RPC_FC_SMALL:
             param_type = RPC_FC_SMALL;
-            param_type_string = "FC_SMALL";
             break;
         case RPC_FC_BYTE:
         case RPC_FC_USMALL:
             param_type = RPC_FC_USMALL;
-            param_type_string = "FC_USMALL";
             break;
         case RPC_FC_WCHAR:
         case RPC_FC_SHORT:
         case RPC_FC_ENUM16:
             param_type = RPC_FC_SHORT;
-            param_type_string = "FC_SHORT";
             break;
         case RPC_FC_USHORT:
             param_type = RPC_FC_USHORT;
-            param_type_string = "FC_USHORT";
             break;
         case RPC_FC_LONG:
         case RPC_FC_ENUM32:
             param_type = RPC_FC_LONG;
-            param_type_string = "FC_LONG";
             break;
         case RPC_FC_ULONG:
             param_type = RPC_FC_ULONG;
-            param_type_string = "FC_ULONG";
             break;
         case RPC_FC_RP:
         case RPC_FC_UP:
         case RPC_FC_OP:
         case RPC_FC_FP:
             if (sizeof(void *) == 4)  /* FIXME */
-            {
                 param_type = RPC_FC_LONG;
-                param_type_string = "FC_LONG";
-            }
             else
-            {
                 param_type = RPC_FC_HYPER;
-                param_type_string = "FC_HYPER";
-            }
             break;
         default:
             error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n",
                 correlation_variable_type);
         }
 
-        print_file(file, 2, "0x%x, /* Corr desc: %s */\n",
-                   RPC_FC_NORMAL_CONFORMANCE | param_type, param_type_string);
+        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);
@@ -675,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);
         }
@@ -682,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);
     }
@@ -923,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;
@@ -946,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
@@ -986,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);
@@ -1006,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);
@@ -1016,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);
@@ -1317,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;
@@ -1421,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;
     }
@@ -1490,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)
         {
@@ -1515,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)
         {
@@ -1537,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);
     }
@@ -1895,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
     {
@@ -1967,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))
     {
@@ -2098,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))
     {
@@ -2634,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))
@@ -2971,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