Include guiddef.h in widltypes.h.
[wine/multimedia.git] / tools / widl / parser.l
bloba7bc76aa75c8aa6da2ad48bea1f13c46c75e9303
1 /*
2  * IDL Compiler
3  *
4  * Copyright 2002 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  */
21 %option stack
22 %option never-interactive
24 nl      \r?\n
25 ws      [ \f\t\r]
26 cident  [a-zA-Z_][0-9a-zA-Z_]*
27 int     [0-9]+
28 hexd    [0-9a-fA-F]
29 hex     0x{hexd}+
30 uuid    {hexd}{8}-{hexd}{4}-{hexd}{4}-{hexd}{4}-{hexd}{12}
32 %x QUOTE
36 #include "config.h"
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <ctype.h>
42 #include <assert.h>
43 #ifdef HAVE_UNISTD_H
44 # include <unistd.h>
45 #endif
47 #include "widl.h"
48 #include "utils.h"
49 #include "parser.h"
50 #include "../wpp/wpp.h"
52 #include "y.tab.h"
54 #define YY_USE_PROTOS
55 #define YY_NO_UNPUT
56 #define YY_NO_TOP_STATE
58 extern char *temp_name;
60 static void addcchar(char c);
61 static char *get_buffered_cstring(void);
63 static char *cbuffer;
64 static int cbufidx;
65 static int cbufalloc = 0;
67 static int kw_token(const char *kw);
69 #define MAX_IMPORT_DEPTH 10
70 struct {
71   YY_BUFFER_STATE state;
72   char *temp_name;
73 } import_stack[MAX_IMPORT_DEPTH];
74 int import_stack_ptr = 0;
76 static void pop_import(void);
78 static UUID* parse_uuid(const char*u)
80   UUID* uuid = xmalloc(sizeof(UUID));
81   char b[3];
82   /* it would be nice to use UuidFromStringA */
83   uuid->Data1 = strtoul(u, NULL, 16);
84   uuid->Data2 = strtoul(u+9, NULL, 16);
85   uuid->Data3 = strtoul(u+14, NULL, 16);
86   b[2] = 0;
87   memcpy(b, u+19, 2); uuid->Data4[0] = strtoul(b, NULL, 16);
88   memcpy(b, u+21, 2); uuid->Data4[1] = strtoul(b, NULL, 16);
89   memcpy(b, u+24, 2); uuid->Data4[2] = strtoul(b, NULL, 16);
90   memcpy(b, u+26, 2); uuid->Data4[3] = strtoul(b, NULL, 16);
91   memcpy(b, u+28, 2); uuid->Data4[4] = strtoul(b, NULL, 16);
92   memcpy(b, u+30, 2); uuid->Data4[5] = strtoul(b, NULL, 16);
93   memcpy(b, u+32, 2); uuid->Data4[6] = strtoul(b, NULL, 16);
94   memcpy(b, u+34, 2); uuid->Data4[7] = strtoul(b, NULL, 16);
95   return uuid;
101  **************************************************************************
102  * The flexer starts here
103  **************************************************************************
104  */
106 ^#.*
107 \"                      yy_push_state(QUOTE); cbufidx = 0;
108 <QUOTE>\"               {
109                                 yy_pop_state();
110                                 yylval.str = get_buffered_cstring();
111                                 return aSTRING;
112                         }
113 <QUOTE>\\\\             |
114 <QUOTE>\\\"             addcchar(yytext[1]);
115 <QUOTE>\\.              addcchar('\\'); addcchar(yytext[1]);
116 <QUOTE>.                addcchar(yytext[0]);
117 {uuid}                  {
118                                 yylval.uuid = parse_uuid(yytext);
119                                 return aUUID;
120                         }
121 {hex}                   {
122                                 yylval.num = strtol(yytext, NULL, 0);
123                                 return aHEXNUM;
124                         }
125 {int}                   {
126                                 yylval.num = strtol(yytext, NULL, 0);
127                                 return aNUM;
128                         }
129 {cident}                return kw_token(yytext);
131 {ws}
132 \<\<                    return SHL;
133 \>\>                    return SHR;
134 .                       return yytext[0];
135 <<EOF>>                 {
136                                 if (import_stack_ptr) {
137                                         pop_import();
138                                         return aEOF;
139                                 }
140                                 else yyterminate();
141                         }
144 #ifndef yywrap
145 int yywrap(void)
147         return 1;
149 #endif
151 static struct keyword {
152         const char *kw;
153         int token;
154         int val;
155 } keywords[] = {
156         {"__cdecl",                     tCDECL},
157         {"__int64",                     tINT64},
158         {"__stdcall",                   tSTDCALL},
159         {"_stdcall",                    tSTDCALL},
160         {"aggregatable",                tAGGREGATABLE},
161         {"allocate",                    tALLOCATE},
162         {"appobject",                   tAPPOBJECT},
163         {"arrays",                      tARRAYS},
164         {"async",                       tASYNC},
165         {"async_uuid",                  tASYNCUUID},
166         {"auto_handle",                 tAUTOHANDLE},
167         {"bindable",                    tBINDABLE},
168         {"boolean",                     tBOOLEAN},
169         {"broadcast",                   tBROADCAST},
170         {"byte",                        tBYTE},
171         {"byte_count",                  tBYTECOUNT},
172         {"call_as",                     tCALLAS},
173         {"callback",                    tCALLBACK},
174         {"case",                        tCASE},
175         {"char",                        tCHAR},
176         {"coclass",                     tCOCLASS},
177         {"code",                        tCODE},
178         {"comm_status",                 tCOMMSTATUS},
179         {"const",                       tCONST},
180         {"context_handle",              tCONTEXTHANDLE},
181         {"context_handle_noserialize",  tCONTEXTHANDLENOSERIALIZE},
182         {"context_handle_serialize",    tCONTEXTHANDLENOSERIALIZE},
183         {"control",                     tCONTROL},
184         {"cpp_quote",                   tCPPQUOTE},
185 /* ... */
186         {"default",                     tDEFAULT},
187 /* ... */
188         {"double",                      tDOUBLE},
189 /* ... */
190         {"enum",                        tENUM},
191         {"error_status_t",              tERRORSTATUST},
192 /* ... */
193         {"extern",                      tEXTERN},
194 /* ... */
195         {"float",                       tFLOAT},
196 /* ... */
197         {"handle_t",                    tHANDLET},
198 /* ... */
199         {"hyper",                       tHYPER},
200 /* ... */
201         {"idempotent",                  tIDEMPOTENT},
202 /* ... */
203         {"iid_is",                      tIIDIS},
204 /* ... */
205         {"import",                      tIMPORT},
206         {"importlib",                   tIMPORTLIB},
207         {"in",                          tIN},
208         {"include",                     tINCLUDE},
209         {"in_line",                     tINLINE},
210         {"int",                         tINT},
211 /* ... */
212         {"interface",                   tINTERFACE},
213 /* ... */
214         {"length_is",                   tLENGTHIS},
215 /* ... */
216         {"local",                       tLOCAL},
217         {"long",                        tLONG},
218 /* ... */
219         {"object",                      tOBJECT},
220         {"odl",                         tODL},
221         {"oleautomation",               tOLEAUTOMATION},
222 /* ... */
223         {"out",                         tOUT},
224 /* ... */
225         {"pointer_default",             tPOINTERDEFAULT},
226 /* ... */
227         {"ref",                         tREF},
228 /* ... */
229         {"short",                       tSHORT},
230         {"signed",                      tSIGNED},
231         {"size_is",                     tSIZEIS},
232         {"sizeof",                      tSIZEOF},
233 /* ... */
234         {"string",                      tSTRING},
235         {"struct",                      tSTRUCT},
236         {"switch",                      tSWITCH},
237         {"switch_is",                   tSWITCHIS},
238         {"switch_type",                 tSWITCHTYPE},
239 /* ... */
240         {"typedef",                     tTYPEDEF},
241         {"union",                       tUNION},
242 /* ... */
243         {"unique",                      tUNIQUE},
244         {"unsigned",                    tUNSIGNED},
245 /* ... */
246         {"uuid",                        tUUID},
247         {"v1_enum",                     tV1ENUM},
248 /* ... */
249         {"version",                     tVERSION},
250         {"void",                        tVOID},
251         {"wchar_t",                     tWCHAR},
252         {"wire_marshal",                tWIREMARSHAL}
254 #define NKEYWORDS (sizeof(keywords)/sizeof(keywords[0]))
255 #define KWP(p) ((struct keyword *)(p))
257 static int kw_cmp_func(const void *s1, const void *s2)
259         return strcmp(KWP(s1)->kw, KWP(s2)->kw);
262 #define KW_BSEARCH
263 static int kw_token(const char *kw)
265         struct keyword key, *kwp;
266         key.kw = kw;
267 #ifdef KW_BSEARCH
268         kwp = bsearch(&key, keywords, NKEYWORDS, sizeof(keywords[0]), kw_cmp_func);
269 #else
270         {
271                 int i;
272                 for (kwp=NULL, i=0; i < NKEYWORDS; i++)
273                         if (!kw_cmp_func(&key, &keywords[i])) {
274                                 kwp = &keywords[i];
275                                 break;
276                         }
277         }
278 #endif
279         if (kwp) {
280                 yylval.str = (char*)kwp->kw;
281                 return kwp->token;
282         }
283         yylval.str = xstrdup(kw);
284         return is_type(kw) ? aKNOWNTYPE : aIDENTIFIER;
287 static void addcchar(char c)
289         if(cbufidx >= cbufalloc)
290         {
291                 cbufalloc += 1024;
292                 cbuffer = xrealloc(cbuffer, cbufalloc * sizeof(cbuffer[0]));
293                 if(cbufalloc > 65536)
294                         yywarning("Reallocating string buffer larger than 64kB");
295         }
296         cbuffer[cbufidx++] = c;
299 static char *get_buffered_cstring(void)
301         addcchar(0);
302         return xstrdup(cbuffer);
305 static void pop_import(void)
307         int ptr = import_stack_ptr-1;
309         fclose(yyin);
310         yy_delete_buffer( YY_CURRENT_BUFFER );
311         yy_switch_to_buffer( import_stack[ptr].state );
312         if (temp_name) {
313                 unlink(temp_name);
314                 free(temp_name);
315         }
316         temp_name = import_stack[ptr].temp_name;
317         import_stack_ptr--;
320 struct imports {
321         char *name;
322         struct imports *next;
323 } *first_import;
325 int do_import(char *fname)
327         FILE *f;
328         char *hname, *path;
329         struct imports *import;
330         int ptr = import_stack_ptr;
331         int ret;
333         if (!parse_only) {
334                 hname = dup_basename(fname, ".idl");
335                 strcat(hname, ".h");
337                 fprintf(header, "#include \"%s\"\n", hname);
338                 free(hname);
339         }
341         import = first_import;
342         while (import && strcmp(import->name, fname))
343                 import = import->next;
344         if (import) return 0; /* already imported */
346         import = xmalloc(sizeof(struct imports));
347         import->name = xstrdup(fname);
348         import->next = first_import;
349         first_import = import;
351         if (!(path = wpp_find_include( fname, 1 )))
352             yyerror("Unable to open include file %s", fname);
354         import_stack[ptr].temp_name = temp_name;
355         import_stack_ptr++;
357         ret = wpp_parse_temp( path, NULL, &temp_name );
358         free( path );
359         if (ret) exit(1);
361         if((f = fopen(temp_name, "r")) == NULL)
362                 yyerror("Unable to open %s", temp_name);
364         import_stack[ptr].state = YY_CURRENT_BUFFER;
365         yy_switch_to_buffer(yy_create_buffer(f, YY_BUF_SIZE));
366         return 1;
369 void abort_import(void)
371         int ptr;
373         for (ptr=0; ptr<import_stack_ptr; ptr++)
374                 unlink(import_stack[ptr].temp_name);