widl: Remove duplicated code in the form of the write_struct_expr function by enhancing write_expr to allow toplevel identifiers to be prefixed by a string, if specified.
diff --git a/tools/widl/expr.c b/tools/widl/expr.c
index ca9986a..1265e43 100644
--- a/tools/widl/expr.c
+++ b/tools/widl/expr.c
@@ -354,6 +354,44 @@
                        expr_loc->attr ? expr_loc->attr : "");
 }
 
+static type_t *find_identifier(const char *identifier, const type_t *cont_type, int *found_in_cont_type)
+{
+    type_t *type = NULL;
+    const var_t *field;
+    const var_list_t *fields = NULL;
+
+    *found_in_cont_type = 0;
+
+    if (cont_type && (cont_type->type == RPC_FC_FUNCTION || is_struct(cont_type->type)))
+        fields = cont_type->fields_or_args;
+    else if (cont_type && is_union(cont_type->type))
+    {
+        if (cont_type->type == RPC_FC_ENCAPSULATED_UNION)
+        {
+            const var_t *uv = LIST_ENTRY(list_tail(cont_type->fields_or_args), const var_t, entry);
+            fields = uv->type->fields_or_args;
+        }
+        else
+            fields = cont_type->fields_or_args;
+    }
+
+    if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
+        if (field->name && !strcmp(identifier, field->name))
+        {
+            type = field->type;
+            *found_in_cont_type = 1;
+            break;
+        }
+
+    if (!type)
+    {
+        var_t *const_var = find_const(identifier, 0);
+        if (const_var) type = const_var->type;
+    }
+
+    return type;
+}
+
 static struct expression_type resolve_expression(const struct expr_loc *expr_loc,
                                                  const type_t *cont_type,
                                                  const expr_t *e)
@@ -380,34 +418,10 @@
         break;
     case EXPR_IDENTIFIER:
     {
-        const var_t *field;
-        const var_list_t *fields = NULL;
-
-        if (cont_type && (cont_type->type == RPC_FC_FUNCTION || is_struct(cont_type->type)))
-            fields = cont_type->fields_or_args;
-        else if (cont_type && is_union(cont_type->type))
-        {
-            if (cont_type->type == RPC_FC_ENCAPSULATED_UNION)
-            {
-                const var_t *uv = LIST_ENTRY(list_tail(cont_type->fields_or_args), const var_t, entry);
-                fields = uv->type->fields_or_args;
-            }
-            else
-                fields = cont_type->fields_or_args;
-        }
-
-        if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
-            if (field->name && !strcmp(e->u.sval, field->name))
-            {
-                result.type = field->type;
-                break;
-            }
-
-        if (!result.type)
-        {
-            var_t *const_var = find_const(e->u.sval, 0);
-            if (const_var) result.type = const_var->type;
-        }
+        int found_in_cont_type;
+        result.is_variable = TRUE;
+        result.is_temporary = FALSE;
+        result.type = find_identifier(e->u.sval, cont_type, &found_in_cont_type);
         if (!result.type)
         {
             error_loc_info(&expr_loc->v->loc_info, "identifier %s cannot be resolved in expression%s%s\n",
@@ -550,7 +564,9 @@
     return expr_type.type;
 }
 
-void write_expr(FILE *h, const expr_t *e, int brackets)
+void write_expr(FILE *h, const expr_t *e, int brackets,
+                int toplevel, const char *toplevel_prefix,
+                const type_t *cont_type)
 {
     switch (e->type)
     {
@@ -572,37 +588,43 @@
             fprintf(h, "TRUE");
         break;
     case EXPR_IDENTIFIER:
+        if (toplevel && toplevel_prefix && cont_type)
+        {
+            int found_in_cont_type;
+            find_identifier(e->u.sval, cont_type, &found_in_cont_type);
+            if (found_in_cont_type) fprintf(h, "%s", toplevel_prefix);
+        }
         fprintf(h, "%s", e->u.sval);
         break;
     case EXPR_LOGNOT:
         fprintf(h, "!");
-        write_expr(h, e->ref, 1);
+        write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type);
         break;
     case EXPR_NOT:
         fprintf(h, "~");
-        write_expr(h, e->ref, 1);
+        write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type);
         break;
     case EXPR_POS:
         fprintf(h, "+");
-        write_expr(h, e->ref, 1);
+        write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type);
         break;
     case EXPR_NEG:
         fprintf(h, "-");
-        write_expr(h, e->ref, 1);
+        write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type);
         break;
     case EXPR_ADDRESSOF:
         fprintf(h, "&");
-        write_expr(h, e->ref, 1);
+        write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type);
         break;
     case EXPR_PPTR:
         fprintf(h, "*");
-        write_expr(h, e->ref, 1);
+        write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type);
         break;
     case EXPR_CAST:
         fprintf(h, "(");
         write_type_decl(h, e->u.tref, NULL);
         fprintf(h, ")");
-        write_expr(h, e->ref, 1);
+        write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type);
         break;
     case EXPR_SIZEOF:
         fprintf(h, "sizeof(");
@@ -628,7 +650,7 @@
     case EXPR_GTREQL:
     case EXPR_LESSEQL:
         if (brackets) fprintf(h, "(");
-        write_expr(h, e->ref, 1);
+        write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type);
         switch (e->type)
         {
         case EXPR_SHL:          fprintf(h, " << "); break;
@@ -651,38 +673,38 @@
         case EXPR_LESSEQL:      fprintf(h, " <= "); break;
         default: break;
         }
-        write_expr(h, e->u.ext, 1);
+        write_expr(h, e->u.ext, 1, toplevel, toplevel_prefix, cont_type);
         if (brackets) fprintf(h, ")");
         break;
     case EXPR_MEMBER:
         if (brackets) fprintf(h, "(");
         if (e->ref->type == EXPR_PPTR)
         {
-            write_expr(h, e->ref->ref, 1);
+            write_expr(h, e->ref->ref, 1, toplevel, toplevel_prefix, cont_type);
             fprintf(h, "->");
         }
         else
         {
-            write_expr(h, e->ref, 1);
+            write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type);
             fprintf(h, ".");
         }
-        write_expr(h, e->u.ext, 1);
+        write_expr(h, e->u.ext, 1, 0, toplevel_prefix, cont_type);
         if (brackets) fprintf(h, ")");
         break;
     case EXPR_COND:
         if (brackets) fprintf(h, "(");
-        write_expr(h, e->ref, 1);
+        write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type);
         fprintf(h, " ? ");
-        write_expr(h, e->u.ext, 1);
+        write_expr(h, e->u.ext, 1, toplevel, toplevel_prefix, cont_type);
         fprintf(h, " : ");
-        write_expr(h, e->ext2, 1);
+        write_expr(h, e->ext2, 1, toplevel, toplevel_prefix, cont_type);
         if (brackets) fprintf(h, ")");
         break;
     case EXPR_ARRAY:
         if (brackets) fprintf(h, "(");
-        write_expr(h, e->ref, 1);
+        write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type);
         fprintf(h, "[");
-        write_expr(h, e->u.ext, 1);
+        write_expr(h, e->u.ext, 1, 1, toplevel_prefix, cont_type);
         fprintf(h, "]");
         if (brackets) fprintf(h, ")");
         break;
diff --git a/tools/widl/expr.h b/tools/widl/expr.h
index e32ec29..1b773e0 100644
--- a/tools/widl/expr.h
+++ b/tools/widl/expr.h
@@ -37,4 +37,4 @@
 extern const type_t *expr_resolve_type(const struct expr_loc *expr_loc, const type_t *cont_type, const expr_t *expr);
 extern int compare_expr(const expr_t *a, const expr_t *b);
 
-extern void write_expr(FILE *h, const expr_t *e, int brackets);
+extern void write_expr(FILE *h, const expr_t *e, int brackets, int toplevel, const char *toplevel_prefix, const type_t *cont_type);
diff --git a/tools/widl/header.c b/tools/widl/header.c
index a22a3ec..3915244 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -195,7 +195,7 @@
       write_name(h, v);
       if (v->eval) {
         fprintf(h, " = ");
-        write_expr(h, v->eval, 0);
+        write_expr(h, v->eval, 0, 1, NULL, NULL);
       }
     }
     if (list_next( enums, &v->entry )) fprintf(h, ",\n");
@@ -476,7 +476,7 @@
 void write_constdef(const var_t *v)
 {
   fprintf(header, "#define %s (", v->name);
-  write_expr(header, v->eval, 0);
+  write_expr(header, v->eval, 0, 1, NULL, NULL);
   fprintf(header, ")\n\n");
 }
 
diff --git a/tools/widl/proxy.c b/tools/widl/proxy.c
index 01ad4da..2fa0a4d 100644
--- a/tools/widl/proxy.c
+++ b/tools/widl/proxy.c
@@ -194,7 +194,7 @@
   if (size)
   {
     print_proxy( "_StubMsg.MaxCount = " );
-    write_expr(proxy, size, 0);
+    write_expr(proxy, size, 0, 1, NULL, NULL);
     fprintf(proxy, ";\n\n");
     print_proxy( "NdrClearOutParameters( &_StubMsg, ");
     fprintf(proxy, "&__MIDL_TypeFormatString.Format[%u], ", type_offset );
@@ -222,7 +222,7 @@
     if( iid )
     {
       print_proxy( "_StubMsg.MaxCount = (unsigned long) " );
-      write_expr(proxy, iid, 1);
+      write_expr(proxy, iid, 1, 1, NULL, NULL);
       print_proxy( ";\n\n" );
     }
     print_proxy( "NdrClearOutParameters( &_StubMsg, ");
diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c
index 7a5f6f9..a2f8258 100644
--- a/tools/widl/typegen.c
+++ b/tools/widl/typegen.c
@@ -2759,7 +2759,7 @@
             if (type->size_is && is_size_needed_for_phase(phase))
             {
                 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
-                write_expr(file, type->size_is, 1);
+                write_expr(file, type->size_is, 1, 1, NULL, NULL);
                 fprintf(file, ";\n");
             }
 
@@ -2789,7 +2789,7 @@
             {
                 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
                 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
-                write_expr(file, type->length_is, 1);
+                write_expr(file, type->length_is, 1, 1, NULL, NULL);
                 fprintf(file, ";\n\n");
             }
             array_type = "VaryingArray";
@@ -2799,7 +2799,7 @@
             if (is_size_needed_for_phase(phase))
             {
                 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
-                write_expr(file, type->size_is, 1);
+                write_expr(file, type->size_is, 1, 1, NULL, NULL);
                 fprintf(file, ";\n\n");
             }
             array_type = "ConformantArray";
@@ -2811,14 +2811,14 @@
                 if (type->size_is)
                 {
                     print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
-                    write_expr(file, type->size_is, 1);
+                    write_expr(file, type->size_is, 1, 1, NULL, NULL);
                     fprintf(file, ";\n");
                 }
                 if (type->length_is)
                 {
                     print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
                     print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
-                    write_expr(file, type->length_is, 1);
+                    write_expr(file, type->length_is, 1, 1, NULL, NULL);
                     fprintf(file, ";\n\n");
                 }
             }
@@ -2882,7 +2882,7 @@
                 if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
                 {
                     print_file( file, indent, "_StubMsg.MaxCount = (unsigned long) " );
-                    write_expr( file, iid, 1 );
+                    write_expr( file, iid, 1, 1, NULL, NULL );
                     fprintf( file, ";\n\n" );
                 }
                 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
@@ -2912,13 +2912,13 @@
             if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
             {
                 print_file( file, indent, "_StubMsg.MaxCount = (unsigned long) " );
-                write_expr( file, iid, 1 );
+                write_expr( file, iid, 1, 1, NULL, NULL );
                 fprintf( file, ";\n\n" );
             }
             else if (sx)
             {
                 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long) ");
-                write_expr(file, sx, 1);
+                write_expr(file, sx, 1, 1, NULL, NULL);
                 fprintf(file, ";\n\n");
             }
             if (var->type->ref->type == RPC_FC_IP)
@@ -3009,156 +3009,6 @@
     return process_tfs(NULL, ifaces, pred);
 }
 
-static void write_struct_expr(FILE *h, const expr_t *e, int brackets,
-                              const var_list_t *fields, const char *structvar)
-{
-    switch (e->type) {
-        case EXPR_VOID:
-            break;
-        case EXPR_NUM:
-            fprintf(h, "%lu", e->u.lval);
-            break;
-        case EXPR_HEXNUM:
-            fprintf(h, "0x%lx", e->u.lval);
-            break;
-        case EXPR_DOUBLE:
-            fprintf(h, "%#.15g", e->u.dval);
-            break;
-        case EXPR_TRUEFALSE:
-            if (e->u.lval == 0)
-                fprintf(h, "FALSE");
-            else
-                fprintf(h, "TRUE");
-            break;
-        case EXPR_IDENTIFIER:
-        {
-            const var_t *field;
-            LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
-                if (!strcmp(e->u.sval, field->name))
-                {
-                    fprintf(h, "%s->%s", structvar, e->u.sval);
-                    break;
-                }
-
-            if (&field->entry == fields) error("no field found for identifier %s\n", e->u.sval);
-            break;
-        }
-        case EXPR_LOGNOT:
-            fprintf(h, "!");
-            write_struct_expr(h, e->ref, 1, fields, structvar);
-            break;
-        case EXPR_NOT:
-            fprintf(h, "~");
-            write_struct_expr(h, e->ref, 1, fields, structvar);
-            break;
-        case EXPR_POS:
-            fprintf(h, "+");
-            write_struct_expr(h, e->ref, 1, fields, structvar);
-            break;
-        case EXPR_NEG:
-            fprintf(h, "-");
-            write_struct_expr(h, e->ref, 1, fields, structvar);
-            break;
-        case EXPR_ADDRESSOF:
-            fprintf(h, "&");
-            write_struct_expr(h, e->ref, 1, fields, structvar);
-            break;
-        case EXPR_PPTR:
-            fprintf(h, "*");
-            write_struct_expr(h, e->ref, 1, fields, structvar);
-            break;
-        case EXPR_CAST:
-            fprintf(h, "(");
-            write_type_decl(h, e->u.tref, NULL);
-            fprintf(h, ")");
-            write_struct_expr(h, e->ref, 1, fields, structvar);
-            break;
-        case EXPR_SIZEOF:
-            fprintf(h, "sizeof(");
-            write_type_decl(h, e->u.tref, NULL);
-            fprintf(h, ")");
-            break;
-        case EXPR_SHL:
-        case EXPR_SHR:
-        case EXPR_MOD:
-        case EXPR_MUL:
-        case EXPR_DIV:
-        case EXPR_ADD:
-        case EXPR_SUB:
-        case EXPR_AND:
-        case EXPR_OR:
-        case EXPR_LOGOR:
-        case EXPR_LOGAND:
-        case EXPR_XOR:
-        case EXPR_EQUALITY:
-        case EXPR_INEQUALITY:
-        case EXPR_GTR:
-        case EXPR_LESS:
-        case EXPR_GTREQL:
-        case EXPR_LESSEQL:
-            if (brackets) fprintf(h, "(");
-            write_struct_expr(h, e->ref, 1, fields, structvar);
-            switch (e->type) {
-                case EXPR_SHL:          fprintf(h, " << "); break;
-                case EXPR_SHR:          fprintf(h, " >> "); break;
-                case EXPR_MOD:          fprintf(h, " %% "); break;
-                case EXPR_MUL:          fprintf(h, " * "); break;
-                case EXPR_DIV:          fprintf(h, " / "); break;
-                case EXPR_ADD:          fprintf(h, " + "); break;
-                case EXPR_SUB:          fprintf(h, " - "); break;
-                case EXPR_AND:          fprintf(h, " & "); break;
-                case EXPR_OR:           fprintf(h, " | "); break;
-                case EXPR_MEMBER:       fprintf(h, "."); break;
-                case EXPR_LOGOR:        fprintf(h, " || "); break;
-                case EXPR_LOGAND:       fprintf(h, " && "); break;
-                case EXPR_XOR:          fprintf(h, " ^ "); break;
-                case EXPR_EQUALITY:     fprintf(h, " == "); break;
-                case EXPR_INEQUALITY:   fprintf(h, " != "); break;
-                case EXPR_GTR:          fprintf(h, " > "); break;
-                case EXPR_LESS:         fprintf(h, " < "); break;
-                case EXPR_GTREQL:       fprintf(h, " >= "); break;
-                case EXPR_LESSEQL:      fprintf(h, " <= "); break;
-                default: break;
-            }
-            write_struct_expr(h, e->u.ext, 1, fields, structvar);
-            if (brackets) fprintf(h, ")");
-            break;
-        case EXPR_MEMBER:
-            if (brackets) fprintf(h, "(");
-            if (e->ref->type == EXPR_PPTR)
-            {
-                write_expr(h, e->ref->ref, 1);
-                fprintf(h, "->");
-            }
-            else
-            {
-                write_expr(h, e->ref, 1);
-                fprintf(h, ".");
-            }
-            write_expr(h, e->u.ext, 1);
-            if (brackets) fprintf(h, ")");
-            break;
-        case EXPR_COND:
-            if (brackets) fprintf(h, "(");
-            write_struct_expr(h, e->ref, 1, fields, structvar);
-            fprintf(h, " ? ");
-            write_struct_expr(h, e->u.ext, 1, fields, structvar);
-            fprintf(h, " : ");
-            write_struct_expr(h, e->ext2, 1, fields, structvar);
-            if (brackets) fprintf(h, ")");
-            break;
-        case EXPR_ARRAY:
-            if (brackets) fprintf(h, "(");
-            write_struct_expr(h, e->ref, 1, fields, structvar);
-            fprintf(h, "[");
-            write_struct_expr(h, e->u.ext, 1, fields, structvar);
-            fprintf(h, "]");
-            if (brackets) fprintf(h, ")");
-            break;
-    }
-}
-
-
 void declare_stub_args( FILE *file, int indent, const func_t *func )
 {
     int in_attr, out_attr;
@@ -3254,7 +3104,7 @@
                 fprintf(file, " = NdrAllocate(&_StubMsg, ");
                 for ( ; type->size_is ; type = type->ref)
                 {
-                    write_expr(file, type->size_is, TRUE);
+                    write_expr(file, type->size_is, TRUE, TRUE, NULL, NULL);
                     fprintf(file, " * ");
                 }
                 size = type_memsize(type, &align);
@@ -3279,6 +3129,7 @@
 int write_expr_eval_routines(FILE *file, const char *iface)
 {
     static const char *var_name = "pS";
+    static const char *var_name_expr = "pS->";
     int result = 0;
     struct expr_eval_routine *eval;
     unsigned short callback_offset = 0;
@@ -3286,7 +3137,6 @@
     LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
     {
         const char *name = eval->structure->name;
-        const var_list_t *fields = eval->structure->fields_or_args;
         result = 1;
 
         print_file(file, 0, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
@@ -3296,7 +3146,7 @@
                     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);
+        write_expr(file, eval->expr, 1, 1, var_name_expr, eval->structure);
         fprintf(file, ";\n");
         print_file(file, 0, "}\n\n");
         callback_offset++;