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