* added compilers lcc and bcc (linux86)
[mascara-docs.git] / compilers / lcc / cpp / .svn / text-base / eval.c.svn-base
blob95a9e1194bcf64d0c3d68bfa29a9e96c4cdb456f
1 #include <stdlib.h>
2 #include <string.h>
3 #include "cpp.h"
5 #define NSTAK   32
6 #define SGN     0
7 #define UNS     1
8 #define UND     2
10 #define UNSMARK 0x1000
12 struct value {
13         long    val;
14         int     type;
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
25 /* operator priority, arity, and conversion type, indexed by tokentype */
26 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 */
93 int     evalop(struct pri);
94 struct  value tokval(Token *);
95 struct value vals[NSTAK], *vp;
96 enum toktype ops[NSTAK], *op;
99  * Evaluate an #if #elif #ifdef #ifndef line.  trp->tp points to the keyword.
100  */
101 long
102 eval(Tokenrow *trp, int kw)
104         Token *tp;
105         Nlist *np;
106         int ntok, rand;
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>");
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                 switch(tp->type) {
126                 case WS:
127                 case NL:
128                         continue;
130                 /* nilary */
131                 case NAME:
132                 case NAME1:
133                 case NUMBER:
134                 case CCON:
135                 case STRING:
136                         if (rand)
137                                 goto syntax;
138                         *vp++ = tokval(tp);
139                         rand = 1;
140                         continue;
142                 /* unary */
143                 case DEFINED:
144                 case TILDE:
145                 case NOT:
146                         if (rand)
147                                 goto syntax;
148                         *op++ = tp->type;
149                         continue;
151                 /* unary-binary */
152                 case PLUS: case MINUS: case STAR: case AND:
153                         if (rand==0) {
154                                 if (tp->type==MINUS)
155                                         *op++ = UMINUS;
156                                 if (tp->type==STAR || tp->type==AND) {
157                                         error(ERROR, "Illegal operator * or & in #if/#elsif");
158                                         return 0;
159                                 }
160                                 continue;
161                         }
162                         /* flow through */
164                 /* plain binary */
165                 case EQ: case NEQ: case LEQ: case GEQ: case LSH: case RSH:
166                 case LAND: case LOR: case SLASH: case PCT:
167                 case LT: case GT: case CIRC: case OR: case QUEST:
168                 case COLON: case COMMA:
169                         if (rand==0)
170                                 goto syntax;
171                         if (evalop(priority[tp->type])!=0)
172                                 return 0;
173                         *op++ = tp->type;
174                         rand = 0;
175                         continue;
177                 case LP:
178                         if (rand)
179                                 goto syntax;
180                         *op++ = LP;
181                         continue;
183                 case RP:
184                         if (!rand)
185                                 goto syntax;
186                         if (evalop(priority[RP])!=0)
187                                 return 0;
188                         if (op<=ops || op[-1]!=LP) {
189                                 goto syntax;
190                         }
191                         op--;
192                         continue;
194                 default:
195                         error(ERROR,"Bad operator (%t) in #if/#elsif", tp);
196                         return 0;
197                 }
198         }
199         if (rand==0)
200                 goto syntax;
201         if (evalop(priority[END])!=0)
202                 return 0;
203         if (op!=&ops[1] || vp!=&vals[1]) {
204                 error(ERROR, "Botch in #if/#elsif");
205                 return 0;
206         }
207         if (vals[0].type==UND)
208                 error(ERROR, "Undefined expression value");
209         return vals[0].val;
210 syntax:
211         error(ERROR, "Syntax error in #if/#elsif");
212         return 0;
216 evalop(struct pri pri)
218         struct value v1, v2;
219         long rv1, rv2;
220         int rtype, oper;
222         /* prevent compiler whining. */
223         v1.val = v2.val = 0;
224         v1.type = v2.type = 0;
226         rv2=0;
227         rtype=0;
228         while (pri.pri < priority[op[-1]].pri) {
229                 oper = *--op;
230                 if (priority[oper].arity==2) {
231                         v2 = *--vp;
232                         rv2 = v2.val;
233                 }
234                 v1 = *--vp;
235                 rv1 = v1.val;
236 /*lint -e574 -e644 */
237                 switch (priority[oper].ctype) {
238                 case 0:
239                 default:
240                         error(WARNING, "Syntax error in #if/#endif");
241                         return 1;
242                 case ARITH:
243                 case RELAT:
244                         if (v1.type==UNS || v2.type==UNS)
245                                 rtype = UNS;
246                         else
247                                 rtype = SGN;
248                         if (v1.type==UND || v2.type==UND)
249                                 rtype = UND;
250                         if (priority[oper].ctype==RELAT && rtype==UNS) {
251                                 oper |= UNSMARK;
252                                 rtype = SGN;
253                         }
254                         break;
255                 case SHIFT:
256                         if (v1.type==UND || v2.type==UND)
257                                 rtype = UND;
258                         else
259                                 rtype = v1.type;
260                         if (rtype==UNS)
261                                 oper |= UNSMARK;
262                         break;
263                 case UNARY:
264                         rtype = v1.type;
265                         break;
266                 case LOGIC:
267                 case SPCL:
268                         break;
269                 }
270                 switch (oper) {
271                 case EQ: case EQ|UNSMARK:
272                         rv1 = rv1==rv2; break;
273                 case NEQ: case NEQ|UNSMARK:
274                         rv1 = rv1!=rv2; break;
275                 case LEQ:
276                         rv1 = rv1<=rv2; break;
277                 case GEQ:
278                         rv1 = rv1>=rv2; break;
279                 case LT:
280                         rv1 = rv1<rv2; break;
281                 case GT:
282                         rv1 = rv1>rv2; break;
283                 case LEQ|UNSMARK:
284                         rv1 = (unsigned long)rv1<=rv2; break;
285                 case GEQ|UNSMARK:
286                         rv1 = (unsigned long)rv1>=rv2; break;
287                 case LT|UNSMARK:
288                         rv1 = (unsigned long)rv1<rv2; break;
289                 case GT|UNSMARK:
290                         rv1 = (unsigned long)rv1>rv2; break;
291                 case LSH:
292                         rv1 <<= rv2; break;
293                 case LSH|UNSMARK:
294                         rv1 = (unsigned long)rv1<<rv2; break;
295                 case RSH:
296                         rv1 >>= rv2; break;
297                 case RSH|UNSMARK:
298                         rv1 = (unsigned long)rv1>>rv2; break;
299                 case LAND:
300                         rtype = UND;
301                         if (v1.type==UND)
302                                 break;
303                         if (rv1!=0) {
304                                 if (v2.type==UND)
305                                         break;
306                                 rv1 = rv2!=0;
307                         } else
308                                 rv1 = 0;
309                         rtype = SGN;
310                         break;
311                 case LOR:
312                         rtype = UND;
313                         if (v1.type==UND)
314                                 break;
315                         if (rv1==0) {
316                                 if (v2.type==UND)
317                                         break;
318                                 rv1 = rv2!=0;
319                         } else
320                                 rv1 = 1;
321                         rtype = SGN;
322                         break;
323                 case AND:
324                         rv1 &= rv2; break;
325                 case STAR:
326                         rv1 *= rv2; break;
327                 case PLUS:
328                         rv1 += rv2; break;
329                 case MINUS:
330                         rv1 -= rv2; break;
331                 case UMINUS:
332                         if (v1.type==UND)
333                                 rtype = UND;
334                         rv1 = -rv1; break;
335                 case OR:
336                         rv1 |= rv2; break;
337                 case CIRC:
338                         rv1 ^= rv2; break;
339                 case TILDE:
340                         rv1 = ~rv1; break;
341                 case NOT:
342                         rv1 = !rv1; if (rtype!=UND) rtype = SGN; break;
343                 case SLASH:
344                         if (rv2==0) {
345                                 rtype = UND;
346                                 break;
347                         }
348                         if (rtype==UNS)
349                                 rv1 /= (unsigned long)rv2;
350                         else
351                                 rv1 /= rv2;
352                         break;
353                 case PCT:
354                         if (rv2==0) {
355                                 rtype = UND;
356                                 break;
357                         }
358                         if (rtype==UNS)
359                                 rv1 %= (unsigned long)rv2;
360                         else
361                                 rv1 %= rv2;
362                         break;
363                 case COLON:
364                         if (op[-1] != QUEST)
365                                 error(ERROR, "Bad ?: in #if/endif");
366                         else {
367                                 op--;
368                                 if ((--vp)->val==0)
369                                         v1 = v2;
370                                 rtype = v1.type;
371                                 rv1 = v1.val;
372                         }
373                         break;
374                 case DEFINED:
375                         break;
376                 default:
377                         error(ERROR, "Eval botch (unknown operator)");
378                         return 1;
379                 }
380 /*lint +e574 +e644 */
381                 v1.val = rv1;
382                 v1.type = rtype;
383                 *vp++ = v1;
384         }
385         return 0;
388 struct value
389 tokval(Token *tp)
391         struct value v;
392         Nlist *np;
393         int i, base, c;
394         unsigned long n;
395         uchar *p;
397         v.type = SGN;
398         v.val = 0;
399         switch (tp->type) {
401         case NAME:
402                 v.val = 0;
403                 break;
405         case NAME1:
406                 if ((np = lookup(tp, 0)) != NULL && np->flag&(ISDEFINED|ISMAC))
407                         v.val = 1;
408                 break;
410         case NUMBER:
411                 n = 0;
412                 base = 10;
413                 p = tp->t;
414                 c = p[tp->len];
415                 p[tp->len] = '\0';
416                 if (*p=='0') {
417                         base = 8;
418                         if (p[1]=='x' || p[1]=='X') {
419                                 base = 16;
420                                 p++;
421                         }
422                         p++;
423                 }
424                 for (;; p++) {
425                         if ((i = digit(*p)) < 0)
426                                 break;
427                         if (i>=base)
428                                 error(WARNING,
429                                   "Bad digit in number %t", tp);
430                         n *= base;
431                         n += i;
432                 }
433                 if (n>=0x80000000 && base!=10)
434                         v.type = UNS;
435                 for (; *p; p++) {
436                         if (*p=='u' || *p=='U')
437                                 v.type = UNS;
438                         else if (*p=='l' || *p=='L')
439                                 ;
440                         else {
441                                 error(ERROR,
442                                   "Bad number %t in #if/#elsif", tp);
443                                 break;
444                         }
445                 }
446                 v.val = n;
447                 tp->t[tp->len] = c;
448                 break;
450         case CCON:
451                 n = 0;
452                 p = tp->t;
453                 if (*p=='L') {
454                         p += 1;
455                         error(WARNING, "Wide char constant value undefined");
456                 }
457                 p += 1;
458                 if (*p=='\\') {
459                         p += 1;
460                         if ((i = digit(*p))>=0 && i<=7) {
461                                 n = i;
462                                 p += 1;
463                                 if ((i = digit(*p))>=0 && i<=7) {
464                                         p += 1;
465                                         n <<= 3;
466                                         n += i;
467                                         if ((i = digit(*p))>=0 && i<=7) {
468                                                 p += 1;
469                                                 n <<= 3;
470                                                 n += i;
471                                         }
472                                 }
473                         } else if (*p=='x') {
474                                 p += 1;
475                                 while ((i = digit(*p))>=0 && i<=15) {
476                                         p += 1;
477                                         n <<= 4;
478                                         n += i;
479                                 }
480                         } else {
481                                 static char cvcon[]
482                                   = "b\bf\fn\nr\rt\tv\v''\"\"??\\\\";
483                                 for (i=0; i<sizeof(cvcon); i+=2) {
484                                         if (*p == cvcon[i]) {
485                                                 n = cvcon[i+1];
486                                                 break;
487                                         }
488                                 }
489                                 p += 1;
490                                 if (i>=sizeof(cvcon))
491                                         error(WARNING,
492                                          "Undefined escape in character constant");
493                         }
494                 } else if (*p=='\'')
495                         error(ERROR, "Empty character constant");
496                 else
497                         n = *p++;
498                 if (*p!='\'')
499                         error(WARNING, "Multibyte character constant undefined");
500                 else if (n>127)
501                         error(WARNING, "Character constant taken as not signed");
502                 v.val = n;
503                 break;
505         case STRING:
506                 error(ERROR, "String in #if/#elsif");
507                 break;
508         }
509         return v;
513 digit(int i)
515         if ('0'<=i && i<='9')
516                 i -= '0';
517         else if ('a'<=i && i<='f')
518                 i -= 'a'-10;
519         else if ('A'<=i && i<='F')
520                 i -= 'A'-10;
521         else
522                 i = -1;
523         return i;