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