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