|
|
1.1 ! root 1: /* ! 2: * n0/expand.c ! 3: * C preprocessor. ! 4: * Macro expansion. ! 5: */ ! 6: ! 7: #include <time.h> ! 8: #ifdef vax ! 9: #include "INC$LIB:cc0.h" ! 10: #else ! 11: #include "cc0.h" ! 12: #endif ! 13: ! 14: /* ! 15: * Expand the string as an actual parameter. ! 16: * This happens after the list of strings ! 17: * in the substituted macro has been pushed ! 18: * onto dstack; expand the string as if it ! 19: * formed the rest of the source file and ! 20: * substitute the expanded string back into ! 21: * the source stream, with the hidden sets of ! 22: * identifiers augmented by the macro name we ! 23: * are substituting. ! 24: */ ! 25: char *argexpand(hide, p) int hide; char *p; ! 26: { ! 27: register char *ap, *spshp; ! 28: register int c; ! 29: ! 30: /* Push the parameter as input */ ! 31: dspush(DS_IEOF, NULL); ! 32: dspush(DS_STRNG, p); ! 33: /* Save the push buffer */ ! 34: spshp = dpshp; ! 35: /* Scan the parameter as input */ ! 36: while ((c = get()) >= 0) { ! 37: switch (ct[c]) { ! 38: case QUOTE: ! 39: case STRING: ! 40: dpshstr(c); ! 41: continue; ! 42: case DOT: ! 43: case CON: ! 44: dpshnum(c); ! 45: continue; ! 46: case ID: ! 47: if (expand(c)) ! 48: continue; ! 49: dpshs(id); ! 50: /* Augment hidden set */ ! 51: dpshc(hideaug(hide, idhide)); ! 52: continue; ! 53: default: ! 54: dpshc(c); ! 55: continue; ! 56: } ! 57: } ! 58: ++dstackp; /* pop IEOF */ ! 59: /* Now pop the expanded string off the push buffer */ ! 60: /* and onto the put buffer */ ! 61: p = dputp; ! 62: for (ap = spshp; --ap >= dpshp; ) ! 63: dputc(*ap); ! 64: dputc(0); ! 65: /* Restore push buffer pointer */ ! 66: dpshp = spshp; ! 67: /* Return pointer to expanded argument */ ! 68: return p; ! 69: } ! 70: ! 71: /* ! 72: * Scan and augment the hidden sets in a string. ! 73: * An in place copy in essence. ! 74: */ ! 75: char *argpaste(hide, p) int hide; char *p; ! 76: { ! 77: register int c; ! 78: char *sputp; ! 79: sputp = dputp; ! 80: dputp = p; ! 81: dspush(DS_IEOF, NULL); ! 82: dspush(DS_STRNG, p); ! 83: while ((c = get()) >= 0) { ! 84: switch (ct[c]) { ! 85: case QUOTE: ! 86: case STRING: ! 87: dputstr(c); ! 88: continue; ! 89: case DOT: ! 90: case CON: ! 91: dputnum(c); ! 92: continue; ! 93: case ID: ! 94: getid(c); ! 95: dputs(id); ! 96: /* Augment hidden set */ ! 97: dputc(hideaug(hide, idhide)); ! 98: continue; ! 99: default: ! 100: dputc(c); ! 101: continue; ! 102: } ! 103: } ! 104: ++dstackp; ! 105: dputp = sputp; ! 106: return p; ! 107: } ! 108: ! 109: ! 110: /* ! 111: * Substitute for the macro specified. ! 112: * Collect the actual parameters into the push buffer, ! 113: * then reverse them onto the put buffer. ! 114: * (Collecting the parameters may pop the dstackp.) ! 115: * Then parse the macro body into the put buffer, ! 116: * forming a list of literal strings ! 117: * (with their hidden sets augmented), ! 118: * # parameters, ## parameters, and ! 119: * vanilla parameters. ! 120: * Then scan the list pushed and ! 121: * recursively expand the vanilla ! 122: * parameters with argexpand(), ! 123: * expanding each parameter only once ! 124: * no matter how many times it appears ! 125: * in the substituted body. ! 126: * Then rescan the list pushed again ! 127: * to augment the hidden sets of ## params. ! 128: */ ! 129: substitute(tp, sp) TOK *tp; CPPSYM *sp; ! 130: { ! 131: register int c, d; ! 132: register int narg, plev; ! 133: register char *p, *pp; ! 134: register DSTACK *dsp; ! 135: DSTACK *dparamp, *dbodyp, *dbasep; ! 136: char *cparamp; ! 137: int tpidhide; ! 138: ! 139: /* Install hide set index */ ! 140: tpidhide = hideset(tp); ! 141: ! 142: /* Collect parameters */ ! 143: dparamp = dlistp; ! 144: cparamp = dpshp; ! 145: if (sp->s_value == XUSERA) { ! 146: c = getskip(); ! 147: for (narg = 0; c >= 0 && c != ')'; narg += 1) { ! 148: plev = 0; p = dpshp; ! 149: while (c >= 0) { ! 150: switch (ct[c]) { ! 151: case QUOTE: ! 152: case STRING: ! 153: dpshstr(c); c = get(); continue; ! 154: case LPAREN: ! 155: plev++; break; ! 156: case COMMA: ! 157: if (!plev) goto next; break; ! 158: case RPAREN: ! 159: if (!plev) goto next; plev--; break; ! 160: case SKIP: ! 161: unget(getskip()); c = ' '; break; ! 162: case ID: ! 163: getid(c); dpshs(id); dpshc(idhide); ! 164: c = get(); continue; ! 165: case DOT: ! 166: case CON: ! 167: dpshnum(c); c = get(); continue; ! 168: } ! 169: dpshc(c); c = get(); ! 170: } ! 171: next: if (narg < sp->s_narg) { ! 172: if (dpshp < p && dpshp[0] == ' ') ! 173: ++dpshp; ! 174: dpshc(0); ! 175: dslist(DS_PARAM, p); ! 176: } ! 177: if (c == ',') ! 178: c = getskip(); ! 179: } ! 180: if (c < 0) { ! 181: cerror("EOF in macro \"%s\" invocation", tp->t_id); ! 182: tp = NULL; ! 183: } ! 184: if (sp->s_narg != narg) { ! 185: cerror("\"%s\" argument mismatch", tp->t_id); ! 186: tp = NULL; ! 187: } ! 188: if (tp == NULL) { ! 189: dlistp = dparamp; ! 190: dpshp = cparamp; ! 191: return 1; ! 192: } ! 193: } ! 194: /* Copy the parameter strings onto the top of dbuf */ ! 195: dpshp = cparamp; ! 196: cparamp = dputp; ! 197: for (dsp = dparamp+sp->s_narg; --dsp >= dparamp; ) { ! 198: p = dsp->ds_ptr; ! 199: dsp->ds_ptr = dputp; ! 200: while (d = *--p) dputc(d); ! 201: dputc(d); ! 202: } ! 203: /* Copy the macro body into dbuf */ ! 204: dbodyp = dlistp; ! 205: dspush(DS_IEOF, 0); ! 206: dspush(DS_STRNG, sp->s_body); ! 207: p = dputp; ! 208: dsp = dparamp; ! 209: while ((c = get()) >= 0) { ! 210: switch (ct[c]) { ! 211: case QUOTE: ! 212: case STRING: ! 213: dputstr(c); continue; ! 214: case ID: ! 215: getid(c); ! 216: dputs(id); ! 217: dputc(hideaug(tpidhide, idhide)); ! 218: continue; ! 219: case CON: ! 220: case DOT: ! 221: dputnum(c); continue; ! 222: default: ! 223: dputc(c); continue; ! 224: case HIGH0: /* param */ ! 225: c -= ARG0; ! 226: pp = dsp[c].ds_ptr; ! 227: if (p != dputp) { ! 228: dputc(0); ! 229: dslist(DS_STRNG, p); ! 230: p = dputp; ! 231: } ! 232: c = get(); ! 233: d = get(); ! 234: unget(d); ! 235: unget(c); ! 236: if (c == '#' && d == '#') ! 237: dslist(DS_SHARP2, pp); ! 238: else ! 239: dslist(DS_PARAM, pp); ! 240: continue; ! 241: case SHARP: /* # or ## */ ! 242: c = get(); ! 243: if (ct[c] == HIGH0) { ! 244: c -= ARG0; ! 245: pp = dsp[c].ds_ptr; ! 246: if (p != dputp) { ! 247: dputc(0); ! 248: dslist(DS_STRNG, p); ! 249: p = dputp; ! 250: } ! 251: dslistc(DS_UNGET, '"'); ! 252: dslist(DS_SHARP, pp); ! 253: dslistc(DS_UNGET, '"'); ! 254: continue; ! 255: } ! 256: c = get(); ! 257: if (ct[c] == HIGH0) { ! 258: c -= ARG0; ! 259: pp = dsp[c].ds_ptr; ! 260: if (p != dputp) { ! 261: dputc(0); ! 262: dslist(DS_STRNG, p); ! 263: p = dputp; ! 264: } ! 265: dslist(DS_SHARP2, pp); ! 266: continue; ! 267: } ! 268: unget(c); ! 269: continue; ! 270: } ! 271: } ! 272: if (p != dputp) { ! 273: dputc(0); ! 274: dslist(DS_STRNG, p); ! 275: p = dputp; ! 276: } ! 277: ++dstackp; /* Pop IEOF */ ! 278: dbasep = dstackp; ! 279: dspush(DS_NAME, tp); ! 280: dspush(DS_DPUTP, cparamp); ! 281: while (--dlistp >= dbodyp) ! 282: *--dstackp = *dlistp; ! 283: dlistp = dparamp; ! 284: /* Expand parameters and augment their hidden sets */ ! 285: for (dsp = dstackp; dsp < dbasep; dsp += 1) { ! 286: if (dsp->ds_type == DS_PARAM) { ! 287: p = argexpand(tpidhide, pp = dsp->ds_ptr); ! 288: /* Now make all references to pp */ ! 289: /* refer to the expanded version p */ ! 290: for (dparamp = dsp; dsp < dbasep; dsp += 1) ! 291: if (dsp->ds_type == DS_PARAM ! 292: && dsp->ds_ptr == pp) { ! 293: dsp->ds_type = DS_STRNG; ! 294: dsp->ds_ptr = p; ! 295: } ! 296: dsp = dparamp; ! 297: } ! 298: } ! 299: /* Now scan for glued parameters and augment their hidden sets */ ! 300: /* Done in a separate loop since ##param might appear before */ ! 301: /* param itself in the substitution list, and they both refer */ ! 302: /* to the same copy of the parameter in dbuf before argexpand */ ! 303: for (dsp = dstackp; dsp < dbasep; dsp += 1) { ! 304: if (dsp->ds_type == DS_SHARP2) { ! 305: p = argpaste(tpidhide, pp = dsp->ds_ptr); ! 306: for (dparamp = dsp; dsp < dbasep; dsp += 1) ! 307: if (dsp->ds_type == DS_SHARP2 ! 308: && dsp->ds_ptr == pp) { ! 309: dsp->ds_type = DS_STRNG; ! 310: dsp->ds_ptr = p; ! 311: } ! 312: dsp = dparamp; ! 313: } ! 314: } ! 315: return 1; ! 316: } ! 317: ! 318: /* ! 319: * Try macro expansion, ! 320: * return true if it happened. ! 321: * Read id[] starting with 'c' ! 322: * and see if it is defined. ! 323: * Since this is called for each ! 324: * identifier read, it should use ! 325: * minimal registers and defer most ! 326: * processing to subfunctions. ! 327: */ ! 328: expand(c) register int c; ! 329: { ! 330: char *p; ! 331: CPPSYM *sp; ! 332: TOK *tp; ! 333: extern char *ctime(); ! 334: static char lineno[16]; ! 335: ! 336: getid(c); ! 337: tp = idp; ! 338: if ((sp=idp->t_sym) == NULL ! 339: || sp->s_slevel != SL_CPP ! 340: || hidden()) { ! 341: none_such: if (incpp > 1) { /* Parsing a #if expression */ ! 342: dspush(DS_STRNG, deffalse); ! 343: return 1; ! 344: } ! 345: return 0; ! 346: } ! 347: ! 348: switch ((int)sp->s_value) { ! 349: case XUSER: ! 350: return substitute(tp, sp); ! 351: case XUFILE: ! 352: unget('"'); ! 353: dspush(DS_UFILE, file); ! 354: unget('"'); ! 355: return 1; ! 356: case XUBASE: ! 357: unget('"'); ! 358: dspush(DS_UFILE, basefile); ! 359: unget('"'); ! 360: return 1; ! 361: case XULINE: ! 362: dspush(DS_STRNG, lineno); ! 363: sprintf(lineno, "%d", line); ! 364: return 1; ! 365: case XUDATE: ! 366: case XUTIME: ! 367: p = ctime(&curtime); ! 368: if (sp->s_value == XUDATE) { ! 369: p[24] = 0; ! 370: strcpy(p+11, p+20); ! 371: p += 4; ! 372: } else { ! 373: p[19] = 0; ! 374: p += 11; ! 375: } ! 376: unget('"'); ! 377: dspush(DS_STRNG, p); ! 378: unget('"'); ! 379: return 1; ! 380: #if 0 ! 381: /* ! 382: * ANSI C says __STDC__ should be defined as 0 for a non-ANSI compiler, ! 383: * but too many sources use #ifdef __STDC__ when they should use #if __STDC__. ! 384: * This is therefore conditionalized out here and in n0/cc0key.c. ! 385: */ ! 386: case XUSTDC: ! 387: dspush(DS_STRNG, deffalse); ! 388: return 1; ! 389: #endif ! 390: case XDEFINED: ! 391: if (incpp < 2) ! 392: return 0; ! 393: if ((c = getnb()) == '(') { ! 394: if ((c = getnb()) < 0 || ct[c] != ID) ! 395: goto bad; ! 396: getid(c); ! 397: if ((c = getnb()) != ')') ! 398: goto bad; ! 399: } else if (ct[c] == ID) ! 400: getid(c); ! 401: else { ! 402: bad: cerror("illegal use of defined"); ! 403: dspush(DS_STRNG, deffalse); ! 404: return 1; ! 405: } ! 406: tp = idp; ! 407: if ((sp = tp->t_sym) != NULL ! 408: && sp->s_slevel == SL_CPP ! 409: && ! hidden()) ! 410: dspush(DS_STRNG, deftrue); ! 411: else ! 412: dspush(DS_STRNG, deffalse); ! 413: return 1; ! 414: case XUSERA: ! 415: if (skipto('(')) ! 416: return substitute(tp, sp); ! 417: goto none_such; ! 418: default: ! 419: cbotch("value %d in expand", sp->s_value); ! 420: } ! 421: return 0; ! 422: } ! 423: ! 424: /* end of n0/expand.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.