wined3d: Factor out context_copy_bo_address() function.
[wine.git] / tools / widl / parser.l
blob6520ce72e6b3d5a50ccb4d8d60c9eab9aeb191b9
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
21 %option stack
22 %option noinput nounput noyy_top_state
23 %option 8bit never-interactive prefix="parser_"
25 nl      \r?\n
26 ws      [ \f\t\r]
27 cident  [a-zA-Z_][0-9a-zA-Z_]*
28 u_suffix        (u|U)
29 l_suffix        (l|L)
30 int     [0-9]+({l_suffix}?{u_suffix}?|{u_suffix}?{l_suffix}?)?
31 hexd    [0-9a-fA-F]
32 hex     0(x|X){hexd}+({l_suffix}?{u_suffix}?|{u_suffix}?{l_suffix}?)?
33 uuid    {hexd}{8}-{hexd}{4}-{hexd}{4}-{hexd}{4}-{hexd}{12}
34 double  [0-9]+\.[0-9]+([eE][+-]?[0-9]+)*
36 %x QUOTE
37 %x WSTRQUOTE
38 %x ATTR
39 %x PP_LINE
40 %x PP_PRAGMA
41 %x SQUOTE
45 #include "config.h"
46 #include "wine/port.h"
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <ctype.h>
52 #include <assert.h>
53 #include <errno.h>
54 #include <limits.h>
56 #ifdef HAVE_UNISTD_H
57 #include <unistd.h>
58 #else
59 #define YY_NO_UNISTD_H
60 #endif
62 #include "widl.h"
63 #include "utils.h"
64 #include "parser.h"
65 #include "wine/wpp.h"
67 #include "parser.tab.h"
69 static void addcchar(char c);
70 static char *get_buffered_cstring(void);
72 static char *cbuffer;
73 static int cbufidx;
74 static int cbufalloc = 0;
76 static int kw_token(const char *kw);
77 static int attr_token(const char *kw);
79 static warning_list_t *disabled_warnings = NULL;
81 #define MAX_IMPORT_DEPTH 10
82 struct {
83   YY_BUFFER_STATE state;
84   char *input_name;
85   int   line_number;
86   char *temp_name;
87 } import_stack[MAX_IMPORT_DEPTH];
88 int import_stack_ptr = 0;
90 /* converts an integer in string form to an unsigned long and prints an error
91  * on overflow */
92 static unsigned int xstrtoul(const char *nptr, char **endptr, int base)
94     unsigned long val;
96     errno = 0;
97     val = strtoul(nptr, endptr, base);
98     if ((val == ULONG_MAX && errno == ERANGE) || ((unsigned int)val != val))
99         error_loc("integer constant %s is too large\n", nptr);
100     return val;
103 UUID *parse_uuid(const char *u)
105   UUID* uuid = xmalloc(sizeof(UUID));
106   char b[3];
107   /* it would be nice to use UuidFromStringA */
108   uuid->Data1 = strtoul(u, NULL, 16);
109   uuid->Data2 = strtoul(u+9, NULL, 16);
110   uuid->Data3 = strtoul(u+14, NULL, 16);
111   b[2] = 0;
112   memcpy(b, u+19, 2); uuid->Data4[0] = strtoul(b, NULL, 16);
113   memcpy(b, u+21, 2); uuid->Data4[1] = strtoul(b, NULL, 16);
114   memcpy(b, u+24, 2); uuid->Data4[2] = strtoul(b, NULL, 16);
115   memcpy(b, u+26, 2); uuid->Data4[3] = strtoul(b, NULL, 16);
116   memcpy(b, u+28, 2); uuid->Data4[4] = strtoul(b, NULL, 16);
117   memcpy(b, u+30, 2); uuid->Data4[5] = strtoul(b, NULL, 16);
118   memcpy(b, u+32, 2); uuid->Data4[6] = strtoul(b, NULL, 16);
119   memcpy(b, u+34, 2); uuid->Data4[7] = strtoul(b, NULL, 16);
120   return uuid;
126  **************************************************************************
127  * The flexer starts here
128  **************************************************************************
129  */
131 <INITIAL>^{ws}*\#{ws}*pragma{ws}+ yy_push_state(PP_PRAGMA);
132 <INITIAL,ATTR>^{ws}*\#{ws}*     yy_push_state(PP_LINE);
133 <PP_LINE>[^\n]*         {
134                             int lineno;
135                             char *cptr, *fname;
136                             yy_pop_state();
137                             lineno = (int)strtol(yytext, &cptr, 10);
138                             if(!lineno)
139                                 error_loc("Malformed '#...' line-directive; invalid linenumber\n");
140                             fname = strchr(cptr, '"');
141                             if(!fname)
142                                 error_loc("Malformed '#...' line-directive; missing filename\n");
143                             fname++;
144                             cptr = strchr(fname, '"');
145                             if(!cptr)
146                                 error_loc("Malformed '#...' line-directive; missing terminating \"\n");
147                             *cptr = '\0';
148                             line_number = lineno - 1;  /* We didn't read the newline */
149                             input_name = xstrdup(fname);
150                         }
151 <PP_PRAGMA>midl_echo[^\n]*  yyless(9); yy_pop_state(); return tCPPQUOTE;
152 <PP_PRAGMA>winrt[^\n]*  {
153                             if(import_stack_ptr) {
154                                 if(!winrt_mode)
155                                     error_loc("winrt IDL file imported in non-winrt mode\n");
156                             }else {
157                                 const char *ptr = yytext+5;
159                                 winrt_mode = TRUE;
161                                 while(isspace(*ptr))
162                                     ptr++;
163                                 if(!strncmp(ptr, "ns_prefix", 9) && (!*(ptr += 9) || isspace(*ptr)))
164                                     use_abi_namespace = TRUE;
165                             }
166                             yy_pop_state();
167                         }
168 <PP_PRAGMA>[^\n]*       parser_lval.str = xstrdup(yytext); yy_pop_state(); return aPRAGMA;
169 <INITIAL>^{ws}*midl_pragma{ws}+warning return tPRAGMA_WARNING;
170 <INITIAL,ATTR>\"        yy_push_state(QUOTE); cbufidx = 0;
171 <QUOTE>\"               {
172                                 yy_pop_state();
173                                 parser_lval.str = get_buffered_cstring();
174                                 return aSTRING;
175                         }
176 <INITIAL,ATTR>L\"       yy_push_state(WSTRQUOTE); cbufidx = 0;
177 <WSTRQUOTE>\"           {
178                                 yy_pop_state();
179                                 parser_lval.str = get_buffered_cstring();
180                                 return aWSTRING;
181                         }
182 <INITIAL,ATTR>\'        yy_push_state(SQUOTE); cbufidx = 0;
183 <SQUOTE>\'              {
184                                 yy_pop_state();
185                                 parser_lval.str = get_buffered_cstring();
186                                 return aSQSTRING;
187                         }
188 <QUOTE,WSTRQUOTE,SQUOTE>\\\\    |
189 <QUOTE,WSTRQUOTE>\\\"   addcchar(yytext[1]);
190 <SQUOTE>\\\'    addcchar(yytext[1]);
191 <QUOTE,WSTRQUOTE,SQUOTE>\\.     addcchar('\\'); addcchar(yytext[1]);
192 <QUOTE,WSTRQUOTE,SQUOTE>.       addcchar(yytext[0]);
193 <INITIAL,ATTR>\[        yy_push_state(ATTR); return '[';
194 <ATTR>\]                yy_pop_state(); return ']';
195 <ATTR>{cident}          return attr_token(yytext);
196 <ATTR>{uuid}                    {
197                                 parser_lval.uuid = parse_uuid(yytext);
198                                 return aUUID;
199                         }
200 <INITIAL,ATTR>{hex}     {
201                                 parser_lval.num = xstrtoul(yytext, NULL, 0);
202                                 return aHEXNUM;
203                         }
204 <INITIAL,ATTR>{int}     {
205                                 parser_lval.num = xstrtoul(yytext, NULL, 0);
206                                 return aNUM;
207                         }
208 <INITIAL>{double}       {
209                                 parser_lval.dbl = strtod(yytext, NULL);
210                                 return aDOUBLE;
211                         }
212 SAFEARRAY{ws}*/\(       return tSAFEARRAY;
213 {cident}                return kw_token(yytext);
214 <INITIAL,ATTR>\n        line_number++;
215 <INITIAL,ATTR>{ws}
216 <INITIAL,ATTR>\<\<      return SHL;
217 <INITIAL,ATTR>\>\>      return SHR;
218 <INITIAL,ATTR>\-\>      return MEMBERPTR;
219 <INITIAL,ATTR>==        return EQUALITY;
220 <INITIAL,ATTR>!=        return INEQUALITY;
221 <INITIAL,ATTR>\>=       return GREATEREQUAL;
222 <INITIAL,ATTR>\<=       return LESSEQUAL;
223 <INITIAL,ATTR>\|\|      return LOGICALOR;
224 <INITIAL,ATTR>&&        return LOGICALAND;
225 <INITIAL,ATTR>\.\.\.    return ELLIPSIS;
226 <INITIAL,ATTR>.         return yytext[0];
227 <<EOF>>                 {
228                                 if (import_stack_ptr)
229                                         return aEOF;
230                                 else yyterminate();
231                         }
234 #ifndef parser_wrap
235 int parser_wrap(void)
237         return 1;
239 #endif
241 struct keyword {
242         const char *kw;
243         int token;
246 /* This table MUST be alphabetically sorted on the kw field */
247 static const struct keyword keywords[] = {
248         {"FALSE",                       tFALSE},
249         {"NULL",                        tNULL},
250         {"TRUE",                        tTRUE},
251         {"__cdecl",                     tCDECL},
252         {"__fastcall",                  tFASTCALL},
253         {"__int3264",                   tINT3264},
254         {"__int64",                     tINT64},
255         {"__pascal",                    tPASCAL},
256         {"__stdcall",                   tSTDCALL},
257         {"_cdecl",                      tCDECL},
258         {"_fastcall",                   tFASTCALL},
259         {"_pascal",                     tPASCAL},
260         {"_stdcall",                    tSTDCALL},
261         {"boolean",                     tBOOLEAN},
262         {"byte",                        tBYTE},
263         {"case",                        tCASE},
264         {"cdecl",                       tCDECL},
265         {"char",                        tCHAR},
266         {"coclass",                     tCOCLASS},
267         {"const",                       tCONST},
268         {"cpp_quote",                   tCPPQUOTE},
269         {"default",                     tDEFAULT},
270         {"dispinterface",               tDISPINTERFACE},
271         {"double",                      tDOUBLE},
272         {"enum",                        tENUM},
273         {"error_status_t",              tERRORSTATUST},
274         {"extern",                      tEXTERN},
275         {"float",                       tFLOAT},
276         {"handle_t",                    tHANDLET},
277         {"hyper",                       tHYPER},
278         {"import",                      tIMPORT},
279         {"importlib",                   tIMPORTLIB},
280         {"inline",                      tINLINE},
281         {"int",                         tINT},
282         {"interface",                   tINTERFACE},
283         {"library",                     tLIBRARY},
284         {"long",                        tLONG},
285         {"methods",                     tMETHODS},
286         {"module",                      tMODULE},
287         {"namespace",                   tNAMESPACE},
288         {"pascal",                      tPASCAL},
289         {"properties",                  tPROPERTIES},
290         {"register",                    tREGISTER},
291         {"short",                       tSHORT},
292         {"signed",                      tSIGNED},
293         {"sizeof",                      tSIZEOF},
294         {"small",                       tSMALL},
295         {"static",                      tSTATIC},
296         {"stdcall",                     tSTDCALL},
297         {"struct",                      tSTRUCT},
298         {"switch",                      tSWITCH},
299         {"typedef",                     tTYPEDEF},
300         {"union",                       tUNION},
301         {"unsigned",                    tUNSIGNED},
302         {"void",                        tVOID},
303         {"wchar_t",                     tWCHAR},
305 #define NKEYWORDS (sizeof(keywords)/sizeof(keywords[0]))
307 /* keywords only recognized in attribute lists
308  * This table MUST be alphabetically sorted on the kw field
309  */
310 static const struct keyword attr_keywords[] =
312         {"aggregatable",                tAGGREGATABLE},
313         {"allocate",                    tALLOCATE},
314         {"annotation",                  tANNOTATION},
315         {"apartment",                   tAPARTMENT},
316         {"appobject",                   tAPPOBJECT},
317         {"async",                       tASYNC},
318         {"async_uuid",                  tASYNCUUID},
319         {"auto_handle",                 tAUTOHANDLE},
320         {"bindable",                    tBINDABLE},
321         {"both",                        tBOTH},
322         {"broadcast",                   tBROADCAST},
323         {"byte_count",                  tBYTECOUNT},
324         {"call_as",                     tCALLAS},
325         {"callback",                    tCALLBACK},
326         {"code",                        tCODE},
327         {"comm_status",                 tCOMMSTATUS},
328         {"context_handle",              tCONTEXTHANDLE},
329         {"context_handle_noserialize",  tCONTEXTHANDLENOSERIALIZE},
330         {"context_handle_serialize",    tCONTEXTHANDLENOSERIALIZE},
331         {"control",                     tCONTROL},
332         {"decode",                      tDECODE},
333         {"defaultbind",                 tDEFAULTBIND},
334         {"defaultcollelem",             tDEFAULTCOLLELEM},
335         {"defaultvalue",                tDEFAULTVALUE},
336         {"defaultvtable",               tDEFAULTVTABLE},
337         {"disable_consistency_check",   tDISABLECONSISTENCYCHECK},
338         {"displaybind",                 tDISPLAYBIND},
339         {"dllname",                     tDLLNAME},
340         {"dual",                        tDUAL},
341         {"enable_allocate",             tENABLEALLOCATE},
342         {"encode",                      tENCODE},
343         {"endpoint",                    tENDPOINT},
344         {"entry",                       tENTRY},
345         {"explicit_handle",             tEXPLICITHANDLE},
346         {"fault_status",                tFAULTSTATUS},
347         {"force_allocate",              tFORCEALLOCATE},
348         {"free",                        tFREE},
349         {"handle",                      tHANDLE},
350         {"helpcontext",                 tHELPCONTEXT},
351         {"helpfile",                    tHELPFILE},
352         {"helpstring",                  tHELPSTRING},
353         {"helpstringcontext",           tHELPSTRINGCONTEXT},
354         {"helpstringdll",               tHELPSTRINGDLL},
355         {"hidden",                      tHIDDEN},
356         {"id",                          tID},
357         {"idempotent",                  tIDEMPOTENT},
358         {"ignore",                      tIGNORE},
359         {"iid_is",                      tIIDIS},
360         {"immediatebind",               tIMMEDIATEBIND},
361         {"implicit_handle",             tIMPLICITHANDLE},
362         {"in",                          tIN},
363         {"in_line",                     tIN_LINE},
364         {"input_sync",                  tINPUTSYNC},
365         {"lcid",                        tLCID},
366         {"length_is",                   tLENGTHIS},
367         {"licensed",                    tLICENSED},
368         {"local",                       tLOCAL},
369         {"maybe",                       tMAYBE},
370         {"message",                     tMESSAGE},
371         {"neutral",                     tNEUTRAL},
372         {"nocode",                      tNOCODE},
373         {"nonbrowsable",                tNONBROWSABLE},
374         {"noncreatable",                tNONCREATABLE},
375         {"nonextensible",               tNONEXTENSIBLE},
376         {"notify",                      tNOTIFY},
377         {"notify_flag",                 tNOTIFYFLAG},
378         {"object",                      tOBJECT},
379         {"odl",                         tODL},
380         {"oleautomation",               tOLEAUTOMATION},
381         {"optimize",                    tOPTIMIZE},
382         {"optional",                    tOPTIONAL},
383         {"out",                         tOUT},
384         {"partial_ignore",              tPARTIALIGNORE},
385         {"pointer_default",             tPOINTERDEFAULT},
386         {"progid",                      tPROGID},
387         {"propget",                     tPROPGET},
388         {"propput",                     tPROPPUT},
389         {"propputref",                  tPROPPUTREF},
390         {"proxy",                       tPROXY},
391         {"ptr",                         tPTR},
392         {"public",                      tPUBLIC},
393         {"range",                       tRANGE},
394         {"readonly",                    tREADONLY},
395         {"ref",                         tREF},
396         {"represent_as",                tREPRESENTAS},
397         {"requestedit",                 tREQUESTEDIT},
398         {"restricted",                  tRESTRICTED},
399         {"retval",                      tRETVAL},
400         {"single",                      tSINGLE},
401         {"size_is",                     tSIZEIS},
402         {"source",                      tSOURCE},
403         {"strict_context_handle",       tSTRICTCONTEXTHANDLE},
404         {"string",                      tSTRING},
405         {"switch_is",                   tSWITCHIS},
406         {"switch_type",                 tSWITCHTYPE},
407         {"threading",                   tTHREADING},
408         {"transmit_as",                 tTRANSMITAS},
409         {"uidefault",                   tUIDEFAULT},
410         {"unique",                      tUNIQUE},
411         {"user_marshal",                tUSERMARSHAL},
412         {"usesgetlasterror",            tUSESGETLASTERROR},
413         {"uuid",                        tUUID},
414         {"v1_enum",                     tV1ENUM},
415         {"vararg",                      tVARARG},
416         {"version",                     tVERSION},
417         {"vi_progid",                   tVIPROGID},
418         {"wire_marshal",                tWIREMARSHAL},
421 /* attributes TODO:
422     custom
423     first_is
424     last_is
425     max_is
426     min_is
429 #define KWP(p) ((const struct keyword *)(p))
431 static int kw_cmp_func(const void *s1, const void *s2)
433         return strcmp(KWP(s1)->kw, KWP(s2)->kw);
436 static int kw_token(const char *kw)
438         struct keyword key, *kwp;
439         key.kw = kw;
440         kwp = bsearch(&key, keywords, NKEYWORDS, sizeof(keywords[0]), kw_cmp_func);
441         if (kwp && (winrt_mode || kwp->token != tNAMESPACE)) {
442                 parser_lval.str = xstrdup(kwp->kw);
443                 return kwp->token;
444         }
445         parser_lval.str = xstrdup(kw);
446         return is_type(kw) ? aKNOWNTYPE : aIDENTIFIER;
449 static int attr_token(const char *kw)
451         struct keyword key, *kwp;
452         key.kw = kw;
453         kwp = bsearch(&key, attr_keywords, sizeof(attr_keywords)/sizeof(attr_keywords[0]),
454                       sizeof(attr_keywords[0]), kw_cmp_func);
455         if (kwp) {
456             parser_lval.str = xstrdup(kwp->kw);
457             return kwp->token;
458         }
459         return kw_token(kw);
462 static void addcchar(char c)
464         if(cbufidx >= cbufalloc)
465         {
466                 cbufalloc += 1024;
467                 cbuffer = xrealloc(cbuffer, cbufalloc * sizeof(cbuffer[0]));
468                 if(cbufalloc > 65536)
469                         parser_warning("Reallocating string buffer larger than 64kB\n");
470         }
471         cbuffer[cbufidx++] = c;
474 static char *get_buffered_cstring(void)
476         addcchar(0);
477         return xstrdup(cbuffer);
480 void pop_import(void)
482         int ptr = import_stack_ptr-1;
484         fclose(yyin);
485         yy_delete_buffer( YY_CURRENT_BUFFER );
486         yy_switch_to_buffer( import_stack[ptr].state );
487         if (temp_name) {
488                 unlink(temp_name);
489                 free(temp_name);
490         }
491         temp_name = import_stack[ptr].temp_name;
492         input_name = import_stack[ptr].input_name;
493         line_number = import_stack[ptr].line_number;
494         import_stack_ptr--;
497 struct imports {
498         char *name;
499         struct imports *next;
500 } *first_import;
502 int do_import(char *fname)
504         FILE *f;
505         char *path, *name;
506         struct imports *import;
507         int ptr = import_stack_ptr;
508         int ret, fd;
510         import = first_import;
511         while (import && strcmp(import->name, fname))
512                 import = import->next;
513         if (import) return 0; /* already imported */
515         import = xmalloc(sizeof(struct imports));
516         import->name = xstrdup(fname);
517         import->next = first_import;
518         first_import = import;
520         /* don't search for a file name with a path in the include directories,
521          * for compatibility with MIDL */
522         if (strchr( fname, '/' ) || strchr( fname, '\\' ))
523             path = xstrdup( fname );
524         else if (!(path = wpp_find_include( fname, input_name )))
525             error_loc("Unable to open include file %s\n", fname);
527         import_stack[ptr].temp_name = temp_name;
528         import_stack[ptr].input_name = input_name;
529         import_stack[ptr].line_number = line_number;
530         import_stack_ptr++;
531         input_name = path;
532         line_number = 1;
534         name = xstrdup( "widl.XXXXXX" );
535         if((fd = mkstemps( name, 0 )) == -1)
536             error("Could not generate a temp name from %s\n", name);
538         temp_name = name;
539         if (!(f = fdopen(fd, "wt")))
540             error("Could not open fd %s for writing\n", name);
542         ret = wpp_parse( path, f );
543         fclose( f );
544         if (ret) exit(1);
546         if((f = fopen(temp_name, "r")) == NULL)
547                 error_loc("Unable to open %s\n", temp_name);
549         import_stack[ptr].state = YY_CURRENT_BUFFER;
550         yy_switch_to_buffer(yy_create_buffer(f, YY_BUF_SIZE));
551         return 1;
554 void abort_import(void)
556         int ptr;
558         for (ptr=0; ptr<import_stack_ptr; ptr++)
559                 unlink(import_stack[ptr].temp_name);
562 static void warning_disable(int warning)
564     warning_t *warning_entry;
565     LIST_FOR_EACH_ENTRY(warning_entry, disabled_warnings, warning_t, entry)
566         if(warning_entry->num == warning)
567             return;
568     warning_entry = xmalloc( sizeof(*warning_entry) );
569     warning_entry->num = warning;
570     list_add_tail(disabled_warnings, &warning_entry->entry);
573 static void warning_enable(int warning)
575     warning_t *warning_entry;
576     LIST_FOR_EACH_ENTRY(warning_entry, disabled_warnings, warning_t, entry)
577         if(warning_entry->num == warning)
578         {
579             list_remove(&warning_entry->entry);
580             free(warning_entry);
581             break;
582         }
585 int do_warning(char *toggle, warning_list_t *wnum)
587     warning_t *warning, *next;
588     int ret = 1;
589     if(!disabled_warnings)
590     {
591         disabled_warnings = xmalloc( sizeof(*disabled_warnings) );
592         list_init( disabled_warnings );
593     }
595     if(!strcmp(toggle, "disable"))
596         LIST_FOR_EACH_ENTRY(warning, wnum, warning_t, entry)
597             warning_disable(warning->num);
598     else if(!strcmp(toggle, "enable"))
599         LIST_FOR_EACH_ENTRY(warning, wnum, warning_t, entry)
600             warning_enable(warning->num);
601     else
602         ret = 0;
604     LIST_FOR_EACH_ENTRY_SAFE(warning, next, wnum, warning_t, entry)
605         free(warning);
606     return ret;
609 int is_warning_enabled(int warning)
611     warning_t *warning_entry;
612     if(!disabled_warnings)
613         return 1;
614     LIST_FOR_EACH_ENTRY(warning_entry, disabled_warnings, warning_t, entry)
615         if(warning_entry->num == warning)
616             return 0;
617     return 1;