widl: Add support for structures.
[wine.git] / tools / widl / write_sltg.c
blobc924eff89ed17e7bc0b65b06de6b6604563ce226
1 /*
2 * Typelib (SLTG) generation
4 * Copyright 2015,2016 Dmitry Timoshkov
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include <ctype.h>
28 #include <time.h>
30 #include "widl.h"
31 #include "windef.h"
32 #include "winbase.h"
34 #include "typelib.h"
35 #include "typelib_struct.h"
36 #include "utils.h"
37 #include "header.h"
38 #include "typetree.h"
40 static const GUID sltg_library_guid = { 0x204ff,0,0,{ 0xc0,0,0,0,0,0,0,0x46 } };
42 struct sltg_data
44 int size, allocated;
45 char *data;
48 struct sltg_library
50 short name;
51 char *helpstring;
52 char *helpfile;
53 int helpcontext;
54 int syskind;
55 LCID lcid;
56 int libflags;
57 int version;
58 GUID uuid;
61 struct sltg_block
63 int length;
64 int index_string;
65 void *data;
68 struct sltg_typelib
70 typelib_t *typelib;
71 struct sltg_data index;
72 struct sltg_data name_table;
73 struct sltg_library library;
74 struct sltg_block *blocks;
75 int block_count;
76 int first_block;
77 short typeinfo_count;
78 int typeinfo_size;
79 struct sltg_block *typeinfo;
82 #include "pshpack1.h"
83 struct sltg_typeinfo_header
85 short magic;
86 int href_offset;
87 int res06;
88 int member_offset;
89 int res0e;
90 int version;
91 int res16;
92 struct
94 unsigned unknown1 : 3;
95 unsigned flags : 13;
96 unsigned unknown2 : 8;
97 unsigned typekind : 8;
98 } misc;
99 int res1e;
102 struct sltg_member_header
104 short res00;
105 short res02;
106 char res04;
107 int extra;
110 struct sltg_variable
112 char magic; /* 0x0a */
113 char flags;
114 short next;
115 short name;
116 short byte_offs; /* pos in struct, or offset to const type or const data (if flags & 0x08) */
117 short type; /* if flags & 0x02 this is the type, else offset to type */
118 int memid;
119 short helpcontext;
120 short helpstring;
121 short varflags; /* only present if magic & 0x20 */
124 struct sltg_tail
126 short cFuncs;
127 short cVars;
128 short cImplTypes;
129 short res06; /* always 0000 */
130 short funcs_off; /* offset to functions (starting from the member header) */
131 short vars_off; /* offset to vars (starting from the member header) */
132 short impls_off; /* offset to implemented types (starting from the member header) */
133 short funcs_bytes; /* bytes used by function data */
134 short vars_bytes; /* bytes used by var data */
135 short impls_bytes; /* bytes used by implemented type data */
136 short tdescalias_vt; /* for TKIND_ALIAS */
137 short res16; /* always ffff */
138 short res18; /* always 0000 */
139 short res1a; /* always 0000 */
140 short simple_alias; /* tdescalias_vt is a vt rather than an offset? */
141 short res1e; /* always 0000 */
142 short cbSizeInstance;
143 short cbAlignment;
144 short res24; /* always ffff */
145 short res26; /* always ffff */
146 short cbSizeVft;
147 short res2a; /* always ffff */
148 short res2c; /* always ffff */
149 short res2e; /* always ffff */
150 short res30; /* always ffff */
151 short res32; /* unknown */
152 short type_bytes; /* bytes used by type descriptions */
154 #include "poppack.h"
156 static void init_sltg_data(struct sltg_data *data)
158 data->size = 0;
159 data->allocated = 0;
160 data->data = NULL;
163 static int add_index(struct sltg_data *index, const char *name)
165 int name_offset = index->size;
166 int new_size = index->size + strlen(name) + 1;
168 chat("add_index: name_offset %d, \"%s\"\n", name_offset, name);
170 if (new_size > index->allocated)
172 index->allocated = index->allocated ? max(index->allocated * 2, new_size) : new_size;
173 index->data = xrealloc(index->data, index->allocated);
176 strcpy(index->data + index->size, name);
177 index->size = new_size;
179 return name_offset;
182 static void init_index(struct sltg_data *index)
184 static const char compobj[] = { 1,'C','o','m','p','O','b','j',0 };
186 init_sltg_data(index);
188 add_index(index, compobj);
191 static int add_name(struct sltg_data *name_table, const char *name)
193 int name_offset = name_table->size;
194 int new_size = name_table->size + strlen(name) + 1 + 8;
196 chat("add_name: %s\n", name);
198 new_size = (new_size + 1) & ~1; /* align */
200 if (new_size > name_table->allocated)
202 name_table->allocated = name_table->allocated ? max(name_table->allocated * 2, new_size) : new_size;
203 name_table->data = xrealloc(name_table->data, name_table->allocated);
206 memset(name_table->data + name_table->size, 0xff, 8);
207 strcpy(name_table->data + name_table->size + 8, name);
208 name_table->size = new_size;
209 name_table->data[name_table->size - 1] = 0; /* clear alignment */
211 return name_offset;
214 static void init_name_table(struct sltg_data *name_table)
216 init_sltg_data(name_table);
219 static void init_library(struct sltg_typelib *sltg)
221 const attr_t *attr;
223 sltg->library.name = add_name(&sltg->name_table, sltg->typelib->name);
224 sltg->library.helpstring = NULL;
225 sltg->library.helpcontext = 0;
226 sltg->library.syskind = SYS_WIN32;
227 sltg->library.lcid = 0x0409;
228 sltg->library.libflags = 0;
229 sltg->library.version = 0;
230 sltg->library.helpfile = NULL;
231 memset(&sltg->library.uuid, 0, sizeof(sltg->library.uuid));
233 if (!sltg->typelib->attrs) return;
235 LIST_FOR_EACH_ENTRY(attr, sltg->typelib->attrs, const attr_t, entry)
237 const expr_t *expr;
239 switch (attr->type)
241 case ATTR_VERSION:
242 sltg->library.version = attr->u.ival;
243 break;
244 case ATTR_HELPSTRING:
245 sltg->library.helpstring = attr->u.pval;
246 break;
247 case ATTR_HELPFILE:
248 sltg->library.helpfile = attr->u.pval;
249 break;
250 case ATTR_UUID:
251 sltg->library.uuid = *(GUID *)attr->u.pval;
252 break;
253 case ATTR_HELPCONTEXT:
254 expr = attr->u.pval;
255 sltg->library.helpcontext = expr->cval;
256 break;
257 case ATTR_LIBLCID:
258 expr = attr->u.pval;
259 sltg->library.lcid = expr->cval;
260 break;
261 case ATTR_CONTROL:
262 sltg->library.libflags |= 0x02; /* LIBFLAG_FCONTROL */
263 break;
264 case ATTR_HIDDEN:
265 sltg->library.libflags |= 0x04; /* LIBFLAG_FHIDDEN */
266 break;
267 case ATTR_RESTRICTED:
268 sltg->library.libflags |= 0x01; /* LIBFLAG_FRESTRICTED */
269 break;
270 default:
271 break;
276 static void add_block(struct sltg_typelib *sltg, void *data, int length, const char *name)
278 chat("add_block: %p,%d,\"%s\"\n", data, length, name);
280 sltg->blocks = xrealloc(sltg->blocks, sizeof(sltg->blocks[0]) * (sltg->block_count + 1));
281 sltg->blocks[sltg->block_count].length = length;
282 sltg->blocks[sltg->block_count].data = data;
283 sltg->blocks[sltg->block_count].index_string = add_index(&sltg->index, name);
284 sltg->block_count++;
287 static void add_library_block(struct sltg_typelib *typelib)
289 void *block;
290 short *p;
291 int size;
293 size = sizeof(short) * 9 + sizeof(int) * 3 + sizeof(GUID);
294 if (typelib->library.helpstring) size += strlen(typelib->library.helpstring);
295 if (typelib->library.helpfile) size += strlen(typelib->library.helpfile);
297 block = xmalloc(size);
298 p = block;
299 *p++ = 0x51cc; /* magic */
300 *p++ = 3; /* res02 */
301 *p++ = typelib->library.name;
302 *p++ = 0xffff; /* res06 */
303 if (typelib->library.helpstring)
305 *p++ = strlen(typelib->library.helpstring);
306 strcpy((char *)p, typelib->library.helpstring);
307 p = (short *)((char *)p + strlen(typelib->library.helpstring));
309 else
310 *p++ = 0xffff;
311 if (typelib->library.helpfile)
313 *p++ = strlen(typelib->library.helpfile);
314 strcpy((char *)p, typelib->library.helpfile);
315 p = (short *)((char *)p + strlen(typelib->library.helpfile));
317 else
318 *p++ = 0xffff;
319 *(int *)p = typelib->library.helpcontext;
320 p += 2;
321 *p++ = typelib->library.syskind;
322 *p++ = typelib->library.lcid;
323 *(int *)p = 0; /* res12 */
324 p += 2;
325 *p++ = typelib->library.libflags;
326 *(int *)p = typelib->library.version;
327 p += 2;
328 *(GUID *)p = typelib->library.uuid;
330 add_block(typelib, block, size, "dir");
333 static const char *new_index_name(void)
335 static char name[11] = "AAAAAAAAAA";
336 static int pos = 0;
337 char *new_name;
339 if (name[pos] == 'Z')
341 pos++;
342 if (pos > 9)
343 error("too many index names\n");
346 name[pos]++;
348 new_name = xmalloc(sizeof(name));
349 strcpy(new_name, name);
350 return new_name;
353 static void sltg_add_typeinfo(struct sltg_typelib *sltg, void *data, int length, const char *name)
355 chat("sltg_add_typeinfo: %p,%d,%s\n", data, length, name);
357 sltg->typeinfo = xrealloc(sltg->typeinfo, sizeof(sltg->typeinfo[0]) * (sltg->typeinfo_count + 1));
358 sltg->typeinfo[sltg->typeinfo_count].length = length;
359 sltg->typeinfo[sltg->typeinfo_count].data = data;
360 sltg->typeinfo[sltg->typeinfo_count].index_string = 0;
361 sltg->typeinfo_count++;
362 sltg->typeinfo_size += length;
365 static void append_data(struct sltg_data *block, const void *data, int size)
367 int new_size = block->size + size;
369 if (new_size > block->allocated)
371 block->allocated = max(block->allocated * 2, new_size);
372 block->data = xrealloc(block->data, block->allocated);
375 memcpy(block->data + block->size, data, size);
376 block->size = new_size;
379 static void add_typedef_typeinfo(struct sltg_typelib *typelib, type_t *type)
381 error("add_typedef_typeinfo: %s not implemented\n", type->name);
384 static void add_module_typeinfo(struct sltg_typelib *typelib, type_t *type)
386 error("add_module_typeinfo: %s not implemented\n", type->name);
389 static void add_interface_typeinfo(struct sltg_typelib *typelib, type_t *type)
391 error("add_interface_typeinfo: %s not implemented\n", type->name);
394 static const char *add_typeinfo_block(struct sltg_typelib *typelib, const type_t *type, short kind)
396 struct sltg_data block;
397 const char *index_name, *other_name;
398 short val;
399 void *p;
400 int helpcontext = 0;
401 GUID guid = { 0 };
402 const expr_t *expr;
404 index_name = new_index_name();
405 other_name = new_index_name();
407 expr = get_attrp(type->attrs, ATTR_HELPCONTEXT);
408 if (expr) helpcontext = expr->cval;
410 p = get_attrp(type->attrs, ATTR_UUID);
411 if (p) guid = *(GUID *)p;
413 init_sltg_data(&block);
415 val = strlen(index_name);
416 append_data(&block, &val, sizeof(val));
417 append_data(&block, index_name, val);
418 val = strlen(other_name);
419 append_data(&block, &val, sizeof(val));
420 append_data(&block, other_name, val);
421 val = -1; /* res1a */
422 append_data(&block, &val, sizeof(val));
423 val = add_name(&typelib->name_table, type->name); /* name offset */
424 append_data(&block, &val, sizeof(val));
425 val = 0; /* FIXME: helpstring */
426 append_data(&block, &val, sizeof(val));
427 val = -1; /* res20 */
428 append_data(&block, &val, sizeof(val));
429 append_data(&block, &helpcontext, sizeof(helpcontext));
430 val = -1; /* res26 */
431 append_data(&block, &val, sizeof(val));
432 append_data(&block, &guid, sizeof(guid));
433 append_data(&block, &kind, sizeof(kind));
435 sltg_add_typeinfo(typelib, block.data, block.size, index_name);
437 return index_name;
440 static void init_typeinfo(struct sltg_typeinfo_header *ti, const type_t *type, int kind)
442 ti->magic = 0x0501;
443 ti->href_offset = -1;
444 ti->res06 = -1;
445 ti->member_offset = sizeof(*ti);
446 ti->res0e = -1;
447 ti->version = get_attrv(type->attrs, ATTR_VERSION);
448 ti->res16 = 0xfffe0000;
449 ti->misc.unknown1 = 0x02;
450 ti->misc.flags = 0; /* FIXME */
451 ti->misc.unknown2 = 0x02;
452 ti->misc.typekind = kind;
453 ti->res1e = -1;
456 static void dump_var_desc(const char *data, int size)
458 const unsigned char *p = (const unsigned char *)data;
459 int i;
461 if (!(debuglevel & (DEBUGLEVEL_TRACE | DEBUGLEVEL_CHAT))) return;
463 chat("dump_var_desc: size %d bytes\n", size);
465 for (i = 0; i < size; i++)
466 fprintf(stderr, " %02x", *p++);
468 fprintf(stderr, "\n");
471 static int get_element_size(type_t *type)
473 int vt = get_type_vt(type);
475 switch (vt)
477 case VT_I1:
478 case VT_UI1:
479 return 1;
481 case VT_UI2:
482 case VT_I2:
483 case VT_BOOL:
484 return 2;
486 case VT_INT:
487 case VT_UINT:
488 case VT_I4:
489 case VT_UI4:
490 case VT_R4:
491 case VT_ERROR:
492 case VT_HRESULT:
493 return 4;
495 case VT_R8:
496 case VT_I8:
497 case VT_UI8:
498 case VT_CY:
499 case VT_DATE:
500 return 8;
502 case VT_DECIMAL:
503 return 16;
505 case VT_PTR:
506 case VT_UNKNOWN:
507 case VT_DISPATCH:
508 case VT_BSTR:
509 case VT_LPSTR:
510 case VT_LPWSTR:
511 return 4;
513 case VT_VOID:
514 return 0;
516 case VT_VARIANT:
517 return 16;
519 default:
520 error("get_element_size: unrecognized vt %d\n", vt);
521 break;
524 return 0;
527 static short write_var_desc(struct sltg_data *data, type_t *type, short flags, short base_offset, int *size_instance)
529 short vt, desc_offset;
531 chat("write_var_desc: type %p, type->name %s\n",
532 type, type->name ? type->name : "NULL");
534 if (is_array(type) && !type_array_is_decl_as_ptr(type))
536 int num_dims, elements, array_start, size, array_size;
537 type_t *atype;
538 struct
540 short cDims;
541 short fFeatures;
542 int cbElements;
543 int cLocks;
544 int pvData;
545 int bound[2];
546 } *array;
547 int *bound;
548 short vt_off[2];
550 elements = 1;
551 num_dims = 0;
553 atype = type;
555 while (is_array(atype) && !type_array_is_decl_as_ptr(atype))
557 num_dims++;
558 elements *= type_array_get_dim(atype);
560 atype = type_array_get_element_type(atype);
563 chat("write_var_desc: VT_CARRAY: %d dimensions, %d elements\n", num_dims, elements);
565 array_start = data->size;
567 size = sizeof(*array) + (num_dims - 1) * 8 /* sizeof(SAFEARRAYBOUND) */;
568 array = xmalloc(size);
570 array->cDims = num_dims;
571 array->fFeatures = 0x0004; /* FADF_EMBEDDED */
572 array->cbElements = get_element_size(atype);
573 array->cLocks = 0;
574 array->pvData = 0;
576 bound = array->bound;
578 array_size = array->cbElements;
579 atype = type;
581 while (is_array(atype) && !type_array_is_decl_as_ptr(atype))
583 bound[0] = type_array_get_dim(atype);
584 array_size *= bound[0];
585 bound[1] = 0;
586 bound += 2;
588 atype = type_array_get_element_type(atype);
591 *size_instance += array_size;
592 size_instance = NULL; /* don't account for element size */
594 append_data(data, array, size);
596 desc_offset = data->size;
598 vt_off[0] = VT_CARRAY;
599 vt_off[1] = array_start + base_offset;
600 append_data(data, vt_off, sizeof(vt_off));
602 /* fall through to write array element description */
603 type = atype;
605 else
606 desc_offset = data->size;
608 vt = get_type_vt(type);
610 if (vt == VT_PTR)
612 type_t *ref = is_ptr(type) ? type_pointer_get_ref_type(type) : type_array_get_element_type(type);
614 if (is_ptr(ref))
616 chat("write_var_desc: vt VT_PTR | 0x0400\n");
617 vt = VT_PTR | 0x0400;
618 append_data(data, &vt, sizeof(vt));
619 write_var_desc(data, ref, 0, base_offset, size_instance);
621 else
622 write_var_desc(data, ref, 0x0e00, base_offset, size_instance);
623 return desc_offset;
626 chat("write_var_desc: vt %d, flags %04x\n", vt, flags);
628 if (size_instance)
629 *size_instance += get_element_size(type);
631 vt |= flags;
632 append_data(data, &vt, sizeof(vt));
634 return desc_offset;
637 static void init_sltg_tail(struct sltg_tail *tail)
639 tail->cFuncs = 0;
640 tail->cVars = 0;
641 tail->cImplTypes = 0;
642 tail->res06 = 0;
643 tail->funcs_off = -1;
644 tail->vars_off = 0;
645 tail->impls_off = -1;
646 tail->funcs_bytes = -1;
647 tail->vars_bytes = 0;
648 tail->impls_bytes = -1;
649 tail->tdescalias_vt = -1;
650 tail->res16 = -1;
651 tail->res18 = 0;
652 tail->res1a = 0;
653 tail->simple_alias = 0;
654 tail->res1e = 0;
655 tail->cbSizeInstance = 0;
656 tail->cbAlignment = 4;
657 tail->res24 = -1;
658 tail->res26 = -1;
659 tail->cbSizeVft = 0;
660 tail->res2a = -1;
661 tail->res2c = -1;
662 tail->res2e = -1;
663 tail->res30 = -1;
664 tail->res32 = 0;
665 tail->type_bytes = 0;
668 static void add_structure_typeinfo(struct sltg_typelib *typelib, type_t *type)
670 struct sltg_data data, *var_data = NULL;
671 const char *index_name;
672 struct sltg_typeinfo_header ti;
673 struct sltg_member_header member;
674 struct sltg_tail tail;
675 int member_offset, var_count = 0, var_data_size = 0, size_instance = 0;
676 short *type_desc_offset = NULL;
678 chat("add_structure_typeinfo: %s\n", type->name);
680 init_sltg_data(&data);
682 index_name = add_typeinfo_block(typelib, type, TKIND_RECORD);
684 init_typeinfo(&ti, type, TKIND_RECORD);
685 append_data(&data, &ti, sizeof(ti));
687 if (type_struct_get_fields(type))
689 int i = 0;
690 var_t *var;
692 var_count = list_count(type_struct_get_fields(type));
694 var_data = xmalloc(var_count * sizeof(*var_data));
695 type_desc_offset = xmalloc(var_count * sizeof(*type_desc_offset));
697 LIST_FOR_EACH_ENTRY(var, type_struct_get_fields(type), var_t, entry)
699 short base_offset;
701 chat("add_structure_typeinfo: var %p, name %s, type %p\n",
702 var, var->name, var->declspec.type);
704 init_sltg_data(&var_data[i]);
706 base_offset = var_data_size + (i + 1) * sizeof(struct sltg_variable);
707 type_desc_offset[i] = write_var_desc(&var_data[i], var->declspec.type, 0, base_offset, &size_instance);
708 dump_var_desc(var_data[i].data, var_data[i].size);
710 if (var_data[i].size > sizeof(short))
711 var_data_size += var_data[i].size;
712 i++;
716 member_offset = data.size;
718 member.res00 = 0x0001;
719 member.res02 = 0xffff;
720 member.res04 = 0x01;
721 member.extra = var_data_size + var_count * sizeof(struct sltg_variable);
722 append_data(&data, &member, sizeof(member));
724 var_data_size = 0;
726 if (type_struct_get_fields(type))
728 int i = 0;
729 short next = member_offset;
730 var_t *var;
732 LIST_FOR_EACH_ENTRY(var, type_struct_get_fields(type), var_t, entry)
734 struct sltg_variable variable;
736 next += sizeof(variable);
738 variable.magic = 0x2a; /* always write flags to simplify calculations */
739 variable.name = add_name(&typelib->name_table, var->name);
740 variable.byte_offs = 0;
741 if (var_data[i].size > sizeof(short))
743 variable.flags = 0;
744 var_data_size = next - member_offset + type_desc_offset[i];
745 variable.type = var_data_size;
746 next += var_data[i].size;
748 else
750 variable.flags = 0x02;
751 variable.type = *(short *)var_data[i].data;
753 variable.next = i < var_count - 1 ? next - member_offset : -1;
754 variable.memid = 0x40000000 + i;
755 variable.helpcontext = -2; /* 0xfffe */
756 variable.helpstring = -1;
757 variable.varflags = 0;
759 append_data(&data, &variable, sizeof(variable));
760 if (var_data[i].size > sizeof(short))
761 append_data(&data, var_data[i].data, var_data[i].size);
763 i++;
767 init_sltg_tail(&tail);
768 tail.cVars = var_count;
769 tail.vars_bytes = var_data_size;
770 tail.cbSizeInstance = size_instance;
771 tail.type_bytes = data.size - member_offset - sizeof(member);
772 append_data(&data, &tail, sizeof(tail));
774 add_block(typelib, data.data, data.size, index_name);
777 static void add_enum_typeinfo(struct sltg_typelib *typelib, type_t *type)
779 error("add_enum_typeinfo: %s not implemented\n", type->name);
782 static void add_union_typeinfo(struct sltg_typelib *typelib, type_t *type)
784 error("add_union_typeinfo: %s not implemented\n", type->name);
787 static void add_coclass_typeinfo(struct sltg_typelib *typelib, type_t *type)
789 error("add_coclass_typeinfo: %s not implemented\n", type->name);
792 static void add_type_typeinfo(struct sltg_typelib *typelib, type_t *type)
794 chat("add_type_typeinfo: adding %s, type %d\n", type->name, type_get_type(type));
796 switch (type_get_type(type))
798 case TYPE_INTERFACE:
799 add_interface_typeinfo(typelib, type);
800 break;
801 case TYPE_STRUCT:
802 add_structure_typeinfo(typelib, type);
803 break;
804 case TYPE_ENUM:
805 add_enum_typeinfo(typelib, type);
806 break;
807 case TYPE_UNION:
808 add_union_typeinfo(typelib, type);
809 break;
810 case TYPE_COCLASS:
811 add_coclass_typeinfo(typelib, type);
812 break;
813 case TYPE_BASIC:
814 case TYPE_POINTER:
815 break;
816 default:
817 error("add_type_typeinfo: unhandled type %d for %s\n", type_get_type(type), type->name);
818 break;
822 static void add_statement(struct sltg_typelib *typelib, const statement_t *stmt)
824 switch(stmt->type)
826 case STMT_LIBRARY:
827 case STMT_IMPORT:
828 case STMT_PRAGMA:
829 case STMT_CPPQUOTE:
830 case STMT_DECLARATION:
831 /* not included in typelib */
832 break;
833 case STMT_IMPORTLIB:
834 /* not processed here */
835 break;
837 case STMT_TYPEDEF:
839 typeref_t *ref;
841 if (!stmt->u.type_list)
842 break;
844 LIST_FOR_EACH_ENTRY(ref, stmt->u.type_list, typeref_t, entry)
846 /* if the type is public then add the typedef, otherwise attempt
847 * to add the aliased type */
848 if (is_attr(ref->type->attrs, ATTR_PUBLIC))
849 add_typedef_typeinfo(typelib, ref->type);
850 else
851 add_type_typeinfo(typelib, type_alias_get_aliasee_type(ref->type));
853 break;
856 case STMT_MODULE:
857 add_module_typeinfo(typelib, stmt->u.type);
858 break;
860 case STMT_TYPE:
861 case STMT_TYPEREF:
863 type_t *type = stmt->u.type;
864 add_type_typeinfo(typelib, type);
865 break;
868 default:
869 error("add_statement: unhandled statement type %d\n", stmt->type);
870 break;
874 static void sltg_write_header(struct sltg_typelib *sltg, int *library_block_start)
876 char pad[0x40];
877 struct sltg_header
879 int magic;
880 short block_count;
881 short res06;
882 short size_of_index;
883 short first_blk;
884 GUID uuid;
885 int res1c;
886 int res20;
887 } header;
888 struct sltg_block_entry
890 int length;
891 short index_string;
892 short next;
893 } entry;
894 int i;
896 header.magic = 0x47544c53;
897 header.block_count = sltg->block_count + 1; /* 1-based */
898 header.res06 = 9;
899 header.size_of_index = sltg->index.size;
900 header.first_blk = 1; /* 1-based */
901 header.uuid = sltg_library_guid;
902 header.res1c = 0x00000044;
903 header.res20 = 0xffff0000;
905 put_data(&header, sizeof(header));
907 /* library block is written separately */
908 for (i = 0; i < sltg->block_count - 1; i++)
910 entry.length = sltg->blocks[i].length;
911 entry.index_string = sltg->blocks[i].index_string;
912 entry.next = header.first_blk + i + 1; /* point to next block */
913 chat("sltg_write_header: writing block entry %d: length %#x, index_string %#x, next %#x\n",
914 i, entry.length, entry.index_string, entry.next);
915 put_data(&entry, sizeof(entry));
918 /* library block length includes helpstrings and name table */
919 entry.length = sltg->blocks[sltg->block_count - 1].length + 0x40 /* pad after library block */ +
920 sizeof(sltg->typeinfo_count) + sltg->typeinfo_size + 4 /* library block offset */ + 6 /* dummy help strings */ +
921 12 /* name table header */ + 0x200 /* name table hash */ + sltg->name_table.size;
922 entry.index_string = sltg->blocks[sltg->block_count - 1].index_string;
923 entry.next = 0;
924 chat("sltg_write_header: writing library block entry %d: length %#x, index_string %#x, next %#x\n",
925 i, entry.length, entry.index_string, entry.next);
926 put_data(&entry, sizeof(entry));
928 chat("sltg_write_header: writing index: %d bytes\n", sltg->index.size);
929 put_data(sltg->index.data, sltg->index.size);
930 memset(pad, 0, 9);
931 put_data(pad, 9);
933 /* library block is written separately */
934 for (i = 0; i < sltg->block_count - 1; i++)
936 chat("sltg_write_header: writing block %d: %d bytes\n", i, sltg->blocks[i].length);
937 put_data(sltg->blocks[i].data, sltg->blocks[i].length);
940 /* library block */
941 chat("library_block_start = %#x\n", (int)output_buffer_pos);
942 *library_block_start = output_buffer_pos;
943 chat("sltg_write_header: writing library block %d: %d bytes\n", i, sltg->blocks[i].length);
944 put_data(sltg->blocks[sltg->block_count - 1].data, sltg->blocks[sltg->block_count - 1].length);
946 chat("sltg_write_header: writing pad 0x40 bytes\n");
947 memset(pad, 0xff, 0x40);
948 put_data(pad, 0x40);
951 static void sltg_write_typeinfo(struct sltg_typelib *typelib)
953 short i;
955 put_data(&typelib->typeinfo_count, sizeof(typelib->typeinfo_count));
957 for (i = 0; i < typelib->typeinfo_count; i++)
959 chat("sltg_write_typeinfo: writing block %d: %d bytes\n", i, typelib->typeinfo[i].length);
960 put_data(typelib->typeinfo[i].data, typelib->typeinfo[i].length);
964 static void sltg_write_helpstrings(struct sltg_typelib *typelib)
966 static const char dummy[6];
968 chat("sltg_write_helpstrings: writing dummy 6 bytes\n");
970 put_data(dummy, sizeof(dummy));
973 static void sltg_write_nametable(struct sltg_typelib *typelib)
975 static const short dummy[6] = { 0xffff,1,2,0xff00,0xffff,0xffff };
976 char pad[0x200];
978 chat("sltg_write_nametable: writing 12+0x200+%d bytes\n", typelib->name_table.size);
980 put_data(dummy, sizeof(dummy));
981 memset(pad, 0xff, 0x200);
982 put_data(pad, 0x200);
983 put_data(&typelib->name_table.size, sizeof(typelib->name_table.size));
984 put_data(typelib->name_table.data, typelib->name_table.size);
987 static void sltg_write_remainder(void)
989 static const short dummy1[] = { 1,0xfffe,0x0a03,0,0xffff,0xffff };
990 static const short dummy2[] = { 0xffff,0xffff,0x0200,0,0,0 };
991 static const char dummy3[] = { 0xf4,0x39,0xb2,0x71,0,0,0,0,0,0,0,0,0,0,0,0 };
992 static const char TYPELIB[] = { 8,0,0,0,'T','Y','P','E','L','I','B',0 };
993 int pad;
995 pad = 0x01ffff01;
996 put_data(&pad, sizeof(pad));
997 pad = 0;
998 put_data(&pad, sizeof(pad));
1000 put_data(dummy1, sizeof(dummy1));
1002 put_data(&sltg_library_guid, sizeof(sltg_library_guid));
1004 put_data(TYPELIB, sizeof(TYPELIB));
1006 put_data(dummy2, sizeof(dummy2));
1007 put_data(dummy3, sizeof(dummy3));
1010 static void save_all_changes(struct sltg_typelib *typelib)
1012 int library_block_start;
1013 int *name_table_offset;
1015 sltg_write_header(typelib, &library_block_start);
1016 sltg_write_typeinfo(typelib);
1018 name_table_offset = (int *)(output_buffer + output_buffer_pos);
1019 chat("name_table_offset = %#x\n", (int)output_buffer_pos);
1020 put_data(&library_block_start, sizeof(library_block_start));
1022 sltg_write_helpstrings(typelib);
1024 *name_table_offset = output_buffer_pos - library_block_start;
1025 chat("*name_table_offset = %#x\n", *name_table_offset);
1027 sltg_write_nametable(typelib);
1028 sltg_write_remainder();
1030 if (strendswith(typelib_name, ".res")) /* create a binary resource file */
1032 char typelib_id[13] = "#1";
1034 expr_t *expr = get_attrp(typelib->typelib->attrs, ATTR_ID);
1035 if (expr)
1036 sprintf(typelib_id, "#%d", expr->cval);
1037 add_output_to_resources("TYPELIB", typelib_id);
1038 if (strendswith(typelib_name, "_t.res")) /* add typelib registration */
1039 output_typelib_regscript(typelib->typelib);
1041 else flush_output_buffer(typelib_name);
1044 int create_sltg_typelib(typelib_t *typelib)
1046 struct sltg_typelib sltg;
1047 const statement_t *stmt;
1049 if (pointer_size != 4)
1050 error("Only 32-bit platform is supported\n");
1052 sltg.typelib = typelib;
1053 sltg.typeinfo_count = 0;
1054 sltg.typeinfo_size = 0;
1055 sltg.typeinfo = NULL;
1056 sltg.blocks = NULL;
1057 sltg.block_count = 0;
1058 sltg.first_block = 1;
1060 init_index(&sltg.index);
1061 init_name_table(&sltg.name_table);
1062 init_library(&sltg);
1064 add_library_block(&sltg);
1066 if (typelib->stmts)
1067 LIST_FOR_EACH_ENTRY(stmt, typelib->stmts, const statement_t, entry)
1068 add_statement(&sltg, stmt);
1070 save_all_changes(&sltg);
1072 return 1;