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 *outbufp = 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 outbufp = 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 KWARNING:
208 trp->tp = tp+1;
209 error(WARNING, "#warning directive: %r", trp);
210 break;
211
212 case KERROR:
213 trp->tp = tp+1;
214 error(ERROR, "#error directive: %r", trp);
215 break;
216
217 case KLINE:
218 trp->tp = tp+1;
219 expandrow(trp, "<line>");
220 tp = trp->bp+2;
221 kline:
222 if (tp+1>=trp->lp || tp->type!=NUMBER || tp+3<trp->lp
223 || ((tp+3==trp->lp && ((tp+1)->type!=STRING))||*(tp+1)->t=='L')){
224 error(ERROR, "Syntax error in #line");
225 return;
226 }
227 cursource->line = atol((char*)tp->t)-1;
228 if (cursource->line<0 || cursource->line>=32768)
229 error(WARNING, "#line specifies number out of range");
230 tp = tp+1;
231 if (tp+1<trp->lp)
232 cursource->filename=(char*)newstring(tp->t+1,tp->len-2,0);
233 return;
234
235 case KDEFINED:
236 error(ERROR, "Bad syntax for control line");
237 break;
238
239 case KINCLUDE:
240 doinclude(trp);
241 trp->lp = trp->bp;
242 return;
243
244 case KEVAL:
245 eval(trp, np->val);
246 break;
247
248 default:
249 error(ERROR, "Preprocessor control `%t' not yet implemented", tp);
250 break;
251 }
252 setempty(trp);
253 }
254
255 void *
domalloc(int size)256 domalloc(int size)
257 {
258 void *p = malloc(size);
259
260 if (p==NULL)
261 error(FATAL, "Out of memory from malloc");
262 return p;
263 }
264
265 void
dofree(void * p)266 dofree(void *p)
267 {
268 free(p);
269 }
270
271 void
error(enum errtype type,char * string,...)272 error(enum errtype type, char *string, ...)
273 {
274 va_list ap;
275 char *cp, *ep;
276 Token *tp;
277 Tokenrow *trp;
278 Source *s;
279 int i;
280
281 fprintf(stderr, "cpp: ");
282 for (s=cursource; s; s=s->next)
283 if (*s->filename)
284 fprintf(stderr, "%s:%d ", s->filename, s->line);
285 va_start(ap, string);
286 for (ep=string; *ep; ep++) {
287 if (*ep=='%') {
288 switch (*++ep) {
289
290 case 's':
291 cp = va_arg(ap, char *);
292 fprintf(stderr, "%s", cp);
293 break;
294 case 'd':
295 i = va_arg(ap, int);
296 fprintf(stderr, "%d", i);
297 break;
298 case 't':
299 tp = va_arg(ap, Token *);
300 fprintf(stderr, "%.*s", tp->len, tp->t);
301 break;
302
303 case 'r':
304 trp = va_arg(ap, Tokenrow *);
305 for (tp=trp->tp; tp<trp->lp&&tp->type!=NL; tp++) {
306 if (tp>trp->tp && tp->wslen)
307 fputc(' ', stderr);
308 fprintf(stderr, "%.*s", tp->len, tp->t);
309 }
310 break;
311
312 default:
313 fputc(*ep, stderr);
314 break;
315 }
316 } else
317 fputc(*ep, stderr);
318 }
319 va_end(ap);
320 fputc('\n', stderr);
321 if (type==FATAL)
322 exit(1);
323 if (type!=WARNING)
324 nerrs = 1;
325 fflush(stderr);
326 }
327