Added some flex options to avoid compiler warnings.
[wine/multimedia.git] / tools / widl / parser.l
blob4955bad080bfc86df2771510f2fab6d880d19630
1 /* -*-C-*-
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 nounput noyy_top_state
23 %option 8bit never-interactive
25 nl      \r?\n
26 ws      [ \f\t\r]
27 cident  [a-zA-Z_][0-9a-zA-Z_]*
28 int     [0-9]+
29 hexd    [0-9a-fA-F]
30 hex     0x{hexd}+
31 uuid    {hexd}{8}-{hexd}{4}-{hexd}{4}-{hexd}{4}-{hexd}{12}
33 %x QUOTE
34 %x pp_line
38 #include "config.h"
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <ctype.h>
44 #include <assert.h>
45 #ifdef HAVE_UNISTD_H
46 # include <unistd.h>
47 #endif
49 #include "widl.h"
50 #include "utils.h"
51 #include "parser.h"
52 #include "wine/wpp.h"
54 #include "parser.tab.h"
56 #define YY_USE_PROTOS
57 #define YY_NO_UNPUT
58 #define YY_NO_TOP_STATE
60 extern char *temp_name;
62 static void addcchar(char c);
63 static char *get_buffered_cstring(void);
65 static char *cbuffer;
66 static int cbufidx;
67 static int cbufalloc = 0;
69 static int kw_token(const char *kw);
71 #define MAX_IMPORT_DEPTH 10
72 struct {
73   YY_BUFFER_STATE state;
74   char *input_name;
75   int   line_number;
76   char *temp_name;
77 } import_stack[MAX_IMPORT_DEPTH];
78 int import_stack_ptr = 0;
80 static void pop_import(void);
82 static UUID* parse_uuid(const char*u)
84   UUID* uuid = xmalloc(sizeof(UUID));
85   char b[3];
86   /* it would be nice to use UuidFromStringA */
87   uuid->Data1 = strtoul(u, NULL, 16);
88   uuid->Data2 = strtoul(u+9, NULL, 16);
89   uuid->Data3 = strtoul(u+14, NULL, 16);
90   b[2] = 0;
91   memcpy(b, u+19, 2); uuid->Data4[0] = strtoul(b, NULL, 16);
92   memcpy(b, u+21, 2); uuid->Data4[1] = strtoul(b, NULL, 16);
93   memcpy(b, u+24, 2); uuid->Data4[2] = strtoul(b, NULL, 16);
94   memcpy(b, u+26, 2); uuid->Data4[3] = strtoul(b, NULL, 16);
95   memcpy(b, u+28, 2); uuid->Data4[4] = strtoul(b, NULL, 16);
96   memcpy(b, u+30, 2); uuid->Data4[5] = strtoul(b, NULL, 16);
97   memcpy(b, u+32, 2); uuid->Data4[6] = strtoul(b, NULL, 16);
98   memcpy(b, u+34, 2); uuid->Data4[7] = strtoul(b, NULL, 16);
99   return uuid;
105  **************************************************************************
106  * The flexer starts here
107  **************************************************************************
108  */
110 <INITIAL>^{ws}*\#{ws}*  yy_push_state(pp_line);
111 <pp_line>[^\n]*         {
112                             int lineno;
113                             char *cptr, *fname;
114                             yy_pop_state();
115                             lineno = (int)strtol(yytext, &cptr, 10);
116                             if(!lineno)
117                                 yyerror("Malformed '#...' line-directive; invalid linenumber");
118                             fname = strchr(cptr, '"');
119                             if(!fname)
120                                 yyerror("Malformed '#...' line-directive; missing filename");
121                             fname++;
122                             cptr = strchr(fname, '"');
123                             if(!cptr)
124                                 yyerror("Malformed '#...' line-directive; missing terminating \"");
125                             *cptr = '\0';
126                             line_number = lineno - 1;  /* We didn't read the newline */
127                             free( input_name );
128                             input_name = xstrdup(fname);
129                         }
130 \"                      yy_push_state(QUOTE); cbufidx = 0;
131 <QUOTE>\"               {
132                                 yy_pop_state();
133                                 yylval.str = get_buffered_cstring();
134                                 return aSTRING;
135                         }
136 <QUOTE>\\\\             |
137 <QUOTE>\\\"             addcchar(yytext[1]);
138 <QUOTE>\\.              addcchar('\\'); addcchar(yytext[1]);
139 <QUOTE>.                addcchar(yytext[0]);
140 {uuid}                  {
141                                 yylval.uuid = parse_uuid(yytext);
142                                 return aUUID;
143                         }
144 {hex}                   {
145                                 yylval.num = strtoul(yytext, NULL, 0);
146                                 return aHEXNUM;
147                         }
148 {int}                   {
149                                 yylval.num = strtoul(yytext, NULL, 0);
150                                 return aNUM;
151                         }
152 {cident}                return kw_token(yytext);
153 \n                      line_number++;
154 {ws}
155 \<\<                    return SHL;
156 \>\>                    return SHR;
157 .                       return yytext[0];
158 <<EOF>>                 {
159                                 if (import_stack_ptr) {
160                                         pop_import();
161                                         return aEOF;
162                                 }
163                                 else yyterminate();
164                         }
167 #ifndef yywrap
168 int yywrap(void)
170         return 1;
172 #endif
174 static struct keyword {
175         const char *kw;
176         int token;
177         int val;
178 } keywords[] = {
179         {"__cdecl",                     tCDECL},
180         {"__int64",                     tINT64},
181         {"__stdcall",                   tSTDCALL},
182         {"_stdcall",                    tSTDCALL},
183         {"aggregatable",                tAGGREGATABLE},
184         {"allocate",                    tALLOCATE},
185         {"appobject",                   tAPPOBJECT},
186         {"arrays",                      tARRAYS},
187         {"async",                       tASYNC},
188         {"async_uuid",                  tASYNCUUID},
189         {"auto_handle",                 tAUTOHANDLE},
190         {"bindable",                    tBINDABLE},
191         {"boolean",                     tBOOLEAN},
192         {"broadcast",                   tBROADCAST},
193         {"byte",                        tBYTE},
194         {"byte_count",                  tBYTECOUNT},
195         {"call_as",                     tCALLAS},
196         {"callback",                    tCALLBACK},
197         {"case",                        tCASE},
198         {"char",                        tCHAR},
199         {"coclass",                     tCOCLASS},
200         {"code",                        tCODE},
201         {"comm_status",                 tCOMMSTATUS},
202         {"const",                       tCONST},
203         {"context_handle",              tCONTEXTHANDLE},
204         {"context_handle_noserialize",  tCONTEXTHANDLENOSERIALIZE},
205         {"context_handle_serialize",    tCONTEXTHANDLENOSERIALIZE},
206         {"control",                     tCONTROL},
207         {"cpp_quote",                   tCPPQUOTE},
208 /* ... */
209         {"default",                     tDEFAULT},
210         {"defaultvalue",                tDEFAULTVALUE},
211 /* ... */
212         {"dispinterface",               tDISPINTERFACE},
213 /* ... */
214         {"displaybind",                 tDISPLAYBIND},
215         {"dllname",                     tDLLNAME},
216         {"double",                      tDOUBLE},
217         {"dual",                        tDUAL},
218 /* ... */
219         {"endpoint",                    tENDPOINT},
220         {"entry",                       tENTRY},
221         {"enum",                        tENUM},
222         {"error_status_t",              tERRORSTATUST},
223         {"explicit_handle",             tEXPLICITHANDLE},
224         {"extern",                      tEXTERN},
225 /* ... */
226         {"float",                       tFLOAT},
227 /* ... */
228         {"handle",                      tHANDLE},
229         {"handle_t",                    tHANDLET},
230 /* ... */
231         {"helpcontext",                 tHELPCONTEXT},
232         {"helpfile",                    tHELPFILE},
233         {"helpstring",                  tHELPSTRING},
234         {"helpstringcontext",           tHELPSTRINGCONTEXT},
235         {"helpstringdll",               tHELPSTRINGDLL},
236 /* ... */
237         {"hidden",                      tHIDDEN},
238         {"hyper",                       tHYPER},
239         {"id",                          tID},
240         {"idempotent",                  tIDEMPOTENT},
241 /* ... */
242         {"iid_is",                      tIIDIS},
243 /* ... */
244         {"implicit_handle",             tIMPLICITHANDLE},
245         {"import",                      tIMPORT},
246         {"importlib",                   tIMPORTLIB},
247         {"in",                          tIN},
248         {"include",                     tINCLUDE},
249         {"in_line",                     tINLINE},
250         {"input_sync",                  tINPUTSYNC},
251         {"int",                         tINT},
252 /* ... */
253         {"interface",                   tINTERFACE},
254 /* ... */
255         {"length_is",                   tLENGTHIS},
256         {"library",                     tLIBRARY},
257 /* ... */
258         {"local",                       tLOCAL},
259         {"long",                        tLONG},
260 /* ... */
261         {"methods",                     tMETHODS},
262 /* ... */
263         {"module",                      tMODULE},
264 /* ... */
265         {"noncreatable",                tNONCREATABLE},
266         {"object",                      tOBJECT},
267         {"odl",                         tODL},
268         {"oleautomation",               tOLEAUTOMATION},
269 /* ... */
270         {"optional",                    tOPTIONAL},
271         {"out",                         tOUT},
272 /* ... */
273         {"pointer_default",             tPOINTERDEFAULT},
274 /* ... */
275         {"properties",                  tPROPERTIES},
276         {"propget",                     tPROPGET},
277         {"propput",                     tPROPPUT},
278         {"propputref",                  tPROPPUTREF},
279         {"ptr",                         tPTR},
280 /* ... */
281         {"public",                      tPUBLIC},
282         {"range",                       tRANGE},
283 /* ... */
284         {"readonly",                    tREADONLY},
285         {"ref",                         tREF},
286 /* ... */
287         {"restricted",                  tRESTRICTED},
288         {"retval",                      tRETVAL},
289 /* ... */
290         {"short",                       tSHORT},
291         {"signed",                      tSIGNED},
292         {"single",                      tSINGLE},
293         {"size_is",                     tSIZEIS},
294         {"sizeof",                      tSIZEOF},
295         {"small",                       tSMALL},
296 /* ... */
297         {"source",                      tSOURCE},
298 /* ... */       
299         {"string",                      tSTRING},
300         {"struct",                      tSTRUCT},
301         {"switch",                      tSWITCH},
302         {"switch_is",                   tSWITCHIS},
303         {"switch_type",                 tSWITCHTYPE},
304 /* ... */
305         {"transmit_as",                 tTRANSMITAS},
306         {"typedef",                     tTYPEDEF},
307         {"union",                       tUNION},
308 /* ... */
309         {"unique",                      tUNIQUE},
310         {"unsigned",                    tUNSIGNED},
311 /* ... */
312         {"uuid",                        tUUID},
313         {"v1_enum",                     tV1ENUM},
314 /* ... */
315         {"vararg",                      tVARARG},
316         {"version",                     tVERSION},
317         {"void",                        tVOID},
318         {"wchar_t",                     tWCHAR},
319         {"wire_marshal",                tWIREMARSHAL}
321 #define NKEYWORDS (sizeof(keywords)/sizeof(keywords[0]))
322 #define KWP(p) ((const struct keyword *)(p))
324 static int kw_cmp_func(const void *s1, const void *s2)
326         return strcmp(KWP(s1)->kw, KWP(s2)->kw);
329 #define KW_BSEARCH
330 static int kw_token(const char *kw)
332         struct keyword key, *kwp;
333         key.kw = kw;
334 #ifdef KW_BSEARCH
335         kwp = bsearch(&key, keywords, NKEYWORDS, sizeof(keywords[0]), kw_cmp_func);
336 #else
337         {
338                 int i;
339                 for (kwp=NULL, i=0; i < NKEYWORDS; i++)
340                         if (!kw_cmp_func(&key, &keywords[i])) {
341                                 kwp = &keywords[i];
342                                 break;
343                         }
344         }
345 #endif
346         if (kwp) {
347                 yylval.str = (char*)kwp->kw;
348                 return kwp->token;
349         }
350         yylval.str = xstrdup(kw);
351         return is_type(kw) ? aKNOWNTYPE : aIDENTIFIER;
354 static void addcchar(char c)
356         if(cbufidx >= cbufalloc)
357         {
358                 cbufalloc += 1024;
359                 cbuffer = xrealloc(cbuffer, cbufalloc * sizeof(cbuffer[0]));
360                 if(cbufalloc > 65536)
361                         yywarning("Reallocating string buffer larger than 64kB");
362         }
363         cbuffer[cbufidx++] = c;
366 static char *get_buffered_cstring(void)
368         addcchar(0);
369         return xstrdup(cbuffer);
372 static void pop_import(void)
374         int ptr = import_stack_ptr-1;
376         fclose(yyin);
377         yy_delete_buffer( YY_CURRENT_BUFFER );
378         yy_switch_to_buffer( import_stack[ptr].state );
379         if (temp_name) {
380                 unlink(temp_name);
381                 free(temp_name);
382         }
383         temp_name = import_stack[ptr].temp_name;
384         free( input_name );
385         input_name = import_stack[ptr].input_name;
386         line_number = import_stack[ptr].line_number;
387         import_stack_ptr--;
390 struct imports {
391         char *name;
392         struct imports *next;
393 } *first_import;
395 int do_import(char *fname)
397         FILE *f;
398         char *hname, *path, *p;
399         struct imports *import;
400         int ptr = import_stack_ptr;
401         int ret;
403         if (!parse_only && do_header) {
404                 hname = dup_basename(fname, ".idl");
405                 p = hname + strlen(hname) - 2;
406                 if (p <= hname || strcmp( p, ".h" )) strcat(hname, ".h");
408                 fprintf(header, "#include <%s>\n", hname);
409                 free(hname);
410         }
412         import = first_import;
413         while (import && strcmp(import->name, fname))
414                 import = import->next;
415         if (import) return 0; /* already imported */
417         import = xmalloc(sizeof(struct imports));
418         import->name = xstrdup(fname);
419         import->next = first_import;
420         first_import = import;
422         if (!(path = wpp_find_include( fname, input_name )))
423             yyerror("Unable to open include file %s", fname);
425         import_stack[ptr].temp_name = temp_name;
426         import_stack[ptr].input_name = input_name;
427         import_stack[ptr].line_number = line_number;
428         import_stack_ptr++;
429         input_name = path;
430         line_number = 1;
432         ret = wpp_parse_temp( path, NULL, &temp_name );
433         if (ret) exit(1);
435         if((f = fopen(temp_name, "r")) == NULL)
436                 yyerror("Unable to open %s", temp_name);
438         import_stack[ptr].state = YY_CURRENT_BUFFER;
439         yy_switch_to_buffer(yy_create_buffer(f, YY_BUF_SIZE));
440         return 1;
443 void abort_import(void)
445         int ptr;
447         for (ptr=0; ptr<import_stack_ptr; ptr++)
448                 unlink(import_stack[ptr].temp_name);