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