Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <stdio.h>
21 : #include <stdlib.h>
22 : #include <string.h>
23 : #include <time.h>
24 : #include <stdarg.h>
25 : #include "cpp.h"
26 :
27 : #define OUTS 16384
28 : char outbuf[OUTS];
29 : char *outptr = outbuf;
30 : Source *cursource;
31 : int nerrs;
32 : struct token nltoken = {NL, 0, 0, 1, (uchar *) "\n", 0};
33 : char *curtime;
34 : int incdepth;
35 : int ifdepth;
36 : int ifsatisfied[NIF];
37 : int skipping;
38 :
39 : int
40 : #ifdef _WIN32
41 : __cdecl
42 : #endif // _WIN32
43 0 : main(int argc, char **argv)
44 : {
45 :
46 : Tokenrow tr;
47 : time_t t;
48 : char ebuf[BUFSIZ];
49 :
50 0 : setbuf(stderr, ebuf);
51 0 : t = time(NULL);
52 0 : curtime = ctime(&t);
53 0 : maketokenrow(3, &tr);
54 0 : expandlex();
55 0 : setup(argc, argv);
56 0 : fixlex();
57 0 : if (!Pflag)
58 0 : genline();
59 0 : process(&tr);
60 0 : flushout();
61 0 : fflush(stderr);
62 0 : exit(nerrs > 0);
63 : }
64 :
65 : void
66 0 : process(Tokenrow * trp)
67 : {
68 0 : int anymacros = 0;
69 :
70 : for (;;)
71 : {
72 0 : if (trp->tp >= trp->lp)
73 : {
74 0 : trp->tp = trp->lp = trp->bp;
75 0 : outptr = outbuf;
76 0 : anymacros |= gettokens(trp, 1);
77 0 : trp->tp = trp->bp;
78 : }
79 0 : if (trp->tp->type == END)
80 : {
81 0 : if (--incdepth >= 0)
82 : {
83 0 : if (cursource->ifdepth)
84 0 : error(ERROR,
85 : "Unterminated conditional in #include");
86 0 : unsetsource();
87 0 : cursource->line += cursource->lineinc;
88 0 : trp->tp = trp->lp;
89 0 : if (!Pflag)
90 0 : genline();
91 0 : continue;
92 : }
93 0 : if (ifdepth)
94 0 : error(ERROR, "Unterminated #if/#ifdef/#ifndef");
95 0 : break;
96 : }
97 0 : if (trp->tp->type == SHARP)
98 : {
99 0 : trp->tp += 1;
100 0 : control(trp);
101 : }
102 : else
103 0 : if (!skipping && anymacros)
104 0 : expandrow(trp, NULL);
105 0 : if (skipping)
106 0 : setempty(trp);
107 0 : puttokens(trp);
108 0 : anymacros = 0;
109 0 : cursource->line += cursource->lineinc;
110 0 : if (cursource->lineinc > 1)
111 : {
112 0 : if (!Pflag)
113 0 : genline();
114 : }
115 0 : }
116 0 : }
117 :
118 : void
119 0 : control(Tokenrow * trp)
120 : {
121 : Nlist *np;
122 : Token *tp;
123 :
124 0 : tp = trp->tp;
125 0 : if (tp->type != NAME)
126 : {
127 0 : if (tp->type == NUMBER)
128 0 : goto kline;
129 0 : if (tp->type != NL)
130 0 : error(ERROR, "Unidentifiable control line");
131 0 : return; /* else empty line */
132 : }
133 0 : if ((np = lookup(tp, 0)) == NULL || ((np->flag & ISKW) == 0 && !skipping))
134 : {
135 0 : error(WARNING, "Unknown preprocessor control %t", tp);
136 0 : return;
137 : }
138 0 : if (skipping)
139 : {
140 0 : switch (np->val)
141 : {
142 : case KENDIF:
143 0 : if (--ifdepth < skipping)
144 0 : skipping = 0;
145 0 : --cursource->ifdepth;
146 0 : setempty(trp);
147 0 : return;
148 :
149 : case KIFDEF:
150 : case KIFNDEF:
151 : case KIF:
152 0 : if (++ifdepth >= NIF)
153 0 : error(FATAL, "#if too deeply nested");
154 0 : ++cursource->ifdepth;
155 0 : return;
156 :
157 : case KELIF:
158 : case KELSE:
159 0 : if (ifdepth <= skipping)
160 0 : break;
161 0 : return;
162 :
163 : default:
164 0 : return;
165 : }
166 : }
167 0 : switch (np->val)
168 : {
169 : case KDEFINE:
170 0 : dodefine(trp);
171 0 : break;
172 :
173 : case KUNDEF:
174 0 : tp += 1;
175 0 : if (tp->type != NAME || trp->lp - trp->bp != 4)
176 : {
177 0 : error(ERROR, "Syntax error in #undef");
178 0 : break;
179 : }
180 0 : if ((np = lookup(tp, 0)) != NULL)
181 : {
182 0 : np->flag &= ~ISDEFINED;
183 :
184 0 : if (Mflag)
185 : {
186 0 : if (np->ap)
187 0 : error(INFO, "Macro deletion of %s(%r)", np->name, np->ap);
188 : else
189 0 : error(INFO, "Macro deletion of %s", np->name);
190 : }
191 : }
192 0 : break;
193 :
194 : case KPRAGMA:
195 : case KIDENT:
196 0 : for (tp = trp->tp - 1; ((tp->type != NL) && (tp < trp->lp)); tp++)
197 0 : tp->type = UNCLASS;
198 0 : return;
199 :
200 : case KIFDEF:
201 : case KIFNDEF:
202 : case KIF:
203 0 : if (++ifdepth >= NIF)
204 0 : error(FATAL, "#if too deeply nested");
205 0 : ++cursource->ifdepth;
206 0 : ifsatisfied[ifdepth] = 0;
207 0 : if (eval(trp, np->val))
208 0 : ifsatisfied[ifdepth] = 1;
209 : else
210 0 : skipping = ifdepth;
211 0 : break;
212 :
213 : case KELIF:
214 0 : if (ifdepth == 0)
215 : {
216 0 : error(ERROR, "#elif with no #if");
217 0 : return;
218 : }
219 0 : if (ifsatisfied[ifdepth] == 2)
220 0 : error(ERROR, "#elif after #else");
221 0 : if (eval(trp, np->val))
222 : {
223 0 : if (ifsatisfied[ifdepth])
224 0 : skipping = ifdepth;
225 : else
226 : {
227 0 : skipping = 0;
228 0 : ifsatisfied[ifdepth] = 1;
229 : }
230 : }
231 : else
232 0 : skipping = ifdepth;
233 0 : break;
234 :
235 : case KELSE:
236 0 : if (ifdepth == 0 || cursource->ifdepth == 0)
237 : {
238 0 : error(ERROR, "#else with no #if");
239 0 : return;
240 : }
241 0 : if (ifsatisfied[ifdepth] == 2)
242 0 : error(ERROR, "#else after #else");
243 0 : if (trp->lp - trp->bp != 3)
244 0 : error(ERROR, "Syntax error in #else");
245 0 : skipping = ifsatisfied[ifdepth] ? ifdepth : 0;
246 0 : ifsatisfied[ifdepth] = 2;
247 0 : break;
248 :
249 : case KENDIF:
250 0 : if (ifdepth == 0 || cursource->ifdepth == 0)
251 : {
252 0 : error(ERROR, "#endif with no #if");
253 0 : return;
254 : }
255 0 : --ifdepth;
256 0 : --cursource->ifdepth;
257 0 : if (trp->lp - trp->bp != 3)
258 0 : error(WARNING, "Syntax error in #endif");
259 0 : break;
260 :
261 : case KERROR:
262 0 : trp->tp = tp + 1;
263 0 : error(WARNING, "#error directive: %r", trp);
264 0 : break;
265 :
266 : case KLINE:
267 0 : trp->tp = tp + 1;
268 0 : expandrow(trp, "<line>");
269 0 : tp = trp->bp + 2;
270 : kline:
271 0 : if (tp + 1 >= trp->lp || tp->type != NUMBER || tp + 3 < trp->lp
272 0 : || (tp + 3 == trp->lp
273 0 : && ((tp + 1)->type != STRING || *(tp + 1)->t == 'L')))
274 : {
275 0 : error(ERROR, "Syntax error in #line");
276 0 : return;
277 : }
278 0 : cursource->line = atol((char *) tp->t) - 1;
279 0 : if (cursource->line < 0 || cursource->line >= 32768)
280 0 : error(WARNING, "#line specifies number out of range");
281 0 : tp = tp + 1;
282 0 : if (tp + 1 < trp->lp)
283 0 : cursource->filename = (char *) newstring(tp->t + 1, tp->len - 2, 0);
284 0 : return;
285 :
286 : case KDEFINED:
287 0 : error(ERROR, "Bad syntax for control line");
288 0 : break;
289 :
290 : case KIMPORT:
291 0 : doinclude(trp, -1, 1);
292 0 : trp->lp = trp->bp;
293 0 : return;
294 :
295 : case KINCLUDE:
296 0 : doinclude(trp, -1, 0);
297 0 : trp->lp = trp->bp;
298 0 : return;
299 :
300 : case KINCLUDENEXT:
301 0 : doinclude(trp, cursource->pathdepth, 0);
302 0 : trp->lp = trp->bp;
303 0 : return;
304 :
305 : case KEVAL:
306 0 : eval(trp, np->val);
307 0 : break;
308 :
309 : default:
310 0 : error(ERROR, "Preprocessor control `%t' not yet implemented", tp);
311 0 : break;
312 : }
313 0 : setempty(trp);
314 0 : return;
315 : }
316 :
317 : void *
318 0 : domalloc(size_t size)
319 : {
320 0 : void *p = malloc(size);
321 :
322 0 : if (p == NULL)
323 0 : error(FATAL, "Out of memory from malloc");
324 0 : return p;
325 : }
326 :
327 : void
328 0 : dofree(void *p)
329 : {
330 0 : free(p);
331 0 : }
332 :
333 : void
334 0 : error(enum errtype type, char *string,...)
335 : {
336 : va_list ap;
337 : char c, *cp, *ep;
338 : Token *tp;
339 : Tokenrow *trp;
340 : Source *s;
341 : int i;
342 :
343 0 : fprintf(stderr, "cpp: ");
344 0 : for (s = cursource; s; s = s->next)
345 0 : if (*s->filename)
346 0 : fprintf(stderr, "%s:%d ", s->filename, s->line);
347 0 : va_start(ap, string);
348 0 : for (ep = string; *ep; ep++)
349 : {
350 0 : if (*ep == '%')
351 : {
352 0 : switch (*++ep)
353 : {
354 :
355 : case 'c':
356 0 : c = (char) va_arg(ap, int);
357 0 : fprintf(stderr, "%c", c);
358 0 : break;
359 :
360 : case 's':
361 0 : cp = va_arg(ap, char *);
362 0 : fprintf(stderr, "%s", cp);
363 0 : break;
364 :
365 : case 'd':
366 0 : i = va_arg(ap, int);
367 0 : fprintf(stderr, "%d", i);
368 0 : break;
369 :
370 : case 't':
371 0 : tp = va_arg(ap, Token *);
372 0 : fprintf(stderr, "%.*s", (int)tp->len, tp->t);
373 0 : break;
374 :
375 : case 'r':
376 0 : trp = va_arg(ap, Tokenrow *);
377 0 : for (tp = trp->tp; tp < trp->lp && tp->type != NL; tp++)
378 : {
379 0 : if (tp > trp->tp && tp->wslen)
380 0 : fputc(' ', stderr);
381 0 : fprintf(stderr, "%.*s", (int)tp->len, tp->t);
382 : }
383 0 : break;
384 :
385 : default:
386 0 : fputc(*ep, stderr);
387 0 : break;
388 : }
389 : }
390 : else
391 0 : fputc(*ep, stderr);
392 : }
393 0 : va_end(ap);
394 0 : fputc('\n', stderr);
395 0 : if (type == FATAL)
396 0 : exit(1);
397 0 : if (type != WARNING)
398 0 : nerrs = 1;
399 0 : fflush(stderr);
400 0 : }
401 :
402 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|