]> andersk Git - splint.git/blame - src/cppexp.c
Cleaned up flags to generate manual help.
[splint.git] / src / cppexp.c
CommitLineData
616915dd 1/*
11db3170 2** Splint - annotation-assisted static program checker
77d37419 3** Copyright (C) 1994-2002 University of Virginia,
616915dd 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.
19**
20** For information on lclint: lclint-request@cs.virginia.edu
21** To report a bug: lclint-bug@cs.virginia.edu
11db3170 22** For more information: http://www.splint.org
616915dd 23*/
24/*
25** cppexp.c
26*/
27/* Parse C expressions for CCCP.
28 Copyright (C) 1987, 1992, 1994, 1995, 1997 Free Software Foundation.
29
30This program is free software; you can redistribute it and/or modify it
31under the terms of the GNU General Public License as published by the
32Free Software Foundation; either version 2, or (at your option) any
33later version.
34
35This program is distributed in the hope that it will be useful,
36but WITHOUT ANY WARRANTY; without even the implied warranty of
37MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38GNU General Public License for more details.
39
40You should have received a copy of the GNU General Public License
41along with this program; if not, write to the Free Software
42Foundation, 59 Temple Place - Suite 330,
43Boston, MA 02111-1307, USA.
44
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!
48
49Written by Per Bothner 1994. */
50
51/* Parse a C expression from text in a string */
52
53/*@+charint@*/
54/*@+ignorequals@*/
55/*@+ignoresigns@*/
56/*@+matchanyintegral@*/
616915dd 57
58# include <string.h>
59# include "lclintMacros.nf"
60# include "llbasic.h"
616915dd 61# include "cpplib.h"
62# include "cpphash.h"
63# include "cppexp.h"
64# include "cpperror.h"
65
66/* Yield nonzero if adding two numbers with A's and B's signs can yield a
67 number with SUM's sign, where A, B, and SUM are all C integers. */
68
69/*@function static bool possibleSumSign (sef int, int, int)
70 modifies nothing ; @*/
71
72#define possibleSumSign(a, b, sum) ((((a) ^ (b)) | ~ ((a) ^ (sum))) < 0)
73
74/* these are guesses! */
75
a956d444 76/*@constant int BITS_PER_UNIT = 8@*/
616915dd 77# define BITS_PER_UNIT 8
78
79/*@constant size_t BITS_PER_CHAR@*/
80# define BITS_PER_CHAR 8
81
82/*@constant size_t BITS_PER_WORD@*/
83# define BITS_PER_WORD 32
84
85/*@constant size_t HOST_BITS_PER_INT@*/
86# define HOST_BITS_PER_INT 32
87
a956d444 88/*@constant size_t HOST_BITS_PER_LONG = 32@*/
616915dd 89# define HOST_BITS_PER_LONG 32
90
91/*@constant char TARGET_BELL@*/
92# define TARGET_BELL (char) 6
93
94/*@constant char TARGET_BS@*/
95# define TARGET_BS (char) 7
96
97/*@constant char TARGET_FF@*/
98# define TARGET_FF (char) 8
99
100/*@constant char TARGET_NEWLINE@*/
101# define TARGET_NEWLINE '\n'
102
103/*@constant char TARGET_CR@*/
104# define TARGET_CR '\n'
105
106/*@constant char TARGET_TAB@*/
107# define TARGET_TAB '\t'
108
109/*@constant char TARGET_VT@*/
110# define TARGET_VT '\v'
111
112#ifdef MULTIBYTE_CHARS
113#include <stdlib.h>
114#include <locale.h>
115#endif
116
117#include <stdio.h>
118
119#ifndef INT_TYPE_SIZE
120/*@constant size_t INT_TYPE_SIZE@*/
121#define INT_TYPE_SIZE BITS_PER_WORD
122#endif
123
124#ifndef LONG_TYPE_SIZE
125/*@constant size_t LONG_TYPE_SIZE@*/
126#define LONG_TYPE_SIZE BITS_PER_WORD
127#endif
128
129#ifndef WCHAR_TYPE_SIZE
130/*@constant size_t WCHAR_TYPE_SIZE@*/
131#define WCHAR_TYPE_SIZE INT_TYPE_SIZE
132#endif
133
134# ifndef CHAR_TYPE_SIZE
135/*@constant size_t CHAR_TYPE_SIZE@*/
136# define CHAR_TYPE_SIZE BITS_PER_CHAR
137# endif
138
139#ifndef MAX_CHAR_TYPE_SIZE
140/*@constant size_t MAX_CHAR_TYPE_SIZE@*/
141#define MAX_CHAR_TYPE_SIZE CHAR_TYPE_SIZE
142#endif
143
144#ifndef MAX_LONG_TYPE_SIZE
145/*@constant size_t MAX_LONG_TYPE_SIZE@*/
146#define MAX_LONG_TYPE_SIZE LONG_TYPE_SIZE
147#endif
148
149#ifndef MAX_WCHAR_TYPE_SIZE
150/*@constant size_t MAX_WCHAR_TYPE_SIZE@*/
151#define MAX_WCHAR_TYPE_SIZE WCHAR_TYPE_SIZE
152#endif
153
3e3ec469 154static struct operation cppexp_lex (cppReader *);
616915dd 155static void integer_overflow (cppReader *);
156static long left_shift (cppReader *, long, bool p_unsignedp, size_t);
157static long right_shift (long, bool p_unsignedp, unsigned long);
158
159/*@constant short CPPREADER_ERRORTOK@*/
160#define CPPREADER_ERRORTOK 299
161
162/*@constant int OROR@*/
163#define OROR 300
164
165/*@constant int ANDAND@*/
166#define ANDAND 301
167
168/*@constant int CPP_EQUALTOK@*/
169#define CPP_EQUALTOK 302
170
171/*@constant int NOTEQUAL@*/
172#define NOTEQUAL 303
173
174/*@constant int LEQ@*/
175#define LEQ 304
176
177/*@constant int GEQ@*/
178#define GEQ 305
179
180/*@constant int LSH@*/
181#define LSH 306
182
183/*@constant int RSH@*/
184#define RSH 307
185
186/*@constant int NAME@*/
187#define NAME 308
188
189/*@constant short CPPEXP_INT@*/
190#define CPPEXP_INT 309
191
192/*@constant short CPPEXP_CHAR@*/
193#define CPPEXP_CHAR 310
194
195/*@constant int LEFT_OPERAND_REQUIRED@*/
196#define LEFT_OPERAND_REQUIRED 1
197
198/*@constant int RIGHT_OPERAND_REQUIRED@*/
199#define RIGHT_OPERAND_REQUIRED 2
200
201/*@constant int HAVE_VALUE@*/
202#define HAVE_VALUE 4
203
204#ifndef HOST_BITS_PER_WIDE_INT
205
206#if HOST_BITS_PER_LONG > HOST_BITS_PER_INT
207/*@constant int HOST_BITS_PER_WIDE_INT@*/
208#define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_LONG
209/*@notfunction@*/
210#define HOST_WIDE_INT long
211#else
212/*@constant int HOST_BITS_PER_WIDE_INT@*/
213#define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_INT
214/*@notfunction@*/
215#define HOST_WIDE_INT long
216#endif
217
218#endif
219
220struct operation {
221 short op;
222
223 /* Priority of op (relative to it right operand). */
224 /*@reldef@*/ char rprio;
225
226 /*@reldef@*/ char flags;
227
228 /* true if value should be treated as unsigned */
229 /*@reldef@*/ bool unsignedp;
230
231 /* The value logically "right" of op. */
232 /*@reldef@*/ HOST_WIDE_INT value;
233} ;
234
235/* Take care of parsing a number (anything that starts with a digit).
236 LEN is the number of characters in it. */
237
238/* maybe needs to actually deal with floating point numbers */
239
240struct operation
241cppReader_parseNumber (cppReader *pfile, char *start, int olen)
242{
243 struct operation op;
244 char *p = start;
245 char c;
246 int i;
247 long n = 0;
248 unsigned long nd, ULONG_MAX_over_base;
249 int base = 10;
250 int len = olen;
251 bool overflow = FALSE;
252 int digit, largest_digit = 0;
253 bool spec_long = FALSE;
254
255 op.unsignedp = FALSE;
256
257 for (i = 0; i < len; i++)
258 {
259 if (p[i] == '.') {
260 /* It's a float since it contains a point. */
261 cppReader_errorLit
262 (pfile,
263 cstring_makeLiteralTemp
264 ("Floating point numbers not allowed in #if expressions"));
265 op.op = CPPREADER_ERRORTOK;
266 return op;
267 }
268 }
269
270 if (len >= 3 && (mstring_equalPrefix (p, "0x")
271 || mstring_equalPrefix (p, "0X")))
272 {
273 p += 2;
274 base = 16;
275 len -= 2;
276 }
277 else if (*p == '0')
278 {
279 base = 8;
280 }
281 else
282 {
283 ;
284 }
285
286 /* Some buggy compilers (e.g. MPW C) seem to need both casts. */
287 ULONG_MAX_over_base = ((unsigned long) -1) / ((unsigned long) base);
288
289 for (; len > 0; len--) {
290 c = *p++;
291
292 if (c >= '0' && c <= '9')
293 {
294 digit = (int) (c - '0');
295 }
296 else if (base == 16 && c >= 'a' && c <= 'f')
297 {
298 digit = (int) (c - 'a') + 10;
299 }
300 else if (base == 16 && c >= 'A' && c <= 'F')
301 {
302 digit = (int) (c - 'A') + 10;
303 }
304 else
305 {
306 /* `l' means long, and `u' means unsigned. */
307 while (TRUE)
308 {
309 if (c == 'l' || c == 'L')
310 {
311 if (spec_long)
312 cppReader_errorLit (pfile,
313 cstring_makeLiteralTemp ("two `l's in integer constant"));
314 spec_long = TRUE;
315 }
316 else if (c == 'u' || c == 'U')
317 {
318 if (op.unsignedp)
319 cppReader_errorLit (pfile,
320 cstring_makeLiteralTemp ("two `u's in integer constant"));
321 op.unsignedp = TRUE;
322 }
323 else
324 {
325 /*@innerbreak@*/ break;
326 }
327
328 if (--len == 0)
329 {
330 /*@innerbreak@*/ break;
331 }
332
333 c = *p++;
334 }
335 /* Don't look for any more digits after the suffixes. */
336 break;
337 }
338
339 if (largest_digit < digit)
340 {
341 largest_digit = digit;
342 }
343
344 nd = (long unsigned) (n * base + digit);
345 overflow |= (ULONG_MAX_over_base < (unsigned long) n)
346 | (nd < (unsigned long) n);
347 n = (long) nd;
348 }
349
350 if (len != 0)
351 {
352 cppReader_errorLit
353 (pfile,
354 cstring_makeLiteralTemp ("Invalid number in #if expression"));
355 op.op = CPPREADER_ERRORTOK;
356 return op;
357 }
358
359 if (base <= largest_digit)
360 {
361 cppReader_pedwarnLit
362 (pfile,
363 cstring_makeLiteralTemp
364 ("Integer constant contains digits beyond the radix"));
365 }
366
367 if (overflow)
368 {
28bf4b0b 369 /*@i23 add flags for all these...*/
616915dd 370 cppReader_pedwarnLit
371 (pfile,
372 cstring_makeLiteralTemp ("Integer constant out of range"));
373 }
374
375 /* If too big to be signed, consider it unsigned. */
376 if ((long) n < 0 && ! op.unsignedp)
377 {
378 if (base == 10)
379 {
380 cppReader_warningLit
381 (pfile,
382 cstring_makeLiteralTemp ("Integer constant is so large that it is unsigned"));
383 }
384
385 op.unsignedp = TRUE;
386 }
387
388 op.value = n;
389 op.op = CPPEXP_INT;
3e3ec469 390 DPRINTF (("Parse number: %d", op.value));
616915dd 391 return op;
392}
393
394struct token {
395 /*@null@*/ /*@observer@*/ char *operator;
396 int token;
397};
398
399static struct token tokentab2[] = {
400 { "&&", ANDAND },
401 { "||", OROR },
402 { "<<", LSH },
403 { ">>", RSH },
404 { "==", CPP_EQUALTOK },
405 { "!=", NOTEQUAL },
406 { "<=", LEQ },
407 { ">=", GEQ },
408 { "++", CPPREADER_ERRORTOK },
409 { "--", CPPREADER_ERRORTOK },
410 { NULL, CPPREADER_ERRORTOK }
411} ;
412
413/* Read one token. */
414
3e3ec469 415struct operation cppexp_lex (cppReader *pfile)
616915dd 416{
417 int ic;
418 char c;
419 register struct token *toktab;
420 enum cpp_token token;
421 struct operation op;
422 char *tok_start, *tok_end;
423 int old_written;
424
425 retry:
3e3ec469 426
427 old_written = size_toInt (cpplib_getWritten (pfile));
616915dd 428 cppSkipHspace (pfile);
3e3ec469 429 ic = cpplib_bufPeek (cppReader_getBufferSafe (pfile));
616915dd 430
431 c = (char) ic;
432 llassert (c != '#');
3e3ec469 433 DPRINTF (("Read: %c", c));
434
616915dd 435 if (c == '\n')
436 {
437 op.op = 0;
438 return op;
439 }
440
3e3ec469 441 token = cpplib_getTokenForceExpand (pfile);
442
616915dd 443 tok_start = pfile->token_buffer + old_written;
3e3ec469 444 tok_end = cpplib_getPWritten (pfile);
445
446 DPRINTF (("Token: %s < %s", tok_start, tok_end));
447
616915dd 448 pfile->limit = tok_start;
449
450 switch (token)
3e3ec469 451 {
616915dd 452 case CPP_EOF: /* Should not happen ... */
453 case CPP_VSPACE:
454 op.op = 0;
455 return op;
456 case CPP_POP:
457 if (cstring_isDefined (cppReader_getBufferSafe (pfile)->fname))
458 {
459 op.op = 0;
460 return op;
461 }
462 (void) cppReader_popBuffer (pfile);
463 goto retry;
464 case CPP_HSPACE: case CPP_COMMENT:
465 goto retry;
466 case CPP_NUMBER:
467 return cppReader_parseNumber (pfile, tok_start, tok_end - tok_start);
468 case CPP_STRING:
469 cppReader_errorLit (pfile,
3e3ec469 470 cstring_makeLiteralTemp ("string constants not allowed in #if expressions"));
616915dd 471 op.op = CPPREADER_ERRORTOK;
472 return op;
473 case CPP_CHAR:
474 /* This code for reading a character constant
475 handles multicharacter constants and wide characters.
476 It is mostly copied from c-lex.c. */
477 {
478 int result = 0;
479 int num_chars = 0;
480 size_t width = MAX_CHAR_TYPE_SIZE;
481 int wide_flag = 0;
482 int max_chars;
483 char *ptr = tok_start;
484#ifdef MULTIBYTE_CHARS
485 char token_buffer[MAX_LONG_TYPE_SIZE/MAX_CHAR_TYPE_SIZE + MB_CUR_MAX];
486#else
487 char token_buffer[MAX_LONG_TYPE_SIZE/MAX_CHAR_TYPE_SIZE + 1];
488#endif
3e3ec469 489
616915dd 490 if (*ptr == 'L')
491 {
492 ptr++;
493 wide_flag = 1;
494 width = MAX_WCHAR_TYPE_SIZE;
495#ifdef MULTIBYTE_CHARS
496 max_chars = MB_CUR_MAX;
497#else
498 max_chars = 1;
499#endif
500 }
501 else
502 {
503 max_chars = size_toInt (MAX_LONG_TYPE_SIZE / width);
504 }
3e3ec469 505
616915dd 506 ++ptr;
507 while (ptr < tok_end && ((c = *ptr++) != '\''))
508 {
509 if (c == '\\')
510 {
511 c = cppReader_parseEscape (pfile, &ptr);
512 if (width < HOST_BITS_PER_INT && c >= (1 << width))
513 {
514 cppReader_pedwarnLit
515 (pfile,
516 cstring_makeLiteralTemp ("Escape sequence out of range for character"));
517 }
518 }
519
520 num_chars++;
521
522 /* Merge character into result; ignore excess chars. */
523 if (num_chars < max_chars + 1)
524 {
525 if (width < HOST_BITS_PER_INT)
526 {
527 result = (int) ((unsigned) result << width) | (c & ((1 << width) - 1));
528 }
529 else
530 {
531 result = c;
532 }
533
534 token_buffer[num_chars - 1] = c;
535 }
536 }
537
538 token_buffer[num_chars] = 0;
539
540 if (c != '\'')
541 cppReader_errorLit (pfile,
542 cstring_makeLiteralTemp ("malformatted character constant"));
543 else if (num_chars == 0)
544 cppReader_errorLit (pfile,
545 cstring_makeLiteralTemp ("empty character constant"));
546 else if (num_chars > max_chars)
547 {
548 num_chars = max_chars;
549 cppReader_errorLit (pfile,
550 cstring_makeLiteralTemp ("character constant too long"));
551 }
552 else if (num_chars != 1 && ! cppReader_isTraditional (pfile))
553 {
554 cppReader_warningLit (pfile,
555 cstring_makeLiteralTemp ("multi-character character constant"));
556 }
557 else
558 {
559 ;
560 }
561
562 /* If char type is signed, sign-extend the constant. */
563 if (wide_flag == 0)
564 {
565 int num_bits = num_chars * width;
566
3e3ec469 567 if ((cpphash_lookup ("__CHAR_UNSIGNED__",
616915dd 568 sizeof ("__CHAR_UNSIGNED__") - 1, -1) != NULL)
a956d444 569 || (((unsigned) result >> (int_toNonNegative (num_bits - 1))) & 1) == 0)
616915dd 570 {
571 op.value
a956d444 572 = result & ((unsigned long) ~0
573 >> int_toNonNegative ((HOST_BITS_PER_LONG - num_bits)));
616915dd 574 }
575 else
576 {
577 op.value
a956d444 578 = result | ~((unsigned long) ~0
579 >> int_toNonNegative ((HOST_BITS_PER_LONG - num_bits)));
616915dd 580 }
581 }
582 else
583 {
584#ifdef MULTIBYTE_CHARS
585 /* Set the initial shift state and convert the next sequence. */
586 result = 0;
587 /* In all locales L'\0' is zero and mbtowc will return zero,
588 so don't use it. */
589 if (num_chars > 1
590 || (num_chars == 1 && token_buffer[0] != '\0'))
591 {
592 wchar_t wc;
593 (void) mbtowc (NULL, NULL, 0);
594 if (mbtowc (& wc, token_buffer, num_chars) == num_chars)
595 result = wc;
596 else
597 cppReader_pedwarn (pfile,"Ignoring invalid multibyte character");
598 }
599#endif
600 op.value = result;
601 }
602 }
603
604 /* This is always a signed type. */
605 op.unsignedp = FALSE;
606 op.op = CPPEXP_CHAR;
607
608 return op;
609
610 case CPP_NAME:
3e3ec469 611 DPRINTF (("Name!"));
616915dd 612 return cppReader_parseNumber (pfile, "0", 0);
613
614 case CPP_OTHER:
615 /* See if it is a special token of length 2. */
616 if (tok_start + 2 == tok_end)
617 {
618 for (toktab = tokentab2; toktab->operator != NULL; toktab++)
619 {
620 if (tok_start[0] == toktab->operator[0]
621 && tok_start[1] == toktab->operator[1])
622 {
623 /*@loopbreak@*/ break;
624 }
625 }
626
627 if (toktab->token == CPPREADER_ERRORTOK)
628 {
629 cppReader_error (pfile, message ("`%s' not allowed in operand of `#if'", cstring_fromChars (tok_start)));
630 }
631
632 op.op = toktab->token;
633 return op;
634 }
635 /*@fallthrough@*/
636 default:
637 op.op = *tok_start;
638 return op;
639 }
640
641 BADEXIT;
642 /*@notreached@*/
643}
644
645
646/* Parse a C escape sequence. STRING_PTR points to a variable
647 containing a pointer to the string to parse. That pointer
648 is updated past the characters we use. The value of the
649 escape sequence is returned.
650
651 A negative value means the sequence \ newline was seen,
652 which is supposed to be equivalent to nothing at all.
653
654 If \ is followed by a null character, we return a negative
655 value and leave the string pointer pointing at the null character.
656
657 If \ is followed by 000, we return 0 and leave the string pointer
658 after the zeros. A value of 0 does not mean end of string. */
659
660int
661cppReader_parseEscape (cppReader *pfile, char **string_ptr)
662{
663 char c = *(*string_ptr)++;
664
665 switch (c)
666 {
667 case 'a':
668 return TARGET_BELL;
669 case 'b':
670 return TARGET_BS;
671 case 'e':
672 case 'E':
673 if (cppReader_isPedantic (pfile))
674 {
675 cppReader_pedwarn (pfile,
676 message ("non-ANSI-standard escape sequence, `\\%c'", c));
677 }
678 return (char) 033;
679 case 'f':
680 return TARGET_FF;
681 case 'n':
682 return TARGET_NEWLINE;
683 case 'r':
684 return TARGET_CR;
685 case 't':
686 return TARGET_TAB;
687 case 'v':
688 return TARGET_VT;
689 case '\n':
690 return -2;
691 case 0:
692 (*string_ptr)--;
693 return 0;
694
695 case '0':
696 case '1':
697 case '2':
698 case '3':
699 case '4':
700 case '5':
701 case '6':
702 case '7':
703 {
704 int i = (int) c - '0';
705 int count = 0;
706
707 while (++count < 3)
708 {
709 c = *(*string_ptr)++;
710 if (c >= '0' && c <= '7')
711 {
712 i = ((unsigned) i << 3) + c - '0';
713 }
714
715 else
716 {
717 (*string_ptr)--;
718 /*@loopbreak@*/ break;
719 }
720 }
721 if ((i & ~((1 << MAX_CHAR_TYPE_SIZE) - 1)) != 0)
722 {
723 i &= (1 << MAX_CHAR_TYPE_SIZE) - 1;
724 cppReader_pedwarnLit (pfile,
725 cstring_makeLiteralTemp ("octal character constant does not fit in a byte"));
726 }
727 return i;
728 }
729 case 'x':
730 {
731 register unsigned i = 0, overflow = 0, digits_found = 0, digit;
732 for (;;)
733 {
734 c = *(*string_ptr)++;
735
736 if (c >= '0' && c <= '9')
737 {
738 digit = (unsigned int) (c - '0');
739 }
740 else if (c >= 'a' && c <= 'f')
741 {
742 digit = (unsigned int) (c - 'a') + 10;
743 }
744 else if (c >= 'A' && c <= 'F')
745 {
746 digit = (unsigned int) (c - 'A') + 10;
747 }
748 else
749 {
750 (*string_ptr)--;
751 /*@loopbreak@*/ break;
752 }
753 overflow |= i ^ (i << 4 >> 4);
754 i = (i << 4) + digit;
755 digits_found = 1;
756 }
757
758 if (digits_found == 0)
759 {
760 cppReader_errorLit (pfile,
761 cstring_makeLiteralTemp ("\\x used with no following hex digits"));
762 }
763
a956d444 764 if ((overflow | (i & ~((1 << int_toNonNegative (BITS_PER_UNIT)) - 1))) != 0)
616915dd 765 {
766 i &= (1 << BITS_PER_UNIT) - 1;
767 cppReader_pedwarnLit (pfile,
768 cstring_makeLiteralTemp ("hex character constant does not fit in a byte"));
769 }
770
771 return i;
772 }
773 default:
774 return c;
775 }
776}
777
778static void
779integer_overflow (cppReader *pfile)
780{
781 if (cppReader_isPedantic (pfile))
782 cppReader_pedwarnLit (pfile,
783 cstring_makeLiteralTemp ("integer overflow in preprocessor expression"));
784}
785
786static long
787left_shift (cppReader *pfile, long a, bool unsignedp, size_t b)
788{
789 if (b >= HOST_BITS_PER_LONG)
790 {
791 if (!unsignedp && a != 0)
792 {
793 integer_overflow (pfile);
794 }
795
796 return 0;
797 }
798 else if (unsignedp)
799 {
800 return (unsigned long) a << b;
801 }
802 else
803 {
a956d444 804 long l = int_toNonNegative (a) << b;
616915dd 805
a956d444 806 if (int_toNonNegative (l) >> b != a)
616915dd 807 {
808 integer_overflow (pfile);
809 }
810
811 return l;
812 }
813}
814
815static long
816right_shift (long a, bool unsignedp, unsigned long b)
817{
818 if (b >= HOST_BITS_PER_LONG)
a956d444 819 return (unsignedp ? 0 : int_toNonNegative (a) >> (HOST_BITS_PER_LONG - 1));
616915dd 820 else if (unsignedp)
821 return (unsigned long) a >> b;
822 else
a956d444 823 return int_toNonNegative (a) >> b;
616915dd 824}
825
826/* These priorities are all even, so we can handle associatively. */
827
828/*@constant int PAREN_INNER_PRIO@*/
829#define PAREN_INNER_PRIO 0
830
831/*@constant int COMMA_PRIO@*/
832#define COMMA_PRIO 4
833
834/*@constant int COND_PRIO@*/
835#define COND_PRIO (COMMA_PRIO+2)
836
837/*@constant int OROR_PRIO@*/
838#define OROR_PRIO (COND_PRIO+2)
839
840/*@constant int ANDAND_PRIO@*/
841#define ANDAND_PRIO (OROR_PRIO+2)
842
843/*@constant int OR_PRIO@*/
844#define OR_PRIO (ANDAND_PRIO+2)
845
846/*@constant int XOR_PRIO@*/
847#define XOR_PRIO (OR_PRIO+2)
848
849/*@constant int AND_PRIO@*/
850#define AND_PRIO (XOR_PRIO+2)
851
852/*@constant int CPP_EQUAL_PRIO@*/
853#define CPP_EQUAL_PRIO (AND_PRIO+2)
854
855/*@constant int LESS_PRIO@*/
856#define LESS_PRIO (CPP_EQUAL_PRIO+2)
857
858/*@constant int SHIFT_PRIO@*/
859#define SHIFT_PRIO (LESS_PRIO+2)
860
861/*@constant int PLUS_PRIO@*/
862#define PLUS_PRIO (SHIFT_PRIO+2)
863
864/*@constant int MUL_PRIO@*/
865#define MUL_PRIO (PLUS_PRIO+2)
866
867/*@constant int UNARY_PRIO@*/
868#define UNARY_PRIO (MUL_PRIO+2)
869
870/*@constant int PAREN_OUTER_PRIO@*/
871#define PAREN_OUTER_PRIO (UNARY_PRIO+2)
872
873/*@notfunction@*/
874#define COMPARE(OP) \
875 top->unsignedp = FALSE;\
876 top->value = ((unsigned1 || unsigned2) \
877 ? (unsigned long) v1 OP (unsigned long) v2 \
878 : ((long) v1 OP (long) v2)) ? 1 : 0
879
880/* Parse and evaluate a C expression, reading from PFILE.
881 Returns the value of the expression. */
882
883/*@constant int INIT_STACK_SIZE@*/
884# define INIT_STACK_SIZE 20
885
886HOST_WIDE_INT
887cppReader_parseExpression (cppReader *pfile)
888{
889 /* The implementation is an operator precedence parser,
890 i.e. a bottom-up parser, using a stack for not-yet-reduced tokens.
891
892 The stack base is 'stack', and the current stack pointer is 'top'.
893 There is a stack element for each operator (only),
894 and the most recently pushed operator is 'top->op'.
895 An operand (value) is stored in the 'value' field of the stack
896 element of the operator that precedes it.
897 In that case the 'flags' field has the HAVE_VALUE flag set. */
898
899 struct operation init_stack[INIT_STACK_SIZE];
900 struct operation *stack = init_stack;
901 struct operation *limit = stack + INIT_STACK_SIZE;
902 register struct operation *top = stack;
903 int lprio, rprio = 0;
904 int skip_evaluation = 0;
905
906 top->rprio = 0;
907 top->flags = 0;
908
909 for (;;)
910 {
911 struct operation op;
912 int flags = 0;
913
914 /* Read a token */
3e3ec469 915 op = cppexp_lex (pfile);
616915dd 916
917 /* See if the token is an operand, in which case go to set_value.
918 If the token is an operator, figure out its left and right
919 priorities, and then goto maybe_reduce. */
920
921 switch (op.op)
922 {
923 case NAME:
924 top->value = 0, top->unsignedp = FALSE;
925 goto set_value;
926 case CPPEXP_INT:
927 case CPPEXP_CHAR:
928 top->value = op.value;
929 top->unsignedp = op.unsignedp;
930 goto set_value;
931 case 0:
932 lprio = 0; goto maybe_reduce;
933 case '+': case '-':
934 /* Is this correct if unary ? FIXME */
935 flags = RIGHT_OPERAND_REQUIRED;
936 lprio = PLUS_PRIO; rprio = lprio + 1; goto maybe_reduce;
937 case '!': case '~':
938 flags = RIGHT_OPERAND_REQUIRED;
939 rprio = UNARY_PRIO; lprio = rprio + 1; goto maybe_reduce;
940 case '*': case '/': case '%':
941 lprio = MUL_PRIO; goto binop;
942 case '<': case '>': case LEQ: case GEQ:
943 lprio = LESS_PRIO; goto binop;
944 case CPP_EQUALTOK: case NOTEQUAL:
945 lprio = CPP_EQUAL_PRIO; goto binop;
946 case LSH: case RSH:
947 lprio = SHIFT_PRIO; goto binop;
948 case '&': lprio = AND_PRIO; goto binop;
949 case '^': lprio = XOR_PRIO; goto binop;
950 case '|': lprio = OR_PRIO; goto binop;
951 case ANDAND: lprio = ANDAND_PRIO; goto binop;
952 case OROR: lprio = OROR_PRIO; goto binop;
953 case ',':
954 lprio = COMMA_PRIO; goto binop;
955 case '(':
956 lprio = PAREN_OUTER_PRIO; rprio = PAREN_INNER_PRIO;
957 goto maybe_reduce;
958 case ')':
959 lprio = PAREN_INNER_PRIO; rprio = PAREN_OUTER_PRIO;
960 goto maybe_reduce;
961 case ':':
962 lprio = COND_PRIO; rprio = COND_PRIO;
963 goto maybe_reduce;
964 case '?':
965 lprio = COND_PRIO + 1; rprio = COND_PRIO;
966 goto maybe_reduce;
967 binop:
968 flags = LEFT_OPERAND_REQUIRED | RIGHT_OPERAND_REQUIRED;
969 rprio = lprio + 1;
970 goto maybe_reduce;
971 default:
972 cppReader_error
973 (pfile,
974 message ("Invalid character in #if: %c",
975 (char) op.op));
976 goto syntax_error;
977 }
978
979 set_value:
980 /* Push a value onto the stack. */
981 if ((top->flags & HAVE_VALUE) != 0)
982 {
983 cppReader_errorLit (pfile,
984 cstring_makeLiteralTemp ("syntax error in #if"));
985 goto syntax_error;
986 }
987 top->flags |= HAVE_VALUE;
988 continue;
989
990 maybe_reduce:
991 /* Push an operator, and check if we can reduce now. */
992 while (top->rprio > lprio)
993 {
994 /*@-usedef@*/
995 long v1 = top[-1].value, v2 = top[0].value;
996 bool unsigned1 = top[-1].unsignedp;
997 bool unsigned2 = top[0].unsignedp;
998
999 top--;
1000
1001 if (((top[1].flags & LEFT_OPERAND_REQUIRED) != 0)
1002 && ((top[0].flags & HAVE_VALUE) == 0))
1003 {
1004 cppReader_errorLit (pfile,
1005 cstring_makeLiteralTemp ("syntax error - missing left operand"));
1006 goto syntax_error;
1007 }
1008 if (((top[1].flags & RIGHT_OPERAND_REQUIRED) != 0)
1009 && ((top[1].flags & HAVE_VALUE) == 0))
1010 {
1011 cppReader_errorLit (pfile,
1012 cstring_makeLiteralTemp ("syntax error - missing right operand"));
1013 goto syntax_error;
1014 }
1015 /* top[0].value = (top[1].op)(v1, v2);*/
1016 switch (top[1].op)
1017 {
1018 case '+':
1019 if ((top->flags & HAVE_VALUE) == 0)
1020 { /* Unary '+' */
1021 top->value = v2;
1022 top->unsignedp = unsigned2;
1023 top->flags |= HAVE_VALUE;
1024 }
1025 else
1026 {
1027 top->value = v1 + v2;
1028 top->unsignedp = unsigned1 || unsigned2;
1029 if (!top->unsignedp && (skip_evaluation == 0)
1030 && ! possibleSumSign (v1, v2, top->value))
1031 integer_overflow (pfile);
1032 }
1033 /*@switchbreak@*/ break;
1034 case '-':
1035 if ((top->flags & HAVE_VALUE) == 0)
1036 { /* Unary '-' */
1037 top->value = - v2;
1038 if ((skip_evaluation == 0)
1039 && (top->value & v2) < 0 && !unsigned2)
1040 integer_overflow (pfile);
1041 top->unsignedp = unsigned2;
1042 top->flags |= HAVE_VALUE;
1043 }
1044 else
1045 { /* Binary '-' */
1046 top->value = v1 - v2;
1047 top->unsignedp = unsigned1 || unsigned2;
1048 if (!top->unsignedp && (skip_evaluation == 0)
1049 && !possibleSumSign (top->value, v2, v1))
1050 {
1051 integer_overflow (pfile);
1052 }
1053 }
1054 /*@switchbreak@*/ break;
1055 case '*':
1056 top->unsignedp = unsigned1 || unsigned2;
1057
1058 if (top->unsignedp)
1059 {
1060 top->value = (unsigned long) v1 * v2;
1061 }
1062 else if (skip_evaluation == 0)
1063 {
1064 top->value = v1 * v2;
1065 if ((v1 != 0)
1066 && (top->value / v1 != v2
1067 || (top->value & v1 & v2) < 0))
1068 {
1069 integer_overflow (pfile);
1070 }
1071 }
1072 else
1073 {
1074 ;
1075 }
1076
1077 /*@switchbreak@*/ break;
1078 case '/':
1079 if (skip_evaluation != 0)
1080 /*@switchbreak@*/ break;
1081 if (v2 == 0)
1082 {
1083 cppReader_errorLit (pfile,
1084 cstring_makeLiteralTemp ("Division by zero in #if"));
1085 v2 = 1;
1086 }
1087 top->unsignedp = unsigned1 || unsigned2;
1088 if (top->unsignedp)
1089 top->value = (unsigned long) v1 / v2;
1090 else
1091 {
1092 top->value = v1 / v2;
1093 if ((top->value & v1 & v2) < 0)
1094 integer_overflow (pfile);
1095 }
1096 /*@switchbreak@*/ break;
1097 case '%':
1098 if (skip_evaluation != 0)
1099 /*@switchbreak@*/ break;
1100 if (v2 == 0)
1101 {
1102 cppReader_errorLit (pfile,
1103 cstring_makeLiteralTemp ("Division by zero in #if"));
1104 v2 = 1;
1105 }
1106 top->unsignedp = unsigned1 || unsigned2;
1107 if (top->unsignedp)
1108 top->value = (unsigned long) v1 % v2;
1109 else
1110 top->value = v1 % v2;
1111 /*@switchbreak@*/ break;
1112 case '!':
1113 if ((top->flags & HAVE_VALUE) != 0)
1114 {
1115 cppReader_errorLit (pfile,
1116 cstring_makeLiteralTemp ("Syntax error"));
1117 goto syntax_error;
1118 }
1119
1120 top->value = (v2 == 0) ? 1 : 0;
1121 top->unsignedp = FALSE;
1122 top->flags |= HAVE_VALUE;
1123 /*@switchbreak@*/ break;
1124 case '~':
1125 if ((top->flags & HAVE_VALUE) != 0)
1126 {
1127 cppReader_errorLit (pfile,
1128 cstring_makeLiteralTemp ("syntax error"));
1129 goto syntax_error;
1130 }
1131 top->value = ~ v2;
1132 top->unsignedp = unsigned2;
1133 top->flags |= HAVE_VALUE;
1134 /*@switchbreak@*/ break;
1135 case '<': COMPARE(<); /*@switchbreak@*/ break;
1136 case '>': COMPARE(>); /*@switchbreak@*/ break;
1137 case LEQ: COMPARE(<=); /*@switchbreak@*/ break;
1138 case GEQ: COMPARE(>=); /*@switchbreak@*/ break;
1139 case CPP_EQUALTOK:
1140 top->value = (v1 == v2) ? 1 : 0;
1141 top->unsignedp = FALSE;
1142 /*@switchbreak@*/ break;
1143 case NOTEQUAL:
1144 top->value = (v1 != v2) ? 1 : 0;
1145 top->unsignedp = FALSE;
1146 /*@switchbreak@*/ break;
1147 case LSH:
1148 if (skip_evaluation != 0)
1149 {
1150 /*@switchbreak@*/ break;
1151 }
1152
1153 top->unsignedp = unsigned1;
1154 if (v2 < 0 && ! unsigned2)
1155 top->value = right_shift (v1, unsigned1, -v2);
1156 else
1157 top->value = left_shift (pfile, v1, unsigned1, v2);
1158 /*@switchbreak@*/ break;
1159 case RSH:
1160 if (skip_evaluation != 0)
1161 {
1162 /*@switchbreak@*/ break;
1163 }
1164 top->unsignedp = unsigned1;
1165 if (v2 < 0 && ! unsigned2)
1166 top->value = left_shift (pfile, v1, unsigned1, -v2);
1167 else
1168 top->value = right_shift (v1, unsigned1, v2);
1169 /*@switchbreak@*/ break;
1170
1171/*@notfunction@*/
1172#define LOGICAL(OP) \
1173 top->value = v1 OP v2;\
1174 top->unsignedp = unsigned1 || unsigned2;
1175
1176 case '&': LOGICAL(&); /*@switchbreak@*/ break;
1177 case '^': LOGICAL(^); /*@switchbreak@*/ break;
1178 case '|': LOGICAL(|); /*@switchbreak@*/ break;
1179 case ANDAND:
1180 top->value = ((v1 != 0) && (v2 != 0)) ? 1 : 0;
1181 top->unsignedp = FALSE;
1182
1183 if (v1 == 0)
1184 {
1185 skip_evaluation--;
1186 }
1187 /*@switchbreak@*/ break;
1188 case OROR:
1189 top->value = ((v1 != 0) || (v2 != 0)) ? 1 : 0;
1190 top->unsignedp = FALSE;
1191 if (v1 != 0)
1192 {
1193 skip_evaluation--;
1194 }
1195 /*@switchbreak@*/ break;
1196 case ',':
1197 if (cppReader_isPedantic (pfile))
1198 cppReader_pedwarnLit (pfile,
1199 cstring_makeLiteralTemp ("comma operator in operand of `#if'"));
1200 top->value = v2;
1201 top->unsignedp = unsigned2;
1202 /*@switchbreak@*/ break;
1203 case '(': case '?':
1204 cppReader_errorLit (pfile,
1205 cstring_makeLiteralTemp ("syntax error in #if"));
1206 goto syntax_error;
1207 case ':':
1208 if (top[0].op != '?')
1209 {
1210 cppReader_errorLit (pfile,
1211 cstring_makeLiteralTemp ("syntax error ':' without preceding '?'"));
1212 goto syntax_error;
1213 }
1214 else if (((top[1].flags & HAVE_VALUE) == 0)
1215 || ((top[-1].flags & HAVE_VALUE) == 0)
1216 || ((top[0].flags & HAVE_VALUE) == 0))
1217 {
1218 cppReader_errorLit (pfile,
1219 cstring_makeLiteralTemp ("bad syntax for ?: operator"));
1220 goto syntax_error;
1221 }
1222 else
1223 {
1224 top--;
1225 if (top->value != 0)
1226 {
1227 skip_evaluation--;
1228 }
1229
1230 top->value = (top->value != 0) ? v1 : v2;
1231 top->unsignedp = unsigned1 || unsigned2;
1232 }
1233 /*@switchbreak@*/ break;
1234 case ')':
1235 if (((top[1].flags & HAVE_VALUE) != 0)
1236 || ((top[0].flags & HAVE_VALUE) == 0)
1237 || top[0].op != '('
1238 || ((top[-1].flags & HAVE_VALUE) != 0))
1239 {
1240 cppReader_errorLit (pfile,
1241 cstring_makeLiteralTemp ("mismatched parentheses in #if"));
1242 goto syntax_error;
1243 }
1244 else
1245 {
1246 top--;
1247 top->value = v1;
1248 top->unsignedp = unsigned1;
1249 top->flags |= HAVE_VALUE;
1250 }
1251 /*@switchbreak@*/ break;
1252 default:
28bf4b0b 1253 /*@-formatconst@*/
616915dd 1254 fprintf (stderr,
1255 top[1].op >= ' ' && top[1].op <= '~'
1256 ? "unimplemented operator '%c'\n"
1257 : "unimplemented operator '\\%03o'\n",
1258 top[1].op);
28bf4b0b 1259 /*@=formatconst@*/
616915dd 1260 }
1261 }
1262 if (op.op == 0)
1263 {
1264 long val;
1265
1266 if (top != stack)
1267 {
1268 cppReader_errorLit (pfile,
1269 cstring_makeLiteralTemp ("internal error in #if expression"));
1270 }
1271
1272 val = top->value;
1273
1274 if (stack != init_stack)
1275 {
1276 sfree (stack);
1277 /*@-branchstate@*/
1278 } /*@=branchstate@*/
1279
1280 return val;
1281 }
1282 top++;
1283
1284 /* Check for and handle stack overflow. */
1285 if (top == limit)
1286 {
1287 struct operation *new_stack;
1288 int old_size = (char *) limit - (char *) stack;
1289 size_t new_size = size_fromInt (2 * old_size);
1290
1291 if (stack != init_stack)
1292 {
1293 new_stack = (struct operation *) drealloc ((char *) stack,
1294 new_size);
1295 }
1296 else
1297 {
1298 new_stack = (struct operation *) dmalloc (new_size);
1299
1300 /* Bug: the parameters were in the wrong order! */
1301 memcpy ((char *) new_stack, (char *) stack, old_size);
1302 /*@-branchstate@*/
1303 } /*@=branchstate@*/
1304
1305 stack = new_stack;
1306 top = (struct operation *) ((char *) new_stack + old_size);
1307 limit = (struct operation *) ((char *) new_stack + new_size);
1308 /*@-branchstate@*/
1309 } /*@=branchstate@*/
1310
1311 top->flags = flags;
1312 top->rprio = rprio;
1313 top->op = op.op;
1314 if ((op.op == OROR && (top[-1].value != 0))
1315 || (op.op == ANDAND && (top[-1].value == 0))
1316 || (op.op == '?' && (top[-1].value == 0)))
1317 {
1318 skip_evaluation++;
1319 }
1320 else if (op.op == ':')
1321 {
1322 if (top[-2].value != 0) /* Was condition true? */
1323 {
1324 skip_evaluation++;
1325 }
1326 else
1327 {
1328 skip_evaluation--;
1329 }
1330 }
1331 else
1332 {
1333 ;
1334 }
1335 }
1336 syntax_error:
1337 /*@-usereleased@*/
1338 if (stack != init_stack)
1339 {
1340 sfree (stack);
1341 /*@-branchstate@*/
1342 } /*@=branchstate@*/
1343 /*@=usereleased@*/
1344
1345 cppReader_skipRestOfLine (pfile);
1346 return 0;
1347}
This page took 1.285705 seconds and 5 git commands to generate.