CVS: winex/tools/widl .cvsignore, 1.5, 1.6 client.c, 1.1, 1.2 hash.c, 1.1, 1.2 header.c, 1.5, 1.6 header.h, 1.3, 1.4 parser.l, 1.9, 1.10 parser.y, 1.5, 1.6 proxy.c, 1.3, 1.4 server.c, 1.1, 1.2 typegen.c, 1.1, 1.2 typegen.h, 1.1, 1.2 typelib.c, 1.2, 1.3 typelib.h, 1.2, 1.3 typelib_struct.h, 1.1, 1.2 utils.c, 1.4, 1.5 widl.c, 1.6, 1.7 widl.h, 1.3, 1.4 widltypes.h, 1.5, 1.6 write_msft.c, 1.1, 1.2

[email protected] 14 Dec 2007 20:18:53 -0000
Newsgroups gmane.comp.emulators.winex.cvs
Message-ID <[email protected]>
Subject: winex/tools/widl .cvsignore,1.5,1.6 client.c,1.1,1.2 hash.c,1.1,1.2 header.c,1.5,1.6 header.h,1.3,1.4 parser.l,1.9,1.10 parser.y,1.5,1.6 proxy.c,1.3,1.4 server.c,1.1,1.2 typegen.c,1.1,1.2 typegen.h,1.1,1.2 typelib.c,1.2,1.3 typelib.h,1.2,1.3 typelib_struct.h,1.1,1.2 utils.c,1.4,1.5 widl.c,1.6,1.7 widl.h,1.3,1.4 widltypes.h,1.5,1.6 write_msft.c,1.1,1.2Update of /var/lib/cvsd/cvsroot/winex/tools/widl
In directory agravaine:/tmp/cvs-serv15346/tools/widl

Modified Files:
	.cvsignore client.c hash.c header.c header.h parser.l parser.y 
	proxy.c server.c typegen.c typegen.h typelib.c typelib.h 
	typelib_struct.h utils.c widl.c widl.h widltypes.h 
	write_msft.c 
Log Message:
Merge of WineHQ widl code of 2007-07-30.


Index: .cvsignore
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/tools/widl/.cvsignore,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- .cvsignore	14 Dec 2007 20:18:02 -0000	1.5
+++ .cvsignore	14 Dec 2007 20:18:50 -0000	1.6
@@ -1,14 +1,7 @@
-*.avi
-*.bmp
-*.cur
-*.ico
-*.mc.rc
-*.res
-*.tab.[ch]
-*.tlb
-*.yy.c
-*_[cips].c
 *.d
 Makefile
+parser.tab.c
+parser.tab.h
+parser.yy.c
 widl
 widl.man

Index: client.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/tools/widl/client.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- client.c	6 Nov 2006 14:30:41 -0000	1.1
+++ client.c	14 Dec 2007 20:18:50 -0000	1.2
@@ -44,52 +44,23 @@
 static FILE* client;
 static int indent = 0;
 
-static int print_client( const char *format, ... )
+static void print_client( const char *format, ... )
 {
     va_list va;
-    int i, r;
-
     va_start(va, format);
-    if (format[0] != '\n')
-        for (i = 0; i < indent; i++)
-            fprintf(client, "    ");
-    r = vfprintf(client, format, va);
+    print(client, indent, format, va);
     va_end(va);
-    return r;
 }
 
 
-static void print_message_buffer_size(const func_t *func)
-{
-    unsigned int total_size = 0;
-
-    if (func->args)
-    {
-        const var_t *var = func->args;
-        while (NEXT_LINK(var)) var = NEXT_LINK(var);
-        while (var)
-        {
-            unsigned int alignment;
-
-            total_size += get_required_buffer_size(var, &alignment, PASS_IN);
-            total_size += alignment;
-
-            var = PREV_LINK(var);
-        }
-    }
-    fprintf(client, " %u", total_size);
-}
-
 static void check_pointers(const func_t *func)
 {
-    var_t *var;
+    const var_t *var;
 
     if (!func->args)
         return;
 
-    var = func->args;
-    while (NEXT_LINK(var)) var = NEXT_LINK(var);
-    while (var)
+    LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
     {
         if (is_var_ptr(var) && cant_be_null(var))
         {
@@ -100,25 +71,24 @@
             indent--;
             print_client("}\n\n");
         }
-
-        var = PREV_LINK(var);
     }
 }
 
-static void write_function_stubs(type_t *iface, unsigned int *proc_offset, unsigned int *type_offset)
+static void write_function_stubs(type_t *iface, unsigned int *proc_offset)
 {
-    const func_t *func = iface->funcs;
+    const func_t *func;
     const char *implicit_handle = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE);
     int explicit_handle = is_attr(iface->attrs, ATTR_EXPLICIT_HANDLE);
-    var_t *var;
+    const var_t *var;
     int method_count = 0;
 
-    while (NEXT_LINK(func)) func = NEXT_LINK(func);
-    while (func)
+    if (!implicit_handle)
+        print_client("static RPC_BINDING_HANDLE %s__MIDL_AutoBindHandle;\n\n", iface->name);
+
+    if (iface->funcs) LIST_FOR_EACH_ENTRY( func, iface->funcs, const func_t, entry )
     {
         const var_t *def = func->def;
         const var_t* explicit_handle_var;
-        unsigned int type_offset_func;
 
         /* check for a defined binding handle */
         explicit_handle_var = get_explicit_handle_var(func);
@@ -139,9 +109,10 @@
             }
         }
 
-        write_type(client, def->type, def, def->tname);
-        fprintf(client, " ");
-        write_name(client, def);
+        write_type_left(client, def->type);
+        if (needs_space_after(def->type))
+          fprintf(client, " ");
+        write_prefix_name(client, prefix_client, def);
         fprintf(client, "(\n");
         indent++;
         if (func->args)
@@ -156,10 +127,10 @@
         indent++;
 
         /* declare return value '_RetVal' */
-        if (!is_void(def->type, NULL))
+        if (!is_void(def->type))
         {
             print_client("");
-            write_type(client, def->type, def, def->tname);
+            write_type_left(client, def->type);
             fprintf(client, " _RetVal;\n");
         }
 
@@ -197,13 +168,7 @@
             fprintf(client, "\n");
         }
 
-        /* emit the message buffer size */
-        print_client("_StubMsg.BufferLength =");
-        print_message_buffer_size(func);
-        fprintf(client, ";\n");
-
-        type_offset_func = *type_offset;
-        write_remoting_arguments(client, indent, func, &type_offset_func, PASS_IN, PHASE_BUFFERSIZE);
+        write_remoting_arguments(client, indent, func, PASS_IN, PHASE_BUFFERSIZE);
 
         print_client("NdrGetBuffer(\n");
         indent++;
@@ -216,12 +181,8 @@
         indent--;
         fprintf(client, "\n");
 
-
-        /* make a copy so we don't increment the type offset twice */
-        type_offset_func = *type_offset;
-
         /* marshal arguments */
-        write_remoting_arguments(client, indent, func, &type_offset_func, PASS_IN, PHASE_MARSHAL);
+        write_remoting_arguments(client, indent, func, PASS_IN, PHASE_MARSHAL);
 
         /* send/receive message */
         /* print_client("NdrNsSendReceive(\n"); */
@@ -251,24 +212,19 @@
 
         /* unmarshall arguments */
         fprintf(client, "\n");
-        write_remoting_arguments(client, indent, func, type_offset, PASS_OUT, PHASE_UNMARSHAL);
+        write_remoting_arguments(client, indent, func, PASS_OUT, PHASE_UNMARSHAL);
 
         /* unmarshal return value */
-        if (!is_void(def->type, NULL))
+        if (!is_void(def->type))
             print_phase_basetype(client, indent, PHASE_UNMARSHAL, PASS_RETURN, def, "_RetVal");
 
         /* update proc_offset */
         if (func->args)
         {
-            var = func->args;
-            while (NEXT_LINK(var)) var = NEXT_LINK(var);
-            while (var)
-            {
+            LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
                 *proc_offset += get_size_procformatstring_var(var);
-                var = PREV_LINK(var);
-            }
         }
-        if (!is_void(def->type, NULL))
+        if (!is_void(def->type))
             *proc_offset += get_size_procformatstring_var(def);
         else
             *proc_offset += 2; /* FC_END and FC_PAD */
@@ -290,7 +246,7 @@
 
 
         /* emit return code */
-        if (!is_void(def->type, NULL))
+        if (!is_void(def->type))
         {
             fprintf(client, "\n");
             print_client("return _RetVal;\n");
@@ -301,18 +257,10 @@
         fprintf(client, "\n");
 
         method_count++;
-        func = PREV_LINK(func);
     }
 }
 
 
-static void write_bindinghandledecl(type_t *iface)
-{
-    print_client("static RPC_BINDING_HANDLE %s__MIDL_AutoBindHandle;\n", iface->name);
-    fprintf(client, "\n");
-}
-
-
 static void write_stubdescdecl(type_t *iface)
 {
     print_client("static const MIDL_STUB_DESC %s_StubDesc;\n", iface->name);
@@ -351,7 +299,7 @@
     print_client("0,\n");
     print_client("0x50100a4, /* MIDL Version 5.1.164 */\n");
     print_client("0,\n");
-    print_client("0,\n");
+    print_client("%s,\n", list_empty(&user_type_list) ? "0" : "UserMarshalRoutines");
     print_client("0,  /* notify & notify_flag routine table */\n");
     print_client("1,  /* Flags */\n");
     print_client("0,  /* Reserved3 */\n");
@@ -367,6 +315,9 @@
 {
     unsigned long ver = get_attrv(iface->attrs, ATTR_VERSION);
     const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID);
+    const str_list_t *endpoints = get_attrp(iface->attrs, ATTR_ENDPOINT);
+
+    if (endpoints) write_endpoints( client, iface->name, endpoints );
 
     print_client("static const RPC_CLIENT_INTERFACE %s___RpcClientInterface =\n", iface->name );
     print_client("{\n");
@@ -378,8 +329,16 @@
                  uuid->Data4[7], LOWORD(ver), HIWORD(ver));
     print_client("{{0x8a885d04,0x1ceb,0x11c9,{0x9f,0xe8,0x08,0x00,0x2b,0x10,0x48,0x60}},{2,0}},\n"); /* FIXME */
     print_client("0,\n");
-    print_client("0,\n");
-    print_client("0,\n");
+    if (endpoints)
+    {
+        print_client("%u,\n", list_count(endpoints));
+        print_client("(PRPC_PROTSEQ_ENDPOINT)%s__RpcProtseqEndpoint,\n", iface->name);
+    }
+    else
+    {
+        print_client("0,\n");
+        print_client("0,\n");
+    }
     print_client("0,\n");
     print_client("0,\n");
     print_client("0,\n");
@@ -389,8 +348,8 @@
         print_client("RPC_IF_HANDLE %s_ClientIfHandle = (RPC_IF_HANDLE)& %s___RpcClientInterface;\n",
                      iface->name, iface->name);
     else
-        print_client("RPC_IF_HANDLE %s_v%d_%d_c_ifspec = (RPC_IF_HANDLE)& %s___RpcClientInterface;\n",
-                     iface->name, LOWORD(ver), HIWORD(ver), iface->name);
+        print_client("RPC_IF_HANDLE %s%s_v%d_%d_c_ifspec = (RPC_IF_HANDLE)& %s___RpcClientInterface;\n",
+                     prefix_client, iface->name, LOWORD(ver), HIWORD(ver), iface->name);
     fprintf(client, "\n");
 }
 
@@ -424,17 +383,15 @@
 }
 
 
-void write_client(ifref_t *ifaces)
+void write_client(ifref_list_t *ifaces)
 {
     unsigned int proc_offset = 0;
-    unsigned int type_offset = 2;
-    ifref_t *iface = ifaces;
+    ifref_t *iface;
 
     if (!do_client)
         return;
-    if (!iface)
+    if (do_everything && !ifaces)
         return;
-    END_OF_LIST(iface);
 
     init_client();
     if (!client)
@@ -442,7 +399,7 @@
 
     write_formatstringsdecl(client, indent, ifaces, 0);
 
-    for (; iface; iface = PREV_LINK(iface))
+    if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, ifref_t, entry )
     {
         if (is_object(iface->iface->attrs) || is_local(iface->iface->attrs))
             continue;
@@ -460,9 +417,7 @@
     
             write_clientinterfacedecl(iface->iface);
             write_stubdescdecl(iface->iface);
-            write_bindinghandledecl(iface->iface);
-    
-            write_function_stubs(iface->iface, &proc_offset, &type_offset);
+            write_function_stubs(iface->iface, &proc_offset);
 
             print_client("#if !defined(__RPC_WIN32__)\n");
             print_client("#error  Invalid build platform for this stub.\n");
@@ -473,6 +428,7 @@
             expr_eval_routines = write_expr_eval_routines(client, iface->iface->name);
             if (expr_eval_routines)
                 write_expr_eval_routine_list(client, iface->iface->name);
+            write_user_quad_list(client);
             write_stubdescriptor(iface->iface, expr_eval_routines);
         }
     }

Index: hash.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/tools/widl/hash.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- hash.c	6 Nov 2006 14:30:41 -0000	1.1
+++ hash.c	14 Dec 2007 20:18:50 -0000	1.2
@@ -514,7 +514,7 @@
   switch (PRIMARYLANGID(LANGIDFROMLCID(lcid)))
   {
   default:
-    fprintf(stderr, "Unknown lcid %lx, treating as latin-based, please report\n", lcid);
+    fprintf(stderr, "Unknown lcid %x, treating as latin-based, please report\n", lcid);
     /* .. Fall Through .. */
   case LANG_AFRIKAANS:  case LANG_ALBANIAN:   case LANG_ARMENIAN:
   case LANG_ASSAMESE:   case LANG_AZERI:      case LANG_BASQUE:

Index: header.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/tools/widl/header.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- header.c	6 Nov 2006 14:30:41 -0000	1.5
+++ header.c	14 Dec 2007 20:18:50 -0000	1.6
@@ -20,6 +20,7 @@
 
 #include "config.h"
 
+#include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #ifdef HAVE_UNISTD_H
@@ -46,29 +47,25 @@
   if (delta > 0) indentation += delta;
 }
 
-static void write_icom_method_def(type_t *iface)
+static void write_icom_method_def(const type_t *iface)
 {
-  func_t *cur = iface->funcs;
-  while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
-  while (cur) {
+  const func_t *cur;
+
+  LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry ) {
     var_t *def = cur->def;
     if (!is_callas(def->attrs)) {
-      var_t *arg = cur->args;
+      const var_t *arg;
       int argc = 0;
-      if (arg) {
-        argc++;
-        while (NEXT_LINK(arg)) {
-          arg = NEXT_LINK(arg);
-          argc++;
-        }
-      }
+
+      if (cur->args) LIST_FOR_EACH_ENTRY( arg, cur->args, const var_t, entry ) argc++;
+
       fprintf(header, " \\\n");
-      if (!is_void(def->type, def)) {
+      if (!is_void(def->type)) {
         if (argc)
           fprintf(header, "    ICOM_METHOD%d (", argc);
         else
           fprintf(header, "    ICOM_METHOD  (");
-        write_type(header, def->type, def, def->tname);
+        write_type_left(header, def->type);
         fprintf(header, ",");
       } else
         if (argc)
@@ -76,77 +73,88 @@
         else
           fprintf(header, "    ICOM_VMETHOD (");
       write_name(header, def);
-      while (arg) {
+      if (cur->args) LIST_FOR_EACH_ENTRY( arg, cur->args, const var_t, entry ) {
         fprintf(header, ",");
-        write_type(header, arg->type, arg, arg->tname);
+        write_type_left(header, arg->type);
         /* since the ICOM macros can't express arrays,
          * we have to pretend they're pointers instead */
-        if (arg->array) fprintf(header, "*");
+        if (arg->type->declarray)
+          fprintf(header, "*");
         fprintf(header, ",");
         write_name(header,arg);
-        arg = PREV_LINK(arg);
       }
       fprintf(header, ")");
     }
-    cur = PREV_LINK(cur);
   }
   fprintf(header, "\n");
 }
 
 
-int is_attr(const attr_t *a, enum attr_type t)
+int is_ptrchain_attr(const var_t *var, enum attr_type t)
 {
-  while (a) {
-    if (a->type == t) return 1;
-    a = NEXT_LINK(a);
-  }
-  return 0;
+    if (is_attr(var->attrs, t))
+        return 1;
+    else
+    {
+        type_t *type = var->type;
+        for (;;)
+        {
+            if (is_attr(type->attrs, t))
+                return 1;
+            else if (type->kind == TKIND_ALIAS)
+                type = type->orig;
+            else if (is_ptr(type))
+                type = type->ref;
+            else return 0;
+        }
+    }
 }
 
-void *get_attrp(const attr_t *a, enum attr_type t)
+int is_attr(const attr_list_t *list, enum attr_type t)
 {
-  while (a) {
-    if (a->type == t) return a->u.pval;
-    a = NEXT_LINK(a);
-  }
-  return NULL;
+    const attr_t *attr;
+    if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry )
+        if (attr->type == t) return 1;
+    return 0;
 }
 
-unsigned long get_attrv(const attr_t *a, enum attr_type t)
+void *get_attrp(const attr_list_t *list, enum attr_type t)
 {
-  while (a) {
-    if (a->type == t) return a->u.ival;
-    a = NEXT_LINK(a);
-  }
-  return 0;
+    const attr_t *attr;
+    if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry )
+        if (attr->type == t) return attr->u.pval;
+    return NULL;
 }
 
-int is_void(const type_t *t, const var_t *v)
+unsigned long get_attrv(const attr_list_t *list, enum attr_type t)
+{
+    const attr_t *attr;
+    if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry )
+        if (attr->type == t) return attr->u.ival;
+    return 0;
+}
+
+int is_void(const type_t *t)
 {
-  if (v && v->ptr_level) return 0;
   if (!t->type && !t->ref) return 1;
   return 0;
 }
 
+int is_conformant_array(const type_t *t)
+{
+    return t->type == RPC_FC_CARRAY || t->type == RPC_FC_CVARRAY;
+}
+
 void write_guid(FILE *f, const char *guid_prefix, const char *name, const UUID *uuid)
 {
   if (!uuid) return;
-  fprintf(f, "DEFINE_GUID(%s_%s, 0x%08lx, 0x%04x, 0x%04x, 0x%02x,0x%02x, 0x%02x,"
+  fprintf(f, "DEFINE_GUID(%s_%s, 0x%08x, 0x%04x, 0x%04x, 0x%02x,0x%02x, 0x%02x,"
         "0x%02x,0x%02x,0x%02x,0x%02x,0x%02x);\n",
         guid_prefix, name, uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0],
         uuid->Data4[1], uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5],
         uuid->Data4[6], uuid->Data4[7]);
 }
 
-static void write_pident(FILE *h, const var_t *v)
-{
-  int c;
-  for (c=0; c<v->ptr_level; c++) {
-    fprintf(h, "*");
-  }
-  if (v->name) fprintf(h, "%s", v->name);
-}
-
 void write_name(FILE *h, const var_t *v)
 {
   if (is_attr( v->attrs, ATTR_PROPGET ))
@@ -158,40 +166,18 @@
   fprintf(h, "%s", v->name);
 }
 
-const char* get_name(const var_t *v)
-{
-  return v->name;
-}
-
-void write_array(FILE *h, const expr_t *v, int field)
+void write_prefix_name(FILE *h, const char *prefix, const var_t *v)
 {
-  if (!v) return;
-  while (NEXT_LINK(v)) v = NEXT_LINK(v);
-  fprintf(h, "[");
-  while (v) {
-    if (v->is_const)
-      fprintf(h, "%ld", v->cval); /* statically sized array */
-    else
-      if (field) fprintf(h, "1"); /* dynamically sized array */
-    if (PREV_LINK(v))
-      fprintf(h, ", ");
-    v = PREV_LINK(v);
-  }
-  fprintf(h, "]");
+  fprintf(h, "%s", prefix);
+  write_name(h, v);
 }
 
 static void write_field(FILE *h, var_t *v)
 {
   if (!v) return;
   if (v->type) {
-    indent(h, 0);
-    write_type(h, v->type, NULL, v->tname);
-    if (get_name(v)) {
-      fprintf(h, " ");
-      write_pident(h, v);
-    }
-    else {
-      /* not all C/C++ compilers support anonymous structs and unions */
+    const char *name = v->name;
+    if (name == NULL) {
       switch (v->type->type) {
       case RPC_FC_STRUCT:
       case RPC_FC_CVSTRUCT:
@@ -200,39 +186,36 @@
       case RPC_FC_PSTRUCT:
       case RPC_FC_BOGUS_STRUCT:
       case RPC_FC_ENCAPSULATED_UNION:
-        fprintf(h, " DUMMYSTRUCTNAME");
+        name = "DUMMYSTRUCTNAME";
         break;
       case RPC_FC_NON_ENCAPSULATED_UNION:
-        fprintf(h, " DUMMYUNIONNAME");
+        name = "DUMMYUNIONNAME";
         break;
       default:
         /* ? */
         break;
       }
     }
-    write_array(h, v->array, 1);
+    indent(h, 0);
+    write_type(h, v->type, TRUE, "%s", name);
     fprintf(h, ";\n");
   }
 }
 
-static void write_fields(FILE *h, var_t *v)
+static void write_fields(FILE *h, var_list_t *fields)
 {
-  var_t *first = v;
-  if (!v) return;
-  while (NEXT_LINK(v)) v = NEXT_LINK(v);
-  while (v) {
-    write_field(h, v);
-    if (v == first) break;
-    v = PREV_LINK(v);
-  }
+    var_t *v;
+    if (!fields) return;
+    LIST_FOR_EACH_ENTRY( v, fields, var_t, entry ) write_field(h, v);
 }
 
-static void write_enums(FILE *h, var_t *v)
+static void write_enums(FILE *h, var_list_t *enums)
 {
-  if (!v) return;
-  while (NEXT_LINK(v)) v = NEXT_LINK(v);
-  while (v) {
-    if (get_name(v)) {
+  var_t *v;
+  if (!enums) return;
+  LIST_FOR_EACH_ENTRY( v, enums, var_t, entry )
+  {
+    if (v->name) {
       indent(h, 0);
       write_name(h, v);
       if (v->eval) {
@@ -240,26 +223,23 @@
         write_expr(h, v->eval, 0);
       }
     }
-    if (PREV_LINK(v))
-      fprintf(h, ",\n");
-    v = PREV_LINK(v);
+    if (list_next( enums, &v->entry )) fprintf(h, ",\n");
   }
   fprintf(h, "\n");
 }
 
 int needs_space_after(type_t *t)
 {
-  return t->kind == TKIND_ALIAS || ! is_ptr(t);
+  return (t->kind == TKIND_ALIAS
+          || (!is_ptr(t) && (!is_conformant_array(t) || t->declarray)));
 }
 
-void write_type(FILE *h, type_t *t, const var_t *v, const char *n)
+void write_type_left(FILE *h, type_t *t)
 {
-  int c;
-
   if (t->is_const) fprintf(h, "const ");
 
-  if (n) fprintf(h, "%s", n);
-  else if (t->kind == TKIND_ALIAS) fprintf(h, "%s", t->name);
+  if (t->kind == TKIND_ALIAS) fprintf(h, "%s", t->name);
+  else if (t->declarray) write_type_left(h, t->ref);
   else {
     if (t->sign > 0) fprintf(h, "signed ");
     else if (t->sign < 0) fprintf(h, "unsigned ");
@@ -311,41 +291,61 @@
       case RPC_FC_UP:
       case RPC_FC_FP:
       case RPC_FC_OP:
-        if (t->ref) write_type(h, t->ref, NULL, t->name);
+      case RPC_FC_CARRAY:
+      case RPC_FC_CVARRAY:
+        write_type_left(h, t->ref);
         fprintf(h, "%s*", needs_space_after(t->ref) ? " " : "");
         break;
       default:
         fprintf(h, "%s", t->name);
     }
   }
-  if (v) {
-    for (c=0; c<v->ptr_level; c++) {
-      fprintf(h, "*");
+}
+
+void write_type_right(FILE *h, type_t *t, int is_field)
+{
+  if (t->declarray) {
+    if (is_conformant_array(t)) {
+      fprintf(h, "[%s]", is_field ? "1" : "");
+      t = t->ref;
     }
+    for ( ; t->declarray; t = t->ref)
+      fprintf(h, "[%lu]", t->dim);
   }
 }
 
-
-struct user_type
+void write_type(FILE *h, type_t *t, int is_field, const char *fmt, ...)
 {
-    struct user_type *next;
-    char name[1];
-};
+  write_type_left(h, t);
+  if (fmt) {
+    va_list args;
+    va_start(args, fmt);
+    if (needs_space_after(t))
+      fprintf(h, " ");
+    vfprintf(h, fmt, args);
+    va_end(args);
+  }
+  write_type_right(h, t, is_field);
+}
 
-static struct user_type *user_type_list;
+user_type_list_t user_type_list = LIST_INIT(user_type_list);
 
 static int user_type_registered(const char *name)
 {
-  struct user_type *ut;
-  for (ut = user_type_list; ut; ut = ut->next)
+  user_type_t *ut;
+  LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
     if (!strcmp(name, ut->name))
-        return 1;
+      return 1;
   return 0;
 }
 
-static void check_for_user_types(const var_t *v)
+void check_for_user_types(const var_list_t *list)
 {
-  while (v) {
+  const var_t *v;
+
+  if (!list) return;
+  LIST_FOR_EACH_ENTRY( v, list, const var_t, entry )
+  {
     type_t *type;
     for (type = v->type; type; type = type->kind == TKIND_ALIAS ? type->orig : type->ref) {
       const char *name = type->name;
@@ -354,44 +354,40 @@
       if (is_attr(type->attrs, ATTR_WIREMARSHAL)) {
         if (!user_type_registered(name))
         {
-          struct user_type *ut = xmalloc(sizeof(struct user_type) + strlen(name));
-          strcpy(ut->name, name);
-          ut->next = user_type_list;
-          user_type_list = ut;
+          user_type_t *ut = xmalloc(sizeof *ut);
+          ut->name = xstrdup(name);
+          list_add_tail(&user_type_list, &ut->entry);
         }
         /* don't carry on parsing fields within this type as we are already
          * using a wire marshaled type */
         break;
       }
-      else if (type->fields)
+      else
       {
-        const var_t *fields = type->fields;
-        while (NEXT_LINK(fields)) fields = NEXT_LINK(fields);
-        check_for_user_types(fields);
+        check_for_user_types(type->fields);
       }
     }
-    v = PREV_LINK(v);
   }
 }
 
 void write_user_types(void)
 {
-  struct user_type *ut;
-  for (ut = user_type_list; ut; ut = ut->next)
+  user_type_t *ut;
+  LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
   {
     const char *name = ut->name;
-    fprintf(header, "unsigned long   __RPC_USER %s_UserSize     (unsigned long *, unsigned long,   %s *);\n", name, name);
-    fprintf(header, "unsigned char * __RPC_USER %s_UserMarshal  (unsigned long *, unsigned char *, %s *);\n", name, name);
-    fprintf(header, "unsigned char * __RPC_USER %s_UserUnmarshal(unsigned long *, unsigned char *, %s *);\n", name, name);
-    fprintf(header, "void            __RPC_USER %s_UserFree     (unsigned long *, %s *);\n", name, name);
+    fprintf(header, "ULONG           __RPC_USER %s_UserSize     (ULONG *, ULONG, %s *);\n", name, name);
+    fprintf(header, "unsigned char * __RPC_USER %s_UserMarshal  (ULONG *, unsigned char *, %s *);\n", name, name);
+    fprintf(header, "unsigned char * __RPC_USER %s_UserUnmarshal(ULONG *, unsigned char *, %s *);\n", name, name);
+    fprintf(header, "void            __RPC_USER %s_UserFree     (ULONG *, %s *);\n", name, name);
   }
 }
 
 void write_typedef(type_t *type)
 {
   fprintf(header, "typedef ");
-  write_type(header, type->orig, NULL, NULL);
-  fprintf(header, "%s%s;\n", needs_space_after(type->orig) ? " " : "", type->name);
+  write_type(header, type->orig, FALSE, "%s", type->name);
+  fprintf(header, ";\n");
 }
 
 void write_expr(FILE *h, const expr_t *e, int brackets)
@@ -400,11 +396,14 @@
   case EXPR_VOID:
     break;
   case EXPR_NUM:
-    fprintf(h, "%ld", e->u.lval);
+    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");
@@ -428,13 +427,13 @@
     break;
   case EXPR_CAST:
     fprintf(h, "(");
-    write_type(h, e->u.tref->ref, NULL, e->u.tref->name);
+    write_type(h, e->u.tref, FALSE, NULL);
     fprintf(h, ")");
     write_expr(h, e->ref, 1);
     break;
   case EXPR_SIZEOF:
     fprintf(h, "sizeof(");
-    write_type(h, e->u.tref->ref, NULL, e->u.tref->name);
+    write_type(h, e->u.tref, FALSE, NULL);
     fprintf(h, ")");
     break;
   case EXPR_SHL:
@@ -475,7 +474,7 @@
 
 void write_constdef(const var_t *v)
 {
-  fprintf(header, "#define %s (", get_name(v));
+  fprintf(header, "#define %s (", v->name);
   write_expr(header, v->eval, 0);
   fprintf(header, ")\n\n");
 }
@@ -483,15 +482,12 @@
 void write_externdef(const var_t *v)
 {
   fprintf(header, "extern const ");
-  write_type(header, v->type, NULL, v->tname);
-  if (get_name(v)) {
-    fprintf(header, " ");
-    write_pident(header, v);
-  }
+  write_type(header, v->type, FALSE, "%s", v->name);
   fprintf(header, ";\n\n");
 }
 
-void write_library(const char *name, const attr_t *attr) {
+void write_library(const char *name, const attr_list_t *attr)
+{
   const UUID *uuid = get_attrp(attr, ATTR_UUID);
   fprintf(header, "\n");
   write_guid(header, "LIBID", name, uuid);
@@ -506,83 +502,69 @@
     if (!func->args)
         return NULL;
 
-    var = func->args;
-    while (NEXT_LINK(var)) var = NEXT_LINK(var);
-    while (var)
-    {
+    LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
         if (var->type->type == RPC_FC_BIND_PRIMITIVE)
             return var;
 
-        var = PREV_LINK(var);
-    }
-
     return NULL;
 }
 
 int has_out_arg_or_return(const func_t *func)
 {
-    var_t *var;
+    const var_t *var;
 
-    if (!is_void(func->def->type, NULL))
+    if (!is_void(func->def->type))
         return 1;
 
     if (!func->args)
         return 0;
 
-    var = func->args;
-    while (NEXT_LINK(var)) var = NEXT_LINK(var);
-    while (var)
-    {
+    LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
         if (is_attr(var->attrs, ATTR_OUT))
             return 1;
 
-        var = PREV_LINK(var);
-    }
     return 0;
 }
 
 
 /********** INTERFACES **********/
 
-int is_object(const attr_t *a)
+int is_object(const attr_list_t *list)
 {
-  while (a) {
-    if (a->type == ATTR_OBJECT || a->type == ATTR_ODL) return 1;
-    a = NEXT_LINK(a);
-  }
-  return 0;
+    const attr_t *attr;
+    if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry )
+        if (attr->type == ATTR_OBJECT || attr->type == ATTR_ODL) return 1;
+    return 0;
 }
 
-int is_local(const attr_t *a)
+int is_local(const attr_list_t *a)
 {
   return is_attr(a, ATTR_LOCAL);
 }
 
-const var_t *is_callas(const attr_t *a)
+const var_t *is_callas(const attr_list_t *a)
 {
   return get_attrp(a, ATTR_CALLAS);
 }
 
 static void write_method_macro(const type_t *iface, const char *name)
 {
-  func_t *cur = iface->funcs;
+  const func_t *cur;
 
   if (iface->ref) write_method_macro(iface->ref, name);
 
-  if (!cur) return;
-  while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
+  if (!iface->funcs) return;
 
   fprintf(header, "/*** %s methods ***/\n", iface->name);
-  while (cur) {
+  LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry )
+  {
     var_t *def = cur->def;
     if (!is_callas(def->attrs)) {
-      var_t *arg = cur->args;
+      const var_t *arg;
       int argc = 0;
       int c;
-      while (arg) {
-	arg = NEXT_LINK(arg);
-	argc++;
-      }
+
+      if (cur->args) LIST_FOR_EACH_ENTRY( arg, cur->args, const var_t, entry ) argc++;
 
       fprintf(header, "#define %s_", name);
       write_name(header,def);
@@ -612,17 +594,14 @@
 	fprintf(header, ",%c", c+'a');
       fprintf(header, ")\n");
     }
-    cur = PREV_LINK(cur);
   }
 }
 
-void write_args(FILE *h, var_t *arg, const char *name, int method, int do_indent)
+void write_args(FILE *h, const var_list_t *args, const char *name, int method, int do_indent)
 {
+  const var_t *arg;
   int count = 0;
-  if (arg) {
-    while (NEXT_LINK(arg))
-      arg = NEXT_LINK(arg);
-  }
+
   if (do_indent)
   {
       indentation++;
@@ -632,7 +611,7 @@
     fprintf(h, "%s* This", name);
     count++;
   }
-  while (arg) {
+  if (args) LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) {
     if (count) {
         if (do_indent)
         {
@@ -641,29 +620,23 @@
         }
         else fprintf(h, ",");
     }
-    write_type(h, arg->type, arg, arg->tname);
     if (arg->args)
     {
+      write_type_left(h, arg->type);
       fprintf(h, " (STDMETHODCALLTYPE *");
       write_name(h,arg);
       fprintf(h, ")(");
       write_args(h, arg->args, NULL, 0, FALSE);
       fprintf(h, ")");
     }
-    else
-    {
-      if ( use_icom )
-          fprintf( h, "*" );
-          
-      if (needs_space_after(arg->type))
-        fprintf(h, " ");
-      write_name(h, arg);
+    else if (use_icom) {
+      write_type_left(h, arg->type);
+      if (arg->type->declarray)
+        fprintf(h, "*");
+      fprintf(h, "%s", arg->name);
     }
-    
-    if ( !method && !use_icom )
-      write_array(h, arg->array, 0);
-      
-    arg = PREV_LINK(arg);
+    else
+      write_type(h, arg->type, FALSE, "%s", arg->name);
     count++;
   }
   if (do_indent) indentation--;
@@ -671,16 +644,17 @@
 
 static void write_cpp_method_def(const type_t *iface)
 {
-  func_t *cur = iface->funcs;
+  const func_t *cur;
 
-  if (!cur) return;
-  while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
-  while (cur) {
+  if (!iface->funcs) return;
+
+  LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry )
+  {
     var_t *def = cur->def;
     if (!is_callas(def->attrs)) {
       indent(header, 0);
       fprintf(header, "virtual ");
-      write_type(header, def->type, def, def->tname);
+      write_type_left(header, def->type);
       fprintf(header, " STDMETHODCALLTYPE ");
       write_name(header, def);
       fprintf(header, "(\n");
@@ -688,25 +662,24 @@
       fprintf(header, ") = 0;\n");
       fprintf(header, "\n");
     }
-    cur = PREV_LINK(cur);
   }
 }
 
 static void do_write_c_method_def(const type_t *iface, const char *name)
 {
-  const func_t *cur = iface->funcs;
+  const func_t *cur;
 
   if (iface->ref) do_write_c_method_def(iface->ref, name);
 
-  if (!cur) return;
-  while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
+  if (!iface->funcs) return;
   indent(header, 0);
   fprintf(header, "/*** %s methods ***/\n", iface->name);
-  while (cur) {
+  LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry )
+  {
     const var_t *def = cur->def;
     if (!is_callas(def->attrs)) {
       indent(header, 0);
-      write_type(header, def->type, def, def->tname);
+      write_type_left(header, def->type);
       fprintf(header, " (STDMETHODCALLTYPE *");
       write_name(header, def);
       fprintf(header, ")(\n");
@@ -714,7 +687,6 @@
       fprintf(header, ");\n");
       fprintf(header, "\n");
     }
-    cur = PREV_LINK(cur);
   }
 }
 
@@ -730,17 +702,17 @@
 
 static void write_method_proto(const type_t *iface)
 {
-  const func_t *cur = iface->funcs;
+  const func_t *cur;
 
-  if (!cur) return;
-  while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
-  while (cur) {
+  if (!iface->funcs) return;
+  LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry )
+  {
     const var_t *def = cur->def;
     const var_t *cas = is_callas(def->attrs);
-    const var_t *args;
+
     if (!is_local(def->attrs)) {
       /* proxy prototype */
-      write_type(header, def->type, def, def->tname);
+      write_type_left(header, def->type);
       fprintf(header, " CALLBACK %s_", iface->name);
       write_name(header, def);
       fprintf(header, "_Proxy(\n");
@@ -754,29 +726,22 @@
       fprintf(header, "    IRpcChannelBuffer* pRpcChannelBuffer,\n");
       fprintf(header, "    PRPC_MESSAGE pRpcMessage,\n");
       fprintf(header, "    DWORD* pdwStubPhase);\n");
-
-      args = cur->args;
-      if (args) {
-        while (NEXT_LINK(args))
-          args = NEXT_LINK(args);
-      }
-      check_for_user_types(args);
     }
     if (cas) {
-      const func_t *m = iface->funcs;
-      while (m && strcmp(get_name(m->def), cas->name))
-        m = NEXT_LINK(m);
-      if (m) {
+      const func_t *m;
+      LIST_FOR_EACH_ENTRY( m, iface->funcs, const func_t, entry )
+          if (!strcmp(m->def->name, cas->name)) break;
+      if (&m->entry != iface->funcs) {
         const var_t *mdef = m->def;
         /* proxy prototype - use local prototype */
-        write_type(header, mdef->type, mdef, mdef->tname);
+        write_type_left(header, mdef->type);
         fprintf(header, " CALLBACK %s_", iface->name);
         write_name(header, mdef);
         fprintf(header, "_Proxy(\n");
         write_args(header, m->args, iface->name, 1, TRUE);
         fprintf(header, ");\n");
         /* stub prototype - use remotable prototype */
-        write_type(header, def->type, def, def->tname);
+        write_type_left(header, def->type);
         fprintf(header, " __RPC_STUB %s_", iface->name);
         write_name(header, mdef);
         fprintf(header, "_Stub(\n");
@@ -784,23 +749,39 @@
         fprintf(header, ");\n");
       }
       else {
-        parser_warning("invalid call_as attribute (%s -> %s)\n", get_name(def), cas->name);
+        parser_warning("invalid call_as attribute (%s -> %s)\n", def->name, cas->name);
       }
     }
-
-    cur = PREV_LINK(cur);
   }
 }
 
-static void write_function_proto(const type_t *iface)
+static void write_function_proto(const type_t *iface, const func_t *fun, const char *prefix)
+{
+  var_t *def = fun->def;
+
+  /* FIXME: do we need to handle call_as? */
+  write_type_left(header, def->type);
+  fprintf(header, " ");
+  write_prefix_name(header, prefix, def);
+  fprintf(header, "(\n");
+  if (fun->args)
+    write_args(header, fun->args, iface->name, 0, TRUE);
+  else
+    fprintf(header, "    void");
+  fprintf(header, ");\n");
+}
+
+static void write_function_protos(const type_t *iface)
 {
   const char *implicit_handle = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE);
   int explicit_handle = is_attr(iface->attrs, ATTR_EXPLICIT_HANDLE);
   const var_t* explicit_handle_var;
+  const func_t *cur;
+  int prefixes_differ = strcmp(prefix_client, prefix_server);
 
-  func_t *cur = iface->funcs;
-  while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
-  while (cur) {
+  if (!iface->funcs) return;
+  LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry )
+  {
     var_t *def = cur->def;
 
     /* check for a defined binding handle */
@@ -817,18 +798,12 @@
       }
     }
 
-    /* FIXME: do we need to handle call_as? */
-    write_type(header, def->type, def, def->tname);
-    fprintf(header, " ");
-    write_name(header, def);
-    fprintf(header, "(\n");
-    if (cur->args)
-      write_args(header, cur->args, iface->name, 0, TRUE);
-    else
-      fprintf(header, "    void");
-    fprintf(header, ");\n");
-
-    cur = PREV_LINK(cur);
+    if (prefixes_differ) {
+      fprintf(header, "/* client prototype */\n");
+      write_function_proto(iface, cur, prefix_client);
+      fprintf(header, "/* server prototype */\n");
+    }
+    write_function_proto(iface, cur, prefix_server);
   }
 }
 
@@ -935,7 +910,7 @@
       fprintf(header, "    END_INTERFACE\n");
       fprintf(header, "} %sVtbl;\n", iface->name);
       fprintf(header, "interface %s {\n", iface->name);
-      fprintf(header, "    const %sVtbl* lpVtbl;\n", iface->name);
+      fprintf(header, "    CONST_VTBL %sVtbl* lpVtbl;\n", iface->name);
       fprintf(header, "};\n");
       fprintf(header, "\n");
       fprintf(header, "#ifdef COBJMACROS\n");
@@ -950,12 +925,10 @@
       }
       write_method_macro(iface, iface->name);
       fprintf(header, "#endif\n");
-      
-      
       fprintf(header, "\n");
       fprintf(header, "#endif\n");
   }
-  
+
   fprintf(header, "\n");
   write_method_proto(iface);
   fprintf(header,"\n#endif  /* __%s_INTERFACE_DEFINED__ */\n\n", iface->name);
@@ -985,15 +958,17 @@
     if (var) fprintf(header, "extern handle_t %s;\n", var);
     if (old_names)
     {
-        fprintf(header, "extern RPC_IF_HANDLE %s_ClientIfHandle;\n", iface->name);
-        fprintf(header, "extern RPC_IF_HANDLE %s_ServerIfHandle;\n", iface->name);
+        fprintf(header, "extern RPC_IF_HANDLE %s%s_ClientIfHandle;\n", prefix_client, iface->name);
+        fprintf(header, "extern RPC_IF_HANDLE %s%s_ServerIfHandle;\n", prefix_server, iface->name);
     }
     else
     {
-        fprintf(header, "extern RPC_IF_HANDLE %s_v%d_%d_c_ifspec;\n", iface->name, LOWORD(ver), HIWORD(ver));
-        fprintf(header, "extern RPC_IF_HANDLE %s_v%d_%d_s_ifspec;\n", iface->name, LOWORD(ver), HIWORD(ver));
+        fprintf(header, "extern RPC_IF_HANDLE %s%s_v%d_%d_c_ifspec;\n",
+                prefix_client, iface->name, LOWORD(ver), HIWORD(ver));
+        fprintf(header, "extern RPC_IF_HANDLE %s%s_v%d_%d_s_ifspec;\n",
+                prefix_server, iface->name, LOWORD(ver), HIWORD(ver));
     }
-    write_function_proto(iface);
+    write_function_protos(iface);
   }
   fprintf(header,"\n#endif  /* __%s_INTERFACE_DEFINED__ */\n\n", iface->name);
 
@@ -1033,7 +1008,7 @@
   fprintf(header, "    END_INTERFACE\n");
   fprintf(header, "} %sVtbl;\n", iface->name);
   fprintf(header, "interface %s {\n", iface->name);
-  fprintf(header, "    const %sVtbl* lpVtbl;\n", iface->name);
+  fprintf(header, "    CONST_VTBL %sVtbl* lpVtbl;\n", iface->name);
   fprintf(header, "};\n");
   fprintf(header, "\n");
   fprintf(header, "#ifdef COBJMACROS\n");

Index: header.h
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/tools/widl/header.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- header.h	6 Nov 2006 14:30:41 -0000	1.3
+++ header.h	14 Dec 2007 20:18:50 -0000	1.4
@@ -21,18 +21,26 @@
 #ifndef __WIDL_HEADER_H
 #define __WIDL_HEADER_H
 
-extern int is_attr(const attr_t *a, enum attr_type t);
-extern void *get_attrp(const attr_t *a, enum attr_type t);
-extern unsigned long get_attrv(const attr_t *a, enum attr_type t);
-extern int is_void(const type_t *t, const var_t *v);
+#include "widltypes.h"
+
+extern int is_ptrchain_attr(const var_t *var, enum attr_type t);
+extern int is_attr(const attr_list_t *list, enum attr_type t);
+extern void *get_attrp(const attr_list_t *list, enum attr_type t);
+extern unsigned long get_attrv(const attr_list_t *list, enum attr_type t);
+extern int is_void(const type_t *t);
+extern int is_conformant_array(const type_t *t);
 extern void write_name(FILE *h, const var_t *v);
+extern void write_prefix_name(FILE *h, const char *prefix, const var_t *v);
 extern const char* get_name(const var_t *v);
-extern void write_type(FILE *h, type_t *t, const var_t *v, const char *n);
-extern int is_object(const attr_t *a);
-extern int is_local(const attr_t *a);
-extern const var_t *is_callas(const attr_t *a);
-extern void write_args(FILE *h, var_t *arg, const char *name, int obj, int do_indent);
-extern void write_array(FILE *h, const expr_t *v, int field);
+extern void write_type_left(FILE *h, type_t *t);
+extern void write_type_right(FILE *h, type_t *t, int is_field);
+extern void write_type(FILE *h, type_t *t, int is_field, const char *fmt, ...);
+extern int needs_space_after(type_t *t);
+extern int is_object(const attr_list_t *list);
+extern int is_local(const attr_list_t *list);
+extern const var_t *is_callas(const attr_list_t *list);
+extern void write_args(FILE *h, const var_list_t *arg, const char *name, int obj, int do_indent);
+extern void write_array(FILE *h, array_dims_t *v, int field);
 extern void write_forward(type_t *iface);
 extern void write_interface(type_t *iface);
 extern void write_dispinterface(type_t *iface);
@@ -42,23 +50,26 @@
 extern void write_expr(FILE *h, const expr_t *e, int brackets);
 extern void write_constdef(const var_t *v);
 extern void write_externdef(const var_t *v);
-extern void write_library(const char *name, const attr_t *attr);
+extern void write_library(const char *name, const attr_list_t *attr);
 extern void write_user_types(void);
 extern const var_t* get_explicit_handle_var(const func_t* func);
 extern int has_out_arg_or_return(const func_t *func);
 extern void write_guid(FILE *f, const char *guid_prefix, const char *name,
                        const UUID *uuid);
 
-static inline int is_string_type(const attr_t *attrs, int ptr_level, const expr_t *array)
+static inline int last_ptr(const type_t *type)
 {
-    return (is_attr(attrs, ATTR_STRING) &&
-            ((ptr_level == 1 && !array) || (ptr_level == 0 && array)));
+    return is_ptr(type) && !is_ptr(type->ref);
 }
 
-static inline int is_array_type(const attr_t *attrs, int ptr_level, const expr_t *array)
+static inline int last_array(const type_t *type)
 {
-    return ((ptr_level == 1 && !array && is_attr(attrs, ATTR_SIZEIS)) ||
-            (ptr_level == 0 && array));
+    return is_array(type) && !is_array(type->ref);
+}
+
+static inline int is_string_type(const attr_list_t *attrs, const type_t *type)
+{
+    return is_attr(attrs, ATTR_STRING) && (last_ptr(type) || last_array(type));
 }
 
 #endif

Index: parser.l
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/tools/widl/parser.l,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- parser.l	6 Nov 2006 14:30:41 -0000	1.9
+++ parser.l	14 Dec 2007 20:18:50 -0000	1.10
@@ -29,9 +29,11 @@
 hexd	[0-9a-fA-F]
 hex	0x{hexd}+
 uuid	{hexd}{8}-{hexd}{4}-{hexd}{4}-{hexd}{4}-{hexd}{12}
+double	[0-9]+\.[0-9]+([eE][+-]?[0-9]+)*
 
 %x QUOTE
-%x pp_line
+%x ATTR
+%x PP_LINE
 
 %{
 
@@ -63,6 +65,7 @@
 static int cbufalloc = 0;
 
 static int kw_token(const char *kw);
+static int attr_token(const char *kw);
 
 #define MAX_IMPORT_DEPTH 10
 struct {
@@ -103,8 +106,8 @@
  **************************************************************************
  */
 %%
-<INITIAL>^{ws}*\#{ws}*	yy_push_state(pp_line);
-<pp_line>[^\n]*         {
+<INITIAL,ATTR>^{ws}*\#{ws}*	yy_push_state(PP_LINE);
+<PP_LINE>[^\n]*         {
                             int lineno;
                             char *cptr, *fname;
                             yy_pop_state();
@@ -123,7 +126,7 @@
                             free( input_name );
                             input_name = xstrdup(fname);
                         }
-\"			yy_push_state(QUOTE); cbufidx = 0;
+<INITIAL,ATTR>\"	yy_push_state(QUOTE); cbufidx = 0;
 <QUOTE>\"		{
 				yy_pop_state();
 				parser_lval.str = get_buffered_cstring();
@@ -133,25 +136,32 @@
 <QUOTE>\\\"		addcchar(yytext[1]);
 <QUOTE>\\.		addcchar('\\'); addcchar(yytext[1]);
 <QUOTE>.		addcchar(yytext[0]);
-{uuid}			{
+<INITIAL,ATTR>\[	yy_push_state(ATTR); return '[';
+<ATTR>\]		yy_pop_state(); return ']';
+<ATTR>{cident}		return attr_token(yytext);
+<ATTR>{uuid}			{
 				parser_lval.uuid = parse_uuid(yytext);
 				return aUUID;
 			}
-{hex}			{
+<INITIAL,ATTR>{hex}	{
 				parser_lval.num = strtoul(yytext, NULL, 0);
 				return aHEXNUM;
 			}
-{int}			{
+<INITIAL,ATTR>{int}	{
 				parser_lval.num = strtoul(yytext, NULL, 0);
 				return aNUM;
 			}
+<INITIAL>{double}	{
+				parser_lval.dbl = strtod(yytext, NULL);
+				return aDOUBLE;
+			}
 SAFEARRAY{ws}*/\(	return tSAFEARRAY;
 {cident}		return kw_token(yytext);
-\n			line_number++;
-{ws}
-\<\<			return SHL;
-\>\>			return SHR;
-.			return yytext[0];
+<INITIAL,ATTR>\n	line_number++;
+<INITIAL,ATTR>{ws}
+<INITIAL,ATTR>\<\<	return SHL;
+<INITIAL,ATTR>\>\>	return SHR;
+<INITIAL,ATTR>.		return yytext[0];
 <<EOF>>			{
 				if (import_stack_ptr) {
 					pop_import();
@@ -168,29 +178,20 @@
 }
 #endif
 
-static struct keyword {
+struct keyword {
 	const char *kw;
 	int token;
-	int val;
-} keywords[] = {
+};
+
+static const struct keyword keywords[] = {
 	{"FALSE",			tFALSE},
 	{"TRUE",			tTRUE},
 	{"__cdecl",			tCDECL},
 	{"__int64",			tINT64},
 	{"__stdcall",			tSTDCALL},
 	{"_stdcall",			tSTDCALL},
-	{"aggregatable",		tAGGREGATABLE},
-	{"allocate",			tALLOCATE},
-	{"appobject",			tAPPOBJECT},
-	{"async",			tASYNC},
-	{"async_uuid",			tASYNCUUID},
-	{"auto_handle",			tAUTOHANDLE},
-	{"bindable",			tBINDABLE},
 	{"boolean",			tBOOLEAN},
-	{"broadcast",			tBROADCAST},
 	{"byte",			tBYTE},
-	{"byte_count",			tBYTECOUNT},
-	{"call_as",			tCALLAS},
 	{"callback",			tCALLBACK},
 	{"case",			tCASE},
 	{"char",			tCHAR},
@@ -198,121 +199,119 @@
 	{"code",			tCODE},
 	{"comm_status",			tCOMMSTATUS},
 	{"const",			tCONST},
-	{"context_handle",		tCONTEXTHANDLE},
-	{"context_handle_noserialize",	tCONTEXTHANDLENOSERIALIZE},
-	{"context_handle_serialize",	tCONTEXTHANDLENOSERIALIZE},
-	{"control",			tCONTROL},
 	{"cpp_quote",			tCPPQUOTE},
-/* ... */
 	{"default",			tDEFAULT},
-	{"defaultcollelem",		tDEFAULTCOLLELEM},
-	{"defaultvalue",		tDEFAULTVALUE},
-	{"defaultvtable",		tDEFAULTVTABLE},
 	{"dispinterface",		tDISPINTERFACE},
-	{"displaybind",			tDISPLAYBIND},
-	{"dllname",			tDLLNAME},
 	{"double",			tDOUBLE},
-	{"dual",			tDUAL},
-	{"endpoint",			tENDPOINT},
-	{"entry",			tENTRY},
 	{"enum",			tENUM},
 	{"error_status_t",		tERRORSTATUST},
-	{"explicit_handle",		tEXPLICITHANDLE},
 	{"extern",			tEXTERN},
 	{"float",			tFLOAT},
-	{"handle",			tHANDLE},
 	{"handle_t",			tHANDLET},
-	{"helpcontext",			tHELPCONTEXT},
-	{"helpfile",			tHELPFILE},
-	{"helpstring",			tHELPSTRING},
-	{"helpstringcontext",		tHELPSTRINGCONTEXT},
-	{"helpstringdll",		tHELPSTRINGDLL},
-	{"hidden",                      tHIDDEN},
 	{"hyper",			tHYPER},
-	{"id",				tID},
-	{"idempotent",			tIDEMPOTENT},
-/* ... */
-	{"iid_is",			tIIDIS},
-	{"immediatebind",		tIMMEDIATEBIND},
-	{"implicit_handle",		tIMPLICITHANDLE},
 	{"import",			tIMPORT},
 	{"importlib",			tIMPORTLIB},
-	{"in",				tIN},
 	{"in_line",			tINLINE},
-	{"input_sync",			tINPUTSYNC},
 	{"int",				tINT},
-/* ... */
 	{"interface",			tINTERFACE},
-	{"lcid",			tLCID},
-	{"length_is",			tLENGTHIS},
 	{"library",			tLIBRARY},
-/* ... */
-	{"local",			tLOCAL},
 	{"long",			tLONG},
-/* ... */
 	{"methods",			tMETHODS},
-/* ... */
 	{"module",			tMODULE},
-/* ... */
-	{"nonbrowsable",		tNONBROWSABLE},
-	{"noncreatable",		tNONCREATABLE},
-	{"nonextensible",		tNONEXTENSIBLE},
-	{"object",			tOBJECT},
-	{"odl",				tODL},
-	{"oleautomation",		tOLEAUTOMATION},
-/* ... */
-	{"optional",			tOPTIONAL},
-	{"out",				tOUT},
-/* ... */
-	{"pointer_default",		tPOINTERDEFAULT},
-/* ... */
 	{"properties",			tPROPERTIES},
-	{"propget",			tPROPGET},
-	{"propput",			tPROPPUT},
-	{"propputref",			tPROPPUTREF},
-        {"ptr",				tPTR},
-/* ... */
-	{"public",			tPUBLIC},
-        {"range",			tRANGE},
-/* ... */
-	{"readonly",			tREADONLY},
-	{"ref",				tREF},
-	{"requestedit",			tREQUESTEDIT},
-	{"restricted",                  tRESTRICTED},
-	{"retval",			tRETVAL},
-/* ... */
 	{"short",			tSHORT},
 	{"signed",			tSIGNED},
-	{"single",			tSINGLE},
-	{"size_is",			tSIZEIS},
 	{"sizeof",			tSIZEOF},
         {"small",			tSMALL},
-/* ... */
-	{"source",			tSOURCE},
-/* ... */	
-	{"string",			tSTRING},
 	{"struct",			tSTRUCT},
 	{"switch",			tSWITCH},
-	{"switch_is",			tSWITCHIS},
-	{"switch_type",			tSWITCHTYPE},
-/* ... */
-	{"transmit_as",			tTRANSMITAS},
 	{"typedef",			tTYPEDEF},
 	{"union",			tUNION},
-/* ... */
-	{"unique",			tUNIQUE},
 	{"unsigned",			tUNSIGNED},
-/* ... */
-	{"uuid",			tUUID},
-	{"v1_enum",			tV1ENUM},
-/* ... */
-	{"vararg",			tVARARG},
-	{"version",			tVERSION},
 	{"void",			tVOID},
 	{"wchar_t",			tWCHAR},
-	{"wire_marshal",		tWIREMARSHAL},
 };
 #define NKEYWORDS (sizeof(keywords)/sizeof(keywords[0]))
+
+/* keywords only recognized in attribute lists */
+static const struct keyword attr_keywords[] =
+{
+        {"aggregatable",                tAGGREGATABLE},
+        {"allocate",                    tALLOCATE},
+        {"appobject",                   tAPPOBJECT},
+        {"async",                       tASYNC},
+        {"async_uuid",                  tASYNCUUID},
+        {"auto_handle",                 tAUTOHANDLE},
+        {"bindable",                    tBINDABLE},
+        {"broadcast",                   tBROADCAST},
+        {"byte_count",                  tBYTECOUNT},
+        {"call_as",                     tCALLAS},
+        {"context_handle",              tCONTEXTHANDLE},
+        {"context_handle_noserialize",  tCONTEXTHANDLENOSERIALIZE},
+        {"context_handle_serialize",    tCONTEXTHANDLENOSERIALIZE},
+        {"control",                     tCONTROL},
+        {"defaultcollelem",             tDEFAULTCOLLELEM},
+        {"defaultvalue",                tDEFAULTVALUE},
+        {"defaultvtable",               tDEFAULTVTABLE},
+        {"displaybind",                 tDISPLAYBIND},
+        {"dllname",                     tDLLNAME},
+        {"dual",                        tDUAL},
+        {"endpoint",                    tENDPOINT},
+        {"entry",                       tENTRY},
+        {"explicit_handle",             tEXPLICITHANDLE},
+        {"handle",                      tHANDLE},
+        {"helpcontext",                 tHELPCONTEXT},
+        {"helpfile",                    tHELPFILE},
+        {"helpstring",                  tHELPSTRING},
+        {"helpstringcontext",           tHELPSTRINGCONTEXT},
+        {"helpstringdll",               tHELPSTRINGDLL},
+        {"hidden",                      tHIDDEN},
+        {"id",                          tID},
+        {"idempotent",                  tIDEMPOTENT},
+        {"iid_is",                      tIIDIS},
+        {"immediatebind",               tIMMEDIATEBIND},
+        {"implicit_handle",             tIMPLICITHANDLE},
+        {"in",                          tIN},
+        {"input_sync",                  tINPUTSYNC},
+        {"lcid",                        tLCID},
+        {"length_is",                   tLENGTHIS},
+        {"local",                       tLOCAL},
+        {"nonbrowsable",                tNONBROWSABLE},
+        {"noncreatable",                tNONCREATABLE},
+        {"nonextensible",               tNONEXTENSIBLE},
+        {"object",                      tOBJECT},
+        {"odl",                         tODL},
+        {"oleautomation",               tOLEAUTOMATION},
+        {"optional",                    tOPTIONAL},
+        {"out",                         tOUT},
+        {"pointer_default",             tPOINTERDEFAULT},
+        {"propget",                     tPROPGET},
+        {"propput",                     tPROPPUT},
+        {"propputref",                  tPROPPUTREF},
+        {"ptr",                         tPTR},
+        {"public",                      tPUBLIC},
+        {"range",                       tRANGE},
+        {"readonly",                    tREADONLY},
+        {"ref",                         tREF},
+        {"requestedit",                 tREQUESTEDIT},
+        {"restricted",                  tRESTRICTED},
+        {"retval",                      tRETVAL},
+        {"single",                      tSINGLE},
+        {"size_is",                     tSIZEIS},
+        {"source",                      tSOURCE},
+        {"string",                      tSTRING},
+        {"switch_is",                   tSWITCHIS},
+        {"switch_type",                 tSWITCHTYPE},
+        {"transmit_as",                 tTRANSMITAS},
+        {"unique",                      tUNIQUE},
+        {"uuid",                        tUUID},
+        {"v1_enum",                     tV1ENUM},
+        {"vararg",                      tVARARG},
+        {"version",                     tVERSION},
+        {"wire_marshal",                tWIREMARSHAL},
+};
+
+
 #define KWP(p) ((const struct keyword *)(p))
 
 static int kw_cmp_func(const void *s1, const void *s2)
@@ -320,31 +319,32 @@
 	return strcmp(KWP(s1)->kw, KWP(s2)->kw);
 }
 
-#define KW_BSEARCH
 static int kw_token(const char *kw)
 {
 	struct keyword key, *kwp;
 	key.kw = kw;
-#ifdef KW_BSEARCH
 	kwp = bsearch(&key, keywords, NKEYWORDS, sizeof(keywords[0]), kw_cmp_func);
-#else
-	{
-		int i;
-		for (kwp=NULL, i=0; i < NKEYWORDS; i++)
-			if (!kw_cmp_func(&key, &keywords[i])) {
-				kwp = &keywords[i];
-				break;
-			}
-	}
-#endif
 	if (kwp) {
-		parser_lval.str = (char*)kwp->kw;
+		parser_lval.str = xstrdup(kwp->kw);
 		return kwp->token;
 	}
 	parser_lval.str = xstrdup(kw);
 	return is_type(kw) ? aKNOWNTYPE : aIDENTIFIER;
 }
 
+static int attr_token(const char *kw)
+{
+        struct keyword key, *kwp;
+        key.kw = kw;
+        kwp = bsearch(&key, attr_keywords, sizeof(attr_keywords)/sizeof(attr_keywords[0]),
+                      sizeof(attr_keywords[0]), kw_cmp_func);
+        if (kwp) {
+            parser_lval.str = xstrdup(kwp->kw);
+            return kwp->token;
+        }
+        return kw_token(kw);
+}
+
 static void addcchar(char c)
 {
 	if(cbufidx >= cbufalloc)

Index: parser.y
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/tools/widl/parser.y,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- parser.y	6 Nov 2006 14:30:41 -0000	1.5
+++ parser.y	14 Dec 2007 20:18:50 -0000	1.6
@@ -38,6 +38,7 @@
 #include "parser.h"
 #include "header.h"
 #include "typelib.h"
+#include "typegen.h"
 
 #if defined(YYBYACC)
 	/* Berkeley yacc (byacc) doesn't seem to know about these */
@@ -64,49 +65,68 @@
 # endif
 #endif
 
[...1306 lines suppressed...]
   }
 }
 
@@ -1687,3 +1963,16 @@
   if (t->type == 0 && ! is_var_ptr(arg))
     yyerror("argument '%s' has void type", arg->name);
 }
+
+static void check_all_user_types(ifref_list_t *ifrefs)
+{
+  const ifref_t *ifref;
+  const func_t *f;
+
+  if (ifrefs) LIST_FOR_EACH_ENTRY(ifref, ifrefs, const ifref_t, entry)
+  {
+    const func_list_t *fs = ifref->iface->funcs;
+    if (fs) LIST_FOR_EACH_ENTRY(f, fs, const func_t, entry)
+      check_for_user_types(f->args);
+  }
+}

Index: proxy.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/tools/widl/proxy.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- proxy.c	6 Nov 2006 14:30:41 -0000	1.3
+++ proxy.c	14 Dec 2007 20:18:50 -0000	1.4
@@ -51,39 +51,46 @@
 
 /* FIXME: support generation of stubless proxies */
 
-static int print_proxy( const char *format, ... )
+static void print_proxy( const char *format, ... )
 {
   va_list va;
-  int i, r;
-
   va_start( va, format );
-  if ( format[0] != '\n' )
[...1075 lines suppressed...]
+              fprintf(proxy, "        *pIndex = %d;\n", c);
+              fprintf(proxy, "        return 1;\n");
+              fprintf(proxy, "    }\n");
+              c++;
+          }
   fprintf(proxy, "    return 0;\n");
   fprintf(proxy, "}\n");
   fprintf(proxy, "\n");
 
   fprintf(proxy, "const ExtendedProxyFileInfo %s_ProxyFileInfo =\n", file_id);
   fprintf(proxy, "{\n");
-  fprintf(proxy, "    (PCInterfaceProxyVtblList*)&_%s_ProxyVtblList,\n", file_id);
-  fprintf(proxy, "    (PCInterfaceStubVtblList*)&_%s_StubVtblList,\n", file_id);
-  fprintf(proxy, "    (const PCInterfaceName*)&_%s_InterfaceNamesList,\n", file_id);
+  fprintf(proxy, "    (const PCInterfaceProxyVtblList*)&_%s_ProxyVtblList,\n", file_id);
+  fprintf(proxy, "    (const PCInterfaceStubVtblList*)&_%s_StubVtblList,\n", file_id);
+  fprintf(proxy, "    _%s_InterfaceNamesList,\n", file_id);
   fprintf(proxy, "    0,\n");
   fprintf(proxy, "    &_%s_IID_Lookup,\n", file_id);
   fprintf(proxy, "    %d,\n", c);

Index: server.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/tools/widl/server.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- server.c	6 Nov 2006 14:30:41 -0000	1.1
+++ server.c	14 Dec 2007 20:18:50 -0000	1.2
@@ -46,156 +46,26 @@
 static int indent = 0;
 
 
-static int print_server(const char *format, ...)
+static void print_server(const char *format, ...)
 {
     va_list va;
-    int i, r;
-
     va_start(va, format);
-    if (format[0] != '\n')
-        for (i = 0; i < indent; i++)
-            fprintf(server, "    ");
-    r = vfprintf(server, format, va);
+    print(server, indent, format, va);
     va_end(va);
-    return r;
-}
-
-
-static void write_parameters_init(const func_t *func)
-{
-    const var_t *var;
-
-    if (!func->args)
-        return;
-
-    var = func->args;
-    while (NEXT_LINK(var)) var = NEXT_LINK(var);
-    while (var)
-    {
-        if (var->type->type != RPC_FC_BIND_PRIMITIVE)
-            print_server("%s = 0;\n", var->name);
-
-        var = PREV_LINK(var);
-    }
-    fprintf(server, "\n");
-}
-
-
-static void declare_args(const func_t *func)
-{
-    int in_attr, out_attr;
-    int i = 0;
-    var_t *var;
-
-    if (!func->args)
-        return;
-
-    var = func->args;
-    while (NEXT_LINK(var)) var = NEXT_LINK(var);
-    while (var)
-    {
-        const expr_t *size_is = get_attrp(var->attrs, ATTR_SIZEIS);
-        int has_size = size_is && (size_is->type != EXPR_VOID);
-        int is_string = is_attr(var->attrs, ATTR_STRING);
-
-        in_attr = is_attr(var->attrs, ATTR_IN);
-        out_attr = is_attr(var->attrs, ATTR_OUT);
-        if (!out_attr && !in_attr)
-            in_attr = 1;
-
-        if (!in_attr && !has_size && !is_string)
-        {
-            int indirection;
-            print_server("");
-            write_type(server, var->type, NULL, var->tname);
-            for (indirection = 0; indirection < var->ptr_level - 1; indirection++)
-                fprintf(server, "*");
-            fprintf(server, " _W%u;\n", i++);
-        }
-
-        print_server("");
-        write_type(server, var->type, var, var->tname);
-        fprintf(server, " ");
-        write_name(server, var);
-        write_array(server, var->array, 0);
-        fprintf(server, ";\n");
-
-        var = PREV_LINK(var);
-    }
 }
 
-
-static void assign_out_args(const func_t *func)
-{
-    int in_attr, out_attr;
-    int i = 0, sep = 0;
-    var_t *var;
-    const expr_t *size_is;
-    int has_size;
-
-    if (!func->args)
-        return;
-
-    var = func->args;
-    while (NEXT_LINK(var)) var = NEXT_LINK(var);
-    while (var)
-    {
-        int is_string = is_attr(var->attrs, ATTR_STRING);
-        size_is = get_attrp(var->attrs, ATTR_SIZEIS);
-        has_size = size_is && (size_is->type != EXPR_VOID);
-        in_attr = is_attr(var->attrs, ATTR_IN);
-        out_attr = is_attr(var->attrs, ATTR_OUT);
-        if (!out_attr && !in_attr)
-            in_attr = 1;
-
-        if (!in_attr)
-        {
-            print_server("");
-            write_name(server, var);
-
-            if (has_size)
-            {
-                unsigned int size;
-                type_t *type = var->type;
-
-                fprintf(server, " = NdrAllocate(&_StubMsg, ");
-                write_expr(server, size_is, 1);
-                size = get_type_memsize(type);
-                fprintf(server, " * %u);\n", size);
-            }
-            else if (!is_string)
-            {
-                fprintf(server, " = &_W%u;\n", i);
-                if (var->ptr_level > 1)
-                    print_server("_W%u = 0;\n", i);
-                i++;
-            }
-
-            sep = 1;
-        }
-
-        var = PREV_LINK(var);
-    }
-
-    if (sep)
-        fprintf(server, "\n");
-}
-
-
-static void write_function_stubs(type_t *iface, unsigned int *proc_offset, unsigned int *type_offset)
+static void write_function_stubs(type_t *iface, unsigned int *proc_offset)
 {
     char *implicit_handle = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE);
     int explicit_handle = is_attr(iface->attrs, ATTR_EXPLICIT_HANDLE);
-    const func_t *func = iface->funcs;
+    const func_t *func;
     const var_t *var;
     const var_t* explicit_handle_var;
 
-    while (NEXT_LINK(func)) func = NEXT_LINK(func);
-    while (func)
+    if (!iface->funcs) return;
+    LIST_FOR_EACH_ENTRY( func, iface->funcs, const func_t, entry )
     {
         const var_t *def = func->def;
-        unsigned long buffer_size = 0;
-        unsigned int type_offset_func;
 
         /* check for a defined binding handle */
         explicit_handle_var = get_explicit_handle_var(func);
@@ -228,16 +98,8 @@
         fprintf(server, "{\n");
         indent++;
 
-        /* declare return value '_RetVal' */
-        if (!is_void(def->type, NULL))
-        {
-            print_server("");
-            write_type(server, def->type, def, def->tname);
-            fprintf(server, " _RetVal;\n");
-        }
-
         /* Declare arguments */
-        declare_args(func);
+        declare_stub_args(server, indent, func);
 
         print_server("MIDL_STUB_MESSAGE _StubMsg;\n");
         print_server("RPC_STATUS _Status;\n");
@@ -253,7 +115,7 @@
         indent--;
         fprintf(server, "\n");
 
-        write_parameters_init(func);
+        write_parameters_init(server, indent, func);
 
         if (explicit_handle_var)
         {
@@ -279,11 +141,8 @@
             indent -= 2;
             fprintf(server, "\n");
 
-            /* make a copy so we don't increment the type offset twice */
-            type_offset_func = *type_offset;
-
             /* unmarshall arguments */
-            write_remoting_arguments(server, indent, func, &type_offset_func, PASS_IN, PHASE_UNMARSHAL);
+            write_remoting_arguments(server, indent, func, PASS_IN, PHASE_UNMARSHAL);
         }
 
         print_server("if (_StubMsg.Buffer > _StubMsg.BufferEnd)\n");
@@ -304,14 +163,14 @@
         fprintf(server, "\n");
 
         /* Assign 'out' arguments */
-        assign_out_args(func);
+        assign_stub_out_args(server, indent, func);
 
         /* Call the real server function */
-        if (!is_void(def->type, NULL))
+        if (!is_void(def->type))
             print_server("_RetVal = ");
         else
             print_server("");
-        write_name(server, def);
+        write_prefix_name(server, prefix_server, def);
 
         if (func->args)
         {
@@ -319,17 +178,16 @@
 
             fprintf(server, "(\n");
             indent++;
-            var = func->args;
-            while (NEXT_LINK(var)) var = NEXT_LINK(var);
-            while (var)
+            LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
             {
                 if (first_arg)
                     first_arg = 0;
                 else
                     fprintf(server, ",\n");
                 print_server("");
+                if (var->type->declarray)
+                    fprintf(server, "*");
                 write_name(server, var);
-                var = PREV_LINK(var);
             }
             fprintf(server, ");\n");
             indent--;
@@ -339,37 +197,9 @@
             fprintf(server, "();\n");
         }
 
-        if (func->args)
-        {
-            const var_t *var = func->args;
-            while (NEXT_LINK(var)) var = NEXT_LINK(var);
-            while (var)
-            {
-                if (is_attr(var->attrs, ATTR_OUT))
-                {
-                    unsigned int alignment;
-                    buffer_size += get_required_buffer_size(var, &alignment, PASS_OUT);
-                    buffer_size += alignment;
-                }
-
-                var = PREV_LINK(var);
-            }
-        }
-
-        if (!is_void(def->type, NULL))
-        {
-            unsigned int alignment;
-            buffer_size += get_required_buffer_size(def, &alignment, PASS_RETURN);
-            buffer_size += alignment;
-        }
-
         if (has_out_arg_or_return(func))
         {
-            fprintf(server, "\n");
-            print_server("_StubMsg.BufferLength = %u;\n", buffer_size);
-
-            type_offset_func = *type_offset;
-            write_remoting_arguments(server, indent, func, &type_offset_func, PASS_OUT, PHASE_BUFFERSIZE);
+            write_remoting_arguments(server, indent, func, PASS_OUT, PHASE_BUFFERSIZE);
 
             print_server("_pRpcMessage->BufferLength = _StubMsg.BufferLength;\n");
             fprintf(server, "\n");
@@ -383,13 +213,11 @@
             fprintf(server, "\n");
         }
 
-        type_offset_func = *type_offset;
-
         /* marshall arguments */
-        write_remoting_arguments(server, indent, func, type_offset, PASS_OUT, PHASE_MARSHAL);
+        write_remoting_arguments(server, indent, func, PASS_OUT, PHASE_MARSHAL);
 
         /* marshall the return value */
-        if (!is_void(def->type, NULL))
+        if (!is_void(def->type))
             print_phase_basetype(server, indent, PHASE_MARSHAL, PASS_RETURN, def, "_RetVal");
 
         indent--;
@@ -398,7 +226,7 @@
         print_server("{\n");
         indent++;
 
-        write_remoting_arguments(server, indent, func, &type_offset_func, PASS_OUT, PHASE_FREE);
+        write_remoting_arguments(server, indent, func, PASS_OUT, PHASE_FREE);
 
         indent--;
         print_server("}\n");
@@ -415,22 +243,7 @@
         fprintf(server, "\n");
 
         /* update proc_offset */
-        if (func->args)
-        {
-            var = func->args;
-            while (NEXT_LINK(var)) var = NEXT_LINK(var);
-            while (var)
-            {
-                *proc_offset += get_size_procformatstring_var(var);
-                var = PREV_LINK(var);
-            }
-        }
-        if (!is_void(def->type, NULL))
-            *proc_offset += get_size_procformatstring_var(def);
-        else
-            *proc_offset += 2; /* FC_END and FC_PAD */
-
-        func = PREV_LINK(func);
+        *proc_offset += get_size_procformatstring_func( func );
     }
 }
 
@@ -439,13 +252,13 @@
 {
     unsigned long ver = get_attrv(iface->attrs, ATTR_VERSION);
     unsigned long method_count = 0;
-    func_t *func = iface->funcs;
+    const func_t *func;
 
     print_server("static RPC_DISPATCH_FUNCTION %s_table[] =\n", iface->name);
     print_server("{\n");
     indent++;
-    while (NEXT_LINK(func)) func = NEXT_LINK(func);
-    while (func)
+
+    if (iface->funcs) LIST_FOR_EACH_ENTRY( func, iface->funcs, const func_t, entry )
     {
         var_t *def = func->def;
 
@@ -454,7 +267,6 @@
         fprintf(server, ",\n");
 
         method_count++;
-        func = PREV_LINK(func);
     }
     print_server("0\n");
     indent--;
@@ -503,7 +315,7 @@
     print_server("0,\n");
     print_server("0x50100a4, /* MIDL Version 5.1.164 */\n");
     print_server("0,\n");
-    print_server("0,\n");
+    print_server("%s,\n", list_empty(&user_type_list) ? "0" : "UserMarshalRoutines");
     print_server("0,  /* notify & notify_flag routine table */\n");
     print_server("1,  /* Flags */\n");
     print_server("0,  /* Reserved3 */\n");
@@ -519,6 +331,9 @@
 {
     unsigned long ver = get_attrv(iface->attrs, ATTR_VERSION);
     UUID *uuid = get_attrp(iface->attrs, ATTR_UUID);
+    const str_list_t *endpoints = get_attrp(iface->attrs, ATTR_ENDPOINT);
+
+    if (endpoints) write_endpoints( server, iface->name, endpoints );
 
     print_server("extern RPC_DISPATCH_TABLE %s_v%d_%d_DispatchTable;\n", iface->name, LOWORD(ver), HIWORD(ver));
     fprintf(server, "\n");
@@ -532,8 +347,16 @@
                  uuid->Data4[7], LOWORD(ver), HIWORD(ver));
     print_server("{{0x8a885d04,0x1ceb,0x11c9,{0x9f,0xe8,0x08,0x00,0x2b,0x10,0x48,0x60}},{2,0}},\n"); /* FIXME */
     print_server("&%s_v%d_%d_DispatchTable,\n", iface->name, LOWORD(ver), HIWORD(ver));
-    print_server("0,\n");
-    print_server("0,\n");
+    if (endpoints)
+    {
+        print_server("%u,\n", list_count(endpoints));
+        print_server("(PRPC_PROTSEQ_ENDPOINT)%s__RpcProtseqEndpoint,\n", iface->name);
+    }
+    else
+    {
+        print_server("0,\n");
+        print_server("0,\n");
+    }
     print_server("0,\n");
     print_server("0,\n");
     print_server("0,\n");
@@ -543,8 +366,8 @@
         print_server("RPC_IF_HANDLE %s_ServerIfHandle = (RPC_IF_HANDLE)& %s___RpcServerInterface;\n",
                      iface->name, iface->name);
     else
-        print_server("RPC_IF_HANDLE %s_v%d_%d_s_ifspec = (RPC_IF_HANDLE)& %s___RpcServerInterface;\n",
-                     iface->name, LOWORD(ver), HIWORD(ver), iface->name);
+        print_server("RPC_IF_HANDLE %s%s_v%d_%d_s_ifspec = (RPC_IF_HANDLE)& %s___RpcServerInterface;\n",
+                     prefix_server, iface->name, LOWORD(ver), HIWORD(ver), iface->name);
     fprintf(server, "\n");
 }
 
@@ -564,17 +387,15 @@
 }
 
 
-void write_server(ifref_t *ifaces)
+void write_server(ifref_list_t *ifaces)
 {
     unsigned int proc_offset = 0;
-    unsigned int type_offset = 2;
-    ifref_t *iface = ifaces;
+    ifref_t *iface;
 
     if (!do_server)
         return;
-    if (!ifaces)
+    if (do_everything && !ifaces)
         return;
-    END_OF_LIST(iface);
 
     init_server();
     if (!server)
@@ -582,7 +403,7 @@
 
     write_formatstringsdecl(server, indent, ifaces, 0);
 
-    for (; iface; iface = PREV_LINK(iface))
+    if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, ifref_t, entry )
     {
         if (is_object(iface->iface->attrs) || is_local(iface->iface->attrs))
             continue;
@@ -599,7 +420,7 @@
             write_serverinterfacedecl(iface->iface);
             write_stubdescdecl(iface->iface);
     
-            write_function_stubs(iface->iface, &proc_offset, &type_offset);
+            write_function_stubs(iface->iface, &proc_offset);
     
             print_server("#if !defined(__RPC_WIN32__)\n");
             print_server("#error  Invalid build platform for this stub.\n");
@@ -611,6 +432,7 @@
             if (expr_eval_routines)
                 write_expr_eval_routine_list(server, iface->iface->name);
 
+            write_user_quad_list(server);
             write_stubdescriptor(iface->iface, expr_eval_routines);
             write_dispatchtable(iface->iface);
         }

Index: typegen.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/tools/widl/typegen.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- typegen.c	6 Nov 2006 14:30:41 -0000	1.1
+++ typegen.c	14 Dec 2007 20:18:50 -0000	1.2
@@ -59,8 +59,160 @@
     const expr_t *expr;
 };
 
-static size_t type_memsize(const type_t *t, int ptr_level, const expr_t *array);
-static size_t fields_memsize(const var_t *v);
+static size_t fields_memsize(const var_list_t *fields, unsigned int *align);
+static size_t write_struct_tfs(FILE *file, type_t *type, const char *name, unsigned int *tfsoff);
+static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type,
+                                const char *name, int write_ptr, unsigned int *tfsoff);
+
+const char *string_of_type(unsigned char type)
[...3372 lines suppressed...]
+            fputc( *p, f );
+        }
+        if (!*p) goto error;
+        if (p[1] != '[') goto error;
+
+        fprintf( f, "\", (const unsigned char *)\"" );
+        for (p += 2; *p && *p != ']'; p++)
+        {
+            if (*p == '"' || *p == '\\') fputc( '\\', f );
+            fputc( *p, f );
+        }
+        if (*p != ']') goto error;
+        fprintf( f, "\" },\n" );
+    }
+    print_file( f, 0, "};\n\n" );
+    return;
+
+error:
+    error("Invalid endpoint syntax '%s'\n", endpoint->str);
+}

Index: typegen.h
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/tools/widl/typegen.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- typegen.h	6 Nov 2006 14:30:41 -0000	1.1
+++ typegen.h	14 Dec 2007 20:18:50 -0000	1.2
@@ -19,6 +19,7 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#include <stdarg.h>
 
 enum pass
 {
@@ -35,16 +36,22 @@
     PHASE_FREE
 };
 
-void write_formatstringsdecl(FILE *f, int indent, ifref_t *ifaces, int for_objects);
-void write_procformatstring(FILE *file, const ifref_t *ifaces, int for_objects);
-void write_typeformatstring(FILE *file, const ifref_t *ifaces, int for_objects);
-size_t get_type_memsize(const type_t *type);
-unsigned int get_required_buffer_size(const var_t *var, unsigned int *alignment, enum pass pass);
+void write_formatstringsdecl(FILE *f, int indent, ifref_list_t *ifaces, int for_objects);
+void write_procformatstring(FILE *file, const ifref_list_t *ifaces, int for_objects);
+void write_typeformatstring(FILE *file, const ifref_list_t *ifaces, int for_objects);
 void print_phase_basetype(FILE *file, int indent, enum remoting_phase phase, enum pass pass, const var_t *var, const char *varname);
-void write_remoting_arguments(FILE *file, int indent, const func_t *func, unsigned int *type_offset, enum pass pass, enum remoting_phase phase);
+void write_remoting_arguments(FILE *file, int indent, const func_t *func, enum pass pass, enum remoting_phase phase);
 size_t get_size_procformatstring_var(const var_t *var);
-size_t get_size_typeformatstring_var(const var_t *var);
-size_t get_size_procformatstring(const ifref_t *ifaces, int for_objects);
-size_t get_size_typeformatstring(const ifref_t *ifaces, int for_objects);
+size_t get_size_procformatstring_func(const func_t *func);
+size_t get_size_procformatstring(const ifref_list_t *ifaces, int for_objects);
+size_t get_size_typeformatstring(const ifref_list_t *ifaces, int for_objects);
+void assign_stub_out_args( FILE *file, int indent, const func_t *func );
+void declare_stub_args( FILE *file, int indent, const func_t *func );
 int write_expr_eval_routines(FILE *file, const char *iface);
 void write_expr_eval_routine_list(FILE *file, const char *iface);
+void write_user_quad_list(FILE *file);
+void write_endpoints( FILE *f, const char *prefix, const str_list_t *list );
+size_t type_memsize(const type_t *t, unsigned int *align);
+int decl_indirect(const type_t *t);
+void write_parameters_init(FILE *file, int indent, const func_t *func);
+void print(FILE *file, int indent, const char *format, va_list ap);

Index: typelib.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/tools/widl/typelib.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- typelib.c	6 Nov 2006 14:30:41 -0000	1.2
+++ typelib.c	14 Dec 2007 20:18:50 -0000	1.3
@@ -69,6 +69,7 @@
   a->name = xstrdup(name);
   a->kind = TKIND_ALIAS;
   a->attrs = NULL;
+  a->declarray = FALSE;
 
   return a;
 }
@@ -82,6 +83,23 @@
       || c == RPC_FC_OP;
 }
 
+int is_array(const type_t *t)
+{
+    switch (t->type)
+    {
+    case RPC_FC_SMFARRAY:
+    case RPC_FC_LGFARRAY:
+    case RPC_FC_SMVARRAY:
+    case RPC_FC_LGVARRAY:
+    case RPC_FC_CARRAY:
+    case RPC_FC_CVARRAY:
+    case RPC_FC_BOGUS_ARRAY:
+        return TRUE;
+    default:
+        return FALSE;
+    }
+}
+
 /* List of oleauto types that should be recognized by name.
  * (most of) these seem to be intrinsic types in mktyplib. */
 
@@ -181,7 +199,11 @@
   case RPC_FC_OP:
   case RPC_FC_FP:
     if(t->ref)
+    {
+      if (match(t->ref->name, "SAFEARRAY"))
+        return VT_SAFEARRAY;
       return VT_PTR;
+    }
 
     error("get_type_vt: unknown-deref-type: %d\n", t->ref->type);
     break;
@@ -208,20 +230,7 @@
   return 0;
 }
 
-unsigned short get_var_vt(var_t *v)
-{
-  unsigned short vt;
-
-  chat("get_var_vt: %p tname %s\n", v, v->tname);
-  if (v->tname) {
-    vt = builtin_vt(v->tname);
-    if (vt) return vt;
-  }
-
-  return get_type_vt(v->type);
-}
-
-void start_typelib(char *name, attr_t *attrs)
+void start_typelib(char *name, attr_list_t *attrs)
 {
     in_typelib++;
     if (!do_typelib) return;
@@ -230,8 +239,8 @@
     typelib->name = xstrdup(name);
     typelib->filename = xstrdup(typelib_name);
     typelib->attrs = attrs;
-    typelib->entry = NULL;
-    typelib->importlibs = NULL;
+    list_init( &typelib->entries );
+    list_init( &typelib->importlibs );
 }
 
 void end_typelib(void)
@@ -251,11 +260,10 @@
     chat("add kind %i: %s\n", t->kind, t->name);
     entry = xmalloc(sizeof(*entry));
     entry->type = t;
-    LINK(entry, typelib->entry);
-    typelib->entry = entry;
+    list_add_tail( &typelib->entries, &entry->entry );
 }
 
-static void tlb_read(int fd, void *buf, size_t count)
+static void tlb_read(int fd, void *buf, int count)
 {
     if(read(fd, buf, count) < count)
         error("error while reading importlib.\n");
@@ -365,10 +373,9 @@
 
     if(!typelib) return;
 
-    for(importlib = typelib->importlibs; importlib; importlib = NEXT_LINK(importlib)) {
+    LIST_FOR_EACH_ENTRY( importlib, &typelib->importlibs, importlib_t, entry )
         if(!strcmp(name, importlib->name))
             return;
-    }
 
     chat("add_importlib: %s\n", name);
 
@@ -377,7 +384,5 @@
     importlib->name = xstrdup(name);
 
     read_importlib(importlib);
-
-    LINK(importlib, typelib->importlibs);
-    typelib->importlibs = importlib;
+    list_add_head( &typelib->importlibs, &importlib->entry );
 }

Index: typelib.h
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/tools/widl/typelib.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- typelib.h	6 Nov 2006 14:30:41 -0000	1.2
+++ typelib.h	14 Dec 2007 20:18:50 -0000	1.3
@@ -22,7 +22,7 @@
 #define __WIDL_TYPELIB_H
 
 extern int in_typelib;
-extern void start_typelib(char *name, attr_t *attrs);
+extern void start_typelib(char *name, attr_list_t *attrs);
 extern void end_typelib(void);
 extern void add_typelib_entry(type_t *t);
 extern void add_importlib(const char *name);
@@ -82,7 +82,6 @@
     VT_TYPEMASK = 0xfff
 };
 extern unsigned short get_type_vt(type_t *t);
-extern unsigned short get_var_vt(var_t *v);
 
 extern int create_msft_typelib(typelib_t *typelib);
 #endif

Index: typelib_struct.h
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/tools/widl/typelib_struct.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- typelib_struct.h	6 Nov 2006 14:30:41 -0000	1.1
+++ typelib_struct.h	14 Dec 2007 20:18:50 -0000	1.2
@@ -148,7 +148,7 @@
 /*050*/ INT     size;           /* size in bytes, at least for structures */
         /* FIXME: name of this field */
         INT     datatype1;      /* position in type description table */
-                                /* or in base intefaces */
+                                /* or in base interfaces */
                                 /* if coclass: offset in reftable */
                                 /* if interface: reference to inherited if */
         INT     datatype2;      /* for interfaces: hiword is num of inherited funcs */
@@ -286,7 +286,7 @@
                         /* 0x3800 if name is typeinfo name */
 			/* upper 16 bits are hash code */
 } MSFT_NameIntro;
-/* the custom data table directory has enties like this */
+/* the custom data table directory has entries like this */
 typedef struct {
     INT   GuidOffset;
     INT   DataOffset;

Index: utils.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/tools/widl/utils.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- utils.c	6 Nov 2006 14:30:41 -0000	1.4
+++ utils.c	14 Dec 2007 20:18:50 -0000	1.5
@@ -34,10 +34,9 @@
 #include "utils.h"
 #include "parser.h"
 
-/* #define WANT_NEAR_INDICATION */
+static const int want_near_indication = 0;
 
-#ifdef WANT_NEAR_INDICATION
-void make_print(char *str)
+static void make_print(char *str)
 {
 	while(*str)
 	{
@@ -46,13 +45,13 @@
 		str++;
 	}
 }
-#endif
 
 static void generic_msg(const char *s, const char *t, const char *n, va_list ap)
 {
 	fprintf(stderr, "%s:%d: %s: ", input_name ? input_name : "stdin", line_number, t);
 	vfprintf(stderr, s, ap);
-#ifdef WANT_NEAR_INDICATION
+
+	if (want_near_indication)
 	{
 		char *cpy;
 		if(n)
@@ -63,7 +62,7 @@
 			free(cpy);
 		}
 	}
-#endif
+
 	fprintf(stderr, "\n");
 }
 

Index: widl.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/tools/widl/widl.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- widl.c	6 Nov 2006 14:59:53 -0000	1.6
+++ widl.c	14 Dec 2007 20:18:50 -0000	1.7
@@ -22,6 +22,7 @@
 #include "config.h"
 #include "wine/port.h"
 
+#include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #ifdef HAVE_UNISTD_H
@@ -62,6 +63,9 @@
 "   --oldnames  Use old naming conventions\n"
 "   -p          Generate proxy\n"
 "   -P file     Name of proxy file (default is infile_p.c)\n"
+"   --prefix-all=p  Prefix names of client stubs / server functions with 'p'\n"
+"   --prefix-client=p  Prefix names of client stubs with 'p'\n"
+"   --prefix-server=p  Prefix names of server functions with 'p'\n"
 "   -s          Generate server stub\n"
 "   -S file     Name of server stub file (default is infile_s.c)\n"
 "   -t          Generate typelib\n"
@@ -87,7 +91,7 @@
 int parser_debug, yy_flex_debug;
 
 int pedantic = 0;
-static int do_everything = 1;
+int do_everything = 1;
 int preprocess_only = 0;
 int do_header = 0;
 int do_typelib = 0;
@@ -113,6 +117,8 @@
 char *idfile_name;
 char *idfile_token;
 char *temp_name;
+const char *prefix_client = "";
+const char *prefix_server = "";
 
 int line_number = 1;
 
@@ -122,15 +128,24 @@
 
 time_t now;
 
+enum {
+    OLDNAMES_OPTION = CHAR_MAX + 1,
+    PREFIX_ALL_OPTION,
+    PREFIX_CLIENT_OPTION,
+    PREFIX_SERVER_OPTION
+};
+
 static const char *short_options =
     "bBcC:d:D:EhH:I:NpP:sS:tT:uU:VW";
 static struct option long_options[] = {
-    { "oldnames", 0, 0, 1 },
+    { "oldnames", no_argument, 0, OLDNAMES_OPTION },
+    { "prefix-all", required_argument, 0, PREFIX_ALL_OPTION },
+    { "prefix-client", required_argument, 0, PREFIX_CLIENT_OPTION },
+    { "prefix-server", required_argument, 0, PREFIX_SERVER_OPTION },
     { 0, 0, 0, 0 }
 };
 
 static void rm_tempfile(void);
-static void segvhandler(int sig);
 
 static char *make_token(const char *name)
 {
@@ -172,7 +187,6 @@
   int ret = 0;
   int opti = 0;
 
-  signal(SIGSEGV, segvhandler);
   signal( SIGTERM, exit_on_signal );
   signal( SIGINT, exit_on_signal );
 #ifdef SIGHUP
@@ -183,9 +197,19 @@
 
   while((optc = getopt_long(argc, argv, short_options, long_options, &opti)) != EOF) {
     switch(optc) {
-    case 1:
+    case OLDNAMES_OPTION:
       old_names = 1;
       break;
+    case PREFIX_ALL_OPTION:
+      prefix_client = xstrdup(optarg);
+      prefix_server = xstrdup(optarg);
+      break;
+    case PREFIX_CLIENT_OPTION:
+      prefix_client = xstrdup(optarg);
+      break;
+    case PREFIX_SERVER_OPTION:
+      prefix_server = xstrdup(optarg);
+      break;
     case 'b':
       compat_icom = 1;
       break;
@@ -437,11 +461,3 @@
   if (server_name)
     unlink(server_name);
 }
-
-static void segvhandler(int sig)
-{
-  fprintf(stderr, "\n%s:%d: Oops, segment violation\n", input_name, line_number);
-  fflush(stdout);
-  fflush(stderr);
-  abort();
-}

Index: widl.h
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/tools/widl/widl.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- widl.h	6 Nov 2006 14:30:41 -0000	1.3
+++ widl.h	14 Dec 2007 20:18:50 -0000	1.4
@@ -36,6 +36,7 @@
 
 extern int win32;
 extern int pedantic;
+extern int do_everything;
 extern int do_header;
 extern int do_typelib;
 extern int do_proxies;
@@ -55,6 +56,8 @@
 extern char *client_token;
 extern char *server_name;
 extern char *server_token;
+extern const char *prefix_client;
+extern const char *prefix_server;
 extern time_t now;
 
 extern int line_number;
@@ -63,8 +66,8 @@
 extern FILE* header;
 extern FILE* idfile;
 
-extern void write_proxies(ifref_t *ifaces);
-extern void write_client(ifref_t *ifaces);
-extern void write_server(ifref_t *ifaces);
+extern void write_proxies(ifref_list_t *ifaces);
+extern void write_client(ifref_list_t *ifaces);
+extern void write_server(ifref_list_t *ifaces);
 
 #endif

Index: widltypes.h
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/tools/widl/widltypes.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- widltypes.h	6 Nov 2006 14:30:41 -0000	1.5
+++ widltypes.h	14 Dec 2007 20:18:50 -0000	1.6
@@ -24,6 +24,7 @@
 #include <stdarg.h>
 #include "guiddef.h"
 #include "wine/rpcfc.h"
+#include "wine-lgpl/list.h"
 
 #ifndef UUID_DEFINED
 #define UUID_DEFINED
@@ -38,30 +39,24 @@
 typedef struct _type_t type_t;
 typedef struct _typeref_t typeref_t;
 typedef struct _var_t var_t;
+typedef struct _pident_t pident_t;
 typedef struct _func_t func_t;
 typedef struct _ifref_t ifref_t;
 typedef struct _typelib_entry_t typelib_entry_t;
 typedef struct _importlib_t importlib_t;
 typedef struct _importinfo_t importinfo_t;
 typedef struct _typelib_t typelib_t;
+typedef struct _user_type_t user_type_t;
 
-#define DECL_LINK(type) \
-  type *l_next; \
-  type *l_prev
-
-#define LINK(x,y) do { x->l_next = y; x->l_prev = NULL; if (y) y->l_prev = x; } while (0)
-
-#define INIT_LINK(x) do { x->l_next = NULL; x->l_prev = NULL; } while (0)
-#define NEXT_LINK(x) ((x)->l_next)
-#define PREV_LINK(x) ((x)->l_prev)
-
-#define END_OF_LIST(list)       \
-  do {                          \
-    if (list) {                 \
-      while (NEXT_LINK(list))   \
-        list = NEXT_LINK(list); \
-    }                           \
-  } while(0)
+typedef struct list attr_list_t;
+typedef struct list str_list_t;
+typedef struct list func_list_t;
+typedef struct list expr_list_t;
+typedef struct list var_list_t;
+typedef struct list pident_list_t;
+typedef struct list ifref_list_t;
+typedef struct list array_dims_t;
+typedef struct list user_type_list_t;
 
 enum attr_type
 {
@@ -140,6 +135,7 @@
     EXPR_VOID,
     EXPR_NUM,
     EXPR_HEXNUM,
+    EXPR_DOUBLE,
     EXPR_IDENTIFIER,
     EXPR_NEG,
     EXPR_NOT,
@@ -171,7 +167,13 @@
     TKIND_UNION,
     TKIND_MAX
 };
-   
+
+struct str_list_entry_t
+{
+    char *str;
+    struct list entry;
+};
+
 struct _attr_t {
   enum attr_type type;
   union {
@@ -179,7 +181,7 @@
     void *pval;
   } u;
   /* parser-internal */
-  DECL_LINK(attr_t);
+  struct list entry;
 };
 
 struct _expr_t {
@@ -187,15 +189,16 @@
   const expr_t *ref;
   union {
     long lval;
+    double dval;
     const char *sval;
     const expr_t *ext;
-    const typeref_t *tref;
+    type_t *tref;
   } u;
   const expr_t *ext2;
   int is_const;
   long cval;
   /* parser-internal */
-  DECL_LINK(expr_t);
+  struct list entry;
 };
 
 struct _type_t {
@@ -203,58 +206,64 @@
   enum type_kind kind;
   unsigned char type;
   struct _type_t *ref;
-  const attr_t *attrs;
-  func_t *funcs;                  /* interfaces and modules */
-  var_t *fields;                  /* interfaces, structures and enumerations */
-  ifref_t *ifaces;                /* coclasses */
+  const attr_list_t *attrs;
+  func_list_t *funcs;             /* interfaces and modules */
+  var_list_t *fields;             /* interfaces, structures and enumerations */
+  ifref_list_t *ifaces;           /* coclasses */
+  unsigned long dim;              /* array dimension */
+  expr_t *size_is, *length_is;
   type_t *orig;                   /* dup'd types */
-  int ignore, is_const, sign;
-  int defined, written, user_types_registered;
+  unsigned int typestring_offset;
   int typelib_idx;
-  /* parser-internal */
-  DECL_LINK(type_t);
-};
-
-struct _typeref_t {
-  char *name;
-  type_t *ref;
-  int uniq;
+  unsigned int declarray : 1;     /* if declared as an array */
+  unsigned int ignore : 1;
+  unsigned int is_const : 1;
+  unsigned int defined : 1;
+  unsigned int written : 1;
+  unsigned int user_types_registered : 1;
+  unsigned int tfswrite : 1;   /* if the type needs to be written to the TFS */
+  int sign : 2;
 };
 
 struct _var_t {
   char *name;
-  int ptr_level;
-  expr_t *array;
   type_t *type;
-  var_t *args;  /* for function pointers */
-  const char *tname;
-  attr_t *attrs;
+  var_list_t *args;  /* for function pointers */
+  attr_list_t *attrs;
   expr_t *eval;
 
   /* parser-internal */
-  DECL_LINK(var_t);
+  struct list entry;
+};
+
+struct _pident_t {
+  var_t *var;
+  int ptr_level;
+
+  /* parser-internal */
+  struct list entry;
 };
 
 struct _func_t {
   var_t *def;
-  var_t *args;
+  var_list_t *args;
   int ignore, idx;
 
   /* parser-internal */
-  DECL_LINK(func_t);
+  struct list entry;
 };
 
 struct _ifref_t {
   type_t *iface;
-  attr_t *attrs;
+  attr_list_t *attrs;
 
   /* parser-internal */
-  DECL_LINK(ifref_t);
+  struct list entry;
 };
 
 struct _typelib_entry_t {
     type_t *type;
-    DECL_LINK(typelib_entry_t);
+    struct list entry;
 };
 
 struct _importinfo_t {
@@ -279,24 +288,35 @@
 
     int allocated;
 
-    DECL_LINK(importlib_t);
+    struct list entry;
 };
 
 struct _typelib_t {
     char *name;
     char *filename;
-    attr_t *attrs;
-    typelib_entry_t *entry;
-    importlib_t *importlibs;
+    attr_list_t *attrs;
+    struct list entries;
+    struct list importlibs;
 };
 
+struct _user_type_t {
+    struct list entry;
+    const char *name;
+};
+
+extern user_type_list_t user_type_list;
+void check_for_user_types(const var_list_t *list);
+
 void init_types(void);
 
 type_t *duptype(type_t *t, int dupname);
 type_t *alias(type_t *t, const char *name);
 
 int is_ptr(const type_t *t);
-int is_var_ptr(var_t *v);
-int cant_be_null(var_t *v);
+int is_array(const type_t *t);
+int is_var_ptr(const var_t *v);
+int cant_be_null(const var_t *v);
+int is_struct(unsigned char tc);
+int is_union(unsigned char tc);
 
 #endif

Index: write_msft.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/tools/widl/write_msft.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- write_msft.c	6 Nov 2006 14:30:41 -0000	1.1
+++ write_msft.c	14 Dec 2007 20:18:50 -0000	1.2
@@ -49,6 +49,7 @@
 #include "typelib.h"
 #include "typelib_struct.h"
 #include "utils.h"
+#include "header.h"
 #include "hash.h"
 
 enum MSFT_segment_index {
@@ -329,7 +330,6 @@
  *  safe in the slightest.
  */
 static int ctl2_encode_string(
-	msft_typelib_t *typelib,   /* [I] The typelib to operate against (not used?). */
 	const char *string,        /* [I] The string to encode. */
 	char **result)             /* [O] A pointer to a pointer to receive the encoded string. */
 {
@@ -559,7 +559,7 @@
     char *string_space;
     char *encoded_string;
 
-    length = ctl2_encode_string(typelib, string, &encoded_string);
+    length = ctl2_encode_string(string, &encoded_string);
 
     for (offset = 0; offset < typelib->typelib_segdir[MSFT_SEG_STRING].length;
 	 offset += ((((typelib->typelib_segment_data[MSFT_SEG_STRING][offset + 1] << 8) & 0xff)
@@ -633,7 +633,7 @@
     MSFT_ImpFile *importfile;
     char *encoded_string;
 
-    length = ctl2_encode_string(typelib, filename, &encoded_string);
+    length = ctl2_encode_string(filename, &encoded_string);
 
     encoded_string[0] <<= 2;
     encoded_string[0] |= 1;
@@ -716,7 +716,8 @@
     if(!name)
         return NULL;
 
-    for(importlib = typelib->typelib->importlibs; importlib; importlib = NEXT_LINK(importlib)) {
+    LIST_FOR_EACH_ENTRY( importlib, &typelib->typelib->importlibs, importlib_t, entry )
+    {
         for(i=0; i < importlib->ntypeinfos; i++) {
             if(!strcmp(name, importlib->importinfos[i].name)) {
                 chat("Found %s in importlib.\n", name);
@@ -732,6 +733,7 @@
 static void add_interface_typeinfo(msft_typelib_t *typelib, type_t *interface);
 static void add_enum_typeinfo(msft_typelib_t *typelib, type_t *enumeration);
 static void add_coclass_typeinfo(msft_typelib_t *typelib, type_t *cls);
+static void add_dispinterface_typeinfo(msft_typelib_t *typelib, type_t *dispinterface);
 
 
 /****************************************************************************
@@ -827,6 +829,7 @@
 	break;
 
     case VT_CY:
+    case VT_DATE:
 	*encoded_type = default_type;
 	*width = 8;
 	*alignment = 8;
@@ -900,14 +903,22 @@
 	*decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size;
         break;
     }
-#if 0
 
 
     case VT_SAFEARRAY:
-	/* FIXME: Make with the error checking. */
-	FIXME("SAFEARRAY vartype, may not work correctly.\n");
+	{
+	int next_vt;
 
-	ctl2_encode_typedesc(typelib, tdesc->u.lptdesc, &target_type, NULL, NULL, &child_size);
+	/* skip over SAFEARRAY type straight to element type */
+	type = type->ref;
+
+	for(next_vt = 0; type->ref; type = type->ref) {
+	    next_vt = get_type_vt(type->ref);
+	    if (next_vt != 0)
+	        break;
+	}
+
+	encode_type(typelib, next_vt, type->ref, &target_type, NULL, NULL, &child_size);
 
 	for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
 	    typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
@@ -931,16 +942,15 @@
 	    typedata[1] = target_type;
 	}
 
-	*encoded_tdesc = typeoffset;
+	*encoded_type = typeoffset;
 
 	*width = 4;
 	*alignment = 4;
-	*decoded_size = sizeof(TYPEDESC) + child_size;
+	*decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size;
 	break;
+	}
 
 
-#endif
-
     case VT_USERDEFINED:
       {
         int typeinfo_offset;
@@ -972,6 +982,8 @@
             case 0:
                 if (type->kind == TKIND_COCLASS)
                     add_coclass_typeinfo(typelib, type);
+                else if (type->kind == TKIND_DISPATCH)
+                    add_dispinterface_typeinfo(typelib, type);
                 else
                     error("encode_type: VT_USERDEFINED - can't yet add typedef's on the fly\n");
                 break;
@@ -1037,7 +1049,8 @@
 
 static int encode_var(
 	msft_typelib_t *typelib,   /* [I] The type library in which to encode the TYPEDESC. */
-	var_t *var,                /* [I] The type description to encode. */
+	type_t *type,              /* [I] The type description to encode. */
+	var_t *var,                /* [I] The var to encode. */
 	int *encoded_type,         /* [O] The encoded type description. */
 	int *width,                /* [O] The width of the type, or NULL. */
 	int *alignment,            /* [O] The alignment of the type, or NULL. */
@@ -1049,19 +1062,57 @@
     int child_size;
     int vt;
     int scratch;
-    type_t *type;
 
     if (!width) width = &scratch;
     if (!alignment) alignment = &scratch;
     if (!decoded_size) decoded_size = &scratch;
     *decoded_size = 0;
 
-    chat("encode_var: var %p var->tname %s var->type %p var->ptr_level %d var->type->ref %p\n", var, var->tname, var->type, var->ptr_level, var->type->ref);
-    if(var->ptr_level) {
-        int skip_ptr;
-        var->ptr_level--;
-	skip_ptr = encode_var(typelib, var, &target_type, NULL, NULL, &child_size);
-        var->ptr_level++;
+    chat("encode_var: var %p type %p type->name %s type->ref %p\n",
+         var, type, type->name ? type->name : "NULL", type->ref);
+
+    if (type->declarray) {
+        int num_dims, elements = 1, arrayoffset;
+        type_t *atype;
+        int *arraydata;
+
+        num_dims = 0;
+        for (atype = type; atype->declarray; atype = atype->ref)
+            ++num_dims;
+
+        chat("array with %d dimensions\n", num_dims);
+        encode_var(typelib, atype, var, &target_type, width, alignment, NULL);
+        arrayoffset = ctl2_alloc_segment(typelib, MSFT_SEG_ARRAYDESC, (2 + 2 * num_dims) * sizeof(long), 0);
+        arraydata = (void *)&typelib->typelib_segment_data[MSFT_SEG_ARRAYDESC][arrayoffset];
+
+        arraydata[0] = target_type;
+        arraydata[1] = num_dims;
+        arraydata[1] |= ((num_dims * 2 * sizeof(long)) << 16);
+
+        arraydata += 2;
+        for (atype = type; atype->declarray; atype = atype->ref)
+        {
+            arraydata[0] = atype->dim;
+            arraydata[1] = 0;
+            arraydata += 2;
+            elements *= atype->dim;
+        }
+
+        typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
+        typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
+
+        typedata[0] = (0x7ffe << 16) | VT_CARRAY;
+        typedata[1] = arrayoffset;
+
+        *encoded_type = typeoffset;
+        *width = *width * elements;
+        *decoded_size = 20 /*sizeof(ARRAYDESC)*/ + (num_dims - 1) * 8 /*sizeof(SAFEARRAYBOUND)*/;
+        return 0;
+    }
+
+    vt = get_type_vt(type);
+    if (vt == VT_PTR) {
+        int skip_ptr = encode_var(typelib, type->ref, var, &target_type, NULL, NULL, &child_size);
 
         if(skip_ptr == 2) {
             chat("encode_var: skipping ptr\n");
@@ -1102,65 +1153,27 @@
         return 0;
     }
 
-    if(var->array) {
-        expr_t *dim = var->array;
-        expr_t *array_save;
-        int num_dims = 1, elements = 1, arrayoffset;
-        int *arraydata;
-
-        while(NEXT_LINK(dim)) {
-            dim = NEXT_LINK(dim);
-            num_dims++;
-        }
-        chat("array with %d dimensions\n", num_dims);
-        array_save = var->array;
-        var->array = NULL;
-	encode_var(typelib, var, &target_type, width, alignment, NULL);
-        var->array = array_save;
-	arrayoffset = ctl2_alloc_segment(typelib, MSFT_SEG_ARRAYDESC, (2 + 2 * num_dims) * sizeof(long), 0);
-	arraydata = (void *)&typelib->typelib_segment_data[MSFT_SEG_ARRAYDESC][arrayoffset];
-
-	arraydata[0] = target_type;
-        arraydata[1] = num_dims;
-        arraydata[1] |= ((num_dims * 2 * sizeof(long)) << 16);
-
-        arraydata += 2;
-        while(dim) {
-            arraydata[0] = dim->cval;
-            arraydata[1] = 0;
-            arraydata += 2;
-            elements *= dim->cval;
-            dim = PREV_LINK(dim);
-        }
-
-	typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
-	typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
-
-	typedata[0] = (0x7ffe << 16) | VT_CARRAY;
-	typedata[1] = arrayoffset;
-
-	*encoded_type = typeoffset;
-	*width = *width * elements;
-	*decoded_size = 20 /*sizeof(ARRAYDESC)*/ + (num_dims - 1) * 8 /*sizeof(SAFEARRAYBOUND)*/;
-        return 0;
-    }
-    dump_type(var->type);
+    dump_type(type);
 
-    vt = get_var_vt(var);
-    type = var->type;
-    while(!vt) {
-        if(type->ref == NULL) {
-            vt = VT_VOID;
-            break;
-        }
-        type = type->ref;
-        vt = get_type_vt(type);
-    }
     encode_type(typelib, vt, type, encoded_type, width, alignment, decoded_size);
     if(type->type == RPC_FC_IP) return 2;
     return 0;
 }
 
+static unsigned long get_ulong_val(unsigned long val, int vt)
+{
+    switch(vt) {
+    case VT_I2:
+    case VT_BOOL:
+    case VT_UI2:
+        return val & 0xffff;
+    case VT_I1:
+    case VT_UI1:
+        return val & 0xff;
+    }
+
+    return val;
+}
 
 static void write_value(msft_typelib_t* typelib, int *out, int vt, void *value)
 {
@@ -1176,12 +1189,13 @@
     case VT_INT:
     case VT_UINT:
     case VT_HRESULT:
+    case VT_PTR:
       {
-        unsigned long *lv = value;
-        if((*lv & 0x3ffffff) == *lv) {
+        const unsigned long lv = get_ulong_val(*(unsigned long*)value, vt);
+        if((lv & 0x3ffffff) == lv) {
             *out = 0x80000000;
             *out |= vt << 26;
-            *out |= *lv;
+            *out |= lv;
         } else {
             int offset = ctl2_alloc_segment(typelib, MSFT_SEG_CUSTDATA, 8, 0);
             *((unsigned short *)&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset]) = vt;
@@ -1242,14 +1256,14 @@
     return S_OK;
 }
 
-static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, func_t *func, int index)
+static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, const func_t *func, int index)
 {
     int offset, name_offset;
     int *typedata, typedata_size;
     int i, id, next_idx;
     int decoded_size, extra_attr = 0;
-    int num_params = 0, num_defaults = 0;
-    var_t *arg, *last_arg = NULL;
+    int num_params = 0, num_optional = 0, num_defaults = 0;
+    var_t *arg;
     char *namedata;
     const attr_t *attr;
     unsigned int funcflags = 0, callconv = 4 /* CC_STDCALL */;
@@ -1273,31 +1287,36 @@
         break;
     }
 
-    for(attr = func->def->attrs; attr; attr = NEXT_LINK(attr)) {
-        if(attr->type == ATTR_LOCAL) {
-            chat("add_func_desc: skipping local function\n");
-            return S_FALSE;
-        }
+    if (is_local( func->def->attrs )) {
+        chat("add_func_desc: skipping local function\n");
+        return S_FALSE;
     }
 
-    for(arg = func->args; arg; arg = NEXT_LINK(arg)) {
-        last_arg = arg;
+    if (func->args)
+      LIST_FOR_EACH_ENTRY( arg, func->args, var_t, entry )
+      {
         num_params++;
-        for(attr = arg->attrs; attr; attr = NEXT_LINK(attr)) {
-            if(attr->type == ATTR_DEFAULTVALUE_EXPR || attr->type == ATTR_DEFAULTVALUE_STRING) {
+        if (arg->attrs) LIST_FOR_EACH_ENTRY( attr, arg->attrs, const attr_t, entry ) {
+            if(attr->type == ATTR_DEFAULTVALUE_EXPR || attr->type == ATTR_DEFAULTVALUE_STRING)
                 num_defaults++;
-                break;
-            }
+            else if(attr->type == ATTR_OPTIONAL)
+                num_optional++;
         }
-    }
+      }
 
     chat("add_func_desc: num of params %d\n", num_params);
 
     name_offset = ctl2_alloc_name(typeinfo->typelib, func->def->name);
 
-    for(attr = func->def->attrs; attr; attr = NEXT_LINK(attr)) {
-        expr_t *expr = attr->u.pval; 
+    if (func->def->attrs) LIST_FOR_EACH_ENTRY( attr, func->def->attrs, const attr_t, entry ) {
+        expr_t *expr = attr->u.pval;
         switch(attr->type) {
+        case ATTR_BINDABLE:
+            funcflags |= 0x4; /* FUNCFLAG_BINDABLE */
+            break;
+        case ATTR_DISPLAYBIND:
+            funcflags |= 0x10; /* FUNCFLAG_DISPLAYBIND */
+            break;
         case ATTR_ENTRY_ORDINAL:
             extra_attr = max(extra_attr, 3);
             entry = expr->cval;
@@ -1325,6 +1344,9 @@
         case ATTR_ID:
             id = expr->cval;
             break;
+        case ATTR_NONBROWSABLE:
+            funcflags |= 0x400; /* FUNCFLAG_NONBROWSABLE */
+            break;
         case ATTR_OUT:
             break;
         case ATTR_PROPGET:
@@ -1339,8 +1361,11 @@
         case ATTR_RESTRICTED:
             funcflags |= 0x1; /* FUNCFLAG_FRESTRICTED */
             break;
-        case ATTR_BINDABLE:
-            funcflags |= 0x4; /* FUNCFLAG_BINDABLE */
+        case ATTR_VARARG:
+            if (num_optional || num_defaults)
+                warning("add_func_desc: ignoring vararg in function with optional or defaultvalue params\n");
+            else
+                num_optional = -1;
             break;
         default:
             warning("add_func_desc: ignoring attr %d\n", attr->type);
@@ -1348,25 +1373,6 @@
         }
     }
 
-    switch(invokekind) {
-    case 0x2: /* INVOKE_PROPERTYGET */
-        if((num_params != 0 && typeinfo->typekind == TKIND_DISPATCH)
-           || (num_params != 1 && typeinfo->typekind == TKIND_INTERFACE)) {
-            error("expecting no args on a propget func\n");
-            return S_FALSE;
-        }
-        break;
-    case 0x4: /* INVOKE_PROPERTYPUT */
-    case 0x8: /* INVOKE_PROPERTYPUTREF */
-        if(num_params != 1) {
-            error("expecting one arg on a propput func\n");
-            return S_FALSE;
-        }
-        break;
-    default:
-        break;
-    }
-
     /* allocate type data space for us */
     typedata_size = 0x18 + extra_attr * sizeof(int) + (num_params * (num_defaults ? 16 : 12));
 
@@ -1408,13 +1414,13 @@
 
     /* fill out the basic type information */
     typedata[0] = typedata_size | (index << 16);
-    encode_var(typeinfo->typelib, func->def, &typedata[1], NULL, NULL, &decoded_size);
+    encode_var(typeinfo->typelib, func->def->type, func->def, &typedata[1], NULL, NULL, &decoded_size);
     typedata[2] = funcflags;
     typedata[3] = ((52 /*sizeof(FUNCDESC)*/ + decoded_size) << 16) | typeinfo->typeinfo->cbSizeVft;
     typedata[4] = (next_idx << 16) | (callconv << 8) | (invokekind << 3) | funckind;
     if(num_defaults) typedata[4] |= 0x1000;
     if(entry_is_ord) typedata[4] |= 0x2000;
-    typedata[5] = num_params;
+    typedata[5] = (num_optional << 16) | num_params;
 
     /* NOTE: High word of typedata[3] is total size of FUNCDESC + size of all ELEMDESCs for params + TYPEDESCs for pointer params and return types. */
     /* That is, total memory allocation required to reconstitute the FUNCDESC in its entirety. */
@@ -1434,7 +1440,11 @@
         warning("unknown number of optional attrs\n");
     }
 
-    for (arg = last_arg, i = 0; arg; arg = PREV_LINK(arg), i++) {
+    if (func->args)
+    {
+      i = 0;
+      LIST_FOR_EACH_ENTRY( arg, func->args, var_t, entry )
+      {
         const attr_t *attr;
         int paramflags = 0;
         int *paramdata = typedata + 6 + extra_attr + (num_defaults ? num_params : 0) + i * 3;
@@ -1442,8 +1452,8 @@
 
         if(defaultdata) *defaultdata = -1;
 
-	encode_var(typeinfo->typelib, arg, paramdata, NULL, NULL, &decoded_size);
-        for(attr = arg->attrs; attr; attr = NEXT_LINK(attr)) {
+	encode_var(typeinfo->typelib, arg->type, arg, paramdata, NULL, NULL, &decoded_size);
+        if (arg->attrs) LIST_FOR_EACH_ENTRY( attr, arg->attrs, const attr_t, entry ) {
             switch(attr->type) {
             case ATTR_DEFAULTVALUE_EXPR:
               {
@@ -1452,7 +1462,7 @@
                 if (arg->type->type == RPC_FC_ENUM16)
                     vt = VT_INT;
                 else
-                    vt = get_var_vt(arg);
+                    vt = get_type_vt(arg->type);
                 paramflags |= 0x30; /* PARAMFLAG_FHASDEFAULT | PARAMFLAG_FOPT */
                 chat("default value %ld\n", expr->cval);
                 write_value(typeinfo->typelib, defaultdata, vt, &expr->cval);
@@ -1465,7 +1475,7 @@
                 if (arg->type->type == RPC_FC_ENUM16)
                   vt = VT_INT;
                 else
-                  vt = get_var_vt(arg);
+                  vt = get_type_vt(arg->type);
                 paramflags |= 0x30; /* PARAMFLAG_FHASDEFAULT | PARAMFLAG_FOPT */
                 chat("default value '%s'\n", s);
                 write_value(typeinfo->typelib, defaultdata, vt, s);
@@ -1492,6 +1502,8 @@
 	paramdata[1] = -1;
 	paramdata[2] = paramflags;
 	typedata[3] += decoded_size << 16;
+        i++;
+      }
     }
 
     if(typeinfo->funcs_allocated == 0) {
@@ -1540,12 +1552,19 @@
     if(typeinfo->typekind == TKIND_MODULE)
         namedata[9] |= 0x20;
 
-    if(invokekind != 0x4 /* INVOKE_PROPERTYPUT */ && invokekind != 0x8 /* INVOKE_PROPERTYPUTREF */) { 
-        /* don't give the arg of a [propput*] func a name */
-        for (arg = last_arg, i = 0; arg; arg = PREV_LINK(arg), i++) {
-            int *paramdata = typedata + 6 + extra_attr + (num_defaults ? num_params : 0) + i * 3;
-            offset = ctl2_alloc_name(typeinfo->typelib, arg->name);
-            paramdata[1] = offset;
+    if (func->args)
+    {
+        i = 0;
+        LIST_FOR_EACH_ENTRY( arg, func->args, var_t, entry )
+        {
+            /* don't give the last arg of a [propput*] func a name */
+            if(i != num_params - 1 || (invokekind != 0x4 /* INVOKE_PROPERTYPUT */ && invokekind != 0x8 /* INVOKE_PROPERTYPUTREF */))
+            {
+                int *paramdata = typedata + 6 + extra_attr + (num_defaults ? num_params : 0) + i * 3;
+                offset = ctl2_alloc_name(typeinfo->typelib, arg->name);
+                paramdata[1] = offset;
+            }
+            i++;
         }
     }
     return S_OK;
@@ -1565,12 +1584,12 @@
     char *namedata;
     int var_num = (typeinfo->typeinfo->cElement >> 16) & 0xffff;
 
-    chat("add_var_desc(%d,%s) array %p\n", index, var->name, var->array);
+    chat("add_var_desc(%d, %s)\n", index, var->name);
 
     id = 0x40000000 + index;
 
-    for(attr = var->attrs; attr; attr = NEXT_LINK(attr)) {
-        expr_t *expr = attr->u.pval; 
+    if (var->attrs) LIST_FOR_EACH_ENTRY( attr, var->attrs, const attr_t, entry ) {
+        expr_t *expr = attr->u.pval;
         switch(attr->type) {
         case ATTR_HIDDEN:
             varflags |= 0x40; /* VARFLAG_FHIDDEN */
@@ -1635,7 +1654,7 @@
     typeinfo->var_offsets[var_num] = offset;
 
     /* figure out type widths and whatnot */
-    encode_var(typeinfo->typelib, var, &typedata[1], &var_datawidth,
+    encode_var(typeinfo->typelib, var->type, var, &typedata[1], &var_datawidth,
                &var_alignment, &var_type_size);
 
     /* pad out starting position to data width */
@@ -1728,8 +1747,9 @@
 }
 
 static msft_typeinfo_t *create_msft_typeinfo(msft_typelib_t *typelib, enum type_kind kind,
-                                             const char *name, const attr_t *attr, int idx)
+                                             const char *name, const attr_list_t *attrs)
 {
+    const attr_t *attr;
     msft_typeinfo_t *msft_typeinfo;
     int nameoffset;
     int typeinfo_offset;
@@ -1758,7 +1778,7 @@
     if(kind == TKIND_COCLASS)
         typeinfo->flags |= 0x2; /* TYPEFLAG_FCANCREATE */
 
-    for( ; attr; attr = NEXT_LINK(attr)) {
+    if (attrs) LIST_FOR_EACH_ENTRY( attr, attrs, const attr_t, entry ) {
         switch(attr->type) {
         case ATTR_AGGREGATABLE:
             if (kind == TKIND_COCLASS)
@@ -1895,9 +1915,9 @@
 }
 
 static void add_dispinterface_typeinfo(msft_typelib_t *typelib, type_t *dispinterface)
-{ 
+{
     int idx = 0;
-    func_t *func;
+    const func_t *func;
     var_t *var;
     msft_typeinfo_t *msft_typeinfo;
 
@@ -1906,7 +1926,7 @@
 
     dispinterface->typelib_idx = typelib->typelib_header.nrtypeinfos;
     msft_typeinfo = create_msft_typeinfo(typelib, TKIND_DISPATCH, dispinterface->name,
-                                         dispinterface->attrs, typelib->typelib_header.nrtypeinfos);
+                                         dispinterface->attrs);
 
     msft_typeinfo->typeinfo->size = 4;
     msft_typeinfo->typeinfo->typekind |= 0x2100;
@@ -1915,50 +1935,38 @@
     add_dispatch(typelib);
     msft_typeinfo->typeinfo->cImplTypes = 1;
 
-    /* count the no of funcs, as the variable indicies come after the funcs */
-    if((func = dispinterface->funcs)) {
-        idx++;
-        while(NEXT_LINK(func)) {
-            func = NEXT_LINK(func);
-            idx++;
-        }
-    }
+    /* count the no of funcs, as the variable indices come after the funcs */
+    if (dispinterface->funcs)
+        LIST_FOR_EACH_ENTRY( func, dispinterface->funcs, const func_t, entry ) idx++;
 
-    if((var = dispinterface->fields)) {
-        while(NEXT_LINK(var)) var = NEXT_LINK(var);
-        while(var) {
-            add_var_desc(msft_typeinfo, idx, var);
-            idx++;
-            var = PREV_LINK(var);
-        }
-    }
+    if (dispinterface->fields)
+        LIST_FOR_EACH_ENTRY( var, dispinterface->fields, var_t, entry )
+            add_var_desc(msft_typeinfo, idx++, var);
 
-    idx = 0;
-    /* the func count above has already left us pointing at the first func */
-    while(func) {
-        if(add_func_desc(msft_typeinfo, func, idx) == S_OK)
-            idx++;
-        func = PREV_LINK(func);
+    if (dispinterface->funcs)
+    {
+        idx = 0;
+        LIST_FOR_EACH_ENTRY( func, dispinterface->funcs, const func_t, entry )
+            if(add_func_desc(msft_typeinfo, func, idx) == S_OK)
+                idx++;
     }
 }
 
 static void add_interface_typeinfo(msft_typelib_t *typelib, type_t *interface)
 {
     int idx = 0;
-    func_t *func;
+    const func_t *func;
     type_t *ref;
     msft_typeinfo_t *msft_typeinfo;
     importinfo_t *ref_importinfo = NULL;
     int num_parents = 0, num_funcs = 0;
-    const attr_t *attr;
     const type_t *derived;
 
     if (-1 < interface->typelib_idx)
         return;
 
-    for(attr = interface->attrs; attr; attr = NEXT_LINK(attr))
-        if(attr->type == ATTR_DISPINTERFACE)
-            return add_dispinterface_typeinfo(typelib, interface);
+    if (is_attr(interface->attrs, ATTR_DISPINTERFACE))
+        return add_dispinterface_typeinfo(typelib, interface);
 
     /* midl adds the parent interface first, unless the parent itself
        has no parent (i.e. it stops before IUnknown). */
@@ -1971,8 +1979,7 @@
     }
 
     interface->typelib_idx = typelib->typelib_header.nrtypeinfos;
-    msft_typeinfo = create_msft_typeinfo(typelib, TKIND_INTERFACE, interface->name, interface->attrs,
-                                         typelib->typelib_header.nrtypeinfos);
+    msft_typeinfo = create_msft_typeinfo(typelib, TKIND_INTERFACE, interface->name, interface->attrs);
     msft_typeinfo->typeinfo->size = 4;
     msft_typeinfo->typeinfo->typekind |= 0x2200;
 
@@ -1990,67 +1997,50 @@
     /* count the number of inherited interfaces and non-local functions */
     for(ref = interface->ref; ref; ref = ref->ref) {
         num_parents++;
-        for(func = ref->funcs; func; func = NEXT_LINK(func)) {
-            const attr_t *attr;
-            for(attr = func->def->attrs; attr; attr = NEXT_LINK(attr))
-                if(attr->type == ATTR_LOCAL)
-                    break;
-            if(!attr)
-                num_funcs++;
-        }
+        if (ref->funcs)
+            LIST_FOR_EACH_ENTRY( func, ref->funcs, const func_t, entry )
+                if (!is_local(func->def->attrs)) num_funcs++;
     }
     msft_typeinfo->typeinfo->datatype2 = num_funcs << 16 | num_parents;
     msft_typeinfo->typeinfo->cbSizeVft = num_funcs * 4;
 
-    if((func = interface->funcs)) {
-        while(NEXT_LINK(func)) func = NEXT_LINK(func);
-        while(func) {
+    if (interface->funcs)
+        LIST_FOR_EACH_ENTRY( func, interface->funcs, const func_t, entry )
             if(add_func_desc(msft_typeinfo, func, idx) == S_OK)
                 idx++;
-            func = PREV_LINK(func);
-        }
-    }
 }
 
 static void add_structure_typeinfo(msft_typelib_t *typelib, type_t *structure)
 {
     int idx = 0;
-    var_t *cur = structure->fields;
+    var_t *cur;
     msft_typeinfo_t *msft_typeinfo;
 
     if (-1 < structure->typelib_idx)
         return;
 
     structure->typelib_idx = typelib->typelib_header.nrtypeinfos;
-    msft_typeinfo = create_msft_typeinfo(typelib, TKIND_RECORD, structure->name, structure->attrs,
-                                         typelib->typelib_header.nrtypeinfos);
+    msft_typeinfo = create_msft_typeinfo(typelib, TKIND_RECORD, structure->name, structure->attrs);
     msft_typeinfo->typeinfo->size = 0;
 
-    while(NEXT_LINK(cur)) cur = NEXT_LINK(cur);
-    while(cur) {
-        add_var_desc(msft_typeinfo, idx, cur);
-        idx++;
-        cur = PREV_LINK(cur);
-    }
+    if (structure->fields)
+        LIST_FOR_EACH_ENTRY( cur, structure->fields, var_t, entry )
+            add_var_desc(msft_typeinfo, idx++, cur);
 }
 
 static void add_enum_typeinfo(msft_typelib_t *typelib, type_t *enumeration)
 {
     int idx = 0;
-    var_t *cur = enumeration->fields;
+    var_t *cur;
     msft_typeinfo_t *msft_typeinfo;
 
     enumeration->typelib_idx = typelib->typelib_header.nrtypeinfos;
-    msft_typeinfo = create_msft_typeinfo(typelib, TKIND_ENUM, enumeration->name, enumeration->attrs,
-                                         typelib->typelib_header.nrtypeinfos);
+    msft_typeinfo = create_msft_typeinfo(typelib, TKIND_ENUM, enumeration->name, enumeration->attrs);
     msft_typeinfo->typeinfo->size = 0;
 
-    while(NEXT_LINK(cur)) cur = NEXT_LINK(cur);
-    while(cur) {
-        add_var_desc(msft_typeinfo, idx, cur);
-        idx++;
-        cur = PREV_LINK(cur);
-    }
+    if (enumeration->fields)
+        LIST_FOR_EACH_ENTRY( cur, enumeration->fields, var_t, entry )
+            add_var_desc(msft_typeinfo, idx++, cur);
 }
 
 static void add_typedef_typeinfo(msft_typelib_t *typelib, type_t *tdef)
@@ -2062,8 +2052,7 @@
         return;
 
     tdef->typelib_idx = typelib->typelib_header.nrtypeinfos;
-    msft_typeinfo = create_msft_typeinfo(typelib, TKIND_ALIAS, tdef->name, tdef->attrs,
-                                         typelib->typelib_header.nrtypeinfos);
+    msft_typeinfo = create_msft_typeinfo(typelib, TKIND_ALIAS, tdef->name, tdef->attrs);
     encode_type(typelib, get_type_vt(tdef->orig), tdef->orig, &msft_typeinfo->typeinfo->datatype1, &msft_typeinfo->typeinfo->size,
                &alignment, &msft_typeinfo->typeinfo->datatype2);
     msft_typeinfo->typeinfo->typekind |= (alignment << 11 | alignment << 6);
@@ -2082,20 +2071,15 @@
         return;
 
     cls->typelib_idx = typelib->typelib_header.nrtypeinfos;
-    msft_typeinfo = create_msft_typeinfo(typelib, TKIND_COCLASS, cls->name, cls->attrs,
-                                         typelib->typelib_header.nrtypeinfos);
+    msft_typeinfo = create_msft_typeinfo(typelib, TKIND_COCLASS, cls->name, cls->attrs);
 
-    if((iref = cls->ifaces)) {
-        num_ifaces++;
-        while(NEXT_LINK(iref)) {
-            iref = NEXT_LINK(iref);
-            num_ifaces++;
-        }
-    }
+    if (cls->ifaces) LIST_FOR_EACH_ENTRY( iref, cls->ifaces, ifref_t, entry ) num_ifaces++;
 
     offset = msft_typeinfo->typeinfo->datatype1 = ctl2_alloc_segment(typelib, MSFT_SEG_REFERENCES,
                                                                      num_ifaces * sizeof(*ref), 0);
-    for(i = 0; i < num_ifaces; i++) {
+
+    i = 0;
+    if (cls->ifaces) LIST_FOR_EACH_ENTRY( iref, cls->ifaces, ifref_t, entry ) {
         if(iref->iface->typelib_idx == -1)
             add_interface_typeinfo(typelib, iref->iface);
         ref = (MSFT_RefRecord*) (typelib->typelib_segment_data[MSFT_SEG_REFERENCES] + offset + i * sizeof(*ref));
@@ -2106,7 +2090,7 @@
         if(i < num_ifaces - 1)
             ref->onext = offset + (i + 1) * sizeof(*ref);
 
-        for(attr = iref->attrs; attr; attr = NEXT_LINK(attr)) {
+        if (iref->attrs) LIST_FOR_EACH_ENTRY( attr, iref->attrs, const attr_t, entry ) {
             switch(attr->type) {
             case ATTR_DEFAULT:
                 ref->flags |= 0x1; /* IMPLTYPEFLAG_FDEFAULT */
@@ -2138,7 +2122,7 @@
             else if(!first)
                 first = ref;
         }
-        iref = PREV_LINK(iref);
+        i++;
     }
 
     /* If we haven't had a default interface, then set the default flags on the
@@ -2156,25 +2140,21 @@
 static void add_module_typeinfo(msft_typelib_t *typelib, type_t *module)
 {
     int idx = 0;
-    func_t *func;
+    const func_t *func;
     msft_typeinfo_t *msft_typeinfo;
 
     if (-1 < module->typelib_idx)
         return;
 
     module->typelib_idx = typelib->typelib_header.nrtypeinfos;
-    msft_typeinfo = create_msft_typeinfo(typelib, TKIND_MODULE, module->name, module->attrs,
-                                         typelib->typelib_header.nrtypeinfos);
+    msft_typeinfo = create_msft_typeinfo(typelib, TKIND_MODULE, module->name, module->attrs);
     msft_typeinfo->typeinfo->typekind |= 0x0a00;
 
-    if((func = module->funcs)) {
-        while(NEXT_LINK(func)) func = NEXT_LINK(func);
-        while(func) {
+    if (module->funcs)
+        LIST_FOR_EACH_ENTRY( func, module->funcs, const func_t, entry )
             if(add_func_desc(msft_typeinfo, func, idx) == S_OK)
                 idx++;
-            func = PREV_LINK(func);
-        }
-    }
+
     msft_typeinfo->typeinfo->size = idx;
 }
 
@@ -2224,34 +2204,22 @@
 
 static void set_version(msft_typelib_t *typelib)
 {
-    long version = MAKELONG(0,0);
-    const attr_t *attr;
-
-    for(attr = typelib->typelib->attrs; attr; attr = NEXT_LINK(attr)) {
-        if(attr->type == ATTR_VERSION) {
-            version = attr->u.ival;
-        }
-    }
-    typelib->typelib_header.version = version;
-    return;
+    typelib->typelib_header.version = get_attrv( typelib->typelib->attrs, ATTR_VERSION );
 }
 
 static void set_guid(msft_typelib_t *typelib)
 {
     MSFT_GuidEntry guidentry;
     int offset;
-    const attr_t *attr;
+    void *ptr;
     GUID guid = {0,0,0,{0,0,0,0,0,0}};
 
     guidentry.guid = guid;
     guidentry.hreftype = -2;
     guidentry.next_hash = -1;
 
-    for(attr = typelib->typelib->attrs; attr; attr = NEXT_LINK(attr)) {
-        if(attr->type == ATTR_UUID) {
-            guidentry.guid = *(GUID*)(attr->u.pval);
-        }
-    }
+    ptr = get_attrp( typelib->typelib->attrs, ATTR_UUID );
+    if (ptr) guidentry.guid = *(GUID *)ptr;
 
     offset = ctl2_alloc_guid(typelib, &guidentry);
     typelib->typelib_header.posguid = offset;
@@ -2261,71 +2229,55 @@
 
 static void set_doc_string(msft_typelib_t *typelib)
 {
-    const attr_t *attr;
-    int offset;
+    char *str = get_attrp( typelib->typelib->attrs, ATTR_HELPSTRING );
 
-    for(attr = typelib->typelib->attrs; attr; attr = NEXT_LINK(attr)) {
-        if(attr->type == ATTR_HELPSTRING) {
-            offset = ctl2_alloc_string(typelib, attr->u.pval);
-            if (offset == -1) return;
-            typelib->typelib_header.helpstring = offset;
-        }
+    if (str)
+    {
+        int offset = ctl2_alloc_string(typelib, str);
+        if (offset != -1) typelib->typelib_header.helpstring = offset;
     }
-    return;
 }
 
 static void set_help_file_name(msft_typelib_t *typelib)
 {
-    int offset;
-    const attr_t *attr;
-    for(attr = typelib->typelib->attrs; attr; attr = NEXT_LINK(attr)) {
-        if(attr->type == ATTR_HELPFILE) {
-            offset = ctl2_alloc_string(typelib, attr->u.pval);
-            if (offset == -1) return;
+    char *str = get_attrp( typelib->typelib->attrs, ATTR_HELPFILE );
+
+    if (str)
+    {
+        int offset = ctl2_alloc_string(typelib, str);
+        if (offset != -1)
+        {
             typelib->typelib_header.helpfile = offset;
             typelib->typelib_header.varflags |= 0x10;
         }
     }
-    return;
 }
 
 static void set_help_context(msft_typelib_t *typelib)
 {
-    const attr_t *attr;
-    for(attr = typelib->typelib->attrs; attr; attr = NEXT_LINK(attr)) {
-        if(attr->type == ATTR_HELPCONTEXT) {
-            const expr_t *expr = (expr_t *)attr->u.pval;
-            typelib->typelib_header.helpcontext = expr->cval;
-        }
-    }
-    return;
+    const expr_t *expr = get_attrp( typelib->typelib->attrs, ATTR_HELPCONTEXT );
+    if (expr) typelib->typelib_header.helpcontext = expr->cval;
 }
 
 static void set_help_string_dll(msft_typelib_t *typelib)
 {
-    int offset;
-    const attr_t *attr;
-    for(attr = typelib->typelib->attrs; attr; attr = NEXT_LINK(attr)) {
-        if(attr->type == ATTR_HELPSTRINGDLL) {
-            offset = ctl2_alloc_string(typelib, attr->u.pval);
-            if (offset == -1) return;
+    char *str = get_attrp( typelib->typelib->attrs, ATTR_HELPSTRINGDLL );
+
+    if (str)
+    {
+        int offset = ctl2_alloc_string(typelib, str);
+        if (offset != -1)
+        {
             typelib->help_string_dll_offset = offset;
             typelib->typelib_header.varflags |= 0x100;
         }
     }
-    return;
 }
 
 static void set_help_string_context(msft_typelib_t *typelib)
 {
-    const attr_t *attr;
-    for(attr = typelib->typelib->attrs; attr; attr = NEXT_LINK(attr)) {
-        if(attr->type == ATTR_HELPSTRINGCONTEXT) {
-            const expr_t *expr = (expr_t *)attr->u.pval;
-            typelib->typelib_header.helpstringcontext = expr->cval;
-        }
-    }
-    return;
+    const expr_t *expr = get_attrp( typelib->typelib->attrs, ATTR_HELPSTRINGCONTEXT );
+    if (expr) typelib->typelib_header.helpstringcontext = expr->cval;
 }
 
 static void set_lcid(msft_typelib_t *typelib)
@@ -2339,7 +2291,9 @@
     const attr_t *attr;
 
     typelib->typelib_header.flags = 0;
-    for(attr = typelib->typelib->attrs; attr; attr = NEXT_LINK(attr)) {
+    if (!typelib->typelib->attrs) return;
+    LIST_FOR_EACH_ENTRY( attr, typelib->typelib->attrs, const attr_t, entry )
+    {
         switch(attr->type) {
         case ATTR_CONTROL:
             typelib->typelib_header.flags |= 0x02; /* LIBFLAG_FCONTROL */
@@ -2532,7 +2486,11 @@
     if (ctl2_alloc_segment(msft, MSFT_SEG_GUIDHASH, 0x80, 0x80)) { failed = 1; }
     if (ctl2_alloc_segment(msft, MSFT_SEG_NAMEHASH, 0x200, 0x200)) { failed = 1; }
 
-    if(failed) return 0;
+    if(failed)
+    {
+        free(msft);
+        return 0;
+    }
 
     msft->typelib_guidhash_segment = (int *)msft->typelib_segment_data[MSFT_SEG_GUIDHASH];
     msft->typelib_namehash_segment = (int *)msft->typelib_segment_data[MSFT_SEG_NAMEHASH];
@@ -2557,12 +2515,10 @@
     set_custdata(msft, &midl_time_guid, VT_UI4, &cur_time, &msft->typelib_header.CustomDataOffset);
     set_custdata(msft, &midl_version_guid, VT_UI4, &version, &msft->typelib_header.CustomDataOffset);
 
-    for(entry = typelib->entry; entry && NEXT_LINK(entry); entry = NEXT_LINK(entry))
-        ;
-
-    for( ; entry; entry = PREV_LINK(entry))
+    LIST_FOR_EACH_ENTRY( entry, &typelib->entries, typelib_entry_t, entry )
         add_entry(msft, entry);
 
     save_all_changes(msft);
+    free(msft);
     return 1;
 }