widl: Fix a typo in the man page.
[wine] / tools / widl / typelib.c
1 /*
2  * IDL Compiler
3  *
4  * Copyright 2004 Ove Kaaven
5  * Copyright 2006 Jacek Caban for CodeWeavers
6  *
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.
11  *
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.
16  *
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
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24 #include "wine/wpp.h"
25
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>
34
35 #define NONAMELESSUNION
36 #define NONAMELESSSTRUCT
37
38 #include "windef.h"
39 #include "winbase.h"
40
41 #include "widl.h"
42 #include "utils.h"
43 #include "parser.h"
44 #include "header.h"
45 #include "typelib.h"
46 #include "widltypes.h"
47 #include "typelib_struct.h"
48
49 int in_typelib = 0;
50
51 static typelib_t *typelib;
52
53 /* List of oleauto types that should be recognized by name.
54  * (most of) these seem to be intrinsic types in mktyplib. */
55
56 static struct oatype {
57   const char *kw;
58   unsigned short vt;
59 } oatypes[] = {
60   {"BSTR",          VT_BSTR},
61   {"CURRENCY",      VT_CY},
62   {"DATE",          VT_DATE},
63   {"DECIMAL",       VT_DECIMAL},
64   {"HRESULT",       VT_HRESULT},
65   {"LPSTR",         VT_LPSTR},
66   {"LPWSTR",        VT_LPWSTR},
67   {"SCODE",         VT_ERROR},
68   {"VARIANT",       VT_VARIANT},
69   {"VARIANT_BOOL",  VT_BOOL}
70 };
71 #define NTYPES (sizeof(oatypes)/sizeof(oatypes[0]))
72 #define KWP(p) ((const struct oatype *)(p))
73
74 static int kw_cmp_func(const void *s1, const void *s2)
75 {
76         return strcmp(KWP(s1)->kw, KWP(s2)->kw);
77 }
78
79 static unsigned short builtin_vt(const char *kw)
80 {
81   struct oatype key, *kwp;
82   key.kw = kw;
83 #ifdef KW_BSEARCH
84   kwp = bsearch(&key, oatypes, NTYPES, sizeof(oatypes[0]), kw_cmp_func);
85 #else
86   {
87     unsigned int i;
88     for (kwp=NULL, i=0; i < NTYPES; i++)
89       if (!kw_cmp_func(&key, &oatypes[i])) {
90         kwp = &oatypes[i];
91         break;
92       }
93   }
94 #endif
95   if (kwp) {
96     return kwp->vt;
97   }
98   return 0;
99 }
100
101 static int match(const char*n, const char*m)
102 {
103   if (!n) return 0;
104   return !strcmp(n, m);
105 }
106
107 unsigned short get_type_vt(type_t *t)
108 {
109   unsigned short vt;
110
111   chat("get_type_vt: %p type->name %s\n", t, t->name);
112   if (t->name) {
113     vt = builtin_vt(t->name);
114     if (vt) return vt;
115   }
116
117   switch (t->type) {
118   case RPC_FC_BYTE:
119   case RPC_FC_USMALL:
120     return VT_UI1;
121   case RPC_FC_CHAR:
122   case RPC_FC_SMALL:
123     return VT_I1;
124   case RPC_FC_WCHAR:
125     return VT_I2; /* mktyplib seems to parse wchar_t as short */
126   case RPC_FC_SHORT:
127     return VT_I2;
128   case RPC_FC_USHORT:
129     return VT_UI2;
130   case RPC_FC_LONG:
131     if (t->ref && match(t->ref->name, "int")) return VT_INT;
132     return VT_I4;
133   case RPC_FC_ULONG:
134     if (t->ref && match(t->ref->name, "int")) return VT_UINT;
135     return VT_UI4;
136   case RPC_FC_HYPER:
137     if (t->sign < 0) return VT_UI8;
138     if (t->ref && match(t->ref->name, "MIDL_uhyper")) return VT_UI8;
139     return VT_I8;
140   case RPC_FC_FLOAT:
141     return VT_R4;
142   case RPC_FC_DOUBLE:
143     return VT_R8;
144   case RPC_FC_RP:
145   case RPC_FC_UP:
146   case RPC_FC_OP:
147   case RPC_FC_FP:
148     if(t->ref)
149       return VT_PTR;
150
151     error("get_type_vt: unknown-deref-type: %d\n", t->ref->type);
152     break;
153   case RPC_FC_IP:
154     if(match(t->name, "IUnknown"))
155       return VT_UNKNOWN;
156     if(match(t->name, "IDispatch"))
157       return VT_DISPATCH;
158     return VT_USERDEFINED;
159
160   case RPC_FC_ENUM16:
161   case RPC_FC_STRUCT:
162   case RPC_FC_PSTRUCT:
163   case RPC_FC_CSTRUCT:
164   case RPC_FC_CPSTRUCT:
165   case RPC_FC_CVSTRUCT:
166   case RPC_FC_BOGUS_STRUCT:
167     return VT_USERDEFINED;
168   case 0:
169     if(t->attrs)
170         return VT_USERDEFINED;
171     return 0;
172   default:
173     error("get_type_vt: unknown type: 0x%02x\n", t->type);
174   }
175   return 0;
176 }
177
178 unsigned short get_var_vt(var_t *v)
179 {
180   unsigned short vt;
181
182   chat("get_var_vt: %p tname %s\n", v, v->tname);
183   if (v->tname) {
184     vt = builtin_vt(v->tname);
185     if (vt) return vt;
186   }
187
188   return get_type_vt(v->type);
189 }
190
191 void start_typelib(char *name, attr_t *attrs)
192 {
193     in_typelib++;
194     if (!do_typelib) return;
195
196     typelib = xmalloc(sizeof(*typelib));
197     typelib->name = xstrdup(name);
198     typelib->filename = xstrdup(typelib_name);
199     typelib->attrs = attrs;
200 }
201
202 void end_typelib(void)
203 {
204     in_typelib--;
205     if (!typelib) return;
206
207     create_msft_typelib(typelib);
208     return;
209 }
210
211 void add_interface(type_t *iface)
212 {
213     typelib_entry_t *entry;
214     if (!typelib) return;
215
216     chat("add interface: %s\n", iface->name);
217     entry = xmalloc(sizeof(*entry));
218     entry->kind = TKIND_INTERFACE;
219     entry->u.interface = iface;
220     LINK(entry, typelib->entry);
221     typelib->entry = entry;
222 }
223
224 void add_coclass(class_t *cls)
225 {
226     typelib_entry_t *entry;
227
228     if (!typelib) return;
229
230     chat("add coclass: %s\n", cls->name);
231
232     entry = xmalloc(sizeof(*entry));
233     entry->kind = TKIND_COCLASS;
234     entry->u.class = cls;
235     LINK(entry, typelib->entry);
236     typelib->entry = entry;
237 }
238
239 void add_module(type_t *module)
240 {
241     typelib_entry_t *entry;
242     if (!typelib) return;
243
244     chat("add module: %s\n", module->name);
245     entry = xmalloc(sizeof(*entry));
246     entry->kind = TKIND_MODULE;
247     entry->u.module = module;
248     LINK(entry, typelib->entry);
249     typelib->entry = entry;
250 }
251
252 void add_struct(type_t *structure)
253 {
254      typelib_entry_t *entry;
255      if (!typelib) return;
256
257      chat("add struct: %s\n", structure->name);
258      entry = xmalloc(sizeof(*entry));
259      entry->kind = TKIND_RECORD;
260      entry->u.structure = structure;
261      LINK(entry, typelib->entry);
262      typelib->entry = entry;
263 }
264
265 void add_enum(type_t *enumeration)
266 {
267      typelib_entry_t *entry;
268      if (!typelib) return;
269
270      chat("add enum: %s\n", enumeration->name);
271      entry = xmalloc(sizeof(*entry));
272      entry->kind = TKIND_ENUM;
273      entry->u.enumeration = enumeration;
274      LINK(entry, typelib->entry);
275      typelib->entry = entry;
276 }
277
278 void add_typedef(type_t *tdef, var_t *name)
279 {
280      typelib_entry_t *entry;
281      if (!typelib) return;
282
283      chat("add typedef: %s\n", name->name);
284      entry = xmalloc(sizeof(*entry));
285      entry->kind = TKIND_ALIAS;
286      entry->u.tdef = xmalloc(sizeof(*entry->u.tdef));
287      memcpy(entry->u.tdef, name, sizeof(*name));
288      entry->u.tdef->type = tdef;
289      entry->u.tdef->name = xstrdup(name->name);
290      LINK(entry, typelib->entry);
291      typelib->entry = entry;
292 }
293
294 static void tlb_read(int fd, void *buf, size_t count)
295 {
296     if(read(fd, buf, count) < count)
297         error("error while reading importlib.\n");
298 }
299
300 static void tlb_lseek(int fd, off_t offset)
301 {
302     if(lseek(fd, offset, SEEK_SET) == -1)
303         error("lseek failed\n");
304 }
305
306 static void msft_read_guid(int fd, MSFT_SegDir *segdir, int offset, GUID *guid)
307 {
308     tlb_lseek(fd, segdir->pGuidTab.offset+offset);
309     tlb_read(fd, guid, sizeof(GUID));
310 }
311
312 static void read_msft_importlib(importlib_t *importlib, int fd)
313 {
314     MSFT_Header header;
315     MSFT_SegDir segdir;
316     int *typeinfo_offs;
317     int i;
318
319     importlib->allocated = 0;
320
321     tlb_lseek(fd, 0);
322     tlb_read(fd, &header, sizeof(header));
323
324     importlib->version = header.version;
325
326     typeinfo_offs = xmalloc(header.nrtypeinfos*sizeof(INT));
327     tlb_read(fd, typeinfo_offs, header.nrtypeinfos*sizeof(INT));
328     tlb_read(fd, &segdir, sizeof(segdir));
329
330     msft_read_guid(fd, &segdir, header.posguid, &importlib->guid);
331
332     importlib->ntypeinfos = header.nrtypeinfos;
333     importlib->importinfos = xmalloc(importlib->ntypeinfos*sizeof(importinfo_t));
334
335     for(i=0; i < importlib->ntypeinfos; i++) {
336         MSFT_TypeInfoBase base;
337         MSFT_NameIntro nameintro;
338         int len;
339
340         tlb_lseek(fd, sizeof(MSFT_Header) + header.nrtypeinfos*sizeof(INT) + sizeof(MSFT_SegDir)
341                  + typeinfo_offs[i]);
342         tlb_read(fd, &base, sizeof(base));
343
344         importlib->importinfos[i].importlib = importlib;
345         importlib->importinfos[i].flags = (base.typekind&0xf)<<24;
346         importlib->importinfos[i].offset = -1;
347         importlib->importinfos[i].id = i;
348
349         if(base.posguid != -1) {
350             importlib->importinfos[i].flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
351             msft_read_guid(fd, &segdir, base.posguid, &importlib->importinfos[i].guid);
352         }
353
354         tlb_lseek(fd, segdir.pNametab.offset + base.NameOffset);
355         tlb_read(fd, &nameintro, sizeof(nameintro));
356
357         len = nameintro.namelen & 0xff;
358
359         importlib->importinfos[i].name = xmalloc(len+1);
360         tlb_read(fd, importlib->importinfos[i].name, len);
361         importlib->importinfos[i].name[len] = 0;
362     }
363
364     free(typeinfo_offs);
365 }
366
367 static void read_importlib(importlib_t *importlib)
368 {
369     int fd;
370     INT magic;
371     char *file_name;
372
373     file_name = wpp_find_include(importlib->name, NULL);
374     if(file_name) {
375         fd = open(file_name, O_RDONLY);
376         free(file_name);
377     }else {
378         fd = open(importlib->name, O_RDONLY);
379     }
380
381     if(fd < 0)
382         error("Could not open importlib %s.\n", importlib->name);
383
384     tlb_read(fd, &magic, sizeof(magic));
385
386     switch(magic) {
387     case MSFT_MAGIC:
388         read_msft_importlib(importlib, fd);
389         break;
390     default:
391         error("Wrong or unsupported typelib magic %x\n", magic);
392     };
393
394     close(fd);
395 }
396
397 void add_importlib(const char *name)
398 {
399     importlib_t *importlib;
400
401     if(!typelib) return;
402
403     for(importlib = typelib->importlibs; importlib; importlib = NEXT_LINK(importlib)) {
404         if(!strcmp(name, importlib->name))
405             return;
406     }
407
408     chat("add_importlib: %s\n", name);
409
410     importlib = xmalloc(sizeof(*importlib));
411     importlib->name = xstrdup(name);
412
413     read_importlib(importlib);
414
415     LINK(importlib, typelib->importlibs);
416     typelib->importlibs = importlib;
417 }