2 * Typelib (SLTG) generation
4 * Copyright 2015 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
35 #include "typelib_struct.h"
40 static const GUID sltg_library_guid
= { 0x204ff,0,0,{ 0xc0,0,0,0,0,0,0,0x46 } };
71 struct sltg_data index
;
72 struct sltg_data name_table
;
73 struct sltg_library library
;
74 struct sltg_block
*blocks
;
80 static void init_sltg_data(struct sltg_data
*data
)
87 static int add_index(struct sltg_data
*index
, const char *name
)
89 int name_offset
= index
->size
;
90 int new_size
= index
->size
+ strlen(name
) + 1;
92 if (new_size
> index
->allocated
)
94 index
->allocated
= index
->allocated
? max(index
->allocated
* 2, new_size
) : new_size
;
95 index
->data
= xrealloc(index
->data
, index
->allocated
);
98 strcpy(index
->data
+ index
->size
, name
);
99 index
->size
= new_size
;
104 static void init_index(struct sltg_data
*index
)
106 static const char compobj
[] = { 1,'C','o','m','p','O','b','j',0 };
108 init_sltg_data(index
);
110 add_index(index
, compobj
);
113 static int add_name(struct sltg_data
*name_table
, const char *name
)
115 int name_offset
= name_table
->size
;
116 int new_size
= name_table
->size
+ strlen(name
) + 1 + 8;
118 new_size
= (new_size
+ 1) & ~1; /* align */
120 if (new_size
> name_table
->allocated
)
122 name_table
->allocated
= name_table
->allocated
? max(name_table
->allocated
* 2, new_size
) : new_size
;
123 name_table
->data
= xrealloc(name_table
->data
, name_table
->allocated
);
126 memset(name_table
->data
+ name_table
->size
, 0xff, 8);
127 strcpy(name_table
->data
+ name_table
->size
+ 8, name
);
128 name_table
->size
= new_size
;
129 name_table
->data
[name_table
->size
- 1] = 0; /* clear alignment */
134 static void init_name_table(struct sltg_data
*name_table
)
136 init_sltg_data(name_table
);
139 static void init_library(struct sltg_typelib
*sltg
)
143 sltg
->library
.name
= add_name(&sltg
->name_table
, sltg
->typelib
->name
);
144 sltg
->library
.helpstring
= NULL
;
145 sltg
->library
.helpcontext
= 0;
146 sltg
->library
.syskind
= SYS_WIN32
;
147 sltg
->library
.lcid
= 0x0409;
148 sltg
->library
.libflags
= 0;
149 sltg
->library
.version
= 0;
150 sltg
->library
.helpfile
= NULL
;
151 memset(&sltg
->library
.uuid
, 0, sizeof(sltg
->library
.uuid
));
153 if (!sltg
->typelib
->attrs
) return;
155 LIST_FOR_EACH_ENTRY(attr
, sltg
->typelib
->attrs
, const attr_t
, entry
)
162 sltg
->library
.version
= attr
->u
.ival
;
164 case ATTR_HELPSTRING
:
165 sltg
->library
.helpstring
= attr
->u
.pval
;
168 sltg
->library
.helpfile
= attr
->u
.pval
;
171 sltg
->library
.uuid
= *(GUID
*)attr
->u
.pval
;
173 case ATTR_HELPCONTEXT
:
175 sltg
->library
.helpcontext
= expr
->cval
;
179 sltg
->library
.lcid
= expr
->cval
;
182 sltg
->library
.libflags
|= 0x02; /* LIBFLAG_FCONTROL */
185 sltg
->library
.libflags
|= 0x04; /* LIBFLAG_FHIDDEN */
187 case ATTR_RESTRICTED
:
188 sltg
->library
.libflags
|= 0x01; /* LIBFLAG_FRESTRICTED */
196 static void add_block(struct sltg_typelib
*sltg
, void *data
, int length
, const char *name
)
198 sltg
->blocks
= xrealloc(sltg
->blocks
, sizeof(sltg
->blocks
[0]) * (sltg
->block_count
+ 1));
199 sltg
->blocks
[sltg
->block_count
].length
= length
;
200 sltg
->blocks
[sltg
->block_count
].data
= data
;
201 sltg
->blocks
[sltg
->block_count
].index_string
= add_index(&sltg
->index
, name
);
205 static void add_library_block(struct sltg_typelib
*typelib
)
211 size
= sizeof(short) * 9 + sizeof(int) * 3 + sizeof(GUID
);
212 if (typelib
->library
.helpstring
) size
+= strlen(typelib
->library
.helpstring
);
213 if (typelib
->library
.helpfile
) size
+= strlen(typelib
->library
.helpfile
);
215 block
= xmalloc(size
);
217 *p
++ = 0x51cc; /* magic */
218 *p
++ = 3; /* res02 */
219 *p
++ = typelib
->library
.name
;
220 *p
++ = 0xffff; /* res06 */
221 if (typelib
->library
.helpstring
)
223 *p
++ = strlen(typelib
->library
.helpstring
);
224 strcpy((char *)p
, typelib
->library
.helpstring
);
225 p
= (short *)((char *)p
+ strlen(typelib
->library
.helpstring
));
229 if (typelib
->library
.helpfile
)
231 *p
++ = strlen(typelib
->library
.helpfile
);
232 strcpy((char *)p
, typelib
->library
.helpfile
);
233 p
= (short *)((char *)p
+ strlen(typelib
->library
.helpfile
));
237 *(int *)p
= typelib
->library
.helpcontext
;
239 *p
++ = typelib
->library
.syskind
;
240 *p
++ = typelib
->library
.lcid
;
241 *(int *)p
= 0; /* res12 */
243 *p
++ = typelib
->library
.libflags
;
244 *(int *)p
= typelib
->library
.version
;
246 *(GUID
*)p
= typelib
->library
.uuid
;
248 add_block(typelib
, block
, size
, "dir");
251 static void add_typedef_typeinfo(struct sltg_typelib
*typelib
, type_t
*type
)
253 error("add_typedef_typeinfo: %s not implemented\n", type
->name
);
256 static void add_module_typeinfo(struct sltg_typelib
*typelib
, type_t
*type
)
258 error("add_module_typeinfo: %s not implemented\n", type
->name
);
261 static void add_interface_typeinfo(struct sltg_typelib
*typelib
, type_t
*type
)
263 error("add_interface_typeinfo: %s not implemented\n", type
->name
);
266 static void add_structure_typeinfo(struct sltg_typelib
*typelib
, type_t
*type
)
268 error("add_structure_typeinfo: %s not implemented\n", type
->name
);
271 static void add_enum_typeinfo(struct sltg_typelib
*typelib
, type_t
*type
)
273 error("add_enum_typeinfo: %s not implemented\n", type
->name
);
276 static void add_union_typeinfo(struct sltg_typelib
*typelib
, type_t
*type
)
278 error("add_union_typeinfo: %s not implemented\n", type
->name
);
281 static void add_coclass_typeinfo(struct sltg_typelib
*typelib
, type_t
*type
)
283 error("add_coclass_typeinfo: %s not implemented\n", type
->name
);
286 static void add_type_typeinfo(struct sltg_typelib
*typelib
, type_t
*type
)
288 chat("add_type_typeinfo: adding %s, type %d\n", type
->name
, type_get_type(type
));
290 switch (type_get_type(type
))
293 add_interface_typeinfo(typelib
, type
);
296 add_structure_typeinfo(typelib
, type
);
299 add_enum_typeinfo(typelib
, type
);
302 add_union_typeinfo(typelib
, type
);
305 add_coclass_typeinfo(typelib
, type
);
311 error("add_type_typeinfo: unhandled type %d for %s\n", type_get_type(type
), type
->name
);
316 static void add_statement(struct sltg_typelib
*typelib
, const statement_t
*stmt
)
324 case STMT_DECLARATION
:
325 /* not included in typelib */
328 /* not processed here */
335 if (!stmt
->u
.type_list
)
338 LIST_FOR_EACH_ENTRY(ref
, stmt
->u
.type_list
, typeref_t
, entry
)
340 /* if the type is public then add the typedef, otherwise attempt
341 * to add the aliased type */
342 if (is_attr(ref
->type
->attrs
, ATTR_PUBLIC
))
343 add_typedef_typeinfo(typelib
, ref
->type
);
345 add_type_typeinfo(typelib
, type_alias_get_aliasee_type(ref
->type
));
351 add_module_typeinfo(typelib
, stmt
->u
.type
);
357 type_t
*type
= stmt
->u
.type
;
358 add_type_typeinfo(typelib
, type
);
363 error("add_statement: unhandled statement type %d\n", stmt
->type
);
368 static void sltg_write_header(struct sltg_typelib
*sltg
, int *library_block_start
)
382 struct sltg_block_entry
390 header
.magic
= 0x47544c53;
391 header
.block_count
= sltg
->block_count
+ 1; /* 1-based */
393 header
.size_of_index
= sltg
->index
.size
;
394 header
.first_blk
= 1; /* 1-based */
395 header
.uuid
= sltg_library_guid
;
396 header
.res1c
= 0x00000044;
397 header
.res20
= 0xffff0000;
399 put_data(&header
, sizeof(header
));
401 /* library block is written separately */
402 for (i
= 0; i
< sltg
->block_count
- 1; i
++)
404 entry
.length
= sltg
->blocks
[i
].length
;
405 entry
.index_string
= sltg
->blocks
[i
].index_string
;
406 entry
.next
= header
.first_blk
+ i
;
407 put_data(&entry
, sizeof(entry
));
410 /* library block length includes helpstrings and name table */
411 entry
.length
= sltg
->blocks
[sltg
->block_count
- 1].length
+ 0x40 /* pad after library block */ +
412 sizeof(sltg
->typeinfo_count
) + 4 /* library block offset */ + 6 /* dummy help strings */ +
413 12 /* name table header */ + 0x200 /* name table hash */ + sltg
->name_table
.size
;
414 entry
.index_string
= sltg
->blocks
[sltg
->block_count
- 1].index_string
;
416 put_data(&entry
, sizeof(entry
));
418 put_data(sltg
->index
.data
, sltg
->index
.size
);
422 /* library block is written separately */
423 for (i
= 0; i
< sltg
->block_count
- 1; i
++)
425 chat("sltg_write_header: writing block %d: %d bytes\n", i
, sltg
->blocks
[i
].length
);
426 put_data(sltg
->blocks
[i
].data
, sltg
->blocks
[i
].length
);
430 *library_block_start
= output_buffer_pos
;
431 put_data(sltg
->blocks
[sltg
->block_count
- 1].data
, sltg
->blocks
[sltg
->block_count
- 1].length
);
433 memset(pad
, 0xff, 0x40);
437 static void sltg_write_typeinfo(struct sltg_typelib
*typelib
)
439 put_data(&typelib
->typeinfo_count
, sizeof(typelib
->typeinfo_count
));
442 static void sltg_write_helpstrings(struct sltg_typelib
*typelib
)
444 static const char dummy
[6];
446 put_data(dummy
, sizeof(dummy
));
449 static void sltg_write_nametable(struct sltg_typelib
*typelib
)
451 static const short dummy
[6] = { 0xffff,1,2,0xff00,0xffff,0xffff };
454 put_data(dummy
, sizeof(dummy
));
455 memset(pad
, 0xff, 0x200);
456 put_data(pad
, 0x200);
457 put_data(&typelib
->name_table
.size
, sizeof(typelib
->name_table
.size
));
458 put_data(typelib
->name_table
.data
, typelib
->name_table
.size
);
461 static void sltg_write_remainder(void)
463 static const short dummy1
[] = { 1,0xfffe,0x0a03,0,0xffff,0xffff };
464 static const short dummy2
[] = { 0xffff,0xffff,0x0200,0,0,0 };
465 static const char dummy3
[] = { 0xf4,0x39,0xb2,0x71,0,0,0,0,0,0,0,0,0,0,0,0 };
466 static const char TYPELIB
[] = { 8,0,0,0,'T','Y','P','E','L','I','B',0 };
470 put_data(&pad
, sizeof(pad
));
472 put_data(&pad
, sizeof(pad
));
474 put_data(dummy1
, sizeof(dummy1
));
476 put_data(&sltg_library_guid
, sizeof(sltg_library_guid
));
478 put_data(TYPELIB
, sizeof(TYPELIB
));
480 put_data(dummy2
, sizeof(dummy2
));
481 put_data(dummy3
, sizeof(dummy3
));
484 static void save_all_changes(struct sltg_typelib
*typelib
)
486 int library_block_start
;
487 int *name_table_offset
;
489 sltg_write_header(typelib
, &library_block_start
);
490 sltg_write_typeinfo(typelib
);
492 name_table_offset
= (int *)(output_buffer
+ output_buffer_pos
);
493 put_data(&library_block_start
, sizeof(library_block_start
));
495 sltg_write_helpstrings(typelib
);
497 *name_table_offset
= output_buffer_pos
- library_block_start
;
499 sltg_write_nametable(typelib
);
500 sltg_write_remainder();
502 if (strendswith(typelib_name
, ".res")) /* create a binary resource file */
504 char typelib_id
[13] = "#1";
506 expr_t
*expr
= get_attrp(typelib
->typelib
->attrs
, ATTR_ID
);
508 sprintf(typelib_id
, "#%d", expr
->cval
);
509 add_output_to_resources("TYPELIB", typelib_id
);
510 if (strendswith(typelib_name
, "_t.res")) /* add typelib registration */
511 output_typelib_regscript(typelib
->typelib
);
513 else flush_output_buffer(typelib_name
);
516 int create_sltg_typelib(typelib_t
*typelib
)
518 struct sltg_typelib sltg
;
519 const statement_t
*stmt
;
521 sltg
.typelib
= typelib
;
522 sltg
.typeinfo_count
= 0;
524 sltg
.block_count
= 0;
525 sltg
.first_block
= 1;
527 init_index(&sltg
.index
);
528 init_name_table(&sltg
.name_table
);
531 add_library_block(&sltg
);
534 LIST_FOR_EACH_ENTRY(stmt
, typelib
->stmts
, const statement_t
, entry
)
535 add_statement(&sltg
, stmt
);
537 save_all_changes(&sltg
);