]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/cpp/cpp.c
upas/fs: remove useless loop in rf822()
[plan9front.git] / sys / src / cmd / cpp / cpp.c
1 #include <u.h>
2 #include <libc.h>
3 #include <stdio.h>
4 #include "cpp.h"
5
6 #define OUTS    16384
7 char    outbuf[OUTS];
8 char    *outp = outbuf;
9 Source  *cursource;
10 int     nerrs;
11 struct  token nltoken = { NL, 0, 0, 0, 1, (uchar*)"\n" };
12 char    *curtime;
13 int     incdepth;
14 int     ifdepth;
15 int     ifsatisfied[NIF];
16 int     skipping;
17
18 int
19 main(int argc, char **argv)
20 {
21         Tokenrow tr;
22         long t;
23         char ebuf[BUFSIZ];
24
25         setbuf(stderr, ebuf);
26         t = time(NULL);
27         curtime = ctime(t);
28         maketokenrow(3, &tr);
29         expandlex();
30         setup(argc, argv);
31         iniths();
32         genline();
33         process(&tr);
34         flushout();
35         fflush(stderr);
36         exits(nerrs? "errors" : 0);
37         return 0;
38 }
39
40 void
41 process(Tokenrow *trp)
42 {
43         int anymacros = 0;
44
45         for (;;) {
46                 if (trp->tp >= trp->lp) {
47                         trp->tp = trp->lp = trp->bp;
48                         outp = outbuf;
49                         anymacros |= gettokens(trp, 1);
50                         trp->tp = trp->bp;
51                 }
52                 if (trp->tp->type == END) {
53                         if (--incdepth>=0) {
54                                 if (cursource->ifdepth)
55                                         error(ERROR,
56                                          "Unterminated conditional in #include");
57                                 unsetsource();
58                                 cursource->line += cursource->lineinc;
59                                 trp->tp = trp->lp;
60                                 genline();
61                                 continue;
62                         }
63                         if (ifdepth)
64                                 error(ERROR, "Unterminated #if/#ifdef/#ifndef");
65                         break;
66                 }
67                 if (trp->tp->type==SHARP) {
68                         trp->tp += 1;
69                         control(trp);
70                 } else if (!skipping && anymacros)
71                         expandrow(trp, NULL, Notinmacro);
72                 if (skipping)
73                         setempty(trp);
74                 puttokens(trp);
75                 anymacros = 0;
76                 cursource->line += cursource->lineinc;
77                 if (cursource->lineinc>1) {
78                         genline();
79                 }
80         }
81 }
82         
83 void
84 control(Tokenrow *trp)
85 {
86         Nlist *np;
87         Token *tp;
88
89         tp = trp->tp;
90         if (tp->type!=NAME) {
91                 if (tp->type==NUMBER)
92                         goto kline;
93                 if (tp->type != NL)
94                         error(ERROR, "Unidentifiable control line");
95                 return;                 /* else empty line */
96         }
97         if ((np = lookup(tp, 0))==NULL || (np->flag&ISKW)==0 && !skipping) {
98                 error(WARNING, "Unknown preprocessor control %t", tp);
99                 return;
100         }
101         if (skipping) {
102                 if ((np->flag&ISKW)==0)
103                         return;
104                 switch (np->val) {
105                 case KENDIF:
106                         if (--ifdepth<skipping)
107                                 skipping = 0;
108                         --cursource->ifdepth;
109                         setempty(trp);
110                         return;
111
112                 case KIFDEF:
113                 case KIFNDEF:
114                 case KIF:
115                         if (++ifdepth >= NIF)
116                                 error(FATAL, "#if too deeply nested");
117                         ++cursource->ifdepth;
118                         return;
119
120                 case KELIF:
121                 case KELSE:
122                         if (ifdepth<=skipping)
123                                 break;
124                         return;
125
126                 default:
127                         return;
128                 }
129         }
130         switch (np->val) {
131         case KDEFINE:
132                 dodefine(trp);
133                 break;
134
135         case KUNDEF:
136                 tp += 1;
137                 if (tp->type!=NAME || trp->lp - trp->bp != 4) {
138                         error(ERROR, "Syntax error in #undef");
139                         break;
140                 }
141                 if ((np = lookup(tp, 0))) {
142                         if (np->flag&ISUNCHANGE) {
143                                 error(ERROR, "#defined token %t can't be undefined", tp);
144                                 return;
145                         }
146                         np->flag &= ~ISDEFINED;
147                 }
148                 break;
149
150         case KPRAGMA:
151                 return;
152
153         case KIFDEF:
154         case KIFNDEF:
155         case KIF:
156                 if (++ifdepth >= NIF)
157                         error(FATAL, "#if too deeply nested");
158                 ++cursource->ifdepth;
159                 ifsatisfied[ifdepth] = 0;
160                 if (eval(trp, np->val))
161                         ifsatisfied[ifdepth] = 1;
162                 else
163                         skipping = ifdepth;
164                 break;
165
166         case KELIF:
167                 if (ifdepth==0) {
168                         error(ERROR, "#elif with no #if");
169                         return;
170                 }
171                 if (ifsatisfied[ifdepth]==2)
172                         error(ERROR, "#elif after #else");
173                 if (eval(trp, np->val)) {
174                         if (ifsatisfied[ifdepth])
175                                 skipping = ifdepth;
176                         else {
177                                 skipping = 0;
178                                 ifsatisfied[ifdepth] = 1;
179                         }
180                 } else
181                         skipping = ifdepth;
182                 break;
183
184         case KELSE:
185                 if (ifdepth==0 || cursource->ifdepth==0) {
186                         error(ERROR, "#else with no #if");
187                         return;
188                 }
189                 if (ifsatisfied[ifdepth]==2)
190                         error(ERROR, "#else after #else");
191                 if (trp->lp - trp->bp != 3)
192                         error(ERROR, "Syntax error in #else");
193                 skipping = ifsatisfied[ifdepth]? ifdepth: 0;
194                 ifsatisfied[ifdepth] = 2;
195                 break;
196
197         case KENDIF:
198                 if (ifdepth==0 || cursource->ifdepth==0) {
199                         error(ERROR, "#endif with no #if");
200                         return;
201                 }
202                 --ifdepth;
203                 --cursource->ifdepth;
204                 if (trp->lp - trp->bp != 3)
205                         error(WARNING, "Syntax error in #endif");
206                 break;
207
208         case KERROR:
209                 trp->tp = tp+1;
210                 error(ERROR, "#error directive: %r", trp);
211                 break;
212
213         case KWARNING:
214                 trp->tp = tp+1;
215                 error(WARNING, "#warning directive: %r", trp);
216                 break;
217
218         case KLINE:
219                 trp->tp = tp+1;
220                 expandrow(trp, "<line>", Notinmacro);
221                 tp = trp->bp+2;
222         kline:
223                 if (tp+1>=trp->lp || tp->type!=NUMBER || tp+3<trp->lp
224                  || (tp+3==trp->lp && ((tp+1)->type!=STRING)||*(tp+1)->t=='L')){
225                         error(ERROR, "Syntax error in #line");
226                         return;
227                 }
228                 cursource->line = atol((char*)tp->t)-1;
229                 if (cursource->line<0 || cursource->line>=32768)
230                         error(WARNING, "#line specifies number out of range");
231                 tp = tp+1;
232                 if (tp+1<trp->lp)
233                         cursource->filename=(char*)newstring(tp->t+1,tp->len-2,0);
234                 return;
235
236         case KDEFINED:
237                 error(ERROR, "Bad syntax for control line");
238                 break;
239
240         case KINCLUDE:
241                 doinclude(trp);
242                 trp->lp = trp->bp;
243                 return;
244
245         case KEVAL:
246                 eval(trp, np->val);
247                 break;
248
249         default:
250                 error(ERROR, "Preprocessor control `%t' not yet implemented", tp);
251                 break;
252         }
253         setempty(trp);
254         return;
255 }
256
257 void *
258 dorealloc(void *ptr, int size)
259 {
260         void *p = realloc(ptr, size);
261
262         if (p==NULL)
263                 error(FATAL, "Out of memory from realloc");
264         return p;
265 }
266
267 void *
268 domalloc(int size)
269 {
270         void *p = malloc(size);
271
272         if (p==NULL)
273                 error(FATAL, "Out of memory from malloc");
274         return p;
275 }
276
277 void
278 dofree(void *p)
279 {
280         free(p);
281 }
282
283 void
284 error(enum errtype type, char *string, ...)
285 {
286         va_list ap;
287         char *cp, *ep;
288         Token *tp;
289         Tokenrow *trp;
290         Source *s;
291         int i;
292         void *p;
293
294         fprintf(stderr, "cpp: ");
295         for (s=cursource; s; s=s->next)
296                 if (*s->filename)
297                         fprintf(stderr, "%s:%d ", s->filename, s->line);
298         va_start(ap, string);
299         for (ep=string; *ep; ep++) {
300                 if (*ep=='%') {
301                         switch (*++ep) {
302
303                         case 's':
304                                 cp = va_arg(ap, char *);
305                                 fprintf(stderr, "%s", cp);
306                                 break;
307                         case 'd':
308                                 i = va_arg(ap, int);
309                                 fprintf(stderr, "%d", i);
310                                 break;
311                         case 'p':
312                                 p = va_arg(ap, void *);
313                                 fprintf(stderr, "%p", p);
314                                 break;
315                         case 't':
316                                 tp = va_arg(ap, Token *);
317                                 fprintf(stderr, "%.*s", tp->len, tp->t);
318                                 break;
319
320                         case 'r':
321                                 trp = va_arg(ap, Tokenrow *);
322                                 for (tp=trp->tp; tp<trp->lp&&tp->type!=NL; tp++) {
323                                         if (tp>trp->tp && tp->wslen)
324                                                 fputc(' ', stderr);
325                                         fprintf(stderr, "%.*s", tp->len, tp->t);
326                                 }
327                                 break;
328
329                         default:
330                                 fputc(*ep, stderr);
331                                 break;
332                         }
333                 } else
334                         fputc(*ep, stderr);
335         }
336         va_end(ap);
337         fputc('\n', stderr);
338         if (type==FATAL)
339                 exits("error");
340         if (type!=WARNING)
341                 nerrs = 1;
342         fflush(stderr);
343 }