4 * Copyright 2002 Ove Kaaven
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.
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.
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
22 %option bison-locations
24 %option noinput nounput noyy_top_state
26 %option 8bit never-interactive prefix="parser_"
30 uuid {hd}{8}-{hd}{4}-{hd}{4}-{hd}{4}-{hd}{12}
48 #define YY_NO_UNISTD_H
53 #include "wpp_private.h"
55 #define YYerror PARSER_error
56 #define YYSTYPE PARSER_STYPE
57 #define YYLTYPE PARSER_LTYPE
58 #define YYUNDEF PARSER_UNDEF
59 #define yyerror parser_error
61 #include "parser.tab.h"
63 static void reset_location( struct location *where, const char *input_name );
64 static void update_location( struct location *where, const char *yytext );
65 static void end_of_line( struct location *where );
67 #define YY_USER_INIT reset_location( yylloc, input_name )
68 #define YY_USER_ACTION update_location( yylloc, yytext );
70 static void switch_to_acf(void);
72 static warning_list_t *disabled_warnings = NULL;
76 YY_BUFFER_STATE buffer;
78 struct location where;
81 static struct list import_stack = LIST_INIT( import_stack );
89 static struct list imports = LIST_INIT( imports );
90 static struct location previous_location;
92 /* converts an integer in string form to an unsigned long and prints an error
94 static unsigned int xstrtoul(const char *nptr, char **endptr, int base)
99 val = strtoul(nptr, endptr, base);
100 if ((val == ULONG_MAX && errno == ERANGE) || ((unsigned int)val != val))
101 error_loc("integer constant %s is too large\n", nptr);
105 static int token_uuid( const char *str, YYSTYPE *yylval )
110 if (*str == '\"') str++;
112 uuid = xmalloc( sizeof(*uuid) );
113 uuid->Data1 = strtoul( str , NULL, 16 );
114 uuid->Data2 = strtoul( str + 9, NULL, 16 );
115 uuid->Data3 = strtoul( str + 14, NULL, 16 );
116 memcpy( tmp, str + 19, 2 );
117 uuid->Data4[0] = strtoul( tmp, NULL, 16 );
118 memcpy( tmp, str + 21, 2 );
119 uuid->Data4[1] = strtoul( tmp, NULL, 16 );
120 memcpy( tmp, str + 24, 2 );
121 uuid->Data4[2] = strtoul( tmp, NULL, 16 );
122 memcpy( tmp, str + 26, 2 );
123 uuid->Data4[3] = strtoul( tmp, NULL, 16 );
124 memcpy( tmp, str + 28, 2 );
125 uuid->Data4[4] = strtoul( tmp, NULL, 16 );
126 memcpy( tmp, str + 30, 2 );
127 uuid->Data4[5] = strtoul( tmp, NULL, 16 );
128 memcpy( tmp, str + 32, 2 );
129 uuid->Data4[6] = strtoul( tmp, NULL, 16 );
130 memcpy( tmp, str + 34, 2 );
131 uuid->Data4[7] = strtoul( tmp, NULL, 16 );
137 static int token_str( int token, const char *str, YYSTYPE *yylval )
139 char *tmp = xstrdup( str );
141 if (token == aWSTRING || token == aSTRING || token == aSQSTRING)
144 src = dst = ++tmp; /* skip first quote */
147 if (*src == '\\') src++;
150 dst[-1] = 0; /* strip last quote */
157 static int token_num( int token, const char *yytext, YYSTYPE *yylval )
159 yylval->num = xstrtoul( yytext, NULL, 0 );
163 static int token_ident( const char *str, YYSTYPE *yylval )
165 return token_str( is_type( str ) ? aKNOWNTYPE : aIDENTIFIER, str, yylval );
168 static int token_winrt( int token, const char *str, YYSTYPE *yylval )
170 if (winrt_mode) return token;
171 return token_ident( str, yylval );
174 static void winrt_enable( int ns_prefix )
176 if (!list_empty( &import_stack ) && !winrt_mode) error_loc( "WinRT IDL file imported in non-winrt mode.\n" );
178 use_abi_namespace = ns_prefix;
185 **************************************************************************
186 * The flexer starts here
187 **************************************************************************
193 yylloc->first_line -= 1;
196 winrt{ws}+ns_prefix[^\n]* {
198 yylloc->first_line -= 1;
199 winrt_enable( TRUE );
203 yylloc->first_line -= 1;
204 winrt_enable( FALSE );
208 yylloc->first_line -= 1;
209 return token_str( aPRAGMA, yytext, yylval );
212 <PP_LINE>[0-9]+{ws}* {
213 yylloc->first_line = strtoul( yytext, NULL, 10 ) - 1;
214 yylloc->last_line = yylloc->first_line;
216 yy_push_state(PP_FILE);
218 <PP_FILE>\"(\\[^n]|[^"\\\n])*\"{ws}* {
219 input_name = xstrdup( yytext + 1 );
220 *strchr( input_name, '"' ) = 0;
221 yylloc->input_name = input_name;
223 <PP_FILE>[^"][^\n]* { yy_pop_state(); }
226 \] { yy_pop_state(); return ']'; }
228 ({uuid}|\"{uuid}\") { return token_uuid( yytext, yylval ); }
229 activatable { return token_winrt( tACTIVATABLE, yytext, yylval ); }
230 aggregatable { return tAGGREGATABLE; }
231 agile { return token_winrt( tAGILE, yytext, yylval ); }
232 all_nodes { return tALLNODES; }
233 allocate { return tALLOCATE; }
234 annotation { return tANNOTATION; }
235 apartment { return tAPARTMENT; }
236 appobject { return tAPPOBJECT; }
237 async { return tASYNC; }
238 async_uuid { return tASYNCUUID; }
239 auto_handle { return tAUTOHANDLE; }
240 bindable { return tBINDABLE; }
241 both { return tBOTH; }
242 broadcast { return tBROADCAST; }
243 byte_count { return tBYTECOUNT; }
244 call_as { return tCALLAS; }
245 callback { return tCALLBACK; }
246 code { return tCODE; }
247 comm_status { return tCOMMSTATUS; }
248 composable { return token_winrt( tCOMPOSABLE, yytext, yylval ); }
249 context_handle { return tCONTEXTHANDLE; }
250 context_handle_noserialize { return tCONTEXTHANDLENOSERIALIZE; }
251 context_handle_serialize { return tCONTEXTHANDLENOSERIALIZE; }
252 contract { return token_winrt( tCONTRACT, yytext, yylval ); }
253 contractversion { return token_winrt( tCONTRACTVERSION, yytext, yylval ); }
254 control { return tCONTROL; }
255 custom { return tCUSTOM; }
256 decode { return tDECODE; }
257 defaultbind { return tDEFAULTBIND; }
258 defaultcollelem { return tDEFAULTCOLLELEM; }
259 defaultvalue { return tDEFAULTVALUE; }
260 defaultvtable { return tDEFAULTVTABLE; }
261 disable_consistency_check { return tDISABLECONSISTENCYCHECK; }
262 displaybind { return tDISPLAYBIND; }
263 dllname { return tDLLNAME; }
264 dont_free { return tDONTFREE; }
265 dual { return tDUAL; }
266 enable_allocate { return tENABLEALLOCATE; }
267 encode { return tENCODE; }
268 endpoint { return tENDPOINT; }
269 entry { return tENTRY; }
270 eventadd { return token_winrt( tEVENTADD, yytext, yylval ); }
271 eventremove { return token_winrt( tEVENTREMOVE, yytext, yylval ); }
272 exclusiveto { return token_winrt( tEXCLUSIVETO, yytext, yylval ); }
273 explicit_handle { return tEXPLICITHANDLE; }
274 fault_status { return tFAULTSTATUS; }
275 flags { return token_winrt( tFLAGS, yytext, yylval ); }
276 force_allocate { return tFORCEALLOCATE; }
277 free { return tFREE; }
278 handle { return tHANDLE; }
279 helpcontext { return tHELPCONTEXT; }
280 helpfile { return tHELPFILE; }
281 helpstring { return tHELPSTRING; }
282 helpstringcontext { return tHELPSTRINGCONTEXT; }
283 helpstringdll { return tHELPSTRINGDLL; }
284 hidden { return tHIDDEN; }
286 idempotent { return tIDEMPOTENT; }
287 ignore { return tIGNORE; }
288 iid_is { return tIIDIS; }
289 immediatebind { return tIMMEDIATEBIND; }
290 implicit_handle { return tIMPLICITHANDLE; }
292 in_line { return tIN_LINE; }
293 input_sync { return tINPUTSYNC; }
294 lcid { return tLCID; }
295 length_is { return tLENGTHIS; }
296 licensed { return tLICENSED; }
297 local { return tLOCAL; }
298 marshaling_behavior { return token_winrt( tMARSHALINGBEHAVIOR, yytext, yylval ); }
299 maybe { return tMAYBE; }
300 message { return tMESSAGE; }
302 neutral { return tNEUTRAL; }
303 nocode { return tNOCODE; }
304 nonbrowsable { return tNONBROWSABLE; }
305 noncreatable { return tNONCREATABLE; }
306 none { return token_winrt( tNONE, yytext, yylval ); }
307 nonextensible { return tNONEXTENSIBLE; }
308 notify { return tNOTIFY; }
309 notify_flag { return tNOTIFYFLAG; }
310 object { return tOBJECT; }
312 oleautomation { return tOLEAUTOMATION; }
313 optimize { return tOPTIMIZE; }
314 optional { return tOPTIONAL; }
316 overload { return tOVERLOAD; }
317 partial_ignore { return tPARTIALIGNORE; }
318 pointer_default { return tPOINTERDEFAULT; }
319 progid { return tPROGID; }
320 propget { return tPROPGET; }
321 propput { return tPROPPUT; }
322 propputref { return tPROPPUTREF; }
323 protected { return tPROTECTED; }
324 proxy { return tPROXY; }
326 public { return tPUBLIC; }
327 range { return tRANGE; }
328 readonly { return tREADONLY; }
330 represent_as { return tREPRESENTAS; }
331 requestedit { return tREQUESTEDIT; }
332 restricted { return tRESTRICTED; }
333 retval { return tRETVAL; }
334 single { return tSINGLE; }
335 single_node { return tSINGLENODE; }
336 size_is { return tSIZEIS; }
337 source { return tSOURCE; }
338 standard { return token_winrt( tSTANDARD, yytext, yylval ); }
339 static { return token_winrt( tSTATIC, yytext, yylval ); }
340 strict_context_handle { return tSTRICTCONTEXTHANDLE; }
341 string { return tSTRING; }
342 switch_is { return tSWITCHIS; }
343 switch_type { return tSWITCHTYPE; }
344 threading { return tTHREADING; }
345 transmit_as { return tTRANSMITAS; }
346 uidefault { return tUIDEFAULT; }
347 unique { return tUNIQUE; }
348 user_marshal { return tUSERMARSHAL; }
349 usesgetlasterror { return tUSESGETLASTERROR; }
350 uuid { return tUUID; }
351 v1_enum { return tV1ENUM; }
352 vararg { return tVARARG; }
353 version { return tVERSION; }
354 vi_progid { return tVIPROGID; }
355 wire_marshal { return tWIREMARSHAL; }
359 ^{ws}*\#{ws}*pragma{ws}+ { yy_push_state( PP_PRAGMA ); }
360 ^{ws}*midl_pragma{ws}+warning { return tPRAGMA_WARNING; }
362 [0-9]+\.[0-9]+([eE][+-]?[0-9]+)* {
363 yylval->dbl = strtod( yytext, NULL );
368 SAFEARRAY{ws}*/\( return tSAFEARRAY;
371 ^{ws}*\#{ws}* { yy_push_state(PP_LINE); }
372 \[ { yy_push_state(ATTR); return '['; }
374 FALSE { return tFALSE; }
375 NULL { return tNULL; }
376 TRUE { return tTRUE; }
377 _?_?cdecl { return token_str( tCDECL, "__cdecl", yylval ); }
378 _?_?pascal { return token_str( tPASCAL, "__pascal", yylval ); }
379 _?_?stdcall { return token_str( tSTDCALL, "__stdcall", yylval ); }
380 __?fastcall { return token_str( tFASTCALL, "__fastcall", yylval ); }
381 __int32 { return tINT32; }
382 __int3264 { return tINT3264; }
383 __int64 { return tINT64; }
384 apicontract { return token_winrt( tAPICONTRACT, yytext, yylval ); }
385 boolean { return tBOOLEAN; }
386 byte { return tBYTE; }
387 case { return tCASE; }
388 char { return tCHAR; }
389 coclass { return tCOCLASS; }
390 const { return tCONST; }
391 cpp_quote { return tCPPQUOTE; }
392 declare { return token_winrt( tDECLARE, yytext, yylval ); }
393 default { return tDEFAULT; }
394 delegate { return token_winrt( tDELEGATE, yytext, yylval ); }
395 dispinterface { return tDISPINTERFACE; }
396 double { return tDOUBLE; }
397 enum { return tENUM; }
398 error_status_t { return tERRORSTATUST; }
399 extern { return tEXTERN; }
400 float { return tFLOAT; }
401 handle_t { return tHANDLET; }
402 hyper { return tHYPER; }
403 import { return tIMPORT; }
404 importlib { return tIMPORTLIB; }
405 inline { return tINLINE; }
407 interface { return tINTERFACE; }
408 library { return tLIBRARY; }
409 long { return tLONG; }
410 methods { return tMETHODS; }
411 module { return tMODULE; }
412 namespace { return token_winrt( tNAMESPACE, yytext, yylval ); }
413 properties { return tPROPERTIES; }
414 register { return tREGISTER; }
415 requires { return token_winrt( tREQUIRES, yytext, yylval ); }
416 runtimeclass { return token_winrt( tRUNTIMECLASS, yytext, yylval ); }
417 short { return tSHORT; }
418 signed { return tSIGNED; }
419 sizeof { return tSIZEOF; }
420 small { return tSMALL; }
421 static { return tSTATIC; }
422 struct { return tSTRUCT; }
423 switch { return tSWITCH; }
424 typedef { return tTYPEDEF; }
425 union { return tUNION; }
426 unsigned { return tUNSIGNED; }
427 void { return tVOID; }
428 wchar_t { return tWCHAR; }
430 [a-zA-Z_][0-9a-zA-Z_]* { return token_ident( yytext, yylval ); }
432 0[xX]{hd}+([lL][uU]?|[uU][lL]?)? { return token_num( aHEXNUM, yytext, yylval ); }
433 [0-9]+([lL][uU]?|[uU][lL]?)? { return token_num( aNUM, yytext, yylval ); }
435 L\"(\\.|[^"\\])*\" { return token_str( aWSTRING, yytext + 1, yylval ); }
436 \"(\\.|[^"\\])*\" { return token_str( aSTRING, yytext, yylval ); }
437 \'(\\.|[^'\\])*\' { return token_str( aSQSTRING, yytext, yylval ); }
439 \n { end_of_line( yylloc ); }
443 \-\> { return MEMBERPTR; }
444 == { return EQUALITY; }
445 != { return INEQUALITY; }
446 \>= { return GREATEREQUAL; }
447 \<= { return LESSEQUAL; }
448 \|\| { return LOGICALOR; }
449 && { return LOGICALAND; }
450 \.\.\. { return ELLIPSIS; }
451 . { return yytext[0]; }
455 if (!list_empty( &import_stack ))
466 static void print_imports(void)
468 struct import_state *state, *next;
470 if (list_empty( &import_stack )) return;
472 fprintf( stderr, "In file included from " );
473 LIST_FOR_EACH_ENTRY_SAFE_REV( state, next, &import_stack, struct import_state, entry )
475 if (&next->entry == &import_stack) break;
476 fprintf( stderr, "%s:%d,\n", state->input_name, state->where.first_line );
477 fprintf( stderr, " from ");
479 fprintf( stderr, "%s:%d:\n", state->input_name, state->where.first_line );
482 void pop_import( struct location *where )
484 struct list *entry = list_head( &import_stack );
485 struct import_state *state;
488 state = LIST_ENTRY( entry, struct import_state, entry );
489 list_remove( &state->entry );
490 parse_only = !list_empty( &import_stack );
492 if (yyin) fclose( yyin );
493 yy_delete_buffer( YY_CURRENT_BUFFER );
494 yy_switch_to_buffer( state->buffer );
496 input_name = state->input_name;
497 *where = state->where;
501 void push_import( const char *import_name, struct location *where )
503 struct import_state *state;
504 struct import *import;
507 state = xmalloc( sizeof(struct import_state ));
508 list_add_head( &import_stack, &state->entry );
509 parse_only = !list_empty( &import_stack );
511 state->buffer = YY_CURRENT_BUFFER;
512 state->input_name = input_name;
513 state->where = *where;
516 /* reset buffer for <<EOF>>, in case import fails or already imported */
517 yy_scan_string( "" );
519 LIST_FOR_EACH_ENTRY( import, &imports, struct import, entry )
520 if (!strcmp( import->name, import_name )) return; /* already imported */
522 import = xmalloc( sizeof(struct import) );
523 import->name = xstrdup( import_name );
524 list_add_tail( &imports, &import->entry );
526 input_name = find_input_file( import_name, state->input_name );
527 file = open_input_file( input_name );
528 reset_location( where, input_name );
530 yy_switch_to_buffer( yy_create_buffer( file, YY_BUF_SIZE ) );
533 static void switch_to_acf(void)
537 if (yyin) fclose( yyin );
538 yy_delete_buffer( YY_CURRENT_BUFFER );
540 input_name = xstrdup( acf_name );
541 file = open_input_file( input_name );
544 yy_switch_to_buffer( yy_create_buffer( file, YY_BUF_SIZE ) );
547 static void reset_location( struct location *where, const char *input_name )
549 where->first_line = 1;
550 where->last_line = 1;
551 where->first_column = 1;
552 where->last_column = 1;
553 where->input_name = xstrdup( input_name );
556 static void update_location( struct location *where, const char *yytext )
558 int len = strlen( yytext );
559 previous_location = *where;
560 where->first_column = where->last_column;
561 where->last_column += len;
564 static void end_of_line( struct location *where )
568 where->first_column = 1;
569 where->last_column = 1;
572 void init_location( struct location *where, const struct location *begin, const struct location *end )
574 if (!begin) begin = &previous_location;
579 where->last_line = end->last_line;
580 where->last_column = end->last_column;
584 where->first_line = begin->last_line;
585 where->first_column = begin->last_column;
589 static void diagnostic( const struct location *where, const char *type, const char *message )
591 char buffer[1024], *line = NULL;
595 if (!where) where = &previous_location;
599 fprintf( stderr, "%s:%d:%d: %s: %s\n", where->input_name, where->first_line, where->first_column, type, message );
601 if (!where->input_name || !(file = fopen( where->input_name, "r" ))) return;
602 for (i = 0; i < where->first_line; i++) if (!(line = fgets( buffer, sizeof(buffer), file ))) break;
605 fprintf( stderr, "%s", line );
608 for (i = 0; i < where->first_column - 1; i++) line += sprintf( line, " " );
609 line += sprintf( line, "^" );
610 for (i = where->first_column + 1; i < where->last_column; i++) line += sprintf( line, "~" );
611 fprintf( stderr, "%s\n", buffer );
614 void parser_error( const struct location *where, const char *message )
616 diagnostic( where, "error", message );
619 void parser_warning( const struct location *where, const char *message )
621 diagnostic( where, "warning", message );
624 static void warning_disable(int warning)
626 warning_t *warning_entry;
627 LIST_FOR_EACH_ENTRY(warning_entry, disabled_warnings, warning_t, entry)
628 if(warning_entry->num == warning)
630 warning_entry = xmalloc( sizeof(*warning_entry) );
631 warning_entry->num = warning;
632 list_add_tail(disabled_warnings, &warning_entry->entry);
635 static void warning_enable(int warning)
637 warning_t *warning_entry;
638 LIST_FOR_EACH_ENTRY(warning_entry, disabled_warnings, warning_t, entry)
639 if(warning_entry->num == warning)
641 list_remove(&warning_entry->entry);
647 int do_warning(const char *toggle, warning_list_t *wnum)
649 warning_t *warning, *next;
651 if(!disabled_warnings)
653 disabled_warnings = xmalloc( sizeof(*disabled_warnings) );
654 list_init( disabled_warnings );
657 if(!strcmp(toggle, "disable"))
658 LIST_FOR_EACH_ENTRY(warning, wnum, warning_t, entry)
659 warning_disable(warning->num);
660 else if(!strcmp(toggle, "enable") || !strcmp(toggle, "default"))
661 LIST_FOR_EACH_ENTRY(warning, wnum, warning_t, entry)
662 warning_enable(warning->num);
666 LIST_FOR_EACH_ENTRY_SAFE(warning, next, wnum, warning_t, entry)
671 int is_warning_enabled(int warning)
673 warning_t *warning_entry;
674 if(!disabled_warnings)
676 LIST_FOR_EACH_ENTRY(warning_entry, disabled_warnings, warning_t, entry)
677 if(warning_entry->num == warning)