xref: /trunk/main/soltools/cpp/_eval.c (revision cdf0e10c)
1 #include "cpp.h"
2 
3 #include <stdlib.h>
4 #include <string.h>
5 
6 #define	NSTAK	32
7 #define	SGN	0
8 #define	UNS	1
9 #define	UND	2
10 
11 #define	UNSMARK	0x1000
12 
13 struct value
14 {
15     long val;
16     int type;
17 };
18 
19 /* conversion types */
20 #define	RELAT	1
21 #define	ARITH	2
22 #define	LOGIC	3
23 #define	SPCL	4
24 #define	SHIFT	5
25 #define	UNARY	6
26 
27 /* operator priority, arity, and conversion type, indexed by tokentype */
28 struct pri
29 {
30     char pri;
31     char arity;
32     char ctype;
33 }   priority[] =
34 
35 {
36     {
37         0, 0, 0
38     },                                  /* END */
39     {
40         0, 0, 0
41     },                                  /* UNCLASS */
42     {
43         0, 0, 0
44     },                                  /* NAME */
45     {
46         0, 0, 0
47     },                                  /* NUMBER */
48     {
49         0, 0, 0
50     },                                  /* STRING */
51     {
52         0, 0, 0
53     },                                  /* CCON */
54     {
55         0, 0, 0
56     },                                  /* NL */
57     {
58         0, 0, 0
59     },                                  /* WS */
60     {
61         0, 0, 0
62     },                                  /* DSHARP */
63     {
64         11, 2, RELAT
65     },                                  /* EQ */
66     {
67         11, 2, RELAT
68     },                                  /* NEQ */
69     {
70         12, 2, RELAT
71     },                                  /* LEQ */
72     {
73         12, 2, RELAT
74     },                                  /* GEQ */
75     {
76         13, 2, SHIFT
77     },                                  /* LSH */
78     {
79         13, 2, SHIFT
80     },                                  /* RSH */
81     {
82         7, 2, LOGIC
83     },                                  /* LAND */
84     {
85         6, 2, LOGIC
86     },                                  /* LOR */
87     {
88         0, 0, 0
89     },                                  /* PPLUS */
90     {
91         0, 0, 0
92     },                                  /* MMINUS */
93     {
94         0, 0, 0
95     },                                  /* ARROW */
96     {
97         0, 0, 0
98     },                                  /* SBRA */
99     {
100         0, 0, 0
101     },                                  /* SKET */
102     {
103         3, 0, 0
104     },                                  /* LP */
105     {
106         3, 0, 0
107     },                                  /* RP */
108     {
109         0, 0, 0
110     },                                  /* DOT */
111     {
112         10, 2, ARITH
113     },                                  /* AND */
114     {
115         15, 2, ARITH
116     },                                  /* STAR */
117     {
118         14, 2, ARITH
119     },                                  /* PLUS */
120     {
121         14, 2, ARITH
122     },                                  /* MINUS */
123     {
124         16, 1, UNARY
125     },                                  /* TILDE */
126     {
127         16, 1, UNARY
128     },                                  /* NOT */
129     {
130         15, 2, ARITH
131     },                                  /* SLASH */
132     {
133         15, 2, ARITH
134     },                                  /* PCT */
135     {
136         12, 2, RELAT
137     },                                  /* LT */
138     {
139         12, 2, RELAT
140     },                                  /* GT */
141     {
142         9, 2, ARITH
143     },                                  /* CIRC */
144     {
145         8, 2, ARITH
146     },                                  /* OR */
147     {
148         5, 2, SPCL
149     },                                  /* QUEST */
150     {
151         5, 2, SPCL
152     },                                  /* COLON */
153     {
154         0, 0, 0
155     },                                  /* ASGN */
156     {
157         4, 2, 0
158     },                                  /* COMMA */
159     {
160         0, 0, 0
161     },                                  /* SHARP */
162     {
163         0, 0, 0
164     },                                  /* SEMIC */
165     {
166         0, 0, 0
167     },                                  /* CBRA */
168     {
169         0, 0, 0
170     },                                  /* CKET */
171     {
172         0, 0, 0
173     },                                  /* ASPLUS */
174     {
175         0, 0, 0
176     },                                  /* ASMINUS */
177     {
178         0, 0, 0
179     },                                  /* ASSTAR */
180     {
181         0, 0, 0
182     },                                  /* ASSLASH */
183     {
184         0, 0, 0
185     },                                  /* ASPCT */
186     {
187         0, 0, 0
188     },                                  /* ASCIRC */
189     {
190         0, 0, 0
191     },                                  /* ASLSH */
192     {
193         0, 0, 0
194     },                                  /* ASRSH */
195     {
196         0, 0, 0
197     },                                  /* ASOR */
198     {
199         0, 0, 0
200     },                                  /* ASAND */
201     {
202         0, 0, 0
203     },                                  /* ELLIPS */
204     {
205         0, 0, 0
206     },                                  /* DSHARP1 */
207     {
208         0, 0, 0
209     },                                  /* NAME1 */
210     {
211         0, 0, 0
212     },                                  /* NAME2 */
213     {
214         16, 1, UNARY
215     },                                  /* DEFINED */
216     {
217         16, 0, UNARY
218     },                                  /* UMINUS */
219     {
220         16, 1, UNARY
221     },                                  /* ARCHITECTURE */
222 };
223 
224 int evalop(struct pri);
225 struct value tokval(Token *);
226 struct value vals[NSTAK], *vp;
227 enum toktype ops[NSTAK], *op;
228 
229 /*
230  * Evaluate an #if #elif #ifdef #ifndef line.  trp->tp points to the keyword.
231  */
232 long
233     eval(Tokenrow * trp, int kw)
234 {
235     Token *tp;
236     Nlist *np;
237     int ntok, rnd;
238 
239     trp->tp++;
240     if (kw == KIFDEF || kw == KIFNDEF)
241     {
242         if (trp->lp - trp->bp != 4 || trp->tp->type != NAME)
243         {
244             error(ERROR, "Syntax error in #ifdef/#ifndef");
245             return 0;
246         }
247         np = lookup(trp->tp, 0);
248         return (kw == KIFDEF) == (np && np->flag & (ISDEFINED | ISMAC));
249     }
250     ntok = trp->tp - trp->bp;
251     kwdefined->val = KDEFINED;          /* activate special meaning of
252                                          * defined */
253     expandrow(trp, "<if>");
254     kwdefined->val = NAME;
255     vp = vals;
256     op = ops;
257     *op++ = END;
258     for (rnd = 0, tp = trp->bp + ntok; tp < trp->lp; tp++)
259     {
260         switch (tp->type)
261         {
262             case WS:
263             case NL:
264                 continue;
265 
266                 /* nilary */
267             case NAME:
268             case NAME1:
269             case NAME2:
270             case NUMBER:
271             case CCON:
272             case STRING:
273                 if (rnd)
274                     goto syntax;
275                 *vp++ = tokval(tp);
276                 rnd = 1;
277                 continue;
278 
279                 /* unary */
280             case DEFINED:
281             case TILDE:
282             case NOT:
283                 if (rnd)
284                     goto syntax;
285                 *op++ = tp->type;
286                 continue;
287 
288                 /* unary-binary */
289             case PLUS:
290             case MINUS:
291             case STAR:
292             case AND:
293                 if (rnd == 0)
294                 {
295                     if (tp->type == MINUS)
296                         *op++ = UMINUS;
297                     if (tp->type == STAR || tp->type == AND)
298                     {
299                         error(ERROR, "Illegal operator * or & in #if/#elsif");
300                         return 0;
301                     }
302                     continue;
303                 }
304                 /* flow through */
305 
306                 /* plain binary */
307             case EQ:
308             case NEQ:
309             case LEQ:
310             case GEQ:
311             case LSH:
312             case RSH:
313             case LAND:
314             case LOR:
315             case SLASH:
316             case PCT:
317             case LT:
318             case GT:
319             case CIRC:
320             case OR:
321             case QUEST:
322             case COLON:
323             case COMMA:
324                 if (rnd == 0)
325                     goto syntax;
326                 if (evalop(priority[tp->type]) != 0)
327                     return 0;
328                 *op++ = tp->type;
329                 rnd = 0;
330                 continue;
331 
332             case LP:
333                 if (rnd)
334                     goto syntax;
335                 *op++ = LP;
336                 continue;
337 
338             case RP:
339                 if (!rnd)
340                     goto syntax;
341                 if (evalop(priority[RP]) != 0)
342                     return 0;
343                 if (op <= ops || op[-1] != LP)
344                 {
345                     goto syntax;
346                 }
347                 op--;
348                 continue;
349 
350             case SHARP:
351                 if ((tp + 1) < trp->lp)
352                 {
353                     np = lookup(tp + 1, 0);
354                     if (np && (np->val == KMACHINE))
355                     {
356                         tp++;
357                         if (rnd)
358                             goto syntax;
359                         *op++ = ARCHITECTURE;
360                         continue;
361                     }
362                 }
363                 /* fall through */
364 
365             default:
366                 error(ERROR, "Bad operator (%t) in #if/#elsif", tp);
367                 return 0;
368         }
369     }
370     if (rnd == 0)
371         goto syntax;
372     if (evalop(priority[END]) != 0)
373         return 0;
374     if (op != &ops[1] || vp != &vals[1])
375     {
376         error(ERROR, "Botch in #if/#elsif");
377         return 0;
378     }
379     if (vals[0].type == UND)
380         error(ERROR, "Undefined expression value");
381     return vals[0].val;
382 syntax:
383     error(ERROR, "Syntax error in #if/#elsif");
384     return 0;
385 }
386 
387 int
388     evalop(struct pri pri)
389 {
390     struct value v1;
391     struct value v2 = { 0, UND };
392     long rv1, rv2;
393     int rtype, oper;
394 
395     rv2 = 0;
396     rtype = 0;
397     while (pri.pri < priority[op[-1]].pri)
398     {
399         oper = *--op;
400         if (priority[oper].arity == 2)
401         {
402             v2 = *--vp;
403             rv2 = v2.val;
404         }
405         v1 = *--vp;
406         rv1 = v1.val;
407 /*lint -e574 -e644 */
408         switch (priority[oper].ctype)
409         {
410             case 0:
411             default:
412                 error(WARNING, "Syntax error in #if/#endif");
413                 return 1;
414             case ARITH:
415             case RELAT:
416                 if (v1.type == UNS || v2.type == UNS)
417                     rtype = UNS;
418                 else
419                     rtype = SGN;
420                 if (v1.type == UND || v2.type == UND)
421                     rtype = UND;
422                 if (priority[oper].ctype == RELAT && rtype == UNS)
423                 {
424                     oper |= UNSMARK;
425                     rtype = SGN;
426                 }
427                 break;
428             case SHIFT:
429                 if (v1.type == UND || v2.type == UND)
430                     rtype = UND;
431                 else
432                     rtype = v1.type;
433                 if (rtype == UNS)
434                     oper |= UNSMARK;
435                 break;
436             case UNARY:
437                 rtype = v1.type;
438                 break;
439             case LOGIC:
440             case SPCL:
441                 break;
442         }
443         switch (oper)
444         {
445             case EQ:
446             case EQ | UNSMARK:
447                 rv1 = rv1 == rv2;
448                 break;
449             case NEQ:
450             case NEQ | UNSMARK:
451                 rv1 = rv1 != rv2;
452                 break;
453             case LEQ:
454                 rv1 = rv1 <= rv2;
455                 break;
456             case GEQ:
457                 rv1 = rv1 >= rv2;
458                 break;
459             case LT:
460                 rv1 = rv1 < rv2;
461                 break;
462             case GT:
463                 rv1 = rv1 > rv2;
464                 break;
465             case LEQ | UNSMARK:
466                 rv1 = (unsigned long)rv1 <= (unsigned long)rv2;
467                 break;
468             case GEQ | UNSMARK:
469                 rv1 = (unsigned long)rv1 >= (unsigned long)rv2;
470                 break;
471             case LT | UNSMARK:
472                 rv1 = (unsigned long)rv1 < (unsigned long)rv2;
473                 break;
474             case GT | UNSMARK:
475                 rv1 = (unsigned long)rv1 > (unsigned long)rv2;
476                 break;
477             case LSH:
478                 rv1 <<= rv2;
479                 break;
480             case LSH | UNSMARK:
481                 rv1 = (unsigned long) rv1 << rv2;
482                 break;
483             case RSH:
484                 rv1 >>= rv2;
485                 break;
486             case RSH | UNSMARK:
487                 rv1 = (unsigned long) rv1 >> rv2;
488                 break;
489             case LAND:
490                 rtype = UND;
491                 if (v1.type == UND)
492                     break;
493                 if (rv1 != 0)
494                 {
495                     if (v2.type == UND)
496                         break;
497                     rv1 = rv2 != 0;
498                 }
499                 else
500                     rv1 = 0;
501                 rtype = SGN;
502                 break;
503             case LOR:
504                 rtype = UND;
505                 if (v1.type == UND)
506                     break;
507                 if (rv1 == 0)
508                 {
509                     if (v2.type == UND)
510                         break;
511                     rv1 = rv2 != 0;
512                 }
513                 else
514                     rv1 = 1;
515                 rtype = SGN;
516                 break;
517             case AND:
518                 rv1 &= rv2;
519                 break;
520             case STAR:
521                 rv1 *= rv2;
522                 break;
523             case PLUS:
524                 rv1 += rv2;
525                 break;
526             case MINUS:
527                 rv1 -= rv2;
528                 break;
529             case UMINUS:
530                 if (v1.type == UND)
531                     rtype = UND;
532                 rv1 = -rv1;
533                 break;
534             case OR:
535                 rv1 |= rv2;
536                 break;
537             case CIRC:
538                 rv1 ^= rv2;
539                 break;
540             case TILDE:
541                 rv1 = ~rv1;
542                 break;
543             case NOT:
544                 rv1 = !rv1;
545                 if (rtype != UND)
546                     rtype = SGN;
547                 break;
548             case SLASH:
549                 if (rv2 == 0)
550                 {
551                     rtype = UND;
552                     break;
553                 }
554                 if (rtype == UNS)
555                     rv1 /= (unsigned long) rv2;
556                 else
557                     rv1 /= rv2;
558                 break;
559             case PCT:
560                 if (rv2 == 0)
561                 {
562                     rtype = UND;
563                     break;
564                 }
565                 if (rtype == UNS)
566                     rv1 %= (unsigned long) rv2;
567                 else
568                     rv1 %= rv2;
569                 break;
570             case COLON:
571                 if (op[-1] != QUEST)
572                     error(ERROR, "Bad ?: in #if/endif");
573                 else
574                 {
575                     op--;
576                     if ((--vp)->val == 0)
577                         v1 = v2;
578                     rtype = v1.type;
579                     rv1 = v1.val;
580                 }
581                 break;
582 
583             case DEFINED:
584             case ARCHITECTURE:
585                 break;
586 
587             default:
588                 error(ERROR, "Eval botch (unknown operator)");
589                 return 1;
590         }
591 /*lint +e574 +e644 */
592         v1.val = rv1;
593         v1.type = rtype;
594         *vp++ = v1;
595     }
596     return 0;
597 }
598 
599 struct value
600     tokval(Token * tp)
601 {
602     struct value v;
603     Nlist *np;
604     int i, base;
605     unsigned long n;
606     uchar *p, c;
607 
608     v.type = SGN;
609     v.val = 0;
610     switch (tp->type)
611     {
612 
613         case NAME:
614             v.val = 0;
615             break;
616 
617         case NAME1:
618             if ((np = lookup(tp, 0)) != NULL && np->flag & (ISDEFINED | ISMAC))
619                 v.val = 1;
620             break;
621 
622         case NAME2:
623             if ((np = lookup(tp, 0)) != NULL && np->flag & (ISARCHITECTURE))
624                 v.val = 1;
625             break;
626 
627         case NUMBER:
628             n = 0;
629             base = 10;
630             p = tp->t;
631             c = p[tp->len];
632             p[tp->len] = '\0';
633             if (*p == '0')
634             {
635                 base = 8;
636                 if (p[1] == 'x' || p[1] == 'X')
637                 {
638                     base = 16;
639                     p++;
640                 }
641                 p++;
642             }
643             for (;; p++)
644             {
645                 if ((i = digit(*p)) < 0)
646                     break;
647                 if (i >= base)
648                     error(WARNING,
649                           "Bad digit in number %t", tp);
650                 n *= base;
651                 n += i;
652             }
653             if (n >= 0x80000000 && base != 10)
654                 v.type = UNS;
655             for (; *p; p++)
656             {
657                 if (*p == 'u' || *p == 'U')
658                     v.type = UNS;
659                 else
660                     if (*p == 'l' || *p == 'L')
661                         ;
662                     else
663                     {
664                         error(ERROR,
665                               "Bad number %t in #if/#elsif", tp);
666                         break;
667                     }
668             }
669             v.val = n;
670             tp->t[tp->len] = c;
671             break;
672 
673         case CCON:
674             n = 0;
675             p = tp->t;
676             if (*p == 'L')
677             {
678                 p += 1;
679                 error(WARNING, "Wide char constant value undefined");
680             }
681             p += 1;
682             if (*p == '\\')
683             {
684                 p += 1;
685                 if ((i = digit(*p)) >= 0 && i <= 7)
686                 {
687                     n = i;
688                     p += 1;
689                     if ((i = digit(*p)) >= 0 && i <= 7)
690                     {
691                         p += 1;
692                         n <<= 3;
693                         n += i;
694                         if ((i = digit(*p)) >= 0 && i <= 7)
695                         {
696                             p += 1;
697                             n <<= 3;
698                             n += i;
699                         }
700                     }
701                 }
702                 else
703                     if (*p == 'x')
704                     {
705                         p += 1;
706                         while ((i = digit(*p)) >= 0 && i <= 15)
707                         {
708                             p += 1;
709                             n <<= 4;
710                             n += i;
711                         }
712                     }
713                     else
714                     {
715                         static char cvcon[] = "b\bf\fn\nr\rt\tv\v''\"\"??\\\\";
716                         static size_t cvlen = sizeof(cvcon) - 1;
717 
718                         size_t j;
719                         for (j = 0; j < cvlen; j += 2)
720                         {
721                             if (*p == cvcon[j])
722                             {
723                                 n = cvcon[j + 1];
724                                 break;
725                             }
726                         }
727                         p += 1;
728                         if (j >= cvlen)
729                             error(WARNING,
730                                "Undefined escape in character constant");
731                     }
732             }
733             else
734                 if (*p == '\'')
735                     error(ERROR, "Empty character constant");
736                 else
737                     n = *p++;
738             if (*p != '\'')
739                 error(WARNING, "Multibyte character constant undefined");
740             else
741                 if (n > 127)
742                     error(WARNING, "Character constant taken as not signed");
743             v.val = n;
744             break;
745 
746         case STRING:
747             error(ERROR, "String in #if/#elsif");
748             break;
749     }
750     return v;
751 }
752 
753 int
754     digit(int i)
755 {
756     if ('0' <= i && i <= '9')
757         i -= '0';
758     else
759         if ('a' <= i && i <= 'f')
760             i -= 'a' - 10;
761         else
762             if ('A' <= i && i <= 'F')
763                 i -= 'A' - 10;
764             else
765                 i = -1;
766     return i;
767 }
768