|
|
1.1 ! root 1: /* ! 2: * C compiler. ! 3: * Syntax analyser mainline. ! 4: * Impure stuff. ! 5: */ ! 6: #ifdef vax ! 7: #include "INC$LIB:cc0.h" ! 8: #else ! 9: #include "cc0.h" ! 10: #endif ! 11: ! 12: /* ! 13: * Impure areas. ! 14: * All external impure data is here ! 15: * and is reinitialized by the overlaid version of the mainline. ! 16: * This permits the compiler to be called many times if loaded as a big block. ! 17: */ ! 18: #if !OVERLAID ! 19: int line = 1; /* Source line */ ! 20: char file[NFNAME]; /* Source file name */ ! 21: TOK *tfile; /* Source file token */ ! 22: char id[NCSYMB]; /* Identifier buffer */ ! 23: FILE *ifp; /* Input file pointer */ ! 24: FILE *ofp; /* Output file pointer */ ! 25: VARIANT variant; /* Variant template */ ! 26: #endif ! 27: ! 28: /* Cpp variables */ ! 29: char dbuf[NDBUF]; /* Substitution buffer */ ! 30: char *dputp = dbuf; /* Define buffer pointer */ ! 31: char *dpshp = dbuf+sizeof(dbuf); /* Define buffer pointer */ ! 32: DSTACK dstack[NDLEV]; /* Substitution stack */ ! 33: DSTACK *dlistp=dstack; /* Substitution list */ ! 34: DSTACK *dstackp=dstack+NDLEV-1; /* Input stack */ ! 35: ISTACK istack[NLEV]; /* Include stack */ ! 36: ISTACK *istackp=istack+NLEV; /* Include stack pointer */ ! 37: CSTACK cstack[NLEV]; /* Condition stack pointer */ ! 38: CSTACK *cstackp=cstack+NLEV; /* Condition stack pointer */ ! 39: int cstate = 0; /* Conditional state == true */ ! 40: int ndirs; /* Number of include directories */ ! 41: char *incdirs[NDIRS+3]; /* Include directory list */ ! 42: char deftrue[] = "1"; ! 43: char deffalse[] = "0"; ! 44: long curtime; /* NB should be time_t */ ! 45: ! 46: int incpp; /* "in a cpp control" flag */ ! 47: int instring; /* "in a string" flag */ ! 48: int notskip; /* count of not skipped chars */ ! 49: int lastchar; /* Last character read from a file */ ! 50: int ininit; /* "in an initializer" flag */ ! 51: int incase; /* "in a case" flag */ ! 52: int nargs; /* # of args this function */ ! 53: SYM *args[NARGS]; /* The args themselves */ ! 54: int llex; /* Lexical level */ ! 55: int lsym = SL_MOS; /* Symbol table level */ ! 56: ival_t ival; /* Return for lex */ ! 57: lval_t lval; /* Return for lex */ ! 58: dval_t dval; /* Return for lex */ ! 59: short tval; /* Return for lex int/long constant type */ ! 60: unsigned idhash; /* Hash number for symbol */ ! 61: unsigned idhide; /* Hide set for symbol */ ! 62: HIDESET *hidefree, *hidesets; /* Hide set management */ ! 63: int idsize; /* Length of symbol */ ! 64: TOK *idp; /* Hashed identifier token */ ! 65: TOK *hash0[NHASH]; /* Hash table */ ! 66: int cblab; /* Break label */ ! 67: int cclab; /* Continue label */ ! 68: SBLOCK *sbp; /* Current switch block */ ! 69: SYM *cfsym; /* Current symbol */ ! 70: int cflab; /* Current return label */ ! 71: int s; /* Lexical window */ ! 72: ! 73: /* ! 74: * It all starts here. ! 75: * Open the source file. ! 76: * Open the output stream file. ! 77: * Put reserved words into the symbol table. ! 78: * Parse externals until end of file. ! 79: * Finish off the output stream and exit. ! 80: */ ! 81: #if !OVERLAID ! 82: main(argc, argv) ! 83: char *argv[]; ! 84: { ! 85: register char *p; ! 86: register int i; ! 87: extern char *index(); ! 88: extern char *getenv(); ! 89: ! 90: passname = "cc0"; ! 91: if (argc < 4) ! 92: usage(); ! 93: getvariant(argv[1]); ! 94: if ((ifp=fopen(argv[2], "r")) == NULL) { ! 95: fprintf(stderr, "%s: cannot open.\n", argv[2]); ! 96: exit(BAD); ! 97: } ! 98: if (isvariant(VCPP)) { ! 99: if (strcmp(argv[3], "-") == 0) ! 100: ofp = stdout; ! 101: else if ((ofp = fopen(argv[3], "w")) == NULL) { ! 102: fprintf(stderr, "%s: cannot create.\n", argv[3]); ! 103: exit(BAD); ! 104: } ! 105: } else if ((ofp=fopen(argv[3], SWMODE)) == NULL) { ! 106: fprintf(stderr, "%s: cannot create.\n", argv[3]); ! 107: exit(BAD); ! 108: } ! 109: vinit(); ! 110: kinit(); ! 111: time(&curtime); ! 112: newtree(sizeof(TREE)); ! 113: cppd(MACHINE, deftrue); ! 114: cppd(SYSTEM, deftrue); ! 115: cppd(LOCATION, deftrue); ! 116: cppi(argv[2]); /* Source directory will be parsed later */ ! 117: for (i=4; i<argc; ++i) { ! 118: if (argv[i][0] != '-') ! 119: break; ! 120: switch (argv[i][1]) { ! 121: case 'I': cppi(argv[i]+2); break; ! 122: case 'U': cppu(argv[i]+2); break; ! 123: case 'D': ! 124: if (p = index(argv[i]+2, '=')) ! 125: *p++ = 0; ! 126: else ! 127: p = deftrue; ! 128: cppd(argv[i]+2, p); ! 129: break; ! 130: default: ! 131: usage(); ! 132: } ! 133: } ! 134: if ((p = getenv("INCDIR")) == 0) ! 135: p = DEFDISK; ! 136: cppi(p); ! 137: cppi(argv[2]); /* Second copy of source directory */ ! 138: setid(argv[2]); ! 139: setfname(); ! 140: /* Now parse the source file directory */ ! 141: i = 0; ! 142: #if COHERENT ! 143: for (p = argv[2]; *p != 0; p += 1) ! 144: if (*p == '/') ! 145: i = p-argv[2]; ! 146: #endif ! 147: #if GEMDOS || MSDOS ! 148: for (p = argv[2]; *p != 0; p += 1) ! 149: if (*p == '\\') ! 150: i = p-argv[2]; ! 151: #endif ! 152: argv[2][i] = 0; ! 153: emptyfilep(); ! 154: if (notvariant(VCPP)) { ! 155: dbfname(file); ! 156: setmname(); ! 157: labgen = 0; ! 158: oldseg = -1; ! 159: while (lex() != EOF) ! 160: xdef(); ! 161: llex = -1; ! 162: downlex(); ! 163: bput(FINISH); ! 164: } else ! 165: cppwork(); ! 166: if (nerr != 0) ! 167: exit(BAD); ! 168: exit(OK); ! 169: } ! 170: ! 171: /* ! 172: * Print usage message. ! 173: */ ! 174: usage() ! 175: { ! 176: fprintf(stderr, ! 177: "Usage: cc0 variant in out [-Dname[=value]] [-Idirectory] [-Uname]\n" ! 178: ); ! 179: exit(BAD); ! 180: } ! 181: ! 182: #else ! 183: #assert 0 /* This is not ready for the new conventions */ ! 184: /* The argv syntax needs to be worked out */ ! 185: /* Cleaning up the HIDESET and TOK and SYM pools as well */ ! 186: /* ! 187: * This is the mainline of the syntax analysis phase ! 188: * if the compiler is being run as an overlay job. ! 189: * The impure area must be reinitialized if monolithic, ! 190: * because the code can be called again and again. ! 191: */ ! 192: cc0() ! 193: { ! 194: register char *p; ! 195: register int i; ! 196: extern char *index(); ! 197: ! 198: passname = "cc0"; ! 199: if (setjmp(death) != 0) { ! 200: llex = -1; ! 201: downlex(); ! 202: cppfinal(); ! 203: return (ABORT); ! 204: } ! 205: vinit(); ! 206: kinit(); ! 207: cppi(""); ! 208: time(&curtime); ! 209: newtree(sizeof(TREE)); ! 210: for (i=4; i<argc; ++i) { ! 211: if (argv[i][0] != '-') ! 212: break; ! 213: switch (argv[i][1]) { ! 214: case 'I': ! 215: cppi(argv[i]+2); ! 216: break; ! 217: case 'U': ! 218: cppu(argv[i]+2); ! 219: break; ! 220: case 'D': ! 221: if (p = index(argv[i]+2, '=')) ! 222: *p++ = 0; ! 223: else ! 224: p = deftrue; ! 225: cppd(argv[i]+2, p); ! 226: break; ! 227: default: ! 228: cbotch("cpp args"); ! 229: } ! 230: } ! 231: cppi(DEFDISK); ! 232: cppi(""); ! 233: labgen = 0; ! 234: oldseg = -1; ! 235: line = 1; ! 236: #if MONOLITHIC ! 237: incpp = 0; ! 238: instring = 0; ! 239: lastchar = 0; ! 240: ininit = 0; ! 241: incase = 0; ! 242: cblab = 0; ! 243: cclab = 0; ! 244: sbp = NULL; ! 245: cfsym = NULL; ! 246: lsym = SL_MOS; ! 247: ndirs = 0; ! 248: dputp = dbuf; ! 249: dpshp = dbuf+sizeof(dbuf); ! 250: dstackp = dstack + NDLEV-1; ! 251: dlistp = dstack; ! 252: istackp = istack + NLEV; ! 253: cstackp = cstack + NLEV; ! 254: cstate = 0; ! 255: #endif ! 256: setid(argv[2]); ! 257: setfname(); ! 258: if (notvariant(VCPP)) { ! 259: setmname(); ! 260: while (lex() != EOF) ! 261: xdef(); ! 262: llex = -1; ! 263: downlex(); ! 264: bput(FINISH); ! 265: } else ! 266: cppwork(); ! 267: cppfinal(); ! 268: if (nerr != 0) ! 269: return (BAD); ! 270: return (OK); ! 271: } ! 272: #endif ! 273: ! 274: /* ! 275: * Given the file name token in idp, ! 276: * inform the usual parties of the change. ! 277: */ ! 278: setfname() ! 279: { ! 280: tfile = idp; ! 281: strncpy(file, idp->t_id, NFNAME); ! 282: if (notvariant(VCPP)) { ! 283: bput(FNAME); ! 284: sput(file); ! 285: } else if (notvariant(VCPPE)) ! 286: fprintf(ofp, "#line %d \"%s\"\n", line, file); ! 287: } ! 288: ! 289: /* ! 290: * Given a file name string, ! 291: * make up the associated module name. ! 292: * And then send it on it's way. ! 293: * This routine is tinkered for UDI, DEC systems, MS-DOS ! 294: * and for the Coherent-like systems. ! 295: * Of course, the MNAME item is pointless ! 296: * to all systems except .omf, but we do ! 297: * it anyway. ! 298: * NB, id[] is used as a buffer ! 299: * to construct the module name. ! 300: */ ! 301: setmname() ! 302: { ! 303: register char *tp, *p1, *p2; ! 304: ! 305: tp = id; ! 306: p1 = file; ! 307: while (*p1 != 0) ! 308: ++p1; ! 309: p2 = p1; ! 310: while (p1>file ! 311: && (p1[-1]!=':' && p1[-1]!='/' && p1[-1]!=']' && p1[-1]!='\\')) ! 312: --p1; ! 313: while (p2>p1 && p2[0]!='.') ! 314: --p2; ! 315: while (p1 < p2) ! 316: *tp++ = *p1++; ! 317: *tp = 0; ! 318: bput(MNAME); ! 319: sput(id); ! 320: } ! 321: ! 322: /* ! 323: * Process an external declaration. ! 324: * On entry, 's' contains the first token of the external. ! 325: * On exit, 's' contains the last token in the declaration. ! 326: */ ! 327: xdef() ! 328: { ! 329: register SYM *sp; ! 330: SYM *nsp; ! 331: DIM *dp, *ndp; ! 332: INFO *ip; ! 333: int c; ! 334: int t; ! 335: int rf; ! 336: int seg; ! 337: ! 338: if (s == SEMI) ! 339: return; ! 340: gcandt(&c, &t, &dp, &ip, &rf); ! 341: if (c == C_NONE) ! 342: c = C_GDEF; ! 343: else if (c == C_SIN) ! 344: c = C_SEX; ! 345: else if (c!=C_GREF && c!=C_TYPE) { ! 346: cerror("bad external storage class"); ! 347: c = C_GDEF; ! 348: } ! 349: if (s == SEMI) { ! 350: xdropinfo(t, ip); ! 351: return; ! 352: } ! 353: if (t == T_NONE) ! 354: t = T_INT; ! 355: for (;;) { ! 356: if (!gdecl(&nsp, &ndp, dp, c, SL_VAR)) { ! 357: cerror("external syntax"); ! 358: while (s!=EOF && s!=SEMI && s!=LBRACE && s!=RBRACE) ! 359: skip(); ! 360: if (s == LBRACE) ! 361: statement(); ! 362: break; ! 363: } ! 364: sp = nsp; ! 365: sp = declare(sp, c, t, ndp, ip, rf); ! 366: if (c!=C_GREF && sp->s_class!=C_GREF && sp->s_class!=C_TYPE) { ! 367: if (isfunc(sp)) { ! 368: xfunc(sp); ! 369: break; ! 370: } ! 371: seg = SPURE; ! 372: if (s==EOF || s==COMMA || s==SEMI) { ! 373: if ((rf&S_RONLY) == 0) ! 374: seg = SBSS; ! 375: sp->s_seg = seg; ! 376: if (isvariant(VCOMM) ! 377: && sp->s_class == C_GDEF ! 378: && seg == SBSS) { ! 379: sp->s_class = C_GREF; ! 380: bput(COMM); ! 381: nput(sp->s_id); ! 382: } else { ! 383: newseg(seg); ! 384: align(sp); ! 385: xlabel(sp); ! 386: bput(BLOCK); ! 387: } ! 388: zput(ssize(sp)); ! 389: } else { ! 390: if ((rf&S_RONLY) == 0) ! 391: seg = SDATA; ! 392: sp->s_seg = seg; ! 393: newseg(seg); ! 394: align(sp); ! 395: xlabel(sp); ! 396: /* ! 397: * The following gives a warning rather than an ! 398: * error (over steve's objection) so programs ! 399: * using old style initializers e.g. "int i 1;" ! 400: * will compile; see K&R "Anachronisms" p. 212. ! 401: */ ! 402: if (s != ASSIGN) ! 403: cwarn("missing '='"); ! 404: else ! 405: lex(); ! 406: init(sp, sp->s_dp, (sizeof_t)0, 1); ! 407: } ! 408: dbdecl(sp); ! 409: } ! 410: if (s != COMMA) { ! 411: if (s != SEMI) ! 412: cerror("missing semicolon"); ! 413: break; ! 414: } ! 415: lex(); ! 416: } ! 417: xdropinfo(t, ip); ! 418: } ! 419: ! 420: /* ! 421: * Test if the symbol pointed to by 'sp' is a function. ! 422: */ ! 423: isfunc(sp) ! 424: SYM *sp; ! 425: { ! 426: register DIM *dp; ! 427: ! 428: if ((dp=sp->s_dp)!=NULL && dp->d_type==D_FUNC) ! 429: return (1); ! 430: return (0); ! 431: } ! 432: ! 433: /* ! 434: * Compile a function. ! 435: * 'sp' points at the symbol table node for the function name. ! 436: * 's' is the first token after the function declaration. ! 437: */ ! 438: xfunc(sp) ! 439: register SYM *sp; ! 440: { ! 441: register SYM *fsp; ! 442: SYM *nfsp; ! 443: DIM *dp, *fdp; ! 444: INFO *ip; ! 445: int c; ! 446: int t; ! 447: int rf; ! 448: int fline; ! 449: ! 450: fline = line; ! 451: for (;;) { ! 452: gcandt(&c, &t, &dp, &ip, &rf); ! 453: if (c==C_NONE && t==T_NONE) ! 454: break; ! 455: if (c == C_NONE) ! 456: c = C_PAUTO; ! 457: else if (c == C_REG) ! 458: c = C_PREG; ! 459: else { ! 460: cerror("bad argument storage class"); ! 461: c = C_PAUTO; ! 462: } ! 463: if (t == T_NONE) ! 464: t = T_INT; ! 465: for (;;) { ! 466: if (gdecl(&nfsp, &fdp, dp, c, SL_VAR)) { ! 467: fsp = nfsp; ! 468: fsp = declare(fsp, c, t, fdp, ip, rf); ! 469: } ! 470: if (s != COMMA) ! 471: break; ! 472: lex(); ! 473: } ! 474: xdropinfo(t, ip); ! 475: mustbe(SEMI); ! 476: } ! 477: initlocals(); ! 478: bindargs(); ! 479: newseg(SCODE); ! 480: sp->s_seg = SCODE; ! 481: xlabel(sp); ! 482: bput(PROLOG); ! 483: loadargs(); ! 484: dbdecl(sp); ! 485: dbargs(); ! 486: dbstat(LBRACE, line); ! 487: cfsym = sp; ! 488: cflab = newlab(); ! 489: if (s != LBRACE) ! 490: cerror("compound statement required"); ! 491: else ! 492: lex(); ! 493: llex = LL_AUTO; ! 494: locals(); ! 495: putautos(); ! 496: while (s!=EOF && s!=RBRACE) ! 497: statement(); ! 498: if (s != RBRACE) ! 499: cerror("missing right brace"); ! 500: llex = LL_EXT; ! 501: downlex(); ! 502: label(cflab); ! 503: dbstat(RBRACE, line); ! 504: bput(EPILOG); ! 505: cfsym = NULL; ! 506: } ! 507: ! 508: /* ! 509: * Emit an external label. ! 510: */ ! 511: xlabel(sp) ! 512: register SYM *sp; ! 513: { ! 514: bput((sp->s_class==C_GDEF) ? GLABEL : SLABEL); ! 515: nput(sp->s_id); ! 516: } ! 517: ! 518: /* ! 519: * Conditionally drop a structure information block. ! 520: * Sometimes a non null info pointer is a symbol table pointer! ! 521: */ ! 522: xdropinfo(t, ip) ! 523: register int t; ! 524: register INFO *ip; ! 525: { ! 526: if (t==T_FSTRUCT || t==T_FUNION || t==T_FENUM) ! 527: return; ! 528: dropinfo(ip); ! 529: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.