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