update dev300-m58
[ooovba.git] / idlc / source / preproc / cpp.c
blob0faa3da75945d0f43673e9c143b250e75fc04fed
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: cpp.c,v $
10 * $Revision: 1.10 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <time.h>
34 #include <stdarg.h>
35 #include "cpp.h"
37 #define OUTS 16384
38 char outbuf[OUTS];
39 char *outptr = outbuf;
40 Source *cursource;
41 int nerrs;
42 struct token nltoken = {NL, 0, 0, 1, (uchar *) "\n"};
43 char *curtime;
44 int incdepth;
45 int ifdepth;
46 int ifsatisfied[NIF];
47 int skipping;
49 char rcsid[] = "$Version 1.2 $ $Revision: 1.10 $ $Date: 2008-07-11 14:50:24 $";
51 int realargc;
52 char* realargv[512];
54 void checkCommandFile(char* cmdfile)
56 FILE *commandfile;
57 char option[256];
59 commandfile = fopen(cmdfile+1, "r");
60 if( commandfile == NULL )
62 error(FATAL, "Can't open command file %s", cmdfile);
63 } else
65 int i=0;
66 int found = 0;
67 char c;
68 while ( fscanf(commandfile, "%c", &c) != EOF )
70 if (c=='\"') {
71 if (found) {
72 found=0;
73 } else {
74 found=1;
75 continue;
77 } else {
78 if (c!=13 && c!=10) {
79 if (found || c!=' ') {
80 option[i++]=c;
81 continue;
84 if (i==0)
85 continue;
87 option[i]='\0';
88 found=0;
89 i=0;
90 if (option[0]== '@' || option[1]== '@')
92 checkCommandFile(option);
93 } else
95 realargv[realargc]= strdup(option);
96 realargc++;
97 option[0]='\0';
100 if (option[0] != '\0') {
101 option[i]='\0';
102 realargv[realargc]= strdup(option);
103 realargc++;
105 fclose(commandfile);
109 void checkCommandArgs(int argc, char **argv)
111 int i;
113 for (i=0; i<argc; i++)
115 if (argv[i][0]== '@')
117 checkCommandFile(argv[i]);
118 } else
120 realargv[i]= strdup(argv[i]);
121 realargc++;
126 void cleanCommandArgs()
128 int i;
130 for (i=0; i<realargc; i++)
132 free(realargv[i]);
136 #ifdef WNT
137 int __cdecl main(int argc, char **argv)
138 #else
139 int main(int argc, char **argv)
140 #endif
142 Tokenrow tr;
143 time_t t;
144 char ebuf[BUFSIZ];
146 checkCommandArgs(argc, argv);
148 setbuf(stderr, ebuf);
149 t = time(NULL);
150 curtime = ctime(&t);
151 maketokenrow(3, &tr);
152 expandlex();
153 setup(realargc, realargv);
154 if (!Pflag)
155 genline();
156 process(&tr);
157 flushout();
158 fflush(stderr);
159 cleanCommandArgs();
160 exit(nerrs);
161 //return nerrs;
164 void
165 process(Tokenrow * trp)
167 int anymacros = 0;
169 for (;;)
171 if (trp->tp >= trp->lp)
173 trp->tp = trp->lp = trp->bp;
174 outptr = outbuf;
175 anymacros |= gettokens(trp, 1);
176 trp->tp = trp->bp;
178 if (trp->tp->type == END)
180 if (--incdepth >= 0)
182 if (cursource->ifdepth)
183 error(ERROR,
184 "Unterminated conditional in #include");
185 unsetsource();
186 cursource->line += cursource->lineinc;
187 trp->tp = trp->lp;
188 if (!Pflag)
189 genline();
190 continue;
192 if (ifdepth)
193 error(ERROR, "Unterminated #if/#ifdef/#ifndef");
194 break;
196 if (trp->tp->type == SHARP)
198 trp->tp += 1;
199 control(trp);
201 else
202 if (!skipping && anymacros)
203 expandrow(trp, NULL);
204 if (skipping)
205 setempty(trp);
206 puttokens(trp);
207 anymacros = 0;
208 cursource->line += cursource->lineinc;
209 if (cursource->lineinc > 1)
211 if (!Pflag)
212 genline();
217 void
218 control(Tokenrow * trp)
220 Nlist *np;
221 Token *tp;
223 tp = trp->tp;
224 if (tp->type != NAME)
226 if (tp->type == NUMBER)
227 goto kline;
228 if (tp->type != NL)
229 error(ERROR, "Unidentifiable control line");
230 return; /* else empty line */
232 if ((np = lookup(tp, 0)) == NULL || ((np->flag & ISKW) == 0 && !skipping))
234 error(WARNING, "Unknown preprocessor control %t", tp);
235 return;
237 if (skipping)
239 switch (np->val)
241 case KENDIF:
242 if (--ifdepth < skipping)
243 skipping = 0;
244 --cursource->ifdepth;
245 setempty(trp);
246 return;
248 case KIFDEF:
249 case KIFNDEF:
250 case KIF:
251 if (++ifdepth >= NIF)
252 error(FATAL, "#if too deeply nested");
253 ++cursource->ifdepth;
254 return;
256 case KELIF:
257 case KELSE:
258 if (ifdepth <= skipping)
259 break;
260 return;
262 default:
263 return;
266 switch (np->val)
268 case KDEFINE:
269 dodefine(trp);
270 break;
272 case KUNDEF:
273 tp += 1;
274 if (tp->type != NAME || trp->lp - trp->bp != 4)
276 error(ERROR, "Syntax error in #undef");
277 break;
279 if ((np = lookup(tp, 0)) != NULL)
281 np->flag &= ~ISDEFINED;
283 if (Mflag)
285 if (np->ap)
286 error(INFO, "Macro deletion of %s(%r)", np->name, np->ap);
287 else
288 error(INFO, "Macro deletion of %s", np->name);
291 break;
293 case KPRAGMA:
294 case KIDENT:
295 for (tp = trp->tp - 1; ((tp->type != NL) && (tp < trp->lp)); tp++)
296 tp->type = UNCLASS;
297 return;
299 case KIFDEF:
300 case KIFNDEF:
301 case KIF:
302 if (++ifdepth >= NIF)
303 error(FATAL, "#if too deeply nested");
304 ++cursource->ifdepth;
305 ifsatisfied[ifdepth] = 0;
306 if (eval(trp, np->val))
307 ifsatisfied[ifdepth] = 1;
308 else
309 skipping = ifdepth;
310 break;
312 case KELIF:
313 if (ifdepth == 0)
315 error(ERROR, "#elif with no #if");
316 return;
318 if (ifsatisfied[ifdepth] == 2)
319 error(ERROR, "#elif after #else");
320 if (eval(trp, np->val))
322 if (ifsatisfied[ifdepth])
323 skipping = ifdepth;
324 else
326 skipping = 0;
327 ifsatisfied[ifdepth] = 1;
330 else
331 skipping = ifdepth;
332 break;
334 case KELSE:
335 if (ifdepth == 0 || cursource->ifdepth == 0)
337 error(ERROR, "#else with no #if");
338 return;
340 if (ifsatisfied[ifdepth] == 2)
341 error(ERROR, "#else after #else");
342 if (trp->lp - trp->bp != 3)
343 error(ERROR, "Syntax error in #else");
344 skipping = ifsatisfied[ifdepth] ? ifdepth : 0;
345 ifsatisfied[ifdepth] = 2;
346 break;
348 case KENDIF:
349 if (ifdepth == 0 || cursource->ifdepth == 0)
351 error(ERROR, "#endif with no #if");
352 return;
354 --ifdepth;
355 --cursource->ifdepth;
356 if (trp->lp - trp->bp != 3)
357 error(WARNING, "Syntax error in #endif");
358 break;
360 case KERROR:
361 trp->tp = tp + 1;
362 error(WARNING, "#error directive: %r", trp);
363 break;
365 case KLINE:
366 trp->tp = tp + 1;
367 expandrow(trp, "<line>");
368 tp = trp->bp + 2;
369 kline:
370 if (tp + 1 >= trp->lp || tp->type != NUMBER || tp + 3 < trp->lp
371 || (tp + 3 == trp->lp
372 && ((tp + 1)->type != STRING || *(tp + 1)->t == 'L')))
374 error(ERROR, "Syntax error in #line");
375 return;
377 cursource->line = atol((char *) tp->t) - 1;
378 if (cursource->line < 0 || cursource->line >= 32768)
379 error(WARNING, "#line specifies number out of range");
380 tp = tp + 1;
381 if (tp + 1 < trp->lp)
382 cursource->filename = (char *) newstring(tp->t + 1, tp->len - 2, 0);
383 return;
385 case KDEFINED:
386 error(ERROR, "Bad syntax for control line");
387 break;
389 case KIMPORT:
390 doinclude(trp, -1, 1);
391 trp->lp = trp->bp;
392 return;
394 case KINCLUDE:
395 doinclude(trp, -1, 0);
396 trp->lp = trp->bp;
397 return;
399 case KINCLUDENEXT:
400 doinclude(trp, cursource->pathdepth, 0);
401 trp->lp = trp->bp;
402 return;
404 case KEVAL:
405 eval(trp, np->val);
406 break;
408 default:
409 error(ERROR, "Preprocessor control `%t' not yet implemented", tp);
410 break;
412 setempty(trp);
413 return;
416 void *
417 domalloc(int size)
419 void *p = malloc(size);
421 if (p == NULL)
422 error(FATAL, "Out of memory from malloc");
423 return p;
426 void
427 dofree(void *p)
429 free(p);
432 void
433 error(enum errtype type, char *string,...)
435 va_list ap;
436 char c, *cp, *ep;
437 Token *tp;
438 Tokenrow *trp;
439 Source *s;
440 int i;
442 fprintf(stderr, "cpp: ");
443 for (s = cursource; s; s = s->next)
444 if (*s->filename)
445 fprintf(stderr, "%s:%d ", s->filename, s->line);
446 va_start(ap, string);
447 for (ep = string; *ep; ep++)
449 if (*ep == '%')
451 switch (*++ep)
454 case 'c':
455 /* need a cast here since va_arg only
456 takes fully promoted types */
457 c = (char) va_arg(ap, int);
458 fprintf(stderr, "%c", c);
459 break;
461 case 's':
462 cp = va_arg(ap, char *);
463 fprintf(stderr, "%s", cp);
464 break;
466 case 'd':
467 i = va_arg(ap, int);
468 fprintf(stderr, "%d", i);
469 break;
471 case 't':
472 tp = va_arg(ap, Token *);
473 fprintf(stderr, "%.*s", tp->len, tp->t);
474 break;
476 case 'r':
477 trp = va_arg(ap, Tokenrow *);
478 for (tp = trp->tp; tp < trp->lp && tp->type != NL; tp++)
480 if (tp > trp->tp && tp->wslen)
481 fputc(' ', stderr);
482 fprintf(stderr, "%.*s", tp->len, tp->t);
484 break;
486 default:
487 fputc(*ep, stderr);
488 break;
491 else
492 fputc(*ep, stderr);
494 va_end(ap);
495 fputc('\n', stderr);
496 if (type == FATAL)
497 exit(-1);
498 if (type != WARNING)
499 nerrs += 1;
500 fflush(stderr);