xref: /aoo41x/main/soltools/cpp/_cpp.c (revision cdf0e10c)
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <time.h>
5 #include <stdarg.h>
6 #include "cpp.h"
7 
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;
19 
20 char rcsid[] = "$Version 1.2 $ $Revision: 1.5 $ $Date: 2006-06-20 05:05:46 $";
21 
22 int
23 #ifdef _WIN32
24 __cdecl
25 #endif // _WIN32
26 	main(int argc, char **argv)
27 {
28 
29 	Tokenrow tr;
30 	time_t t;
31 	char ebuf[BUFSIZ];
32 
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);
46 }
47 
48 void
49     process(Tokenrow * trp)
50 {
51     int anymacros = 0;
52 
53     for (;;)
54     {
55         if (trp->tp >= trp->lp)
56         {
57             trp->tp = trp->lp = trp->bp;
58             outptr = outbuf;
59             anymacros |= gettokens(trp, 1);
60             trp->tp = trp->bp;
61         }
62         if (trp->tp->type == END)
63         {
64             if (--incdepth >= 0)
65             {
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;
75             }
76             if (ifdepth)
77                 error(ERROR, "Unterminated #if/#ifdef/#ifndef");
78             break;
79         }
80         if (trp->tp->type == SHARP)
81         {
82             trp->tp += 1;
83             control(trp);
84         }
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)
94         {
95             if (!Pflag)
96                 genline();
97         }
98     }
99 }
100 
101 void
102     control(Tokenrow * trp)
103 {
104     Nlist *np;
105     Token *tp;
106 
107     tp = trp->tp;
108     if (tp->type != NAME)
109     {
110         if (tp->type == NUMBER)
111             goto kline;
112         if (tp->type != NL)
113             error(ERROR, "Unidentifiable control line");
114         return;                         /* else empty line */
115     }
116     if ((np = lookup(tp, 0)) == NULL || ((np->flag & ISKW) == 0 && !skipping))
117     {
118         error(WARNING, "Unknown preprocessor control %t", tp);
119         return;
120     }
121     if (skipping)
122     {
123         switch (np->val)
124         {
125             case KENDIF:
126                 if (--ifdepth < skipping)
127                     skipping = 0;
128                 --cursource->ifdepth;
129                 setempty(trp);
130                 return;
131 
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;
139 
140             case KELIF:
141             case KELSE:
142                 if (ifdepth <= skipping)
143                     break;
144                 return;
145 
146             default:
147                 return;
148         }
149     }
150     switch (np->val)
151     {
152         case KDEFINE:
153             dodefine(trp);
154             break;
155 
156         case KUNDEF:
157             tp += 1;
158             if (tp->type != NAME || trp->lp - trp->bp != 4)
159             {
160                 error(ERROR, "Syntax error in #undef");
161                 break;
162             }
163             if ((np = lookup(tp, 0)) != NULL)
164 			{
165                 np->flag &= ~ISDEFINED;
166 
167 				if (Mflag)
168 				{
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);
173 				}
174 			}
175             break;
176 
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;
182 
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;
195 
196         case KELIF:
197             if (ifdepth == 0)
198             {
199                 error(ERROR, "#elif with no #if");
200                 return;
201             }
202             if (ifsatisfied[ifdepth] == 2)
203                 error(ERROR, "#elif after #else");
204             if (eval(trp, np->val))
205             {
206                 if (ifsatisfied[ifdepth])
207                     skipping = ifdepth;
208                 else
209                 {
210                     skipping = 0;
211                     ifsatisfied[ifdepth] = 1;
212                 }
213             }
214             else
215                 skipping = ifdepth;
216             break;
217 
218         case KELSE:
219             if (ifdepth == 0 || cursource->ifdepth == 0)
220             {
221                 error(ERROR, "#else with no #if");
222                 return;
223             }
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;
231 
232         case KENDIF:
233             if (ifdepth == 0 || cursource->ifdepth == 0)
234             {
235                 error(ERROR, "#endif with no #if");
236                 return;
237             }
238             --ifdepth;
239             --cursource->ifdepth;
240             if (trp->lp - trp->bp != 3)
241                 error(WARNING, "Syntax error in #endif");
242             break;
243 
244         case KERROR:
245             trp->tp = tp + 1;
246             error(WARNING, "#error directive: %r", trp);
247             break;
248 
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')))
257             {
258                 error(ERROR, "Syntax error in #line");
259                 return;
260             }
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;
268 
269         case KDEFINED:
270             error(ERROR, "Bad syntax for control line");
271             break;
272 
273 		case KIMPORT:
274             doinclude(trp, -1, 1);
275             trp->lp = trp->bp;
276 			return;
277 
278         case KINCLUDE:
279             doinclude(trp, -1, 0);
280             trp->lp = trp->bp;
281             return;
282 
283         case KINCLUDENEXT:
284             doinclude(trp, cursource->pathdepth, 0);
285             trp->lp = trp->bp;
286             return;
287 
288         case KEVAL:
289             eval(trp, np->val);
290             break;
291 
292         default:
293             error(ERROR, "Preprocessor control `%t' not yet implemented", tp);
294             break;
295     }
296     setempty(trp);
297     return;
298 }
299 
300 void *
301     domalloc(int size)
302 {
303     void *p = malloc(size);
304 
305     if (p == NULL)
306         error(FATAL, "Out of memory from malloc");
307     return p;
308 }
309 
310 void
311     dofree(void *p)
312 {
313     free(p);
314 }
315 
316 void
317     error(enum errtype type, char *string,...)
318 {
319     va_list ap;
320     char c, *cp, *ep;
321     Token *tp;
322     Tokenrow *trp;
323     Source *s;
324     int i;
325 
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++)
332     {
333         if (*ep == '%')
334         {
335             switch (*++ep)
336             {
337 
338                 case 'c':
339                     c = (char) va_arg(ap, int);
340                     fprintf(stderr, "%c", c);
341                     break;
342 
343 				case 's':
344                     cp = va_arg(ap, char *);
345                     fprintf(stderr, "%s", cp);
346                     break;
347 
348                 case 'd':
349                     i = va_arg(ap, int);
350                     fprintf(stderr, "%d", i);
351                     break;
352 
353                 case 't':
354                     tp = va_arg(ap, Token *);
355                     fprintf(stderr, "%.*s", (int)tp->len, tp->t);
356                     break;
357 
358                 case 'r':
359                     trp = va_arg(ap, Tokenrow *);
360                     for (tp = trp->tp; tp < trp->lp && tp->type != NL; tp++)
361                     {
362                         if (tp > trp->tp && tp->wslen)
363                             fputc(' ', stderr);
364                         fprintf(stderr, "%.*s", (int)tp->len, tp->t);
365                     }
366                     break;
367 
368                 default:
369                     fputc(*ep, stderr);
370                     break;
371             }
372         }
373         else
374             fputc(*ep, stderr);
375     }
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);
383 }
384