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