Added rules to parse library, coclass, dispinterface, and module
[wine] / tools / widl / typelib.c
1 /*
2  * IDL Compiler
3  *
4  * Copyright 2004 Ove Kaaven
5  *
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.
10  *
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.
15  *
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <string.h>
27 #include <assert.h>
28 #include <ctype.h>
29 #include <signal.h>
30
31 #include "widl.h"
32 #include "utils.h"
33 #include "parser.h"
34 #include "header.h"
35 #include "typelib.h"
36
37 int in_typelib = 0;
38 static FILE* typelib;
39
40 /* Copied from wtypes.h. Not included directly because that would create a
41  * circular dependency (after all, wtypes.h is generated by widl...) */
42
43 enum VARENUM {
44     VT_EMPTY = 0,
45     VT_NULL = 1,
46     VT_I2 = 2,
47     VT_I4 = 3,
48     VT_R4 = 4,
49     VT_R8 = 5,
50     VT_CY = 6,
51     VT_DATE = 7,
52     VT_BSTR = 8,
53     VT_DISPATCH = 9,
54     VT_ERROR = 10,
55     VT_BOOL = 11,
56     VT_VARIANT = 12,
57     VT_UNKNOWN = 13,
58     VT_DECIMAL = 14,
59     VT_I1 = 16,
60     VT_UI1 = 17,
61     VT_UI2 = 18,
62     VT_UI4 = 19,
63     VT_I8 = 20,
64     VT_UI8 = 21,
65     VT_INT = 22,
66     VT_UINT = 23,
67     VT_VOID = 24,
68     VT_HRESULT = 25,
69     VT_PTR = 26,
70     VT_SAFEARRAY = 27,
71     VT_CARRAY = 28,
72     VT_USERDEFINED = 29,
73     VT_LPSTR = 30,
74     VT_LPWSTR = 31,
75     VT_RECORD = 36,
76     VT_FILETIME = 64,
77     VT_BLOB = 65,
78     VT_STREAM = 66,
79     VT_STORAGE = 67,
80     VT_STREAMED_OBJECT = 68,
81     VT_STORED_OBJECT = 69,
82     VT_BLOB_OBJECT = 70,
83     VT_CF = 71,
84     VT_CLSID = 72,
85     VT_BSTR_BLOB = 0xfff,
86     VT_VECTOR = 0x1000,
87     VT_ARRAY = 0x2000,
88     VT_BYREF = 0x4000,
89     VT_RESERVED = 0x8000,
90     VT_ILLEGAL = 0xffff,
91     VT_ILLEGALMASKED = 0xfff,
92     VT_TYPEMASK = 0xfff
93 };
94
95 /* List of oleauto types that should be recognized by name.
96  * (most of) these seem to be intrinsic types in mktyplib. */
97
98 static struct oatype {
99   const char *kw;
100   unsigned short vt;
101 } oatypes[] = {
102   {"BSTR",      VT_BSTR},
103   {"CURRENCY",  VT_CY},
104   {"DATE",      VT_DATE},
105   {"DECIMAL",   VT_DECIMAL},
106   {"HRESULT",   VT_HRESULT},
107   {"LPSTR",     VT_LPSTR},
108   {"LPWSTR",    VT_LPWSTR},
109   {"SCODE",     VT_ERROR},
110   {"VARIANT",   VT_VARIANT}
111 };
112 #define NTYPES (sizeof(oatypes)/sizeof(oatypes[0]))
113 #define KWP(p) ((struct oatype *)(p))
114
115 static int kw_cmp_func(const void *s1, const void *s2)
116 {
117         return strcmp(KWP(s1)->kw, KWP(s2)->kw);
118 }
119
120 static unsigned short builtin_vt(const char *kw)
121 {
122   struct oatype key, *kwp;
123   key.kw = kw;
124 #ifdef KW_BSEARCH
125   kwp = bsearch(&key, oatypes, NTYPES, sizeof(oatypes[0]), kw_cmp_func);
126 #else
127   {
128     int i;
129     for (kwp=NULL, i=0; i < NTYPES; i++)
130       if (!kw_cmp_func(&key, &oatypes[i])) {
131         kwp = &oatypes[i];
132         break;
133       }
134   }
135 #endif
136   if (kwp) {
137     return kwp->vt;
138   }
139   return 0;
140 }
141
142 static int match(const char*n, const char*m)
143 {
144   if (!n) return 0;
145   return !strcmp(n, m);
146 }
147
148 unsigned short get_type_vt(type_t *t)
149 {
150   unsigned short vt;
151
152   if (t->name) {
153     vt = builtin_vt(t->name);
154     if (vt) return vt;
155   }
156
157   switch (t->type) {
158   case RPC_FC_BYTE:
159   case RPC_FC_USMALL:
160     return VT_UI1;
161   case RPC_FC_CHAR:
162   case RPC_FC_SMALL:
163     return VT_I1;
164   case RPC_FC_WCHAR:
165     return VT_I2; /* mktyplib seems to parse wchar_t as short */
166   case RPC_FC_SHORT:
167     return VT_I2;
168   case RPC_FC_USHORT:
169     return VT_UI2;
170   case RPC_FC_LONG:
171     if (t->ref && match(t->ref->name, "int")) return VT_INT;
172     return VT_I4;
173   case RPC_FC_ULONG:
174     if (t->ref && match(t->ref->name, "int")) return VT_UINT;
175     return VT_UI4;
176   case RPC_FC_HYPER:
177     if (t->sign < 0) return VT_UI8;
178     if (t->ref && match(t->ref->name, "MIDL_uhyper")) return VT_UI8;
179     return VT_I8;
180   case RPC_FC_FLOAT:
181     return VT_R4;
182   case RPC_FC_DOUBLE:
183     return VT_R8;
184   case RPC_FC_RP:
185   case RPC_FC_UP:
186   case RPC_FC_OP:
187   case RPC_FC_FP:
188     /* it's a pointer... */
189     if (t->ref && t->ref->type == RPC_FC_IP) {
190       /* it's to an interface, which one? */
191       if (match(t->ref->name, "IDispatch"))
192         return VT_DISPATCH;
193       if (match(t->ref->name, "IUnknown"))
194         return VT_UNKNOWN;
195     }
196     /* FIXME: should we recurse and add a VT_BYREF? */
197     /* Or just return VT_PTR? */
198     error("get_type_vt: unknown-deref-type: %d\n", t->ref->type);
199     break;
200   default:
201     error("get_type_vt: unknown-type: %d\n", t->type);
202   }
203   return 0;
204 }
205
206 unsigned short get_var_vt(var_t *v)
207 {
208   unsigned short vt;
209
210   if (v->tname) {
211     vt = builtin_vt(v->tname);
212     if (vt) return vt;
213   }
214
215   return get_type_vt(v->type);
216 }
217
218 void start_typelib(char *name, attr_t *attrs)
219 {
220   in_typelib++;
221   if (!do_everything && !typelib_only) return;
222   typelib = fopen(typelib_name, "wb");
223 }
224
225 void end_typelib(void)
226 {
227   if (typelib) fclose(typelib);
228   in_typelib--;
229 }
230
231 void add_interface(type_t *iface)
232 {
233   if (!typelib) return;
234
235   /* FIXME: add interface and dependent types to typelib */
236   printf("add interface: %s\n", iface->name);
237 }
238
239 void add_coclass(class_t *cls)
240 {
241   ifref_t *lcur = cls->ifaces;
242   ifref_t *cur;
243
244   if (lcur) {
245     while (NEXT_LINK(lcur)) lcur = NEXT_LINK(lcur);
246   }
247
248   if (!typelib) return;
249
250   /* install interfaces the coclass depends on */
251   cur = lcur;
252   while (cur) {
253     add_interface(cur->iface);
254     cur = PREV_LINK(cur);
255   }
256
257   /* FIXME: add coclass to typelib */
258   printf("add coclass: %s\n", cls->name);
259 }
260
261 void add_module(type_t *module)
262 {
263   if (!typelib) return;
264
265   /* FIXME: add module to typelib */
266   printf("add module: %s\n", module->name);
267 }