Changeset 5522 for trunk/tools/wrc/parser.l
- Timestamp:
- Apr 16, 2001, 7:11:03 PM (24 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/tools/wrc/parser.l
r3426 r5522 1 1 /* -*-C-*- 2 2 * 3 * Copyright 1994 Martin von Loewis 4 * Copyright 1998 Bertho A. Stultiens (BS) 3 * Copyright 1998-2000 Bertho A. Stultiens (BS) 5 4 * 5 * 21-May-2000 BS - Fixed the ident requirement of resource names 6 * which can be keywords. 7 * 30-Apr-2000 BS - Reintegration into the wine-tree 8 * 11-Jan-2000 BS - Very drastic cleanup because we don't have a 9 * preprocessor in here anymore. 10 * 02-Jan-2000 BS - Removed the preprocessor code 11 * 23-Dec-1999 BS - Removed the copyright for Martin von Loewis. 12 * There is really nothing left of his code in 13 * this parser. 6 14 * 20-Jun-1998 BS - Changed the filename conversion. Filenames are 7 15 * case-sensitive inder *nix, but not under dos. … … 45 53 */ 46 54 47 /* Exclusive rules when looking for a filename */48 %x yywf49 %x yywf_s50 55 /* Exclusive string handling */ 51 56 %x yystr … … 56 61 /* Exclusive comment eating... */ 57 62 %x comment 58 /* Preprocessor exclusives */59 %x pp_incl60 %x pp_def61 %x pp_undef62 %x pp_if63 %x pp_ifdef64 %x pp_ifndef65 %x pp_elif66 %x pp_else67 %x pp_endif68 %x pp_error69 /* Set when accumulating #define's expansion text */70 %x pp_def_s71 /* Set when processing function type defines */72 %x pp_ignore73 /* Set when need to strip to eol */74 %x pp_ignore_eol75 /* Set when handling a false #if case */76 %x pp_false77 63 /* Set when stripping c-junk */ 78 64 %x pp_stripe … … 80 66 %x pp_stripp 81 67 %x pp_stripp_final 82 83 /*%option stack*/ 68 /* Set when scanning #line style directives */ 69 %x pp_line 70 71 %option stack 84 72 %option never-interactive 85 /*%option noyywrap */ 73 86 74 /* Some shortcut definitions */ 87 75 ws [ \f\t\r] … … 89 77 90 78 %{ 91 92 #if !defined(YY_FLEX_MAJOR_VERSION) || (1000 * YY_FLEX_MAJOR_VERSION + YY_FLEX_MINOR_VERSION < 2005)93 #error Must use flex version 2.5.1 or higher (yy_scan_* routines are required).94 #endif95 79 96 80 /*#define LEX_DEBUG*/ … … 102 86 #include <string.h> 103 87 #include <ctype.h> 88 #include <assert.h> 104 89 105 90 #include "wrc.h" … … 113 98 #define YY_USE_PROTOS 114 99 #define YY_NO_UNPUT 100 #define YY_NO_TOP_STATE 115 101 116 102 /* Always update the current character position within a line */ 117 #define YY_USER_ACTION char_number+=yyleng; 118 119 raw_data_t *new_raw_data(void); 120 121 void addcchar(char c); 122 void addwchar(short s); 123 string_t *get_buffered_cstring(void); 124 string_t *get_buffered_wstring(void); 125 string_t *make_string(char *s); 126 string_t *make_filename(char *s, int len); 127 128 int line_number = 1; /* The current line */ 129 int char_number = 1; /* The current char pos within the line */ 103 #define YY_USER_ACTION char_number+=yyleng; wanted_id = want_id; want_id = 0; 104 105 static void addcchar(char c); 106 static void addwchar(short s); 107 static string_t *get_buffered_cstring(void); 108 static string_t *get_buffered_wstring(void); 109 static string_t *make_string(char *s); 110 130 111 static char *cbuffer; /* Buffers for string collection */ 131 112 static int cbufidx; … … 134 115 static int wbufidx; 135 116 static int wbufalloc = 0; 136 static int want_nl = 0; /* Set when newline needs to go to parser */137 static int want_ident = 0; /* Set is #ifdef, #ifndef or defined is seen */138 117 static int stripslevel = 0; /* Count {} during pp_strips/pp_stripe mode */ 139 118 static int stripplevel = 0; /* Count () during pp_strips mode */ 140 static char *substtext = NULL; /* Holds the substition text while getting a define */141 119 static int cjunk_tagline; /* Where did we start stripping (helps error tracking) */ 142 120 143 #ifdef YY_USE_STACK 144 void push_to(int start) { yy_push_state(start); } 145 void pop_start(void) { yy_pop_state(start); } 146 #else 147 #define MAXSTARTSTACK 32 148 static int startstack[MAXSTARTSTACK]; 149 static int startstackidx = 0; 150 151 void push_to(int start) 152 { 153 if(yydebug) 154 printf("push_to(%d): %d -> %d\n", line_number, YY_START, start); 155 if(startstackidx >= MAXSTARTSTACK-1) 156 internal_error(__FILE__, __LINE__, "Start condition stack overflow"); 157 startstack[startstackidx++] = YY_START; 158 BEGIN(start); 159 } 160 161 void pop_start(void) 162 { 163 if(yydebug) 164 printf("pop_start(%d): %d <- %d\n", line_number, startstack[startstackidx-1], YY_START); 165 if(startstackidx <= 0) 166 internal_error(__FILE__, __LINE__, "Start condition stack underflow"); 167 --startstackidx; 168 BEGIN(startstack[startstackidx]); 169 } 170 #endif 171 172 173 struct bufferstackentry { 174 YY_BUFFER_STATE bufferstate; /* Buffer to switch back to */ 175 struct pp_entry *define; /* Points to expanding define 176 or NULL if handling includes 177 */ 178 int line_number; /* Line that we were handling */ 179 int char_number; /* The current position */ 180 char *filename; /* Filename that we were handling */ 181 }; 182 183 #define MAXBUFFERSTACK 128 184 static struct bufferstackentry bufferstack[MAXBUFFERSTACK]; 185 static int bufferstackidx = 0; 186 187 void push_buffer(YY_BUFFER_STATE buf, struct pp_entry *ppp, char *filename) 188 { 189 if(yydebug) 190 printf("push_buffer: %p %p %p\n", buf, ppp, filename); 191 if(bufferstackidx >= MAXBUFFERSTACK-1) 192 internal_error(__FILE__, __LINE__, "Buffer stack overflow"); 193 memset(&bufferstack[bufferstackidx], 0, sizeof(bufferstack[0])); 194 bufferstack[bufferstackidx].bufferstate = buf; 195 bufferstack[bufferstackidx].define = ppp; 196 if(ppp) 197 ppp->expanding = 1; 198 else if(filename) 199 { 200 /* These will track the yyerror to the correct file and line */ 201 bufferstack[bufferstackidx].line_number = line_number; 202 bufferstack[bufferstackidx].char_number = char_number; 203 line_number = 1; 204 char_number = 1; 205 bufferstack[bufferstackidx].filename = input_name; 206 input_name = filename; 207 } 208 else 209 internal_error(__FILE__, __LINE__, "Pushing buffer without knowing where to go to"); 210 bufferstackidx++; 211 } 212 213 YY_BUFFER_STATE pop_buffer(void) 214 { 215 if(bufferstackidx <= 0) 216 return (YY_BUFFER_STATE)0; 217 bufferstackidx--; 218 if(bufferstack[bufferstackidx].define) 219 bufferstack[bufferstackidx].define->expanding = 0; 220 else 221 { 222 line_number = bufferstack[bufferstackidx].line_number; 223 char_number = bufferstack[bufferstackidx].char_number; 224 input_name = bufferstack[bufferstackidx].filename; 225 fclose(yyin); 226 } 227 if(yydebug) 228 printf("pop_buffer: %p %p (%d, %d) %p\n", 229 bufferstack[bufferstackidx].bufferstate, 230 bufferstack[bufferstackidx].define, 231 bufferstack[bufferstackidx].line_number, 232 bufferstack[bufferstackidx].char_number, 233 bufferstack[bufferstackidx].filename); 234 yy_switch_to_buffer(bufferstack[bufferstackidx].bufferstate); 235 return bufferstack[bufferstackidx].bufferstate; 236 } 237 238 void do_include(char *name, int namelen) 239 { 240 char *cpy = (char *)xmalloc(namelen); 241 strcpy(cpy, name+1); /* strip leading " or < */ 242 cpy[namelen-2] = '\0'; /* strip trailing " or > */ 243 if((yyin = open_include(cpy, name[0] == '"')) == NULL) 244 yyerror("Unable to open include file %s", cpy); 245 push_buffer(YY_CURRENT_BUFFER, NULL, cpy); 246 yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); 247 } 248 121 /* 122 * This one is a bit tricky. 123 * We set 'want_id' in the parser to get the first 124 * identifier we get across in the scanner, but we 125 * also want it to be reset at nearly any token we 126 * see. Exceptions are: 127 * - newlines 128 * - comments 129 * - whitespace 130 * 131 * The scanner will automatically reset 'want_id' 132 * after *each* scanner reduction and puts is value 133 * into the var below. In this way we can see the 134 * state after the YY_RULE_SETUP (i.e. the user action; 135 * see above) and don't have to worry too much when 136 * it needs to be reset. 137 */ 138 static int wanted_id = 0; 139 static int save_wanted_id; /* To save across comment reductions */ 249 140 250 141 struct keyword { … … 253 144 int isextension; 254 145 int needcase; 255 int alwaysk eyword;146 int alwayskw; 256 147 }; 257 148 258 149 static struct keyword keywords[] = { 259 { "ACCELERATORS", ACCELERATORS, 0, 0, 0}, 260 { "ALT", ALT, 0, 0, 0}, 261 { "ASCII", ASCII, 0, 0, 0}, 262 { "AUTO3STATE", AUTO3STATE, 1, 0, 0}, 263 { "AUTOCHECKBOX", AUTOCHECKBOX, 1, 0, 0}, 264 { "AUTORADIOBUTTON", AUTORADIOBUTTON, 1, 0, 0}, 265 { "BEGIN", tBEGIN, 0, 0, 1}, 266 { "BITMAP", tBITMAP, 0, 0, 0}, 267 { "BLOCK", BLOCK, 0, 0, 1}, 268 { "BUTTON", BUTTON, 1, 0, 0}, 269 { "CAPTION", CAPTION, 0, 0, 0}, 270 { "CHARACTERISTICS", CHARACTERISTICS, 1, 0, 0}, 271 { "CHECKBOX", CHECKBOX, 0, 0, 0}, 272 { "CHECKED", CHECKED, 0, 0, 0}, 273 { "CLASS", CLASS, 0, 0, 0}, 274 { "COMBOBOX", COMBOBOX, 0, 0, 0}, 275 { "CONTROL", CONTROL, 0, 0, 0}, 276 { "CTEXT", CTEXT, 0, 0, 0}, 277 { "CURSOR", CURSOR, 0, 0, 0}, 278 { "defined", tDEFINED, 0, 1, 1}, 279 { "DEFPUSHBUTTON", DEFPUSHBUTTON, 0, 0, 1}, 280 { "DIALOG", DIALOG, 0, 0, 0}, 281 { "DIALOGEX", DIALOGEX, 1, 0, 0}, 282 { "DISCARDABLE", DISCARDABLE, 0, 0, 0}, 283 { "DLGINIT", DLGINIT, 0, 0, 0}, 284 { "EDITTEXT", EDITTEXT, 0, 0, 0}, 285 { "END", tEND, 0, 0, 1}, 286 { "EXSTYLE", EXSTYLE, 0, 0, 0}, 287 { "extern", tEXTERN, 0, 1, 1}, 288 { "FILEFLAGS", FILEFLAGS, 0, 0, 0}, 289 { "FILEFLAGSMASK", FILEFLAGSMASK, 0, 0, 0}, 290 { "FILEOS", FILEOS, 0, 0, 0}, 291 { "FILESUBTYPE", FILESUBTYPE, 0, 0, 0}, 292 { "FILETYPE", FILETYPE, 0, 0, 0}, 293 { "FILEVERSION", FILEVERSION, 0, 0, 0}, 294 { "FIXED", tFIXED, 0, 0, 0}, 295 { "FONT", FONT, 0, 0, 0}, 296 { "GRAYED", GRAYED, 0, 0, 0}, 297 { "GROUPBOX", GROUPBOX, 0, 0, 0}, 298 { "HELP", HELP, 0, 0, 0}, 299 { "ICON", ICON, 0, 0, 0}, 300 { "IMPURE", IMPURE, 0, 0, 0}, 301 { "INACTIVE", INACTIVE, 0, 0, 0}, 302 { "LANGUAGE", LANGUAGE, 1, 0, 1}, 303 { "LISTBOX", LISTBOX, 0, 0, 0}, 304 { "LOADONCALL", LOADONCALL, 0, 0, 0}, 305 { "LTEXT", LTEXT, 0, 0, 0}, 306 { "MENU", MENU, 0, 0, 0}, 307 { "MENUBARBREAK", MENUBARBREAK, 0, 0, 0}, 308 { "MENUBREAK", MENUBREAK, 0, 0, 0}, 309 { "MENUEX", MENUEX, 1, 0, 0}, 310 { "MENUITEM", MENUITEM, 0, 0, 0}, 311 { "MESSAGETABLE", MESSAGETABLE, 1, 0, 0}, 312 { "MOVEABLE", MOVEABLE, 0, 0, 0}, 313 { "NOINVERT", NOINVERT, 0, 0, 0}, 314 { "NOT", NOT, 0, 0, 0}, 315 { "POPUP", POPUP, 0, 0, 0}, 316 { "PRELOAD", PRELOAD, 0, 0, 0}, 317 { "PRODUCTVERSION", PRODUCTVERSION, 0, 0, 0}, 318 { "PURE", tPURE, 0, 0, 0}, 319 { "PUSHBUTTON", PUSHBUTTON, 0, 0, 0}, 320 { "RADIOBUTTON", RADIOBUTTON, 0, 0, 0}, 321 { "RCDATA", RCDATA, 0, 0, 0}, 322 { "RTEXT", RTEXT, 0, 0, 0}, 323 { "SCROLLBAR", SCROLLBAR, 0, 0, 0}, 324 { "SEPARATOR", SEPARATOR, 0, 0, 0}, 325 { "SHIFT", SHIFT, 0, 0, 0}, 326 { "STATE3", STATE3, 1, 0, 0}, 327 { "STRING", tSTRING, 0, 0, 0}, 328 { "STRINGTABLE", STRINGTABLE, 0, 0, 1}, 329 { "STYLE", STYLE, 0, 0, 0}, 330 { "TOOLBAR", TOOLBAR, 1, 0, 0}, 331 { "typedef", tTYPEDEF, 0, 1, 1}, 332 { "VALUE", VALUE, 0, 0, 0}, 333 { "VERSION", VERSION, 1, 0, 0}, 334 { "VERSIONINFO", VERSIONINFO, 0, 0, 0}, 335 { "VIRTKEY", VIRTKEY, 0, 0, 0} 150 { "ACCELERATORS", tACCELERATORS, 0, 0, 0}, 151 { "ALT", tALT, 0, 0, 0}, 152 { "ASCII", tASCII, 0, 0, 0}, 153 { "AUTO3STATE", tAUTO3STATE, 1, 0, 0}, 154 { "AUTOCHECKBOX", tAUTOCHECKBOX, 1, 0, 0}, 155 { "AUTORADIOBUTTON", tAUTORADIOBUTTON, 1, 0, 0}, 156 { "BEGIN", tBEGIN, 0, 0, 0}, 157 { "BITMAP", tBITMAP, 0, 0, 0}, 158 { "BLOCK", tBLOCK, 0, 0, 0}, 159 { "BUTTON", tBUTTON, 1, 0, 0}, 160 { "CAPTION", tCAPTION, 0, 0, 0}, 161 { "CHARACTERISTICS", tCHARACTERISTICS, 1, 0, 0}, 162 { "CHECKBOX", tCHECKBOX, 0, 0, 0}, 163 { "CHECKED", tCHECKED, 0, 0, 0}, 164 { "CLASS", tCLASS, 0, 0, 0}, 165 { "COMBOBOX", tCOMBOBOX, 0, 0, 0}, 166 { "CONTROL", tCONTROL, 0, 0, 0}, 167 { "CTEXT", tCTEXT, 0, 0, 0}, 168 { "CURSOR", tCURSOR, 0, 0, 0}, 169 { "DEFPUSHBUTTON", tDEFPUSHBUTTON, 0, 0, 0}, 170 { "DIALOG", tDIALOG, 0, 0, 0}, 171 { "DIALOGEX", tDIALOGEX, 1, 0, 0}, 172 { "DISCARDABLE", tDISCARDABLE, 0, 0, 0}, 173 { "DLGINIT", tDLGINIT, 0, 0, 0}, 174 { "EDITTEXT", tEDITTEXT, 0, 0, 0}, 175 { "END", tEND, 0, 0, 0}, 176 { "enum", tENUM, 0, 1, 1}, 177 { "EXSTYLE", tEXSTYLE, 0, 0, 0}, 178 { "extern", tEXTERN, 0, 1, 1}, 179 { "FILEFLAGS", tFILEFLAGS, 0, 0, 0}, 180 { "FILEFLAGSMASK", tFILEFLAGSMASK, 0, 0, 0}, 181 { "FILEOS", tFILEOS, 0, 0, 0}, 182 { "FILESUBTYPE", tFILESUBTYPE, 0, 0, 0}, 183 { "FILETYPE", tFILETYPE, 0, 0, 0}, 184 { "FILEVERSION", tFILEVERSION, 0, 0, 0}, 185 { "FIXED", tFIXED, 0, 0, 0}, 186 { "FONT", tFONT, 0, 0, 0}, 187 { "FONTDIR", tFONTDIR, 0, 0, 0}, /* This is a Borland BRC extension */ 188 { "GRAYED", tGRAYED, 0, 0, 0}, 189 { "GROUPBOX", tGROUPBOX, 0, 0, 0}, 190 { "HELP", tHELP, 0, 0, 0}, 191 { "ICON", tICON, 0, 0, 0}, 192 { "IMPURE", tIMPURE, 0, 0, 0}, 193 { "INACTIVE", tINACTIVE, 0, 0, 0}, 194 { "inline", tINLINE, 0, 1, 1}, 195 { "LANGUAGE", tLANGUAGE, 1, 0, 1}, 196 { "LISTBOX", tLISTBOX, 0, 0, 0}, 197 { "LOADONCALL", tLOADONCALL, 0, 0, 0}, 198 { "LTEXT", tLTEXT, 0, 0, 0}, 199 { "MENU", tMENU, 0, 0, 0}, 200 { "MENUBARBREAK", tMENUBARBREAK, 0, 0, 0}, 201 { "MENUBREAK", tMENUBREAK, 0, 0, 0}, 202 { "MENUEX", tMENUEX, 1, 0, 0}, 203 { "MENUITEM", tMENUITEM, 0, 0, 0}, 204 { "MESSAGETABLE", tMESSAGETABLE, 1, 0, 0}, 205 { "MOVEABLE", tMOVEABLE, 0, 0, 0}, 206 { "NOINVERT", tNOINVERT, 0, 0, 0}, 207 { "NOT", tNOT, 0, 0, 0}, 208 { "POPUP", tPOPUP, 0, 0, 0}, 209 { "PRELOAD", tPRELOAD, 0, 0, 0}, 210 { "PRODUCTVERSION", tPRODUCTVERSION, 0, 0, 0}, 211 { "PURE", tPURE, 0, 0, 0}, 212 { "PUSHBUTTON", tPUSHBUTTON, 0, 0, 0}, 213 { "RADIOBUTTON", tRADIOBUTTON, 0, 0, 0}, 214 { "RCDATA", tRCDATA, 0, 0, 0}, 215 { "RTEXT", tRTEXT, 0, 0, 0}, 216 { "SCROLLBAR", tSCROLLBAR, 0, 0, 0}, 217 { "SEPARATOR", tSEPARATOR, 0, 0, 0}, 218 { "SHIFT", tSHIFT, 0, 0, 0}, 219 { "STATE3", tSTATE3, 1, 0, 0}, 220 { "static", tSTATIC, 0, 1, 1}, 221 { "STRING", tSTRING, 0, 0, 0}, 222 { "STRINGTABLE", tSTRINGTABLE, 0, 0, 1}, 223 { "struct", tSTRUCT, 0, 1, 1}, 224 { "STYLE", tSTYLE, 0, 0, 0}, 225 { "TOOLBAR", tTOOLBAR, 1, 0, 0}, 226 { "typedef", tTYPEDEF, 0, 1, 1}, 227 { "VALUE", tVALUE, 0, 0, 0}, 228 { "VERSION", tVERSION, 1, 0, 0}, 229 { "VERSIONINFO", tVERSIONINFO, 0, 0, 0}, 230 { "VIRTKEY", tVIRTKEY, 0, 0, 0} 336 231 }; 337 232 338 233 #define NKEYWORDS (sizeof(keywords)/sizeof(keywords[0])) 339 234 #define KWP(p) ((struct keyword *)(p)) 340 int kw_cmp_func(const void *s1, const void *s2)235 static int kw_cmp_func(const void *s1, const void *s2) 341 236 { 342 237 int ret; … … 350 245 #define KW_BSEARCH 351 246 #define DO_SORT 352 st ruct keyword *iskeyword(char *kw)247 static struct keyword *iskeyword(char *kw) 353 248 { 354 249 struct keyword *kwp; … … 384 279 #endif 385 280 386 #ifdef LEX_DEBUG387 if(kwp && !strcmp(kwp->keyword, "LANGUAGE"))388 printf("Got Language\n");389 #endif390 281 if(kwp == NULL || (kwp->isextension && !extensions)) 391 282 return NULL; … … 394 285 } 395 286 396 void add_to_substtext(char *text, int len) 397 { 398 if(!substtext) 399 { 400 substtext = xstrdup(text); 287 %} 288 289 /* 290 ************************************************************************** 291 * The flexer starts here 292 ************************************************************************** 293 */ 294 %% 295 /* 296 * Catch the GCC-style line statements here and parse them. 297 * This has the advantage that you can #include at any 298 * stage in the resource file. 299 * The preprocessor generates line directives in the format: 300 * # <linenum> "filename" <codes> 301 * 302 * Codes can be a sequence of: 303 * - 1 start of new file 304 * - 2 returning to previous 305 * - 3 system header 306 * - 4 interpret as C-code 307 * 308 * 4 is not used and 1 mutually excludes 2 309 * Anyhow, we are not really interested in these at all 310 * because we only want to know the linenumber and 311 * filename. 312 */ 313 <INITIAL,pp_strips,pp_stripp>^{ws}*\#{ws}* yy_push_state(pp_line); 314 <pp_line>[^\n]* { 315 int lineno; 316 char *cptr; 317 char *fname; 318 yy_pop_state(); 319 lineno = (int)strtol(yytext, &cptr, 10); 320 if(!lineno) 321 yyerror("Malformed '#...' line-directive; invalid linenumber"); 322 fname = strchr(cptr, '"'); 323 if(!fname) 324 yyerror("Malformed '#...' line-directive; missing filename"); 325 fname++; 326 cptr = strchr(fname, '"'); 327 if(!cptr) 328 yyerror("Malformed '#...' line-directive; missing terminating \""); 329 *cptr = '\0'; 330 line_number = lineno - 1; /* We didn't read the newline */ 331 input_name = xstrdup(fname); 401 332 } 402 else 403 { 404 substtext = (char *)xrealloc(substtext, strlen(substtext)+len+1); 405 strcat(substtext, text); 406 } 407 } 408 409 %} 410 411 %% 412 /* #include handling */ 413 ^{ws}*#{ws}*include{ws}* push_to(pp_incl); 414 <pp_incl>\<[^\n\>]+\> do_include(yytext, yyleng); pop_start(); 415 <pp_incl>\"[^\n\>]+\" do_include(yytext, yyleng); pop_start(); 416 <pp_incl>. yyerror("Malformed #include"); 417 418 /* #define handling */ 419 ^{ws}*#{ws}*define{ws}* push_to(pp_def); 420 <pp_def>{cident} { 421 set_define(yytext); 422 push_to(pp_def_s); 423 } 424 <pp_def>{cident}\( push_to(pp_ignore); /* Ignore function-like defines for now*/ 425 <pp_def>. yyerror("Malformed #define"); 426 427 <pp_ignore,pp_def_s>[^\/\\\n]* { 428 if(YY_START == pp_def_s) 429 add_to_substtext(yytext, yyleng); 430 } 431 <pp_ignore,pp_def_s>\/[^\/\*][^\/\\\n]* { /* Comment is handled in normal handling */ 432 if(YY_START == pp_def_s) 433 add_to_substtext(yytext, yyleng); 434 } 435 <pp_ignore,pp_def_s>\\{ws}*\n line_number++; char_number = 1; /* Line continuation */ 436 <pp_ignore,pp_def_s>\n { 437 if(YY_START == pp_def_s) 438 { 439 add_define(substtext ? substtext : ""); 440 free(substtext); 441 substtext = NULL; 442 } 443 line_number++; 444 char_number = 1; 445 pop_start(); 446 pop_start(); 447 } 448 449 /* #undef handling */ 450 ^{ws}*#{ws}*undef{ws}* push_to(pp_undef); 451 <pp_undef>{cident} { 452 del_define(yytext); 453 pop_start(); 454 /*push_to(pp_ignore);*/ 455 } 456 457 /* Conditional handling */ 458 <INITIAL,pp_strips,pp_stripe,pp_stripp,pp_false>^{ws}*#{ws}*if{ws}* { 459 if(YY_START == pp_false) 460 { 461 if(yydebug) 462 printf("(%d)#if ignored\n", line_number); 463 push_if(0, 0, 1); 464 push_to(pp_ignore_eol); 465 } 466 else 467 { 468 push_to(INITIAL); 469 want_nl = 1; 470 return tIF; 471 } 472 } 473 <INITIAL,pp_strips,pp_stripe,pp_stripp,pp_false>^{ws}*#{ws}*ifdef{ws}* { 474 if(YY_START == pp_false) 475 { 476 if(yydebug) 477 printf("(%d)#ifdef ignored\n", line_number); 478 push_if(0, 0, 1); 479 push_to(pp_ignore_eol); 480 } 481 else 482 { 483 push_to(INITIAL); 484 want_nl = 1; 485 want_ident = 1; 486 return tIFDEF; 487 } 488 } 489 <INITIAL,pp_strips,pp_stripe,pp_stripp,pp_false>^{ws}*#{ws}*ifndef{ws}* { 490 if(YY_START == pp_false) 491 { 492 if(yydebug) 493 printf("(%d)#ifndef ignored\n", line_number); 494 push_if(0, 0, 1); 495 push_to(pp_ignore_eol); 496 } 497 else 498 { 499 push_to(INITIAL); 500 want_nl = 1; 501 want_ident = 1; 502 return tIFNDEF; 503 } 504 } 505 <INITIAL,pp_strips,pp_stripe,pp_stripp,pp_false>^{ws}*#{ws}*elif{ws}* { 506 if(!isnevertrue_if()) 507 { 508 push_to(INITIAL); 509 want_nl = 1; 510 return tELIF; 511 } 512 else if(YY_START == pp_false) 513 push_to(pp_ignore_eol); 514 if(yydebug) 515 printf("(%d)#elif ignored\n", line_number); 516 } 517 <INITIAL,pp_strips,pp_stripe,pp_stripp,pp_false>^{ws}*#{ws}*else{ws}* { 518 if(!isnevertrue_if()) 519 { 520 push_to(INITIAL); 521 want_nl = 1; 522 return tELSE; 523 } 524 if(yydebug) 525 printf("(%d)#else ignored\n", line_number); 526 } 527 <INITIAL,pp_strips,pp_stripe,pp_stripp,pp_false>^{ws}*#{ws}*endif{ws}* { 528 if(!isnevertrue_if()) 529 { 530 want_nl = 1; 531 return tENDIF; 532 } 533 else 534 { 535 if(yydebug) 536 printf("(%d)#endif ignored\n", line_number); 537 pop_if(); 538 } 539 } 540 541 /* The error directive */ 542 <INITIAL,pp_strips,pp_stripe,pp_stripp>^{ws}*#{ws}*error{ws}* push_to(pp_error); 543 <pp_error>[^\n]* yyerror("Error directive: %s", yytext); 544 <pp_false>^{ws}*#{ws}*error[^\n]* { 545 if(yydebug) 546 printf("(%d)#error ignored\n", line_number); 547 } 548 549 /* preprocessor junk */ 550 <INITIAL,pp_strips,pp_stripe,pp_stripp,pp_false>^{ws}*#{ws}*pragma[^\n]* ; /* Ignore #pragma */ 551 <INITIAL,pp_strips,pp_stripe,pp_stripp,pp_false>^{ws}*#{ws}*ident[^\n]* ; /* Ignore #ident */ 552 <INITIAL,pp_strips,pp_stripe,pp_stripp,pp_false>^{ws}*#{ws}*line[^\n]* ; /* Ignore #line */ 553 /* We'll get an error on malformed #xxx statements 554 * by not recognising '#' at all. This helps tracking 555 * preprocessor errors. 556 */ 557 /*^{ws}*#{ws}* ; Ignore # */ 558 559 <pp_strips>\{ stripslevel++; 560 <pp_strips>\} stripslevel--; 561 <pp_strips>; if(!stripslevel) pop_start(); 333 334 /* 335 * Strip everything until a ';' taking 336 * into account braces {} for structures, 337 * classes and enums. 338 */ 339 <pp_strips>\{ stripslevel++; 340 <pp_strips>\} stripslevel--; 341 <pp_strips>; if(!stripslevel) yy_pop_state(); 562 342 <pp_strips>\/[^*\n] ; /* To catch comments */ 563 343 <pp_strips>[^\{\};\n#/]* ; /* Ignore rest */ 564 565 <pp_stripe>\{ stripslevel++; 566 <pp_stripe>\} { 567 stripslevel--; 568 if(!stripslevel) pop_start(); 569 } 570 <pp_stripe>; if(!stripslevel) pop_start(); 571 <pp_stripe>\/[^*\n] ; /* To catch comments */ 572 <pp_stripe>[^\{\};\n#/]* ; /* Ignore rest */ 573 574 <pp_stripp>\( stripplevel++; 575 <pp_stripp>\) { 576 stripplevel--; 577 if(!stripplevel) 578 { 579 pop_start(); 580 push_to(pp_stripp_final); 344 <pp_strips>\n line_number++; char_number = 1; 345 346 <pp_stripp>\( stripplevel++; 347 <pp_stripp>\) { 348 stripplevel--; 349 if(!stripplevel) 350 { 351 yy_pop_state(); 352 yy_push_state(pp_stripp_final); 353 } 581 354 } 582 }583 355 <pp_stripp>\/[^*\n] ; /* To catch comments */ 584 356 <pp_stripp>[^\(\);\n#/]* ; /* Ignore rest */ 585 586 <pp_stripp_final>{ws}* ; /* Ignore */ 587 <pp_stripp_final>; pop_start(); /* Kill the semicolon */ 588 <pp_stripp_final>\n line_number++; char_number = 1; pop_start(); 589 <pp_stripp_final>. yyless(0); pop_start(); 590 591 <pp_false>. ; /* Ignore everything except #xxx during false #if state */ 592 593 <pp_ignore_eol>[^\n]* pop_start(); 594 595 /* These are special cases due to filename scanning */ 596 <yywf>[Dd][Ii][Ss][Cc][Aa][Rr][Dd][Aa][Bb][Ll][Ee] return DISCARDABLE; 597 <yywf>[Ff][Ii][Xx][Ee][Dd] return tFIXED; 598 <yywf>[Ii][Mm][Pp][Uu][Rr][Ee] return IMPURE; 599 <yywf>[Mm][Oo][Vv][Ee][Aa][Bb][Ll][Ee] return MOVEABLE; 600 <yywf>[Ll][Oo][Aa][Dd][Oo][Nn][Cc][Aa][Ll][Ll] return LOADONCALL; 601 <yywf>[Pp][Rr][Ee][Ll][Oo][Aa][Dd] return PRELOAD; 602 <yywf>[Pp][Uu][Rr][Ee] return tPURE; 357 <pp_stripp>\n line_number++; char_number = 1; 358 359 <pp_stripp_final>{ws}* ; /* Ignore */ 360 <pp_stripp_final>; yy_pop_state(); /* Kill the semicolon */ 361 <pp_stripp_final>\n line_number++; char_number = 1; yy_pop_state(); 362 <pp_stripp_final>. yyless(0); yy_pop_state(); 603 363 604 364 \{ return tBEGIN; 605 365 \} return tEND; 606 366 607 [0-9]+[lL]? { yylval.num = strtoul(yytext, 0, 10); return toupper(yytext[yyleng-1]) == 'L' ? LNUMBER : NUMBER; } 608 0[xX][0-9A-Fa-f]+[lL]? { yylval.num = strtoul(yytext, 0, 16); return toupper(yytext[yyleng-1]) == 'L' ? LNUMBER : NUMBER; } 609 0[oO][0-7]+[lL]? { yylval.num = strtoul(yytext+2, 0, 8); return toupper(yytext[yyleng-1]) == 'L' ? LNUMBER : NUMBER; } 367 [0-9]+[lL]? { yylval.num = strtoul(yytext, 0, 10); return toupper(yytext[yyleng-1]) == 'L' ? tLNUMBER : tNUMBER; } 368 0[xX][0-9A-Fa-f]+[lL]? { yylval.num = strtoul(yytext, 0, 16); return toupper(yytext[yyleng-1]) == 'L' ? tLNUMBER : tNUMBER; } 369 0[oO][0-7]+[lL]? { yylval.num = strtoul(yytext+2, 0, 8); return toupper(yytext[yyleng-1]) == 'L' ? tLNUMBER : tNUMBER; } 370 371 /* 372 * The next two rules scan identifiers and filenames. 373 * This is achieved by using the priority ruling 374 * of the scanner where a '.' is valid in a filename 375 * and *only* in a filename. In this case, the second 376 * rule will be reduced because it is longer. 377 */ 610 378 [A-Za-z_0-9]+ { 611 struct keyword *token; 612 struct pp_entry *ppp; 613 614 want_rscname = 0; 615 616 if(want_ident) 379 struct keyword *tok = iskeyword(yytext); 380 381 if(tok) 617 382 { 618 /* Prevent preprocessor subst */ 619 want_ident = 0; 620 yylval.str = make_string(yytext); 621 #ifdef LEX_DEBUG 622 printf("want IDENT (%s, %d, %d): <%s>\n", input_name, line_number, char_number, yytext); 623 #endif 624 return IDENT; 625 } 626 else if((ppp = pp_lookup(yytext)) != NULL) 627 { 628 /* Do preprocessor substitution, 629 * but expand only if macro is not 630 * already expanding. 631 */ 632 if(!ppp->expanding) 383 if(tok->token == tCLASS && !strcmp(yytext, "class")) 384 return tCPPCLASS; 385 else if(wanted_id && !tok->alwayskw) 633 386 { 634 #ifdef LEX_DEBUG 635 printf("expand IDENT (%s, %d, %d): <%s>\n", input_name, line_number, char_number, yytext); 636 #endif 637 push_buffer(YY_CURRENT_BUFFER, ppp, NULL); 638 yy_scan_string(ppp->subst); 387 yylval.str = make_string(yytext); 388 return tIDENT; 639 389 } 640 } 641 else if((token = iskeyword(yytext)) != NULL 642 && !(!token->alwayskeyword && want_rscname)) 643 { 644 switch(token->token) 645 { 646 case tDEFINED: 647 want_ident = 1; 648 break; 649 /*case RCDATA:*/ 650 case CURSOR: 651 case tBITMAP: 652 case MESSAGETABLE: 653 case DLGINIT: 654 push_to(yywf); 655 break; 656 case FONT: 657 case ICON: 658 if(!indialog) 659 push_to(yywf); 660 break; 661 case DIALOG: 662 case DIALOGEX: 663 indialog = 1; 664 break; 665 } 666 return token->token; 390 else 391 return tok->token; 667 392 } 668 393 else 669 394 { 670 395 yylval.str = make_string(yytext); 671 #ifdef LEX_DEBUG 672 printf("%s IDENT (%s, %d, %d): <%s>\n", 673 want_rscname ? "rscname" : "just", 674 input_name, 675 line_number, 676 char_number, 677 yytext); 678 #endif 679 return IDENT; 396 return tIDENT; 680 397 } 681 398 } 682 \|\| return LOGOR; 683 \&\& return LOGAND; 684 \=\= return EQ; 685 \!\= return NE; 686 \<\= return LTE; 687 \>\= return GTE; 688 689 <yywf>[^ \f\t\r\n\"]* { pop_start(); yylval.str = make_filename(yytext, yyleng); return FILENAME; } 690 <yywf>\" push_to(yywf_s); 691 <yywf_s>[^\"\n]*\" { pop_start(); pop_start(); yylval.str = make_filename(yytext, yyleng-1); return FILENAME; } 692 <yywf_s>\n yyerror("Newline in filename"); 693 399 [A-Za-z_0-9./\\]+ yylval.str = make_string(yytext); return tFILENAME; 400 401 /* 402 * Wide string scanning 403 */ 694 404 L\" { 695 push_to(yylstr);405 yy_push_state(yylstr); 696 406 wbufidx = 0; 697 407 if(!win32) 698 408 yywarning("16bit resource contains unicode strings\n"); 699 409 } 410 <yylstr>\"{ws}+ | 700 411 <yylstr>\" { 701 pop_start();412 yy_pop_state(); 702 413 yylval.str = get_buffered_wstring(); 703 414 return tSTRING; 704 415 } 705 <yylstr>\n yyerror("Unterminated string");706 416 <yylstr>\\[0-7]{1,6} { /* octal escape sequence */ 707 417 int result; … … 716 426 addwchar((short)result); 717 427 } 428 <yylstr>\\x[0-9a-fA-F]{1,3} { yyerror("Invalid hex escape sequence '%s'", yytext); } 429 718 430 <yylstr>\\[0-9]+ yyerror("Bad escape secuence"); 719 431 <yylstr>\\a addwchar('\a'); … … 724 436 <yylstr>\\t addwchar('\t'); 725 437 <yylstr>\\v addwchar('\v'); 726 <yylstr>\\(.|\n) addwchar(yytext[1]); 438 <yylstr>\\(\n|.) addwchar(yytext[1]); 439 <yylstr>\\\r\n addwchar(yytext[2]); 727 440 <yylstr>\"\" addcchar('\"'); /* "bla""bla" -> "bla\"bla" */ 728 441 <yylstr>\\\"\" addcchar('\"'); /* "bla\""bla" -> "bla\"bla" */ … … 733 446 addwchar(*yptr++ & 0xff); 734 447 } 735 736 \" { 737 push_to(yystr); 738 cbufidx = 0; 739 } 448 <yylstr>\n yyerror("Unterminated string"); 449 450 /* 451 * Normal string scanning 452 */ 453 \" yy_push_state(yystr); cbufidx = 0; 454 <yystr>\"{ws}+ | 740 455 <yystr>\" { 741 pop_start();456 yy_pop_state(); 742 457 yylval.str = get_buffered_cstring(); 743 458 return tSTRING; 744 459 } 745 <yystr>\n yyerror("Unterminated string");746 460 <yystr>\\[0-7]{1,3} { /* octal escape sequence */ 747 461 int result; … … 756 470 addcchar((char)result); 757 471 } 472 <yystr>\\x[0-9a-fA-F] { yyerror("Invalid hex escape sequence '%s'", yytext); } 473 758 474 <yystr>\\[0-9]+ yyerror("Bad escape secuence"); 759 475 <yystr>\\a addcchar('\a'); … … 764 480 <yystr>\\t addcchar('\t'); 765 481 <yystr>\\v addcchar('\v'); 766 <yystr>\\(.|\n) addcchar(yytext[1]); 482 <yystr>\\(\n|.) addcchar(yytext[1]); 483 <yystr>\\\r\n addcchar(yytext[2]); 767 484 <yystr>[^\\\n\"]+ { 768 485 char *yptr = yytext; … … 773 490 <yystr>\\\"\" addcchar('\"'); /* "bla\""bla" -> "bla\"bla" */ 774 491 <yystr>\"{ws}+\" ; /* "bla" "bla" -> "blabla" */ 775 <yystr>. yywarning("Matched %c", *yytext); 776 777 778 \' { 779 push_to(yyrcd); 780 cbufidx = 0; 781 } 492 <yystr>\n yyerror("Unterminated string"); 493 494 /* 495 * Raw data scanning 496 */ 497 \' yy_push_state(yyrcd); cbufidx = 0; 782 498 <yyrcd>\' { 783 pop_start();499 yy_pop_state(); 784 500 yylval.raw = new_raw_data(); 785 501 yylval.raw->size = cbufidx; 786 502 yylval.raw->data = xmalloc(yylval.raw->size); 787 503 memcpy(yylval.raw->data, cbuffer, yylval.raw->size); 788 return RAWDATA;504 return tRAWDATA; 789 505 } 790 506 <yyrcd>[0-9a-fA-F]{2} { … … 797 513 <yyrcd>. yyerror("Malformed data-line"); 798 514 799 <INITIAL,pp_ignore,pp_def_s,pp_strips,pp_stripe,pp_stripp>"/*" push_to(comment); /* Eat comment */ 515 /* 516 * Comment stripping 517 * Should never occur after preprocessing 518 */ 519 <INITIAL,pp_stripp,pp_strips>"/*" { 520 yy_push_state(comment); 521 save_wanted_id = wanted_id; 522 if(!no_preprocess) 523 yywarning("Found comments after preprocessing, please report"); 524 } 800 525 <comment>[^*\n]* ; 801 526 <comment>"*"+[^*/\n]* ; 802 527 <comment>\n line_number++; char_number = 1; 803 <comment>"*"+"/" pop_start(); 804 805 ;[^\n]* ; /* Eat comment */ 806 <INITIAL,pp_ignore,pp_def_s>"//"[^\n]* ; /* Eat comment */ 807 808 <INITIAL,yywf,pp_false,pp_strips,pp_stripe,pp_stripp>\n { 809 if(YY_START == yywf) 810 pop_start(); 528 <comment>"*"+"/" yy_pop_state(); want_id = save_wanted_id; 529 530 ;[^\n]* want_id = wanted_id; /* not really comment, but left-over c-junk */ 531 "//"[^\n]* want_id = wanted_id; if(!no_preprocess) yywarning("Found comments after preprocessing, please report"); 532 533 \n { 534 want_id = wanted_id; 811 535 line_number++; 812 536 char_number = 1; … … 817 541 } 818 542 } 819 <INITIAL,yywf>{ws}+; /* Eat whitespace */543 {ws}+ want_id = wanted_id; /* Eat whitespace */ 820 544 821 545 <INITIAL>. return yytext[0]; 546 822 547 <<EOF>> { 823 YY_BUFFER_STATE b = YY_CURRENT_BUFFER; 824 if(!pop_buffer()) 825 { 826 if(YY_START == pp_strips || YY_START == pp_stripe || YY_START == pp_stripp || YY_START == pp_stripp_final) 827 yyerror("Unexpected end of file during c-junk scanning (started at %d)", cjunk_tagline); 828 else 829 yyterminate(); 830 } 831 yy_delete_buffer(b); 548 if(YY_START == pp_strips || YY_START == pp_stripe || YY_START == pp_stripp || YY_START == pp_stripp_final) 549 yyerror("Unexpected end of file during c-junk scanning (started at %d)", cjunk_tagline); 550 else 551 yyterminate(); 832 552 } 833 553 … … 840 560 } 841 561 yywarning("Unmatched text '%c' (0x%02x) YY_START=%d stripslevel=%d", 842 isprint(*yytext ) ? *yytext : '.', *yytext, YY_START,stripslevel);562 isprint(*yytext & 0xff) ? *yytext : '.', *yytext, YY_START,stripslevel); 843 563 } 844 564 … … 861 581 * the resource string. 862 582 */ 863 void addcchar(char c)583 static void addcchar(char c) 864 584 { 865 585 if(cbufidx >= cbufalloc) … … 873 593 } 874 594 875 void addwchar(short s)595 static void addwchar(short s) 876 596 { 877 597 if(wbufidx >= wbufalloc) … … 894 614 } 895 615 896 st ring_t *get_buffered_cstring(void)616 static string_t *get_buffered_cstring(void) 897 617 { 898 618 string_t *str = new_string(); … … 902 622 memcpy(str->str.cstr, cbuffer, cbufidx); 903 623 str->str.cstr[cbufidx] = '\0'; 904 /* printf("got cstring \"%s\"\n", str->str.cstr); */905 624 return str; 906 625 } 907 626 908 st ring_t *get_buffered_wstring(void)627 static string_t *get_buffered_wstring(void) 909 628 { 910 629 string_t *str = new_string(); … … 917 636 } 918 637 919 st ring_t *make_string(char *s)638 static string_t *make_string(char *s) 920 639 { 921 640 string_t *str = new_string(); … … 927 646 } 928 647 929 string_t *make_filename(char *s, int len)930 {931 char *cptr;932 string_t *str = new_string();933 934 str->size = len;935 str->type = str_char;936 str->str.cstr = (char *)xmalloc(str->size+1);937 memcpy(str->str.cstr, s, str->size);938 str->str.cstr[str->size] = '\0';939 940 /* Remove escaped backslash and convert to forward */941 cptr = str->str.cstr;942 for(cptr = str->str.cstr; (cptr = strchr(cptr, '\\')) != NULL; cptr++)943 {944 if(cptr[1] == '\\')945 {946 memmove(cptr, cptr+1, strlen(cptr));947 str->size--;948 }949 *cptr = '/';950 }951 952 /* Convert to lower case. Seems to be reasonable to do */953 for(cptr = str->str.cstr; !leave_case && *cptr; cptr++)954 {955 *cptr = tolower(*cptr);956 }957 return str;958 }959 960 /* Called from the parser to signal filename request */961 void set_yywf(void)962 {963 push_to(yywf);964 }965 966 /* Called from the parser to signal preprocessor if case */967 void set_pp_ignore(int state)968 {969 if(state)970 push_to(pp_false);971 else972 pop_start();973 }974 975 648 /* Called from the parser to kill c-junk */ 976 649 void strip_extern(void) 977 650 { 978 651 cjunk_tagline = line_number; 979 push_to(pp_stripe);652 yy_push_state(pp_stripe); 980 653 } 981 654 … … 983 656 { 984 657 cjunk_tagline = line_number; 985 push_to(pp_strips);658 yy_push_state(pp_strips); 986 659 } 987 660 … … 990 663 cjunk_tagline = line_number; 991 664 stripplevel = 1; /* One scanned already */ 992 push_to(pp_stripp);993 } 994 665 yy_push_state(pp_stripp); 666 } 667
Note:
See TracChangeset
for help on using the changeset viewer.