|
|
1.1 root 1: /*
2: * n0/get.c
3: * C preprocessor.
4: * Read next character.
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: * Look ahead for '#' or '(' and restore the stream if you fail.
16: * This gets reentered looking for '#'
17: * when the search for a '(' passes newline.
18: */
19: skipto(d) int d;
20: {
21: register char *p, *sp;
22: register int c;
23:
24: sp = dpshp;
25: while ((c = get()) >= 0 && ct[c] == SKIP)
26: dpshc(c);
27: if (c >= 0)
28: dpshc(c);
29: if (c != d) {
30: for (p = dpshp; p < sp; ++p)
31: unget(*p);
32: dpshp = sp;
33: return 0;
34: }
35: dpshp = sp;
36: return 1;
37: }
38:
39: /*
40: * Look at a newly opened file.
41: */
42: emptyfilep()
43: {
44: register int c;
45:
46: c = getc(ifp);
47: if (c == EOF) {
48: c = '\n';
49: }
50: ungetc(c, ifp);
51: }
52:
53: /*
54: * Get a character.
55: * This function returns the next character,
56: * and implements one character pushback,
57: * as well as the expanded macro stack.
58: */
59: get()
60: {
61: register int c;
62:
63: for (;;) {
64: switch (dstackp->ds_type) {
65:
66: case DS_FUNGET: /* Ungotten character from file */
67: c = (dstackp++)->ds_char & 0377;
68: goto file_char;
69:
70: case DS_FILE: /* Read next character from source file */
71: while ((c = getc(ifp)) < 0) { /* Pop include stack */
72: eof: fclose(ifp);
73: if (lastchar != '\n' && lastchar != EOF)
74: eof_in_line: cfatal("EOF in midline");
75: if (istackp < istack+NLEV) {
76: if (cstackp != istackp->i_cstackp)
77: cerror("missing #endif");
78: cstackp = istackp->i_cstackp;
79: line = istackp->i_line;
80: if (notvariant(VCPP)) {
81: bput(LINE);
82: iput((ival_t)line);
83: }
84: idp = istackp->i_file;
85: setfname();
86: ifp = istackp->i_fp;
87: ++istackp;
88: continue;
89: }
90: if (cstackp < cstack+NLEV)
91: cerror("missing #endif");
92: cstackp = cstack + NLEV;
93: lastchar = c;
94: return c; /* ie, EOF */
95: }
96: file_char: lastchar = c;
97: switch (ct[c]) {
98:
99: case SKIP: /* New line? */
100: #if GEMDOS || MSDOS /* Assuming use of bingetc() */
101: if (c == '\r')
102: continue;
103: #endif
104: if (c == '\n') {
105: if (incpp) {
106: ungetc(c, ifp);
107: return EOF;
108: }
109: if (instring) {
110: cerror("new line in %s literal",
111: instring=='"' ? "string" : "character");
112: ++line;
113: c = ' ';
114: } else
115: notskip = 0;
116: }
117: notskip -= 1;
118: break;
119:
120: case QUEST: /* Trigraph? */
121: if (notvariant(V3GRAPH))
122: break;
123: if ((c = getc(ifp)) < 0)
124: goto eof_in_line;
125: if (c != '?') {
126: ungetc(c, ifp);
127: c = '?';
128: break;
129: }
130: if ((c = getc(ifp)) < 0)
131: goto eof_in_line;
132: switch (c) {
133: case '=': ungetc('#', ifp); continue;
134: case '(': ungetc('[', ifp); continue;
135: case '/': ungetc('\\', ifp); continue;
136: case ')': ungetc(']', ifp); continue;
137: case '\'': ungetc('^', ifp); continue;
138: case '<': ungetc('{', ifp); continue;
139: case '!': ungetc('|', ifp); continue;
140: case '>': ungetc('}', ifp); continue;
141: case '-': ungetc('~', ifp); continue;
142: default:
143: ungetc(c, ifp);
144: dspushc(DS_FUNGET, '?');
145: c = '?';
146: }
147: break;
148:
149: case DIV: /* Comment? */
150: if (instring || cstate != 0)
151: break;
152: if (isvariant(VCPP) && isvariant(VCPPC))
153: break;
154: if ((c = getc(ifp)) < 0)
155: goto eof_in_line;
156: else if (isvariant(VCPLUS) && c == '/') {
157: /* Ignore //-delimited C++ online comment. */
158: while ((c = getc(ifp)) != '\n')
159: if (c < 0)
160: goto eof_in_comment;
161: break;
162: } else if (c != '*') {
163: ungetc(c, ifp);
164: c = '/';
165: break;
166: }
167: for (;;) {
168: if ((c = getc(ifp)) < 0)
169: eof_in_comment: cfatal("EOF in comment");
170: if (c == '*') {
171: if ((c = getc(ifp)) < 0)
172: goto eof_in_comment;
173: if (c == '/')
174: break;
175: ungetc(c, ifp);
176: } else if (c == '/') {
177: if ((c = getc(ifp)) < 0)
178: goto eof_in_comment;
179: if (c == '*')
180: cwarn("nested comments");
181: ungetc(c, ifp);
182: } else if (c == '\n')
183: ++line;
184: }
185: c = ' ';
186: break;
187:
188: case BACKDIV: /* Splice? */
189: try_again: if ((c = getc(ifp)) < 0)
190: goto eof_in_line;
191: if (c != '\n') {
192: #if GEMDOS || MSDOS /* Assuming use of bingetc() */
193: if (c == '\r')
194: goto try_again;
195: #endif
196: ungetc(c, ifp);
197: c = '\\';
198: break;
199: }
200: ++line;
201: continue;
202:
203: case HIGH0:
204: case HIGH1:
205: case HIGH2:
206: case HIGH3:
207: case JUNK:
208: #if GEMDOS || MSDOS /* Assuming use of bingetc() */
209: if (c == 26) /* ^Z */
210: goto eof;
211: #endif
212: if (instring || (c > ' ' && c < 0177) || cstate != 0)
213: break;
214: cerror("illegal cpp character (%d decimal)", c);
215: continue;
216:
217: case SHARP:
218: if (notskip != 0)
219: break;
220: ++incpp;
221: control();
222: --incpp;
223: continue;
224: }
225: notskip += 1;
226: break;
227:
228: case DS_UNGET: /* Read ungotten character */
229: c = (dstackp++)->ds_char & 0377;
230: break;
231:
232: case DS_STRNG:
233: if ((c = *dstackp->ds_ptr++ & 0377) == 0) {
234: ++dstackp;
235: continue;
236: }
237: break;
238:
239: case DS_UFILE: /* Convert file name into string */
240: if ((c = *dstackp->ds_ptr++ & 0377) == 0) {
241: ++dstackp;
242: continue;
243: }
244: if (c == '\\' || c == '"') {
245: unget(c);
246: c = '\\';
247: }
248: break;
249:
250: case DS_SHARP: /* Read and stringize */
251: if ((c = *dstackp->ds_ptr++ & 0377) == 0) {
252: ++dstackp;
253: continue;
254: }
255: if (dstackp->ds_char) {
256: if (c == dstackp->ds_char) {
257: dstackp->ds_char = 0;
258: if (c == '"') {
259: unget(c);
260: c = '\\';
261: }
262: } else if (c == '\\') {
263: c = *dstackp->ds_ptr++;
264: unget(c);
265: if (c == '"')
266: unget('\\');
267: unget('\\');
268: c = '\\';
269: }
270: } else if (c == '"') {
271: dstackp->ds_char = c;
272: unget(c);
273: c = '\\';
274: } else if (c == '\'')
275: dstackp->ds_char = c;
276: else if (c >= SET0)
277: continue;
278: break;
279:
280: case DS_DPUTP:
281: dputp = (dstackp++)->ds_ptr;
282: continue;
283:
284: case DS_NAME:
285: ++dstackp;
286: continue;
287:
288: case DS_IEOF:
289: c = EOF;
290: break;
291:
292: default:
293: cbotch("bad ds_type %d", dstackp->ds_type);
294: }
295: if (c == '\n') ++line;
296: if (cstate != 0 && incpp == 0)
297: continue;
298: return c;
299: }
300: }
301:
302: /*
303: * One character pushback for the callers of get().
304: */
305: unget(c) register int c;
306: {
307: if (c < 0)
308: return;
309: dspushc(DS_UNGET, c);
310: if (c == '\n')
311: --line;
312: }
313:
314: /* end of n0/get.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.