1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <time.h>
5 #include <stdarg.h>
6 #include "cpp.h"
7
8 char rcsid[] = "cpp.c - faked rcsid";
9
10 #define OUTS 16384
11 char outbuf[OUTS];
12 char *outp = outbuf;
13 Source *cursource;
14 int nerrs;
15 struct token nltoken = { NL, 0, 0, 0, 1, (uchar*)"\n" };
16 char *curtime;
17 int incdepth;
18 int ifdepth;
19 int ifsatisfied[NIF];
20 int skipping;
21
22
23 int
main(int argc,char ** argv)24 main(int argc, char **argv)
25 {
26 Tokenrow tr;
27 time_t t;
28 char ebuf[BUFSIZ];
29
30 setbuf(stderr, ebuf);
31 t = time(NULL);
32 curtime = ctime(&t);
33 maketokenrow(3, &tr);
34 expandlex();
35 setup(argc, argv);
36 fixlex();
37 iniths();
38 genline();
39 process(&tr);
40 flushout();
41 fflush(stderr);
42 exit(nerrs > 0);
43 return 0;
44 }
45
46 void
process(Tokenrow * trp)47 process(Tokenrow *trp)
48 {
49 int anymacros = 0;
50
51 for (;;) {
52 if (trp->tp >= trp->lp) {
53 trp->tp = trp->lp = trp->bp;
54 outp = outbuf;
55 anymacros |= gettokens(trp, 1);
56 trp->tp = trp->bp;
57 }
58 if (trp->tp->type == END) {
59 if (--incdepth>=0) {
60 if (cursource->ifdepth)
61 error(ERROR,
62 "Unterminated conditional in #include");
63 unsetsource();
64 cursource->line += cursource->lineinc;
65 trp->tp = trp->lp;
66 genline();
67 continue;
68 }
69 if (ifdepth)
70 error(ERROR, "Unterminated #if/#ifdef/#ifndef");
71 break;
72 }
73 if (trp->tp->type==SHARP) {
74 trp->tp += 1;
75 control(trp);
76 } else if (!skipping && anymacros)
77 expandrow(trp, NULL);
78 if (skipping)
79 setempty(trp);
80 puttokens(trp);
81 anymacros = 0;
82 cursource->line += cursource->lineinc;
83 if (cursource->lineinc>1) {
84 genline();
85 }
86 }
87 }
88
89 void
control(Tokenrow * trp)90 control(Tokenrow *trp)
91 {
92 Nlist *np;
93 Token *tp;
94
95 tp = trp->tp;
96 if (tp->type!=NAME) {
97 if (tp->type==NUMBER)
98 goto kline;
99 if (tp->type != NL)
100 error(ERROR, "Unidentifiable control line");
101 return; /* else empty line */
102 }
103 if ((np = lookup(tp, 0))==NULL || ((np->flag&ISKW)==0 && !skipping)) {
104 error(WARNING, "Unknown preprocessor control %t", tp);
105 return;
106 }
107 if (skipping) {
108 switch (np->val) {
109 case KENDIF:
110 if (--ifdepth<skipping)
111 skipping = 0;
112 --cursource->ifdepth;
113 setempty(trp);
114 return;
115
116 case KIFDEF:
117 case KIFNDEF:
118 case KIF:
119 if (++ifdepth >= NIF)
120 error(FATAL, "#if too deeply nested");
121 ++cursource->ifdepth;
122 return;
123
124 case KELIF:
125 case KELSE:
126 if (ifdepth<=skipping)
127 break;
128 return;
129
130 default:
131 return;
132 }
133 }
134 switch (np->val) {
135 case KDEFINE:
136 dodefine(trp);
137 break;
138
139 case KUNDEF:
140 tp += 1;
141 if (tp->type!=NAME || trp->lp - trp->bp != 4) {
142 error(ERROR, "Syntax error in #undef");
143 break;
144 }
145 if ((np = lookup(tp, 0)) != NULL)
146 np->flag &= ~ISDEFINED;
147 break;
148
149 case KPRAGMA:
150 return;
151
152 case KIFDEF:
153 case KIFNDEF:
154 case KIF:
155 if (++ifdepth >= NIF)
156 error(FATAL, "#if too deeply nested");
157 ++cursource->ifdepth;
158 ifsatisfied[ifdepth] = 0;
159 if (eval(trp, np->val))
160 ifsatisfied[ifdepth] = 1;
161 else
162 skipping = ifdepth;
163 break;
164
165 case KELIF:
166 if (ifdepth==0) {
167 error(ERROR, "#elif with no #if");
168 return;
169 }
170 if (ifsatisfied[ifdepth]==2)
171 error(ERROR, "#elif after #else");
172 if (eval(trp, np->val)) {
173 if (ifsatisfied[ifdepth])
174 skipping = ifdepth;
175 else {
176 skipping = 0;
177 ifsatisfied[ifdepth] = 1;
178 }
179 } else
180 skipping = ifdepth;
181 break;
182
183 case KELSE:
184 if (ifdepth==0 || cursource->ifdepth==0) {
185 error(ERROR, "#else with no #if");
186 return;
187 }
188 if (ifsatisfied[ifdepth]==2)
189 error(ERROR, "#else after #else");
190 if (trp->lp - trp->bp != 3)
191 error(ERROR, "Syntax error in #else");
192 skipping = ifsatisfied[ifdepth]? ifdepth: 0;
193 ifsatisfied[ifdepth] = 2;
194 break;
195
196 case KENDIF:
197 if (ifdepth==0 || cursource->ifdepth==0) {
198 error(ERROR, "#endif with no #if");
199 return;
200 }
201 --ifdepth;
202 --cursource->ifdepth;
203 if (trp->lp - trp->bp != 3)
204 error(WARNING, "Syntax error in #endif");
205 break;
206
207 case KERROR:
208 trp->tp = tp+1;
209 error(WARNING, "#error directive: %r", trp);
210 break;
211
212 case KLINE:
213 trp->tp = tp+1;
214 expandrow(trp, "<line>");
215 tp = trp->bp+2;
216 kline:
217 if (tp+1>=trp->lp || tp->type!=NUMBER || tp+3<trp->lp
218 || ((tp+3==trp->lp && ((tp+1)->type!=STRING))||*(tp+1)->t=='L')){
219 error(ERROR, "Syntax error in #line");
220 return;
221 }
222 cursource->line = atol((char*)tp->t)-1;
223 if (cursource->line<0 || cursource->line>=32768)
224 error(WARNING, "#line specifies number out of range");
225 tp = tp+1;
226 if (tp+1<trp->lp)
227 cursource->filename=(char*)newstring(tp->t+1,tp->len-2,0);
228 return;
229
230 case KDEFINED:
231 error(ERROR, "Bad syntax for control line");
232 break;
233
234 case KINCLUDE:
235 doinclude(trp);
236 trp->lp = trp->bp;
237 return;
238
239 case KEVAL:
240 eval(trp, np->val);
241 break;
242
243 default:
244 error(ERROR, "Preprocessor control `%t' not yet implemented", tp);
245 break;
246 }
247 setempty(trp);
248 return;
249 }
250
251 void *
domalloc(int size)252 domalloc(int size)
253 {
254 void *p = malloc(size);
255
256 if (p==NULL)
257 error(FATAL, "Out of memory from malloc");
258 return p;
259 }
260
261 void
dofree(void * p)262 dofree(void *p)
263 {
264 free(p);
265 }
266
267 void
error(enum errtype type,char * string,...)268 error(enum errtype type, char *string, ...)
269 {
270 va_list ap;
271 char *cp, *ep;
272 Token *tp;
273 Tokenrow *trp;
274 Source *s;
275 int i;
276
277 fprintf(stderr, "cpp: ");
278 for (s=cursource; s; s=s->next)
279 if (*s->filename)
280 fprintf(stderr, "%s:%d ", s->filename, s->line);
281 va_start(ap, string);
282 for (ep=string; *ep; ep++) {
283 if (*ep=='%') {
284 switch (*++ep) {
285
286 case 's':
287 cp = va_arg(ap, char *);
288 fprintf(stderr, "%s", cp);
289 break;
290 case 'd':
291 i = va_arg(ap, int);
292 fprintf(stderr, "%d", i);
293 break;
294 case 't':
295 tp = va_arg(ap, Token *);
296 fprintf(stderr, "%.*s", tp->len, tp->t);
297 break;
298
299 case 'r':
300 trp = va_arg(ap, Tokenrow *);
301 for (tp=trp->tp; tp<trp->lp&&tp->type!=NL; tp++) {
302 if (tp>trp->tp && tp->wslen)
303 fputc(' ', stderr);
304 fprintf(stderr, "%.*s", tp->len, tp->t);
305 }
306 break;
307
308 default:
309 fputc(*ep, stderr);
310 break;
311 }
312 } else
313 fputc(*ep, stderr);
314 }
315 va_end(ap);
316 fputc('\n', stderr);
317 if (type==FATAL)
318 exit(1);
319 if (type!=WARNING)
320 nerrs = 1;
321 fflush(stderr);
322 }
323