merge the formfield patch from ooo-build
[ooovba.git] / idlc / source / preproc / eval.c
blob69d1efb19c3577196f843ee962264a716faf55aa
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: eval.c,v $
10 * $Revision: 1.4 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
30 #include <stdlib.h>
31 #include <string.h>
32 #include "cpp.h"
34 #define NSTAK 32
35 #define SGN 0
36 #define UNS 1
37 #define UND 2
39 #define UNSMARK 0x1000
41 struct value
43 long val;
44 int type;
47 /* conversion types */
48 #define RELAT 1
49 #define ARITH 2
50 #define LOGIC 3
51 #define SPCL 4
52 #define SHIFT 5
53 #define UNARY 6
55 /* operator priority, arity, and conversion type, indexed by tokentype */
56 struct pri
58 char pri;
59 char arity;
60 char ctype;
61 } priority[] =
65 0, 0, 0
66 }, /* END */
68 0, 0, 0
69 }, /* UNCLASS */
71 0, 0, 0
72 }, /* NAME */
74 0, 0, 0
75 }, /* NUMBER */
77 0, 0, 0
78 }, /* STRING */
80 0, 0, 0
81 }, /* CCON */
83 0, 0, 0
84 }, /* NL */
86 0, 0, 0
87 }, /* WS */
89 0, 0, 0
90 }, /* DSHARP */
92 11, 2, RELAT
93 }, /* EQ */
95 11, 2, RELAT
96 }, /* NEQ */
98 12, 2, RELAT
99 }, /* LEQ */
101 12, 2, RELAT
102 }, /* GEQ */
104 13, 2, SHIFT
105 }, /* LSH */
107 13, 2, SHIFT
108 }, /* RSH */
110 7, 2, LOGIC
111 }, /* LAND */
113 6, 2, LOGIC
114 }, /* LOR */
116 0, 0, 0
117 }, /* PPLUS */
119 0, 0, 0
120 }, /* MMINUS */
122 0, 0, 0
123 }, /* ARROW */
125 0, 0, 0
126 }, /* SBRA */
128 0, 0, 0
129 }, /* SKET */
131 3, 0, 0
132 }, /* LP */
134 3, 0, 0
135 }, /* RP */
137 0, 0, 0
138 }, /* DOT */
140 10, 2, ARITH
141 }, /* AND */
143 15, 2, ARITH
144 }, /* STAR */
146 14, 2, ARITH
147 }, /* PLUS */
149 14, 2, ARITH
150 }, /* MINUS */
152 16, 1, UNARY
153 }, /* TILDE */
155 16, 1, UNARY
156 }, /* NOT */
158 15, 2, ARITH
159 }, /* SLASH */
161 15, 2, ARITH
162 }, /* PCT */
164 12, 2, RELAT
165 }, /* LT */
167 12, 2, RELAT
168 }, /* GT */
170 9, 2, ARITH
171 }, /* CIRC */
173 8, 2, ARITH
174 }, /* OR */
176 5, 2, SPCL
177 }, /* QUEST */
179 5, 2, SPCL
180 }, /* COLON */
182 0, 0, 0
183 }, /* ASGN */
185 4, 2, 0
186 }, /* COMMA */
188 0, 0, 0
189 }, /* SHARP */
191 0, 0, 0
192 }, /* SEMIC */
194 0, 0, 0
195 }, /* CBRA */
197 0, 0, 0
198 }, /* CKET */
200 0, 0, 0
201 }, /* ASPLUS */
203 0, 0, 0
204 }, /* ASMINUS */
206 0, 0, 0
207 }, /* ASSTAR */
209 0, 0, 0
210 }, /* ASSLASH */
212 0, 0, 0
213 }, /* ASPCT */
215 0, 0, 0
216 }, /* ASCIRC */
218 0, 0, 0
219 }, /* ASLSH */
221 0, 0, 0
222 }, /* ASRSH */
224 0, 0, 0
225 }, /* ASOR */
227 0, 0, 0
228 }, /* ASAND */
230 0, 0, 0
231 }, /* ELLIPS */
233 0, 0, 0
234 }, /* DSHARP1 */
236 0, 0, 0
237 }, /* NAME1 */
239 0, 0, 0
240 }, /* NAME2 */
242 16, 1, UNARY
243 }, /* DEFINED */
245 16, 0, UNARY
246 }, /* UMINUS */
248 16, 1, UNARY
249 }, /* ARCHITECTURE */
252 int evalop(struct pri);
253 struct value tokval(Token *);
254 struct value vals[NSTAK], *vp;
255 enum toktype ops[NSTAK], *op;
258 * Evaluate an #if #elif #ifdef #ifndef line. trp->tp points to the keyword.
260 long
261 eval(Tokenrow * trp, int kw)
263 Token *tp;
264 Nlist *np;
265 int ntok, rand;
267 trp->tp++;
268 if (kw == KIFDEF || kw == KIFNDEF)
270 if (trp->lp - trp->bp != 4 || trp->tp->type != NAME)
272 error(ERROR, "Syntax error in #ifdef/#ifndef");
273 return 0;
275 np = lookup(trp->tp, 0);
276 return (kw == KIFDEF) == (np && np->flag & (ISDEFINED | ISMAC));
278 ntok = trp->tp - trp->bp;
279 kwdefined->val = KDEFINED; /* activate special meaning of
280 * defined */
281 expandrow(trp, "<if>");
282 kwdefined->val = NAME;
283 vp = vals;
284 op = ops;
285 *op++ = END;
286 for (rand = 0, tp = trp->bp + ntok; tp < trp->lp; tp++)
288 switch (tp->type)
290 case WS:
291 case NL:
292 continue;
294 /* nilary */
295 case NAME:
296 case NAME1:
297 case NAME2:
298 case NUMBER:
299 case CCON:
300 case STRING:
301 if (rand)
302 goto syntax;
303 *vp++ = tokval(tp);
304 rand = 1;
305 continue;
307 /* unary */
308 case DEFINED:
309 case TILDE:
310 case NOT:
311 if (rand)
312 goto syntax;
313 *op++ = tp->type;
314 continue;
316 /* unary-binary */
317 case PLUS:
318 case MINUS:
319 case STAR:
320 case AND:
321 if (rand == 0)
323 if (tp->type == MINUS)
324 *op++ = UMINUS;
325 if (tp->type == STAR || tp->type == AND)
327 error(ERROR, "Illegal operator * or & in #if/#elsif");
328 return 0;
330 continue;
332 /* flow through */
334 /* plain binary */
335 case EQ:
336 case NEQ:
337 case LEQ:
338 case GEQ:
339 case LSH:
340 case RSH:
341 case LAND:
342 case LOR:
343 case SLASH:
344 case PCT:
345 case LT:
346 case GT:
347 case CIRC:
348 case OR:
349 case QUEST:
350 case COLON:
351 case COMMA:
352 if (rand == 0)
353 goto syntax;
354 if (evalop(priority[tp->type]) != 0)
355 return 0;
356 *op++ = tp->type;
357 rand = 0;
358 continue;
360 case LP:
361 if (rand)
362 goto syntax;
363 *op++ = LP;
364 continue;
366 case RP:
367 if (!rand)
368 goto syntax;
369 if (evalop(priority[RP]) != 0)
370 return 0;
371 if (op <= ops || op[-1] != LP)
373 goto syntax;
375 op--;
376 continue;
378 case SHARP:
379 if ((tp + 1) < trp->lp)
381 np = lookup(tp + 1, 0);
382 if (np && (np->val == KMACHINE))
384 tp++;
385 if (rand)
386 goto syntax;
387 *op++ = ARCHITECTURE;
388 continue;
391 /* fall through */
393 default:
394 error(ERROR, "Bad operator (%t) in #if/#elsif", tp);
395 return 0;
398 if (rand == 0)
399 goto syntax;
400 if (evalop(priority[END]) != 0)
401 return 0;
402 if (op != &ops[1] || vp != &vals[1])
404 error(ERROR, "Botch in #if/#elsif");
405 return 0;
407 if (vals[0].type == UND)
408 error(ERROR, "Undefined expression value");
409 return vals[0].val;
410 syntax:
411 error(ERROR, "Syntax error in #if/#elsif");
412 return 0;
416 evalop(struct pri pri)
418 struct value v1, v2 = { 0, 0 };
419 long rv1, rv2;
420 int rtype, oper;
422 rv2 = 0;
423 rtype = 0;
424 while (pri.pri < priority[op[-1]].pri)
426 oper = *--op;
427 if (priority[oper].arity == 2)
429 v2 = *--vp;
430 rv2 = v2.val;
432 v1 = *--vp;
433 rv1 = v1.val;
434 /*lint -e574 -e644 */
435 switch (priority[oper].ctype)
437 case 0:
438 default:
439 error(WARNING, "Syntax error in #if/#endif");
440 return 1;
441 case ARITH:
442 case RELAT:
443 if (v1.type == UNS || v2.type == UNS)
444 rtype = UNS;
445 else
446 rtype = SGN;
447 if (v1.type == UND || v2.type == UND)
448 rtype = UND;
449 if (priority[oper].ctype == RELAT && rtype == UNS)
451 oper |= UNSMARK;
452 rtype = SGN;
454 break;
455 case SHIFT:
456 if (v1.type == UND || v2.type == UND)
457 rtype = UND;
458 else
459 rtype = v1.type;
460 if (rtype == UNS)
461 oper |= UNSMARK;
462 break;
463 case UNARY:
464 rtype = v1.type;
465 break;
466 case LOGIC:
467 case SPCL:
468 break;
470 switch (oper)
472 case EQ:
473 case EQ | UNSMARK:
474 rv1 = rv1 == rv2;
475 break;
476 case NEQ:
477 case NEQ | UNSMARK:
478 rv1 = rv1 != rv2;
479 break;
480 case LEQ:
481 rv1 = rv1 <= rv2;
482 break;
483 case GEQ:
484 rv1 = rv1 >= rv2;
485 break;
486 case LT:
487 rv1 = rv1 < rv2;
488 break;
489 case GT:
490 rv1 = rv1 > rv2;
491 break;
492 case LEQ | UNSMARK:
493 rv1 = (unsigned long)rv1 <= (unsigned long)rv2;
494 break;
495 case GEQ | UNSMARK:
496 rv1 = (unsigned long)rv1 >= (unsigned long)rv2;
497 break;
498 case LT | UNSMARK:
499 rv1 = (unsigned long)rv1 < (unsigned long)rv2;
500 break;
501 case GT | UNSMARK:
502 rv1 = (unsigned long)rv1 > (unsigned long)rv2;
503 break;
504 case LSH:
505 rv1 <<= rv2;
506 break;
507 case LSH | UNSMARK:
508 rv1 = (unsigned long) rv1 << rv2;
509 break;
510 case RSH:
511 rv1 >>= rv2;
512 break;
513 case RSH | UNSMARK:
514 rv1 = (unsigned long) rv1 >> rv2;
515 break;
516 case LAND:
517 rtype = UND;
518 if (v1.type == UND)
519 break;
520 if (rv1 != 0)
522 if (v2.type == UND)
523 break;
524 rv1 = rv2 != 0;
526 else
527 rv1 = 0;
528 rtype = SGN;
529 break;
530 case LOR:
531 rtype = UND;
532 if (v1.type == UND)
533 break;
534 if (rv1 == 0)
536 if (v2.type == UND)
537 break;
538 rv1 = rv2 != 0;
540 else
541 rv1 = 1;
542 rtype = SGN;
543 break;
544 case AND:
545 rv1 &= rv2;
546 break;
547 case STAR:
548 rv1 *= rv2;
549 break;
550 case PLUS:
551 rv1 += rv2;
552 break;
553 case MINUS:
554 rv1 -= rv2;
555 break;
556 case UMINUS:
557 if (v1.type == UND)
558 rtype = UND;
559 rv1 = -rv1;
560 break;
561 case OR:
562 rv1 |= rv2;
563 break;
564 case CIRC:
565 rv1 ^= rv2;
566 break;
567 case TILDE:
568 rv1 = ~rv1;
569 break;
570 case NOT:
571 rv1 = !rv1;
572 if (rtype != UND)
573 rtype = SGN;
574 break;
575 case SLASH:
576 if (rv2 == 0)
578 rtype = UND;
579 break;
581 if (rtype == UNS)
582 rv1 /= (unsigned long) rv2;
583 else
584 rv1 /= rv2;
585 break;
586 case PCT:
587 if (rv2 == 0)
589 rtype = UND;
590 break;
592 if (rtype == UNS)
593 rv1 %= (unsigned long) rv2;
594 else
595 rv1 %= rv2;
596 break;
597 case COLON:
598 if (op[-1] != QUEST)
599 error(ERROR, "Bad ?: in #if/endif");
600 else
602 op--;
603 if ((--vp)->val == 0)
604 v1 = v2;
605 rtype = v1.type;
606 rv1 = v1.val;
608 break;
610 case DEFINED:
611 case ARCHITECTURE:
612 break;
614 default:
615 error(ERROR, "Eval botch (unknown operator)");
616 return 1;
618 /*lint +e574 +e644 */
619 v1.val = rv1;
620 v1.type = rtype;
621 *vp++ = v1;
623 return 0;
626 struct value
627 tokval(Token * tp)
629 struct value v;
630 Nlist *np;
631 int i, base;
632 unsigned long n;
633 uchar *p, c;
635 v.type = SGN;
636 v.val = 0;
637 switch (tp->type)
640 case NAME:
641 v.val = 0;
642 break;
644 case NAME1:
645 if ((np = lookup(tp, 0)) != NULL && np->flag & (ISDEFINED | ISMAC))
646 v.val = 1;
647 break;
649 case NAME2:
650 if ((np = lookup(tp, 0)) != NULL && np->flag & (ISARCHITECTURE))
651 v.val = 1;
652 break;
654 case NUMBER:
655 n = 0;
656 base = 10;
657 p = tp->t;
658 c = p[tp->len];
659 p[tp->len] = '\0';
660 if (*p == '0')
662 base = 8;
663 if (p[1] == 'x' || p[1] == 'X')
665 base = 16;
666 p++;
668 p++;
670 for (;; p++)
672 if ((i = digit(*p)) < 0)
673 break;
674 if (i >= base)
675 error(WARNING,
676 "Bad digit in number %t", tp);
677 n *= base;
678 n += i;
680 if (n >= 0x80000000 && base != 10)
681 v.type = UNS;
682 for (; *p; p++)
684 if (*p == 'u' || *p == 'U')
685 v.type = UNS;
686 else
687 if (*p == 'l' || *p == 'L')
689 else
691 error(ERROR,
692 "Bad number %t in #if/#elsif", tp);
693 break;
696 v.val = n;
697 tp->t[tp->len] = c;
698 break;
700 case CCON:
701 n = 0;
702 p = tp->t;
703 if (*p == 'L')
705 p += 1;
706 error(WARNING, "Wide char constant value undefined");
708 p += 1;
709 if (*p == '\\')
711 p += 1;
712 if ((i = digit(*p)) >= 0 && i <= 7)
714 n = i;
715 p += 1;
716 if ((i = digit(*p)) >= 0 && i <= 7)
718 p += 1;
719 n <<= 3;
720 n += i;
721 if ((i = digit(*p)) >= 0 && i <= 7)
723 p += 1;
724 n <<= 3;
725 n += i;
729 else
730 if (*p == 'x')
732 p += 1;
733 while ((i = digit(*p)) >= 0 && i <= 15)
735 p += 1;
736 n <<= 4;
737 n += i;
740 else
742 static char cvcon[]
743 = "b\bf\fn\nr\rt\tv\v''\"\"??\\\\";
745 for (i = 0; i < (int)sizeof(cvcon); i += 2)
747 if (*p == cvcon[i])
749 n = cvcon[i + 1];
750 break;
753 p += 1;
754 if (i >= (int)sizeof(cvcon))
755 error(WARNING,
756 "Undefined escape in character constant");
759 else
760 if (*p == '\'')
761 error(ERROR, "Empty character constant");
762 else
763 n = *p++;
764 if (*p != '\'')
765 error(WARNING, "Multibyte character constant undefined");
766 else
767 if (n > 127)
768 error(WARNING, "Character constant taken as not signed");
769 v.val = n;
770 break;
772 case STRING:
773 error(ERROR, "String in #if/#elsif");
774 break;
776 return v;
780 digit(int i)
782 if ('0' <= i && i <= '9')
783 i -= '0';
784 else
785 if ('a' <= i && i <= 'f')
786 i -= 'a' - 10;
787 else
788 if ('A' <= i && i <= 'F')
789 i -= 'A' - 10;
790 else
791 i = -1;
792 return i;