1 #ifndef lint 2 static char *sccsid ="@(#)scan.c 2.13 (Berkeley) 12/10/87"; 3 #endif lint 4 5 # include "pass1.h" 6 # include <a.out.h> 7 # include <stab.h> 8 # include <ctype.h> 9 # include <signal.h> 10 11 /* temporarily */ 12 13 int asm_esc = 0; /* asm escaped used in file */ 14 /* lexical actions */ 15 16 # define A_ERR 0 /* illegal character */ 17 # define A_LET 1 /* saw a letter */ 18 # define A_DIG 2 /* saw a digit */ 19 # define A_1C 3 /* return a single character */ 20 # define A_STR 4 /* string */ 21 # define A_CC 5 /* character constant */ 22 # define A_BCD 6 /* GCOS BCD constant */ 23 # define A_SL 7 /* saw a / */ 24 # define A_DOT 8 /* saw a . */ 25 # define A_PL 9 /* + */ 26 # define A_MI 10 /* - */ 27 # define A_EQ 11 /* = */ 28 # define A_NOT 12 /* ! */ 29 # define A_LT 13 /* < */ 30 # define A_GT 14 /* > */ 31 # define A_AND 16 /* & */ 32 # define A_OR 17 /* | */ 33 # define A_WS 18 /* whitespace (not \n) */ 34 # define A_NL 19 /* \n */ 35 36 /* character classes */ 37 38 # define LEXLET 01 39 # define LEXDIG 02 40 # define LEXOCT 04 41 # define LEXHEX 010 42 # define LEXWS 020 43 # define LEXDOT 040 44 45 /* reserved word actions */ 46 47 # define AR_TY 0 /* type word */ 48 # define AR_RW 1 /* simple reserved word */ 49 # define AR_CL 2 /* storage class word */ 50 # define AR_S 3 /* struct */ 51 # define AR_U 4 /* union */ 52 # define AR_E 5 /* enum */ 53 # define AR_A 6 /* asm */ 54 55 /* text buffer */ 56 #ifndef FLEXNAMES 57 # define LXTSZ 100 58 #else 59 #define LXTSZ BUFSIZ 60 #endif 61 char yytext[LXTSZ]; 62 char * lxgcp; 63 64 extern int proflg; 65 extern int gdebug; 66 extern int fpe(); 67 struct sigvec fpe_sigvec; 68 int oldway; /* allocate storage so lint will compile as well */ 69 #ifndef LINT 70 extern int lastloc; 71 #endif 72 73 unsigned caloff(); 74 /* ARGSUSED */ 75 mainp1( argc, argv ) int argc; char *argv[]; { /* control multiple files */ 76 77 register i; 78 register char *cp; 79 extern int idebug, bdebug, tdebug, edebug; 80 extern int ddebug, xdebug, gdebug, adebug; 81 extern unsigned int offsz; 82 int fdef = 0; 83 extern char *release; 84 85 offsz = caloff(); 86 for( i=1; i<argc; ++i ){ 87 if( *(cp=argv[i]) == '-' && *++cp == 'X' ){ 88 while( *++cp ){ 89 switch( *cp ){ 90 91 case 'r': 92 fprintf( stderr, "Release: %s\n", 93 release ); 94 break; 95 96 case 'd': 97 ++ddebug; 98 break; 99 case 'i': 100 ++idebug; 101 break; 102 case 'b': 103 ++bdebug; 104 break; 105 case 't': 106 ++tdebug; 107 break; 108 case 'e': 109 ++edebug; 110 break; 111 case 'x': 112 ++xdebug; 113 break; 114 case 'P': /* profiling */ 115 ++proflg; 116 break; 117 case 'g': 118 ++gdebug; 119 break; 120 case 'a': 121 ++adebug; 122 break; 123 case 'G': 124 ++gdebug; 125 oldway = 1; 126 break; 127 } 128 } 129 } 130 else { 131 if( *(argv[i]) != '-' ) switch( fdef++ ) { 132 case 0: 133 case 1: 134 if( freopen(argv[i], fdef==1 ? "r" : "w", fdef==1 ? stdin : stdout) == NULL) { 135 fprintf(stderr, "ccom:can't open %s\n", argv[i]); 136 exit(1); 137 } 138 break; 139 140 default: 141 ; 142 } 143 } 144 } 145 146 # ifdef ONEPASS 147 (void) p2init( argc, argv ); 148 # endif 149 150 for( i=0; i<SYMTSZ; ++i ) stab[i].stype = TNULL; 151 152 lineno = 1; 153 154 lxinit(); 155 tinit(); 156 mkdope(); 157 158 /* dimension table initialization */ 159 160 dimtab[NULL] = 0; 161 dimtab[CHAR] = SZCHAR; 162 dimtab[INT] = SZINT; 163 dimtab[FLOAT] = SZFLOAT; 164 dimtab[DOUBLE] = SZDOUBLE; 165 dimtab[LONG] = SZLONG; 166 dimtab[SHORT] = SZSHORT; 167 dimtab[UCHAR] = SZCHAR; 168 dimtab[USHORT] = SZSHORT; 169 dimtab[UNSIGNED] = SZINT; 170 dimtab[ULONG] = SZLONG; 171 /* starts past any of the above */ 172 curdim = 16; 173 reached = 1; 174 175 fpe_sigvec.sv_handler = fpe; 176 (void) sigvec(SIGFPE, &fpe_sigvec, (struct sigvec *) NULL); 177 178 (void) yyparse(); 179 yyaccpt(); 180 181 ejobcode( nerrors ? 1 : 0 ); 182 return(nerrors?1:0); 183 184 } 185 186 # ifdef ibm 187 188 # define CSMASK 0377 189 # define CSSZ 256 190 191 # else 192 193 # define CSMASK 0177 194 # define CSSZ 128 195 196 # endif 197 198 short lxmask[CSSZ+1]; 199 200 lxenter( s, m ) register char *s; register short m; { 201 /* enter a mask into lxmask */ 202 register c; 203 204 while( c= *s++ ) lxmask[c+1] |= m; 205 206 } 207 208 209 # define lxget(c,m) (lxgcp=yytext,lxmore(c,m)) 210 211 lxmore( c, m ) register c, m; { 212 register char *cp; 213 214 *(cp = lxgcp) = c; 215 while( c=getchar(), lxmask[c+1]&m ){ 216 if( cp < &yytext[LXTSZ-1] ){ 217 *++cp = c; 218 } 219 } 220 ungetc(c,stdin); 221 *(lxgcp = cp+1) = '\0'; 222 } 223 224 struct lxdope { 225 short lxch; /* the character */ 226 short lxact; /* the action to be performed */ 227 short lxtok; /* the token number to be returned */ 228 short lxval; /* the value to be returned */ 229 } lxdope[] = { 230 231 '@', A_ERR, 0, 0, /* illegal characters go here... */ 232 '_', A_LET, 0, 0, /* letters point here */ 233 '0', A_DIG, 0, 0, /* digits point here */ 234 ' ', A_WS, 0, 0, /* whitespace goes here */ 235 '\n', A_NL, 0, 0, 236 '"', A_STR, 0, 0, /* character string */ 237 '\'', A_CC, 0, 0, /* character constant */ 238 '`', A_BCD, 0, 0, /* GCOS BCD constant */ 239 '(', A_1C, LP, 0, 240 ')', A_1C, RP, 0, 241 '{', A_1C, LC, 0, 242 '}', A_1C, RC, 0, 243 '[', A_1C, LB, 0, 244 ']', A_1C, RB, 0, 245 '*', A_1C, MUL, MUL, 246 '?', A_1C, QUEST, 0, 247 ':', A_1C, COLON, 0, 248 '+', A_PL, PLUS, PLUS, 249 '-', A_MI, MINUS, MINUS, 250 '/', A_SL, DIVOP, DIV, 251 '%', A_1C, DIVOP, MOD, 252 '&', A_AND, AND, AND, 253 '|', A_OR, OR, OR, 254 '^', A_1C, ER, ER, 255 '!', A_NOT, UNOP, NOT, 256 '~', A_1C, UNOP, COMPL, 257 ',', A_1C, CM, CM, 258 ';', A_1C, SM, 0, 259 '.', A_DOT, STROP, DOT, 260 '<', A_LT, RELOP, LT, 261 '>', A_GT, RELOP, GT, 262 '=', A_EQ, ASSIGN, ASSIGN, 263 -1, A_1C, 0, 0, 264 }; 265 266 struct lxdope *lxcp[CSSZ+1]; 267 268 lxinit(){ 269 register struct lxdope *p; 270 register i; 271 register char *cp; 272 /* set up character classes */ 273 274 lxenter( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$", LEXLET ); 275 lxenter( "0123456789", LEXDIG ); 276 lxenter( "0123456789abcdefABCDEF", LEXHEX ); 277 /* \013 should become \v someday; \013 is OK for ASCII and EBCDIC */ 278 lxenter( " \t\r\b\f\013", LEXWS ); 279 lxenter( "01234567", LEXOCT ); 280 lxmask['.'+1] |= LEXDOT; 281 282 /* make lxcp point to appropriate lxdope entry for each character */ 283 284 /* initialize error entries */ 285 286 for( i= 0; i<=CSSZ; ++i ) lxcp[i] = lxdope; 287 288 /* make unique entries */ 289 290 for( p=lxdope; ; ++p ) { 291 lxcp[p->lxch+1] = p; 292 if( p->lxch < 0 ) break; 293 } 294 295 /* handle letters, digits, and whitespace */ 296 /* by convention, first, second, and third places */ 297 298 cp = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$"; 299 while( *cp ) lxcp[*cp++ + 1] = &lxdope[1]; 300 cp = "123456789"; 301 while( *cp ) lxcp[*cp++ + 1] = &lxdope[2]; 302 cp = "\t\b\r\f\013"; 303 while( *cp ) lxcp[*cp++ + 1] = &lxdope[3]; 304 305 /* first line might have title */ 306 lxtitle(); 307 308 } 309 310 int lxmatch = 0; /* character to be matched in char or string constant */ 311 312 lxstr(ct){ 313 /* match a string or character constant, up to lxmatch */ 314 315 register c; 316 register val; 317 register i; 318 319 i=0; 320 while( (c=getchar()) != lxmatch ){ 321 switch( c ) { 322 323 case EOF: 324 uerror( "unexpected EOF" ); 325 break; 326 327 case '\n': 328 uerror( "newline in string or char constant" ); 329 ++lineno; 330 break; 331 332 case '\\': 333 switch( c = getchar() ){ 334 335 case '\n': 336 ++lineno; 337 continue; 338 339 default: 340 val = c; 341 goto mkcc; 342 343 case 'n': 344 val = '\n'; 345 goto mkcc; 346 347 case 'r': 348 val = '\r'; 349 goto mkcc; 350 351 case 'b': 352 val = '\b'; 353 goto mkcc; 354 355 case 't': 356 val = '\t'; 357 goto mkcc; 358 359 case 'f': 360 val = '\f'; 361 goto mkcc; 362 363 case 'v': 364 val = '\013'; 365 goto mkcc; 366 367 case '0': 368 case '1': 369 case '2': 370 case '3': 371 case '4': 372 case '5': 373 case '6': 374 case '7': 375 val = c-'0'; 376 c=getchar(); /* try for 2 */ 377 if( lxmask[c+1] & LEXOCT ){ 378 val = (val<<3) | (c-'0'); 379 c = getchar(); /* try for 3 */ 380 if( lxmask[c+1] & LEXOCT ){ 381 val = (val<<3) | (c-'0'); 382 } 383 else ungetc( c ,stdin); 384 } 385 else ungetc( c ,stdin); 386 387 goto mkcc1; 388 389 } 390 default: 391 val =c; 392 mkcc: 393 val = CCTRANS(val); 394 mkcc1: 395 if( lxmatch == '\'' ){ 396 val = CHARCAST(val); /* it is, after all, a "character" constant */ 397 makecc( val, i ); 398 } 399 else { /* stash the byte into the string */ 400 if( strflg ) { 401 if( ct==0 || i<ct ) putbyte( val ); 402 else if( i == ct ) werror( "non-null byte ignored in string initializer" ); 403 } 404 else bycode( val, i ); 405 } 406 ++i; 407 continue; 408 } 409 break; 410 } 411 /* end of string or char constant */ 412 413 if( lxmatch == '"' ){ 414 if( strflg ){ /* end the string */ 415 if( ct==0 || i<ct ) putbyte( 0 ); /* the null at the end */ 416 } 417 else { /* the initializer gets a null byte */ 418 bycode( 0, i++ ); 419 bycode( -1, i ); 420 dimtab[curdim] = i; /* in case of later sizeof ... */ 421 } 422 } 423 else { /* end the character constant */ 424 if( i == 0 ) uerror( "empty character constant" ); 425 if( i>(SZINT/SZCHAR) || ( (pflag||hflag)&&i>1) ) 426 uerror( "too many characters in character constant" ); 427 } 428 lxmatch = 0; /* handshake with yylex() */ 429 } 430 431 lxcom(){ 432 register c; 433 /* saw a /*: process a comment */ 434 435 for(;;){ 436 437 switch( c = getchar() ){ 438 439 case EOF: 440 uerror( "unexpected EOF" ); 441 return; 442 443 case '\n': 444 ++lineno; 445 446 default: 447 continue; 448 449 case '*': 450 if( (c = getchar()) == '/' ) return; 451 else ungetc( c ,stdin); 452 continue; 453 454 # ifdef LINT 455 case 'V': 456 lxget( c, LEXLET|LEXDIG ); 457 { 458 extern int vaflag; 459 int i; 460 i = yytext[7]?yytext[7]-'0':0; 461 yytext[7] = '\0'; 462 if( strcmp( yytext, "VARARGS" ) ) continue; 463 vaflag = i; 464 continue; 465 } 466 case 'L': 467 lxget( c, LEXLET ); 468 if( strcmp( yytext, "LINTLIBRARY" ) ) continue; 469 { 470 extern int libflag; 471 libflag = 1; 472 } 473 continue; 474 475 case 'A': 476 lxget( c, LEXLET ); 477 if( strcmp( yytext, "ARGSUSED" ) ) continue; 478 { 479 extern int argflag, vflag; 480 argflag = 1; 481 vflag = 0; 482 } 483 continue; 484 485 case 'N': 486 lxget( c, LEXLET ); 487 if( strcmp( yytext, "NOTREACHED" ) ) continue; 488 reached = 0; 489 continue; 490 # endif 491 } 492 } 493 } 494 495 yylex(){ 496 if (lxmatch != 0) { 497 /* recover from a syntax error that consumes a STRING token */ 498 strflg = 1; 499 lxstr(0); 500 } 501 for(;;){ 502 503 register lxchar; 504 register struct lxdope *p; 505 register struct symtab *sp; 506 int id; 507 char *s; 508 static char sc[5]; 509 510 switch( (p=lxcp[(lxchar=getchar())+1])->lxact ){ 511 512 onechar: 513 ungetc( lxchar ,stdin); 514 515 case A_1C: 516 /* eat up a single character, and return an opcode */ 517 518 yylval.intval = p->lxval; 519 return( p->lxtok ); 520 521 case A_ERR: 522 switch( lxchar ){ 523 case '\\': s = "\\\\"; break; 524 case '\0': s = "\\0"; break; 525 default: 526 if( isgraph( lxchar ) ){ 527 sc[0] = lxchar; 528 sc[1] = '\0'; 529 } 530 else 531 sprintf( sc, "\\%03.3o", (unsigned char) lxchar ); 532 s = sc; 533 break; 534 } 535 uerror( "illegal character: '%s'", s ); 536 break; 537 538 case A_LET: 539 /* collect an identifier, check for reserved word, and return */ 540 lxget( lxchar, LEXLET|LEXDIG ); 541 if( (lxchar=lxres()) > 0 ) return( lxchar ); /* reserved word */ 542 if( lxchar== 0 ) continue; 543 #ifdef FLEXNAMES 544 id = lookup( hash(yytext), 545 #else 546 id = lookup( yytext, 547 #endif 548 /* tag name for struct/union/enum */ 549 (stwart&TAGNAME)? STAG: 550 /* member name for struct/union */ 551 (stwart&(INSTRUCT|INUNION|FUNNYNAME))?SMOS:0 ); 552 sp = &stab[id]; 553 if( sp->sclass == TYPEDEF && !stwart ){ 554 stwart = instruct; 555 yylval.nodep = mkty( sp->stype, sp->dimoff, sp->sizoff ); 556 return( TYPE ); 557 } 558 stwart = (stwart&SEENAME) ? instruct : 0; 559 yylval.intval = id; 560 return( NAME ); 561 562 case A_DIG: 563 /* collect a digit string, then look at last one... */ 564 lastcon = 0; 565 lxget( lxchar, LEXDIG ); 566 switch( lxchar=getchar() ){ 567 568 case 'x': 569 case 'X': 570 if( yytext[0] != '0' && !yytext[1] ) uerror( "illegal hex constant" ); 571 lxmore( lxchar, LEXHEX ); 572 /* convert the value */ 573 { 574 register char *cp; 575 for( cp = yytext+2; *cp; ++cp ){ 576 /* this code won't work for all wild character sets, 577 but seems ok for ascii and ebcdic */ 578 lastcon <<= 4; 579 if( isdigit( *cp ) ) lastcon += *cp-'0'; 580 else if( isupper( *cp ) ) lastcon += *cp - 'A'+ 10; 581 else lastcon += *cp - 'a'+ 10; 582 } 583 } 584 585 hexlong: 586 /* criterion for longness for hex and octal constants is that it 587 fit within 0177777 */ 588 if( lastcon & ~0177777L ) yylval.intval = 1; 589 else yylval.intval = 0; 590 591 goto islong; 592 593 case '.': 594 lxmore( lxchar, LEXDIG ); 595 596 getfp: 597 if( (lxchar=getchar()) == 'e' || lxchar == 'E' ){ /* exponent */ 598 599 case 'e': 600 case 'E': 601 if( (lxchar=getchar()) == '+' || lxchar == '-' ){ 602 *lxgcp++ = 'e'; 603 } 604 else { 605 ungetc(lxchar,stdin); 606 lxchar = 'e'; 607 } 608 lxmore( lxchar, LEXDIG ); 609 /* now have the whole thing... */ 610 } 611 else { /* no exponent */ 612 ungetc( lxchar ,stdin); 613 } 614 return( isitfloat( yytext ) ); 615 616 default: 617 ungetc( lxchar ,stdin); 618 if( yytext[0] == '0' ){ 619 /* convert in octal */ 620 register char *cp; 621 for( cp = yytext+1; *cp; ++cp ){ 622 lastcon <<= 3; 623 lastcon += *cp - '0'; 624 } 625 goto hexlong; 626 } 627 else { 628 /* convert in decimal */ 629 register char *cp; 630 for( cp = yytext; *cp; ++cp ){ 631 lastcon = lastcon * 10 + *cp - '0'; 632 } 633 } 634 635 /* decide if it is long or not (decimal case) */ 636 637 /* if it is positive and fits in 15 bits, or negative and 638 and fits in 15 bits plus an extended sign, it is int; otherwise long */ 639 /* if there is an l or L following, all bets are off... */ 640 641 { CONSZ v; 642 v = lastcon & ~077777L; 643 if( v == 0 || v == ~077777L ) yylval.intval = 0; 644 else yylval.intval = 1; 645 } 646 647 islong: 648 /* finally, look for trailing L or l */ 649 if( (lxchar = getchar()) == 'L' || lxchar == 'l' ) yylval.intval = 1; 650 else ungetc( lxchar ,stdin); 651 return( ICON ); 652 } 653 654 case A_DOT: 655 /* look for a dot: if followed by a digit, floating point */ 656 lxchar = getchar(); 657 if( lxmask[lxchar+1] & LEXDIG ){ 658 ungetc(lxchar,stdin); 659 lxget( '.', LEXDIG ); 660 goto getfp; 661 } 662 stwart = FUNNYNAME; 663 goto onechar; 664 665 case A_STR: 666 /* string constant */ 667 lxmatch = '"'; 668 return( STRING ); 669 670 case A_CC: 671 /* character constant */ 672 lxmatch = '\''; 673 lastcon = 0; 674 lxstr(0); 675 yylval.intval = 0; 676 return( ICON ); 677 678 case A_BCD: 679 { 680 register i; 681 int j; 682 for( i=0; i<LXTSZ; ++i ){ 683 if( ( j = getchar() ) == '`' ) break; 684 if( j == '\n' ){ 685 uerror( "newline in BCD constant" ); 686 break; 687 } 688 yytext[i] = j; 689 } 690 yytext[i] = '\0'; 691 if( i>6 ) uerror( "BCD constant exceeds 6 characters" ); 692 # ifdef gcos 693 else strtob( yytext, &lastcon, i ); 694 lastcon >>= 6*(6-i); 695 # else 696 uerror( "gcos BCD constant illegal" ); 697 # endif 698 yylval.intval = 0; /* not long */ 699 return( ICON ); 700 } 701 702 case A_SL: 703 /* / */ 704 if( (lxchar=getchar()) != '*' ) goto onechar; 705 lxcom(); 706 case A_WS: 707 continue; 708 709 case A_NL: 710 ++lineno; 711 lxtitle(); 712 continue; 713 714 case A_NOT: 715 /* ! */ 716 if( (lxchar=getchar()) != '=' ) goto onechar; 717 yylval.intval = NE; 718 return( EQUOP ); 719 720 case A_MI: 721 /* - */ 722 if( (lxchar=getchar()) == '-' ){ 723 yylval.intval = DECR; 724 return( INCOP ); 725 } 726 if( lxchar != '>' ) goto onechar; 727 stwart = FUNNYNAME; 728 yylval.intval=STREF; 729 return( STROP ); 730 731 case A_PL: 732 /* + */ 733 if( (lxchar=getchar()) != '+' ) goto onechar; 734 yylval.intval = INCR; 735 return( INCOP ); 736 737 case A_AND: 738 /* & */ 739 if( (lxchar=getchar()) != '&' ) goto onechar; 740 return( yylval.intval = ANDAND ); 741 742 case A_OR: 743 /* | */ 744 if( (lxchar=getchar()) != '|' ) goto onechar; 745 return( yylval.intval = OROR ); 746 747 case A_LT: 748 /* < */ 749 if( (lxchar=getchar()) == '<' ){ 750 yylval.intval = LS; 751 return( SHIFTOP ); 752 } 753 if( lxchar != '=' ) goto onechar; 754 yylval.intval = LE; 755 return( RELOP ); 756 757 case A_GT: 758 /* > */ 759 if( (lxchar=getchar()) == '>' ){ 760 yylval.intval = RS; 761 return(SHIFTOP ); 762 } 763 if( lxchar != '=' ) goto onechar; 764 yylval.intval = GE; 765 return( RELOP ); 766 767 case A_EQ: 768 /* = */ 769 switch( lxchar = getchar() ){ 770 771 case '=': 772 yylval.intval = EQ; 773 return( EQUOP ); 774 775 #ifdef old_assignment_ops 776 case '+': 777 yylval.intval = ASG PLUS; 778 break; 779 780 case '-': 781 yylval.intval = ASG MINUS; 782 783 warn: 784 if( lxmask[ (lxchar=getchar())+1] & (LEXLET|LEXDIG|LEXDOT) ){ 785 werror( "ambiguous assignment: assignment op taken" ); 786 } 787 ungetc( lxchar ,stdin); 788 break; 789 790 case '*': 791 yylval.intval = ASG MUL; 792 goto warn; 793 794 case '/': 795 yylval.intval = ASG DIV; 796 break; 797 798 case '%': 799 yylval.intval = ASG MOD; 800 break; 801 802 case '&': 803 yylval.intval = ASG AND; 804 break; 805 806 case '|': 807 yylval.intval = ASG OR; 808 break; 809 810 case '^': 811 yylval.intval = ASG ER; 812 break; 813 814 case '<': 815 if( (lxchar=getchar()) != '<' ){ 816 uerror( "=<%c illegal", lxchar ); 817 } 818 yylval.intval = ASG LS; 819 break; 820 821 case '>': 822 if( (lxchar=getchar()) != '>' ){ 823 uerror( "=>%c illegal", lxchar ); 824 } 825 yylval.intval = ASG RS; 826 break; 827 #endif old_assignment_ops 828 829 default: 830 goto onechar; 831 832 } 833 834 #ifdef old_assignment_ops /* defeat 'unreachable code' warning */ 835 return( ASOP ); 836 #endif old_assignment_ops 837 838 default: 839 cerror( "yylex error, character %03o (octal)", lxchar ); 840 841 } 842 843 /* ordinarily, repeat here... */ 844 cerror( "out of switch in yylex" ); 845 846 } 847 848 } 849 850 struct lxrdope { 851 /* dope for reserved, in alphabetical order */ 852 853 char *lxrch; /* name of reserved word */ 854 short lxract; /* reserved word action */ 855 short lxrval; /* value to be returned */ 856 } lxrdope[] = { 857 858 "asm", AR_A, 0, 859 "auto", AR_CL, AUTO, 860 "break", AR_RW, BREAK, 861 "char", AR_TY, CHAR, 862 "case", AR_RW, CASE, 863 "continue", AR_RW, CONTINUE, 864 "double", AR_TY, DOUBLE, 865 "default", AR_RW, DEFAULT, 866 "do", AR_RW, DO, 867 "extern", AR_CL, EXTERN, 868 "else", AR_RW, ELSE, 869 "enum", AR_E, ENUM, 870 "for", AR_RW, FOR, 871 "float", AR_TY, FLOAT, 872 "fortran", AR_CL, FORTRAN, 873 "goto", AR_RW, GOTO, 874 "if", AR_RW, IF, 875 "int", AR_TY, INT, 876 "long", AR_TY, LONG, 877 "return", AR_RW, RETURN, 878 "register", AR_CL, REGISTER, 879 "switch", AR_RW, SWITCH, 880 "struct", AR_S, 0, 881 "sizeof", AR_RW, SIZEOF, 882 "short", AR_TY, SHORT, 883 "static", AR_CL, STATIC, 884 "typedef", AR_CL, TYPEDEF, 885 "unsigned", AR_TY, UNSIGNED, 886 "union", AR_U, 0, 887 "void", AR_TY, UNDEF, /* tymerge adds FTN */ 888 "while", AR_RW, WHILE, 889 "", 0, 0, /* to stop the search */ 890 }; 891 892 lxres() { 893 /* check to see of yytext is reserved; if so, 894 /* do the appropriate action and return */ 895 /* otherwise, return -1 */ 896 897 register c, ch; 898 register struct lxrdope *p; 899 900 ch = yytext[0]; 901 902 if( !islower(ch) ) return( -1 ); 903 904 switch( ch ){ 905 906 case 'a': 907 c=0; break; 908 case 'b': 909 c=2; break; 910 case 'c': 911 c=3; break; 912 case 'd': 913 c=6; break; 914 case 'e': 915 c=9; break; 916 case 'f': 917 c=12; break; 918 case 'g': 919 c=15; break; 920 case 'i': 921 c=16; break; 922 case 'l': 923 c=18; break; 924 case 'r': 925 c=19; break; 926 case 's': 927 c=21; break; 928 case 't': 929 c=26; break; 930 case 'u': 931 c=27; break; 932 case 'v': 933 c=29; break; 934 case 'w': 935 c=30; break; 936 937 default: 938 return( -1 ); 939 } 940 941 for( p= lxrdope+c; p->lxrch[0] == ch; ++p ){ 942 if( !strcmp( yytext, p->lxrch ) ){ /* match */ 943 switch( p->lxract ){ 944 945 case AR_TY: 946 /* type word */ 947 stwart = instruct; 948 yylval.nodep = mkty( (TWORD)p->lxrval, 0, p->lxrval ); 949 return( TYPE ); 950 951 case AR_RW: 952 /* ordinary reserved word */ 953 return( yylval.intval = p->lxrval ); 954 955 case AR_CL: 956 /* class word */ 957 yylval.intval = p->lxrval; 958 return( CLASS ); 959 960 case AR_S: 961 /* struct */ 962 stwart = INSTRUCT|SEENAME|TAGNAME; 963 yylval.intval = INSTRUCT; 964 return( STRUCT ); 965 966 case AR_U: 967 /* union */ 968 stwart = INUNION|SEENAME|TAGNAME; 969 yylval.intval = INUNION; 970 return( STRUCT ); 971 972 case AR_E: 973 /* enums */ 974 stwart = SEENAME|TAGNAME; 975 return( yylval.intval = ENUM ); 976 977 case AR_A: 978 /* asm */ 979 asm_esc = 1; /* warn the world! */ 980 lxget( ' ', LEXWS ); 981 if( getchar() != '(' ) goto badasm; 982 lxget( ' ', LEXWS ); 983 if( getchar() != '"' ) goto badasm; 984 # ifndef ONEPASS 985 # ifndef LINT 986 putchar(')'); 987 # endif 988 # endif 989 while( (c=getchar()) != '"' ){ 990 if( c=='\n' || c==EOF ) goto badasm; 991 # ifndef LINT 992 putchar(c); 993 # endif 994 } 995 lxget( ' ', LEXWS ); 996 if( getchar() != ')' ) goto badasm; 997 # ifndef LINT 998 putchar('\n'); 999 # endif 1000 return( 0 ); 1001 1002 badasm: 1003 uerror( "bad asm construction" ); 1004 return( 0 ); 1005 1006 default: 1007 cerror( "bad AR_?? action" ); 1008 } 1009 } 1010 } 1011 return( -1 ); 1012 } 1013 1014 extern int labelno; 1015 1016 lxtitle(){ 1017 /* called after a newline; set linenumber and file name */ 1018 1019 register c, val; 1020 register char *cp, *cq; 1021 1022 for(;;){ /* might be several such lines in a row */ 1023 if( (c=getchar()) != '#' ){ 1024 if( c != EOF ) ungetc(c,stdin); 1025 #ifndef LINT 1026 if ( lastloc != PROG) return; 1027 cp = ftitle; 1028 cq = ititle; 1029 while ( *cp ) if (*cp++ != *cq++) return; 1030 if ( *cq ) return; 1031 if( nerrors == 0 ) psline(); 1032 #endif 1033 return; 1034 } 1035 1036 lxget( ' ', LEXWS ); 1037 c = getchar(); 1038 if( c == 'i' ){ 1039 /* #ident -- currently a no-op */ 1040 lxget( c, LEXLET ); 1041 if( strcmp( yytext, "ident" ) ) 1042 werror( "%s: undefined control", yytext ); 1043 while( (c = getchar()) != '\n' && c != EOF ) 1044 ; 1045 continue; 1046 } 1047 if( c == 'p' ){ 1048 /* #pragma -- special instructions */ 1049 lxget( c, LEXLET ); 1050 if( strcmp( yytext, "pragma" ) ) { 1051 werror( "%s: undefined control", yytext ); 1052 while( (c = getchar()) != '\n' && c != EOF ) 1053 ; 1054 continue; 1055 } 1056 lxget( ' ' , LEXWS ); 1057 switch( c = getchar() ){ 1058 # ifdef LINT 1059 case 'V': 1060 lxget( c, LEXLET|LEXDIG ); 1061 { 1062 extern int vaflag; 1063 int i; 1064 i = yytext[7]?yytext[7]-'0':0; 1065 yytext[7] = '\0'; 1066 if( strcmp( yytext, "VARARGS" ) ) break; 1067 vaflag = i; 1068 break; 1069 } 1070 case 'L': 1071 lxget( c, LEXLET ); 1072 if( strcmp( yytext, "LINTLIBRARY" ) ) break; 1073 { 1074 extern int libflag; 1075 libflag = 1; 1076 } 1077 break; 1078 1079 case 'A': 1080 lxget( c, LEXLET ); 1081 if( strcmp( yytext, "ARGSUSED" ) ) break; 1082 { 1083 extern int argflag, vflag; 1084 argflag = 1; 1085 vflag = 0; 1086 } 1087 break; 1088 1089 case 'N': 1090 lxget( c, LEXLET ); 1091 if( strcmp( yytext, "NOTREACHED" ) ) break; 1092 reached = 0; 1093 break; 1094 #endif 1095 1096 case '\n': 1097 case EOF: 1098 continue; 1099 } 1100 while( (c = getchar()) != '\n' && c != EOF ) 1101 ; 1102 continue; 1103 } 1104 if( c == 'l' ){ 1105 /* #line -- just like # */ 1106 lxget( c, LEXLET ); 1107 if( strcmp( yytext, "line" ) ){ 1108 werror( "%s: undefined control", yytext ); 1109 while( (c = getchar()) != '\n' && c != EOF ) 1110 ; 1111 continue; 1112 } 1113 lxget( ' ', LEXWS ); 1114 c = getchar(); 1115 } 1116 if( !isdigit(c) ){ 1117 if( isalpha(c) ){ 1118 lxget( c, LEXLET ); 1119 werror( "%s: undefined control", yytext ); 1120 } 1121 while( c != '\n' && c != EOF ) 1122 c = getchar(); 1123 continue; 1124 } 1125 1126 val = 0; 1127 do { 1128 val = val*10+ c - '0'; 1129 } 1130 while( isdigit( c = getchar() ) ); 1131 1132 if( c == EOF ) 1133 continue; 1134 ungetc( c, stdin ); 1135 lineno = val; 1136 lxget( ' ', LEXWS ); 1137 if( (c=getchar()) != '\n' && c != EOF ){ 1138 for( cp=ftitle; c!=EOF && c!='\n'; c=getchar(),++cp ){ 1139 *cp = c; 1140 } 1141 *cp = '\0'; 1142 #ifndef LINT 1143 if (ititle[0] == '\0') { 1144 cp = ftitle; 1145 cq = ititle; 1146 while ( *cp ) 1147 *cq++ = *cp++; 1148 *cq = '\0'; 1149 *--cq = '\0'; 1150 #ifndef FLEXNAMES 1151 for ( cp = ititle+1; *(cp-1); cp += 8 ) { 1152 pstab(cp, N_SO); 1153 if (gdebug) printf("0,0,LL%d\n", labelno); 1154 } 1155 #else 1156 pstab(ititle+1, N_SO); 1157 if (gdebug) printf("0,0,LL%d\n", labelno); 1158 #endif 1159 1160 *cq = '"'; 1161 printf("LL%d:\n", labelno++); 1162 } 1163 #endif 1164 } 1165 } 1166 } 1167 1168 #ifdef FLEXNAMES 1169 #define NSAVETAB 4096 1170 char *savetab; 1171 unsigned saveleft; 1172 char *malloc(); 1173 char *calloc(); 1174 char *strncpy(); 1175 1176 char * 1177 savestr(cp) 1178 register char *cp; 1179 { 1180 register int len; 1181 1182 len = strlen(cp) + 1; 1183 if (len > saveleft) { 1184 saveleft = NSAVETAB; 1185 if (len > saveleft) 1186 saveleft = len; 1187 savetab = malloc(saveleft); 1188 if (savetab == 0) 1189 cerror("Ran out of memory (savestr)"); 1190 } 1191 (void) strncpy(savetab, cp, len); 1192 cp = savetab; 1193 savetab += len; 1194 saveleft -= len; 1195 return (cp); 1196 } 1197 1198 /* 1199 * The definition for the segmented hash tables. 1200 */ 1201 #define MAXHASH 20 1202 #define HASHINC 1013 1203 struct ht { 1204 char **ht_low; 1205 char **ht_high; 1206 int ht_used; 1207 } htab[MAXHASH]; 1208 1209 char * 1210 hash(s) 1211 char *s; 1212 { 1213 register char **h; 1214 register i; 1215 register char *cp; 1216 struct ht *htp; 1217 int sh; 1218 1219 /* 1220 * The hash function is a modular hash of 1221 * the sum of the characters with the sum 1222 * doubled before each successive character 1223 * is added. 1224 */ 1225 cp = s; 1226 i = 0; 1227 while (*cp) 1228 i = i*2 + *cp++; 1229 sh = (i&077777) % HASHINC; 1230 cp = s; 1231 /* 1232 * There are as many as MAXHASH active 1233 * hash tables at any given point in time. 1234 * The search starts with the first table 1235 * and continues through the active tables 1236 * as necessary. 1237 */ 1238 for (htp = htab; htp < &htab[MAXHASH]; htp++) { 1239 if (htp->ht_low == 0) { 1240 register char **hp = 1241 (char **) calloc(sizeof (char **), HASHINC); 1242 if (hp == 0) 1243 cerror("ran out of memory (hash)"); 1244 htp->ht_low = hp; 1245 htp->ht_high = htp->ht_low + HASHINC; 1246 } 1247 h = htp->ht_low + sh; 1248 /* 1249 * quadratic rehash increment 1250 * starts at 1 and incremented 1251 * by two each rehash. 1252 */ 1253 i = 1; 1254 do { 1255 if (*h == 0) { 1256 if (htp->ht_used > (HASHINC * 3)/4) 1257 break; 1258 htp->ht_used++; 1259 *h = savestr(cp); 1260 return (*h); 1261 } 1262 if (**h == *cp && strcmp(*h, cp) == 0) 1263 return (*h); 1264 h += i; 1265 i += 2; 1266 if (h >= htp->ht_high) 1267 h -= HASHINC; 1268 } while (i < HASHINC); 1269 } 1270 cerror("ran out of hash tables"); 1271 /*NOTREACHED*/ 1272 } 1273 #endif 1274