Update ooo320-m1
[ooovba.git] / soltools / cpp / _cpp.c
blob40d6ad67d56a1b7effd7269dde07c633902f40be
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <time.h>
5 #include <stdarg.h>
6 #include "cpp.h"
8 #define OUTS 16384
9 char outbuf[OUTS];
10 char *outptr = outbuf;
11 Source *cursource;
12 int nerrs;
13 struct token nltoken = {NL, 0, 0, 1, (uchar *) "\n", 0};
14 char *curtime;
15 int incdepth;
16 int ifdepth;
17 int ifsatisfied[NIF];
18 int skipping;
20 char rcsid[] = "$Version 1.2 $ $Revision: 1.5 $ $Date: 2006-06-20 05:05:46 $";
22 int
23 #ifdef _WIN32
24 __cdecl
25 #endif // _WIN32
26 main(int argc, char **argv)
29 Tokenrow tr;
30 time_t t;
31 char ebuf[BUFSIZ];
33 setbuf(stderr, ebuf);
34 t = time(NULL);
35 curtime = ctime(&t);
36 maketokenrow(3, &tr);
37 expandlex();
38 setup(argc, argv);
39 fixlex();
40 if (!Pflag)
41 genline();
42 process(&tr);
43 flushout();
44 fflush(stderr);
45 exit(nerrs > 0);
48 void
49 process(Tokenrow * trp)
51 int anymacros = 0;
53 for (;;)
55 if (trp->tp >= trp->lp)
57 trp->tp = trp->lp = trp->bp;
58 outptr = outbuf;
59 anymacros |= gettokens(trp, 1);
60 trp->tp = trp->bp;
62 if (trp->tp->type == END)
64 if (--incdepth >= 0)
66 if (cursource->ifdepth)
67 error(ERROR,
68 "Unterminated conditional in #include");
69 unsetsource();
70 cursource->line += cursource->lineinc;
71 trp->tp = trp->lp;
72 if (!Pflag)
73 genline();
74 continue;
76 if (ifdepth)
77 error(ERROR, "Unterminated #if/#ifdef/#ifndef");
78 break;
80 if (trp->tp->type == SHARP)
82 trp->tp += 1;
83 control(trp);
85 else
86 if (!skipping && anymacros)
87 expandrow(trp, NULL);
88 if (skipping)
89 setempty(trp);
90 puttokens(trp);
91 anymacros = 0;
92 cursource->line += cursource->lineinc;
93 if (cursource->lineinc > 1)
95 if (!Pflag)
96 genline();
101 void
102 control(Tokenrow * trp)
104 Nlist *np;
105 Token *tp;
107 tp = trp->tp;
108 if (tp->type != NAME)
110 if (tp->type == NUMBER)
111 goto kline;
112 if (tp->type != NL)
113 error(ERROR, "Unidentifiable control line");
114 return; /* else empty line */
116 if ((np = lookup(tp, 0)) == NULL || ((np->flag & ISKW) == 0 && !skipping))
118 error(WARNING, "Unknown preprocessor control %t", tp);
119 return;
121 if (skipping)
123 switch (np->val)
125 case KENDIF:
126 if (--ifdepth < skipping)
127 skipping = 0;
128 --cursource->ifdepth;
129 setempty(trp);
130 return;
132 case KIFDEF:
133 case KIFNDEF:
134 case KIF:
135 if (++ifdepth >= NIF)
136 error(FATAL, "#if too deeply nested");
137 ++cursource->ifdepth;
138 return;
140 case KELIF:
141 case KELSE:
142 if (ifdepth <= skipping)
143 break;
144 return;
146 default:
147 return;
150 switch (np->val)
152 case KDEFINE:
153 dodefine(trp);
154 break;
156 case KUNDEF:
157 tp += 1;
158 if (tp->type != NAME || trp->lp - trp->bp != 4)
160 error(ERROR, "Syntax error in #undef");
161 break;
163 if ((np = lookup(tp, 0)) != NULL)
165 np->flag &= ~ISDEFINED;
167 if (Mflag)
169 if (np->ap)
170 error(INFO, "Macro deletion of %s(%r)", np->name, np->ap);
171 else
172 error(INFO, "Macro deletion of %s", np->name);
175 break;
177 case KPRAGMA:
178 case KIDENT:
179 for (tp = trp->tp - 1; ((tp->type != NL) && (tp < trp->lp)); tp++)
180 tp->type = UNCLASS;
181 return;
183 case KIFDEF:
184 case KIFNDEF:
185 case KIF:
186 if (++ifdepth >= NIF)
187 error(FATAL, "#if too deeply nested");
188 ++cursource->ifdepth;
189 ifsatisfied[ifdepth] = 0;
190 if (eval(trp, np->val))
191 ifsatisfied[ifdepth] = 1;
192 else
193 skipping = ifdepth;
194 break;
196 case KELIF:
197 if (ifdepth == 0)
199 error(ERROR, "#elif with no #if");
200 return;
202 if (ifsatisfied[ifdepth] == 2)
203 error(ERROR, "#elif after #else");
204 if (eval(trp, np->val))
206 if (ifsatisfied[ifdepth])
207 skipping = ifdepth;
208 else
210 skipping = 0;
211 ifsatisfied[ifdepth] = 1;
214 else
215 skipping = ifdepth;
216 break;
218 case KELSE:
219 if (ifdepth == 0 || cursource->ifdepth == 0)
221 error(ERROR, "#else with no #if");
222 return;
224 if (ifsatisfied[ifdepth] == 2)
225 error(ERROR, "#else after #else");
226 if (trp->lp - trp->bp != 3)
227 error(ERROR, "Syntax error in #else");
228 skipping = ifsatisfied[ifdepth] ? ifdepth : 0;
229 ifsatisfied[ifdepth] = 2;
230 break;
232 case KENDIF:
233 if (ifdepth == 0 || cursource->ifdepth == 0)
235 error(ERROR, "#endif with no #if");
236 return;
238 --ifdepth;
239 --cursource->ifdepth;
240 if (trp->lp - trp->bp != 3)
241 error(WARNING, "Syntax error in #endif");
242 break;
244 case KERROR:
245 trp->tp = tp + 1;
246 error(WARNING, "#error directive: %r", trp);
247 break;
249 case KLINE:
250 trp->tp = tp + 1;
251 expandrow(trp, "<line>");
252 tp = trp->bp + 2;
253 kline:
254 if (tp + 1 >= trp->lp || tp->type != NUMBER || tp + 3 < trp->lp
255 || (tp + 3 == trp->lp
256 && ((tp + 1)->type != STRING || *(tp + 1)->t == 'L')))
258 error(ERROR, "Syntax error in #line");
259 return;
261 cursource->line = atol((char *) tp->t) - 1;
262 if (cursource->line < 0 || cursource->line >= 32768)
263 error(WARNING, "#line specifies number out of range");
264 tp = tp + 1;
265 if (tp + 1 < trp->lp)
266 cursource->filename = (char *) newstring(tp->t + 1, tp->len - 2, 0);
267 return;
269 case KDEFINED:
270 error(ERROR, "Bad syntax for control line");
271 break;
273 case KIMPORT:
274 doinclude(trp, -1, 1);
275 trp->lp = trp->bp;
276 return;
278 case KINCLUDE:
279 doinclude(trp, -1, 0);
280 trp->lp = trp->bp;
281 return;
283 case KINCLUDENEXT:
284 doinclude(trp, cursource->pathdepth, 0);
285 trp->lp = trp->bp;
286 return;
288 case KEVAL:
289 eval(trp, np->val);
290 break;
292 default:
293 error(ERROR, "Preprocessor control `%t' not yet implemented", tp);
294 break;
296 setempty(trp);
297 return;
300 void *
301 domalloc(int size)
303 void *p = malloc(size);
305 if (p == NULL)
306 error(FATAL, "Out of memory from malloc");
307 return p;
310 void
311 dofree(void *p)
313 free(p);
316 void
317 error(enum errtype type, char *string,...)
319 va_list ap;
320 char c, *cp, *ep;
321 Token *tp;
322 Tokenrow *trp;
323 Source *s;
324 int i;
326 fprintf(stderr, "cpp: ");
327 for (s = cursource; s; s = s->next)
328 if (*s->filename)
329 fprintf(stderr, "%s:%d ", s->filename, s->line);
330 va_start(ap, string);
331 for (ep = string; *ep; ep++)
333 if (*ep == '%')
335 switch (*++ep)
338 case 'c':
339 c = (char) va_arg(ap, int);
340 fprintf(stderr, "%c", c);
341 break;
343 case 's':
344 cp = va_arg(ap, char *);
345 fprintf(stderr, "%s", cp);
346 break;
348 case 'd':
349 i = va_arg(ap, int);
350 fprintf(stderr, "%d", i);
351 break;
353 case 't':
354 tp = va_arg(ap, Token *);
355 fprintf(stderr, "%.*s", (int)tp->len, tp->t);
356 break;
358 case 'r':
359 trp = va_arg(ap, Tokenrow *);
360 for (tp = trp->tp; tp < trp->lp && tp->type != NL; tp++)
362 if (tp > trp->tp && tp->wslen)
363 fputc(' ', stderr);
364 fprintf(stderr, "%.*s", (int)tp->len, tp->t);
366 break;
368 default:
369 fputc(*ep, stderr);
370 break;
373 else
374 fputc(*ep, stderr);
376 va_end(ap);
377 fputc('\n', stderr);
378 if (type == FATAL)
379 exit(1);
380 if (type != WARNING)
381 nerrs = 1;
382 fflush(stderr);