1 #ifndef lint 2 static char *sccsid ="@(#)scan.c 2.4 (Berkeley) 04/22/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 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 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; /* 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 if (hflag) 341 uerror("superfluous backslash in string/character constant"); 342 /*FALLTHROUGH*/ 343 case '\\': 344 case '\"': 345 case '\'': 346 val = c; 347 goto mkcc; 348 349 case 'n': 350 val = '\n'; 351 goto mkcc; 352 353 case 'r': 354 val = '\r'; 355 goto mkcc; 356 357 case 'b': 358 val = '\b'; 359 goto mkcc; 360 361 case 't': 362 val = '\t'; 363 goto mkcc; 364 365 case 'f': 366 val = '\f'; 367 goto mkcc; 368 369 case 'v': 370 val = '\013'; 371 goto mkcc; 372 373 case '0': 374 case '1': 375 case '2': 376 case '3': 377 case '4': 378 case '5': 379 case '6': 380 case '7': 381 val = c-'0'; 382 c=getchar(); /* try for 2 */ 383 if( lxmask[c+1] & LEXOCT ){ 384 val = (val<<3) | (c-'0'); 385 c = getchar(); /* try for 3 */ 386 if( lxmask[c+1] & LEXOCT ){ 387 val = (val<<3) | (c-'0'); 388 } 389 else ungetc( c ,stdin); 390 } 391 else ungetc( c ,stdin); 392 393 goto mkcc1; 394 395 } 396 default: 397 val =c; 398 mkcc: 399 val = CCTRANS(val); 400 mkcc1: 401 if( lxmatch == '\'' ){ 402 val = CHARCAST(val); /* it is, after all, a "character" constant */ 403 makecc( val, i ); 404 } 405 else { /* stash the byte into the string */ 406 if( strflg ) { 407 if( ct==0 || i<ct ) putbyte( val ); 408 else if( i == ct ) werror( "non-null byte ignored in string initializer" ); 409 } 410 else bycode( val, i ); 411 } 412 ++i; 413 continue; 414 } 415 break; 416 } 417 /* end of string or char constant */ 418 419 if( lxmatch == '"' ){ 420 if( strflg ){ /* end the string */ 421 if( ct==0 || i<ct ) putbyte( 0 ); /* the null at the end */ 422 } 423 else { /* the initializer gets a null byte */ 424 bycode( 0, i++ ); 425 bycode( -1, i ); 426 dimtab[curdim] = i; /* in case of later sizeof ... */ 427 } 428 } 429 else { /* end the character constant */ 430 if( i == 0 ) uerror( "empty character constant" ); 431 if( i>(SZINT/SZCHAR) || ( (pflag||hflag)&&i>1) ) 432 uerror( "too many characters in character constant" ); 433 } 434 } 435 436 lxcom(){ 437 register c; 438 /* saw a /*: process a comment */ 439 440 for(;;){ 441 442 switch( c = getchar() ){ 443 444 case EOF: 445 uerror( "unexpected EOF" ); 446 return; 447 448 case '\n': 449 ++lineno; 450 451 default: 452 continue; 453 454 case '*': 455 if( (c = getchar()) == '/' ) return; 456 else ungetc( c ,stdin); 457 continue; 458 459 # ifdef LINT 460 case 'V': 461 lxget( c, LEXLET|LEXDIG ); 462 { 463 extern int vaflag; 464 int i; 465 i = yytext[7]?yytext[7]-'0':0; 466 yytext[7] = '\0'; 467 if( strcmp( yytext, "VARARGS" ) ) continue; 468 vaflag = i; 469 continue; 470 } 471 case 'L': 472 lxget( c, LEXLET ); 473 if( strcmp( yytext, "LINTLIBRARY" ) ) continue; 474 { 475 extern int libflag; 476 libflag = 1; 477 } 478 continue; 479 480 case 'A': 481 lxget( c, LEXLET ); 482 if( strcmp( yytext, "ARGSUSED" ) ) continue; 483 { 484 extern int argflag, vflag; 485 argflag = 1; 486 vflag = 0; 487 } 488 continue; 489 490 case 'N': 491 lxget( c, LEXLET ); 492 if( strcmp( yytext, "NOTREACHED" ) ) continue; 493 reached = 0; 494 continue; 495 # endif 496 } 497 } 498 } 499 500 yylex(){ 501 for(;;){ 502 503 register lxchar; 504 register struct lxdope *p; 505 register struct symtab *sp; 506 int id; 507 508 switch( (p=lxcp[(lxchar=getchar())+1])->lxact ){ 509 510 onechar: 511 ungetc( lxchar ,stdin); 512 513 case A_1C: 514 /* eat up a single character, and return an opcode */ 515 516 yylval.intval = p->lxval; 517 return( p->lxtok ); 518 519 case A_ERR: 520 uerror( "illegal character: %03o (octal)", lxchar ); 521 break; 522 523 case A_LET: 524 /* collect an identifier, check for reserved word, and return */ 525 lxget( lxchar, LEXLET|LEXDIG ); 526 if( (lxchar=lxres()) > 0 ) return( lxchar ); /* reserved word */ 527 if( lxchar== 0 ) continue; 528 #ifdef FLEXNAMES 529 id = lookup( hash(yytext), 530 #else 531 id = lookup( yytext, 532 #endif 533 /* tag name for struct/union/enum */ 534 (stwart&TAGNAME)? STAG: 535 /* member name for struct/union */ 536 (stwart&(INSTRUCT|INUNION|FUNNYNAME))?SMOS:0 ); 537 sp = &stab[id]; 538 if( sp->sclass == TYPEDEF && !stwart ){ 539 stwart = instruct; 540 yylval.nodep = mkty( sp->stype, sp->dimoff, sp->sizoff ); 541 return( TYPE ); 542 } 543 stwart = (stwart&SEENAME) ? instruct : 0; 544 yylval.intval = id; 545 return( NAME ); 546 547 case A_DIG: 548 /* collect a digit string, then look at last one... */ 549 lastcon = 0; 550 lxget( lxchar, LEXDIG ); 551 switch( lxchar=getchar() ){ 552 553 case 'x': 554 case 'X': 555 if( yytext[0] != '0' && !yytext[1] ) uerror( "illegal hex constant" ); 556 lxmore( lxchar, LEXHEX ); 557 /* convert the value */ 558 { 559 register char *cp; 560 for( cp = yytext+2; *cp; ++cp ){ 561 /* this code won't work for all wild character sets, 562 but seems ok for ascii and ebcdic */ 563 lastcon <<= 4; 564 if( isdigit( *cp ) ) lastcon += *cp-'0'; 565 else if( isupper( *cp ) ) lastcon += *cp - 'A'+ 10; 566 else lastcon += *cp - 'a'+ 10; 567 } 568 } 569 570 hexlong: 571 /* criterion for longness for hex and octal constants is that it 572 fit within 0177777 */ 573 if( lastcon & ~0177777L ) yylval.intval = 1; 574 else yylval.intval = 0; 575 576 goto islong; 577 578 case '.': 579 lxmore( lxchar, LEXDIG ); 580 581 getfp: 582 if( (lxchar=getchar()) == 'e' || lxchar == 'E' ){ /* exponent */ 583 584 case 'e': 585 case 'E': 586 if( (lxchar=getchar()) == '+' || lxchar == '-' ){ 587 *lxgcp++ = 'e'; 588 } 589 else { 590 ungetc(lxchar,stdin); 591 lxchar = 'e'; 592 } 593 lxmore( lxchar, LEXDIG ); 594 /* now have the whole thing... */ 595 } 596 else { /* no exponent */ 597 ungetc( lxchar ,stdin); 598 } 599 return( isitfloat( yytext ) ); 600 601 default: 602 ungetc( lxchar ,stdin); 603 if( yytext[0] == '0' ){ 604 /* convert in octal */ 605 register char *cp; 606 for( cp = yytext+1; *cp; ++cp ){ 607 lastcon <<= 3; 608 lastcon += *cp - '0'; 609 } 610 goto hexlong; 611 } 612 else { 613 /* convert in decimal */ 614 register char *cp; 615 for( cp = yytext; *cp; ++cp ){ 616 lastcon = lastcon * 10 + *cp - '0'; 617 } 618 } 619 620 /* decide if it is long or not (decimal case) */ 621 622 /* if it is positive and fits in 15 bits, or negative and 623 and fits in 15 bits plus an extended sign, it is int; otherwise long */ 624 /* if there is an l or L following, all bets are off... */ 625 626 { CONSZ v; 627 v = lastcon & ~077777L; 628 if( v == 0 || v == ~077777L ) yylval.intval = 0; 629 else yylval.intval = 1; 630 } 631 632 islong: 633 /* finally, look for trailing L or l */ 634 if( (lxchar = getchar()) == 'L' || lxchar == 'l' ) yylval.intval = 1; 635 else ungetc( lxchar ,stdin); 636 return( ICON ); 637 } 638 639 case A_DOT: 640 /* look for a dot: if followed by a digit, floating point */ 641 lxchar = getchar(); 642 if( lxmask[lxchar+1] & LEXDIG ){ 643 ungetc(lxchar,stdin); 644 lxget( '.', LEXDIG ); 645 goto getfp; 646 } 647 stwart = FUNNYNAME; 648 goto onechar; 649 650 case A_STR: 651 /* string constant */ 652 lxmatch = '"'; 653 return( STRING ); 654 655 case A_CC: 656 /* character constant */ 657 lxmatch = '\''; 658 lastcon = 0; 659 lxstr(0); 660 yylval.intval = 0; 661 return( ICON ); 662 663 case A_BCD: 664 { 665 register i; 666 int j; 667 for( i=0; i<LXTSZ; ++i ){ 668 if( ( j = getchar() ) == '`' ) break; 669 if( j == '\n' ){ 670 uerror( "newline in BCD constant" ); 671 break; 672 } 673 yytext[i] = j; 674 } 675 yytext[i] = '\0'; 676 if( i>6 ) uerror( "BCD constant exceeds 6 characters" ); 677 # ifdef gcos 678 else strtob( yytext, &lastcon, i ); 679 lastcon >>= 6*(6-i); 680 # else 681 uerror( "gcos BCD constant illegal" ); 682 # endif 683 yylval.intval = 0; /* not long */ 684 return( ICON ); 685 } 686 687 case A_SL: 688 /* / */ 689 if( (lxchar=getchar()) != '*' ) goto onechar; 690 lxcom(); 691 case A_WS: 692 continue; 693 694 case A_NL: 695 ++lineno; 696 lxtitle(); 697 continue; 698 699 case A_NOT: 700 /* ! */ 701 if( (lxchar=getchar()) != '=' ) goto onechar; 702 yylval.intval = NE; 703 return( EQUOP ); 704 705 case A_MI: 706 /* - */ 707 if( (lxchar=getchar()) == '-' ){ 708 yylval.intval = DECR; 709 return( INCOP ); 710 } 711 if( lxchar != '>' ) goto onechar; 712 stwart = FUNNYNAME; 713 yylval.intval=STREF; 714 return( STROP ); 715 716 case A_PL: 717 /* + */ 718 if( (lxchar=getchar()) != '+' ) goto onechar; 719 yylval.intval = INCR; 720 return( INCOP ); 721 722 case A_AND: 723 /* & */ 724 if( (lxchar=getchar()) != '&' ) goto onechar; 725 return( yylval.intval = ANDAND ); 726 727 case A_OR: 728 /* | */ 729 if( (lxchar=getchar()) != '|' ) goto onechar; 730 return( yylval.intval = OROR ); 731 732 case A_LT: 733 /* < */ 734 if( (lxchar=getchar()) == '<' ){ 735 yylval.intval = LS; 736 return( SHIFTOP ); 737 } 738 if( lxchar != '=' ) goto onechar; 739 yylval.intval = LE; 740 return( RELOP ); 741 742 case A_GT: 743 /* > */ 744 if( (lxchar=getchar()) == '>' ){ 745 yylval.intval = RS; 746 return(SHIFTOP ); 747 } 748 if( lxchar != '=' ) goto onechar; 749 yylval.intval = GE; 750 return( RELOP ); 751 752 case A_EQ: 753 /* = */ 754 switch( lxchar = getchar() ){ 755 756 case '=': 757 yylval.intval = EQ; 758 return( EQUOP ); 759 760 case '+': 761 yylval.intval = ASG PLUS; 762 break; 763 764 case '-': 765 yylval.intval = ASG MINUS; 766 767 warn: 768 if( lxmask[ (lxchar=getchar())+1] & (LEXLET|LEXDIG|LEXDOT) ){ 769 werror( "ambiguous assignment: assignment op taken" ); 770 } 771 ungetc( lxchar ,stdin); 772 break; 773 774 case '*': 775 yylval.intval = ASG MUL; 776 goto warn; 777 778 case '/': 779 yylval.intval = ASG DIV; 780 break; 781 782 case '%': 783 yylval.intval = ASG MOD; 784 break; 785 786 case '&': 787 yylval.intval = ASG AND; 788 break; 789 790 case '|': 791 yylval.intval = ASG OR; 792 break; 793 794 case '^': 795 yylval.intval = ASG ER; 796 break; 797 798 case '<': 799 if( (lxchar=getchar()) != '<' ){ 800 uerror( "=<%c illegal", lxchar ); 801 } 802 yylval.intval = ASG LS; 803 break; 804 805 case '>': 806 if( (lxchar=getchar()) != '>' ){ 807 uerror( "=>%c illegal", lxchar ); 808 } 809 yylval.intval = ASG RS; 810 break; 811 812 default: 813 goto onechar; 814 815 } 816 817 return( ASOP ); 818 819 default: 820 cerror( "yylex error, character %03o (octal)", lxchar ); 821 822 } 823 824 /* ordinarily, repeat here... */ 825 cerror( "out of switch in yylex" ); 826 827 } 828 829 } 830 831 struct lxrdope { 832 /* dope for reserved, in alphabetical order */ 833 834 char *lxrch; /* name of reserved word */ 835 short lxract; /* reserved word action */ 836 short lxrval; /* value to be returned */ 837 } lxrdope[] = { 838 839 "asm", AR_A, 0, 840 "auto", AR_CL, AUTO, 841 "break", AR_RW, BREAK, 842 "char", AR_TY, CHAR, 843 "case", AR_RW, CASE, 844 "continue", AR_RW, CONTINUE, 845 "double", AR_TY, DOUBLE, 846 "default", AR_RW, DEFAULT, 847 "do", AR_RW, DO, 848 "extern", AR_CL, EXTERN, 849 "else", AR_RW, ELSE, 850 "enum", AR_E, ENUM, 851 "for", AR_RW, FOR, 852 "float", AR_TY, FLOAT, 853 "fortran", AR_CL, FORTRAN, 854 "goto", AR_RW, GOTO, 855 "if", AR_RW, IF, 856 "int", AR_TY, INT, 857 "long", AR_TY, LONG, 858 "return", AR_RW, RETURN, 859 "register", AR_CL, REGISTER, 860 "switch", AR_RW, SWITCH, 861 "struct", AR_S, 0, 862 "sizeof", AR_RW, SIZEOF, 863 "short", AR_TY, SHORT, 864 "static", AR_CL, STATIC, 865 "typedef", AR_CL, TYPEDEF, 866 "unsigned", AR_TY, UNSIGNED, 867 "union", AR_U, 0, 868 "void", AR_TY, UNDEF, /* tymerge adds FTN */ 869 "while", AR_RW, WHILE, 870 "", 0, 0, /* to stop the search */ 871 }; 872 873 lxres() { 874 /* check to see of yytext is reserved; if so, 875 /* do the appropriate action and return */ 876 /* otherwise, return -1 */ 877 878 register c, ch; 879 register struct lxrdope *p; 880 881 ch = yytext[0]; 882 883 if( !islower(ch) ) return( -1 ); 884 885 switch( ch ){ 886 887 case 'a': 888 c=0; break; 889 case 'b': 890 c=2; break; 891 case 'c': 892 c=3; break; 893 case 'd': 894 c=6; break; 895 case 'e': 896 c=9; break; 897 case 'f': 898 c=12; break; 899 case 'g': 900 c=15; break; 901 case 'i': 902 c=16; break; 903 case 'l': 904 c=18; break; 905 case 'r': 906 c=19; break; 907 case 's': 908 c=21; break; 909 case 't': 910 c=26; break; 911 case 'u': 912 c=27; break; 913 case 'v': 914 c=29; break; 915 case 'w': 916 c=30; break; 917 918 default: 919 return( -1 ); 920 } 921 922 for( p= lxrdope+c; p->lxrch[0] == ch; ++p ){ 923 if( !strcmp( yytext, p->lxrch ) ){ /* match */ 924 switch( p->lxract ){ 925 926 case AR_TY: 927 /* type word */ 928 stwart = instruct; 929 yylval.nodep = mkty( (TWORD)p->lxrval, 0, p->lxrval ); 930 return( TYPE ); 931 932 case AR_RW: 933 { 934 extern int nsizeof; 935 936 if (p->lxrval == SIZEOF) 937 ++nsizeof; 938 } 939 /* ordinary reserved word */ 940 return( yylval.intval = p->lxrval ); 941 942 case AR_CL: 943 /* class word */ 944 yylval.intval = p->lxrval; 945 return( CLASS ); 946 947 case AR_S: 948 /* struct */ 949 stwart = INSTRUCT|SEENAME|TAGNAME; 950 yylval.intval = INSTRUCT; 951 return( STRUCT ); 952 953 case AR_U: 954 /* union */ 955 stwart = INUNION|SEENAME|TAGNAME; 956 yylval.intval = INUNION; 957 return( STRUCT ); 958 959 case AR_E: 960 /* enums */ 961 stwart = SEENAME|TAGNAME; 962 return( yylval.intval = ENUM ); 963 964 case AR_A: 965 /* asm */ 966 asm_esc = 1; /* warn the world! */ 967 lxget( ' ', LEXWS ); 968 if( getchar() != '(' ) goto badasm; 969 lxget( ' ', LEXWS ); 970 if( getchar() != '"' ) goto badasm; 971 # ifndef ONEPASS 972 # ifndef LINT 973 putchar(')'); 974 # endif 975 # endif 976 while( (c=getchar()) != '"' ){ 977 if( c=='\n' || c==EOF ) goto badasm; 978 # ifndef LINT 979 putchar(c); 980 # endif 981 } 982 lxget( ' ', LEXWS ); 983 if( getchar() != ')' ) goto badasm; 984 # ifndef LINT 985 putchar('\n'); 986 # endif 987 return( 0 ); 988 989 badasm: 990 uerror( "bad asm construction" ); 991 return( 0 ); 992 993 default: 994 cerror( "bad AR_?? action" ); 995 } 996 } 997 } 998 return( -1 ); 999 } 1000 1001 extern int labelno; 1002 1003 lxtitle(){ 1004 /* called after a newline; set linenumber and file name */ 1005 1006 register c, val; 1007 register char *cp, *cq; 1008 1009 for(;;){ /* might be several such lines in a row */ 1010 if( (c=getchar()) != '#' ){ 1011 if( c != EOF ) ungetc(c,stdin); 1012 #ifndef LINT 1013 if ( lastloc != PROG) return; 1014 cp = ftitle; 1015 cq = ititle; 1016 while ( *cp ) if (*cp++ != *cq++) return; 1017 if ( *cq ) return; 1018 psline(); 1019 #endif 1020 return; 1021 } 1022 1023 lxget( ' ', LEXWS ); 1024 val = 0; 1025 for( c=getchar(); isdigit(c); c=getchar() ){ 1026 val = val*10+ c - '0'; 1027 } 1028 if( c == EOF ) 1029 continue; 1030 ungetc( c, stdin ); 1031 lineno = val; 1032 lxget( ' ', LEXWS ); 1033 if( (c=getchar()) != '\n' && c != EOF ){ 1034 for( cp=ftitle; c!=EOF && c!='\n'; c=getchar(),++cp ){ 1035 *cp = c; 1036 } 1037 *cp = '\0'; 1038 #ifndef LINT 1039 if (ititle[0] == '\0') { 1040 cp = ftitle; 1041 cq = ititle; 1042 while ( *cp ) 1043 *cq++ = *cp++; 1044 *cq = '\0'; 1045 *--cq = '\0'; 1046 #ifndef FLEXNAMES 1047 for ( cp = ititle+1; *(cp-1); cp += 8 ) { 1048 pstab(cp, N_SO); 1049 if (gdebug) printf("0,0,LL%d\n", labelno); 1050 } 1051 #else 1052 pstab(ititle+1, N_SO); 1053 if (gdebug) printf("0,0,LL%d\n", labelno); 1054 #endif 1055 1056 *cq = '"'; 1057 printf("LL%d:\n", labelno++); 1058 } 1059 #endif 1060 } 1061 } 1062 } 1063 1064 #ifdef FLEXNAMES 1065 #define NSAVETAB 4096 1066 char *savetab; 1067 int saveleft; 1068 1069 char * 1070 savestr(cp) 1071 register char *cp; 1072 { 1073 register int len; 1074 1075 len = strlen(cp) + 1; 1076 if (len > saveleft) { 1077 saveleft = NSAVETAB; 1078 if (len > saveleft) 1079 saveleft = len; 1080 savetab = (char *)malloc(saveleft); 1081 if (savetab == 0) 1082 cerror("Ran out of memory (savestr)"); 1083 } 1084 strncpy(savetab, cp, len); 1085 cp = savetab; 1086 savetab += len; 1087 saveleft -= len; 1088 return (cp); 1089 } 1090 1091 /* 1092 * The definition for the segmented hash tables. 1093 */ 1094 #define MAXHASH 20 1095 #define HASHINC 1013 1096 struct ht { 1097 char **ht_low; 1098 char **ht_high; 1099 int ht_used; 1100 } htab[MAXHASH]; 1101 1102 char * 1103 hash(s) 1104 char *s; 1105 { 1106 register char **h; 1107 register i; 1108 register char *cp; 1109 struct ht *htp; 1110 int sh; 1111 1112 /* 1113 * The hash function is a modular hash of 1114 * the sum of the characters with the sum 1115 * doubled before each successive character 1116 * is added. 1117 */ 1118 cp = s; 1119 i = 0; 1120 while (*cp) 1121 i = i*2 + *cp++; 1122 sh = (i&077777) % HASHINC; 1123 cp = s; 1124 /* 1125 * There are as many as MAXHASH active 1126 * hash tables at any given point in time. 1127 * The search starts with the first table 1128 * and continues through the active tables 1129 * as necessary. 1130 */ 1131 for (htp = htab; htp < &htab[MAXHASH]; htp++) { 1132 if (htp->ht_low == 0) { 1133 register char **hp = 1134 (char **) calloc(sizeof (char **), HASHINC); 1135 if (hp == 0) 1136 cerror("ran out of memory (hash)"); 1137 htp->ht_low = hp; 1138 htp->ht_high = htp->ht_low + HASHINC; 1139 } 1140 h = htp->ht_low + sh; 1141 /* 1142 * quadratic rehash increment 1143 * starts at 1 and incremented 1144 * by two each rehash. 1145 */ 1146 i = 1; 1147 do { 1148 if (*h == 0) { 1149 if (htp->ht_used > (HASHINC * 3)/4) 1150 break; 1151 htp->ht_used++; 1152 *h = savestr(cp); 1153 return (*h); 1154 } 1155 if (**h == *cp && strcmp(*h, cp) == 0) 1156 return (*h); 1157 h += i; 1158 i += 2; 1159 if (h >= htp->ht_high) 1160 h -= HASHINC; 1161 } while (i < HASHINC); 1162 } 1163 cerror("ran out of hash tables"); 1164 } 1165 #endif 1166