1 #include <u.h>
2 #include <libc.h>
3 #include "cpp.h"
4
5 #define NSTAK 1024
6 #define SGN 0
7 #define UNS 1
8 #define UND 2
9
10 #define UNSMARK 0x1000
11
12 struct value {
13 long val;
14 int type;
15 };
16
17 /* conversion types */
18 #define RELAT 1
19 #define ARITH 2
20 #define LOGIC 3
21 #define SPCL 4
22 #define SHIFT 5
23 #define UNARY 6
24
25 /* operator priority, arity, and conversion type, indexed by tokentype */
26 const struct pri {
27 char pri;
28 char arity;
29 char ctype;
30 } priority[] = {
31 { 0, 0, 0 }, /* END */
32 { 0, 0, 0 }, /* UNCLASS */
33 { 0, 0, 0 }, /* NAME */
34 { 0, 0, 0 }, /* NUMBER */
35 { 0, 0, 0 }, /* STRING */
36 { 0, 0, 0 }, /* CCON */
37 { 0, 0, 0 }, /* NL */
38 { 0, 0, 0 }, /* WS */
39 { 0, 0, 0 }, /* DSHARP */
40 { 11, 2, RELAT }, /* EQ */
41 { 11, 2, RELAT }, /* NEQ */
42 { 12, 2, RELAT }, /* LEQ */
43 { 12, 2, RELAT }, /* GEQ */
44 { 13, 2, SHIFT }, /* LSH */
45 { 13, 2, SHIFT }, /* RSH */
46 { 7, 2, LOGIC }, /* LAND */
47 { 6, 2, LOGIC }, /* LOR */
48 { 0, 0, 0 }, /* PPLUS */
49 { 0, 0, 0 }, /* MMINUS */
50 { 0, 0, 0 }, /* ARROW */
51 { 0, 0, 0 }, /* SBRA */
52 { 0, 0, 0 }, /* SKET */
53 { 3, 0, 0 }, /* LP */
54 { 3, 0, 0 }, /* RP */
55 { 0, 0, 0 }, /* DOT */
56 { 10, 2, ARITH }, /* AND */
57 { 15, 2, ARITH }, /* STAR */
58 { 14, 2, ARITH }, /* PLUS */
59 { 14, 2, ARITH }, /* MINUS */
60 { 16, 1, UNARY }, /* TILDE */
61 { 16, 1, UNARY }, /* NOT */
62 { 15, 2, ARITH }, /* SLASH */
63 { 15, 2, ARITH }, /* PCT */
64 { 12, 2, RELAT }, /* LT */
65 { 12, 2, RELAT }, /* GT */
66 { 9, 2, ARITH }, /* CIRC */
67 { 8, 2, ARITH }, /* OR */
68 { 5, 2, SPCL }, /* QUEST */
69 { 5, 2, SPCL }, /* COLON */
70 { 0, 0, 0 }, /* ASGN */
71 { 4, 2, 0 }, /* COMMA */
72 { 0, 0, 0 }, /* SHARP */
73 { 0, 0, 0 }, /* SEMIC */
74 { 0, 0, 0 }, /* CBRA */
75 { 0, 0, 0 }, /* CKET */
76 { 0, 0, 0 }, /* ASPLUS */
77 { 0, 0, 0 }, /* ASMINUS */
78 { 0, 0, 0 }, /* ASSTAR */
79 { 0, 0, 0 }, /* ASSLASH */
80 { 0, 0, 0 }, /* ASPCT */
81 { 0, 0, 0 }, /* ASCIRC */
82 { 0, 0, 0 }, /* ASLSH */
83 { 0, 0, 0 }, /* ASRSH */
84 { 0, 0, 0 }, /* ASOR */
85 { 0, 0, 0 }, /* ASAND */
86 { 0, 0, 0 }, /* ELLIPS */
87 { 0, 0, 0 }, /* DSHARP1 */
88 { 0, 0, 0 }, /* NAME1 */
89 { 16, 1, UNARY }, /* DEFINED */
90 { 16, 0, UNARY }, /* UMINUS */
91 };
92
93 int evalop(struct pri);
94 struct value tokval(Token *);
95 struct value vals[NSTAK + 1], *vp;
96 enum toktype ops[NSTAK + 1], *op;
97
98 /*
99 * Evaluate an #if #elif #ifdef #ifndef line. trp->tp points to the keyword.
100 */
101 long
eval(Tokenrow * trp,int kw)102 eval(Tokenrow *trp, int kw)
103 {
104 Token *tp;
105 Nlist *np;
106 int ntok, rand;
107
108 trp->tp++;
109 if (kw==KIFDEF || kw==KIFNDEF) {
110 if (trp->lp - trp->bp != 4 || trp->tp->type!=NAME) {
111 error(ERROR, "Syntax error in #ifdef/#ifndef");
112 return 0;
113 }
114 np = lookup(trp->tp, 0);
115 return (kw==KIFDEF) == (np && np->flag&(ISDEFINED|ISMAC));
116 }
117 ntok = trp->tp - trp->bp;
118 kwdefined->val = KDEFINED; /* activate special meaning of defined */
119 expandrow(trp, "<if>", Notinmacro);
120 kwdefined->val = NAME;
121 vp = vals;
122 op = ops;
123 *op++ = END;
124 for (rand=0, tp = trp->bp+ntok; tp < trp->lp; tp++) {
125 if(op >= ops + NSTAK)
126 sysfatal("cpp: can't evaluate #if: increase NSTAK");
127 switch(tp->type) {
128 case WS:
129 case NL:
130 continue;
131
132 /* nilary */
133 case NAME:
134 case NAME1:
135 case NUMBER:
136 case CCON:
137 case STRING:
138 if (rand)
139 goto syntax;
140 *vp++ = tokval(tp);
141 rand = 1;
142 continue;
143
144 /* unary */
145 case DEFINED:
146 case TILDE:
147 case NOT:
148 if (rand)
149 goto syntax;
150 *op++ = tp->type;
151 continue;
152
153 /* unary-binary */
154 case PLUS: case MINUS: case STAR: case AND:
155 if (rand==0) {
156 if (tp->type==MINUS)
157 *op++ = UMINUS;
158 if (tp->type==STAR || tp->type==AND) {
159 error(ERROR, "Illegal operator * or & in #if/#elif");
160 return 0;
161 }
162 continue;
163 }
164 /* flow through */
165
166 /* plain binary */
167 case EQ: case NEQ: case LEQ: case GEQ: case LSH: case RSH:
168 case LAND: case LOR: case SLASH: case PCT:
169 case LT: case GT: case CIRC: case OR: case QUEST:
170 case COLON: case COMMA:
171 if (rand==0)
172 goto syntax;
173 if (evalop(priority[tp->type])!=0)
174 return 0;
175 *op++ = tp->type;
176 rand = 0;
177 continue;
178
179 case LP:
180 if (rand)
181 goto syntax;
182 *op++ = LP;
183 continue;
184
185 case RP:
186 if (!rand)
187 goto syntax;
188 if (evalop(priority[RP])!=0)
189 return 0;
190 if (op<=ops || op[-1]!=LP) {
191 goto syntax;
192 }
193 op--;
194 continue;
195
196 default:
197 error(ERROR,"Bad operator (%t) in #if/#elif", tp);
198 return 0;
199 }
200 }
201 if (rand==0)
202 goto syntax;
203 if (evalop(priority[END])!=0)
204 return 0;
205 if (op!=&ops[1] || vp!=&vals[1]) {
206 error(ERROR, "Botch in #if/#elif");
207 return 0;
208 }
209 if (vals[0].type==UND)
210 error(ERROR, "Undefined expression value");
211 return vals[0].val;
212 syntax:
213 error(ERROR, "Syntax error in #if/#elif");
214 return 0;
215 }
216
217 int
evalop(struct pri pri)218 evalop(struct pri pri)
219 {
220 struct value v1, v2;
221 long rv1, rv2;
222 int rtype, oper;
223
224 rv2=0;
225 rtype=0;
226 while (pri.pri < priority[op[-1]].pri) {
227 oper = *--op;
228 if (priority[oper].arity==2) {
229 v2 = *--vp;
230 rv2 = v2.val;
231 }
232 v1 = *--vp;
233 rv1 = v1.val;
234 switch (priority[oper].ctype) {
235 case 0:
236 default:
237 error(WARNING, "Syntax error in #if/#endif");
238 return 1;
239 case ARITH:
240 case RELAT:
241 if (v1.type==UNS || v2.type==UNS)
242 rtype = UNS;
243 else
244 rtype = SGN;
245 if (v1.type==UND || v2.type==UND)
246 rtype = UND;
247 if (priority[oper].ctype==RELAT && rtype==UNS) {
248 oper |= UNSMARK;
249 rtype = SGN;
250 }
251 break;
252 case SHIFT:
253 if (v1.type==UND || v2.type==UND)
254 rtype = UND;
255 else
256 rtype = v1.type;
257 if (rtype==UNS)
258 oper |= UNSMARK;
259 break;
260 case UNARY:
261 rtype = v1.type;
262 break;
263 case LOGIC:
264 case SPCL:
265 break;
266 }
267 switch (oper) {
268 case EQ: case EQ|UNSMARK:
269 rv1 = rv1==rv2; break;
270 case NEQ: case NEQ|UNSMARK:
271 rv1 = rv1!=rv2; break;
272 case LEQ:
273 rv1 = rv1<=rv2; break;
274 case GEQ:
275 rv1 = rv1>=rv2; break;
276 case LT:
277 rv1 = rv1<rv2; break;
278 case GT:
279 rv1 = rv1>rv2; break;
280 case LEQ|UNSMARK:
281 rv1 = (unsigned long)rv1<=rv2; break;
282 case GEQ|UNSMARK:
283 rv1 = (unsigned long)rv1>=rv2; break;
284 case LT|UNSMARK:
285 rv1 = (unsigned long)rv1<rv2; break;
286 case GT|UNSMARK:
287 rv1 = (unsigned long)rv1>rv2; break;
288 case LSH:
289 rv1 <<= rv2; break;
290 case LSH|UNSMARK:
291 rv1 = (unsigned long)rv1<<rv2; break;
292 case RSH:
293 rv1 >>= rv2; break;
294 case RSH|UNSMARK:
295 rv1 = (unsigned long)rv1>>rv2; break;
296 case LAND:
297 rtype = UND;
298 if (v1.type==UND)
299 break;
300 if (rv1!=0) {
301 if (v2.type==UND)
302 break;
303 rv1 = rv2!=0;
304 } else
305 rv1 = 0;
306 rtype = SGN;
307 break;
308 case LOR:
309 rtype = UND;
310 if (v1.type==UND)
311 break;
312 if (rv1==0) {
313 if (v2.type==UND)
314 break;
315 rv1 = rv2!=0;
316 } else
317 rv1 = 1;
318 rtype = SGN;
319 break;
320 case AND:
321 rv1 &= rv2; break;
322 case STAR:
323 rv1 *= rv2; break;
324 case PLUS:
325 rv1 += rv2; break;
326 case MINUS:
327 rv1 -= rv2; break;
328 case UMINUS:
329 if (v1.type==UND)
330 rtype = UND;
331 rv1 = -rv1; break;
332 case OR:
333 rv1 |= rv2; break;
334 case CIRC:
335 rv1 ^= rv2; break;
336 case TILDE:
337 rv1 = ~rv1; break;
338 case NOT:
339 rv1 = !rv1; if (rtype!=UND) rtype = SGN; break;
340 case SLASH:
341 if (rv2==0) {
342 rtype = UND;
343 break;
344 }
345 if (rtype==UNS)
346 rv1 /= (unsigned long)rv2;
347 else
348 rv1 /= rv2;
349 break;
350 case PCT:
351 if (rv2==0) {
352 rtype = UND;
353 break;
354 }
355 if (rtype==UNS)
356 rv1 %= (unsigned long)rv2;
357 else
358 rv1 %= rv2;
359 break;
360 case COLON:
361 if (op[-1] != QUEST)
362 error(ERROR, "Bad ?: in #if/endif");
363 else {
364 op--;
365 if ((--vp)->val==0)
366 v1 = v2;
367 rtype = v1.type;
368 rv1 = v1.val;
369 }
370 break;
371 case DEFINED:
372 break;
373 default:
374 error(ERROR, "Eval botch (unknown operator)");
375 return 1;
376 }
377 v1.val = rv1;
378 v1.type = rtype;
379 *vp++ = v1;
380 }
381 return 0;
382 }
383
384 struct value
tokval(Token * tp)385 tokval(Token *tp)
386 {
387 struct value v;
388 Nlist *np;
389 int i, base, c, longcc;
390 unsigned long n;
391 Rune r;
392 uchar *p;
393
394 v.type = SGN;
395 v.val = 0;
396 switch (tp->type) {
397
398 case NAME:
399 v.val = 0;
400 break;
401
402 case NAME1:
403 if ((np = lookup(tp, 0)) && np->flag&(ISDEFINED|ISMAC))
404 v.val = 1;
405 break;
406
407 case NUMBER:
408 n = 0;
409 base = 10;
410 p = tp->t;
411 c = p[tp->len];
412 p[tp->len] = '\0';
413 if (*p=='0') {
414 base = 8;
415 if (p[1]=='x' || p[1]=='X') {
416 base = 16;
417 p++;
418 }
419 p++;
420 }
421 for (;; p++) {
422 if ((i = digit(*p)) < 0)
423 break;
424 if (i>=base)
425 error(WARNING,
426 "Bad digit in number %t", tp);
427 n *= base;
428 n += i;
429 }
430 if (n>=0x80000000 && base!=10)
431 v.type = UNS;
432 for (; *p; p++) {
433 if (*p=='u' || *p=='U')
434 v.type = UNS;
435 else if (*p=='l' || *p=='L')
436 {}
437 else {
438 error(ERROR,
439 "Bad number %t in #if/#elif", tp);
440 break;
441 }
442 }
443 v.val = n;
444 tp->t[tp->len] = c;
445 break;
446
447 case CCON:
448 n = 0;
449 p = tp->t;
450 longcc = 0;
451 if (*p=='L') {
452 p += 1;
453 longcc = 1;
454 }
455 p += 1;
456 if (*p=='\\') {
457 p += 1;
458 if ((i = digit(*p))>=0 && i<=7) {
459 n = i;
460 p += 1;
461 if ((i = digit(*p))>=0 && i<=7) {
462 p += 1;
463 n <<= 3;
464 n += i;
465 if ((i = digit(*p))>=0 && i<=7) {
466 p += 1;
467 n <<= 3;
468 n += i;
469 }
470 }
471 } else if (*p=='x') {
472 p += 1;
473 while ((i = digit(*p))>=0 && i<=15) {
474 p += 1;
475 n <<= 4;
476 n += i;
477 }
478 } else {
479 static char cvcon[]
480 = "a\ab\bf\fn\nr\rt\tv\v''\"\"??\\\\";
481 for (i=0; i<sizeof(cvcon); i+=2) {
482 if (*p == cvcon[i]) {
483 n = cvcon[i+1];
484 break;
485 }
486 }
487 p += 1;
488 if (i>=sizeof(cvcon))
489 error(WARNING,
490 "Undefined escape in character constant");
491 }
492 } else if (*p=='\'')
493 error(ERROR, "Empty character constant");
494 else {
495 i = chartorune(&r, (char*)p);
496 n = r;
497 p += i;
498 if (i>1 && longcc==0)
499 error(WARNING, "Undefined character constant");
500 }
501 if (*p!='\'')
502 error(WARNING, "Multibyte character constant undefined");
503 else if (n>127 && longcc==0)
504 error(WARNING, "Character constant taken as not signed");
505 v.val = n;
506 break;
507
508 case STRING:
509 error(ERROR, "String in #if/#elif");
510 break;
511 }
512 return v;
513 }
514
515 int
digit(int i)516 digit(int i)
517 {
518 if ('0'<=i && i<='9')
519 i -= '0';
520 else if ('a'<=i && i<='f')
521 i -= 'a'-10;
522 else if ('A'<=i && i<='F')
523 i -= 'A'-10;
524 else
525 i = -1;
526 return i;
527 }
528