|
|
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.