|
|
1.1 ! root 1: /* ! 2: * n0/sharp.c ! 3: * C preprocessor. ! 4: * This version of cpp runs as a module of cc0. ! 5: */ ! 6: ! 7: #ifdef vax ! 8: #include "INC$LIB:cc0.h" ! 9: #else ! 10: #include "cc0.h" ! 11: #endif ! 12: ! 13: /* ! 14: * Define a macro. ! 15: */ ! 16: define() ! 17: { ! 18: register int c, narg; ! 19: register CPPSYM *sp; ! 20: register TOK *tp; ! 21: TOK *targ[NARGS]; ! 22: ! 23: c = getnb(); ! 24: if (c < 0 || ct[c] != ID) ! 25: goto bad; ! 26: getid(c); ! 27: tp = idp; ! 28: if ((sp = tp->t_sym) != NULL && sp->s_slevel == SL_CPP) ! 29: ; ! 30: else ! 31: sp = NULL; ! 32: /* ! 33: * Gather up the arguments. ! 34: */ ! 35: narg = -1; ! 36: if ((c = get()) == '(') { ! 37: ++narg; ! 38: do { ! 39: if ((c = getnb()) == ')') ! 40: break; ! 41: if (c<0 || ct[c]!=ID) ! 42: goto bad; ! 43: getid(c); ! 44: if (narg < NARGS) ! 45: targ[narg] = idp; ! 46: ++narg; ! 47: c = getnb(); ! 48: } while (c == ','); ! 49: if (c != ')') ! 50: goto bad; ! 51: c = getnb(); ! 52: } else if (c == ' ' || c == '\t') ! 53: c = getnb(); ! 54: /* ! 55: * Gather macro body. ! 56: */ ! 57: unget(c); ! 58: while ((c = get()) >= 0) { ! 59: switch (ct[c]) { ! 60: case QUOTE: ! 61: case STRING: ! 62: dputstr(c); ! 63: continue; ! 64: case SKIP: ! 65: unget(c = getnb()); ! 66: dputc(' '); ! 67: continue; ! 68: case SHARP: ! 69: if (nextis(c)) { ! 70: if (dputp > dbuf && dputp[-1] == ' ') ! 71: --dputp; ! 72: if (dputp == dbuf) { ! 73: cerror("## at beginning of macro"); ! 74: continue; ! 75: } ! 76: c = getnb(); ! 77: if (c < 0) { ! 78: cerror("## at end of macro"); ! 79: continue; ! 80: } ! 81: unget(c); ! 82: dputc('#'); ! 83: dputc('#'); ! 84: continue; ! 85: } ! 86: c = getnb(); ! 87: if (ct[c] != ID) { ! 88: unget(c); ! 89: c = narg; ! 90: } else { ! 91: getid(c); ! 92: for (c = 0; c < narg; c += 1) ! 93: if (idp == targ[c]) ! 94: break; ! 95: } ! 96: if (c >= narg) ! 97: cerror("parameter must follow #"); ! 98: else { ! 99: dputc('#'); ! 100: dputc(ARG0+c); ! 101: } ! 102: continue; ! 103: case CON: ! 104: case DOT: ! 105: dputnum(c); ! 106: continue; ! 107: case ID: ! 108: getid(c); ! 109: for (c = 0; c < narg; c += 1) ! 110: if (idp == targ[c]) ! 111: break; ! 112: if (c >= narg) ! 113: dputs(id); ! 114: else ! 115: dputc(ARG0+c); ! 116: continue; ! 117: default: ! 118: dputc(c); ! 119: continue; ! 120: } ! 121: } ! 122: if (dputp > dbuf && dputp[-1] == ' ') ! 123: --dputp; ! 124: dputc(0); ! 125: if (sp != NULL) { ! 126: if (sp->s_value > XUSERA ! 127: || strcmp(dbuf, sp->s_body) != 0 ! 128: || sp->s_narg != narg) ! 129: cerror("\"%s\" redefined", tp->t_id); ! 130: #if ANSI_STUPID ! 131: else ! 132: for (c = 0; c < narg; c += 1) ! 133: if (targ[c] != sp->s_targ[c]) ! 134: cerror("\"%s\" redefined", tp->t_id); ! 135: #endif ! 136: } else { ! 137: if (narg > NARGS) { ! 138: cerror("\"%s\" has too many arguments", tp->t_id); ! 139: narg = NARGS; ! 140: } ! 141: sp = newcpp(narg, dbuf, dputp-dbuf); ! 142: sp->s_sp = tp->t_sym; ! 143: tp->t_sym = sp; ! 144: #if ANSI_STUPID ! 145: if (narg > 0) { ! 146: sp->s_targ = new(narg * sizeof(TOK *)); ! 147: for (c = 0; c < sp->s_narg; c += 1) ! 148: sp->s_targ[c] = targ[c]; ! 149: } ! 150: #endif ! 151: } ! 152: dputp = dbuf; ! 153: return; ! 154: ! 155: bad: ! 156: cerror("error in #define syntax"); ! 157: while (c >= 0) ! 158: c = get(); ! 159: dputp = dbuf; ! 160: } ! 161: ! 162: /* ! 163: * Read a file name for #include or #line ! 164: * into dbuf. ! 165: * Return quote character on success, ! 166: * 0 for any kind of error. ! 167: */ ! 168: getfname() ! 169: { ! 170: register int c, d, expanded; ! 171: register char *spshp, *p; ! 172: ! 173: d = expanded = 0; ! 174: spshp = dpshp; ! 175: while ((c = getnb()) >= 0 && ct[c] == ID) { ! 176: if (!expand(c)) ! 177: goto done; /* error, not " or < */ ! 178: ++expanded; ! 179: } ! 180: if (c == '<') ! 181: d = '>'; ! 182: else if (c == '"') ! 183: d = c; ! 184: else ! 185: goto done; ! 186: instring = d; ! 187: while ((c = get()) >= 0 && c != d) { ! 188: if (expanded && ct[c] == ID) { ! 189: if (expand(c)) ! 190: continue; ! 191: for (p = id; c = *p++; dpshc(c)) ! 192: ; ! 193: } else ! 194: dpshc(c); ! 195: } ! 196: instring = 0; ! 197: if (c != d) ! 198: d = 0; ! 199: done: ! 200: while (c >= 0) ! 201: c = get(); ! 202: for (p = spshp; --p >= dpshp; ) ! 203: dputc(*p); ! 204: dputc(0); ! 205: dpshp = spshp; ! 206: return d; ! 207: } ! 208: ! 209: /* ! 210: * File inclusion. ! 211: * incdirs[0] is always "". ! 212: */ ! 213: include() ! 214: { ! 215: register int c, d; ! 216: char *fbuf; ! 217: FILE *fp; ! 218: ! 219: if (istackp == istack) ! 220: cfatal("include stack overflow"); ! 221: if ((d = getfname()) == 0) { ! 222: dputp = dbuf; ! 223: cerror("error in #include syntax"); ! 224: return; ! 225: } ! 226: fp = NULL; ! 227: fbuf = dputp; ! 228: dputp = dbuf; ! 229: for (c = (d != '"'); c < ndirs; c += 1) { ! 230: strcpy(fbuf, incdirs[c]); ! 231: #ifdef COHERENT ! 232: if (fbuf[0] != '\0') ! 233: strcat(fbuf, "/"); ! 234: #endif ! 235: #if GEMDOS || MSDOS ! 236: if (fbuf[0] != 0 && fbuf[strlen(fbuf)-1] != '\\') ! 237: strcat(fbuf, "\\"); ! 238: #endif ! 239: strcat(fbuf, dbuf); ! 240: if ((fp=fopen(fbuf, "r")) != NULL) ! 241: break; ! 242: } ! 243: if (fp == NULL) ! 244: return cfatal("cannot open include file \"%s\"", dbuf); ! 245: --istackp; ! 246: istackp->i_fp = ifp; ! 247: istackp->i_file = tfile; ! 248: istackp->i_line = line; ! 249: istackp->i_cstackp = cstackp; ! 250: ifp = fp; ! 251: line = 1; ! 252: notskip = 0; ! 253: setid(fbuf); ! 254: setfname(); ! 255: emptyfilep(); ! 256: return; ! 257: } ! 258: ! 259: /* ! 260: * Undefine the name in 'id'. ! 261: */ ! 262: undefine() ! 263: { ! 264: register CPPSYM *sp; ! 265: ! 266: if ((sp = idp->t_sym) != NULL ! 267: && sp->s_slevel == SL_CPP ! 268: && sp->s_value <= XUSERA) { ! 269: idp->t_sym = sp->s_sp; ! 270: #if ANSI_STUPID ! 271: if (sp->s_narg > 0) ! 272: free(sp->s_targ); ! 273: #endif ! 274: free(sp); ! 275: } ! 276: } ! 277: ! 278: /* ! 279: * Read a constant expression in cpp. ! 280: * As it turns out, this will accept ! 281: * sizeof() and casts if the terms are ! 282: * defined at the time of the reference. ! 283: */ ! 284: cppexpr() ! 285: { ! 286: TREE *stp; ! 287: register TREE *tp; ! 288: register int con, ocstate; ! 289: ! 290: ocstate = cstate; ! 291: cstate = 0; /* so that comments are ignored */ ! 292: ++incpp; ! 293: stp = talloc(); ! 294: lex(); ! 295: tp = expr(); ! 296: if (tp->t_op == ICON) ! 297: con = tp->t_ival == 0; ! 298: else if (tp->t_op == LCON) ! 299: con = tp->t_lval == 0; ! 300: else if (tp->t_op == ZCON) ! 301: con = tp->t_zval == 0; ! 302: else ! 303: cerror("constant expression required"); ! 304: treset(stp); ! 305: --incpp; ! 306: cstate = ocstate; ! 307: return con; ! 308: } ! 309: ! 310: /* ! 311: * Read a control line. ! 312: * Called for #error, #ident and #pragma. ! 313: */ ! 314: static ! 315: char * ! 316: getline() ! 317: { ! 318: register int c; ! 319: register char *p; ! 320: ! 321: p = dputp; ! 322: while ((c = get()) > 0) ! 323: dputc(c); ! 324: dputc(0); ! 325: dputp = p; ! 326: return p; ! 327: } ! 328: ! 329: /* ! 330: * Entry to process a control line ! 331: * after # has been read. ! 332: * Called from within get(). ! 333: */ ! 334: control() ! 335: { ! 336: register int c; ! 337: register SYM *sp; ! 338: register int true; ! 339: register char *p; ! 340: TOK *tp; ! 341: ! 342: unget(c = getnb()); ! 343: if (c < 0) ! 344: return; ! 345: else if (c >= '0' && c <= '9') ! 346: goto line; /* e.g. "# 123" per ATT, hack... */ ! 347: getid('#'); ! 348: tp = idp; ! 349: if ((sp = idp->t_sym) == NULL || sp->s_slevel != SL_CPP) ! 350: goto bad; ! 351: if (cstate == 0 || sp->s_value >= XIF) ! 352: switch ((int)sp->s_value) { ! 353: ! 354: case XDEFINE: ! 355: define(); ! 356: break; ! 357: ! 358: case XINCLUDE: ! 359: include(); ! 360: return; ! 361: ! 362: case XASSERT: ! 363: if (cppexpr()) ! 364: cerror("#assert failure"); ! 365: break; ! 366: ! 367: case XERROR: ! 368: cfatal("#error: %s", getline()); ! 369: break; ! 370: ! 371: case XPRAGMA: ! 372: p = getline(); ! 373: if (pragma(p) == 0) ! 374: cwarn("unrecognized #pragma ignored: %s", p); ! 375: break; ! 376: ! 377: case XIDENT: /* non-ANSI but hal wants it for RCS */ ! 378: getline(); /* line is ignored */ ! 379: break; ! 380: ! 381: case XIFDEF: ! 382: case XIFNDEF: ! 383: c = getnb(); ! 384: if (ct[c] != ID) ! 385: goto bad; ! 386: getid(c); ! 387: if (sp->s_value == XIFDEF) ! 388: true = ! ((sp = idp->t_sym) != NULL && sp->s_slevel == SL_CPP); ! 389: else ! 390: true = ((sp = idp->t_sym) != NULL && sp->s_slevel == SL_CPP); ! 391: goto new_if; ! 392: ! 393: case XIF: ! 394: /* 0 indicates a true section */ ! 395: /* 1 indicates a false section */ ! 396: /* 2 indicates a section which was true already */ ! 397: true = cstate!=0 ? 1 : cppexpr(); ! 398: new_if: ! 399: if (cstackp == cstack) ! 400: cfatal("conditional stack overflow"); ! 401: --cstackp; ! 402: cstackp->c_op = XIF; ! 403: cstackp->c_state = cstate; ! 404: cstate = cstate!=0 ? 2 : true; ! 405: break; ! 406: ! 407: case XELSE: ! 408: if (cstackp == cstack+NLEV) ! 409: cerror("#else used without #if or #ifdef"); ! 410: else if (cstackp->c_op == XELSE) ! 411: cerror("multiple #else's"); ! 412: else { ! 413: cstackp->c_op = XELSE; ! 414: cstate = cstate==1 ? 0 : 2; ! 415: } ! 416: break; ! 417: ! 418: case XELIF: ! 419: if (cstackp == cstack+NLEV) ! 420: cerror("#elif used without #if or #ifdef"); ! 421: else if (cstackp->c_op == XELSE) ! 422: cerror("#elif used after #else"); ! 423: else { ! 424: cstackp->c_op = XELIF; ! 425: cstate = cstate==1 ? cppexpr() : 2; ! 426: } ! 427: break; ! 428: ! 429: case XENDIF: ! 430: if (cstackp == cstack+NLEV) ! 431: cerror("#endif used without #if or #ifdef"); ! 432: else { ! 433: cstate = cstackp->c_state; ! 434: ++cstackp; ! 435: } ! 436: break; ! 437: ! 438: case XUNDEF: ! 439: if ((c = getnb()) < 0 || ct[c] != ID) ! 440: goto bad; ! 441: getid(c); ! 442: undefine(); ! 443: break; ! 444: ! 445: case XLINE: ! 446: line: ! 447: while ((c = getnb()) >= 0 && ct[c] == ID) ! 448: if ( ! expand(c)) ! 449: goto bad; ! 450: if (c < 0 || ct[c] != CON) ! 451: goto bad; ! 452: getnum(c, 0); ! 453: line = ival; ! 454: c = getfname(); ! 455: dputp = dbuf; ! 456: if (c != 0) { ! 457: setid(dbuf); ! 458: setfname(); ! 459: } ! 460: break; ! 461: ! 462: default: ! 463: bad: ! 464: cerror("illegal control line"); ! 465: } ! 466: while ((c = get()) >= 0) /* incpp, new line follows EOF */ ! 467: ; ! 468: } ! 469: ! 470: /* end of n0/sharp.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.