From e35374deb70ca2dd7e26df954b57e61dd21668a4 Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Thu, 14 Jan 2016 15:16:37 +0800
Subject: widl: Add support for recursive type references to SLTG typelib
 generator.

---
 tools/widl/write_sltg.c | 66 ++++++++++++++++++++++++++++++++++---------------
 1 file changed, 46 insertions(+), 20 deletions(-)

diff --git a/tools/widl/write_sltg.c b/tools/widl/write_sltg.c
index b417dc2..4d9ee01 100644
--- a/tools/widl/write_sltg.c
+++ b/tools/widl/write_sltg.c
@@ -203,6 +203,12 @@ struct sltg_hrefinfo
 
 #include "poppack.h"
 
+static void add_structure_typeinfo(struct sltg_typelib *typelib, type_t *type);
+static void add_interface_typeinfo(struct sltg_typelib *typelib, type_t *type);
+static void add_enum_typeinfo(struct sltg_typelib *typelib, type_t *type);
+static void add_union_typeinfo(struct sltg_typelib *typelib, type_t *type);
+static void add_coclass_typeinfo(struct sltg_typelib *typelib, type_t *type);
+
 static void init_sltg_data(struct sltg_data *data)
 {
     data->size = 0;
@@ -461,11 +467,6 @@ static void append_data(struct sltg_data *block, const void *data, int size)
     block->size = new_size;
 }
 
-static void add_typedef_typeinfo(struct sltg_typelib *typelib, type_t *type)
-{
-    error("add_typedef_typeinfo: %s not implemented\n", type->name);
-}
-
 static void add_module_typeinfo(struct sltg_typelib *typelib, type_t *type)
 {
     error("add_module_typeinfo: %s not implemented\n", type->name);
@@ -747,8 +748,8 @@ static int local_href(struct sltg_hrefmap *hrefmap, int typelib_href)
     return href << 2;
 }
 
-static short write_var_desc(struct sltg_data *data, type_t *type, short flags, short base_offset,
-                            int *size_instance, struct sltg_hrefmap *hrefmap)
+static short write_var_desc(struct sltg_typelib *typelib, struct sltg_data *data, type_t *type, short flags,
+                            short base_offset, int *size_instance, struct sltg_hrefmap *hrefmap)
 {
     short vt, vt_flags, desc_offset;
 
@@ -840,10 +841,10 @@ static short write_var_desc(struct sltg_data *data, type_t *type, short flags, s
             chat("write_var_desc: vt VT_PTR | 0x0400\n");
             vt = VT_PTR | 0x0400;
             append_data(data, &vt, sizeof(vt));
-            write_var_desc(data, ref, 0, base_offset, size_instance, hrefmap);
+            write_var_desc(typelib, data, ref, 0, base_offset, size_instance, hrefmap);
         }
         else
-            write_var_desc(data, ref, 0x0e00, base_offset, size_instance, hrefmap);
+            write_var_desc(typelib, data, ref, 0x0e00, base_offset, size_instance, hrefmap);
         return desc_offset;
     }
 
@@ -863,6 +864,33 @@ static short write_var_desc(struct sltg_data *data, type_t *type, short flags, s
              type, type->name, type_get_type(type), type->typelib_idx);
 
         if (type->typelib_idx == -1)
+        {
+            chat("write_var_desc: trying to ref not added type\n");
+
+            switch (type_get_type(type))
+            {
+            case TYPE_STRUCT:
+                add_structure_typeinfo(typelib, type);
+                break;
+            case TYPE_INTERFACE:
+                add_interface_typeinfo(typelib, type);
+                break;
+            case TYPE_ENUM:
+                add_enum_typeinfo(typelib, type);
+                break;
+            case TYPE_UNION:
+                add_union_typeinfo(typelib, type);
+                break;
+            case TYPE_COCLASS:
+                add_coclass_typeinfo(typelib, type);
+                break;
+            default:
+                error("write_var_desc: VT_USERDEFINED - unhandled type %d\n",
+                      type_get_type(type));
+            }
+        }
+
+        if (type->typelib_idx == -1)
             error("write_var_desc: trying to ref not added type\n");
 
         href = local_href(hrefmap, type->typelib_idx);
@@ -888,6 +916,8 @@ static void add_structure_typeinfo(struct sltg_typelib *typelib, type_t *type)
     int member_offset, var_count = 0, var_data_size = 0, size_instance = 0;
     short *type_desc_offset = NULL;
 
+    if (type->typelib_idx != -1) return;
+
     chat("add_structure_typeinfo: type %p, type->name %s\n", type, type->name);
 
     type->typelib_idx = typelib->n_file_blocks;
@@ -897,8 +927,6 @@ static void add_structure_typeinfo(struct sltg_typelib *typelib, type_t *type)
 
     init_sltg_data(&data);
 
-    index_name = add_typeinfo_block(typelib, type, TKIND_RECORD);
-
     if (type_struct_get_fields(type))
     {
         int i = 0;
@@ -913,13 +941,13 @@ static void add_structure_typeinfo(struct sltg_typelib *typelib, type_t *type)
         {
             short base_offset;
 
-            chat("add_structure_typeinfo: var %p, name %s, type %p\n",
-                 var, var->name, var->type);
+            chat("add_structure_typeinfo: var %p (%s), type %p (%s)\n",
+                 var, var->name, var->type, var->type->name);
 
             init_sltg_data(&var_data[i]);
 
             base_offset = var_data_size + (i + 1) * sizeof(struct sltg_variable);
-            type_desc_offset[i] = write_var_desc(&var_data[i], var->type, 0, base_offset, &size_instance, &hrefmap);
+            type_desc_offset[i] = write_var_desc(typelib, &var_data[i], var->type, 0, base_offset, &size_instance, &hrefmap);
             dump_var_desc(var_data[i].data, var_data[i].size);
 
             if (var_data[i].size > sizeof(short))
@@ -928,6 +956,8 @@ static void add_structure_typeinfo(struct sltg_typelib *typelib, type_t *type)
         }
     }
 
+    index_name = add_typeinfo_block(typelib, type, TKIND_RECORD);
+
     init_typeinfo(&ti, type, TKIND_RECORD, &hrefmap);
     append_data(&data, &ti, sizeof(ti));
 
@@ -1060,12 +1090,8 @@ static void add_statement(struct sltg_typelib *typelib, const statement_t *stmt)
         const type_list_t *type_entry = stmt->u.type_list;
         for (; type_entry; type_entry = type_entry->next)
         {
-            /* if the type is public then add the typedef, otherwise attempt
-             * to add the aliased type */
-            if (is_attr(type_entry->type->attrs, ATTR_PUBLIC))
-                add_typedef_typeinfo(typelib, type_entry->type);
-            else
-                add_type_typeinfo(typelib, type_alias_get_aliasee(type_entry->type));
+            /* in old style typelibs all types are public */
+            add_type_typeinfo(typelib, type_entry->type);
         }
         break;
     }
-- 
2.6.4

