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