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