widl: Fix top-level and callback conformances

Dan Hipschman dsh at linux.ucla.edu
Tue Sep 4 11:33:23 CDT 2007


This patch fixes top-level and callback conformances in widl.  Currently,
top-level conformances are implemented by inlining the computation in the
stub, which is fine, but widl still committed suicide for pretty much no
reason because encoding the conformance computation in the NDR was
unimplemented.  This patch removes that problem so top-level conformance
is always handled in the stub and there is no need to signal error.  Also,
I noticed that while callback conformances were supposed to be handled,
they never really were because of a misplaced "optimization."  This patch
fixes that problem as well.  Tests included pass on both wine and windows.

This patch is needed to generate a proxy file for bits.idl.

---
 dlls/rpcrt4/tests/server.c   |   47 ++++++++++++
 dlls/rpcrt4/tests/server.idl |   13 ++++
 tools/widl/typegen.c         |  159 +++++++++++++++---------------------------
 3 files changed, 117 insertions(+), 102 deletions(-)

diff --git a/dlls/rpcrt4/tests/server.c b/dlls/rpcrt4/tests/server.c
index 95bd60b..32735a9 100644
--- a/dlls/rpcrt4/tests/server.c
+++ b/dlls/rpcrt4/tests/server.c
@@ -226,6 +226,16 @@ s_sum_cps(cps_t *cps)
 }
 
 int
+s_sum_cpsc(cpsc_t *cpsc)
+{
+  int sum = 0;
+  int i;
+  for (i = 0; i < (cpsc->c ? cpsc->a : cpsc->b); ++i)
+    sum += cpsc->ca[i];
+  return sum;
+}
+
+int
 s_square_puint(puint_t p)
 {
   int n = atoi(p);
@@ -298,6 +308,27 @@ s_square_encue(encue_t *eue)
   }
 }
 
+int
+s_sum_toplev_conf_2n(int *x, int n)
+{
+  int sum = 0;
+  int i;
+  for (i = 0; i < 2 * n; ++i)
+    sum += x[i];
+  return sum;
+}
+
+int
+s_sum_toplev_conf_cond(int *x, int a, int b, int c)
+{
+  int sum = 0;
+  int n = c ? a : b;
+  int i;
+  for (i = 0; i < n; ++i)
+    sum += x[i];
+  return sum;
+}
+
 void
 s_stop(void)
 {
@@ -584,6 +615,7 @@ array_tests(void)
   static int c[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
   static vector_t vs[2] = {{1, -2, 3}, {4, -5, -6}};
   cps_t cps;
+  cpsc_t cpsc;
   cs_t *cs;
   int n;
 
@@ -616,6 +648,21 @@ array_tests(void)
   cps.n = 3;
   cps.ca2 = &c[3];
   ok(sum_cps(&cps) == 53, "RPC sum_cps\n");
+
+  cpsc.a = 4;
+  cpsc.b = 5;
+  cpsc.c = 1;
+  cpsc.ca = c;
+  ok(sum_cpsc(&cpsc) == 6, "RPC sum_cpsc\n");
+  cpsc.a = 4;
+  cpsc.b = 5;
+  cpsc.c = 0;
+  cpsc.ca = c;
+  ok(sum_cpsc(&cpsc) == 10, "RPC sum_cpsc\n");
+
+  ok(sum_toplev_conf_2n(c, 3) == 15, "RPC sum_toplev_conf_2n\n");
+  ok(sum_toplev_conf_cond(c, 5, 6, 1) == 10, "RPC sum_toplev_conf_cond\n");
+  ok(sum_toplev_conf_cond(c, 5, 6, 0) == 15, "RPC sum_toplev_conf_cond\n");
 }
 
 static void
diff --git a/dlls/rpcrt4/tests/server.idl b/dlls/rpcrt4/tests/server.idl
index c33f179..59c9477 100644
--- a/dlls/rpcrt4/tests/server.idl
+++ b/dlls/rpcrt4/tests/server.idl
@@ -127,8 +127,17 @@ interface IServer
     int n;
   } cps_t;
 
+  typedef struct
+  {
+    [size_is(c ? a : b)] int *ca;
+    int a;
+    int b;
+    int c;
+  } cpsc_t;
+
   int sum_cs(cs_t *cs);
   int sum_cps(cps_t *cps);
+  int sum_cpsc(cpsc_t *cpsc);
 
   typedef [wire_marshal(int)] void *puint_t;
   int square_puint(puint_t p);
@@ -176,5 +185,9 @@ interface IServer
   int sum_pcarr([size_is(n)] int *a[], int n);
   int enum_ord(e_t e);
   double square_encue(encue_t *eue);
+
+  int sum_toplev_conf_2n([size_is(n * 2)] int *x, int n);
+  int sum_toplev_conf_cond([size_is(c ? a : b)] int *x, int a, int b, int c);
+
   void stop(void);
 }
diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c
index 73a3622..2907706 100644
--- a/tools/widl/typegen.c
+++ b/tools/widl/typegen.c
@@ -46,16 +46,11 @@
 static const func_t *current_func;
 static const type_t *current_structure;
 
-/* name of the structure variable for structure callbacks */
-#define STRUCT_EXPR_EVAL_VAR "pS"
-
 static struct list expr_eval_routines = LIST_INIT(expr_eval_routines);
-
 struct expr_eval_routine
 {
     struct list entry;
     const type_t *structure;
-    size_t structure_size;
     const expr_t *expr;
 };
 
@@ -496,9 +491,16 @@ static size_t write_conf_or_var_desc(FILE *file, const func_t *func, const type_
     unsigned char operator_type = 0;
     const char *operator_string = "no operators";
     const expr_t *subexpr;
-    unsigned char correlation_type;
 
-    if (!file) return 4; /* optimisation for sizing pass */
+    if (!structure)
+    {
+        /* Top-level conformance calculations are done inline.  */
+        print_file (file, 2, "0x%x,\t/* Corr desc: parameter */\n",
+                    RPC_FC_TOP_LEVEL_CONFORMANCE);
+        print_file (file, 2, "0x0,\n");
+        print_file (file, 2, "NdrFcShort(0x0),\n");
+        return 4;
+    }
 
     if (expr->is_const)
     {
@@ -565,53 +567,25 @@ static size_t write_conf_or_var_desc(FILE *file, const func_t *func, const type_
         unsigned char correlation_variable_type;
         unsigned char param_type = 0;
         const char *param_type_string = NULL;
-        size_t offset;
+        size_t offset = 0;
+        const var_t *var;
 
-        if (structure)
+        if (structure->fields) LIST_FOR_EACH_ENTRY( var, structure->fields, const var_t, entry )
         {
-            const var_t *var;
-
-            offset = 0;
-            if (structure->fields) LIST_FOR_EACH_ENTRY( var, structure->fields, const var_t, entry )
+            unsigned int align = 0;
+            /* FIXME: take alignment into account */
+            if (var->name && !strcmp(var->name, subexpr->u.sval))
             {
-                unsigned int align = 0;
-                /* FIXME: take alignment into account */
-                if (var->name && !strcmp(var->name, subexpr->u.sval))
-                {
-                    correlation_variable = var->type;
-                    break;
-                }
-                offset += type_memsize(var->type, &align);
-            }
-            if (!correlation_variable)
-                error("write_conf_or_var_desc: couldn't find variable %s in structure\n",
-                      subexpr->u.sval);
-
-            offset -= baseoff;
-            correlation_type = RPC_FC_NORMAL_CONFORMANCE;
-        }
-        else
-        {
-            const var_t *var;
-
-            offset = sizeof(void *);
-            if (func->args) LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
-            {
-                if (!strcmp(var->name, subexpr->u.sval))
-                {
-                    correlation_variable = var->type;
-                    break;
-                }
-                /* FIXME: not all stack variables are sizeof(void *) */
-                offset += sizeof(void *);
+                correlation_variable = var->type;
+                break;
             }
-            if (!correlation_variable)
-                error("write_conf_or_var_desc: couldn't find variable %s in function\n",
-                    subexpr->u.sval);
-
-            correlation_type = RPC_FC_TOP_LEVEL_CONFORMANCE;
+            offset += type_memsize(var->type, &align);
         }
+        if (!correlation_variable)
+            error("write_conf_or_var_desc: couldn't find variable %s in structure\n",
+                  subexpr->u.sval);
 
+        offset -= baseoff;
         correlation_variable_type = correlation_variable->type;
 
         switch (correlation_variable_type)
@@ -665,60 +639,41 @@ static size_t write_conf_or_var_desc(FILE *file, const func_t *func, const type_
                 correlation_variable_type);
         }
 
-        print_file(file, 2, "0x%x, /* Corr desc: %s%s */\n",
-                correlation_type | param_type,
-                correlation_type == RPC_FC_TOP_LEVEL_CONFORMANCE ? "parameter, " : "",
-                param_type_string);
+        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, /* %s */\n", operator_type, operator_string);
-        print_file(file, 2, "NdrFcShort(0x%x), /* %soffset = %d */\n",
-                   offset,
-                   correlation_type == RPC_FC_TOP_LEVEL_CONFORMANCE ? "x86 stack size / " : "",
-                   offset);
+        print_file(file, 2, "NdrFcShort(0x%x), /* offset = %d */\n",
+                   offset, offset);
     }
     else
     {
         unsigned int callback_offset = 0;
+        struct expr_eval_routine *eval;
+        int found = 0;
 
-        if (structure)
+        LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
         {
-            struct expr_eval_routine *eval;
-            int found = 0;
-
-            LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
-            {
-                if (!strcmp(eval->structure->name, structure->name) &&
-                    !compare_expr(eval->expr, expr))
-                {
-                    found = 1;
-                    break;
-                }
-                callback_offset++;
-            }
-
-            if (!found)
+            if (!strcmp (eval->structure->name, structure->name)
+                && !compare_expr (eval->expr, expr))
             {
-                unsigned int align = 0;
-                eval = xmalloc(sizeof(*eval));
-                eval->structure = structure;
-                eval->structure_size = fields_memsize(structure->fields, &align);
-                eval->expr = expr;
-                list_add_tail(&expr_eval_routines, &eval->entry);
+                found = 1;
+                break;
             }
-
-            correlation_type = RPC_FC_NORMAL_CONFORMANCE;
+            callback_offset++;
         }
-        else
+
+        if (!found)
         {
-            error("write_conf_or_var_desc: top-level callback conformance unimplemented\n");
-            correlation_type = RPC_FC_TOP_LEVEL_CONFORMANCE;
+            eval = xmalloc (sizeof(*eval));
+            eval->structure = structure;
+            eval->expr = expr;
+            list_add_tail (&expr_eval_routines, &eval->entry);
         }
 
         if (callback_offset > USHRT_MAX)
             error("Maximum number of callback routines reached\n");
 
-        print_file(file, 2, "0x%x, /* Corr desc: %s */\n",
-                   correlation_type,
-                   correlation_type == RPC_FC_TOP_LEVEL_CONFORMANCE ? "parameter" : "");
+        print_file(file, 2, "0x%x, /* Corr desc: */\n", RPC_FC_NORMAL_CONFORMANCE);
         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);
     }
@@ -2881,27 +2836,28 @@ void assign_stub_out_args( FILE *file, int indent, const func_t *func )
 
 int write_expr_eval_routines(FILE *file, const char *iface)
 {
+    static const char *var_name = "pS";
     int result = 0;
     struct expr_eval_routine *eval;
     unsigned short callback_offset = 0;
 
     LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
     {
-        int indent = 0;
+        const char *name = eval->structure->name;
+        const var_list_t *fields = eval->structure->fields;
+        unsigned align = 0;
         result = 1;
-        print_file(file, indent, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
-                  iface, eval->structure->name, callback_offset);
-        print_file(file, indent, "{\n");
-        indent++;
-        print_file(file, indent, "struct %s *" STRUCT_EXPR_EVAL_VAR " = (struct %s *)(pStubMsg->StackTop - %u);\n",
-                   eval->structure->name, eval->structure->name, eval->structure_size);
-        fprintf(file, "\n");
-        print_file(file, indent, "pStubMsg->Offset = 0;\n"); /* FIXME */
-        print_file(file, indent, "pStubMsg->MaxCount = (unsigned long)");
-        write_struct_expr(file, eval->expr, 1, eval->structure->fields, STRUCT_EXPR_EVAL_VAR);
+
+        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));
+        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);
         fprintf(file, ";\n");
-        indent--;
-        print_file(file, indent, "}\n\n");
+        print_file(file, 0, "}\n\n");
         callback_offset++;
     }
     return result;
@@ -2918,9 +2874,8 @@ void write_expr_eval_routine_list(FILE *file, const char *iface)
 
     LIST_FOR_EACH_ENTRY_SAFE(eval, cursor, &expr_eval_routines, struct expr_eval_routine, entry)
     {
-        print_file(file, 1, "%s_%sExprEval_%04u,\n",
-                   iface, eval->structure->name, callback_offset);
-
+        const char *name = eval->structure->name;
+        print_file(file, 1, "%s_%sExprEval_%04u,\n", iface, name, callback_offset);
         callback_offset++;
         list_remove(&eval->entry);
         free(eval);



More information about the wine-patches mailing list