1 %{ 2 /*=========================================================================== 3 Copyright (c) 1998-2000, The Santa Cruz Operation 4 All rights reserved. 5 6 Redistribution and use in source and binary forms, with or without 7 modification, are permitted provided that the following conditions are met: 8 9 *Redistributions of source code must retain the above copyright notice, 10 this list of conditions and the following disclaimer. 11 12 *Redistributions in binary form must reproduce the above copyright notice, 13 this list of conditions and the following disclaimer in the documentation 14 and/or other materials provided with the distribution. 15 16 *Neither name of The Santa Cruz Operation nor the names of its contributors 17 may be used to endorse or promote products derived from this software 18 without specific prior written permission. 19 20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS 21 IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 22 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 24 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 INTERRUPTION) 28 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 31 DAMAGE. 32 =========================================================================*/ 33 34 /* cscope - interactive C symbol cross-reference 35 * 36 * C symbol scanner 37 */ 38 #include "global.h" 39 #include "alloc.h" 40 #include "scanner.h" 41 #include "lookup.h" 42 43 #include <assert.h> 44 45 /* the line counting has been moved from character reading for speed */ 46 /* comments are discarded */ 47 48 #ifndef FLEX_SCANNER 49 # error Sorry, this scanner needs flex. It is not usable with AT&T Lex. 50 #endif 51 52 #define IFLEVELINC 5 /* #if nesting level size increment */ 53 #define YY_NO_TOP_STATE 1 54 55 int first; /* buffer index for first char of symbol */ 56 int last; /* buffer index for last char of symbol */ 57 int lineno; /* symbol line number */ 58 int myylineno = 1; 59 60 /* HBB 20001007: new variables, emulating yytext in a way that allows 61 * the yymore() simulation, my_yymore(), to be used even in the presence of 62 * yyless(). */ 63 size_t my_yyleng = 0; 64 char *my_yytext = NULL; 65 66 static BOOL arraydimension; /* inside array dimension declaration */ 67 static BOOL bplisting; /* breakpoint listing */ 68 static int braces; /* unmatched left brace count */ 69 static BOOL classdef; /* c++ class definition */ 70 static BOOL elseelif; /* #else or #elif found */ 71 static BOOL esudef; /* enum/struct/union global definition */ 72 static BOOL external; /* external definition */ 73 static int externalbraces; /* external definition outer brace count */ 74 static BOOL fcndef; /* function definition */ 75 static BOOL global; /* file global scope (outside functions) */ 76 static size_t iflevel; /* #if nesting level */ 77 static BOOL initializer; /* data initializer */ 78 static int initializerbraces; /* data initializer outer brace count */ 79 static BOOL lex; /* lex file */ 80 static size_t miflevel = IFLEVELINC; /* maximum #if nesting level */ 81 static int *maxifbraces; /* maximum brace count within #if */ 82 static int *preifbraces; /* brace count before #if */ 83 static int parens; /* unmatched left parenthesis count */ 84 static BOOL ppdefine; /* preprocessor define statement */ 85 static BOOL pseudoelif; /* pseudo-#elif */ 86 static BOOL oldtype; /* next identifier is an old type */ 87 static BOOL rules; /* lex/yacc rules */ 88 static BOOL sdl; /* sdl file */ 89 static BOOL structfield; /* structure field declaration */ 90 static int tagdef; /* class/enum/struct/union tag definition */ 91 static BOOL template; /* function template */ 92 static int templateparens; /* function template outer parentheses count */ 93 static int typedefbraces = -1; /* initial typedef brace count */ 94 static int token; /* token found */ 95 static int ident_start; /* begin of preceding identifier */ 96 97 static void my_yymore(void); 98 99 %} 100 identifier [a-zA-Z_$][a-zA-Z_0-9$]* 101 number \.?[0-9][.0-9a-fA-FlLuUxX]* 102 comment "/*"([^*]*("*"+[^/])?)*"*/"|"//"[^\n]*\n 103 ws [ \t\r\v\f] 104 wsnl [ \t\r\v\f\n]|{comment} 105 106 /* flex options: stack of start conditions, and don't use yywrap() */ 107 %option stack 108 %option noyywrap 109 110 %start SDL 111 %a 4000 112 %o 7000 113 114 /* exclusive start conditions. not available in AT&T lex -> use flex! */ 115 %x IN_PREPROC WAS_ENDIF WAS_IDENTIFIER WAS_ESU IN_DQUOTE IN_SQUOTE COMMENT 116 117 %% 118 119 %\{ { /* lex/yacc C declarations/definitions */ 120 global = YES; 121 goto more; 122 /* NOTREACHED */ 123 } 124 %\} { 125 global = NO; 126 goto more; 127 /* NOTREACHED */ 128 } 129 ^%% { /* lex/yacc rules delimiter */ 130 braces = 0; 131 if (rules == NO) { 132 /* this %% starts the section containing the rules */ 133 rules = YES; 134 135 /* Copy yytext to private buffer, to be able to add further 136 * content following it: */ 137 my_yymore(); 138 139 /* simulate a yylex() or yyparse() definition */ 140 (void) strcat(my_yytext, " /* "); 141 first = strlen(my_yytext); 142 if (lex == YES) { 143 (void) strcat(my_yytext, "yylex"); 144 } else { 145 /* yacc: yyparse implicitly calls yylex */ 146 char *s = " yylex()"; 147 char *cp = s + strlen(s); 148 while (--cp >= s) { 149 unput(*cp); 150 } 151 (void) strcat(my_yytext, "yyparse"); 152 } 153 last = strlen(my_yytext); 154 (void) strcat(my_yytext, " */"); 155 my_yyleng = strlen(my_yytext); 156 return(FCNDEF); 157 } else { 158 /* were in the rules section, now comes the closing one */ 159 rules = NO; 160 global = YES; 161 last = first; 162 my_yymore(); 163 return(FCNEND); 164 /* NOTREACHED */ 165 } 166 } 167 168 <SDL>STATE[ \t]+({identifier}|\*) { /* sdl state, treat as function def */ 169 braces = 1; 170 fcndef = YES; 171 token = FCNDEF; 172 goto findident; 173 /* NOTREACHED */ 174 } 175 <SDL>ENDSTATE[ \t] { /* end of an sdl state, treat as end of a function */ 176 goto endstate; 177 /* NOTREACHED */ 178 } 179 180 \{ { /* count unmatched left braces for fcn def detection */ 181 ++braces; 182 183 /* mark an untagged enum/struct/union so its beginning 184 can be found */ 185 if (tagdef) { 186 if (braces == 1) { 187 esudef = YES; 188 } 189 token = tagdef; 190 tagdef = '\0'; 191 last = first; 192 my_yymore(); 193 return(token); 194 } 195 goto more; 196 /* NOTREACHED */ 197 } 198 199 \#{ws}* { /* start a preprocessor line */ 200 if (rules == NO) /* don't consider CPP for lex/yacc rules */ 201 BEGIN(IN_PREPROC); 202 yyleng = 1; /* get rid of the blanks, if any */ 203 goto more; 204 /* NOTREACHED */ 205 } 206 <IN_PREPROC>endif([^a-zA-Z0-9_$\n].*)? { /* #endif */ 207 /* delay treatment of #endif depending on whether an 208 * #if comes right after it, or not */ 209 /* HBB 20010619: new pattern allows trailing garbage 210 * after the #endif */ 211 BEGIN(WAS_ENDIF); 212 goto more; 213 /* NOTREACHED */ 214 } 215 <WAS_ENDIF>\n{wsnl}*#{ws}*if(ndef|def)?{ws}+ { 216 /* attempt to correct erroneous brace count caused by: 217 * 218 * #if ... 219 * ... { 220 * #endif 221 * #if ... 222 * ... { 223 * #endif 224 */ 225 /* the current #if must not have an #else or #elif */ 226 if (elseelif == YES) { 227 goto endif; 228 /* NOTREACHED */ 229 } 230 pseudoelif = YES; 231 BEGIN(INITIAL); 232 yyless(1); /* rescan all but the line ending */ 233 yy_set_bol(1); 234 goto eol; 235 /* NOTREACHED */ 236 } 237 <WAS_ENDIF>\n{wsnl}* { /* an #endif with no #if right after it */ 238 endif: 239 if (iflevel > 0) { 240 /* get the maximum brace count for this #if */ 241 if (braces < maxifbraces[--iflevel]) { 242 braces = maxifbraces[iflevel]; 243 } 244 } 245 BEGIN(INITIAL); 246 yyless(1); 247 yy_set_bol(1); 248 goto eol; 249 /* NOTREACHED */ 250 } 251 252 <IN_PREPROC>ifndef{ws}+ | 253 <IN_PREPROC>ifdef{ws}+ | 254 <IN_PREPROC>if{ws}+ { /* #if directive */ 255 elseelif = NO; 256 if (pseudoelif == YES) { 257 pseudoelif = NO; 258 goto elif; 259 /* NOTREACHED */ 260 } 261 /* make sure there is room for the current brace count */ 262 if (iflevel == miflevel) { 263 miflevel += IFLEVELINC; 264 maxifbraces = myrealloc(maxifbraces, miflevel * sizeof(*maxifbraces)); 265 preifbraces = myrealloc(preifbraces, miflevel * sizeof(*preifbraces)); 266 } 267 /* push the current brace count */ 268 preifbraces[iflevel] = braces; 269 maxifbraces[iflevel++] = 0; 270 BEGIN(INITIAL); 271 goto more; 272 /* NOTREACHED */ 273 } 274 <IN_PREPROC>else({ws}.*)? { /* #else --- eat up whole line */ 275 elseelif = YES; 276 if (iflevel > 0) { 277 278 /* save the maximum brace count for this #if */ 279 if (braces > maxifbraces[iflevel - 1]) { 280 maxifbraces[iflevel - 1] = braces; 281 } 282 /* restore the brace count to before the #if */ 283 braces = preifbraces[iflevel - 1]; 284 } 285 BEGIN(INITIAL); 286 goto more; 287 /* NOTREACHED */ 288 } 289 <IN_PREPROC>elif{ws}+ { /* #elif */ 290 /* elseelif = YES; --- HBB I doubt this is correct */ 291 elif: 292 if (iflevel > 0) { 293 294 /* save the maximum brace count for this #if */ 295 if (braces > maxifbraces[iflevel - 1]) { 296 maxifbraces[iflevel - 1] = braces; 297 } 298 /* restore the brace count to before the #if */ 299 braces = preifbraces[iflevel - 1]; 300 } 301 BEGIN(INITIAL); 302 goto more; 303 /* NOTREACHED */ 304 } 305 306 <IN_PREPROC>include{ws}*\"[^"\n]+\" | 307 <IN_PREPROC>include{ws}*<[^>\n]+> { /* #include file */ 308 char *s; 309 char remember = yytext[yyleng-1]; 310 311 my_yymore(); 312 s = strpbrk(my_yytext, "\"<"); 313 if (!s) 314 return(LEXERR); 315 my_yytext[my_yyleng-1] = '\0'; 316 incfile(s + 1, s); 317 my_yytext[my_yyleng-1] = remember; 318 first = s - my_yytext; 319 last = my_yyleng - 1; 320 if (compress == YES) { 321 my_yytext[0] = '\2'; /* compress the keyword */ 322 } 323 BEGIN(INITIAL); 324 return(INCLUDE); 325 /* NOTREACHED */ 326 } 327 328 \} { 329 /* could be the last enum member initializer */ 330 if (braces == initializerbraces) { 331 initializerbraces = -1; 332 initializer = NO; 333 } 334 if (--braces <= 0) { 335 endstate: 336 braces = 0; 337 classdef = NO; 338 } 339 if (braces == 0 || (braces == 1 && classdef == YES)) { 340 341 /* if the end of an enum/struct/union definition */ 342 if (esudef == YES) { 343 esudef = NO; 344 } 345 /* if the end of the function */ 346 else if (fcndef == YES) { 347 fcndef = NO; 348 last = first; 349 my_yymore(); 350 return(FCNEND); 351 } 352 } 353 goto more; 354 /* NOTREACHED */ 355 } 356 357 \( { /* count unmatched left parentheses for function templates */ 358 ++parens; 359 goto more; 360 /* NOTREACHED */ 361 } 362 \) { 363 if (--parens <= 0) { 364 parens = 0; 365 } 366 /* if the end of a function template */ 367 if (parens == templateparens) { 368 templateparens = -1; 369 template = NO; 370 } 371 goto more; 372 /* NOTREACHED */ 373 } 374 = { /* if a global definition initializer */ 375 if (!my_yytext) 376 return(LEXERR); 377 if (global == YES && ppdefine == NO && my_yytext[0] != '#') { 378 initializerbraces = braces; 379 initializer = YES; 380 } 381 goto more; 382 /* NOTREACHED */ 383 } 384 : { /* a if global structure field */ 385 if (!my_yytext) 386 return(LEXERR); 387 if (global == YES && ppdefine == NO && my_yytext[0] != '#') { 388 structfield = YES; 389 } 390 goto more; 391 /* NOTREACHED */ 392 } 393 \, { 394 if (braces == initializerbraces) { 395 initializerbraces = -1; 396 initializer = NO; 397 } 398 structfield = NO; 399 goto more; 400 /* NOTREACHED */ 401 } 402 ; { /* if the enum/struct/union was not a definition */ 403 if (braces == 0) { 404 esudef = NO; 405 } 406 /* if the end of a typedef */ 407 if (braces == typedefbraces) { 408 typedefbraces = -1; 409 } 410 /* if the end of a external definition */ 411 if (braces == externalbraces) { 412 externalbraces = -1; 413 external = NO; 414 } 415 structfield = NO; 416 initializer = NO; 417 goto more; 418 /* NOTREACHED */ 419 } 420 <IN_PREPROC>define{ws}+{identifier} { 421 422 /* preprocessor macro or constant definition */ 423 ppdefine = YES; 424 token = DEFINE; 425 if (compress == YES) { 426 my_yytext[0] = '\1'; /* compress the keyword */ 427 } 428 findident: 429 /* search backwards through yytext[] to find the identifier */ 430 /* NOTE: this had better be left to flex, by use of 431 * yet another starting condition */ 432 my_yymore(); 433 first = my_yyleng - 1; 434 while (my_yytext[first] != ' ' && my_yytext[first] != '\t') { 435 --first; 436 } 437 ++first; 438 last = my_yyleng; 439 BEGIN(INITIAL); 440 goto definition; 441 /* NOTREACHED */ 442 } 443 <IN_PREPROC>\n { /* unknown preprocessor line */ 444 BEGIN(INITIAL); 445 ++myylineno; 446 goto more; 447 /* NOTREACHED */ 448 } 449 <IN_PREPROC>. | 450 <IN_PREPROC>{identifier} { /* unknown preprocessor line */ 451 BEGIN(INITIAL); 452 goto more; 453 /* NOTREACHED */ 454 } 455 456 class{wsnl}+{identifier}({wsnl}|{identifier}|[():])*\{ { /* class definition */ 457 classdef = YES; 458 tagdef = 'c'; 459 yyless(5); /* eat up 'class', and re-scan */ 460 yy_set_bol(0); 461 goto more; 462 /* NOTREACHED */ 463 } 464 465 ("enum"|"struct"|"union") { 466 ident_start = first; 467 BEGIN(WAS_ESU); 468 goto more; 469 } 470 <WAS_ESU>{ 471 ({wsnl}+{identifier}){wsnl}*\{ { /* e/s/u definition */ 472 tagdef = my_yytext[ident_start]; 473 BEGIN(WAS_IDENTIFIER); 474 goto ident; 475 } 476 {wsnl}*\{ { /* e/s/u definition without a tag */ 477 tagdef = my_yytext[ident_start]; 478 BEGIN(INITIAL); 479 if (braces == 0) { 480 esudef = YES; 481 } 482 last = first; 483 yyless(0); /* re-scan all this as normal text */ 484 tagdef = '\0'; 485 goto more; 486 } 487 ({wsnl}+{identifier})?{wsnl}* | 488 .|\n { /* e/s/u usage */ 489 BEGIN(WAS_IDENTIFIER); 490 goto ident; 491 } 492 } 493 494 if{wsnl}*\( { /* ignore 'if' */ 495 yyless(2); 496 yy_set_bol(0); 497 goto more; 498 } 499 500 {identifier} { /* identifier found: do nothing, yet. (!) */ 501 BEGIN(WAS_IDENTIFIER); 502 ident_start = first; 503 goto more; 504 /* NOTREACHED */ 505 } 506 507 <WAS_IDENTIFIER>{ 508 {ws}*\(({wsnl}|{identifier}|{number}|[*&[\]=,.:])*\)([()]|{wsnl})*[:a-zA-Z_#{] { 509 /* a function definition */ 510 /* note: "#define a (b) {" and "#if defined(a)\n#" 511 * are not fcn definitions! */ 512 /* warning: "if (...)" must not overflow yytext, 513 * so the content of function argument definitions 514 * is restricted, in particular parentheses are 515 * not allowed */ 516 /* FIXME HBB 20001003: the above 'not allowed' may well be the 517 * reason for the parsing bug concerning function pointer usage, 518 * I suspect. --- I think my new special-case rule for 'if' 519 * could be helpful in removing that limitation */ 520 if ((braces == 0 && ppdefine == NO && my_yytext[0] != '#' && rules == NO) || 521 (braces == 1 && classdef == YES)) { 522 fcndef = YES; 523 token = FCNDEF; 524 goto fcn; 525 /* NOTREACHED */ 526 } 527 goto fcncal; 528 /* NOTREACHED */ 529 } 530 {ws}*\(([*&[\]=,.]|{identifier}|{number}|{wsnl})* { /* function call */ 531 fcncal: if (fcndef == YES || ppdefine == YES || rules == YES) { 532 token = FCNCALL; 533 goto fcn; 534 /* NOTREACHED */ 535 } 536 if (template == NO) { 537 templateparens = parens; 538 template = YES; 539 } 540 goto ident; 541 /* NOTREACHED */ 542 } 543 ("*"|{wsnl})+{identifier} { /* typedef name or modifier use */ 544 goto ident; 545 /* NOTREACHED */ 546 } 547 .|\n { /* general identifer usage */ 548 char *s; 549 550 if (global == YES && ppdefine == NO && my_yytext[0] != '#' && 551 external == NO && initializer == NO && 552 arraydimension == NO && structfield == NO && 553 template == NO && fcndef == NO) { 554 if (esudef == YES) { 555 /* if enum/struct/union */ 556 token = MEMBERDEF; 557 } else { 558 token = GLOBALDEF; 559 } 560 } else { 561 ident: 562 token = IDENT; 563 } 564 fcn: 565 if (YYSTATE == WAS_IDENTIFIER) { 566 /* Position back to the actual identifier: */ 567 last = first; 568 first = ident_start; 569 yyless(0); 570 /* HBB 20001008: if the anti-backup-pattern above matched, 571 * and the matched context ended with a \n, then the scanner 572 * believes it's at the start of a new line. But the yyless() 573 * should feeds that \n back into the input, so that's 574 * wrong. --> force 'beginning-of-line' status off. */ 575 yy_set_bol(0); 576 BEGIN(INITIAL); 577 } else { 578 my_yymore(); 579 last = my_yyleng; 580 } 581 definition: 582 583 /* if a long line */ 584 if (yyleng > STMTMAX) { 585 int c; 586 587 /* skip to the end of the line */ 588 warning("line too long"); 589 while ((c = input()) > LEXEOF) { 590 if (c == '\n') { 591 unput(c); 592 break; 593 } 594 } 595 } 596 /* truncate a long symbol */ 597 if (yyleng > PATLEN) { 598 warning("symbol too long"); 599 my_yyleng = first + PATLEN; 600 my_yytext[my_yyleng] = '\0'; 601 } 602 603 /* if found word was a keyword: */ 604 if ((s = lookup(my_yytext + first)) != NULL) { 605 first = my_yyleng; 606 607 /* if the start of a typedef */ 608 if (s == typedeftext) { 609 typedefbraces = braces; 610 oldtype = YES; 611 } 612 /* if an enum/struct/union */ 613 /* (needed for "typedef struct tag name;" so 614 tag isn't marked as the typedef name) */ 615 else if (s == enumtext || s == structtext || s == uniontext) { 616 /* do nothing */ 617 } else if (s == externtext) { 618 /* if an external definition */ 619 externalbraces = braces; 620 external = YES; 621 } else if (templateparens == parens && template == YES) { 622 /* keyword doesn't start a function 623 * template */ 624 templateparens = -1; 625 template = NO; 626 } else { 627 /* identifier after typedef was a 628 * keyword */ 629 oldtype = NO; 630 } 631 } else { 632 /* not a keyword --> found an identifier */ 633 /* last = yyleng; */ 634 635 /* if a class/enum/struct/union tag definition */ 636 /* FIXME HBB 20001001: why reject "class"? */ 637 if (tagdef && strnotequal(my_yytext + first, "class")) { 638 token = tagdef; 639 tagdef = '\0'; 640 if (braces == 0) { 641 esudef = YES; 642 } 643 } else if (braces == typedefbraces && oldtype == NO && 644 arraydimension == NO) { 645 /* if a typedef name */ 646 token = TYPEDEF; 647 } else { 648 oldtype = NO; 649 } 650 /* my_yymore(); */ 651 return(token); 652 /* NOTREACHED */ 653 } 654 } 655 } 656 657 \[ { /* array dimension (don't worry or about subscripts) */ 658 arraydimension = YES; 659 goto more; 660 /* NOTREACHED */ 661 } 662 \] { 663 arraydimension = NO; 664 goto more; 665 /* NOTREACHED */ 666 } 667 \\\n { /* preprocessor statement is continued on next line */ 668 /* save the '\\' to the output file, but not the '\n': */ 669 yyleng = 1; 670 my_yymore(); 671 goto eol; 672 /* NOTREACHED */ 673 } 674 \n { /* end of the line */ 675 if (ppdefine == YES) { /* end of a #define */ 676 ppdefine = NO; 677 yyless(yyleng - 1); 678 last = first; 679 my_yymore(); 680 return(DEFINEEND); 681 } 682 /* skip the first 8 columns of a breakpoint listing line */ 683 /* and skip the file path in the page header */ 684 if (bplisting == YES) { 685 int c, i; 686 687 /* FIXME HBB 20001007: should call input() instead */ 688 switch (input()) { /* tab and EOF just fall through */ 689 case ' ': /* breakpoint number line */ 690 case '[': 691 for (i = 1; i < 8 && input() > LEXEOF; ++i) 692 ; 693 break; 694 case '.': /* header line */ 695 case '/': 696 /* skip to the end of the line */ 697 while ((c = input()) > LEXEOF) { 698 if (c == '\n') { 699 unput(c); 700 break; 701 } 702 } 703 break; 704 case '\n': /* empty line */ 705 unput('\n'); 706 break; 707 } 708 } 709 eol: 710 ++myylineno; 711 first = 0; 712 last = 0; 713 if (symbols > 0) { 714 /* no my_yymore(): \n doesn't need to be in my_yytext */ 715 return(NEWLINE); 716 } 717 /* line ended --> flush my_yytext */ 718 if (my_yytext) 719 *my_yytext = '\0'; 720 my_yyleng = 0; 721 lineno = myylineno; 722 } 723 724 \' { /* character constant */ 725 if (sdl == NO) 726 BEGIN(IN_SQUOTE); 727 goto more; 728 /* NOTREACHED */ 729 } 730 <IN_SQUOTE>\' { 731 BEGIN(INITIAL); 732 goto more; 733 /* NOTREACHED */ 734 } 735 \" { /* string constant */ 736 BEGIN(IN_DQUOTE); 737 goto more; 738 /* NOTREACHED */ 739 } 740 <IN_DQUOTE>\" { 741 BEGIN(INITIAL); 742 goto more; 743 /* NOTREACHED */ 744 } 745 <IN_DQUOTE,IN_SQUOTE>{ 746 \n { /* syntax error: unexpected EOL */ 747 BEGIN(INITIAL); 748 goto eol; 749 /* NOTREACHED */ 750 } 751 \\. | 752 . { 753 goto more; 754 /* NOTREACHED */ 755 } 756 \\\n { /* line continuation inside a string! */ 757 myylineno++; 758 goto more; 759 /* NOTREACHED */ 760 } 761 } 762 763 ^{ws}+ { /* don't save leading white space */ 764 } 765 766 {ws}+\n { /* eat whitespace at end of line */ 767 unput('\n'); 768 } 769 770 [\t\r\v\f]+ { /* eat non-blank whitespace sequences, replace 771 * by single blank */ 772 unput(' '); 773 } 774 775 {ws}{2,} { /* compress sequential whitespace here, not in putcrossref() */ 776 unput(' '); 777 } 778 779 "/*" yy_push_state(COMMENT); 780 <COMMENT>{ 781 [^*\n]* | 782 "*"+[^*/\n]* ; /* do nothing */ 783 [^*\n]*\n | 784 "*"+[^*/\n]*\n { 785 if (ppdefine == NO) { 786 goto eol; 787 } else { 788 ++myylineno; 789 } 790 /* NOTREACHED */ 791 } 792 "*"+"/" { 793 /* replace the comment by a single blank */ 794 unput(' '); 795 yy_pop_state(); 796 } 797 } 798 799 "//".*\n? { 800 /* C++-style one-line comment */ 801 goto eol; 802 /* NOTREACHED */ 803 } 804 805 {number} | /* number */ 806 <SDL>STATE[ \t]+ | /* ... and other syntax error catchers... */ 807 . { /* punctuation and operators */ 808 more: 809 my_yymore(); 810 first = my_yyleng; 811 } 812 813 %% 814 815 void 816 initscanner(char *srcfile) 817 { 818 char *s; 819 820 if (maxifbraces == NULL) { 821 maxifbraces = mymalloc(miflevel * sizeof(*maxifbraces)); 822 preifbraces = mymalloc(miflevel * sizeof(*preifbraces)); 823 } 824 first = 0; /* buffer index for first char of symbol */ 825 last = 0; /* buffer index for last char of symbol */ 826 lineno = 1; /* symbol line number */ 827 myylineno = 1; /* input line number */ 828 arraydimension = NO; /* inside array dimension declaration */ 829 bplisting = NO; /* breakpoint listing */ 830 braces = 0; /* unmatched left brace count */ 831 classdef = NO; /* c++ class definition */ 832 elseelif = NO; /* #else or #elif found */ 833 esudef = NO; /* enum/struct/union global definition */ 834 external = NO; /* external definition */ 835 externalbraces = -1; /* external definition outer brace count */ 836 fcndef = NO; /* function definition */ 837 global = YES; /* file global scope (outside functions) */ 838 iflevel = 0; /* #if nesting level */ 839 initializer = NO; /* data initializer */ 840 initializerbraces = -1; /* data initializer outer brace count */ 841 lex = NO; /* lex file */ 842 parens = 0; /* unmatched left parenthesis count */ 843 ppdefine = NO; /* preprocessor define statement */ 844 pseudoelif = NO; /* pseudo-#elif */ 845 oldtype = NO; /* next identifier is an old type */ 846 rules = NO; /* lex/yacc rules */ 847 sdl = NO; /* sdl file */ 848 structfield = NO; /* structure field declaration */ 849 tagdef = '\0'; /* class/enum/struct/union tag definition */ 850 template = NO; /* function template */ 851 templateparens = -1; /* function template outer parentheses count */ 852 typedefbraces = -1; /* initial typedef braces count */ 853 ident_start = 0; /* start of previously found identifier */ 854 855 if (my_yytext) 856 *my_yytext = '\0'; 857 my_yyleng = 0; 858 859 BEGIN(INITIAL); 860 861 /* if this is not a C file */ 862 if ((s = strrchr(srcfile, '.')) != NULL) { 863 switch (*++s) { /* this switch saves time on C files */ 864 case 'b': 865 if (strcmp(s, "bp") == 0) { /* breakpoint listing */ 866 bplisting = YES; 867 } 868 break; 869 case 'l': 870 if (strcmp(s, "l") == 0) { /* lex */ 871 lex = YES; 872 global = NO; 873 } 874 break; 875 case 's': 876 if (strcmp(s, "sd") == 0) { /* sdl */ 877 sdl = YES; 878 BEGIN(SDL); 879 } 880 break; 881 case 'y': 882 if (strcmp(s, "y") == 0) { /* yacc */ 883 global = NO; 884 } 885 break; 886 } 887 } 888 } 889 890 #define MY_YY_ALLOCSTEP 1000 891 static void 892 my_yymore(void) 893 { 894 static size_t yytext_size = 0; 895 896 /* my_yytext is an ever-growing buffer. It will not ever 897 * shrink, nor will it be freed at end of program, for now */ 898 while (my_yyleng + yyleng + 1 >= yytext_size) { 899 my_yytext = myrealloc(my_yytext, yytext_size += MY_YY_ALLOCSTEP); 900 } 901 902 strncpy (my_yytext + my_yyleng, yytext, yyleng+1); 903 my_yyleng += yyleng; 904 } 905