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