2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
4 ** Massachusetts Institute of Technology
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.
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.
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
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
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 */
56 /*@+matchanyintegral@*/
58 # include "splintMacros.nf"
65 # include "cpperror.h"
68 /*@constant short CPPREADER_ERRORTOK@*/
69 #define CPPREADER_ERRORTOK 299
71 /*@constant int OROR@*/
74 /*@constant int ANDAND@*/
77 /*@constant int CPP_EQUALTOK@*/
78 #define CPP_EQUALTOK 302
80 /*@constant int NOTEQUAL@*/
83 /*@constant int LEQ@*/
86 /*@constant int GEQ@*/
89 /*@constant int LSH@*/
92 /*@constant int RSH@*/
95 /*@constant int NAME@*/
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@*/
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);
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) @*/
155 unsigned long nd
, ULONG_MAX_over_base
;
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
++)
167 /* It's a float since it contains a point. */
170 cstring_makeLiteralTemp
171 ("Floating point numbers not allowed in #if expressions"));
172 op
.op
= CPPREADER_ERRORTOK
;
177 if (len
>= 3 && (mstring_equalPrefix (p
, "0x")
178 || mstring_equalPrefix (p
, "0X")))
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
--) {
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;
213 /* `l' means long, and `u' means unsigned. */
216 if (c
== 'l' || c
== 'L')
219 cppReader_errorLit (pfile
,
220 cstring_makeLiteralTemp ("two `l's in integer constant"));
223 else if (c
== 'u' || c
== 'U')
226 cppReader_errorLit (pfile
,
227 cstring_makeLiteralTemp ("two `u's in integer constant"));
232 /*@innerbreak@*/ break;
237 /*@innerbreak@*/ break;
242 /* Don't look for any more digits after the suffixes. */
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
);
261 cstring_makeLiteralTemp ("Invalid number in #if expression"));
262 op
.op
= CPPREADER_ERRORTOK
;
266 if (base
<= largest_digit
)
270 cstring_makeLiteralTemp
271 ("Integer constant contains digits beyond the radix"));
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
)
288 cstring_makeLiteralTemp ("Integer constant is so large that it is unsigned"));
296 DPRINTF (("Parse number: %d", op
.value
));
301 /*@null@*/ /*@observer@*/ char *operator;
305 static struct token tokentab2
[] = {
310 { "==", CPP_EQUALTOK
},
314 { "++", CPPREADER_ERRORTOK
},
315 { "--", CPPREADER_ERRORTOK
},
316 { NULL
, CPPREADER_ERRORTOK
}
319 /* Read one token. */
321 struct operation
cppexp_lex (cppReader
*pfile
)
325 register struct token
*toktab
;
326 enum cpp_token token
;
328 char *tok_start
, *tok_end
;
333 old_written
= size_toInt (cpplib_getWritten (pfile
));
334 cppSkipHspace (pfile
);
335 ic
= cpplib_bufPeek (cppReader_getBufferSafe (pfile
));
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
));
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
;
365 case CPP_EOF
: /* Should not happen ... */
370 if (cstring_isDefined (cppReader_getBufferSafe (pfile
)->fname
))
375 (void) cppReader_popBuffer (pfile
);
377 case CPP_HSPACE
: case CPP_COMMENT
:
380 return cppReader_parseNumber (pfile
, tok_start
, tok_end
- tok_start
);
382 cppReader_errorLit (pfile
,
383 cstring_makeLiteralTemp ("string constants not allowed in #if expressions"));
384 op
.op
= CPPREADER_ERRORTOK
;
387 /* This code for reading a character constant
388 handles multicharacter constants and wide characters.
389 It is mostly copied from c-lex.c. */
393 size_t width
= MAX_CHAR_TYPE_SIZE
;
396 char *ptr
= tok_start
;
402 width
= MAX_WCHAR_TYPE_SIZE
;
407 max_chars
= size_toInt (MAX_LONG_TYPE_SIZE
/ width
);
411 while (ptr
< tok_end
&& ((c
= *ptr
++) != '\''))
415 c
= cppReader_parseEscape (pfile
, &ptr
);
416 if (width
< HOST_BITS_PER_INT
&& c
>= (1 << width
))
420 cstring_makeLiteralTemp ("Escape sequence out of range for character"));
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));
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"));
462 /* If char type is signed, sign-extend the constant. */
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)
472 = result
& ((unsigned long) ~0
473 >> int_toNonNegative ((HOST_BITS_PER_LONG
- num_bits
)));
478 = result
| ~((unsigned long) ~0
479 >> int_toNonNegative ((HOST_BITS_PER_LONG
- num_bits
)));
488 /* This is always a signed type. */
489 op
.unsignedp
= FALSE
;
496 return cppReader_parseNumber (pfile
, "0", 0);
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
;
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
)++;
559 if (cppReader_isPedantic (pfile
))
561 cppReader_pedwarn (pfile
,
562 message ("non-standard escape sequence, `\\%c'", c
));
568 return TARGET_NEWLINE
;
590 int i
= (int) c
- '0';
595 c
= *(*string_ptr
)++;
596 if (c
>= '0' && c
<= '7')
598 i
= ((unsigned) i
<< 3) + c
- '0';
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"));
617 register unsigned i
= 0, overflow
= 0, digits_found
= 0, digit
;
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;
637 /*@loopbreak@*/ break;
639 overflow
|= i
^ (i
<< 4 >> 4);
640 i
= (i
<< 4) + digit
;
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"));
665 integer_overflow (cppReader
*pfile
)
667 if (cppReader_isPedantic (pfile
))
668 cppReader_pedwarnLit (pfile
,
669 cstring_makeLiteralTemp ("integer overflow in preprocessor expression"));
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
);
686 return (unsigned long) a
<< b
;
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
);
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));
708 return (unsigned long) a
>> b
;
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@*/
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)
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
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;
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. */
813 top
->unsignedp
= FALSE
;
817 top
->value
= op
.value
;
818 top
->unsignedp
= op
.unsignedp
;
821 lprio
= 0; goto maybe_reduce
;
823 /* Is this correct if unary ? FIXME */
824 flags
= RIGHT_OPERAND_REQUIRED
;
825 lprio
= PLUS_PRIO
; rprio
= lprio
+ 1; goto maybe_reduce
;
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
;
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
;
843 lprio
= COMMA_PRIO
; goto binop
;
845 lprio
= PAREN_OUTER_PRIO
; rprio
= PAREN_INNER_PRIO
;
848 lprio
= PAREN_INNER_PRIO
; rprio
= PAREN_OUTER_PRIO
;
851 lprio
= COND_PRIO
; rprio
= COND_PRIO
;
854 lprio
= COND_PRIO
+ 1; rprio
= COND_PRIO
;
857 flags
= LEFT_OPERAND_REQUIRED
| RIGHT_OPERAND_REQUIRED
;
863 message ("Invalid character in #if: %c",
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"));
876 top
->flags
|= HAVE_VALUE
;
880 /* Push an operator, and check if we can reduce now. */
881 while (top
->rprio
> lprio
)
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
;
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"));
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"));
905 /* top[0].value = (top[1].op)(v1, v2);*/
909 if ((top
->flags
& HAVE_VALUE
) == 0)
912 top
->unsignedp
= unsigned2
;
913 top
->flags
|= HAVE_VALUE
;
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;
925 if ((top
->flags
& HAVE_VALUE
) == 0)
928 if ((skip_evaluation
== 0)
929 && (top
->value
& v2
) < 0 && !unsigned2
)
930 integer_overflow (pfile
);
931 top
->unsignedp
= unsigned2
;
932 top
->flags
|= HAVE_VALUE
;
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;
946 top
->unsignedp
= unsigned1
|| unsigned2
;
950 top
->value
= (unsigned long) v1
* v2
;
952 else if (skip_evaluation
== 0)
954 top
->value
= v1
* v2
;
956 && (top
->value
/ v1
!= v2
957 || (top
->value
& v1
& v2
) < 0))
959 integer_overflow (pfile
);
967 /*@switchbreak@*/ break;
969 if (skip_evaluation
!= 0)
970 /*@switchbreak@*/ break;
973 cppReader_errorLit (pfile
,
974 cstring_makeLiteralTemp ("Division by zero in #if"));
977 top
->unsignedp
= unsigned1
|| unsigned2
;
979 top
->value
= (unsigned long) v1
/ v2
;
982 top
->value
= v1
/ v2
;
983 if ((top
->value
& v1
& v2
) < 0)
984 integer_overflow (pfile
);
986 /*@switchbreak@*/ break;
988 if (skip_evaluation
!= 0)
989 /*@switchbreak@*/ break;
992 cppReader_errorLit (pfile
,
993 cstring_makeLiteralTemp ("Division by zero in #if"));
996 top
->unsignedp
= unsigned1
|| unsigned2
;
998 top
->value
= (unsigned long) v1
% v2
;
1000 top
->value
= v1
% v2
;
1001 /*@switchbreak@*/ break;
1003 if ((top
->flags
& HAVE_VALUE
) != 0)
1005 cppReader_errorLit (pfile
,
1006 cstring_makeLiteralTemp ("Syntax error"));
1010 top
->value
= (v2
== 0) ? 1 : 0;
1011 top
->unsignedp
= FALSE
;
1012 top
->flags
|= HAVE_VALUE
;
1013 /*@switchbreak@*/ break;
1015 if ((top
->flags
& HAVE_VALUE
) != 0)
1017 cppReader_errorLit (pfile
,
1018 cstring_makeLiteralTemp ("syntax error"));
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;
1030 top
->value
= (v1
== v2
) ? 1 : 0;
1031 top
->unsignedp
= FALSE
;
1032 /*@switchbreak@*/ break;
1034 top
->value
= (v1
!= v2
) ? 1 : 0;
1035 top
->unsignedp
= FALSE
;
1036 /*@switchbreak@*/ break;
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
);
1047 top
->value
= left_shift (pfile
, v1
, unsigned1
, v2
);
1048 /*@switchbreak@*/ break;
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
);
1058 top
->value
= right_shift (v1
, unsigned1
, v2
);
1059 /*@switchbreak@*/ break;
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;
1070 top
->value
= ((v1
!= 0) && (v2
!= 0)) ? 1 : 0;
1071 top
->unsignedp
= FALSE
;
1077 /*@switchbreak@*/ break;
1079 top
->value
= ((v1
!= 0) || (v2
!= 0)) ? 1 : 0;
1080 top
->unsignedp
= FALSE
;
1085 /*@switchbreak@*/ break;
1087 if (cppReader_isPedantic (pfile
))
1088 cppReader_pedwarnLit (pfile
,
1089 cstring_makeLiteralTemp ("comma operator in operand of `#if'"));
1091 top
->unsignedp
= unsigned2
;
1092 /*@switchbreak@*/ break;
1094 cppReader_errorLit (pfile
,
1095 cstring_makeLiteralTemp ("syntax error in #if"));
1098 if (top
[0].op
!= '?')
1100 cppReader_errorLit (pfile
,
1101 cstring_makeLiteralTemp ("syntax error ':' without preceding '?'"));
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"));
1115 if (top
->value
!= 0)
1120 top
->value
= (top
->value
!= 0) ? v1
: v2
;
1121 top
->unsignedp
= unsigned1
|| unsigned2
;
1123 /*@switchbreak@*/ break;
1125 if (((top
[1].flags
& HAVE_VALUE
) != 0)
1126 || ((top
[0].flags
& HAVE_VALUE
) == 0)
1128 || ((top
[-1].flags
& HAVE_VALUE
) != 0))
1130 cppReader_errorLit (pfile
,
1131 cstring_makeLiteralTemp ("mismatched parentheses in #if"));
1138 top
->unsignedp
= unsigned1
;
1139 top
->flags
|= HAVE_VALUE
;
1141 /*@switchbreak@*/ break;
1145 top
[1].op
>= ' ' && top
[1].op
<= '~'
1146 ? "unimplemented operator '%c'\n"
1147 : "unimplemented operator '\\%03o'\n",
1158 cppReader_errorLit (pfile
,
1159 cstring_makeLiteralTemp ("internal error in #if expression"));
1164 if (stack
!= init_stack
)
1168 } /*@=branchstate@*/
1174 /* Check for and handle stack overflow. */
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
,
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
);
1193 } /*@=branchstate@*/
1196 top
= (struct operation
*) ((char *) new_stack
+ old_size
);
1197 limit
= (struct operation
*) ((char *) new_stack
+ new_size
);
1199 } /*@=branchstate@*/
1204 if ((op
.op
== OROR
&& (top
[-1].value
!= 0))
1205 || (op
.op
== ANDAND
&& (top
[-1].value
== 0))
1206 || (op
.op
== '?' && (top
[-1].value
== 0)))
1210 else if (op
.op
== ':')
1212 if (top
[-2].value
!= 0) /* Was condition true? */
1228 if (stack
!= init_stack
)
1232 } /*@=branchstate@*/
1235 cppReader_skipRestOfLine (pfile
);