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