Update the address of the Free Software Foundation.
[wine/testsucceed.git] / tools / widl / typelib.c
blobbb2f71584e03fc630a29d081b406eb1ef1a13854
1 /*
2 * IDL Compiler
4 * Copyright 2004 Ove Kaaven
5 * Copyright 2006 Jacek Caban for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "config.h"
23 #include "wine/port.h"
24 #include "wine/wpp.h"
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <stdarg.h>
29 #include <unistd.h>
30 #include <string.h>
31 #include <assert.h>
32 #include <ctype.h>
33 #include <signal.h>
35 #define NONAMELESSUNION
36 #define NONAMELESSSTRUCT
38 #include "windef.h"
39 #include "winbase.h"
41 #include "wine/unicode.h"
43 #include "widl.h"
44 #include "utils.h"
45 #include "parser.h"
46 #include "header.h"
47 #include "typelib.h"
48 #include "widltypes.h"
49 #include "typelib_struct.h"
51 int in_typelib = 0;
53 static typelib_t *typelib;
55 /* List of oleauto types that should be recognized by name.
56 * (most of) these seem to be intrinsic types in mktyplib. */
58 static struct oatype {
59 const char *kw;
60 unsigned short vt;
61 } oatypes[] = {
62 {"BSTR", VT_BSTR},
63 {"CURRENCY", VT_CY},
64 {"DATE", VT_DATE},
65 {"DECIMAL", VT_DECIMAL},
66 {"HRESULT", VT_HRESULT},
67 {"LPSTR", VT_LPSTR},
68 {"LPWSTR", VT_LPWSTR},
69 {"SCODE", VT_ERROR},
70 {"VARIANT", VT_VARIANT},
71 {"VARIANT_BOOL", VT_BOOL}
73 #define NTYPES (sizeof(oatypes)/sizeof(oatypes[0]))
74 #define KWP(p) ((const struct oatype *)(p))
76 static int kw_cmp_func(const void *s1, const void *s2)
78 return strcmp(KWP(s1)->kw, KWP(s2)->kw);
81 static unsigned short builtin_vt(const char *kw)
83 struct oatype key, *kwp;
84 key.kw = kw;
85 #ifdef KW_BSEARCH
86 kwp = bsearch(&key, oatypes, NTYPES, sizeof(oatypes[0]), kw_cmp_func);
87 #else
89 unsigned int i;
90 for (kwp=NULL, i=0; i < NTYPES; i++)
91 if (!kw_cmp_func(&key, &oatypes[i])) {
92 kwp = &oatypes[i];
93 break;
96 #endif
97 if (kwp) {
98 return kwp->vt;
100 return 0;
103 static int match(const char*n, const char*m)
105 if (!n) return 0;
106 return !strcmp(n, m);
109 unsigned short get_type_vt(type_t *t)
111 unsigned short vt;
113 chat("get_type_vt: %p type->name %s\n", t, t->name);
114 if (t->name) {
115 vt = builtin_vt(t->name);
116 if (vt) return vt;
119 switch (t->type) {
120 case RPC_FC_BYTE:
121 case RPC_FC_USMALL:
122 return VT_UI1;
123 case RPC_FC_CHAR:
124 case RPC_FC_SMALL:
125 return VT_I1;
126 case RPC_FC_WCHAR:
127 return VT_I2; /* mktyplib seems to parse wchar_t as short */
128 case RPC_FC_SHORT:
129 return VT_I2;
130 case RPC_FC_USHORT:
131 return VT_UI2;
132 case RPC_FC_LONG:
133 if (t->ref && match(t->ref->name, "int")) return VT_INT;
134 return VT_I4;
135 case RPC_FC_ULONG:
136 if (t->ref && match(t->ref->name, "int")) return VT_UINT;
137 return VT_UI4;
138 case RPC_FC_HYPER:
139 if (t->sign < 0) return VT_UI8;
140 if (t->ref && match(t->ref->name, "MIDL_uhyper")) return VT_UI8;
141 return VT_I8;
142 case RPC_FC_FLOAT:
143 return VT_R4;
144 case RPC_FC_DOUBLE:
145 return VT_R8;
146 case RPC_FC_RP:
147 case RPC_FC_UP:
148 case RPC_FC_OP:
149 case RPC_FC_FP:
150 if(t->ref)
151 return VT_PTR;
153 error("get_type_vt: unknown-deref-type: %d\n", t->ref->type);
154 break;
155 case RPC_FC_IP:
156 if(match(t->name, "IUnknown"))
157 return VT_UNKNOWN;
158 if(match(t->name, "IDispatch"))
159 return VT_DISPATCH;
160 return VT_USERDEFINED;
162 case RPC_FC_ENUM16:
163 case RPC_FC_STRUCT:
164 case RPC_FC_PSTRUCT:
165 case RPC_FC_CSTRUCT:
166 case RPC_FC_CPSTRUCT:
167 case RPC_FC_CVSTRUCT:
168 case RPC_FC_BOGUS_STRUCT:
169 return VT_USERDEFINED;
170 case 0:
171 if(t->attrs)
172 return VT_USERDEFINED;
173 return 0;
174 default:
175 error("get_type_vt: unknown type: 0x%02x\n", t->type);
177 return 0;
180 unsigned short get_var_vt(var_t *v)
182 unsigned short vt;
184 chat("get_var_vt: %p tname %s\n", v, v->tname);
185 if (v->tname) {
186 vt = builtin_vt(v->tname);
187 if (vt) return vt;
190 return get_type_vt(v->type);
193 void start_typelib(char *name, attr_t *attrs)
195 in_typelib++;
196 if (!do_typelib) return;
198 typelib = xmalloc(sizeof(*typelib));
199 typelib->name = xstrdup(name);
200 typelib->filename = xstrdup(typelib_name);
201 typelib->attrs = attrs;
204 void end_typelib(void)
206 in_typelib--;
207 if (!typelib) return;
209 create_msft_typelib(typelib);
210 return;
213 void add_interface(type_t *iface)
215 typelib_entry_t *entry;
216 if (!typelib) return;
218 chat("add interface: %s\n", iface->name);
219 entry = xmalloc(sizeof(*entry));
220 entry->kind = TKIND_INTERFACE;
221 entry->u.interface = iface;
222 LINK(entry, typelib->entry);
223 typelib->entry = entry;
226 void add_coclass(class_t *cls)
228 typelib_entry_t *entry;
230 if (!typelib) return;
232 chat("add coclass: %s\n", cls->name);
234 entry = xmalloc(sizeof(*entry));
235 entry->kind = TKIND_COCLASS;
236 entry->u.class = cls;
237 LINK(entry, typelib->entry);
238 typelib->entry = entry;
241 void add_module(type_t *module)
243 typelib_entry_t *entry;
244 if (!typelib) return;
246 chat("add module: %s\n", module->name);
247 entry = xmalloc(sizeof(*entry));
248 entry->kind = TKIND_MODULE;
249 entry->u.module = module;
250 LINK(entry, typelib->entry);
251 typelib->entry = entry;
254 void add_struct(type_t *structure)
256 typelib_entry_t *entry;
257 if (!typelib) return;
259 chat("add struct: %s\n", structure->name);
260 entry = xmalloc(sizeof(*entry));
261 entry->kind = TKIND_RECORD;
262 entry->u.structure = structure;
263 LINK(entry, typelib->entry);
264 typelib->entry = entry;
267 void add_enum(type_t *enumeration)
269 typelib_entry_t *entry;
270 if (!typelib) return;
272 chat("add enum: %s\n", enumeration->name);
273 entry = xmalloc(sizeof(*entry));
274 entry->kind = TKIND_ENUM;
275 entry->u.enumeration = enumeration;
276 LINK(entry, typelib->entry);
277 typelib->entry = entry;
280 void add_typedef(type_t *tdef, var_t *name)
282 typelib_entry_t *entry;
283 if (!typelib) return;
285 chat("add typedef: %s\n", name->name);
286 entry = xmalloc(sizeof(*entry));
287 entry->kind = TKIND_ALIAS;
288 entry->u.tdef = xmalloc(sizeof(*entry->u.tdef));
289 memcpy(entry->u.tdef, name, sizeof(*name));
290 entry->u.tdef->type = tdef;
291 entry->u.tdef->name = xstrdup(name->name);
292 LINK(entry, typelib->entry);
293 typelib->entry = entry;
296 static void tlb_read(int fd, void *buf, size_t count)
298 if(read(fd, buf, count) < count)
299 error("error while reading importlib.\n");
302 static void tlb_lseek(int fd, off_t offset)
304 if(lseek(fd, offset, SEEK_SET) == -1)
305 error("lseek failed\n");
308 static void msft_read_guid(int fd, MSFT_SegDir *segdir, int offset, GUID *guid)
310 tlb_lseek(fd, segdir->pGuidTab.offset+offset);
311 tlb_read(fd, guid, sizeof(GUID));
314 static void read_msft_importlib(importlib_t *importlib, int fd)
316 MSFT_Header header;
317 MSFT_SegDir segdir;
318 int *typeinfo_offs;
319 int i;
321 importlib->allocated = 0;
323 tlb_lseek(fd, 0);
324 tlb_read(fd, &header, sizeof(header));
326 importlib->version = header.version;
328 typeinfo_offs = xmalloc(header.nrtypeinfos*sizeof(INT));
329 tlb_read(fd, typeinfo_offs, header.nrtypeinfos*sizeof(INT));
330 tlb_read(fd, &segdir, sizeof(segdir));
332 msft_read_guid(fd, &segdir, header.posguid, &importlib->guid);
334 importlib->ntypeinfos = header.nrtypeinfos;
335 importlib->importinfos = xmalloc(importlib->ntypeinfos*sizeof(importinfo_t));
337 for(i=0; i < importlib->ntypeinfos; i++) {
338 MSFT_TypeInfoBase base;
339 MSFT_NameIntro nameintro;
340 int len;
342 tlb_lseek(fd, sizeof(MSFT_Header) + header.nrtypeinfos*sizeof(INT) + sizeof(MSFT_SegDir)
343 + typeinfo_offs[i]);
344 tlb_read(fd, &base, sizeof(base));
346 importlib->importinfos[i].importlib = importlib;
347 importlib->importinfos[i].flags = (base.typekind&0xf)<<24;
348 importlib->importinfos[i].offset = -1;
349 importlib->importinfos[i].id = i;
351 if(base.posguid != -1) {
352 importlib->importinfos[i].flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
353 msft_read_guid(fd, &segdir, base.posguid, &importlib->importinfos[i].guid);
356 tlb_lseek(fd, segdir.pNametab.offset + base.NameOffset);
357 tlb_read(fd, &nameintro, sizeof(nameintro));
359 len = nameintro.namelen & 0xff;
361 importlib->importinfos[i].name = xmalloc(len+1);
362 tlb_read(fd, importlib->importinfos[i].name, len);
363 importlib->importinfos[i].name[len] = 0;
366 free(typeinfo_offs);
369 static void read_importlib(importlib_t *importlib)
371 int fd;
372 INT magic;
373 char *file_name;
375 file_name = wpp_find_include(importlib->name, NULL);
376 if(file_name) {
377 fd = open(file_name, O_RDONLY);
378 free(file_name);
379 }else {
380 fd = open(importlib->name, O_RDONLY);
383 if(fd < 0)
384 error("Could not open importlib %s.\n", importlib->name);
386 tlb_read(fd, &magic, sizeof(magic));
388 switch(magic) {
389 case MSFT_MAGIC:
390 read_msft_importlib(importlib, fd);
391 break;
392 default:
393 error("Wrong or unsupported typelib magic %x\n", magic);
396 close(fd);
399 void add_importlib(const char *name)
401 importlib_t *importlib;
403 if(!typelib) return;
405 for(importlib = typelib->importlibs; importlib; importlib = NEXT_LINK(importlib)) {
406 if(!strcmp(name, importlib->name))
407 return;
410 chat("add_importlib: %s\n", name);
412 importlib = xmalloc(sizeof(*importlib));
413 importlib->name = xstrdup(name);
415 read_importlib(importlib);
417 LINK(importlib, typelib->importlibs);
418 typelib->importlibs = importlib;