Less permissive syntax for notreached comment.
[splint-patched.git] / src / cppexp.c
blob0fc75d3f911a30a4bd1a6f9221377c5a50a48142
1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
4 ** Massachusetts Institute of Technology
5 **
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** General Public License for more details.
15 **
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
20 ** For information on splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
25 ** cppexp.c
27 /* Parse C expressions for CCCP.
28 Copyright (C) 1987, 1992, 1994, 1995, 1997 Free Software Foundation.
30 This program is free software; you can redistribute it and/or modify it
31 under the terms of the GNU General Public License as published by the
32 Free Software Foundation; either version 2, or (at your option) any
33 later version.
35 This program is distributed in the hope that it will be useful,
36 but WITHOUT ANY WARRANTY; without even the implied warranty of
37 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 GNU General Public License for more details.
40 You should have received a copy of the GNU General Public License
41 along with this program; if not, write to the Free Software
42 Foundation, 59 Temple Place - Suite 330,
43 Boston, MA 02111-1307, USA.
45 In other words, you are welcome to use, share and improve this program.
46 You are forbidden to forbid anyone else to use, share and improve
47 what you give them. Help stamp out software-hoarding!
49 Written by Per Bothner 1994. */
51 /* Parse a C expression from text in a string */
53 /*@+charint@*/
54 /*@+ignorequals@*/
55 /*@+ignoresigns@*/
56 /*@+matchanyintegral@*/
58 # include "splintMacros.nf"
59 # include "basic.h"
61 # include "cppconf.h"
62 # include "cpplib.h"
63 # include "cpphash.h"
64 # include "cppexp.h"
65 # include "cpperror.h"
68 /*@constant short CPPREADER_ERRORTOK@*/
69 #define CPPREADER_ERRORTOK 299
71 /*@constant int OROR@*/
72 #define OROR 300
74 /*@constant int ANDAND@*/
75 #define ANDAND 301
77 /*@constant int CPP_EQUALTOK@*/
78 #define CPP_EQUALTOK 302
80 /*@constant int NOTEQUAL@*/
81 #define NOTEQUAL 303
83 /*@constant int LEQ@*/
84 #define LEQ 304
86 /*@constant int GEQ@*/
87 #define GEQ 305
89 /*@constant int LSH@*/
90 #define LSH 306
92 /*@constant int RSH@*/
93 #define RSH 307
95 /*@constant int NAME@*/
96 #define NAME 308
98 /*@constant short CPPEXP_INT@*/
99 #define CPPEXP_INT 309
101 /*@constant short CPPEXP_CHAR@*/
102 #define CPPEXP_CHAR 310
104 /*@constant int LEFT_OPERAND_REQUIRED@*/
105 #define LEFT_OPERAND_REQUIRED 1
107 /*@constant int RIGHT_OPERAND_REQUIRED@*/
108 #define RIGHT_OPERAND_REQUIRED 2
110 /*@constant int HAVE_VALUE@*/
111 #define HAVE_VALUE 4
113 /* Yield nonzero if adding two numbers with A's and B's signs can yield a
114 number with SUM's sign, where A, B, and SUM are all C integers. */
116 /*@function static bool possibleSumSign (sef int, int, int)
117 modifies nothing ; @*/
119 #define possibleSumSign(a, b, sum) ((((a) ^ (b)) | ~ ((a) ^ (sum))) < 0)
121 static struct operation cppexp_lex (cppReader *);
122 static void integer_overflow (cppReader *);
123 static long left_shift (cppReader *, long, bool p_unsignedp, unsigned long);
124 static long right_shift (long, bool p_unsignedp, unsigned long);
127 struct operation {
128 short op;
130 /* Priority of op (relative to it right operand). */
131 /*@reldef@*/ char rprio;
133 /*@reldef@*/ char flags;
135 /* true if value should be treated as unsigned */
136 /*@reldef@*/ bool unsignedp;
138 /* The value logically "right" of op. */
139 /*@reldef@*/ HOST_WIDE_INT value;
142 /* Take care of parsing a number (anything that starts with a digit).
143 LEN is the number of characters in it. */
145 /* maybe needs to actually deal with floating point numbers */
147 static struct operation
148 cppReader_parseNumber (cppReader *pfile, char *start, int olen) /*@requires maxRead(start) >= (olen - 1) @*/
150 struct operation op;
151 char *p = start;
152 char c;
153 int i;
154 long n = 0;
155 unsigned long nd, ULONG_MAX_over_base;
156 int base = 10;
157 int len = olen;
158 bool overflow = FALSE;
159 int digit, largest_digit = 0;
160 bool spec_long = FALSE;
162 op.unsignedp = FALSE;
164 for (i = 0; i < len; i++)
166 if (p[i] == '.') {
167 /* It's a float since it contains a point. */
168 cppReader_errorLit
169 (pfile,
170 cstring_makeLiteralTemp
171 ("Floating point numbers not allowed in #if expressions"));
172 op.op = CPPREADER_ERRORTOK;
173 return op;
177 if (len >= 3 && (mstring_equalPrefix (p, "0x")
178 || mstring_equalPrefix (p, "0X")))
180 p += 2;
181 base = 16;
182 len -= 2;
184 else if (*p == '0')
186 base = 8;
188 else
193 /* Some buggy compilers (e.g. MPW C) seem to need both casts. */
194 ULONG_MAX_over_base = ((unsigned long) -1) / ((unsigned long) base);
196 for (; len > 0; len--) {
197 c = *p++;
199 if (c >= '0' && c <= '9')
201 digit = (int) (c - '0');
203 else if (base == 16 && c >= 'a' && c <= 'f')
205 digit = (int) (c - 'a') + 10;
207 else if (base == 16 && c >= 'A' && c <= 'F')
209 digit = (int) (c - 'A') + 10;
211 else
213 /* `l' means long, and `u' means unsigned. */
214 while (TRUE)
216 if (c == 'l' || c == 'L')
218 if (spec_long)
219 cppReader_errorLit (pfile,
220 cstring_makeLiteralTemp ("two `l's in integer constant"));
221 spec_long = TRUE;
223 else if (c == 'u' || c == 'U')
225 if (op.unsignedp)
226 cppReader_errorLit (pfile,
227 cstring_makeLiteralTemp ("two `u's in integer constant"));
228 op.unsignedp = TRUE;
230 else
232 /*@innerbreak@*/ break;
235 if (--len == 0)
237 /*@innerbreak@*/ break;
240 c = *p++;
242 /* Don't look for any more digits after the suffixes. */
243 break;
246 if (largest_digit < digit)
248 largest_digit = digit;
251 nd = (long unsigned) (n * base + digit);
252 overflow |= (ULONG_MAX_over_base < (unsigned long) n)
253 | (nd < (unsigned long) n);
254 n = (long) nd;
257 if (len != 0)
259 cppReader_errorLit
260 (pfile,
261 cstring_makeLiteralTemp ("Invalid number in #if expression"));
262 op.op = CPPREADER_ERRORTOK;
263 return op;
266 if (base <= largest_digit)
268 cppReader_pedwarnLit
269 (pfile,
270 cstring_makeLiteralTemp
271 ("Integer constant contains digits beyond the radix"));
274 if (overflow)
276 cppReader_pedwarnLit
277 (pfile,
278 cstring_makeLiteralTemp ("Integer constant out of range"));
281 /* If too big to be signed, consider it unsigned. */
282 if ((long) n < 0 && ! op.unsignedp)
284 if (base == 10)
286 cppReader_warningLit
287 (pfile,
288 cstring_makeLiteralTemp ("Integer constant is so large that it is unsigned"));
291 op.unsignedp = TRUE;
294 op.value = n;
295 op.op = CPPEXP_INT;
296 DPRINTF (("Parse number: %d", op.value));
297 return op;
300 struct token {
301 /*@null@*/ /*@observer@*/ char *operator;
302 int token;
305 static struct token tokentab2[] = {
306 { "&&", ANDAND },
307 { "||", OROR },
308 { "<<", LSH },
309 { ">>", RSH },
310 { "==", CPP_EQUALTOK },
311 { "!=", NOTEQUAL },
312 { "<=", LEQ },
313 { ">=", GEQ },
314 { "++", CPPREADER_ERRORTOK },
315 { "--", CPPREADER_ERRORTOK },
316 { NULL, CPPREADER_ERRORTOK }
319 /* Read one token. */
321 struct operation cppexp_lex (cppReader *pfile)
323 int ic;
324 char c;
325 register struct token *toktab;
326 enum cpp_token token;
327 struct operation op;
328 char *tok_start, *tok_end;
329 int old_written;
331 retry:
333 old_written = size_toInt (cpplib_getWritten (pfile));
334 cppSkipHspace (pfile);
335 ic = cpplib_bufPeek (cppReader_getBufferSafe (pfile));
337 c = (char) ic;
339 if (c == '#')
341 /* was: llassert (c != '#'); - Solaris uses this, attempt to continue anyway... */
342 cppReader_pedwarn (pfile,
343 message ("non-standard pre-processor directive: %c", c));
346 DPRINTF (("Read: %c", c));
348 if (c == '\n')
350 op.op = 0;
351 return op;
354 token = cpplib_getTokenForceExpand (pfile);
356 tok_start = pfile->token_buffer + old_written;
357 tok_end = cpplib_getPWritten (pfile);
359 DPRINTF (("Token: %s < %s", tok_start, tok_end));
361 pfile->limit = tok_start;
363 switch (token)
365 case CPP_EOF: /* Should not happen ... */
366 case CPP_VSPACE:
367 op.op = 0;
368 return op;
369 case CPP_POP:
370 if (cstring_isDefined (cppReader_getBufferSafe (pfile)->fname))
372 op.op = 0;
373 return op;
375 (void) cppReader_popBuffer (pfile);
376 goto retry;
377 case CPP_HSPACE: case CPP_COMMENT:
378 goto retry;
379 case CPP_NUMBER:
380 return cppReader_parseNumber (pfile, tok_start, tok_end - tok_start);
381 case CPP_STRING:
382 cppReader_errorLit (pfile,
383 cstring_makeLiteralTemp ("string constants not allowed in #if expressions"));
384 op.op = CPPREADER_ERRORTOK;
385 return op;
386 case CPP_CHAR:
387 /* This code for reading a character constant
388 handles multicharacter constants and wide characters.
389 It is mostly copied from c-lex.c. */
391 int result = 0;
392 int num_chars = 0;
393 size_t width = MAX_CHAR_TYPE_SIZE;
394 int wide_flag = 0;
395 int max_chars;
396 char *ptr = tok_start;
398 if (*ptr == 'L')
400 ptr++;
401 wide_flag = 1;
402 width = MAX_WCHAR_TYPE_SIZE;
403 max_chars = 1;
405 else
407 max_chars = size_toInt (MAX_LONG_TYPE_SIZE / width);
410 ++ptr;
411 while (ptr < tok_end && ((c = *ptr++) != '\''))
413 if (c == '\\')
415 c = cppReader_parseEscape (pfile, &ptr);
416 if (width < HOST_BITS_PER_INT && c >= (1 << width))
418 cppReader_pedwarnLit
419 (pfile,
420 cstring_makeLiteralTemp ("Escape sequence out of range for character"));
424 num_chars++;
426 /* Merge character into result; ignore excess chars. */
427 if (num_chars < max_chars + 1)
429 if (width < HOST_BITS_PER_INT)
431 result = (int) ((unsigned) result << width) | (c & ((1 << width) - 1));
433 else
435 result = c;
440 if (c != '\'')
441 cppReader_errorLit (pfile,
442 cstring_makeLiteralTemp ("malformatted character constant"));
443 else if (num_chars == 0)
444 cppReader_errorLit (pfile,
445 cstring_makeLiteralTemp ("empty character constant"));
446 else if (num_chars > max_chars)
448 num_chars = max_chars;
449 cppReader_errorLit (pfile,
450 cstring_makeLiteralTemp ("character constant too long"));
452 else if (num_chars != 1 && ! cppReader_isTraditional (pfile))
454 cppReader_warningLit (pfile,
455 cstring_makeLiteralTemp ("multi-character character constant"));
457 else
462 /* If char type is signed, sign-extend the constant. */
463 if (wide_flag == 0)
465 int num_bits = num_chars * width;
467 if ((cpphash_lookup ("__CHAR_UNSIGNED__",
468 sizeof ("__CHAR_UNSIGNED__") - 1, -1) != NULL)
469 || (((unsigned) result >> (int_toNonNegative (num_bits - 1))) & 1) == 0)
471 op.value
472 = result & ((unsigned long) ~0
473 >> int_toNonNegative ((HOST_BITS_PER_LONG - num_bits)));
475 else
477 op.value
478 = result | ~((unsigned long) ~0
479 >> int_toNonNegative ((HOST_BITS_PER_LONG - num_bits)));
482 else
484 op.value = result;
488 /* This is always a signed type. */
489 op.unsignedp = FALSE;
490 op.op = CPPEXP_CHAR;
492 return op;
494 case CPP_NAME:
495 DPRINTF (("Name!"));
496 return cppReader_parseNumber (pfile, "0", 0);
498 case CPP_OTHER:
499 /* See if it is a special token of length 2. */
500 if (tok_start + 2 == tok_end)
502 for (toktab = tokentab2; toktab->operator != NULL; toktab++)
504 if (tok_start[0] == toktab->operator[0] &&
505 tok_start[1] == toktab->operator[1])
507 /*@loopbreak@*/ break;
511 if (toktab->token == CPPREADER_ERRORTOK)
513 cppReader_error (pfile,
514 message ("`%s' not allowed in operand of `#if'",
515 cstring_fromChars (tok_start)));
518 op.op = toktab->token;
519 return op;
521 /*@fallthrough@*/
522 default:
523 op.op = *tok_start;
524 return op;
527 /*@notreached@*/
528 BADEXIT;
532 /* Parse a C escape sequence. STRING_PTR points to a variable
533 containing a pointer to the string to parse. That pointer
534 is updated past the characters we use. The value of the
535 escape sequence is returned.
537 A negative value means the sequence \ newline was seen,
538 which is supposed to be equivalent to nothing at all.
540 If \ is followed by a null character, we return a negative
541 value and leave the string pointer pointing at the null character.
543 If \ is followed by 000, we return 0 and leave the string pointer
544 after the zeros. A value of 0 does not mean end of string. */
547 cppReader_parseEscape (cppReader *pfile, char **string_ptr)
549 char c = *(*string_ptr)++;
551 switch (c)
553 case 'a':
554 return TARGET_BELL;
555 case 'b':
556 return TARGET_BS;
557 case 'e':
558 case 'E':
559 if (cppReader_isPedantic (pfile))
561 cppReader_pedwarn (pfile,
562 message ("non-standard escape sequence, `\\%c'", c));
564 return (char) 033;
565 case 'f':
566 return TARGET_FF;
567 case 'n':
568 return TARGET_NEWLINE;
569 case 'r':
570 return TARGET_CR;
571 case 't':
572 return TARGET_TAB;
573 case 'v':
574 return TARGET_VT;
575 case '\n':
576 return -2;
577 case 0:
578 (*string_ptr)--;
579 return 0;
581 case '0':
582 case '1':
583 case '2':
584 case '3':
585 case '4':
586 case '5':
587 case '6':
588 case '7':
590 int i = (int) c - '0';
591 int count = 0;
593 while (++count < 3)
595 c = *(*string_ptr)++;
596 if (c >= '0' && c <= '7')
598 i = ((unsigned) i << 3) + c - '0';
601 else
603 (*string_ptr)--;
604 /*@loopbreak@*/ break;
607 if ((i & ~((1 << MAX_CHAR_TYPE_SIZE) - 1)) != 0)
609 i &= (1 << MAX_CHAR_TYPE_SIZE) - 1;
610 cppReader_pedwarnLit (pfile,
611 cstring_makeLiteralTemp ("octal character constant does not fit in a byte"));
613 return i;
615 case 'x':
617 register unsigned i = 0, overflow = 0, digits_found = 0, digit;
618 for (;;)
620 c = *(*string_ptr)++;
622 if (c >= '0' && c <= '9')
624 digit = (unsigned int) (c - '0');
626 else if (c >= 'a' && c <= 'f')
628 digit = (unsigned int) (c - 'a') + 10;
630 else if (c >= 'A' && c <= 'F')
632 digit = (unsigned int) (c - 'A') + 10;
634 else
636 (*string_ptr)--;
637 /*@loopbreak@*/ break;
639 overflow |= i ^ (i << 4 >> 4);
640 i = (i << 4) + digit;
641 digits_found = 1;
644 if (digits_found == 0)
646 cppReader_errorLit (pfile,
647 cstring_makeLiteralTemp ("\\x used with no following hex digits"));
650 if ((overflow | (i & ~((1 << int_toNonNegative (BITS_PER_UNIT)) - 1))) != 0)
652 i &= (1 << BITS_PER_UNIT) - 1;
653 cppReader_pedwarnLit (pfile,
654 cstring_makeLiteralTemp ("hex character constant does not fit in a byte"));
657 return i;
659 default:
660 return c;
664 static void
665 integer_overflow (cppReader *pfile)
667 if (cppReader_isPedantic (pfile))
668 cppReader_pedwarnLit (pfile,
669 cstring_makeLiteralTemp ("integer overflow in preprocessor expression"));
672 static long
673 left_shift (cppReader *pfile, long a, bool unsignedp, unsigned long b)
675 if (b >= HOST_BITS_PER_LONG)
677 if (!unsignedp && a != 0)
679 integer_overflow (pfile);
682 return 0;
684 else if (unsignedp)
686 return (unsigned long) a << b;
688 else
690 /*@-shiftimplementation@*/
691 long l = a << b; /* int_toNonNegative removed (allow shifts of negative values) */
693 if (l >> b != a) /* int_toNonNegative removed (allow shifts of negative values) */
695 integer_overflow (pfile);
698 return l;
702 static long
703 right_shift (long a, bool unsignedp, unsigned long b)
705 if (b >= HOST_BITS_PER_LONG)
706 return (unsignedp ? 0 : int_toNonNegative (a) >> (HOST_BITS_PER_LONG - 1));
707 else if (unsignedp)
708 return (unsigned long) a >> b;
709 else
710 return a >> b; /* int_toNonNegative removed (allow shifts of negative values) */
711 /*@=shiftimplementation@*/
714 /* These priorities are all even, so we can handle associatively. */
716 /*@constant int PAREN_INNER_PRIO@*/
717 #define PAREN_INNER_PRIO 0
719 /*@constant int COMMA_PRIO@*/
720 #define COMMA_PRIO 4
722 /*@constant int COND_PRIO@*/
723 #define COND_PRIO (COMMA_PRIO+2)
725 /*@constant int OROR_PRIO@*/
726 #define OROR_PRIO (COND_PRIO+2)
728 /*@constant int ANDAND_PRIO@*/
729 #define ANDAND_PRIO (OROR_PRIO+2)
731 /*@constant int OR_PRIO@*/
732 #define OR_PRIO (ANDAND_PRIO+2)
734 /*@constant int XOR_PRIO@*/
735 #define XOR_PRIO (OR_PRIO+2)
737 /*@constant int AND_PRIO@*/
738 #define AND_PRIO (XOR_PRIO+2)
740 /*@constant int CPP_EQUAL_PRIO@*/
741 #define CPP_EQUAL_PRIO (AND_PRIO+2)
743 /*@constant int LESS_PRIO@*/
744 #define LESS_PRIO (CPP_EQUAL_PRIO+2)
746 /*@constant int SHIFT_PRIO@*/
747 #define SHIFT_PRIO (LESS_PRIO+2)
749 /*@constant int PLUS_PRIO@*/
750 #define PLUS_PRIO (SHIFT_PRIO+2)
752 /*@constant int MUL_PRIO@*/
753 #define MUL_PRIO (PLUS_PRIO+2)
755 /*@constant int UNARY_PRIO@*/
756 #define UNARY_PRIO (MUL_PRIO+2)
758 /*@constant int PAREN_OUTER_PRIO@*/
759 #define PAREN_OUTER_PRIO (UNARY_PRIO+2)
761 /*@notfunction@*/
762 #define COMPARE(OP) \
763 top->unsignedp = FALSE;\
764 top->value = ((unsigned1 || unsigned2) \
765 ? (unsigned long) v1 OP (unsigned long) v2 \
766 : ((long) v1 OP (long) v2)) ? 1 : 0
768 /* Parse and evaluate a C expression, reading from PFILE.
769 Returns the value of the expression. */
771 /*@constant int INIT_STACK_SIZE@*/
772 # define INIT_STACK_SIZE 20
774 HOST_WIDE_INT
775 cppReader_parseExpression (cppReader *pfile)
777 /* The implementation is an operator precedence parser,
778 i.e. a bottom-up parser, using a stack for not-yet-reduced tokens.
780 The stack base is 'stack', and the current stack pointer is 'top'.
781 There is a stack element for each operator (only),
782 and the most recently pushed operator is 'top->op'.
783 An operand (value) is stored in the 'value' field of the stack
784 element of the operator that precedes it.
785 In that case the 'flags' field has the HAVE_VALUE flag set. */
787 struct operation init_stack[INIT_STACK_SIZE];
788 struct operation *stack = init_stack;
789 struct operation *limit = stack + INIT_STACK_SIZE;
790 register struct operation *top = stack;
791 int lprio, rprio = 0;
792 int skip_evaluation = 0;
794 top->rprio = 0;
795 top->flags = 0;
797 for (;;)
799 struct operation op;
800 int flags = 0;
802 /* Read a token */
803 op = cppexp_lex (pfile);
805 /* See if the token is an operand, in which case go to set_value.
806 If the token is an operator, figure out its left and right
807 priorities, and then goto maybe_reduce. */
809 switch (op.op)
811 case NAME:
812 top->value = 0;
813 top->unsignedp = FALSE;
814 goto set_value;
815 case CPPEXP_INT:
816 case CPPEXP_CHAR:
817 top->value = op.value;
818 top->unsignedp = op.unsignedp;
819 goto set_value;
820 case 0:
821 lprio = 0; goto maybe_reduce;
822 case '+': case '-':
823 /* Is this correct if unary ? FIXME */
824 flags = RIGHT_OPERAND_REQUIRED;
825 lprio = PLUS_PRIO; rprio = lprio + 1; goto maybe_reduce;
826 case '!': case '~':
827 flags = RIGHT_OPERAND_REQUIRED;
828 rprio = UNARY_PRIO; lprio = rprio + 1; goto maybe_reduce;
829 case '*': case '/': case '%':
830 lprio = MUL_PRIO; goto binop;
831 case '<': case '>': case LEQ: case GEQ:
832 lprio = LESS_PRIO; goto binop;
833 case CPP_EQUALTOK: case NOTEQUAL:
834 lprio = CPP_EQUAL_PRIO; goto binop;
835 case LSH: case RSH:
836 lprio = SHIFT_PRIO; goto binop;
837 case '&': lprio = AND_PRIO; goto binop;
838 case '^': lprio = XOR_PRIO; goto binop;
839 case '|': lprio = OR_PRIO; goto binop;
840 case ANDAND: lprio = ANDAND_PRIO; goto binop;
841 case OROR: lprio = OROR_PRIO; goto binop;
842 case ',':
843 lprio = COMMA_PRIO; goto binop;
844 case '(':
845 lprio = PAREN_OUTER_PRIO; rprio = PAREN_INNER_PRIO;
846 goto maybe_reduce;
847 case ')':
848 lprio = PAREN_INNER_PRIO; rprio = PAREN_OUTER_PRIO;
849 goto maybe_reduce;
850 case ':':
851 lprio = COND_PRIO; rprio = COND_PRIO;
852 goto maybe_reduce;
853 case '?':
854 lprio = COND_PRIO + 1; rprio = COND_PRIO;
855 goto maybe_reduce;
856 binop:
857 flags = LEFT_OPERAND_REQUIRED | RIGHT_OPERAND_REQUIRED;
858 rprio = lprio + 1;
859 goto maybe_reduce;
860 default:
861 cppReader_error
862 (pfile,
863 message ("Invalid character in #if: %c",
864 (char) op.op));
865 goto syntax_error;
868 set_value:
869 /* Push a value onto the stack. */
870 if ((top->flags & HAVE_VALUE) != 0)
872 cppReader_errorLit (pfile,
873 cstring_makeLiteralTemp ("syntax error in #if"));
874 goto syntax_error;
876 top->flags |= HAVE_VALUE;
877 continue;
879 maybe_reduce:
880 /* Push an operator, and check if we can reduce now. */
881 while (top->rprio > lprio)
883 /*@-usedef@*/
884 HOST_WIDE_INT v1 = top[-1].value;
885 HOST_WIDE_INT v2 = top[0].value;
886 bool unsigned1 = top[-1].unsignedp;
887 bool unsigned2 = top[0].unsignedp;
889 top--;
891 if (((top[1].flags & LEFT_OPERAND_REQUIRED) != 0)
892 && ((top[0].flags & HAVE_VALUE) == 0))
894 cppReader_errorLit (pfile,
895 cstring_makeLiteralTemp ("syntax error - missing left operand"));
896 goto syntax_error;
898 if (((top[1].flags & RIGHT_OPERAND_REQUIRED) != 0)
899 && ((top[1].flags & HAVE_VALUE) == 0))
901 cppReader_errorLit (pfile,
902 cstring_makeLiteralTemp ("syntax error - missing right operand"));
903 goto syntax_error;
905 /* top[0].value = (top[1].op)(v1, v2);*/
906 switch (top[1].op)
908 case '+':
909 if ((top->flags & HAVE_VALUE) == 0)
910 { /* Unary '+' */
911 top->value = v2;
912 top->unsignedp = unsigned2;
913 top->flags |= HAVE_VALUE;
915 else
917 top->value = v1 + v2;
918 top->unsignedp = unsigned1 || unsigned2;
919 if (!top->unsignedp && (skip_evaluation == 0)
920 && ! possibleSumSign (v1, v2, top->value))
921 integer_overflow (pfile);
923 /*@switchbreak@*/ break;
924 case '-':
925 if ((top->flags & HAVE_VALUE) == 0)
926 { /* Unary '-' */
927 top->value = - v2;
928 if ((skip_evaluation == 0)
929 && (top->value & v2) < 0 && !unsigned2)
930 integer_overflow (pfile);
931 top->unsignedp = unsigned2;
932 top->flags |= HAVE_VALUE;
934 else
935 { /* Binary '-' */
936 top->value = v1 - v2;
937 top->unsignedp = unsigned1 || unsigned2;
938 if (!top->unsignedp && (skip_evaluation == 0)
939 && !possibleSumSign (top->value, v2, v1))
941 integer_overflow (pfile);
944 /*@switchbreak@*/ break;
945 case '*':
946 top->unsignedp = unsigned1 || unsigned2;
948 if (top->unsignedp)
950 top->value = (unsigned long) v1 * v2;
952 else if (skip_evaluation == 0)
954 top->value = v1 * v2;
955 if ((v1 != 0)
956 && (top->value / v1 != v2
957 || (top->value & v1 & v2) < 0))
959 integer_overflow (pfile);
962 else
967 /*@switchbreak@*/ break;
968 case '/':
969 if (skip_evaluation != 0)
970 /*@switchbreak@*/ break;
971 if (v2 == 0)
973 cppReader_errorLit (pfile,
974 cstring_makeLiteralTemp ("Division by zero in #if"));
975 v2 = 1;
977 top->unsignedp = unsigned1 || unsigned2;
978 if (top->unsignedp)
979 top->value = (unsigned long) v1 / v2;
980 else
982 top->value = v1 / v2;
983 if ((top->value & v1 & v2) < 0)
984 integer_overflow (pfile);
986 /*@switchbreak@*/ break;
987 case '%':
988 if (skip_evaluation != 0)
989 /*@switchbreak@*/ break;
990 if (v2 == 0)
992 cppReader_errorLit (pfile,
993 cstring_makeLiteralTemp ("Division by zero in #if"));
994 v2 = 1;
996 top->unsignedp = unsigned1 || unsigned2;
997 if (top->unsignedp)
998 top->value = (unsigned long) v1 % v2;
999 else
1000 top->value = v1 % v2;
1001 /*@switchbreak@*/ break;
1002 case '!':
1003 if ((top->flags & HAVE_VALUE) != 0)
1005 cppReader_errorLit (pfile,
1006 cstring_makeLiteralTemp ("Syntax error"));
1007 goto syntax_error;
1010 top->value = (v2 == 0) ? 1 : 0;
1011 top->unsignedp = FALSE;
1012 top->flags |= HAVE_VALUE;
1013 /*@switchbreak@*/ break;
1014 case '~':
1015 if ((top->flags & HAVE_VALUE) != 0)
1017 cppReader_errorLit (pfile,
1018 cstring_makeLiteralTemp ("syntax error"));
1019 goto syntax_error;
1021 top->value = ~ v2;
1022 top->unsignedp = unsigned2;
1023 top->flags |= HAVE_VALUE;
1024 /*@switchbreak@*/ break;
1025 case '<': COMPARE(<); /*@switchbreak@*/ break;
1026 case '>': COMPARE(>); /*@switchbreak@*/ break;
1027 case LEQ: COMPARE(<=); /*@switchbreak@*/ break;
1028 case GEQ: COMPARE(>=); /*@switchbreak@*/ break;
1029 case CPP_EQUALTOK:
1030 top->value = (v1 == v2) ? 1 : 0;
1031 top->unsignedp = FALSE;
1032 /*@switchbreak@*/ break;
1033 case NOTEQUAL:
1034 top->value = (v1 != v2) ? 1 : 0;
1035 top->unsignedp = FALSE;
1036 /*@switchbreak@*/ break;
1037 case LSH:
1038 if (skip_evaluation != 0)
1040 /*@switchbreak@*/ break;
1043 top->unsignedp = unsigned1;
1044 if (v2 < 0 && ! unsigned2)
1045 top->value = right_shift (v1, unsigned1, -v2);
1046 else
1047 top->value = left_shift (pfile, v1, unsigned1, v2);
1048 /*@switchbreak@*/ break;
1049 case RSH:
1050 if (skip_evaluation != 0)
1052 /*@switchbreak@*/ break;
1054 top->unsignedp = unsigned1;
1055 if (v2 < 0 && ! unsigned2)
1056 top->value = left_shift (pfile, v1, unsigned1, -v2);
1057 else
1058 top->value = right_shift (v1, unsigned1, v2);
1059 /*@switchbreak@*/ break;
1061 /*@notfunction@*/
1062 #define LOGICAL(OP) \
1063 top->value = v1 OP v2;\
1064 top->unsignedp = unsigned1 || unsigned2;
1066 case '&': LOGICAL(&); /*@switchbreak@*/ break;
1067 case '^': LOGICAL(^); /*@switchbreak@*/ break;
1068 case '|': LOGICAL(|); /*@switchbreak@*/ break;
1069 case ANDAND:
1070 top->value = ((v1 != 0) && (v2 != 0)) ? 1 : 0;
1071 top->unsignedp = FALSE;
1073 if (v1 == 0)
1075 skip_evaluation--;
1077 /*@switchbreak@*/ break;
1078 case OROR:
1079 top->value = ((v1 != 0) || (v2 != 0)) ? 1 : 0;
1080 top->unsignedp = FALSE;
1081 if (v1 != 0)
1083 skip_evaluation--;
1085 /*@switchbreak@*/ break;
1086 case ',':
1087 if (cppReader_isPedantic (pfile))
1088 cppReader_pedwarnLit (pfile,
1089 cstring_makeLiteralTemp ("comma operator in operand of `#if'"));
1090 top->value = v2;
1091 top->unsignedp = unsigned2;
1092 /*@switchbreak@*/ break;
1093 case '(': case '?':
1094 cppReader_errorLit (pfile,
1095 cstring_makeLiteralTemp ("syntax error in #if"));
1096 goto syntax_error;
1097 case ':':
1098 if (top[0].op != '?')
1100 cppReader_errorLit (pfile,
1101 cstring_makeLiteralTemp ("syntax error ':' without preceding '?'"));
1102 goto syntax_error;
1104 else if (((top[1].flags & HAVE_VALUE) == 0)
1105 || ((top[-1].flags & HAVE_VALUE) == 0)
1106 || ((top[0].flags & HAVE_VALUE) == 0))
1108 cppReader_errorLit (pfile,
1109 cstring_makeLiteralTemp ("bad syntax for ?: operator"));
1110 goto syntax_error;
1112 else
1114 top--;
1115 if (top->value != 0)
1117 skip_evaluation--;
1120 top->value = (top->value != 0) ? v1 : v2;
1121 top->unsignedp = unsigned1 || unsigned2;
1123 /*@switchbreak@*/ break;
1124 case ')':
1125 if (((top[1].flags & HAVE_VALUE) != 0)
1126 || ((top[0].flags & HAVE_VALUE) == 0)
1127 || top[0].op != '('
1128 || ((top[-1].flags & HAVE_VALUE) != 0))
1130 cppReader_errorLit (pfile,
1131 cstring_makeLiteralTemp ("mismatched parentheses in #if"));
1132 goto syntax_error;
1134 else
1136 top--;
1137 top->value = v1;
1138 top->unsignedp = unsigned1;
1139 top->flags |= HAVE_VALUE;
1141 /*@switchbreak@*/ break;
1142 default:
1143 /*@-formatconst@*/
1144 fprintf (stderr,
1145 top[1].op >= ' ' && top[1].op <= '~'
1146 ? "unimplemented operator '%c'\n"
1147 : "unimplemented operator '\\%03o'\n",
1148 top[1].op);
1149 /*@=formatconst@*/
1152 if (op.op == 0)
1154 long val;
1156 if (top != stack)
1158 cppReader_errorLit (pfile,
1159 cstring_makeLiteralTemp ("internal error in #if expression"));
1162 val = top->value;
1164 if (stack != init_stack)
1166 sfree (stack);
1167 /*@-branchstate@*/
1168 } /*@=branchstate@*/
1170 return val;
1172 top++;
1174 /* Check for and handle stack overflow. */
1175 if (top == limit)
1177 struct operation *new_stack;
1178 size_t old_size = size_fromInt ((char *) limit - (char *) stack);
1179 size_t new_size = (size_t) (2 * old_size);
1181 if (stack != init_stack)
1183 new_stack = (struct operation *) drealloc ((char *) stack,
1184 new_size);
1186 else
1188 new_stack = (struct operation *) dmalloc (new_size);
1190 /* Bug: the parameters were in the wrong order! */
1191 memcpy ((char *) new_stack, (char *) stack, old_size);
1192 /*@-branchstate@*/
1193 } /*@=branchstate@*/
1195 stack = new_stack;
1196 top = (struct operation *) ((char *) new_stack + old_size);
1197 limit = (struct operation *) ((char *) new_stack + new_size);
1198 /*@-branchstate@*/
1199 } /*@=branchstate@*/
1201 top->flags = flags;
1202 top->rprio = rprio;
1203 top->op = op.op;
1204 if ((op.op == OROR && (top[-1].value != 0))
1205 || (op.op == ANDAND && (top[-1].value == 0))
1206 || (op.op == '?' && (top[-1].value == 0)))
1208 skip_evaluation++;
1210 else if (op.op == ':')
1212 if (top[-2].value != 0) /* Was condition true? */
1214 skip_evaluation++;
1216 else
1218 skip_evaluation--;
1221 else
1226 syntax_error:
1227 /*@-usereleased@*/
1228 if (stack != init_stack)
1230 sfree (stack);
1231 /*@-branchstate@*/
1232 } /*@=branchstate@*/
1233 /*@=usereleased@*/
1235 cppReader_skipRestOfLine (pfile);
1236 return 0;