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