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