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