|
|
1.1 ! root 1: /* ! 2: * This file contains all of the lexical analysis routines ! 3: * for the portable C compiler. ! 4: */ ! 5: #ifdef vax ! 6: #include "INC$LIB:cc0.h" ! 7: #else ! 8: #include "cc0.h" ! 9: #endif ! 10: ! 11: /* ! 12: * Character classes. ! 13: * Indexed by ASCII character code. ! 14: */ ! 15: unsigned char ct[] = { ! 16: JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, ! 17: JUNK, SKIP, SKIP, SKIP, SKIP, SKIP, JUNK, JUNK, ! 18: JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, ! 19: JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, ! 20: SKIP, NOT, STRING, SHARP, JUNK, REM, AND, QUOTE, ! 21: LPAREN, RPAREN, MUL, ADD, COMMA, SUB, DOT, DIV, ! 22: CON, CON, CON, CON, CON, CON, CON, CON, ! 23: CON, CON, COLON, SEMI, LT, ASSIGN, GT, QUEST, ! 24: JUNK, ID, ID, ID, ID, ID, ID, ID, ! 25: ID, ID, ID, ID, ID, ID, ID, ID, ! 26: ID, ID, ID, ID, ID, ID, ID, ID, ! 27: ID, ID, ID, LBRACK, BACKDIV,RBRACK, XOR, ID, ! 28: JUNK, ID, ID, ID, ID, ID, ID, ID, ! 29: ID, ID, ID, ID, ID, ID, ID, ID, ! 30: ID, ID, ID, ID, ID, ID, ID, ID, ! 31: ID, ID, ID, LBRACE, OR, RBRACE, COM, JUNK, ! 32: HIGH0, HIGH0, HIGH0, HIGH0, HIGH0, HIGH0, HIGH0, HIGH0, ! 33: HIGH0, HIGH0, HIGH0, HIGH0, HIGH0, HIGH0, HIGH0, HIGH0, ! 34: HIGH0, HIGH0, HIGH0, HIGH0, HIGH0, HIGH0, HIGH0, HIGH0, ! 35: HIGH0, HIGH0, HIGH0, HIGH0, HIGH0, HIGH0, HIGH0, HIGH0, ! 36: HIGH1, HIGH1, HIGH1, HIGH1, HIGH1, HIGH1, HIGH1, HIGH1, ! 37: HIGH1, HIGH1, HIGH1, HIGH1, HIGH1, HIGH1, HIGH1, HIGH1, ! 38: HIGH1, HIGH1, HIGH1, HIGH1, HIGH1, HIGH1, HIGH1, HIGH1, ! 39: HIGH1, HIGH1, HIGH1, HIGH1, HIGH1, HIGH1, HIGH1, HIGH1, ! 40: HIGH2, HIGH2, HIGH2, HIGH2, HIGH2, HIGH2, HIGH2, HIGH2, ! 41: HIGH2, HIGH2, HIGH2, HIGH2, HIGH2, HIGH2, HIGH2, HIGH2, ! 42: HIGH2, HIGH2, HIGH2, HIGH2, HIGH2, HIGH2, HIGH2, HIGH2, ! 43: HIGH2, HIGH2, HIGH2, HIGH2, HIGH2, HIGH2, HIGH2, HIGH2, ! 44: HIGH3, HIGH3, HIGH3, HIGH3, HIGH3, HIGH3, HIGH3, HIGH3, ! 45: HIGH3, HIGH3, HIGH3, HIGH3, HIGH3, HIGH3, HIGH3, HIGH3, ! 46: HIGH3, HIGH3, HIGH3, HIGH3, HIGH3, HIGH3, HIGH3, HIGH3, ! 47: HIGH3, HIGH3, HIGH3, HIGH3, HIGH3, HIGH3, HIGH3, HIGH3 ! 48: }; ! 49: ! 50: /* ! 51: * Read and decode the next token of the input. ! 52: * The token is returned and stored in 's'. ! 53: * Identifiers are packed into 'id' ! 54: * and their hash table slot is stashed in 'idhash'. ! 55: * Integers are returned in 'ival', ! 56: * long integers in 'lval' and doubles in 'dval'. ! 57: */ ! 58: lex() ! 59: { ! 60: register SYM *sp; ! 61: register int c; ! 62: register int n; ! 63: ! 64: for (;;) { ! 65: if ((c=get()) < 0) ! 66: return (s = EOF); ! 67: switch (s = ct[c]) { ! 68: ! 69: case SKIP: ! 70: continue; ! 71: ! 72: case QUOTE: ! 73: n = 0; ! 74: lval = 0; ! 75: instring = c; /* to allow high-bit chars */ ! 76: while ((c = getmap('\'')) >= 0) { ! 77: lval <<= 8; ! 78: lval |= c; ! 79: ++n; ! 80: } ! 81: instring = 0; ! 82: ival = lval; ! 83: tval = T_INT; ! 84: s = ICON; ! 85: #if 0 ! 86: switch (n) { ! 87: case 0: ! 88: cwarn("empty character constant"); ! 89: break; ! 90: case 2: ! 91: cwarn("multiple character constant"); ! 92: tval = T_INT; ! 93: break; ! 94: case 1: ! 95: break; ! 96: case 3: ! 97: case 4: ! 98: cwarn("character constant promoted to long"); ! 99: tval = T_LONG; ! 100: s = LCON; ! 101: break; ! 102: default: ! 103: cerror("character constant overflows long"); ! 104: tval = T_LONG; ! 105: s = LCON; ! 106: break; ! 107: } ! 108: #else ! 109: if (n != 1) ! 110: cerror("multiple character constant"); ! 111: #endif ! 112: break; ! 113: ! 114: case ADD: ! 115: if (nextis('+')) ! 116: s = INCBEF; ! 117: break; ! 118: ! 119: case SUB: ! 120: if (nextis('-')) ! 121: s = DECBEF; ! 122: else if (nextis('>')) ! 123: s = ARROW; ! 124: break; ! 125: ! 126: case LT: ! 127: if (nextis('=')) ! 128: s = LE; ! 129: else if (nextis('<')) ! 130: s = SHL; ! 131: break; ! 132: ! 133: case GT: ! 134: if (nextis('=')) ! 135: s = GE; ! 136: else if (nextis('>')) ! 137: s = SHR; ! 138: break; ! 139: ! 140: case ASSIGN: ! 141: if (nextis('=')) ! 142: s = EQ; ! 143: break; ! 144: ! 145: case NOT: ! 146: if (nextis('=')) ! 147: s = NE; ! 148: break; ! 149: ! 150: case AND: ! 151: if (nextis('&')) ! 152: s = ANDAND; ! 153: break; ! 154: ! 155: case OR: ! 156: if (nextis('|')) ! 157: s = OROR; ! 158: break; ! 159: ! 160: case DOT: ! 161: c = get(); ! 162: if (c<0 || ct[c]!=CON) { ! 163: unget(c); ! 164: break; ! 165: } ! 166: getnum(c, 1); ! 167: break; ! 168: ! 169: case CON: ! 170: getnum(c, 0); ! 171: break; ! 172: ! 173: case ID: ! 174: if (expand(c)) ! 175: continue; ! 176: for (sp = idp->t_sym; sp != NULL; sp = sp->s_sp) ! 177: if (sp->s_slevel == SL_KEY) { ! 178: s = sp->s_value; ! 179: break; ! 180: } ! 181: break; ! 182: ! 183: case JUNK: ! 184: case HIGH0: ! 185: case HIGH1: ! 186: case HIGH2: ! 187: case HIGH3: ! 188: cerror("illegal character (%d decimal)", c); ! 189: continue; ! 190: ! 191: } ! 192: if ((s>=ADD && s<=SHR) && nextis('=')) ! 193: s += AADD-ADD; ! 194: return (s); ! 195: } ! 196: } ! 197: ! 198: /* ! 199: * Test if the next character in the input is 'n'. ! 200: * If it is, eat it up and return true; ! 201: * otherwise put it back and return false. ! 202: */ ! 203: nextis(n) int n; ! 204: { ! 205: register int c; ! 206: ! 207: if ((c = get()) == n) ! 208: return (1); ! 209: unget(c); ! 210: return (0); ! 211: } ! 212: ! 213: /* ! 214: * Get the next non blank character from the input. ! 215: * This is for cpp, so we do not pass newline. ! 216: */ ! 217: getnb() ! 218: { ! 219: register int c; ! 220: ! 221: while ((c = get())==' ' || c=='\t') ! 222: ; ! 223: return (c); ! 224: } ! 225: ! 226: /* ! 227: * Get the next non-skip character. ! 228: * Different from getnb() which chokes ! 229: * on newline. ! 230: */ ! 231: getskip() ! 232: { ! 233: register int c; ! 234: ! 235: while ((c = get()) > 0 && ct[c] == SKIP) ! 236: ; ! 237: return c; ! 238: } ! 239: ! 240: /* ! 241: * Peek ahead in the input (ignoring whitespace) ! 242: * to see if the next character is 'n'. ! 243: * True return it it is. ! 244: * The character is left in the input stream. ! 245: * This routine is used to look for the ':' after labels ! 246: * and the '(' after undefined names in expressions. ! 247: */ ! 248: spnextis(n) int n; ! 249: { ! 250: register int c; ! 251: ! 252: while ((c=get()) >= 0) { ! 253: if (ct[c] != SKIP) { ! 254: unget(c); ! 255: if (c == n) ! 256: return (1); ! 257: return (0); ! 258: } ! 259: } ! 260: return (0); ! 261: } ! 262: ! 263: /* ! 264: * This routine is like lex(), except that it correctly skips ! 265: * over any strings in the input. ! 266: * Used during error recovery. ! 267: */ ! 268: skip() ! 269: { ! 270: if (s == STRING) ! 271: while (getmap('\"') >= 0) ! 272: ; ! 273: lex(); ! 274: } ! 275: ! 276: /* ! 277: * Read the next character from a string or a character constant. ! 278: * Return -1 when either end of file or the delimiter 'd' is encountered. ! 279: */ ! 280: getmap(d) int d; ! 281: { ! 282: register int c, n, v; ! 283: ! 284: if ((c=get()) == d) ! 285: return (-1); ! 286: if (c<0 || c=='\n') { ! 287: unget(c); ! 288: cerror("nonterminated string or character constant"); ! 289: return (-1); ! 290: } ! 291: if (c == '\\') { ! 292: c = get(); ! 293: switch (c) { ! 294: ! 295: case 'a': ! 296: c = '\07'; ! 297: break; ! 298: ! 299: case 'b': ! 300: c = '\b'; ! 301: break; ! 302: ! 303: case 'f': ! 304: c = '\f'; ! 305: break; ! 306: ! 307: case 'n': ! 308: c = '\n'; ! 309: break; ! 310: ! 311: case 'r': ! 312: c = '\r'; ! 313: break; ! 314: ! 315: case 't': ! 316: c = '\t'; ! 317: break; ! 318: ! 319: case 'v': ! 320: c = '\013'; ! 321: break; ! 322: ! 323: case 'x': ! 324: notbook(); ! 325: c = get(); ! 326: n = 0; ! 327: v = 0; ! 328: while (++n<=3 ! 329: && ( (c>='0' && c<='9') ! 330: || (c>='A' && c<='F') ! 331: || (c>='a' && c<='f') )) { ! 332: v <<= 4; ! 333: if (c>='0' && c<='9') ! 334: v += c - '0'; ! 335: else if (c>='A' && c<='F') ! 336: v += c - 'A' + 10; ! 337: else ! 338: v += c - 'a' + 10; ! 339: c = get(); ! 340: } ! 341: unget(c); ! 342: c = v; ! 343: break; ! 344: ! 345: case '0': ! 346: case '1': ! 347: case '2': ! 348: case '3': ! 349: case '4': ! 350: case '5': ! 351: case '6': ! 352: case '7': ! 353: n = 0; ! 354: v = 0; ! 355: while (++n<=3 && c>='0' && c<='7') { ! 356: v = (v<<3) + c - '0'; ! 357: c = get(); ! 358: } ! 359: unget(c); ! 360: c = v; ! 361: break; ! 362: } ! 363: } ! 364: return (c); ! 365: } ! 366: ! 367: /* ! 368: * Read an identifier into id[] ! 369: * and set idhash. ! 370: */ ! 371: getid(ch) int ch; ! 372: { ! 373: { ! 374: register char *p; ! 375: register int c; ! 376: c = ch; ! 377: p = id; ! 378: idhash = 0; ! 379: idsize = 0; ! 380: idhide = -1; /* Universal */ ! 381: do { ! 382: if (p < &id[NCSYMB-1]) { ! 383: *p++ = c; ! 384: idhash += c; ! 385: idsize += 1; ! 386: } ! 387: if ((c = get()) >= SET0) { ! 388: idhide = hideint(c, idhide); ! 389: c = get(); ! 390: } ! 391: } while (c>=0 && (ct[c]==ID || ct[c]==CON)); ! 392: unget(c); ! 393: if (idhide == -1) ! 394: idhide = SET0; /* Empty */ ! 395: *p++ = 0; ! 396: *p++ = 0; ! 397: *p++ = 0; ! 398: } ! 399: { ! 400: register TOK *tp, **tpp; ! 401: ! 402: idhash %= NHASH; ! 403: for (tpp = hash0+idhash; (tp = *tpp) != NULL; tpp = &tp->t_tp) ! 404: if (ideq(tp)) ! 405: break; ! 406: if (tp == NULL) ! 407: *tpp = tp = newtoken(); ! 408: idp = tp; ! 409: } ! 410: } ! 411: ! 412: setid(cp) char *cp; ! 413: { ! 414: { ! 415: register char *p1, *p2; ! 416: register int c; ! 417: ! 418: p1 = cp; ! 419: p2 = id; ! 420: idhash = 0; ! 421: idsize = 0; ! 422: while (c = *p1++) { ! 423: if (p2 < &id[NCSYMB-1]) { ! 424: *p2++ = c; ! 425: idhash += c; ! 426: idsize += 1; ! 427: } ! 428: } ! 429: *p2 = 0; ! 430: } ! 431: { ! 432: register TOK *tp, **tpp; ! 433: ! 434: idhash %= NHASH; ! 435: for (tpp = hash0+idhash; (tp = *tpp) != NULL; tpp = &tp->t_tp) ! 436: if (ideq(tp)) ! 437: break; ! 438: if (tp == NULL) ! 439: *tpp = tp = newtoken(); ! 440: idp = tp; ! 441: } ! 442: } ! 443: ! 444: /* ! 445: * Read number into id[]. ! 446: * Set 's' appropriately. ! 447: */ ! 448: getnum(c, dotf) register int c; int dotf; ! 449: { ! 450: register char *np; ! 451: int expf, sgnf, ntlf, base; ! 452: int islong, isunsigned, isfloat; ! 453: long n; ! 454: static char ulong[] = "unsigned long"; ! 455: # define slong (ulong+9) ! 456: #if NATIVEFP ! 457: double d; ! 458: char *cp, *dp; ! 459: extern double atof(); ! 460: #endif ! 461: ! 462: expf = 0; ! 463: ntlf = 0; ! 464: sgnf = 1; ! 465: base = 10; ! 466: islong = 0; ! 467: isunsigned = 0; ! 468: isfloat = 0; ! 469: np = id; ! 470: n = 0; ! 471: if (dotf) ! 472: *np++ = '.'; ! 473: if (dotf==0 && c=='0') { ! 474: base = 8; ! 475: if ((c = get()) == 'x' || c == 'X') { ! 476: *np++ = '0'; ! 477: *np++ = c; ! 478: base = 16; ! 479: c = get(); ! 480: } else { ! 481: unget(c); ! 482: c = '0'; ! 483: } ! 484: } ! 485: do { ! 486: if (base!=16 && c=='.') { ! 487: if (dotf++) ! 488: break; ! 489: } else if (c=='+' || c=='-') { ! 490: if (sgnf++) ! 491: break; ! 492: } else if (base!=16 && (c=='e' || c=='E')) { ! 493: if (expf++) ! 494: break; ! 495: sgnf = 0; ! 496: } else if (c<'0' || c>'9') { ! 497: if (base != 16) ! 498: break; ! 499: if (!((c>='A' && c<='F') || (c>='a' && c<='f'))) ! 500: break; ! 501: } else ! 502: ++sgnf; ! 503: if (np < &id[NCSYMB-1]) ! 504: *np++ = c; ! 505: else ! 506: ntlf = 1; ! 507: if (base == 8) ! 508: n <<= 3; ! 509: else if (base == 10) ! 510: n = (n<<3) + (n<<1); ! 511: else ! 512: n <<= 4; ! 513: if (c>='A' && c<='F') ! 514: c -= 'A'-10; ! 515: else if (c>='a' && c<='f') ! 516: c -= 'a'-10; ! 517: else ! 518: c -= '0'; ! 519: n += c; ! 520: } while ((c = get()) >= 0); ! 521: for (;;) { ! 522: if (c=='l' || c=='L') { ! 523: ++islong; ! 524: *np++ = c; ! 525: c = get(); ! 526: } else if (c == 'u' || c == 'U') { ! 527: ++isunsigned; ! 528: *np++ = c; ! 529: c = get(); ! 530: } else if (c == 'f' || c == 'F') { ! 531: ++isfloat; ! 532: *np++ = c; ! 533: c = get(); ! 534: } else { ! 535: unget(c); ! 536: *np = 0; ! 537: break; ! 538: } ! 539: } ! 540: s = ICON; ! 541: tval = T_INT; ! 542: ival = lval = n; ! 543: if (ntlf) { ! 544: cerror("number has too many digits"); ! 545: return; ! 546: } ! 547: if (dotf || expf || isfloat) { ! 548: if (isunsigned || (isfloat+islong > 1)) { ! 549: cerror("illegal floating constant suffix"); ! 550: return; ! 551: } ! 552: tval = isfloat ? T_FLOAT : islong ? T_LDOUBLE : T_DOUBLE; ! 553: #if NATIVEFP ! 554: d = atof(id); ! 555: for (dp = (char *)dval, cp = ((char *)&d)+sizeof(double)-1; cp >= &d; ) ! 556: *dp++ = *cp--; ! 557: #else ! 558: dvalread((char *)dval, id); ! 559: #endif ! 560: s = DCON; ! 561: return; ! 562: } ! 563: if (isunsigned > 1 || islong > 1) { ! 564: cerror("illegal integer constant suffix"); ! 565: return; ! 566: } ! 567: np = NULL; ! 568: if (islong) { ! 569: s = LCON; ! 570: tval = T_LONG; ! 571: if (isunsigned || (n&SLMASK) != 0) ! 572: tval = T_ULONG; ! 573: } else if (isunsigned) { ! 574: tval = T_UINT; ! 575: if ((n&UIMASK) != 0) { ! 576: s = LCON; ! 577: tval = T_ULONG; ! 578: np = ulong; ! 579: } ! 580: } else if (base == 10 && (n&SIMASK) != 0) { ! 581: s = LCON; ! 582: tval = T_LONG; ! 583: np = slong; ! 584: if ((n&SLMASK) != 0) { ! 585: tval = T_ULONG; ! 586: np = ulong; ! 587: } ! 588: } else if ((n&SIMASK) != 0) { ! 589: tval = T_UINT; ! 590: if ((n&UIMASK) != 0) { ! 591: s = LCON; ! 592: tval = T_LONG; ! 593: np = slong; ! 594: if ((n&SLMASK) != 0) { ! 595: tval = T_ULONG; ! 596: np = ulong; ! 597: } ! 598: } ! 599: } ! 600: if (tval == T_ULONG) { ! 601: /* Test for unsigned long overflow */ ! 602: /* and set np = NULL if a diagnostic is given */ ! 603: ; ! 604: } ! 605: if (incpp == 0 && np != NULL && isvariant(VSLCON)) ! 606: cwarn("\"%s\" promoted to %s", id, np); ! 607: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.