shell32: Fix the Chinese translations.
[wine.git] / tools / widl / parser.l
blob799f94f3a5b5e11d782ed42af7637a8ef641865e
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 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
43 #include "config.h"
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <ctype.h>
49 #include <assert.h>
51 #ifdef HAVE_UNISTD_H
52 #include <unistd.h>
53 #else
54 #define YY_NO_UNISTD_H
55 #endif
57 #include "widl.h"
58 #include "utils.h"
59 #include "parser.h"
60 #include "wine/wpp.h"
62 #include "parser.tab.h"
64 extern char *temp_name;
66 static void addcchar(char c);
67 static char *get_buffered_cstring(void);
69 static char *cbuffer;
70 static int cbufidx;
71 static int cbufalloc = 0;
73 static int kw_token(const char *kw);
74 static int attr_token(const char *kw);
76 #define MAX_IMPORT_DEPTH 10
77 struct {
78   YY_BUFFER_STATE state;
79   char *input_name;
80   int   line_number;
81   char *temp_name;
82 } import_stack[MAX_IMPORT_DEPTH];
83 int import_stack_ptr = 0;
85 UUID *parse_uuid(const char *u)
87   UUID* uuid = xmalloc(sizeof(UUID));
88   char b[3];
89   /* it would be nice to use UuidFromStringA */
90   uuid->Data1 = strtoul(u, NULL, 16);
91   uuid->Data2 = strtoul(u+9, NULL, 16);
92   uuid->Data3 = strtoul(u+14, NULL, 16);
93   b[2] = 0;
94   memcpy(b, u+19, 2); uuid->Data4[0] = strtoul(b, NULL, 16);
95   memcpy(b, u+21, 2); uuid->Data4[1] = strtoul(b, NULL, 16);
96   memcpy(b, u+24, 2); uuid->Data4[2] = strtoul(b, NULL, 16);
97   memcpy(b, u+26, 2); uuid->Data4[3] = strtoul(b, NULL, 16);
98   memcpy(b, u+28, 2); uuid->Data4[4] = strtoul(b, NULL, 16);
99   memcpy(b, u+30, 2); uuid->Data4[5] = strtoul(b, NULL, 16);
100   memcpy(b, u+32, 2); uuid->Data4[6] = strtoul(b, NULL, 16);
101   memcpy(b, u+34, 2); uuid->Data4[7] = strtoul(b, NULL, 16);
102   return uuid;
108  **************************************************************************
109  * The flexer starts here
110  **************************************************************************
111  */
113 <INITIAL,ATTR>^{ws}*\#{ws}*     yy_push_state(PP_LINE);
114 <PP_LINE>[^\n]*         {
115                             int lineno;
116                             char *cptr, *fname;
117                             yy_pop_state();
118                             lineno = (int)strtol(yytext, &cptr, 10);
119                             if(!lineno)
120                                 error_loc("Malformed '#...' line-directive; invalid linenumber\n");
121                             fname = strchr(cptr, '"');
122                             if(!fname)
123                                 error_loc("Malformed '#...' line-directive; missing filename\n");
124                             fname++;
125                             cptr = strchr(fname, '"');
126                             if(!cptr)
127                                 error_loc("Malformed '#...' line-directive; missing terminating \"\n");
128                             *cptr = '\0';
129                             line_number = lineno - 1;  /* We didn't read the newline */
130                             free( input_name );
131                             input_name = xstrdup(fname);
132                         }
133 <INITIAL,ATTR>\"        yy_push_state(QUOTE); cbufidx = 0;
134 <QUOTE>\"               {
135                                 yy_pop_state();
136                                 parser_lval.str = get_buffered_cstring();
137                                 return aSTRING;
138                         }
139 <INITIAL,ATTR>L\"       yy_push_state(WSTRQUOTE);
140 <WSTRQUOTE>\"           {
141                                 yy_pop_state();
142                                 parser_lval.str = get_buffered_cstring();
143                                 return aWSTRING;
144                         }
145 <QUOTE,WSTRQUOTE>\\\\   |
146 <QUOTE,WSTRQUOTE>\\\"   addcchar(yytext[1]);
147 <QUOTE,WSTRQUOTE>\\.    addcchar('\\'); addcchar(yytext[1]);
148 <QUOTE,WSTRQUOTE>.      addcchar(yytext[0]);
149 <INITIAL,ATTR>\[        yy_push_state(ATTR); return '[';
150 <ATTR>\]                yy_pop_state(); return ']';
151 <ATTR>{cident}          return attr_token(yytext);
152 <ATTR>{uuid}                    {
153                                 parser_lval.uuid = parse_uuid(yytext);
154                                 return aUUID;
155                         }
156 <INITIAL,ATTR>{hex}     {
157                                 parser_lval.num = strtoul(yytext, NULL, 0);
158                                 return aHEXNUM;
159                         }
160 <INITIAL,ATTR>{int}     {
161                                 parser_lval.num = strtoul(yytext, NULL, 0);
162                                 return aNUM;
163                         }
164 <INITIAL>{double}       {
165                                 parser_lval.dbl = strtod(yytext, NULL);
166                                 return aDOUBLE;
167                         }
168 SAFEARRAY{ws}*/\(       return tSAFEARRAY;
169 {cident}                return kw_token(yytext);
170 <INITIAL,ATTR>\n        line_number++;
171 <INITIAL,ATTR>{ws}
172 <INITIAL,ATTR>\<\<      return SHL;
173 <INITIAL,ATTR>\>\>      return SHR;
174 <INITIAL,ATTR>\-\>      return MEMBERPTR;
175 <INITIAL,ATTR>==        return EQUALITY;
176 <INITIAL,ATTR>!=        return INEQUALITY;
177 <INITIAL,ATTR>\>=       return GREATEREQUAL;
178 <INITIAL,ATTR>\<=       return LESSEQUAL;
179 <INITIAL,ATTR>\|\|      return LOGICALOR;
180 <INITIAL,ATTR>&&        return LOGICALAND;
181 <INITIAL,ATTR>.         return yytext[0];
182 <<EOF>>                 {
183                                 if (import_stack_ptr)
184                                         return aEOF;
185                                 else yyterminate();
186                         }
189 #ifndef parser_wrap
190 int parser_wrap(void)
192         return 1;
194 #endif
196 struct keyword {
197         const char *kw;
198         int token;
201 /* This table MUST be alphabetically sorted on the kw field */
202 static const struct keyword keywords[] = {
203         {"FALSE",                       tFALSE},
204         {"NULL",                        tNULL},
205         {"TRUE",                        tTRUE},
206         {"__cdecl",                     tCDECL},
207         {"__fastcall",                  tFASTCALL},
208         {"__int64",                     tINT64},
209         {"__pascal",                    tPASCAL},
210         {"__stdcall",                   tSTDCALL},
211         {"_cdecl",                      tCDECL},
212         {"_fastcall",                   tFASTCALL},
213         {"_pascal",                     tPASCAL},
214         {"_stdcall",                    tSTDCALL},
215         {"boolean",                     tBOOLEAN},
216         {"byte",                        tBYTE},
217         {"case",                        tCASE},
218         {"cdecl",                       tCDECL},
219         {"char",                        tCHAR},
220         {"coclass",                     tCOCLASS},
221         {"const",                       tCONST},
222         {"cpp_quote",                   tCPPQUOTE},
223         {"default",                     tDEFAULT},
224         {"dispinterface",               tDISPINTERFACE},
225         {"double",                      tDOUBLE},
226         {"enum",                        tENUM},
227         {"error_status_t",              tERRORSTATUST},
228         {"extern",                      tEXTERN},
229         {"float",                       tFLOAT},
230         {"handle_t",                    tHANDLET},
231         {"hyper",                       tHYPER},
232         {"import",                      tIMPORT},
233         {"importlib",                   tIMPORTLIB},
234         {"inline",                      tINLINE},
235         {"int",                         tINT},
236         {"interface",                   tINTERFACE},
237         {"library",                     tLIBRARY},
238         {"long",                        tLONG},
239         {"methods",                     tMETHODS},
240         {"module",                      tMODULE},
241         {"pascal",                      tPASCAL},
242         {"properties",                  tPROPERTIES},
243         {"register",                    tREGISTER},
244         {"short",                       tSHORT},
245         {"signed",                      tSIGNED},
246         {"sizeof",                      tSIZEOF},
247         {"small",                       tSMALL},
248         {"static",                      tSTATIC},
249         {"stdcall",                     tSTDCALL},
250         {"struct",                      tSTRUCT},
251         {"switch",                      tSWITCH},
252         {"typedef",                     tTYPEDEF},
253         {"union",                       tUNION},
254         {"unsigned",                    tUNSIGNED},
255         {"void",                        tVOID},
256         {"wchar_t",                     tWCHAR},
258 #define NKEYWORDS (sizeof(keywords)/sizeof(keywords[0]))
260 /* keywords only recognized in attribute lists
261  * This table MUST be alphabetically sorted on the kw field
262  */
263 static const struct keyword attr_keywords[] =
265         {"aggregatable",                tAGGREGATABLE},
266         {"allocate",                    tALLOCATE},
267         {"appobject",                   tAPPOBJECT},
268         {"async",                       tASYNC},
269         {"async_uuid",                  tASYNCUUID},
270         {"auto_handle",                 tAUTOHANDLE},
271         {"bindable",                    tBINDABLE},
272         {"broadcast",                   tBROADCAST},
273         {"byte_count",                  tBYTECOUNT},
274         {"call_as",                     tCALLAS},
275         {"callback",                    tCALLBACK},
276         {"code",                        tCODE},
277         {"comm_status",                 tCOMMSTATUS},
278         {"context_handle",              tCONTEXTHANDLE},
279         {"context_handle_noserialize",  tCONTEXTHANDLENOSERIALIZE},
280         {"context_handle_serialize",    tCONTEXTHANDLENOSERIALIZE},
281         {"control",                     tCONTROL},
282         {"defaultcollelem",             tDEFAULTCOLLELEM},
283         {"defaultvalue",                tDEFAULTVALUE},
284         {"defaultvtable",               tDEFAULTVTABLE},
285         {"displaybind",                 tDISPLAYBIND},
286         {"dllname",                     tDLLNAME},
287         {"dual",                        tDUAL},
288         {"endpoint",                    tENDPOINT},
289         {"entry",                       tENTRY},
290         {"explicit_handle",             tEXPLICITHANDLE},
291         {"handle",                      tHANDLE},
292         {"helpcontext",                 tHELPCONTEXT},
293         {"helpfile",                    tHELPFILE},
294         {"helpstring",                  tHELPSTRING},
295         {"helpstringcontext",           tHELPSTRINGCONTEXT},
296         {"helpstringdll",               tHELPSTRINGDLL},
297         {"hidden",                      tHIDDEN},
298         {"id",                          tID},
299         {"idempotent",                  tIDEMPOTENT},
300         {"iid_is",                      tIIDIS},
301         {"immediatebind",               tIMMEDIATEBIND},
302         {"implicit_handle",             tIMPLICITHANDLE},
303         {"in",                          tIN},
304         {"in_line",                     tIN_LINE},
305         {"input_sync",                  tINPUTSYNC},
306         {"lcid",                        tLCID},
307         {"length_is",                   tLENGTHIS},
308         {"local",                       tLOCAL},
309         {"nonbrowsable",                tNONBROWSABLE},
310         {"noncreatable",                tNONCREATABLE},
311         {"nonextensible",               tNONEXTENSIBLE},
312         {"object",                      tOBJECT},
313         {"odl",                         tODL},
314         {"oleautomation",               tOLEAUTOMATION},
315         {"optional",                    tOPTIONAL},
316         {"out",                         tOUT},
317         {"pointer_default",             tPOINTERDEFAULT},
318         {"propget",                     tPROPGET},
319         {"propput",                     tPROPPUT},
320         {"propputref",                  tPROPPUTREF},
321         {"ptr",                         tPTR},
322         {"public",                      tPUBLIC},
323         {"range",                       tRANGE},
324         {"readonly",                    tREADONLY},
325         {"ref",                         tREF},
326         {"requestedit",                 tREQUESTEDIT},
327         {"restricted",                  tRESTRICTED},
328         {"retval",                      tRETVAL},
329         {"single",                      tSINGLE},
330         {"size_is",                     tSIZEIS},
331         {"source",                      tSOURCE},
332         {"strict_context_handle",       tSTRICTCONTEXTHANDLE},
333         {"string",                      tSTRING},
334         {"switch_is",                   tSWITCHIS},
335         {"switch_type",                 tSWITCHTYPE},
336         {"transmit_as",                 tTRANSMITAS},
337         {"unique",                      tUNIQUE},
338         {"uuid",                        tUUID},
339         {"v1_enum",                     tV1ENUM},
340         {"vararg",                      tVARARG},
341         {"version",                     tVERSION},
342         {"wire_marshal",                tWIREMARSHAL},
346 #define KWP(p) ((const struct keyword *)(p))
348 static int kw_cmp_func(const void *s1, const void *s2)
350         return strcmp(KWP(s1)->kw, KWP(s2)->kw);
353 static int kw_token(const char *kw)
355         struct keyword key, *kwp;
356         key.kw = kw;
357         kwp = bsearch(&key, keywords, NKEYWORDS, sizeof(keywords[0]), kw_cmp_func);
358         if (kwp) {
359                 parser_lval.str = xstrdup(kwp->kw);
360                 return kwp->token;
361         }
362         parser_lval.str = xstrdup(kw);
363         return is_type(kw) ? aKNOWNTYPE : aIDENTIFIER;
366 static int attr_token(const char *kw)
368         struct keyword key, *kwp;
369         key.kw = kw;
370         kwp = bsearch(&key, attr_keywords, sizeof(attr_keywords)/sizeof(attr_keywords[0]),
371                       sizeof(attr_keywords[0]), kw_cmp_func);
372         if (kwp) {
373             parser_lval.str = xstrdup(kwp->kw);
374             return kwp->token;
375         }
376         return kw_token(kw);
379 static void addcchar(char c)
381         if(cbufidx >= cbufalloc)
382         {
383                 cbufalloc += 1024;
384                 cbuffer = xrealloc(cbuffer, cbufalloc * sizeof(cbuffer[0]));
385                 if(cbufalloc > 65536)
386                         parser_warning("Reallocating string buffer larger than 64kB\n");
387         }
388         cbuffer[cbufidx++] = c;
391 static char *get_buffered_cstring(void)
393         addcchar(0);
394         return xstrdup(cbuffer);
397 void pop_import(void)
399         int ptr = import_stack_ptr-1;
401         fclose(yyin);
402         yy_delete_buffer( YY_CURRENT_BUFFER );
403         yy_switch_to_buffer( import_stack[ptr].state );
404         if (temp_name) {
405                 unlink(temp_name);
406                 free(temp_name);
407         }
408         temp_name = import_stack[ptr].temp_name;
409         input_name = import_stack[ptr].input_name;
410         line_number = import_stack[ptr].line_number;
411         import_stack_ptr--;
414 struct imports {
415         char *name;
416         struct imports *next;
417 } *first_import;
419 int do_import(char *fname)
421         FILE *f;
422         char *path;
423         struct imports *import;
424         int ptr = import_stack_ptr;
425         int ret;
427         import = first_import;
428         while (import && strcmp(import->name, fname))
429                 import = import->next;
430         if (import) return 0; /* already imported */
432         import = xmalloc(sizeof(struct imports));
433         import->name = xstrdup(fname);
434         import->next = first_import;
435         first_import = import;
437         /* don't search for a file name with a path in the include directories,
438          * for compatibility with MIDL */
439         if (strchr( fname, '/' ) || strchr( fname, '\\' ))
440             path = strdup( fname );
441         else if (!(path = wpp_find_include( fname, input_name )))
442             error_loc("Unable to open include file %s\n", fname);
444         import_stack[ptr].temp_name = temp_name;
445         import_stack[ptr].input_name = input_name;
446         import_stack[ptr].line_number = line_number;
447         import_stack_ptr++;
448         input_name = path;
449         line_number = 1;
451         ret = wpp_parse_temp( path, NULL, &temp_name );
452         if (ret) exit(1);
454         if((f = fopen(temp_name, "r")) == NULL)
455                 error_loc("Unable to open %s\n", temp_name);
457         import_stack[ptr].state = YY_CURRENT_BUFFER;
458         yy_switch_to_buffer(yy_create_buffer(f, YY_BUF_SIZE));
459         return 1;
462 void abort_import(void)
464         int ptr;
466         for (ptr=0; ptr<import_stack_ptr; ptr++)
467                 unlink(import_stack[ptr].temp_name);