Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / soltools / cpp / _cpp.c
blob003611c3f53bddbfbaa48aad56de29405b863199
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <time.h>
24 #include <stdarg.h>
25 #include "cpp.h"
27 #define OUTS 16384
28 static char outbuf[OUTS];
29 char *outptr = outbuf;
30 Source *cursource;
31 static int nerrs;
32 struct token nltoken = {NL, 0, 1, (uchar *) "\n", 0};
33 char *curtime;
34 int incdepth;
35 int ifdepth;
36 int ifsatisfied[NIF];
37 int skipping;
39 int
40 #ifdef _WIN32
41 __cdecl
42 #endif // _WIN32
43 main(int argc, char **argv)
46 Tokenrow tr;
47 time_t t;
48 char ebuf[BUFSIZ];
50 setbuf(stderr, ebuf);
51 t = time(NULL);
52 curtime = ctime(&t);
53 maketokenrow(3, &tr);
54 expandlex();
55 // coverity[tainted_string] - build time test tool
56 setup(argc, argv);
57 fixlex();
58 if (!Pflag)
59 genline();
60 process(&tr);
61 flushout();
62 fflush(stderr);
63 exit(nerrs > 0);
66 void
67 process(Tokenrow * trp)
69 int anymacros = 0;
71 for (;;)
73 if (trp->tp >= trp->lp)
75 trp->tp = trp->lp = trp->bp;
76 outptr = outbuf;
77 // coverity[overrun-buffer-arg: FALSE] - a multiple of trp->max is allocated, not trp->max itself
78 anymacros |= gettokens(trp, 1);
79 trp->tp = trp->bp;
81 if (trp->tp->type == END)
83 if (--incdepth >= 0)
85 if (cursource->ifdepth)
86 error(ERROR,
87 "Unterminated conditional in #include");
88 unsetsource();
89 cursource->line += cursource->lineinc;
90 trp->tp = trp->lp;
91 if (!Pflag)
92 genline();
93 continue;
95 if (ifdepth)
96 error(ERROR, "Unterminated #if/#ifdef/#ifndef");
97 break;
99 if (trp->tp->type == SHARP)
101 trp->tp += 1;
102 control(trp);
104 else
105 if (!skipping && anymacros)
106 expandrow(trp, NULL);
107 if (skipping)
108 setempty(trp);
109 puttokens(trp);
110 anymacros = 0;
111 cursource->line += cursource->lineinc;
112 if (cursource->lineinc > 1 && !Pflag)
113 genline();
117 void
118 control(Tokenrow * trp)
120 Nlist *np;
121 Token *tp;
123 tp = trp->tp;
124 if (tp->type != NAME)
126 if (tp->type == NUMBER)
127 goto kline;
128 if (tp->type != NL)
129 error(ERROR, "Unidentifiable control line");
130 return; /* else empty line */
132 if ((np = lookup(tp, 0)) == NULL || ((np->flag & ISKW) == 0 && !skipping))
134 error(WARNING, "Unknown preprocessor control %t", tp);
135 return;
137 if (skipping)
139 switch (np->val)
141 case KENDIF:
142 if (--ifdepth < skipping)
143 skipping = 0;
144 --cursource->ifdepth;
145 setempty(trp);
146 return;
148 case KIFDEF:
149 case KIFNDEF:
150 case KIF:
151 if (++ifdepth >= NIF)
152 error(FATAL, "#if too deeply nested");
153 ++cursource->ifdepth;
154 return;
156 case KELIF:
157 case KELSE:
158 if (ifdepth <= skipping)
159 break;
160 return;
162 default:
163 return;
166 switch (np->val)
168 case KDEFINE:
169 dodefine(trp);
170 break;
172 case KUNDEF:
173 tp += 1;
174 if (tp->type != NAME || trp->lp - trp->bp != 4)
176 error(ERROR, "Syntax error in #undef");
177 break;
179 if ((np = lookup(tp, 0)) != NULL)
181 np->flag &= ~ISDEFINED;
183 if (Mflag)
185 if (np->ap)
186 error(INFO, "Macro deletion of %s(%r)", np->name, np->ap);
187 else
188 error(INFO, "Macro deletion of %s", np->name);
191 break;
193 case KPRAGMA:
194 case KIDENT:
195 for (tp = trp->tp - 1; ((tp->type != NL) && (tp < trp->lp)); tp++)
196 tp->type = UNCLASS;
197 return;
199 case KIFDEF:
200 case KIFNDEF:
201 case KIF:
202 if (++ifdepth >= NIF)
203 error(FATAL, "#if too deeply nested");
204 ++cursource->ifdepth;
205 ifsatisfied[ifdepth] = 0;
206 if (eval(trp, np->val))
207 ifsatisfied[ifdepth] = 1;
208 else
209 skipping = ifdepth;
210 break;
212 case KELIF:
213 if (ifdepth == 0)
215 error(ERROR, "#elif with no #if");
216 return;
218 if (ifsatisfied[ifdepth] == 2)
219 error(ERROR, "#elif after #else");
220 if (eval(trp, np->val))
222 if (ifsatisfied[ifdepth])
223 skipping = ifdepth;
224 else
226 skipping = 0;
227 ifsatisfied[ifdepth] = 1;
230 else
231 skipping = ifdepth;
232 break;
234 case KELSE:
235 if (ifdepth == 0 || cursource->ifdepth == 0)
237 error(ERROR, "#else with no #if");
238 return;
240 if (ifsatisfied[ifdepth] == 2)
241 error(ERROR, "#else after #else");
242 if (trp->lp - trp->bp != 3)
243 error(ERROR, "Syntax error in #else");
244 skipping = ifsatisfied[ifdepth] ? ifdepth : 0;
245 ifsatisfied[ifdepth] = 2;
246 break;
248 case KENDIF:
249 if (ifdepth == 0 || cursource->ifdepth == 0)
251 error(ERROR, "#endif with no #if");
252 return;
254 --ifdepth;
255 --cursource->ifdepth;
256 if (trp->lp - trp->bp != 3)
257 error(WARNING, "Syntax error in #endif");
258 break;
260 case KERROR:
261 trp->tp = tp + 1;
262 error(WARNING, "#error directive: %r", trp);
263 break;
265 case KLINE:
266 trp->tp = tp + 1;
267 expandrow(trp, "<line>");
268 tp = trp->bp + 2;
269 kline:
270 if (tp + 1 >= trp->lp || tp->type != NUMBER || tp + 3 < trp->lp
271 || (tp + 3 == trp->lp
272 && ((tp + 1)->type != STRING || *(tp + 1)->t == 'L')))
274 error(ERROR, "Syntax error in #line");
275 return;
277 cursource->line = atol((char *) tp->t) - 1;
278 if (cursource->line < 0 || cursource->line >= 32768)
279 error(WARNING, "#line specifies number out of range");
280 tp = tp + 1;
281 if (tp + 1 < trp->lp)
282 cursource->filename = (char *) newstring(tp->t + 1, tp->len - 2, 0);
283 return;
285 case KDEFINED:
286 error(ERROR, "Bad syntax for control line");
287 break;
289 case KIMPORT:
290 doinclude(trp, -1, 1);
291 trp->lp = trp->bp;
292 return;
294 case KINCLUDE:
295 doinclude(trp, -1, 0);
296 trp->lp = trp->bp;
297 return;
299 case KINCLUDENEXT:
300 doinclude(trp, cursource->pathdepth, 0);
301 trp->lp = trp->bp;
302 return;
304 case KEVAL:
305 eval(trp, np->val);
306 break;
308 default:
309 error(ERROR, "Preprocessor control `%t' not yet implemented", tp);
310 break;
312 setempty(trp);
313 return;
316 void *
317 domalloc(size_t size)
319 void *p = malloc(size);
321 if (p == NULL)
322 error(FATAL, "Out of memory from malloc");
323 return p;
326 void
327 dofree(void *p)
329 free(p);
332 void
333 error(enum errtype type, char *string,...)
335 va_list ap;
336 char c, *cp, *ep;
337 Token *tp;
338 Tokenrow *trp;
339 Source *s;
340 int i;
342 fprintf(stderr, "cpp: ");
343 for (s = cursource; s; s = s->next)
344 if (*s->filename)
345 fprintf(stderr, "%s:%d ", s->filename, s->line);
346 va_start(ap, string);
347 for (ep = string; *ep; ep++)
349 if (*ep == '%')
351 switch (*++ep)
354 case 'c':
355 c = (char) va_arg(ap, int);
356 fprintf(stderr, "%c", c);
357 break;
359 case 's':
360 cp = va_arg(ap, char *);
361 fprintf(stderr, "%s", cp);
362 break;
364 case 'd':
365 i = va_arg(ap, int);
366 fprintf(stderr, "%d", i);
367 break;
369 case 't':
370 tp = va_arg(ap, Token *);
371 fprintf(stderr, "%.*s", (int)tp->len, tp->t);
372 break;
374 case 'r':
375 trp = va_arg(ap, Tokenrow *);
376 for (tp = trp->tp; tp < trp->lp && tp->type != NL; tp++)
378 if (tp > trp->tp && tp->wslen)
379 fputc(' ', stderr);
380 fprintf(stderr, "%.*s", (int)tp->len, tp->t);
382 break;
384 default:
385 fputc(*ep, stderr);
386 break;
389 else
390 fputc(*ep, stderr);
392 va_end(ap);
393 fputc('\n', stderr);
394 if (type == FATAL)
395 exit(1);
396 if (type != WARNING)
397 nerrs = 1;
398 fflush(stderr);
401 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */