1 /* -*-C-*- 2 * Wrc preprocessor lexical analysis 3 * 4 * Copyright 1999-2000 Bertho A. Stultiens (BS) 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 * 20 *------------------------------------------------------------------------- 21 * The preprocessor's lexographical grammar (approximately): 22 * 23 * pp := {ws} # {ws} if {ws} {expr} {ws} \n 24 * | {ws} # {ws} ifdef {ws} {id} {ws} \n 25 * | {ws} # {ws} ifndef {ws} {id} {ws} \n 26 * | {ws} # {ws} elif {ws} {expr} {ws} \n 27 * | {ws} # {ws} else {ws} \n 28 * | {ws} # {ws} endif {ws} \n 29 * | {ws} # {ws} include {ws} < {anytext} > \n 30 * | {ws} # {ws} include {ws} " {anytext} " \n 31 * | {ws} # {ws} define {ws} {anytext} \n 32 * | {ws} # {ws} define( {arglist} ) {ws} {expansion} \n 33 * | {ws} # {ws} pragma {ws} {anytext} \n 34 * | {ws} # {ws} ident {ws} {anytext} \n 35 * | {ws} # {ws} error {ws} {anytext} \n 36 * | {ws} # {ws} warning {ws} {anytext} \n 37 * | {ws} # {ws} line {ws} " {anytext} " {number} \n 38 * | {ws} # {ws} {number} " {anytext} " {number} [ {number} [{number}] ] \n 39 * | {ws} # {ws} \n 40 * 41 * ws := [ \t\r\f\v]* 42 * 43 * expr := {expr} [+-*%^/|&] {expr} 44 * | {expr} {logor|logand} {expr} 45 * | [!~+-] {expr} 46 * | {expr} ? {expr} : {expr} 47 * 48 * logor := || 49 * 50 * logand := && 51 * 52 * id := [a-zA-Z_][a-zA-Z0-9_]* 53 * 54 * anytext := [^\n]* (see note) 55 * 56 * arglist := 57 * | {id} 58 * | {arglist} , {id} 59 * | {arglist} , {id} ... 60 * 61 * expansion := {id} 62 * | # {id} 63 * | {anytext} 64 * | {anytext} ## {anytext} 65 * 66 * number := [0-9]+ 67 * 68 * Note: "anytext" is not always "[^\n]*". This is because the 69 * trailing context must be considered as well. 70 * 71 * The only certain assumption for the preprocessor to make is that 72 * directives start at the beginning of the line, followed by a '#' 73 * and end with a newline. 74 * Any directive may be suffixed with a line-continuation. Also 75 * classical comment / *...* / (note: no comments within comments, 76 * therefore spaces) is considered to be a line-continuation 77 * (according to gcc and egcs AFAIK, ANSI is a bit vague). 78 * Comments have not been added to the above grammar for simplicity 79 * reasons. However, it is allowed to enter comment anywhere within 80 * the directives as long as they do not interfere with the context. 81 * All comments are considered to be deletable whitespace (both 82 * classical form "/ *...* /" and C++ form "//...\n"). 83 * 84 * All recursive scans, except for macro-expansion, are done by the 85 * parser, whereas the simple state transitions of non-recursive 86 * directives are done in the scanner. This results in the many 87 * exclusive start-conditions of the scanner. 88 * 89 * Macro expansions are slightly more difficult because they have to 90 * prescan the arguments. Parameter substitution is literal if the 91 * substitution is # or ## (either side). This enables new identifiers 92 * to be created (see 'info cpp' node Macro|Pitfalls|Prescan for more 93 * information). 94 * 95 * FIXME: Variable macro parameters is recognized, but not yet 96 * expanded. I have to reread the ANSI standard on the subject (yes, 97 * ANSI defines it). 98 * 99 * The following special defines are supported: 100 * __FILE__ -> "thissource.c" 101 * __LINE__ -> 123 102 * __DATE__ -> "May 1 2000" 103 * __TIME__ -> "23:59:59" 104 * These macros expand, as expected, into their ANSI defined values. 105 * 106 * The same include prevention is implemented as gcc and egcs does. 107 * This results in faster processing because we do not read the text 108 * at all. Some wine-sources attempt to include the same file 4 or 5 109 * times. This strategy also saves a lot blank output-lines, which in 110 * its turn improves the real resource scanner/parser. 111 * 112 */ 113 114 /* 115 * Special flex options and exclusive scanner start-conditions 116 */ 117 %option stack 118 %option 8bit never-interactive 119 %option noinput nounput 120 %option prefix="ppy_" 121 122 %x pp_pp 123 %x pp_eol 124 %x pp_inc 125 %x pp_dqs 126 %x pp_sqs 127 %x pp_iqs 128 %x pp_comment 129 %x pp_def 130 %x pp_define 131 %x pp_macro 132 %x pp_mbody 133 %x pp_macign 134 %x pp_macscan 135 %x pp_macexp 136 %x pp_if 137 %x pp_ifd 138 %x pp_ifignored 139 %x pp_endif 140 %x pp_line 141 %x pp_defined 142 %x pp_ignore 143 %x RCINCL 144 145 ws [ \v\f\t\r] 146 cident [a-zA-Z_][0-9a-zA-Z_]* 147 ul [uUlL]|[uUlL][lL]|[lL][uU]|[lL][lL][uU]|[uU][lL][lL]|[lL][uU][lL] 148 149 %{ 150 #include <stdio.h> 151 #include <stdlib.h> 152 #include <string.h> 153 #include <ctype.h> 154 #include <assert.h> 155 #include <errno.h> 156 #include <limits.h> 157 158 #define YY_NO_UNISTD_H 159 160 #include "wpp_private.h" 161 #include "ppy.tab.h" 162 163 /* 164 * Make sure that we are running an appropriate version of flex. 165 */ 166 #if !defined(YY_FLEX_MAJOR_VERSION) || (1000 * YY_FLEX_MAJOR_VERSION + YY_FLEX_MINOR_VERSION < 2005) 167 #error Must use flex version 2.5.1 or higher (yy_scan_* routines are required). 168 #endif 169 170 #define YY_READ_BUF_SIZE 65536 /* So we read most of a file at once */ 171 172 #define yy_current_state() YY_START 173 #define yy_pp_state(x) yy_pop_state(); yy_push_state(x) 174 175 /* 176 * Always update the current character position within a line 177 */ 178 #define YY_USER_ACTION pp_status.char_number+=ppy_leng; 179 180 /* 181 * Buffer management for includes and expansions 182 */ 183 #define MAXBUFFERSTACK 128 /* Nesting more than 128 includes or macro expansion textss is insane */ 184 185 typedef struct bufferstackentry { 186 YY_BUFFER_STATE bufferstate; /* Buffer to switch back to */ 187 void *filehandle; /* Handle to be used with wpp_callbacks->read */ 188 pp_entry_t *define; /* Points to expanding define or NULL if handling includes */ 189 int line_number; /* Line that we were handling */ 190 int char_number; /* The current position on that line */ 191 char *filename; /* Filename that we were handling */ 192 int if_depth; /* How many #if:s deep to check matching #endif:s */ 193 int ncontinuations; /* Remember the continuation state */ 194 int should_pop; /* Set if we must pop the start-state on EOF */ 195 /* Include management */ 196 include_state_t incl; 197 char *include_filename; 198 } bufferstackentry_t; 199 200 #define ALLOCBLOCKSIZE (1 << 10) /* Allocate these chunks at a time for string-buffers */ 201 202 /* 203 * Macro expansion nesting 204 * We need the stack to handle expansions while scanning 205 * a macro's arguments. The TOS must always be the macro 206 * that receives the current expansion from the scanner. 207 */ 208 #define MAXMACEXPSTACK 128 /* Nesting more than 128 macro expansions is insane */ 209 210 typedef struct macexpstackentry { 211 pp_entry_t *ppp; /* This macro we are scanning */ 212 char **args; /* With these arguments */ 213 char **ppargs; /* Resulting in these preprocessed arguments */ 214 int *nnls; /* Number of newlines per argument */ 215 int nargs; /* And this many arguments scanned */ 216 int parentheses; /* Nesting level of () */ 217 int curargsize; /* Current scanning argument's size */ 218 int curargalloc; /* Current scanning argument's block allocated */ 219 char *curarg; /* Current scanning argument's content */ 220 } macexpstackentry_t; 221 222 #define MACROPARENTHESES() (top_macro()->parentheses) 223 224 /* 225 * Prototypes 226 */ 227 static void newline(int); 228 static int make_number(int radix, YYSTYPE *val, const char *str, int len); 229 static void put_buffer(const char *s, int len); 230 /* Buffer management */ 231 static void push_buffer(pp_entry_t *ppp, char *filename, char *incname, int pop); 232 static bufferstackentry_t *pop_buffer(void); 233 /* String functions */ 234 static void new_string(void); 235 static void add_string(const char *str, int len); 236 static char *get_string(void); 237 static void put_string(void); 238 static int string_start(void); 239 /* Macro functions */ 240 static void push_macro(pp_entry_t *ppp); 241 static macexpstackentry_t *top_macro(void); 242 static macexpstackentry_t *pop_macro(void); 243 static void free_macro(macexpstackentry_t *mep); 244 static void add_text_to_macro(const char *text, int len); 245 static void macro_add_arg(int last); 246 static void macro_add_expansion(void); 247 /* Expansion */ 248 static void expand_special(pp_entry_t *ppp); 249 static void expand_define(pp_entry_t *ppp); 250 static void expand_macro(macexpstackentry_t *mep); 251 252 /* 253 * Local variables 254 */ 255 static int ncontinuations; 256 257 static int strbuf_idx = 0; 258 static int strbuf_alloc = 0; 259 static char *strbuffer = NULL; 260 static int str_startline; 261 262 static macexpstackentry_t *macexpstack[MAXMACEXPSTACK]; 263 static int macexpstackidx = 0; 264 265 static bufferstackentry_t bufferstack[MAXBUFFERSTACK]; 266 static int bufferstackidx = 0; 267 268 /* 269 * Global variables 270 */ 271 include_state_t pp_incl_state = 272 { 273 -1, /* state */ 274 NULL, /* ppp */ 275 0, /* ifdepth */ 276 0 /* seen_junk */ 277 }; 278 279 includelogicentry_t *pp_includelogiclist = NULL; 280 281 #define YY_INPUT(buf,result,max_size) \ 282 { \ 283 result = wpp_read(pp_status.file, buf, max_size); \ 284 } 285 286 #define BUFFERINITIALCAPACITY 256 287 288 void WINAPIV pp_writestring(const char *format, ...) 289 { 290 __ms_va_list valist; 291 int len; 292 static char *buffer; 293 static int buffercapacity; 294 char *new_buffer; 295 296 if(buffercapacity == 0) 297 { 298 buffer = pp_xmalloc(BUFFERINITIALCAPACITY); 299 if(buffer == NULL) 300 return; 301 buffercapacity = BUFFERINITIALCAPACITY; 302 } 303 304 __ms_va_start(valist, format); 305 len = vsnprintf(buffer, buffercapacity, 306 format, valist); 307 __ms_va_end(valist); 308 /* If the string is longer than buffersize, vsnprintf returns 309 * the string length with glibc >= 2.1, -1 with glibc < 2.1 */ 310 while(len > buffercapacity || len < 0) 311 { 312 do 313 { 314 buffercapacity *= 2; 315 } while(len > buffercapacity); 316 317 new_buffer = pp_xrealloc(buffer, buffercapacity); 318 if(new_buffer == NULL) 319 return; 320 buffer = new_buffer; 321 __ms_va_start(valist, format); 322 len = vsnprintf(buffer, buffercapacity, 323 format, valist); 324 __ms_va_end(valist); 325 } 326 327 wpp_write(buffer, len); 328 } 329 330 %} 331 332 /* 333 ************************************************************************** 334 * The scanner starts here 335 ************************************************************************** 336 */ 337 338 %% 339 /* 340 * Catch line-continuations. 341 * Note: Gcc keeps the line-continuations in, for example, strings 342 * intact. However, I prefer to remove them all so that the next 343 * scanner will not need to reduce the continuation state. 344 * 345 * <*>\\\n newline(0); 346 */ 347 348 /* 349 * Detect the leading # of a preprocessor directive. 350 */ 351 <INITIAL,pp_ignore>^{ws}*# pp_incl_state.seen_junk++; yy_push_state(pp_pp); 352 353 /* 354 * Scan for the preprocessor directives 355 */ 356 <pp_pp>{ws}*include{ws}* if(yy_top_state() != pp_ignore) {yy_pp_state(pp_inc); return tINCLUDE;} else {yy_pp_state(pp_eol);} 357 <pp_pp>{ws}*define{ws}* yy_pp_state(yy_current_state() != pp_ignore ? pp_def : pp_eol); 358 <pp_pp>{ws}*error{ws}* yy_pp_state(pp_eol); if(yy_top_state() != pp_ignore) return tERROR; 359 <pp_pp>{ws}*warning{ws}* yy_pp_state(pp_eol); if(yy_top_state() != pp_ignore) return tWARNING; 360 <pp_pp>{ws}*pragma{ws}* yy_pp_state(pp_eol); if(yy_top_state() != pp_ignore) return tPRAGMA; 361 <pp_pp>{ws}*ident{ws}* yy_pp_state(pp_eol); if(yy_top_state() != pp_ignore) return tPPIDENT; 362 <pp_pp>{ws}*undef{ws}* if(yy_top_state() != pp_ignore) {yy_pp_state(pp_ifd); return tUNDEF;} else {yy_pp_state(pp_eol);} 363 <pp_pp>{ws}*ifdef{ws}* yy_pp_state(pp_ifd); return tIFDEF; 364 <pp_pp>{ws}*ifndef{ws}* pp_incl_state.seen_junk--; yy_pp_state(pp_ifd); return tIFNDEF; 365 <pp_pp>{ws}*if{ws}* if(yy_top_state() != pp_ignore) {yy_pp_state(pp_if);} else {yy_pp_state(pp_ifignored);} return tIF; 366 <pp_pp>{ws}*elif{ws}* yy_pp_state(pp_if); return tELIF; 367 <pp_pp>{ws}*else{ws}* yy_pp_state(pp_endif); return tELSE; 368 <pp_pp>{ws}*endif{ws}* yy_pp_state(pp_endif); return tENDIF; 369 <pp_pp>{ws}*line{ws}* if(yy_top_state() != pp_ignore) {yy_pp_state(pp_line); return tLINE;} else {yy_pp_state(pp_eol);} 370 <pp_pp>{ws}+ if(yy_top_state() != pp_ignore) {yy_pp_state(pp_line); return tGCCLINE;} else {yy_pp_state(pp_eol);} 371 <pp_pp>{ws}*[a-z]+ ppy_error("Invalid preprocessor token '%s'", ppy_text); 372 <pp_pp>\r?\n newline(1); yy_pop_state(); return tNL; /* This could be the null-token */ 373 <pp_pp>\\\r?\n newline(0); 374 <pp_pp>\\\r? ppy_error("Preprocessor junk '%s'", ppy_text); 375 <pp_pp>. return *ppy_text; 376 377 /* 378 * Handle #include and #line 379 */ 380 <pp_line>[0-9]+ return make_number(10, &ppy_lval, ppy_text, ppy_leng); 381 <pp_inc>\< new_string(); add_string(ppy_text, ppy_leng); yy_push_state(pp_iqs); 382 <pp_inc,pp_line>\" new_string(); add_string(ppy_text, ppy_leng); yy_push_state(pp_dqs); 383 <pp_inc,pp_line>{ws}+ ; 384 <pp_inc,pp_line>\n newline(1); yy_pop_state(); return tNL; 385 <pp_inc,pp_line>\\\r?\n newline(0); 386 <pp_inc,pp_line>(\\\r?)|(.) ppy_error(yy_current_state() == pp_inc ? "Trailing junk in #include" : "Trailing junk in #line"); 387 388 /* 389 * Ignore all input when a false clause is parsed 390 */ 391 <pp_ignore>[^#/\\\n]+ ; 392 <pp_ignore>\n newline(1); 393 <pp_ignore>\\\r?\n newline(0); 394 <pp_ignore>(\\\r?)|(.) ; 395 396 /* 397 * Handle #if and #elif. 398 * These require conditionals to be evaluated, but we do not 399 * want to jam the scanner normally when we see these tokens. 400 * Note: tIDENT is handled below. 401 */ 402 403 <pp_if>0[0-7]*{ul}? return make_number(8, &ppy_lval, ppy_text, ppy_leng); 404 <pp_if>0[0-7]*[8-9]+{ul}? ppy_error("Invalid octal digit"); 405 <pp_if>[1-9][0-9]*{ul}? return make_number(10, &ppy_lval, ppy_text, ppy_leng); 406 <pp_if>0[xX][0-9a-fA-F]+{ul}? return make_number(16, &ppy_lval, ppy_text, ppy_leng); 407 <pp_if>0[xX] ppy_error("Invalid hex number"); 408 <pp_if>defined yy_push_state(pp_defined); return tDEFINED; 409 <pp_if>"<<" return tLSHIFT; 410 <pp_if>">>" return tRSHIFT; 411 <pp_if>"&&" return tLOGAND; 412 <pp_if>"||" return tLOGOR; 413 <pp_if>"==" return tEQ; 414 <pp_if>"!=" return tNE; 415 <pp_if>"<=" return tLTE; 416 <pp_if>">=" return tGTE; 417 <pp_if>\n newline(1); yy_pop_state(); return tNL; 418 <pp_if>\\\r?\n newline(0); 419 <pp_if>\\\r? ppy_error("Junk in conditional expression"); 420 <pp_if>{ws}+ ; 421 <pp_if>\' new_string(); add_string(ppy_text, ppy_leng); yy_push_state(pp_sqs); 422 <pp_if>\" ppy_error("String constants not allowed in conditionals"); 423 <pp_if>. return *ppy_text; 424 425 <pp_ifignored>[^\n]+ ppy_lval.sint = 0; return tSINT; 426 <pp_ifignored>\n newline(1); yy_pop_state(); return tNL; 427 428 /* 429 * Handle #ifdef, #ifndef and #undef 430 * to get only an untranslated/unexpanded identifier 431 */ 432 <pp_ifd>{cident} ppy_lval.cptr = pp_xstrdup(ppy_text); return tIDENT; 433 <pp_ifd>{ws}+ ; 434 <pp_ifd>\n newline(1); yy_pop_state(); return tNL; 435 <pp_ifd>\\\r?\n newline(0); 436 <pp_ifd>(\\\r?)|(.) ppy_error("Identifier expected"); 437 438 /* 439 * Handle #else and #endif. 440 */ 441 <pp_endif>{ws}+ ; 442 <pp_endif>\n newline(1); yy_pop_state(); return tNL; 443 <pp_endif>\\\r?\n newline(0); 444 <pp_endif>. ppy_error("Garbage after #else or #endif."); 445 446 /* 447 * Handle the special 'defined' keyword. 448 * This is necessary to get the identifier prior to any 449 * substitutions. 450 */ 451 <pp_defined>{cident} yy_pop_state(); ppy_lval.cptr = pp_xstrdup(ppy_text); return tIDENT; 452 <pp_defined>{ws}+ ; 453 <pp_defined>(\()|(\)) return *ppy_text; 454 <pp_defined>\\\r?\n newline(0); 455 <pp_defined>(\\.)|(\n)|(.) ppy_error("Identifier expected"); 456 457 /* 458 * Handle #error, #warning, #pragma and #ident. 459 * Pass everything literally to the parser, which 460 * will act appropriately. 461 * Comments are stripped from the literal text. 462 */ 463 <pp_eol>[^/\\\n]+ if(yy_top_state() != pp_ignore) { ppy_lval.cptr = pp_xstrdup(ppy_text); return tLITERAL; } 464 <pp_eol>\/[^/\\\n*]* if(yy_top_state() != pp_ignore) { ppy_lval.cptr = pp_xstrdup(ppy_text); return tLITERAL; } 465 <pp_eol>(\\\r?)|(\/[^/*]) if(yy_top_state() != pp_ignore) { ppy_lval.cptr = pp_xstrdup(ppy_text); return tLITERAL; } 466 <pp_eol>\n newline(1); yy_pop_state(); if(yy_current_state() != pp_ignore) { return tNL; } 467 <pp_eol>\\\r?\n newline(0); 468 469 /* 470 * Handle left side of #define 471 */ 472 <pp_def>{cident}\( ppy_lval.cptr = pp_xstrdup(ppy_text); if(ppy_lval.cptr) ppy_lval.cptr[ppy_leng-1] = '\0'; yy_pp_state(pp_macro); return tMACRO; 473 <pp_def>{cident} ppy_lval.cptr = pp_xstrdup(ppy_text); yy_pp_state(pp_define); return tDEFINE; 474 <pp_def>{ws}+ ; 475 <pp_def>\\\r?\n newline(0); 476 <pp_def>(\\\r?)|(\n)|(.) perror("Identifier expected"); 477 478 /* 479 * Scan the substitution of a define 480 */ 481 <pp_define>[^'"/\\\n]+ ppy_lval.cptr = pp_xstrdup(ppy_text); return tLITERAL; 482 <pp_define>(\\\r?)|(\/[^/*]) ppy_lval.cptr = pp_xstrdup(ppy_text); return tLITERAL; 483 <pp_define>\\\r?\n{ws}+ newline(0); ppy_lval.cptr = pp_xstrdup(" "); return tLITERAL; 484 <pp_define>\\\r?\n newline(0); 485 <pp_define>\n newline(1); yy_pop_state(); return tNL; 486 <pp_define>\' new_string(); add_string(ppy_text, ppy_leng); yy_push_state(pp_sqs); 487 <pp_define>\" new_string(); add_string(ppy_text, ppy_leng); yy_push_state(pp_dqs); 488 489 /* 490 * Scan the definition macro arguments 491 */ 492 <pp_macro>\){ws}* yy_pp_state(pp_mbody); return tMACROEND; 493 <pp_macro>{ws}+ ; 494 <pp_macro>{cident} ppy_lval.cptr = pp_xstrdup(ppy_text); return tIDENT; 495 <pp_macro>, return ','; 496 <pp_macro>"..." return tELIPSIS; 497 <pp_macro>(\\\r?)|(\n)|(.)|(\.\.?) ppy_error("Argument identifier expected"); 498 <pp_macro>\\\r?\n newline(0); 499 500 /* 501 * Scan the substitution of a macro 502 */ 503 <pp_mbody>[^a-zA-Z0-9'"#/\\\n]+ ppy_lval.cptr = pp_xstrdup(ppy_text); return tLITERAL; 504 <pp_mbody>{cident} ppy_lval.cptr = pp_xstrdup(ppy_text); return tIDENT; 505 <pp_mbody>\#\# return tCONCAT; 506 <pp_mbody>\# return tSTRINGIZE; 507 <pp_mbody>[0-9][a-zA-Z0-9]*[^a-zA-Z0-9'"#/\\\n]* ppy_lval.cptr = pp_xstrdup(ppy_text); return tLITERAL; 508 <pp_mbody>(\\\r?)|(\/[^/*'"#\\\n]*) ppy_lval.cptr = pp_xstrdup(ppy_text); return tLITERAL; 509 <pp_mbody>\\\r?\n{ws}+ newline(0); ppy_lval.cptr = pp_xstrdup(" "); return tLITERAL; 510 <pp_mbody>\\\r?\n newline(0); 511 <pp_mbody>\n newline(1); yy_pop_state(); return tNL; 512 <pp_mbody>\' new_string(); add_string(ppy_text, ppy_leng); yy_push_state(pp_sqs); 513 <pp_mbody>\" new_string(); add_string(ppy_text, ppy_leng); yy_push_state(pp_dqs); 514 515 /* 516 * Macro expansion text scanning. 517 * This state is active just after the identifier is scanned 518 * that triggers an expansion. We *must* delete the leading 519 * whitespace before we can start scanning for arguments. 520 * 521 * If we do not see a '(' as next trailing token, then we have 522 * a false alarm. We just continue with a nose-bleed... 523 */ 524 <pp_macign>{ws}*/\( yy_pp_state(pp_macscan); 525 <pp_macign>{ws}*\n { 526 if(yy_top_state() != pp_macscan) 527 newline(0); 528 } 529 <pp_macign>{ws}*\\\r?\n newline(0); 530 <pp_macign>{ws}+|{ws}*\\\r?|. { 531 macexpstackentry_t *mac = pop_macro(); 532 yy_pop_state(); 533 put_buffer(mac->ppp->ident, strlen(mac->ppp->ident)); 534 put_buffer(ppy_text, ppy_leng); 535 free_macro(mac); 536 } 537 538 /* 539 * Macro expansion argument text scanning. 540 * This state is active when a macro's arguments are being read for expansion. 541 */ 542 <pp_macscan>\( { 543 if(++MACROPARENTHESES() > 1) 544 add_text_to_macro(ppy_text, ppy_leng); 545 } 546 <pp_macscan>\) { 547 if(--MACROPARENTHESES() == 0) 548 { 549 yy_pop_state(); 550 macro_add_arg(1); 551 } 552 else 553 add_text_to_macro(ppy_text, ppy_leng); 554 } 555 <pp_macscan>, { 556 if(MACROPARENTHESES() > 1) 557 add_text_to_macro(ppy_text, ppy_leng); 558 else 559 macro_add_arg(0); 560 } 561 <pp_macscan>\" new_string(); add_string(ppy_text, ppy_leng); yy_push_state(pp_dqs); 562 <pp_macscan>\' new_string(); add_string(ppy_text, ppy_leng); yy_push_state(pp_sqs); 563 <pp_macscan>"/*" yy_push_state(pp_comment); add_text_to_macro(" ", 1); 564 <pp_macscan>\n pp_status.line_number++; pp_status.char_number = 1; add_text_to_macro(ppy_text, ppy_leng); 565 <pp_macscan>([^/(),\\\n"']+)|(\/[^/*(),\\\n'"]*)|(\\\r?)|(.) add_text_to_macro(ppy_text, ppy_leng); 566 <pp_macscan>\\\r?\n newline(0); 567 568 /* 569 * Comment handling (almost all start-conditions) 570 */ 571 <INITIAL,pp_pp,pp_ignore,pp_eol,pp_inc,pp_if,pp_ifd,pp_endif,pp_defined,pp_def,pp_define,pp_macro,pp_mbody,RCINCL>"/*" yy_push_state(pp_comment); 572 <pp_comment>[^*\n]*|"*"+[^*/\n]* ; 573 <pp_comment>\n newline(0); 574 <pp_comment>"*"+"/" yy_pop_state(); 575 576 /* 577 * Remove C++ style comment (almost all start-conditions) 578 */ 579 <INITIAL,pp_pp,pp_ignore,pp_eol,pp_inc,pp_if,pp_ifd,pp_endif,pp_defined,pp_def,pp_define,pp_macro,pp_mbody,pp_macscan,RCINCL>"//"[^\n]* { 580 if(ppy_text[ppy_leng-1] == '\\') 581 ppy_warning("C++ style comment ends with an escaped newline (escape ignored)"); 582 } 583 584 /* 585 * Single, double and <> quoted constants 586 */ 587 <INITIAL,pp_macexp>\" pp_incl_state.seen_junk++; new_string(); add_string(ppy_text, ppy_leng); yy_push_state(pp_dqs); 588 <INITIAL,pp_macexp>\' pp_incl_state.seen_junk++; new_string(); add_string(ppy_text, ppy_leng); yy_push_state(pp_sqs); 589 <pp_dqs>[^"\\\n]+ add_string(ppy_text, ppy_leng); 590 <pp_dqs>\" { 591 add_string(ppy_text, ppy_leng); 592 yy_pop_state(); 593 switch(yy_current_state()) 594 { 595 case pp_pp: 596 case pp_define: 597 case pp_mbody: 598 case pp_inc: 599 case RCINCL: 600 if (yy_current_state()==RCINCL) yy_pop_state(); 601 ppy_lval.cptr = get_string(); 602 return tDQSTRING; 603 case pp_line: 604 ppy_lval.cptr = get_string(); 605 return tDQSTRING; 606 default: 607 put_string(); 608 } 609 } 610 <pp_sqs>[^'\\\n]+ add_string(ppy_text, ppy_leng); 611 <pp_sqs>\' { 612 add_string(ppy_text, ppy_leng); 613 yy_pop_state(); 614 switch(yy_current_state()) 615 { 616 case pp_if: 617 case pp_define: 618 case pp_mbody: 619 ppy_lval.cptr = get_string(); 620 return tSQSTRING; 621 default: 622 put_string(); 623 } 624 } 625 <pp_iqs>[^\>\\\n]+ add_string(ppy_text, ppy_leng); 626 <pp_iqs>\> { 627 add_string(ppy_text, ppy_leng); 628 yy_pop_state(); 629 ppy_lval.cptr = get_string(); 630 return tIQSTRING; 631 } 632 <pp_dqs>\\\r?\n { 633 /* 634 * This is tricky; we need to remove the line-continuation 635 * from preprocessor strings, but OTOH retain them in all 636 * other strings. This is because the resource grammar is 637 * even more braindead than initially analysed and line- 638 * continuations in strings introduce, sigh, newlines in 639 * the output. There goes the concept of non-breaking, non- 640 * spacing whitespace. 641 */ 642 switch(yy_top_state()) 643 { 644 case pp_pp: 645 case pp_define: 646 case pp_mbody: 647 case pp_inc: 648 case pp_line: 649 newline(0); 650 break; 651 default: 652 add_string(ppy_text, ppy_leng); 653 newline(-1); 654 } 655 } 656 <pp_iqs,pp_dqs,pp_sqs>\\. add_string(ppy_text, ppy_leng); 657 <pp_iqs,pp_dqs,pp_sqs>\n { 658 newline(1); 659 add_string(ppy_text, ppy_leng); 660 ppy_warning("Newline in string constant encountered (started line %d)", string_start()); 661 } 662 663 /* 664 * Identifier scanning 665 */ 666 <INITIAL,pp_if,pp_inc,pp_macexp>{cident} { 667 pp_entry_t *ppp; 668 pp_incl_state.seen_junk++; 669 if(!(ppp = pplookup(ppy_text))) 670 { 671 if(yy_current_state() == pp_inc) 672 ppy_error("Expected include filename"); 673 674 else if(yy_current_state() == pp_if) 675 { 676 ppy_lval.cptr = pp_xstrdup(ppy_text); 677 return tIDENT; 678 } 679 else { 680 if((yy_current_state()==INITIAL) && (strcasecmp(ppy_text,"RCINCLUDE")==0)){ 681 yy_push_state(RCINCL); 682 return tRCINCLUDE; 683 } 684 else put_buffer(ppy_text, ppy_leng); 685 } 686 } 687 else if(!ppp->expanding) 688 { 689 switch(ppp->type) 690 { 691 case def_special: 692 expand_special(ppp); 693 break; 694 case def_define: 695 expand_define(ppp); 696 break; 697 case def_macro: 698 yy_push_state(pp_macign); 699 push_macro(ppp); 700 break; 701 default: 702 pp_internal_error(__FILE__, __LINE__, "Invalid define type %d\n", ppp->type); 703 } 704 } 705 else put_buffer(ppy_text, ppy_leng); 706 } 707 708 /* 709 * Everything else that needs to be passed and 710 * newline and continuation handling 711 */ 712 <INITIAL,pp_macexp>[^a-zA-Z_#'"/\\\n \r\t\f\v]+|(\/|\\)[^a-zA-Z_/*'"\\\n \r\t\v\f]* pp_incl_state.seen_junk++; put_buffer(ppy_text, ppy_leng); 713 <INITIAL,pp_macexp>{ws}+ put_buffer(ppy_text, ppy_leng); 714 <INITIAL>\n newline(1); 715 <INITIAL>\\\r?\n newline(0); 716 <INITIAL>\\\r? pp_incl_state.seen_junk++; put_buffer(ppy_text, ppy_leng); 717 718 /* 719 * Special catcher for macro argmument expansion to prevent 720 * newlines to propagate to the output or admin. 721 */ 722 <pp_macexp>(\n)|(.)|(\\\r?(\n|.)) put_buffer(ppy_text, ppy_leng); 723 724 <RCINCL>[A-Za-z0-9_\.\\/]+ { 725 ppy_lval.cptr=pp_xstrdup(ppy_text); 726 yy_pop_state(); 727 return tRCINCLUDEPATH; 728 } 729 730 <RCINCL>{ws}+ ; 731 732 <RCINCL>\" { 733 new_string(); add_string(ppy_text,ppy_leng);yy_push_state(pp_dqs); 734 } 735 736 /* 737 * This is a 'catch-all' rule to discover errors in the scanner 738 * in an orderly manner. 739 */ 740 <*>. pp_incl_state.seen_junk++; ppy_warning("Unmatched text '%c' (0x%02x); please report\n", isprint(*ppy_text & 0xff) ? *ppy_text : ' ', *ppy_text); 741 742 <<EOF>> { 743 YY_BUFFER_STATE b = YY_CURRENT_BUFFER; 744 bufferstackentry_t *bep = pop_buffer(); 745 746 if((!bep && pp_get_if_depth()) || (bep && pp_get_if_depth() != bep->if_depth)) 747 ppy_warning("Unmatched #if/#endif at end of file"); 748 749 if(!bep) 750 { 751 if(YY_START != INITIAL) 752 { 753 ppy_error("Unexpected end of file during preprocessing"); 754 BEGIN(INITIAL); 755 } 756 yyterminate(); 757 } 758 else if(bep->should_pop == 2) 759 { 760 macexpstackentry_t *mac; 761 mac = pop_macro(); 762 expand_macro(mac); 763 } 764 ppy__delete_buffer(b); 765 } 766 767 %% 768 /* 769 ************************************************************************** 770 * Support functions 771 ************************************************************************** 772 */ 773 774 #ifndef ppy_wrap 775 int ppy_wrap(void) 776 { 777 return 1; 778 } 779 #endif 780 781 782 /* 783 *------------------------------------------------------------------------- 784 * Output newlines or set them as continuations 785 * 786 * Input: -1 - Don't count this one, but update local position (see pp_dqs) 787 * 0 - Line-continuation seen and cache output 788 * 1 - Newline seen and flush output 789 *------------------------------------------------------------------------- 790 */ 791 static void newline(int dowrite) 792 { 793 pp_status.line_number++; 794 pp_status.char_number = 1; 795 796 if(dowrite == -1) 797 return; 798 799 ncontinuations++; 800 if(dowrite) 801 { 802 for(;ncontinuations; ncontinuations--) 803 put_buffer("\n", 1); 804 } 805 } 806 807 808 /* 809 *------------------------------------------------------------------------- 810 * Make a number out of an any-base and suffixed string 811 * 812 * Possible number extensions: 813 * - "" int 814 * - "L" long int 815 * - "LL" long long int 816 * - "U" unsigned int 817 * - "UL" unsigned long int 818 * - "ULL" unsigned long long int 819 * - "LU" unsigned long int 820 * - "LLU" unsigned long long int 821 * - "LUL" invalid 822 * 823 * FIXME: 824 * The sizes of resulting 'int' and 'long' are compiler specific. 825 * I depend on sizeof(int) > 2 here (although a relatively safe 826 * assumption). 827 * Long longs are not yet implemented because this is very compiler 828 * specific and I don't want to think too much about the problems. 829 * 830 *------------------------------------------------------------------------- 831 */ 832 static int make_number(int radix, YYSTYPE *val, const char *str, int len) 833 { 834 int is_l = 0; 835 int is_ll = 0; 836 int is_u = 0; 837 char ext[4]; 838 long l; 839 840 ext[3] = '\0'; 841 ext[2] = toupper(str[len-1]); 842 ext[1] = len > 1 ? toupper(str[len-2]) : ' '; 843 ext[0] = len > 2 ? toupper(str[len-3]) : ' '; 844 845 if(!strcmp(ext, "LUL")) 846 { 847 ppy_error("Invalid constant suffix"); 848 return 0; 849 } 850 else if(!strcmp(ext, "LLU") || !strcmp(ext, "ULL")) 851 { 852 is_ll++; 853 is_u++; 854 } 855 else if(!strcmp(ext+1, "LU") || !strcmp(ext+1, "UL")) 856 { 857 is_l++; 858 is_u++; 859 } 860 else if(!strcmp(ext+1, "LL")) 861 { 862 is_ll++; 863 } 864 else if(!strcmp(ext+2, "L")) 865 { 866 is_l++; 867 } 868 else if(!strcmp(ext+2, "U")) 869 { 870 is_u++; 871 } 872 873 if(is_u && is_ll) 874 { 875 errno = 0; 876 val->ull = _strtoui64(str, NULL, radix); 877 if (val->ull == ULLONG_MAX && errno == ERANGE) 878 ppy_error("integer constant %s is too large\n", str); 879 return tULONGLONG; 880 } 881 else if(!is_u && is_ll) 882 { 883 errno = 0; 884 val->sll = _strtoi64(str, NULL, radix); 885 if ((val->sll == LLONG_MIN || val->sll == LLONG_MAX) && errno == ERANGE) 886 ppy_error("integer constant %s is too large\n", str); 887 return tSLONGLONG; 888 } 889 else if(is_u && is_l) 890 { 891 errno = 0; 892 val->ulong = strtoul(str, NULL, radix); 893 if (val->ulong == ULONG_MAX && errno == ERANGE) 894 ppy_error("integer constant %s is too large\n", str); 895 return tULONG; 896 } 897 else if(!is_u && is_l) 898 { 899 errno = 0; 900 val->slong = strtol(str, NULL, radix); 901 if ((val->slong == LONG_MIN || val->slong == LONG_MAX) && errno == ERANGE) 902 ppy_error("integer constant %s is too large\n", str); 903 return tSLONG; 904 } 905 else if(is_u && !is_l) 906 { 907 unsigned long ul; 908 errno = 0; 909 ul = strtoul(str, NULL, radix); 910 if ((ul == ULONG_MAX && errno == ERANGE) || (ul > UINT_MAX)) 911 ppy_error("integer constant %s is too large\n", str); 912 val->uint = (unsigned int)ul; 913 return tUINT; 914 } 915 916 /* Else it must be an int... */ 917 errno = 0; 918 l = strtol(str, NULL, radix); 919 if (((l == LONG_MIN || l == LONG_MAX) && errno == ERANGE) || 920 (l > INT_MAX) || (l < INT_MIN)) 921 ppy_error("integer constant %s is too large\n", str); 922 val->sint = (int)l; 923 return tSINT; 924 } 925 926 927 /* 928 *------------------------------------------------------------------------- 929 * Macro and define expansion support 930 * 931 * FIXME: Variable macro arguments. 932 *------------------------------------------------------------------------- 933 */ 934 static void expand_special(pp_entry_t *ppp) 935 { 936 static char *buf = NULL; 937 char *new_buf; 938 939 assert(ppp->type == def_special); 940 941 if(!strcmp(ppp->ident, "__LINE__")) 942 { 943 new_buf = pp_xrealloc(buf, 32); 944 if(!new_buf) 945 return; 946 buf = new_buf; 947 sprintf(buf, "%d", pp_status.line_number); 948 } 949 else if(!strcmp(ppp->ident, "__FILE__")) 950 { 951 new_buf = pp_xrealloc(buf, strlen(pp_status.input) + 3); 952 if(!new_buf) 953 return; 954 buf = new_buf; 955 sprintf(buf, "\"%s\"", pp_status.input); 956 } 957 else 958 pp_internal_error(__FILE__, __LINE__, "Special macro '%s' not found...\n", ppp->ident); 959 960 if(buf && buf[0]) 961 { 962 push_buffer(ppp, NULL, NULL, 0); 963 yy_scan_string(buf); 964 } 965 } 966 967 static void expand_define(pp_entry_t *ppp) 968 { 969 assert(ppp->type == def_define); 970 971 if(ppp->subst.text && ppp->subst.text[0]) 972 { 973 push_buffer(ppp, NULL, NULL, 0); 974 yy_scan_string(ppp->subst.text); 975 } 976 } 977 978 static int curdef_idx = 0; 979 static int curdef_alloc = 0; 980 static char *curdef_text = NULL; 981 982 static void add_text(const char *str, int len) 983 { 984 int new_alloc; 985 char *new_text; 986 987 if(len == 0) 988 return; 989 if(curdef_idx >= curdef_alloc || curdef_alloc - curdef_idx < len) 990 { 991 new_alloc = curdef_alloc + ((len + ALLOCBLOCKSIZE-1) & ~(ALLOCBLOCKSIZE-1)); 992 new_text = pp_xrealloc(curdef_text, new_alloc * sizeof(curdef_text[0])); 993 if(!new_text) 994 return; 995 curdef_text = new_text; 996 curdef_alloc = new_alloc; 997 if(curdef_alloc > 65536) 998 ppy_warning("Reallocating macro-expansion buffer larger than 64kB"); 999 } 1000 memcpy(&curdef_text[curdef_idx], str, len); 1001 curdef_idx += len; 1002 } 1003 1004 static mtext_t *add_expand_text(mtext_t *mtp, macexpstackentry_t *mep, int *nnl) 1005 { 1006 char *cptr; 1007 char *exp; 1008 int tag; 1009 int n; 1010 1011 if(mtp == NULL) 1012 return NULL; 1013 1014 switch(mtp->type) 1015 { 1016 case exp_text: 1017 add_text(mtp->subst.text, strlen(mtp->subst.text)); 1018 break; 1019 1020 case exp_stringize: 1021 cptr = mep->args[mtp->subst.argidx]; 1022 add_text("\"", 1); 1023 while(*cptr) 1024 { 1025 if(*cptr == '"' || *cptr == '\\') 1026 add_text("\\", 1); 1027 add_text(cptr, 1); 1028 cptr++; 1029 } 1030 add_text("\"", 1); 1031 break; 1032 1033 case exp_concat: 1034 /* Remove trailing whitespace from current expansion text */ 1035 while(curdef_idx) 1036 { 1037 if(isspace(curdef_text[curdef_idx-1] & 0xff)) 1038 curdef_idx--; 1039 else 1040 break; 1041 } 1042 /* tag current position and recursively expand the next part */ 1043 tag = curdef_idx; 1044 mtp = add_expand_text(mtp->next, mep, nnl); 1045 1046 /* Now get rid of the leading space of the expansion */ 1047 cptr = &curdef_text[tag]; 1048 n = curdef_idx - tag; 1049 while(n) 1050 { 1051 if(isspace(*cptr & 0xff)) 1052 { 1053 cptr++; 1054 n--; 1055 } 1056 else 1057 break; 1058 } 1059 if(cptr != &curdef_text[tag]) 1060 { 1061 memmove(&curdef_text[tag], cptr, n); 1062 curdef_idx -= (curdef_idx - tag) - n; 1063 } 1064 break; 1065 1066 case exp_subst: 1067 if((mtp->next && mtp->next->type == exp_concat) || (mtp->prev && mtp->prev->type == exp_concat)) 1068 exp = mep->args[mtp->subst.argidx]; 1069 else 1070 exp = mep->ppargs[mtp->subst.argidx]; 1071 if(exp) 1072 { 1073 add_text(exp, strlen(exp)); 1074 *nnl -= mep->nnls[mtp->subst.argidx]; 1075 cptr = strchr(exp, '\n'); 1076 while(cptr) 1077 { 1078 *cptr = ' '; 1079 cptr = strchr(cptr+1, '\n'); 1080 } 1081 mep->nnls[mtp->subst.argidx] = 0; 1082 } 1083 break; 1084 1085 default: 1086 pp_internal_error(__FILE__, __LINE__, "Invalid expansion type (%d) in macro expansion\n", mtp->type); 1087 } 1088 return mtp; 1089 } 1090 1091 static void expand_macro(macexpstackentry_t *mep) 1092 { 1093 mtext_t *mtp; 1094 int n, k; 1095 char *cptr; 1096 int nnl = 0; 1097 pp_entry_t *ppp = mep->ppp; 1098 int nargs = mep->nargs; 1099 1100 assert(ppp->type == def_macro); 1101 assert(ppp->expanding == 0); 1102 1103 if((ppp->nargs >= 0 && nargs != ppp->nargs) || (ppp->nargs < 0 && nargs < -ppp->nargs)) 1104 { 1105 ppy_error("Too %s macro arguments (%d)", nargs < abs(ppp->nargs) ? "few" : "many", nargs); 1106 return; 1107 } 1108 1109 for(n = 0; n < nargs; n++) 1110 nnl += mep->nnls[n]; 1111 1112 curdef_idx = 0; 1113 1114 for(mtp = ppp->subst.mtext; mtp; mtp = mtp->next) 1115 { 1116 if(!(mtp = add_expand_text(mtp, mep, &nnl))) 1117 break; 1118 } 1119 1120 for(n = 0; n < nnl; n++) 1121 add_text("\n", 1); 1122 1123 /* To make sure there is room and termination (see below) */ 1124 add_text(" \0", 2); 1125 1126 /* Strip trailing whitespace from expansion */ 1127 for(k = curdef_idx, cptr = &curdef_text[curdef_idx-1]; k > 0; k--, cptr--) 1128 { 1129 if(!isspace(*cptr & 0xff)) 1130 break; 1131 } 1132 1133 /* 1134 * We must add *one* whitespace to make sure that there 1135 * is a token-separation after the expansion. 1136 */ 1137 *(++cptr) = ' '; 1138 *(++cptr) = '\0'; 1139 k++; 1140 1141 /* Strip leading whitespace from expansion */ 1142 for(n = 0, cptr = curdef_text; n < k; n++, cptr++) 1143 { 1144 if(!isspace(*cptr & 0xff)) 1145 break; 1146 } 1147 1148 if(k - n > 0) 1149 { 1150 push_buffer(ppp, NULL, NULL, 0); 1151 /*yy_scan_bytes(curdef_text + n, k - n);*/ 1152 yy_scan_string(curdef_text + n); 1153 } 1154 } 1155 1156 /* 1157 *------------------------------------------------------------------------- 1158 * String collection routines 1159 *------------------------------------------------------------------------- 1160 */ 1161 static void new_string(void) 1162 { 1163 #ifdef DEBUG 1164 if(strbuf_idx) 1165 ppy_warning("new_string: strbuf_idx != 0"); 1166 #endif 1167 strbuf_idx = 0; 1168 str_startline = pp_status.line_number; 1169 } 1170 1171 static void add_string(const char *str, int len) 1172 { 1173 int new_alloc; 1174 char *new_buffer; 1175 1176 if(len == 0) 1177 return; 1178 if(strbuf_idx >= strbuf_alloc || strbuf_alloc - strbuf_idx < len) 1179 { 1180 new_alloc = strbuf_alloc + ((len + ALLOCBLOCKSIZE-1) & ~(ALLOCBLOCKSIZE-1)); 1181 new_buffer = pp_xrealloc(strbuffer, new_alloc * sizeof(strbuffer[0])); 1182 if(!new_buffer) 1183 return; 1184 strbuffer = new_buffer; 1185 strbuf_alloc = new_alloc; 1186 if(strbuf_alloc > 65536) 1187 ppy_warning("Reallocating string buffer larger than 64kB"); 1188 } 1189 memcpy(&strbuffer[strbuf_idx], str, len); 1190 strbuf_idx += len; 1191 } 1192 1193 static char *get_string(void) 1194 { 1195 char *str = pp_xmalloc(strbuf_idx + 1); 1196 if(!str) 1197 return NULL; 1198 memcpy(str, strbuffer, strbuf_idx); 1199 str[strbuf_idx] = '\0'; 1200 #ifdef DEBUG 1201 strbuf_idx = 0; 1202 #endif 1203 return str; 1204 } 1205 1206 static void put_string(void) 1207 { 1208 put_buffer(strbuffer, strbuf_idx); 1209 #ifdef DEBUG 1210 strbuf_idx = 0; 1211 #endif 1212 } 1213 1214 static int string_start(void) 1215 { 1216 return str_startline; 1217 } 1218 1219 1220 /* 1221 *------------------------------------------------------------------------- 1222 * Buffer management 1223 *------------------------------------------------------------------------- 1224 */ 1225 static void push_buffer(pp_entry_t *ppp, char *filename, char *incname, int pop) 1226 { 1227 if(bufferstackidx >= MAXBUFFERSTACK) 1228 pp_internal_error(__FILE__, __LINE__, "Buffer stack overflow"); 1229 1230 memset(&bufferstack[bufferstackidx], 0, sizeof(bufferstack[0])); 1231 bufferstack[bufferstackidx].bufferstate = YY_CURRENT_BUFFER; 1232 bufferstack[bufferstackidx].filehandle = pp_status.file; 1233 bufferstack[bufferstackidx].define = ppp; 1234 bufferstack[bufferstackidx].line_number = pp_status.line_number; 1235 bufferstack[bufferstackidx].char_number = pp_status.char_number; 1236 bufferstack[bufferstackidx].if_depth = pp_get_if_depth(); 1237 bufferstack[bufferstackidx].should_pop = pop; 1238 bufferstack[bufferstackidx].filename = pp_status.input; 1239 bufferstack[bufferstackidx].ncontinuations = ncontinuations; 1240 bufferstack[bufferstackidx].incl = pp_incl_state; 1241 bufferstack[bufferstackidx].include_filename = incname; 1242 1243 if(ppp) 1244 ppp->expanding = 1; 1245 else if(filename) 1246 { 1247 /* These will track the ppy_error to the correct file and line */ 1248 pp_status.line_number = 1; 1249 pp_status.char_number = 1; 1250 pp_status.input = filename; 1251 ncontinuations = 0; 1252 } 1253 else if(!pop) 1254 pp_internal_error(__FILE__, __LINE__, "Pushing buffer without knowing where to go to"); 1255 bufferstackidx++; 1256 } 1257 1258 static bufferstackentry_t *pop_buffer(void) 1259 { 1260 if(bufferstackidx < 0) 1261 pp_internal_error(__FILE__, __LINE__, "Bufferstack underflow?"); 1262 1263 if(bufferstackidx == 0) 1264 return NULL; 1265 1266 bufferstackidx--; 1267 1268 if(bufferstack[bufferstackidx].define) 1269 bufferstack[bufferstackidx].define->expanding = 0; 1270 else 1271 { 1272 includelogicentry_t *iep = NULL; 1273 1274 if(!bufferstack[bufferstackidx].should_pop) 1275 { 1276 wpp_close(pp_status.file); 1277 pp_writestring("# %d \"%s\" 2\n", bufferstack[bufferstackidx].line_number, bufferstack[bufferstackidx].filename); 1278 1279 /* We have EOF, check the include logic */ 1280 if(pp_incl_state.state == 2 && !pp_incl_state.seen_junk && pp_incl_state.ppp) 1281 { 1282 pp_entry_t *ppp = pplookup(pp_incl_state.ppp); 1283 if(ppp) 1284 { 1285 iep = pp_xmalloc(sizeof(includelogicentry_t)); 1286 if (iep) 1287 { 1288 iep->ppp = ppp; 1289 ppp->iep = iep; 1290 iep->filename = bufferstack[bufferstackidx].include_filename; 1291 iep->prev = NULL; 1292 iep->next = pp_includelogiclist; 1293 if(iep->next) 1294 iep->next->prev = iep; 1295 pp_includelogiclist = iep; 1296 } 1297 } 1298 } 1299 free(pp_incl_state.ppp); 1300 pp_incl_state = bufferstack[bufferstackidx].incl; 1301 1302 } 1303 if (bufferstack[bufferstackidx].include_filename) 1304 { 1305 free(pp_status.input); 1306 pp_status.input = bufferstack[bufferstackidx].filename; 1307 } 1308 pp_status.line_number = bufferstack[bufferstackidx].line_number; 1309 pp_status.char_number = bufferstack[bufferstackidx].char_number; 1310 ncontinuations = bufferstack[bufferstackidx].ncontinuations; 1311 if (!iep) 1312 free(bufferstack[bufferstackidx].include_filename); 1313 } 1314 1315 pp_status.file = bufferstack[bufferstackidx].filehandle; 1316 ppy__switch_to_buffer(bufferstack[bufferstackidx].bufferstate); 1317 1318 if(bufferstack[bufferstackidx].should_pop) 1319 { 1320 if(yy_current_state() == pp_macexp) 1321 macro_add_expansion(); 1322 else 1323 pp_internal_error(__FILE__, __LINE__, "Pop buffer and state without macro expansion state"); 1324 yy_pop_state(); 1325 } 1326 1327 return &bufferstack[bufferstackidx]; 1328 } 1329 1330 1331 /* 1332 *------------------------------------------------------------------------- 1333 * Macro nestng support 1334 *------------------------------------------------------------------------- 1335 */ 1336 static void push_macro(pp_entry_t *ppp) 1337 { 1338 if(macexpstackidx >= MAXMACEXPSTACK) 1339 { 1340 ppy_error("Too many nested macros"); 1341 return; 1342 } 1343 1344 macexpstack[macexpstackidx] = pp_xmalloc(sizeof(macexpstack[0][0])); 1345 if(!macexpstack[macexpstackidx]) 1346 return; 1347 memset( macexpstack[macexpstackidx], 0, sizeof(macexpstack[0][0])); 1348 macexpstack[macexpstackidx]->ppp = ppp; 1349 macexpstackidx++; 1350 } 1351 1352 static macexpstackentry_t *top_macro(void) 1353 { 1354 return macexpstackidx > 0 ? macexpstack[macexpstackidx-1] : NULL; 1355 } 1356 1357 static macexpstackentry_t *pop_macro(void) 1358 { 1359 if(macexpstackidx <= 0) 1360 pp_internal_error(__FILE__, __LINE__, "Macro expansion stack underflow\n"); 1361 return macexpstack[--macexpstackidx]; 1362 } 1363 1364 static void free_macro(macexpstackentry_t *mep) 1365 { 1366 int i; 1367 1368 for(i = 0; i < mep->nargs; i++) 1369 free(mep->args[i]); 1370 free(mep->args); 1371 free(mep->nnls); 1372 free(mep->curarg); 1373 free(mep); 1374 } 1375 1376 static void add_text_to_macro(const char *text, int len) 1377 { 1378 macexpstackentry_t *mep = top_macro(); 1379 1380 assert(mep->ppp->expanding == 0); 1381 1382 if(mep->curargalloc - mep->curargsize <= len+1) /* +1 for '\0' */ 1383 { 1384 char *new_curarg; 1385 int new_alloc = mep->curargalloc + ((ALLOCBLOCKSIZE > len+1) ? ALLOCBLOCKSIZE : len+1); 1386 new_curarg = pp_xrealloc(mep->curarg, new_alloc * sizeof(mep->curarg[0])); 1387 if(!new_curarg) 1388 return; 1389 mep->curarg = new_curarg; 1390 mep->curargalloc = new_alloc; 1391 } 1392 memcpy(mep->curarg + mep->curargsize, text, len); 1393 mep->curargsize += len; 1394 mep->curarg[mep->curargsize] = '\0'; 1395 } 1396 1397 static void macro_add_arg(int last) 1398 { 1399 int nnl = 0; 1400 char *cptr; 1401 char **new_args, **new_ppargs; 1402 int *new_nnls; 1403 macexpstackentry_t *mep = top_macro(); 1404 1405 assert(mep->ppp->expanding == 0); 1406 1407 new_args = pp_xrealloc(mep->args, (mep->nargs+1) * sizeof(mep->args[0])); 1408 if(!new_args) 1409 return; 1410 mep->args = new_args; 1411 1412 new_ppargs = pp_xrealloc(mep->ppargs, (mep->nargs+1) * sizeof(mep->ppargs[0])); 1413 if(!new_ppargs) 1414 return; 1415 mep->ppargs = new_ppargs; 1416 1417 new_nnls = pp_xrealloc(mep->nnls, (mep->nargs+1) * sizeof(mep->nnls[0])); 1418 if(!new_nnls) 1419 return; 1420 mep->nnls = new_nnls; 1421 1422 mep->args[mep->nargs] = pp_xstrdup(mep->curarg ? mep->curarg : ""); 1423 if(!mep->args[mep->nargs]) 1424 return; 1425 cptr = mep->args[mep->nargs]-1; 1426 while((cptr = strchr(cptr+1, '\n'))) 1427 { 1428 nnl++; 1429 } 1430 mep->nnls[mep->nargs] = nnl; 1431 mep->nargs++; 1432 free(mep->curarg); 1433 mep->curargalloc = mep->curargsize = 0; 1434 mep->curarg = NULL; 1435 1436 /* Each macro argument must be expanded to cope with stingize */ 1437 if(last || mep->args[mep->nargs-1][0]) 1438 { 1439 yy_push_state(pp_macexp); 1440 push_buffer(NULL, NULL, NULL, last ? 2 : 1); 1441 yy_scan_string(mep->args[mep->nargs-1]); 1442 /*mep->bufferstackidx = bufferstackidx; But not nested! */ 1443 } 1444 } 1445 1446 static void macro_add_expansion(void) 1447 { 1448 macexpstackentry_t *mep = top_macro(); 1449 1450 assert(mep->ppp->expanding == 0); 1451 1452 mep->ppargs[mep->nargs-1] = pp_xstrdup(mep->curarg ? mep->curarg : ""); 1453 free(mep->curarg); 1454 mep->curargalloc = mep->curargsize = 0; 1455 mep->curarg = NULL; 1456 } 1457 1458 1459 /* 1460 *------------------------------------------------------------------------- 1461 * Output management 1462 *------------------------------------------------------------------------- 1463 */ 1464 static void put_buffer(const char *s, int len) 1465 { 1466 if(top_macro()) 1467 add_text_to_macro(s, len); 1468 else 1469 wpp_write(s, len); 1470 } 1471 1472 1473 /* 1474 *------------------------------------------------------------------------- 1475 * Include management 1476 *------------------------------------------------------------------------- 1477 */ 1478 void pp_do_include(char *fname, int type) 1479 { 1480 char *newpath; 1481 int n; 1482 includelogicentry_t *iep; 1483 void *fp; 1484 1485 if(!fname) 1486 return; 1487 1488 for(iep = pp_includelogiclist; iep; iep = iep->next) 1489 { 1490 if(!strcmp(iep->filename, fname)) 1491 { 1492 /* 1493 * We are done. The file was included before. 1494 * If the define was deleted, then this entry would have 1495 * been deleted too. 1496 */ 1497 free(fname); 1498 return; 1499 } 1500 } 1501 1502 n = strlen(fname); 1503 1504 if(n <= 2) 1505 { 1506 ppy_error("Empty include filename"); 1507 free(fname); 1508 return; 1509 } 1510 1511 /* Undo the effect of the quotation */ 1512 fname[n-1] = '\0'; 1513 1514 if((fp = pp_open_include(fname+1, type, pp_status.input, &newpath)) == NULL) 1515 { 1516 ppy_error("Unable to open include file %s", fname+1); 1517 free(fname); 1518 return; 1519 } 1520 1521 fname[n-1] = *fname; /* Redo the quotes */ 1522 push_buffer(NULL, newpath, fname, 0); 1523 pp_incl_state.seen_junk = 0; 1524 pp_incl_state.state = 0; 1525 pp_incl_state.ppp = NULL; 1526 1527 pp_status.file = fp; 1528 ppy__switch_to_buffer(ppy__create_buffer(NULL, YY_BUF_SIZE)); 1529 1530 pp_writestring("# 1 \"%s\" 1%s\n", newpath, type ? "" : " 3"); 1531 } 1532 1533 /* 1534 *------------------------------------------------------------------------- 1535 * Push/pop preprocessor ignore state when processing conditionals 1536 * which are false. 1537 *------------------------------------------------------------------------- 1538 */ 1539 void pp_push_ignore_state(void) 1540 { 1541 yy_push_state(pp_ignore); 1542 } 1543 1544 void pp_pop_ignore_state(void) 1545 { 1546 yy_pop_state(); 1547 } 1548