1 %{ 2 /* 3 * CDDL HEADER START 4 * 5 * The contents of this file are subject to the terms of the 6 * Common Development and Distribution License, Version 1.0 only 7 * (the "License"). You may not use this file except in compliance 8 * with the License. 9 * 10 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 11 * or http://www.opensolaris.org/os/licensing. 12 * See the License for the specific language governing permissions 13 * and limitations under the License. 14 * 15 * When distributing Covered Code, include this CDDL HEADER in each 16 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 17 * If applicable, add the following below this CDDL HEADER, with the 18 * fields enclosed by brackets "[]" replaced with your own identifying 19 * information: Portions Copyright [yyyy] [name of copyright owner] 20 * 21 * CDDL HEADER END 22 * 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1988 AT&T */ 28 /* All Rights Reserved */ 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 /* 33 * cscope - interactive C symbol cross-reference 34 * 35 * 36 * C symbol scanner 37 */ 38 #ident "@(#)scanner.l 1.2 93/06/07 SMI" 39 #include "global.h" 40 41 /* the line counting has been moved from character reading for speed */ 42 /* comments are discarded */ 43 #undef input 44 #define input() \ 45 ((yytchar = (yytchar = yysptr > yysbuf ? \ 46 *--yysptr : getc(yyin)) == '/' ? comment() : yytchar) == \ 47 EOF ? 0 : toascii(yytchar)) 48 #define noncommentinput() \ 49 ((yytchar = yysptr > yysbuf ? *--yysptr : getc(yyin)) == \ 50 EOF ? 0 : yytchar) 51 #undef unput 52 #define unput(c) (*yysptr++ = (c)) 53 54 /* not a preprocessor line (allow Ingres(TM) "## char var;" lines) */ 55 #define notpp() (ppdefine == NO && (*yytext != '#' || yytext[1] == '#')) 56 57 #define IFLEVELINC 5 /* #if nesting level size increment */ 58 59 /* keyword text for fast testing of keywords in the scanner */ 60 extern char externtext[]; 61 extern char typedeftext[]; 62 63 int first; /* buffer index for first char of symbol */ 64 int last; /* buffer index for last char of symbol */ 65 int lineno; /* symbol line number */ 66 67 static BOOL arraydimension; /* inside array dimension declaration */ 68 static BOOL bplisting; /* breakpoint listing */ 69 static int braces; /* unmatched left brace count */ 70 static int cesudeftoken; /* class/enum/struct/union definition */ 71 static BOOL classdef; /* c++ class definition */ 72 static BOOL elseelif; /* #else or #elif found */ 73 static BOOL esudef; /* enum/struct/union definition */ 74 static int esubraces; /* outermost enum/struct/union */ 75 /* brace count */ 76 static BOOL externdec; /* extern declaration */ 77 static BOOL fcndef; /* function definition */ 78 static BOOL globalscope; /* file global scope */ 79 /* (outside functions) */ 80 static int iflevel; /* #if nesting level */ 81 static BOOL initializer; /* data initializer */ 82 static int initializerbraces; /* data initializer outer brace count */ 83 static BOOL lex; /* lex file */ 84 static BOOL localdef; /* function/block local definition */ 85 static int miflevel = IFLEVELINC; /* maximum #if nesting level */ 86 static int *maxifbraces; /* maximum brace count within #if */ 87 static int *preifbraces; /* brace count before #if */ 88 static int parens; /* unmatched left parenthesis count */ 89 static BOOL ppdefine; /* preprocessor define statement */ 90 static BOOL psuedoelif; /* psuedo-#elif */ 91 static BOOL oldtype; /* next identifier is an old type */ 92 static BOOL rules; /* lex/yacc rules */ 93 static BOOL sdl; /* SDL file */ 94 static BOOL structfield; /* structure field declaration */ 95 static BOOL template; /* function template */ 96 static int templateparens; /* function template outer parentheses count */ 97 static BOOL typedefdef; /* typedef name definition */ 98 static BOOL typedefname; /* typedef name use */ 99 static int token; /* token found */ 100 101 static BOOL asy; /* assembly file */ 102 103 void multicharconstant(char terminator); 104 int do_assembly(int token); 105 %} 106 identifier [a-zA-Z_][a-zA-Z_0-9]* 107 number \.?[0-9][.0-9a-fA-FlLuUxX]* 108 %start SDL 109 %a 6000 110 %o 11000 111 %p 3000 112 %% 113 %\{ { /* lex/yacc C declarations/definitions */ 114 globalscope = YES; 115 goto more; 116 /* NOTREACHED */ 117 } 118 %\} { 119 globalscope = NO; 120 goto more; 121 /* NOTREACHED */ 122 } 123 ^%% { /* lex/yacc rules delimiter */ 124 braces = 0; 125 if (rules == NO) { 126 rules = YES; 127 128 /* simulate a yylex() or yyparse() definition */ 129 (void) strcat(yytext, " /* "); 130 first = strlen(yytext); 131 if (lex == YES) { 132 (void) strcat(yytext, "yylex"); 133 } else { 134 /* 135 * yacc: yyparse implicitly calls yylex 136 */ 137 char *s = " yylex()"; 138 char *cp = s + strlen(s); 139 while (--cp >= s) { 140 unput(*cp); 141 } 142 (void) strcat(yytext, "yyparse"); 143 } 144 last = strlen(yytext); 145 (void) strcat(yytext, " */"); 146 yyleng = strlen(yytext); 147 yymore(); 148 return (FCNDEF); 149 } else { 150 rules = NO; 151 globalscope = YES; 152 last = first; 153 yymore(); 154 return (FCNEND); 155 } 156 /* NOTREACHED */ 157 } 158 <SDL>(PROCEDURE|STATE)[ \t]+({identifier}|\*) { /* SDL procedure or state */ 159 braces = 1; 160 fcndef = YES; /* treat as function definition */ 161 token = FCNDEF; 162 globalscope = NO; 163 goto findident; 164 /* NOTREACHED */ 165 } 166 <SDL>(CALL|NEXTSTATE)[ \t]+({identifier}|\*) { /* SDL call or nextstate */ 167 token = FCNCALL; 168 goto findident; /* treat as function call */ 169 /* NOTREACHED */ 170 } 171 <SDL>END(PROCEDURE|STATE)[ \t]+({identifier}|\*) { 172 /* end of an SDL procedure or state */ 173 goto endstate; /* treat as the end of a function */ 174 /* NOTREACHED */ 175 } 176 \{ { 177 /* count unmatched left braces for fcn def detection */ 178 ++braces; 179 180 /* 181 * mark an untagged enum/struct/union so its beginning 182 * can be found 183 */ 184 if (cesudeftoken) { 185 last = first; 186 savesymbol(cesudeftoken); 187 cesudeftoken = '\0'; 188 } 189 goto more; 190 /* NOTREACHED */ 191 } 192 \#[ \t]*endif/.*[\n\r][ \t\n\r]*#[ \t]*if { 193 /* 194 * attempt to correct erroneous brace count caused by: 195 * 196 * #if ... 197 * ... { 198 * #endif 199 * #if ... 200 * ... { 201 * #endif 202 */ 203 /* the current #if must not have an #else or #elif */ 204 if (elseelif == YES) { 205 goto endif; 206 } 207 psuedoelif = YES; 208 goto more; 209 /* NOTREACHED */ 210 } 211 \#[ \t]*ifn?(def)? { /* #if, #ifdef or #ifndef */ 212 elseelif = NO; 213 if (psuedoelif == YES) { 214 psuedoelif = NO; 215 goto elif; 216 } 217 /* 218 * make sure there is room for the current brace count 219 */ 220 if (iflevel == miflevel) { 221 miflevel += IFLEVELINC; 222 maxifbraces = myrealloc(maxifbraces, 223 miflevel * sizeof (int)); 224 preifbraces = myrealloc(preifbraces, 225 miflevel * sizeof (int)); 226 } 227 /* push the current brace count */ 228 preifbraces[iflevel] = braces; 229 maxifbraces[iflevel++] = 0; 230 goto more; 231 /* NOTREACHED */ 232 } 233 \#[ \t]*el(se|if) { /* #elif or #else */ 234 elseelif = YES; 235 elif: 236 if (iflevel > 0) { 237 238 /* save the maximum brace count for this #if */ 239 if (braces > maxifbraces[iflevel]) { 240 maxifbraces[iflevel - 1] = braces; 241 } 242 /* restore the brace count to before the #if */ 243 braces = preifbraces[iflevel - 1]; 244 } 245 goto more; 246 /* NOTREACHED */ 247 } 248 \#[ \t]*endif { /* #endif */ 249 endif: 250 if (iflevel > 0) { 251 252 /* get the maximum brace count for this #if */ 253 if (braces < maxifbraces[--iflevel]) { 254 braces = maxifbraces[iflevel]; 255 } 256 } 257 goto more; 258 /* NOTREACHED */ 259 } 260 \} { 261 /* could be the last enum member initializer */ 262 if (braces == initializerbraces) { 263 initializerbraces = -1; 264 initializer = NO; 265 } 266 if (--braces <= 0) { 267 endstate: 268 braces = 0; 269 classdef = NO; 270 } 271 /* 272 * if the end of an outermost enum/struct/union 273 * definition 274 */ 275 if (esudef == YES && braces == esubraces) { 276 esudef = NO; 277 esubraces = -1; 278 last = first; 279 yymore(); 280 return (ESUEND); 281 } 282 /* if the end of a function */ 283 if ((braces == 0 || braces == 1 && classdef == YES) && 284 fcndef == YES) { 285 fcndef = NO; 286 globalscope = YES; 287 last = first; 288 yymore(); 289 return (FCNEND); 290 } 291 goto more; 292 /* NOTREACHED */ 293 } 294 \( { 295 /* 296 * count unmatched left parentheses for function 297 * templates 298 */ 299 ++parens; 300 goto more; 301 /* NOTREACHED */ 302 } 303 \) { 304 if (--parens <= 0) { 305 parens = 0; 306 } 307 /* if the end of a function template */ 308 if (parens == templateparens) { 309 templateparens = -1; 310 template = NO; 311 } 312 goto more; 313 /* NOTREACHED */ 314 } 315 = { /* if a global definition initializer */ 316 if ((globalscope == YES || localdef == YES) && 317 notpp()) { 318 initializerbraces = braces; 319 initializer = YES; 320 } 321 goto more; 322 /* NOTREACHED */ 323 } 324 : { /* if a structure field */ 325 /* note: a pr header has a colon in the date */ 326 if (esudef == YES && notpp()) { 327 structfield = YES; 328 } 329 goto more; 330 /* NOTREACHED */ 331 } 332 \, { 333 if (braces == initializerbraces) { 334 initializerbraces = -1; 335 initializer = NO; 336 } 337 structfield = NO; 338 goto more; 339 /* NOTREACHED */ 340 } 341 "##" | /* start of Ingres(TM) code line */ 342 ; { 343 /* if not in an enum/struct/union declaration */ 344 if (esudef == NO) { 345 externdec = NO; 346 typedefdef = NO; 347 localdef = NO; 348 } 349 structfield = NO; 350 initializer = NO; 351 oldtype = NO; 352 goto more; 353 /* NOTREACHED */ 354 } 355 \#[ \t]*define[ \t]+{identifier} { 356 357 /* preprocessor macro or constant definition */ 358 ppdefine = YES; 359 token = DEFINE; 360 if (compress == YES) { 361 /* compress the keyword */ 362 yytext[0] = '\7'; 363 } 364 findident: 365 first = yyleng - 1; 366 while (isalnum(yytext[first]) || yytext[first] == '_') { 367 --first; 368 } 369 ++first; 370 goto iflongline; 371 /* NOTREACHED */ 372 } 373 class[ \t]+{identifier}[ \t\n\ra-zA-Z0-9_():]*\{ { 374 /* class definition */ 375 classdef = YES; 376 cesudeftoken = 'c'; 377 REJECT; 378 /* NOTREACHED */ 379 } 380 (enum|struct|union)/([ \t\n\r]+{identifier})?[ \t\n\r]*\{ { 381 /* enum/struct/union definition */ 382 esudef = YES; 383 if (esubraces < 0) { 384 /* if outermost enum/struct/union */ 385 esubraces = braces; 386 } 387 cesudeftoken = *(yytext + first); 388 goto iflongline; 389 /* NOTREACHED */ 390 } 391 {identifier}/[ \t]*\(([ \t\n\ra-zA-Z0-9_*&[\]=,.]*|\([ \ta-zA-Z0-9_*[\],]*\))*\)[ \t\n\r()]*[:a-zA-Z_#{] { 392 393 /* 394 * warning: "if (...)" must not overflow yytext, so 395 * the content of function argument definitions is 396 * restricted, in particular parentheses are 397 * not allowed 398 */ 399 400 if (asy) { 401 /* 402 * In assembly files, if it looks like 403 * a definition, pass it down as one and we'll 404 * take care of it later. 405 */ 406 token = FCNDEF; 407 goto iflongline; 408 } 409 410 /* if a function definition */ 411 /* 412 * note: "#define a (b) {" and "#if defined(a)\n#" 413 * are not 414 */ 415 if (braces == 0 && notpp() && rules == NO || 416 braces == 1 && classdef == YES) { 417 fcndef = YES; 418 token = FCNDEF; 419 globalscope = NO; 420 goto iflongline; 421 } 422 goto iffcncall; 423 /* NOTREACHED */ 424 } 425 {identifier}/[ \t]*\( { 426 if (asy) { 427 /* 428 * Macro calls can get here if they have 429 * arguments which contain %'s (i.e., 430 * registers). 431 */ 432 token = FCNDEF; 433 goto iflongline; 434 } 435 436 /* if a function call */ 437 iffcncall: 438 if ((fcndef == YES || ppdefine == YES || 439 rules == YES) && externdec == NO && 440 (localdef == NO || initializer == YES)) { 441 token = FCNCALL; 442 goto iflongline; 443 } 444 if (template == NO && typedefdef == NO) { 445 templateparens = parens; 446 template = YES; 447 } 448 token = IDENT; 449 goto iflongline; 450 /* NOTREACHED */ 451 } 452 (\+\+|--)[ \t]*{identifier} { /* prefix increment or decrement */ 453 token = ASSIGNMENT; 454 goto findident; 455 /* NOTREACHED */ 456 } 457 {identifier}/[ \t]*(\+\+|--) { /* postfix increment or decrement */ 458 token = ASSIGNMENT; 459 goto iflongline; 460 /* NOTREACHED */ 461 } 462 \*[ \t]*{identifier}/[ \t]*[^a-zA-Z0-9_(+-][^+-] { 463 /* indirect assignment or dcl */ 464 while (!isalnum(yytext[first]) && 465 yytext[first] != '_') { 466 ++first; 467 } 468 goto ident; 469 /* NOTREACHED */ 470 } 471 {identifier}/[ \t\n\r]*(=[^=]|[-+*/%&^|]=|<<=|>>=) { /* assignment */ 472 if ((fcndef == YES || ppdefine == YES || 473 rules == YES) && localdef == NO) { 474 token = ASSIGNMENT; 475 goto iflongline; 476 } 477 goto ident; 478 /* NOTREACHED */ 479 } 480 {identifier}/[* \t\n\r]+[a-zA-Z0-9_] { /* possible typedef name use */ 481 if (notpp() && esudef == NO && fcndef == YES && 482 typedefdef == NO && parens == 0) { 483 char c, *s = yytext + first - 1; 484 485 while (--s >= yytext && (c = *s) != ';' && 486 c != '{') { 487 if (!isspace(c) && !isalpha(c)) { 488 goto nottypedefname; 489 } 490 } 491 typedefname = YES; 492 } 493 nottypedefname: 494 /* skip the global/parameter/local tests */ 495 token = IDENT; 496 goto iflongline; 497 /* NOTREACHED */ 498 } 499 {identifier} { 500 struct keystruct *p; 501 char *s; 502 503 ident: token = IDENT; 504 if (notpp() && externdec == NO && 505 arraydimension == NO && initializer == NO) { 506 507 /* if an enum/struct/union member definition */ 508 if (esudef == YES) { 509 if (structfield == NO) { 510 token = MEMBERDEF; 511 } 512 } else if (typedefdef == YES && oldtype == NO) { 513 /* if a typedef name */ 514 token = TYPEDEF; 515 } else if (globalscope == YES && 516 template == NO && oldtype == NO) { 517 /* if a global definition */ 518 token = GLOBALDEF; 519 } else if (fcndef == YES && braces == 0) { 520 /* if a function parameter definition */ 521 token = PARAMETER; 522 } else if (localdef == YES) { 523 /* if a local definition */ 524 token = LOCALDEF; 525 } 526 } 527 iflongline: 528 /* if a long line */ 529 if (yyleng > STMTMAX) { 530 int c; 531 532 /* skip to the end of the line */ 533 warning("line too long"); 534 while ((c = input()) != LEXEOF) { 535 if (c == '\n') { 536 unput(c); 537 break; 538 } 539 } 540 } 541 /* truncate a long symbol */ 542 if (yyleng - first > PATLEN) { 543 warning("symbol too long"); 544 yyleng = first + PATLEN; 545 yytext[yyleng] = '\0'; 546 } 547 548 yymore(); 549 550 if (asy) { 551 int t; 552 553 last = yyleng; 554 t = do_assembly(token); 555 if (t >= 0) { 556 token = t; 557 return (token); 558 } 559 560 goto end; 561 } 562 563 /* if a keyword */ 564 if ((p = lookup(yytext + first)) != NULL) { 565 first = yyleng; 566 s = p->text; 567 568 /* if an extern declaration */ 569 if (s == externtext) { 570 externdec = YES; 571 } else if (s == typedeftext) { 572 /* if a typedef name definition */ 573 typedefdef = YES; 574 oldtype = YES; 575 } else if (p->type == DECL && fcndef == YES && 576 typedefdef == NO && parens == 0) { 577 /* if a local definition */ 578 localdef = YES; 579 } else if (templateparens == parens && 580 template == YES) { 581 /* 582 * keyword doesn't start a function 583 * template 584 */ 585 templateparens = -1; 586 template = NO; 587 } else { 588 /* 589 * next identifier after typedef was 590 * a keyword 591 */ 592 oldtype = NO; 593 } 594 typedefname = NO; 595 } else { /* identifier */ 596 last = yyleng; 597 598 /* 599 * if an enum/struct/union keyword preceded 600 * this ident. 601 */ 602 if (esudef == YES && cesudeftoken) { 603 token = cesudeftoken; 604 cesudeftoken = '\0'; 605 } else { 606 oldtype = NO; 607 } 608 /* if a local definition using a typedef name */ 609 if (typedefname == YES) { 610 localdef = YES; 611 } 612 typedefname = NO; 613 return (token); 614 } 615 616 end: 617 ; 618 } 619 \[ { /* array dimension (don't worry about subscripts) */ 620 arraydimension = YES; 621 goto more; 622 /* NOTREACHED */ 623 } 624 \] { 625 arraydimension = NO; 626 goto more; 627 /* NOTREACHED */ 628 } 629 \\\n { /* preprocessor statement is continued on next line */ 630 goto eol; 631 /* NOTREACHED */ 632 } 633 \n { /* end of the line */ 634 if (ppdefine == YES) { /* end of a #define */ 635 ppdefine = NO; 636 (void) yyless(yyleng - 1); /* rescan \n */ 637 last = first; 638 yymore(); 639 return (DEFINEEND); 640 } 641 /* 642 * skip the first 8 columns of a breakpoint listing 643 * line and skip the file path in the page header 644 */ 645 if (bplisting == YES) { 646 int c, i; 647 648 switch (input()) { 649 /* tab and EOF just fall through */ 650 case ' ': /* breakpoint number line */ 651 case '[': 652 for (i = 1; i < 8 && input() != LEXEOF; 653 ++i) { 654 /*EMPTY*/ 655 } 656 break; 657 case '.': /* header line */ 658 case '/': 659 /* skip to the end of the line */ 660 while ((c = input()) != LEXEOF) { 661 if (c == '\n') { 662 unput(c); 663 break; 664 } 665 } 666 break; 667 case '\n': /* empty line */ 668 unput('\n'); 669 break; 670 } 671 } 672 eol: 673 ++yylineno; 674 first = 0; 675 last = 0; 676 if (symbols > 0) { 677 return (NEWLINE); 678 } 679 lineno = yylineno; 680 } 681 \' { /* character constant */ 682 if (sdl == NO) { 683 multicharconstant('\''); 684 } 685 goto more; 686 /* NOTREACHED */ 687 } 688 \" { /* string constant */ 689 multicharconstant('"'); 690 goto more; 691 /* NOTREACHED */ 692 } 693 ^[ \t\f\b]+ { /* don't save leading white space */ 694 } 695 \#[# \t]*include[ \t]*["<][^"> \t\n\r]+ { /* #include or Ingres ##include */ 696 char *s; 697 698 s = strpbrk(yytext, "\"<"); 699 incfile(s + 1, *s); 700 first = s - yytext; 701 last = yyleng; 702 if (compress == YES) { 703 /* compress the keyword */ 704 yytext[0] = '\1'; 705 } 706 /* 707 * avoid multicharconstant call triggered by trailing 708 * ", which puts a trailing comment in the database 709 */ 710 if (*s == '"') { 711 int c; 712 713 while ((c = input()) != LEXEOF) { 714 if (c == '"') { 715 yytext[yyleng] = '"'; 716 yytext[++yyleng] = '\0'; 717 break; 718 } 719 /* the trailing '"' may be missing */ 720 if (c == '\n') { 721 unput('\n'); 722 break; 723 } 724 } 725 } 726 yymore(); 727 return (INCLUDE); 728 /* NOTREACHED */ 729 } 730 \#[ \t]*pragma[ \t]+weak[ \t]+{identifier} { 731 ppdefine = YES; 732 token = DEFINE; 733 goto findident; 734 735 /*NOTREACHED*/ 736 } 737 \#[ \t]*{identifier} | /* preprocessor keyword */ 738 {number} | /* number */ 739 . { /* punctuation and operators */ 740 more: first = yyleng; 741 yymore(); 742 } 743 %% 744 745 void 746 initscanner(char *srcfile) 747 { 748 char *s; 749 750 if (maxifbraces == NULL) { 751 maxifbraces = mymalloc(miflevel * sizeof (int)); 752 preifbraces = mymalloc(miflevel * sizeof (int)); 753 } 754 first = 0; /* buffer index for first char of symbol */ 755 last = 0; /* buffer index for last char of symbol */ 756 lineno = 1; /* symbol line number */ 757 yylineno = 1; /* input line number */ 758 arraydimension = NO; /* inside array dimension declaration */ 759 bplisting = NO; /* breakpoint listing */ 760 braces = 0; /* unmatched left brace count */ 761 cesudeftoken = '\0'; /* class/enum/struct/union definition */ 762 classdef = NO; /* c++ class definition */ 763 elseelif = NO; /* #else or #elif found */ 764 esudef = NO; /* enum/struct/union definition */ 765 esubraces = -1; /* outermost enum/struct/union brace count */ 766 externdec = NO; /* extern declaration */ 767 fcndef = NO; /* function definition */ 768 globalscope = YES; /* file global scope (outside functions) */ 769 iflevel = 0; /* #if nesting level */ 770 initializer = NO; /* data initializer */ 771 initializerbraces = -1; /* data initializer outer brace count */ 772 lex = NO; /* lex file */ 773 localdef = NO; /* function/block local definition */ 774 parens = 0; /* unmatched left parenthesis count */ 775 ppdefine = NO; /* preprocessor define statement */ 776 psuedoelif = NO; /* psuedo-#elif */ 777 oldtype = NO; /* next identifier is an old type */ 778 rules = NO; /* lex/yacc rules */ 779 sdl = NO; /* SDL file */ 780 structfield = NO; /* structure field declaration */ 781 template = NO; /* function template */ 782 templateparens = -1; /* function template outer parentheses count */ 783 typedefdef = NO; /* typedef name definition */ 784 typedefname = NO; /* typedef name use */ 785 asy = NO; /* assembly file */ 786 BEGIN 0; 787 788 /* if this is not a C file */ 789 if ((s = strrchr(srcfile, '.')) != NULL) { 790 switch (*++s) { /* this switch saves time on C files */ 791 case 'b': 792 if (strcmp(s, "bp") == 0) { /* breakpoint listing */ 793 bplisting = YES; 794 } 795 break; 796 case 'l': 797 if (strcmp(s, "l") == 0) { /* lex */ 798 lex = YES; 799 globalscope = NO; 800 } 801 break; 802 case 'p': 803 case 's': 804 if (strcmp(s, "pr") == 0 || 805 strcmp(s, "sd") == 0) { /* SDL */ 806 sdl = YES; 807 BEGIN SDL; 808 } else if (strcmp(s, "s") == 0) { 809 asy = YES; 810 } 811 break; 812 case 'y': 813 if (strcmp(s, "y") == 0) { /* yacc */ 814 globalscope = NO; 815 } 816 break; 817 } 818 } 819 } 820 821 int 822 comment(void) 823 { 824 int c, lastc; 825 826 do { 827 if ((c = getc(yyin)) == '*') { /* C comment */ 828 lastc = '\0'; 829 while ((c = getc(yyin)) != EOF && 830 (c != '/' || lastc != '*')) { /* fewer '/'s */ 831 if (c == '\n') { 832 ++yylineno; 833 } 834 lastc = c; 835 } 836 /* return a blank for Reiser cpp token concatenation */ 837 if ((c = getc(yyin)) == '_' || isalnum(c)) { 838 (void) ungetc(c, yyin); 839 c = ' '; 840 break; 841 } 842 } else if (c == '/') { /* C++ comment */ 843 while ((c = getc(yyin)) != EOF && c != '\n') { 844 /*EMPTY*/ 845 } 846 break; 847 } else { /* not a comment */ 848 (void) ungetc(c, yyin); 849 c = '/'; 850 break; 851 } 852 853 /* there may be an immediately following comment */ 854 } while (c == '/'); 855 return (c); 856 } 857 858 void 859 multicharconstant(char terminator) 860 { 861 char c; 862 863 /* scan until the terminator is found */ 864 while ((c = yytext[yyleng++] = noncommentinput()) != terminator) { 865 switch (c) { 866 case '\\': /* escape character */ 867 if ((yytext[yyleng++] = noncommentinput()) == '\n') { 868 ++yylineno; 869 } 870 break; 871 case '\t': /* tab character */ 872 873 /* if not a lex program, continue */ 874 if (lex == NO) { 875 break; 876 } 877 /* FALLTHROUGH */ 878 879 case '\n': /* illegal character */ 880 881 /* 882 * assume the terminator is missing, so put 883 * this character back 884 */ 885 unput(c); 886 yytext[--yyleng] = '\0'; 887 /* FALLTHROUGH */ 888 889 case LEXEOF: /* end of file */ 890 return; 891 892 default: 893 /* change a control character to a blank */ 894 if (!isprint(c)) { 895 yytext[yyleng - 1] = ' '; 896 } 897 } 898 /* if this token will overflow the line buffer */ 899 /* note: '\\' may cause yyleng to be > STMTMAX */ 900 if (yyleng >= STMTMAX) { 901 902 /* truncate the token */ 903 while ((c = noncommentinput()) != LEXEOF) { 904 if (c == terminator) { 905 unput(c); 906 break; 907 } else if (c == '\n') { 908 ++yylineno; 909 } 910 } 911 } 912 } 913 yytext[yyleng] = '\0'; 914 } 915 916 /* 917 * Returns true if the beginning of str matches ident, and the next character 918 * is not alphanumeric and not an underscore. 919 */ 920 int 921 identcmp(const char *str, const char *ident) 922 { 923 int n = strlen(ident); 924 925 return (strncmp(str, ident, n) == 0 && !isalnum(str[n]) && 926 str[n] != '_'); 927 } 928 929 /* 930 * Here we want to 931 * - Make *ENTRY*() macro invocations into function definitions 932 * - Make SET_SIZE() macro calls into function ends 933 * - Make "call sym" instructions into function calls 934 * - Eliminate C function definitions (since they are for lint, and we want 935 * only one definition for each function) 936 */ 937 int 938 do_assembly(int token) 939 { 940 /* Handle C keywords? */ 941 942 switch (token) { 943 944 case FCNDEF: 945 /* 946 * We have a symbol that looks like a C function definition or 947 * call. (Note: That can include assembly instructions with 948 * the right parentheses.) We want to convert assembly macro 949 * invocations to function calls, and ignore everything else. 950 * Since we technically can't tell the difference, we'll use 951 * an all-caps heuristic. 952 * 953 * ... except for SET_SIZE macros, since they will precede 954 * FUNCEND tokens, which will break code in find.c which 955 * assumes that FUNCEND tokens occur at the beginning of 956 * lines. 957 */ 958 if (isupper(yytext[first]) && strcmp(yytext, "SET_SIZE") != 0) 959 return (FCNCALL); 960 961 /* Don't return a token. */ 962 return (-1); 963 964 case GLOBALDEF: 965 case IDENT: 966 /* Macro arguments come down as global variable definitions. */ 967 968 if (identcmp(yytext, "ENTRY") || 969 identcmp(yytext, "ENTRY2") || 970 identcmp(yytext, "ENTRY_NP") || 971 identcmp(yytext, "ENTRY_NP2") || 972 identcmp(yytext, "RTENTRY") || 973 identcmp(yytext, "ALTENTRY")) { 974 /* 975 * Identifiers on lines beginning with *ENTRY* macros 976 * are actually function definitions. 977 */ 978 return (FCNDEF); 979 } 980 981 if (identcmp(yytext, "SET_SIZE")) { 982 /* 983 * Identifiers on lines beginning with SET_SIZE are 984 * actually function ends. 985 */ 986 return (FCNEND); 987 } 988 989 if (first != 0 && identcmp(yytext, "call")) { 990 /* 991 * Make this a function call. We exclude first == 0, 992 * because that happens when we're looking at "call" 993 * itself. (Then we'd get function calls to "call" 994 * everywhere.) 995 */ 996 return (FCNCALL); 997 } 998 999 default: 1000 /* Default to normal behavior. */ 1001 return (token); 1002 } 1003 } 1004