comctl32: rebar: Fix lpBand->lpText memory leak in DeleteBand and simplify the code.
[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 type_t *duptype(type_t *t, int dupname)
54 {
55   type_t *d = xmalloc(sizeof *d);
56
57   *d = *t;
58   if (dupname && t->name)
59     d->name = xstrdup(t->name);
60
61   d->orig = t;
62   return d;
63 }
64
65 type_t *alias(type_t *t, const char *name)
66 {
67   type_t *a = duptype(t, 0);
68
69   a->name = xstrdup(name);
70   a->kind = TKIND_ALIAS;
71   a->attrs = NULL;
72
73   return a;
74 }
75
76 int is_ptr(const type_t *t)
77 {
78   unsigned char c = t->type;
79   return c == RPC_FC_RP
80       || c == RPC_FC_UP
81       || c == RPC_FC_FP
82       || c == RPC_FC_OP;
83 }
84
85 /* List of oleauto types that should be recognized by name.
86  * (most of) these seem to be intrinsic types in mktyplib. */
87
88 static struct oatype {
89   const char *kw;
90   unsigned short vt;
91 } oatypes[] = {
92   {"BSTR",          VT_BSTR},
93   {"CURRENCY",      VT_CY},
94   {"DATE",          VT_DATE},
95   {"DECIMAL",       VT_DECIMAL},
96   {"HRESULT",       VT_HRESULT},
97   {"LPSTR",         VT_LPSTR},
98   {"LPWSTR",        VT_LPWSTR},
99   {"SCODE",         VT_ERROR},
100   {"VARIANT",       VT_VARIANT},
101   {"VARIANT_BOOL",  VT_BOOL}
102 };
103 #define NTYPES (sizeof(oatypes)/sizeof(oatypes[0]))
104 #define KWP(p) ((const struct oatype *)(p))
105
106 static int kw_cmp_func(const void *s1, const void *s2)
107 {
108         return strcmp(KWP(s1)->kw, KWP(s2)->kw);
109 }
110
111 static unsigned short builtin_vt(const char *kw)
112 {
113   struct oatype key, *kwp;
114   key.kw = kw;
115 #ifdef KW_BSEARCH
116   kwp = bsearch(&key, oatypes, NTYPES, sizeof(oatypes[0]), kw_cmp_func);
117 #else
118   {
119     unsigned int i;
120     for (kwp=NULL, i=0; i < NTYPES; i++)
121       if (!kw_cmp_func(&key, &oatypes[i])) {
122         kwp = &oatypes[i];
123         break;
124       }
125   }
126 #endif
127   if (kwp) {
128     return kwp->vt;
129   }
130   return 0;
131 }
132
133 static int match(const char*n, const char*m)
134 {
135   if (!n) return 0;
136   return !strcmp(n, m);
137 }
138
139 unsigned short get_type_vt(type_t *t)
140 {
141   unsigned short vt;
142
143   chat("get_type_vt: %p type->name %s\n", t, t->name);
144   if (t->name) {
145     vt = builtin_vt(t->name);
146     if (vt) return vt;
147   }
148
149   if (t->kind == TKIND_ALIAS && t->attrs)
150     return VT_USERDEFINED;
151
152   switch (t->type) {
153   case RPC_FC_BYTE:
154   case RPC_FC_USMALL:
155     return VT_UI1;
156   case RPC_FC_CHAR:
157   case RPC_FC_SMALL:
158     return VT_I1;
159   case RPC_FC_WCHAR:
160     return VT_I2; /* mktyplib seems to parse wchar_t as short */
161   case RPC_FC_SHORT:
162     return VT_I2;
163   case RPC_FC_USHORT:
164     return VT_UI2;
165   case RPC_FC_LONG:
166     if (match(t->name, "int")) return VT_INT;
167     return VT_I4;
168   case RPC_FC_ULONG:
169     if (match(t->name, "int")) return VT_UINT;
170     return VT_UI4;
171   case RPC_FC_HYPER:
172     if (t->sign < 0) return VT_UI8;
173     if (match(t->name, "MIDL_uhyper")) return VT_UI8;
174     return VT_I8;
175   case RPC_FC_FLOAT:
176     return VT_R4;
177   case RPC_FC_DOUBLE:
178     return VT_R8;
179   case RPC_FC_RP:
180   case RPC_FC_UP:
181   case RPC_FC_OP:
182   case RPC_FC_FP:
183     if(t->ref)
184       return VT_PTR;
185
186     error("get_type_vt: unknown-deref-type: %d\n", t->ref->type);
187     break;
188   case RPC_FC_IP:
189     if(match(t->name, "IUnknown"))
190       return VT_UNKNOWN;
191     if(match(t->name, "IDispatch"))
192       return VT_DISPATCH;
193     return VT_USERDEFINED;
194
195   case RPC_FC_ENUM16:
196   case RPC_FC_STRUCT:
197   case RPC_FC_PSTRUCT:
198   case RPC_FC_CSTRUCT:
199   case RPC_FC_CPSTRUCT:
200   case RPC_FC_CVSTRUCT:
201   case RPC_FC_BOGUS_STRUCT:
202     return VT_USERDEFINED;
203   case 0:
204     return t->kind == TKIND_PRIMITIVE ? VT_VOID : VT_USERDEFINED;
205   default:
206     error("get_type_vt: unknown type: 0x%02x\n", t->type);
207   }
208   return 0;
209 }
210
211 unsigned short get_var_vt(var_t *v)
212 {
213   unsigned short vt;
214
215   chat("get_var_vt: %p tname %s\n", v, v->tname);
216   if (v->tname) {
217     vt = builtin_vt(v->tname);
218     if (vt) return vt;
219   }
220
221   return get_type_vt(v->type);
222 }
223
224 void start_typelib(char *name, attr_list_t *attrs)
225 {
226     in_typelib++;
227     if (!do_typelib) return;
228
229     typelib = xmalloc(sizeof(*typelib));
230     typelib->name = xstrdup(name);
231     typelib->filename = xstrdup(typelib_name);
232     typelib->attrs = attrs;
233     list_init( &typelib->entries );
234     list_init( &typelib->importlibs );
235 }
236
237 void end_typelib(void)
238 {
239     in_typelib--;
240     if (!typelib) return;
241
242     create_msft_typelib(typelib);
243     return;
244 }
245
246 void add_typelib_entry(type_t *t)
247 {
248     typelib_entry_t *entry;
249     if (!typelib) return;
250
251     chat("add kind %i: %s\n", t->kind, t->name);
252     entry = xmalloc(sizeof(*entry));
253     entry->type = t;
254     list_add_tail( &typelib->entries, &entry->entry );
255 }
256
257 static void tlb_read(int fd, void *buf, int count)
258 {
259     if(read(fd, buf, count) < count)
260         error("error while reading importlib.\n");
261 }
262
263 static void tlb_lseek(int fd, off_t offset)
264 {
265     if(lseek(fd, offset, SEEK_SET) == -1)
266         error("lseek failed\n");
267 }
268
269 static void msft_read_guid(int fd, MSFT_SegDir *segdir, int offset, GUID *guid)
270 {
271     tlb_lseek(fd, segdir->pGuidTab.offset+offset);
272     tlb_read(fd, guid, sizeof(GUID));
273 }
274
275 static void read_msft_importlib(importlib_t *importlib, int fd)
276 {
277     MSFT_Header header;
278     MSFT_SegDir segdir;
279     int *typeinfo_offs;
280     int i;
281
282     importlib->allocated = 0;
283
284     tlb_lseek(fd, 0);
285     tlb_read(fd, &header, sizeof(header));
286
287     importlib->version = header.version;
288
289     typeinfo_offs = xmalloc(header.nrtypeinfos*sizeof(INT));
290     tlb_read(fd, typeinfo_offs, header.nrtypeinfos*sizeof(INT));
291     tlb_read(fd, &segdir, sizeof(segdir));
292
293     msft_read_guid(fd, &segdir, header.posguid, &importlib->guid);
294
295     importlib->ntypeinfos = header.nrtypeinfos;
296     importlib->importinfos = xmalloc(importlib->ntypeinfos*sizeof(importinfo_t));
297
298     for(i=0; i < importlib->ntypeinfos; i++) {
299         MSFT_TypeInfoBase base;
300         MSFT_NameIntro nameintro;
301         int len;
302
303         tlb_lseek(fd, sizeof(MSFT_Header) + header.nrtypeinfos*sizeof(INT) + sizeof(MSFT_SegDir)
304                  + typeinfo_offs[i]);
305         tlb_read(fd, &base, sizeof(base));
306
307         importlib->importinfos[i].importlib = importlib;
308         importlib->importinfos[i].flags = (base.typekind&0xf)<<24;
309         importlib->importinfos[i].offset = -1;
310         importlib->importinfos[i].id = i;
311
312         if(base.posguid != -1) {
313             importlib->importinfos[i].flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
314             msft_read_guid(fd, &segdir, base.posguid, &importlib->importinfos[i].guid);
315         }
316         else memset( &importlib->importinfos[i].guid, 0, sizeof(importlib->importinfos[i].guid));
317
318         tlb_lseek(fd, segdir.pNametab.offset + base.NameOffset);
319         tlb_read(fd, &nameintro, sizeof(nameintro));
320
321         len = nameintro.namelen & 0xff;
322
323         importlib->importinfos[i].name = xmalloc(len+1);
324         tlb_read(fd, importlib->importinfos[i].name, len);
325         importlib->importinfos[i].name[len] = 0;
326     }
327
328     free(typeinfo_offs);
329 }
330
331 static void read_importlib(importlib_t *importlib)
332 {
333     int fd;
334     INT magic;
335     char *file_name;
336
337     file_name = wpp_find_include(importlib->name, NULL);
338     if(file_name) {
339         fd = open(file_name, O_RDONLY);
340         free(file_name);
341     }else {
342         fd = open(importlib->name, O_RDONLY);
343     }
344
345     if(fd < 0)
346         error("Could not open importlib %s.\n", importlib->name);
347
348     tlb_read(fd, &magic, sizeof(magic));
349
350     switch(magic) {
351     case MSFT_MAGIC:
352         read_msft_importlib(importlib, fd);
353         break;
354     default:
355         error("Wrong or unsupported typelib magic %x\n", magic);
356     };
357
358     close(fd);
359 }
360
361 void add_importlib(const char *name)
362 {
363     importlib_t *importlib;
364
365     if(!typelib) return;
366
367     LIST_FOR_EACH_ENTRY( importlib, &typelib->importlibs, importlib_t, entry )
368         if(!strcmp(name, importlib->name))
369             return;
370
371     chat("add_importlib: %s\n", name);
372
373     importlib = xmalloc(sizeof(*importlib));
374     memset( importlib, 0, sizeof(*importlib) );
375     importlib->name = xstrdup(name);
376
377     read_importlib(importlib);
378     list_add_head( &typelib->importlibs, &importlib->entry );
379 }