update credits
[LibreOffice.git] / soltools / cpp / _cpp.c
blobbfa93bed84b3106783c94f9e9d67d1df850aec6b
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 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;
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 setup(argc, argv);
56 fixlex();
57 if (!Pflag)
58 genline();
59 process(&tr);
60 flushout();
61 fflush(stderr);
62 exit(nerrs > 0);
65 void
66 process(Tokenrow * trp)
68 int anymacros = 0;
70 for (;;)
72 if (trp->tp >= trp->lp)
74 trp->tp = trp->lp = trp->bp;
75 outptr = outbuf;
76 anymacros |= gettokens(trp, 1);
77 trp->tp = trp->bp;
79 if (trp->tp->type == END)
81 if (--incdepth >= 0)
83 if (cursource->ifdepth)
84 error(ERROR,
85 "Unterminated conditional in #include");
86 unsetsource();
87 cursource->line += cursource->lineinc;
88 trp->tp = trp->lp;
89 if (!Pflag)
90 genline();
91 continue;
93 if (ifdepth)
94 error(ERROR, "Unterminated #if/#ifdef/#ifndef");
95 break;
97 if (trp->tp->type == SHARP)
99 trp->tp += 1;
100 control(trp);
102 else
103 if (!skipping && anymacros)
104 expandrow(trp, NULL);
105 if (skipping)
106 setempty(trp);
107 puttokens(trp);
108 anymacros = 0;
109 cursource->line += cursource->lineinc;
110 if (cursource->lineinc > 1)
112 if (!Pflag)
113 genline();
118 void
119 control(Tokenrow * trp)
121 Nlist *np;
122 Token *tp;
124 tp = trp->tp;
125 if (tp->type != NAME)
127 if (tp->type == NUMBER)
128 goto kline;
129 if (tp->type != NL)
130 error(ERROR, "Unidentifiable control line");
131 return; /* else empty line */
133 if ((np = lookup(tp, 0)) == NULL || ((np->flag & ISKW) == 0 && !skipping))
135 error(WARNING, "Unknown preprocessor control %t", tp);
136 return;
138 if (skipping)
140 switch (np->val)
142 case KENDIF:
143 if (--ifdepth < skipping)
144 skipping = 0;
145 --cursource->ifdepth;
146 setempty(trp);
147 return;
149 case KIFDEF:
150 case KIFNDEF:
151 case KIF:
152 if (++ifdepth >= NIF)
153 error(FATAL, "#if too deeply nested");
154 ++cursource->ifdepth;
155 return;
157 case KELIF:
158 case KELSE:
159 if (ifdepth <= skipping)
160 break;
161 return;
163 default:
164 return;
167 switch (np->val)
169 case KDEFINE:
170 dodefine(trp);
171 break;
173 case KUNDEF:
174 tp += 1;
175 if (tp->type != NAME || trp->lp - trp->bp != 4)
177 error(ERROR, "Syntax error in #undef");
178 break;
180 if ((np = lookup(tp, 0)) != NULL)
182 np->flag &= ~ISDEFINED;
184 if (Mflag)
186 if (np->ap)
187 error(INFO, "Macro deletion of %s(%r)", np->name, np->ap);
188 else
189 error(INFO, "Macro deletion of %s", np->name);
192 break;
194 case KPRAGMA:
195 case KIDENT:
196 for (tp = trp->tp - 1; ((tp->type != NL) && (tp < trp->lp)); tp++)
197 tp->type = UNCLASS;
198 return;
200 case KIFDEF:
201 case KIFNDEF:
202 case KIF:
203 if (++ifdepth >= NIF)
204 error(FATAL, "#if too deeply nested");
205 ++cursource->ifdepth;
206 ifsatisfied[ifdepth] = 0;
207 if (eval(trp, np->val))
208 ifsatisfied[ifdepth] = 1;
209 else
210 skipping = ifdepth;
211 break;
213 case KELIF:
214 if (ifdepth == 0)
216 error(ERROR, "#elif with no #if");
217 return;
219 if (ifsatisfied[ifdepth] == 2)
220 error(ERROR, "#elif after #else");
221 if (eval(trp, np->val))
223 if (ifsatisfied[ifdepth])
224 skipping = ifdepth;
225 else
227 skipping = 0;
228 ifsatisfied[ifdepth] = 1;
231 else
232 skipping = ifdepth;
233 break;
235 case KELSE:
236 if (ifdepth == 0 || cursource->ifdepth == 0)
238 error(ERROR, "#else with no #if");
239 return;
241 if (ifsatisfied[ifdepth] == 2)
242 error(ERROR, "#else after #else");
243 if (trp->lp - trp->bp != 3)
244 error(ERROR, "Syntax error in #else");
245 skipping = ifsatisfied[ifdepth] ? ifdepth : 0;
246 ifsatisfied[ifdepth] = 2;
247 break;
249 case KENDIF:
250 if (ifdepth == 0 || cursource->ifdepth == 0)
252 error(ERROR, "#endif with no #if");
253 return;
255 --ifdepth;
256 --cursource->ifdepth;
257 if (trp->lp - trp->bp != 3)
258 error(WARNING, "Syntax error in #endif");
259 break;
261 case KERROR:
262 trp->tp = tp + 1;
263 error(WARNING, "#error directive: %r", trp);
264 break;
266 case KLINE:
267 trp->tp = tp + 1;
268 expandrow(trp, "<line>");
269 tp = trp->bp + 2;
270 kline:
271 if (tp + 1 >= trp->lp || tp->type != NUMBER || tp + 3 < trp->lp
272 || (tp + 3 == trp->lp
273 && ((tp + 1)->type != STRING || *(tp + 1)->t == 'L')))
275 error(ERROR, "Syntax error in #line");
276 return;
278 cursource->line = atol((char *) tp->t) - 1;
279 if (cursource->line < 0 || cursource->line >= 32768)
280 error(WARNING, "#line specifies number out of range");
281 tp = tp + 1;
282 if (tp + 1 < trp->lp)
283 cursource->filename = (char *) newstring(tp->t + 1, tp->len - 2, 0);
284 return;
286 case KDEFINED:
287 error(ERROR, "Bad syntax for control line");
288 break;
290 case KIMPORT:
291 doinclude(trp, -1, 1);
292 trp->lp = trp->bp;
293 return;
295 case KINCLUDE:
296 doinclude(trp, -1, 0);
297 trp->lp = trp->bp;
298 return;
300 case KINCLUDENEXT:
301 doinclude(trp, cursource->pathdepth, 0);
302 trp->lp = trp->bp;
303 return;
305 case KEVAL:
306 eval(trp, np->val);
307 break;
309 default:
310 error(ERROR, "Preprocessor control `%t' not yet implemented", tp);
311 break;
313 setempty(trp);
314 return;
317 void *
318 domalloc(size_t size)
320 void *p = malloc(size);
322 if (p == NULL)
323 error(FATAL, "Out of memory from malloc");
324 return p;
327 void
328 dofree(void *p)
330 free(p);
333 void
334 error(enum errtype type, char *string,...)
336 va_list ap;
337 char c, *cp, *ep;
338 Token *tp;
339 Tokenrow *trp;
340 Source *s;
341 int i;
343 fprintf(stderr, "cpp: ");
344 for (s = cursource; s; s = s->next)
345 if (*s->filename)
346 fprintf(stderr, "%s:%d ", s->filename, s->line);
347 va_start(ap, string);
348 for (ep = string; *ep; ep++)
350 if (*ep == '%')
352 switch (*++ep)
355 case 'c':
356 c = (char) va_arg(ap, int);
357 fprintf(stderr, "%c", c);
358 break;
360 case 's':
361 cp = va_arg(ap, char *);
362 fprintf(stderr, "%s", cp);
363 break;
365 case 'd':
366 i = va_arg(ap, int);
367 fprintf(stderr, "%d", i);
368 break;
370 case 't':
371 tp = va_arg(ap, Token *);
372 fprintf(stderr, "%.*s", (int)tp->len, tp->t);
373 break;
375 case 'r':
376 trp = va_arg(ap, Tokenrow *);
377 for (tp = trp->tp; tp < trp->lp && tp->type != NL; tp++)
379 if (tp > trp->tp && tp->wslen)
380 fputc(' ', stderr);
381 fprintf(stderr, "%.*s", (int)tp->len, tp->t);
383 break;
385 default:
386 fputc(*ep, stderr);
387 break;
390 else
391 fputc(*ep, stderr);
393 va_end(ap);
394 fputc('\n', stderr);
395 if (type == FATAL)
396 exit(1);
397 if (type != WARNING)
398 nerrs = 1;
399 fflush(stderr);
402 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */