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