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