]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/cpp/eval.c
awk: make empty FS unicodely-correct.
[plan9front.git] / sys / src / cmd / cpp / eval.c
1 #include <u.h>
2 #include <libc.h>
3 #include "cpp.h"
4
5 #define NSTAK   32
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], *vp;
96 enum toktype ops[NSTAK], *op;
97
98 /*
99  * Evaluate an #if #elif #ifdef #ifndef line.  trp->tp points to the keyword.
100  */
101 long
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                 switch(tp->type) {
126                 case WS:
127                 case NL:
128                         continue;
129
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;
141
142                 /* unary */
143                 case DEFINED:
144                 case TILDE:
145                 case NOT:
146                         if (rand)
147                                 goto syntax;
148                         *op++ = tp->type;
149                         continue;
150
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/#elif");
158                                         return 0;
159                                 }
160                                 continue;
161                         }
162                         /* flow through */
163
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;
176
177                 case LP:
178                         if (rand)
179                                 goto syntax;
180                         *op++ = LP;
181                         continue;
182
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;
193
194                 default:
195                         error(ERROR,"Bad operator (%t) in #if/#elif", 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/#elif");
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/#elif");
212         return 0;
213 }
214
215 int
216 evalop(struct pri pri)
217 {
218         struct value v1, v2;
219         long rv1, rv2;
220         int rtype, oper;
221
222         rv2=0;
223         rtype=0;
224         while (pri.pri < priority[op[-1]].pri) {
225                 oper = *--op;
226                 if (priority[oper].arity==2) {
227                         v2 = *--vp;
228                         rv2 = v2.val;
229                 }
230                 v1 = *--vp;
231                 rv1 = v1.val;
232                 switch (priority[oper].ctype) {
233                 case 0:
234                 default:
235                         error(WARNING, "Syntax error in #if/#endif");
236                         return 1;
237                 case ARITH:
238                 case RELAT:
239                         if (v1.type==UNS || v2.type==UNS)
240                                 rtype = UNS;
241                         else
242                                 rtype = SGN;
243                         if (v1.type==UND || v2.type==UND)
244                                 rtype = UND;
245                         if (priority[oper].ctype==RELAT && rtype==UNS) {
246                                 oper |= UNSMARK;
247                                 rtype = SGN;
248                         }
249                         break;
250                 case SHIFT:
251                         if (v1.type==UND || v2.type==UND)
252                                 rtype = UND;
253                         else
254                                 rtype = v1.type;
255                         if (rtype==UNS)
256                                 oper |= UNSMARK;
257                         break;
258                 case UNARY:
259                         rtype = v1.type;
260                         break;
261                 case LOGIC:
262                 case SPCL:
263                         break;
264                 }
265                 switch (oper) {
266                 case EQ: case EQ|UNSMARK:
267                         rv1 = rv1==rv2; break;
268                 case NEQ: case NEQ|UNSMARK:
269                         rv1 = rv1!=rv2; break;
270                 case LEQ:
271                         rv1 = rv1<=rv2; break;
272                 case GEQ:
273                         rv1 = rv1>=rv2; break;
274                 case LT:
275                         rv1 = rv1<rv2; break;
276                 case GT:
277                         rv1 = rv1>rv2; break;
278                 case LEQ|UNSMARK:
279                         rv1 = (unsigned long)rv1<=rv2; break;
280                 case GEQ|UNSMARK:
281                         rv1 = (unsigned long)rv1>=rv2; break;
282                 case LT|UNSMARK:
283                         rv1 = (unsigned long)rv1<rv2; break;
284                 case GT|UNSMARK:
285                         rv1 = (unsigned long)rv1>rv2; break;
286                 case LSH:
287                         rv1 <<= rv2; break;
288                 case LSH|UNSMARK:
289                         rv1 = (unsigned long)rv1<<rv2; break;
290                 case RSH:
291                         rv1 >>= rv2; break;
292                 case RSH|UNSMARK:
293                         rv1 = (unsigned long)rv1>>rv2; break;
294                 case LAND:
295                         rtype = UND;
296                         if (v1.type==UND)
297                                 break;
298                         if (rv1!=0) {
299                                 if (v2.type==UND)
300                                         break;
301                                 rv1 = rv2!=0;
302                         } else
303                                 rv1 = 0;
304                         rtype = SGN;
305                         break;
306                 case LOR:
307                         rtype = UND;
308                         if (v1.type==UND)
309                                 break;
310                         if (rv1==0) {
311                                 if (v2.type==UND)
312                                         break;
313                                 rv1 = rv2!=0;
314                         } else
315                                 rv1 = 1;
316                         rtype = SGN;
317                         break;
318                 case AND:
319                         rv1 &= rv2; break;
320                 case STAR:
321                         rv1 *= rv2; break;
322                 case PLUS:
323                         rv1 += rv2; break;
324                 case MINUS:
325                         rv1 -= rv2; break;
326                 case UMINUS:
327                         if (v1.type==UND)
328                                 rtype = UND;
329                         rv1 = -rv1; break;
330                 case OR:
331                         rv1 |= rv2; break;
332                 case CIRC:
333                         rv1 ^= rv2; break;
334                 case TILDE:
335                         rv1 = ~rv1; break;
336                 case NOT:
337                         rv1 = !rv1; if (rtype!=UND) rtype = SGN; break;
338                 case SLASH:
339                         if (rv2==0) {
340                                 rtype = UND;
341                                 break;
342                         }
343                         if (rtype==UNS)
344                                 rv1 /= (unsigned long)rv2;
345                         else
346                                 rv1 /= rv2;
347                         break;
348                 case PCT:
349                         if (rv2==0) {
350                                 rtype = UND;
351                                 break;
352                         }
353                         if (rtype==UNS)
354                                 rv1 %= (unsigned long)rv2;
355                         else
356                                 rv1 %= rv2;
357                         break;
358                 case COLON:
359                         if (op[-1] != QUEST)
360                                 error(ERROR, "Bad ?: in #if/endif");
361                         else {
362                                 op--;
363                                 if ((--vp)->val==0)
364                                         v1 = v2;
365                                 rtype = v1.type;
366                                 rv1 = v1.val;
367                         }
368                         break;
369                 case DEFINED:
370                         break;
371                 default:
372                         error(ERROR, "Eval botch (unknown operator)");
373                         return 1;
374                 }
375                 v1.val = rv1;
376                 v1.type = rtype;
377                 *vp++ = v1;
378         }
379         return 0;
380 }
381
382 struct value
383 tokval(Token *tp)
384 {
385         struct value v;
386         Nlist *np;
387         int i, base, c, longcc;
388         unsigned long n;
389         Rune r;
390         uchar *p;
391
392         v.type = SGN;
393         v.val = 0;
394         switch (tp->type) {
395
396         case NAME:
397                 v.val = 0;
398                 break;
399
400         case NAME1:
401                 if ((np = lookup(tp, 0)) && np->flag&(ISDEFINED|ISMAC))
402                         v.val = 1;
403                 break;
404
405         case NUMBER:
406                 n = 0;
407                 base = 10;
408                 p = tp->t;
409                 c = p[tp->len];
410                 p[tp->len] = '\0';
411                 if (*p=='0') {
412                         base = 8;
413                         if (p[1]=='x' || p[1]=='X') {
414                                 base = 16;
415                                 p++;
416                         }
417                         p++;
418                 }
419                 for (;; p++) {
420                         if ((i = digit(*p)) < 0)
421                                 break;
422                         if (i>=base)
423                                 error(WARNING,
424                                   "Bad digit in number %t", tp);
425                         n *= base;
426                         n += i;
427                 }
428                 if (n>=0x80000000 && base!=10)
429                         v.type = UNS;
430                 for (; *p; p++) {
431                         if (*p=='u' || *p=='U')
432                                 v.type = UNS;
433                         else if (*p=='l' || *p=='L')
434                                 {}
435                         else {
436                                 error(ERROR,
437                                   "Bad number %t in #if/#elif", tp);
438                                 break;
439                         }
440                 }
441                 v.val = n;
442                 tp->t[tp->len] = c;
443                 break;
444
445         case CCON:
446                 n = 0;
447                 p = tp->t;
448                 longcc = 0;
449                 if (*p=='L') {
450                         p += 1;
451                         longcc = 1;
452                 }
453                 p += 1;
454                 if (*p=='\\') {
455                         p += 1;
456                         if ((i = digit(*p))>=0 && i<=7) {
457                                 n = i;
458                                 p += 1;
459                                 if ((i = digit(*p))>=0 && i<=7) {
460                                         p += 1;
461                                         n <<= 3;
462                                         n += i;
463                                         if ((i = digit(*p))>=0 && i<=7) {
464                                                 p += 1;
465                                                 n <<= 3;
466                                                 n += i;
467                                         }
468                                 }
469                         } else if (*p=='x') {
470                                 p += 1;
471                                 while ((i = digit(*p))>=0 && i<=15) {
472                                         p += 1;
473                                         n <<= 4;
474                                         n += i;
475                                 }
476                         } else {
477                                 static char cvcon[]
478                                   = "a\ab\bf\fn\nr\rt\tv\v''\"\"??\\\\";
479                                 for (i=0; i<sizeof(cvcon); i+=2) {
480                                         if (*p == cvcon[i]) {
481                                                 n = cvcon[i+1];
482                                                 break;
483                                         }
484                                 }
485                                 p += 1;
486                                 if (i>=sizeof(cvcon))
487                                         error(WARNING,
488                                          "Undefined escape in character constant");
489                         }
490                 } else if (*p=='\'')
491                         error(ERROR, "Empty character constant");
492                 else {
493                         i = chartorune(&r, (char*)p);
494                         n = r;
495                         p += i;
496                         if (i>1 && longcc==0)
497                                 error(WARNING, "Undefined character constant");
498                 }
499                 if (*p!='\'')
500                         error(WARNING, "Multibyte character constant undefined");
501                 else if (n>127 && longcc==0)
502                         error(WARNING, "Character constant taken as not signed");
503                 v.val = n;
504                 break;
505
506         case STRING:
507                 error(ERROR, "String in #if/#elif");
508                 break;
509         }
510         return v;
511 }
512
513 int
514 digit(int i)
515 {
516         if ('0'<=i && i<='9')
517                 i -= '0';
518         else if ('a'<=i && i<='f')
519                 i -= 'a'-10;
520         else if ('A'<=i && i<='F')
521                 i -= 'A'-10;
522         else
523                 i = -1;
524         return i;
525 }