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