]> andersk Git - splint.git/blame - src/cppexp.c
Fixed problem with assertion checking for negative shifts in
[splint.git] / src / cppexp.c
CommitLineData
616915dd 1/*
11db3170 2** Splint - annotation-assisted static program checker
c59f5181 3** Copyright (C) 1994-2003 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**
155af98d 20** For information on splint: info@splint.org
21** To report a bug: splint-bug@splint.org
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>
1b8ae690 59# include "splintMacros.nf"
b73d1009 60# include "basic.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 *);
c3be2604 156static long left_shift (cppReader *, long, bool p_unsignedp, unsigned long);
616915dd 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
86d93ed3 241cppReader_parseNumber (cppReader *pfile, char *start, int olen) /*@requires maxRead(start) >= (olen - 1) @*/
616915dd 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 {
8fd556fb 259 if (p[i] == '.') {
616915dd 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
8fd556fb 333 c = *p++;
616915dd 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 {
369 cppReader_pedwarnLit
370 (pfile,
371 cstring_makeLiteralTemp ("Integer constant out of range"));
372 }
373
374 /* If too big to be signed, consider it unsigned. */
375 if ((long) n < 0 && ! op.unsignedp)
376 {
377 if (base == 10)
378 {
379 cppReader_warningLit
380 (pfile,
381 cstring_makeLiteralTemp ("Integer constant is so large that it is unsigned"));
382 }
383
384 op.unsignedp = TRUE;
385 }
386
387 op.value = n;
388 op.op = CPPEXP_INT;
3e3ec469 389 DPRINTF (("Parse number: %d", op.value));
616915dd 390 return op;
391}
392
393struct token {
394 /*@null@*/ /*@observer@*/ char *operator;
395 int token;
396};
397
398static struct token tokentab2[] = {
399 { "&&", ANDAND },
400 { "||", OROR },
401 { "<<", LSH },
402 { ">>", RSH },
403 { "==", CPP_EQUALTOK },
404 { "!=", NOTEQUAL },
405 { "<=", LEQ },
406 { ">=", GEQ },
407 { "++", CPPREADER_ERRORTOK },
408 { "--", CPPREADER_ERRORTOK },
409 { NULL, CPPREADER_ERRORTOK }
410} ;
411
412/* Read one token. */
413
3e3ec469 414struct operation cppexp_lex (cppReader *pfile)
616915dd 415{
416 int ic;
417 char c;
418 register struct token *toktab;
419 enum cpp_token token;
420 struct operation op;
421 char *tok_start, *tok_end;
422 int old_written;
423
424 retry:
3e3ec469 425
426 old_written = size_toInt (cpplib_getWritten (pfile));
616915dd 427 cppSkipHspace (pfile);
3e3ec469 428 ic = cpplib_bufPeek (cppReader_getBufferSafe (pfile));
616915dd 429
430 c = (char) ic;
abd7f895 431
432 if (c == '#')
433 {
434 /* was: llassert (c != '#'); - Solaris uses this, attempt to continue anyway... */
435 cppReader_pedwarn (pfile,
436 message ("non-standard pre-processor directive: %c", c));
437 }
438
3e3ec469 439 DPRINTF (("Read: %c", c));
440
616915dd 441 if (c == '\n')
442 {
443 op.op = 0;
444 return op;
445 }
446
3e3ec469 447 token = cpplib_getTokenForceExpand (pfile);
448
616915dd 449 tok_start = pfile->token_buffer + old_written;
3e3ec469 450 tok_end = cpplib_getPWritten (pfile);
451
452 DPRINTF (("Token: %s < %s", tok_start, tok_end));
453
616915dd 454 pfile->limit = tok_start;
455
456 switch (token)
3e3ec469 457 {
616915dd 458 case CPP_EOF: /* Should not happen ... */
459 case CPP_VSPACE:
460 op.op = 0;
461 return op;
462 case CPP_POP:
463 if (cstring_isDefined (cppReader_getBufferSafe (pfile)->fname))
464 {
465 op.op = 0;
466 return op;
467 }
468 (void) cppReader_popBuffer (pfile);
469 goto retry;
470 case CPP_HSPACE: case CPP_COMMENT:
471 goto retry;
472 case CPP_NUMBER:
473 return cppReader_parseNumber (pfile, tok_start, tok_end - tok_start);
474 case CPP_STRING:
475 cppReader_errorLit (pfile,
3e3ec469 476 cstring_makeLiteralTemp ("string constants not allowed in #if expressions"));
616915dd 477 op.op = CPPREADER_ERRORTOK;
478 return op;
479 case CPP_CHAR:
480 /* This code for reading a character constant
481 handles multicharacter constants and wide characters.
482 It is mostly copied from c-lex.c. */
483 {
484 int result = 0;
485 int num_chars = 0;
486 size_t width = MAX_CHAR_TYPE_SIZE;
487 int wide_flag = 0;
488 int max_chars;
489 char *ptr = tok_start;
490#ifdef MULTIBYTE_CHARS
491 char token_buffer[MAX_LONG_TYPE_SIZE/MAX_CHAR_TYPE_SIZE + MB_CUR_MAX];
492#else
493 char token_buffer[MAX_LONG_TYPE_SIZE/MAX_CHAR_TYPE_SIZE + 1];
494#endif
3e3ec469 495
616915dd 496 if (*ptr == 'L')
497 {
498 ptr++;
499 wide_flag = 1;
500 width = MAX_WCHAR_TYPE_SIZE;
501#ifdef MULTIBYTE_CHARS
502 max_chars = MB_CUR_MAX;
503#else
504 max_chars = 1;
505#endif
506 }
507 else
508 {
509 max_chars = size_toInt (MAX_LONG_TYPE_SIZE / width);
510 }
3e3ec469 511
616915dd 512 ++ptr;
8fd556fb 513 while (ptr < tok_end && ((c = *ptr++) != '\''))
616915dd 514 {
515 if (c == '\\')
516 {
517 c = cppReader_parseEscape (pfile, &ptr);
518 if (width < HOST_BITS_PER_INT && c >= (1 << width))
519 {
520 cppReader_pedwarnLit
521 (pfile,
522 cstring_makeLiteralTemp ("Escape sequence out of range for character"));
523 }
524 }
525
526 num_chars++;
527
528 /* Merge character into result; ignore excess chars. */
529 if (num_chars < max_chars + 1)
530 {
531 if (width < HOST_BITS_PER_INT)
532 {
533 result = (int) ((unsigned) result << width) | (c & ((1 << width) - 1));
534 }
535 else
536 {
537 result = c;
538 }
539
540 token_buffer[num_chars - 1] = c;
541 }
542 }
543
8fd556fb 544 token_buffer[num_chars] = 0;
616915dd 545
546 if (c != '\'')
547 cppReader_errorLit (pfile,
80489f0a 548 cstring_makeLiteralTemp ("malformatted character constant"));
616915dd 549 else if (num_chars == 0)
550 cppReader_errorLit (pfile,
80489f0a 551 cstring_makeLiteralTemp ("empty character constant"));
616915dd 552 else if (num_chars > max_chars)
553 {
554 num_chars = max_chars;
555 cppReader_errorLit (pfile,
80489f0a 556 cstring_makeLiteralTemp ("character constant too long"));
616915dd 557 }
558 else if (num_chars != 1 && ! cppReader_isTraditional (pfile))
559 {
560 cppReader_warningLit (pfile,
80489f0a 561 cstring_makeLiteralTemp ("multi-character character constant"));
616915dd 562 }
563 else
564 {
565 ;
566 }
567
568 /* If char type is signed, sign-extend the constant. */
569 if (wide_flag == 0)
570 {
571 int num_bits = num_chars * width;
572
3e3ec469 573 if ((cpphash_lookup ("__CHAR_UNSIGNED__",
616915dd 574 sizeof ("__CHAR_UNSIGNED__") - 1, -1) != NULL)
a956d444 575 || (((unsigned) result >> (int_toNonNegative (num_bits - 1))) & 1) == 0)
616915dd 576 {
577 op.value
a956d444 578 = result & ((unsigned long) ~0
579 >> int_toNonNegative ((HOST_BITS_PER_LONG - num_bits)));
616915dd 580 }
581 else
582 {
583 op.value
a956d444 584 = result | ~((unsigned long) ~0
585 >> int_toNonNegative ((HOST_BITS_PER_LONG - num_bits)));
616915dd 586 }
587 }
588 else
589 {
590#ifdef MULTIBYTE_CHARS
591 /* Set the initial shift state and convert the next sequence. */
592 result = 0;
593 /* In all locales L'\0' is zero and mbtowc will return zero,
594 so don't use it. */
595 if (num_chars > 1
596 || (num_chars == 1 && token_buffer[0] != '\0'))
597 {
598 wchar_t wc;
599 (void) mbtowc (NULL, NULL, 0);
600 if (mbtowc (& wc, token_buffer, num_chars) == num_chars)
601 result = wc;
602 else
603 cppReader_pedwarn (pfile,"Ignoring invalid multibyte character");
604 }
605#endif
606 op.value = result;
607 }
608 }
609
610 /* This is always a signed type. */
611 op.unsignedp = FALSE;
612 op.op = CPPEXP_CHAR;
613
614 return op;
615
616 case CPP_NAME:
3e3ec469 617 DPRINTF (("Name!"));
616915dd 618 return cppReader_parseNumber (pfile, "0", 0);
619
620 case CPP_OTHER:
621 /* See if it is a special token of length 2. */
622 if (tok_start + 2 == tok_end)
623 {
624 for (toktab = tokentab2; toktab->operator != NULL; toktab++)
625 {
8fd556fb 626 if (tok_start[0] == toktab->operator[0] &&
627 tok_start[1] == toktab->operator[1])
616915dd 628 {
629 /*@loopbreak@*/ break;
630 }
631 }
632
633 if (toktab->token == CPPREADER_ERRORTOK)
634 {
80489f0a 635 cppReader_error (pfile,
636 message ("`%s' not allowed in operand of `#if'",
637 cstring_fromChars (tok_start)));
616915dd 638 }
639
640 op.op = toktab->token;
641 return op;
642 }
643 /*@fallthrough@*/
644 default:
645 op.op = *tok_start;
646 return op;
647 }
648
649 BADEXIT;
650 /*@notreached@*/
651}
652
653
654/* Parse a C escape sequence. STRING_PTR points to a variable
655 containing a pointer to the string to parse. That pointer
656 is updated past the characters we use. The value of the
657 escape sequence is returned.
658
659 A negative value means the sequence \ newline was seen,
660 which is supposed to be equivalent to nothing at all.
661
662 If \ is followed by a null character, we return a negative
663 value and leave the string pointer pointing at the null character.
664
665 If \ is followed by 000, we return 0 and leave the string pointer
666 after the zeros. A value of 0 does not mean end of string. */
667
668int
669cppReader_parseEscape (cppReader *pfile, char **string_ptr)
670{
8fd556fb 671 char c = *(*string_ptr)++;
616915dd 672
673 switch (c)
674 {
675 case 'a':
676 return TARGET_BELL;
677 case 'b':
678 return TARGET_BS;
679 case 'e':
680 case 'E':
681 if (cppReader_isPedantic (pfile))
682 {
683 cppReader_pedwarn (pfile,
155af98d 684 message ("non-standard escape sequence, `\\%c'", c));
616915dd 685 }
686 return (char) 033;
687 case 'f':
688 return TARGET_FF;
689 case 'n':
690 return TARGET_NEWLINE;
691 case 'r':
692 return TARGET_CR;
693 case 't':
694 return TARGET_TAB;
695 case 'v':
696 return TARGET_VT;
697 case '\n':
698 return -2;
699 case 0:
700 (*string_ptr)--;
701 return 0;
702
703 case '0':
704 case '1':
705 case '2':
706 case '3':
707 case '4':
708 case '5':
709 case '6':
710 case '7':
711 {
712 int i = (int) c - '0';
713 int count = 0;
714
715 while (++count < 3)
716 {
717 c = *(*string_ptr)++;
718 if (c >= '0' && c <= '7')
719 {
720 i = ((unsigned) i << 3) + c - '0';
721 }
722
723 else
724 {
8fd556fb 725 (*string_ptr)--;
616915dd 726 /*@loopbreak@*/ break;
727 }
728 }
729 if ((i & ~((1 << MAX_CHAR_TYPE_SIZE) - 1)) != 0)
730 {
731 i &= (1 << MAX_CHAR_TYPE_SIZE) - 1;
732 cppReader_pedwarnLit (pfile,
733 cstring_makeLiteralTemp ("octal character constant does not fit in a byte"));
734 }
735 return i;
736 }
737 case 'x':
738 {
739 register unsigned i = 0, overflow = 0, digits_found = 0, digit;
740 for (;;)
741 {
742 c = *(*string_ptr)++;
743
744 if (c >= '0' && c <= '9')
745 {
746 digit = (unsigned int) (c - '0');
747 }
748 else if (c >= 'a' && c <= 'f')
749 {
750 digit = (unsigned int) (c - 'a') + 10;
751 }
752 else if (c >= 'A' && c <= 'F')
753 {
754 digit = (unsigned int) (c - 'A') + 10;
755 }
756 else
757 {
758 (*string_ptr)--;
759 /*@loopbreak@*/ break;
760 }
761 overflow |= i ^ (i << 4 >> 4);
762 i = (i << 4) + digit;
763 digits_found = 1;
764 }
765
766 if (digits_found == 0)
767 {
768 cppReader_errorLit (pfile,
769 cstring_makeLiteralTemp ("\\x used with no following hex digits"));
770 }
771
a956d444 772 if ((overflow | (i & ~((1 << int_toNonNegative (BITS_PER_UNIT)) - 1))) != 0)
616915dd 773 {
774 i &= (1 << BITS_PER_UNIT) - 1;
775 cppReader_pedwarnLit (pfile,
776 cstring_makeLiteralTemp ("hex character constant does not fit in a byte"));
777 }
778
779 return i;
780 }
781 default:
782 return c;
783 }
784}
785
786static void
787integer_overflow (cppReader *pfile)
788{
789 if (cppReader_isPedantic (pfile))
790 cppReader_pedwarnLit (pfile,
791 cstring_makeLiteralTemp ("integer overflow in preprocessor expression"));
792}
793
794static long
c3be2604 795left_shift (cppReader *pfile, long a, bool unsignedp, unsigned long b)
616915dd 796{
797 if (b >= HOST_BITS_PER_LONG)
798 {
799 if (!unsignedp && a != 0)
800 {
801 integer_overflow (pfile);
802 }
803
804 return 0;
805 }
806 else if (unsignedp)
807 {
808 return (unsigned long) a << b;
809 }
810 else
811 {
b8dce3c7 812 /*@-shiftimplementation@*/
813 long l = a << b; /* int_toNonNegative removed (allow shifts of negative values) */
4dd72714 814
815# ifdef WIN32
816# pragma warning( disable : 4018 )
817# endif
818
b8dce3c7 819 if (l >> b != a) /* int_toNonNegative removed (allow shifts of negative values) */
616915dd 820 {
821 integer_overflow (pfile);
822 }
823
824 return l;
825 }
826}
827
828static long
829right_shift (long a, bool unsignedp, unsigned long b)
830{
831 if (b >= HOST_BITS_PER_LONG)
a956d444 832 return (unsignedp ? 0 : int_toNonNegative (a) >> (HOST_BITS_PER_LONG - 1));
616915dd 833 else if (unsignedp)
834 return (unsigned long) a >> b;
835 else
b8dce3c7 836 return a >> b; /* int_toNonNegative removed (allow shifts of negative values) */
837 /*@=shiftimplementation@*/
616915dd 838}
839
840/* These priorities are all even, so we can handle associatively. */
841
842/*@constant int PAREN_INNER_PRIO@*/
843#define PAREN_INNER_PRIO 0
844
845/*@constant int COMMA_PRIO@*/
846#define COMMA_PRIO 4
847
848/*@constant int COND_PRIO@*/
849#define COND_PRIO (COMMA_PRIO+2)
850
851/*@constant int OROR_PRIO@*/
852#define OROR_PRIO (COND_PRIO+2)
853
854/*@constant int ANDAND_PRIO@*/
855#define ANDAND_PRIO (OROR_PRIO+2)
856
857/*@constant int OR_PRIO@*/
858#define OR_PRIO (ANDAND_PRIO+2)
859
860/*@constant int XOR_PRIO@*/
861#define XOR_PRIO (OR_PRIO+2)
862
863/*@constant int AND_PRIO@*/
864#define AND_PRIO (XOR_PRIO+2)
865
866/*@constant int CPP_EQUAL_PRIO@*/
867#define CPP_EQUAL_PRIO (AND_PRIO+2)
868
869/*@constant int LESS_PRIO@*/
870#define LESS_PRIO (CPP_EQUAL_PRIO+2)
871
872/*@constant int SHIFT_PRIO@*/
873#define SHIFT_PRIO (LESS_PRIO+2)
874
875/*@constant int PLUS_PRIO@*/
876#define PLUS_PRIO (SHIFT_PRIO+2)
877
878/*@constant int MUL_PRIO@*/
879#define MUL_PRIO (PLUS_PRIO+2)
880
881/*@constant int UNARY_PRIO@*/
882#define UNARY_PRIO (MUL_PRIO+2)
883
884/*@constant int PAREN_OUTER_PRIO@*/
885#define PAREN_OUTER_PRIO (UNARY_PRIO+2)
886
887/*@notfunction@*/
888#define COMPARE(OP) \
889 top->unsignedp = FALSE;\
890 top->value = ((unsigned1 || unsigned2) \
891 ? (unsigned long) v1 OP (unsigned long) v2 \
892 : ((long) v1 OP (long) v2)) ? 1 : 0
893
894/* Parse and evaluate a C expression, reading from PFILE.
895 Returns the value of the expression. */
896
897/*@constant int INIT_STACK_SIZE@*/
898# define INIT_STACK_SIZE 20
899
900HOST_WIDE_INT
901cppReader_parseExpression (cppReader *pfile)
902{
903 /* The implementation is an operator precedence parser,
904 i.e. a bottom-up parser, using a stack for not-yet-reduced tokens.
905
906 The stack base is 'stack', and the current stack pointer is 'top'.
907 There is a stack element for each operator (only),
908 and the most recently pushed operator is 'top->op'.
909 An operand (value) is stored in the 'value' field of the stack
910 element of the operator that precedes it.
911 In that case the 'flags' field has the HAVE_VALUE flag set. */
912
913 struct operation init_stack[INIT_STACK_SIZE];
914 struct operation *stack = init_stack;
915 struct operation *limit = stack + INIT_STACK_SIZE;
916 register struct operation *top = stack;
917 int lprio, rprio = 0;
918 int skip_evaluation = 0;
919
920 top->rprio = 0;
921 top->flags = 0;
922
923 for (;;)
924 {
925 struct operation op;
926 int flags = 0;
927
928 /* Read a token */
3e3ec469 929 op = cppexp_lex (pfile);
616915dd 930
931 /* See if the token is an operand, in which case go to set_value.
932 If the token is an operator, figure out its left and right
933 priorities, and then goto maybe_reduce. */
934
935 switch (op.op)
936 {
937 case NAME:
938 top->value = 0, top->unsignedp = FALSE;
939 goto set_value;
940 case CPPEXP_INT:
941 case CPPEXP_CHAR:
942 top->value = op.value;
943 top->unsignedp = op.unsignedp;
944 goto set_value;
945 case 0:
946 lprio = 0; goto maybe_reduce;
947 case '+': case '-':
948 /* Is this correct if unary ? FIXME */
949 flags = RIGHT_OPERAND_REQUIRED;
950 lprio = PLUS_PRIO; rprio = lprio + 1; goto maybe_reduce;
951 case '!': case '~':
952 flags = RIGHT_OPERAND_REQUIRED;
953 rprio = UNARY_PRIO; lprio = rprio + 1; goto maybe_reduce;
954 case '*': case '/': case '%':
955 lprio = MUL_PRIO; goto binop;
956 case '<': case '>': case LEQ: case GEQ:
957 lprio = LESS_PRIO; goto binop;
958 case CPP_EQUALTOK: case NOTEQUAL:
959 lprio = CPP_EQUAL_PRIO; goto binop;
960 case LSH: case RSH:
961 lprio = SHIFT_PRIO; goto binop;
962 case '&': lprio = AND_PRIO; goto binop;
963 case '^': lprio = XOR_PRIO; goto binop;
964 case '|': lprio = OR_PRIO; goto binop;
965 case ANDAND: lprio = ANDAND_PRIO; goto binop;
966 case OROR: lprio = OROR_PRIO; goto binop;
967 case ',':
968 lprio = COMMA_PRIO; goto binop;
969 case '(':
970 lprio = PAREN_OUTER_PRIO; rprio = PAREN_INNER_PRIO;
971 goto maybe_reduce;
972 case ')':
973 lprio = PAREN_INNER_PRIO; rprio = PAREN_OUTER_PRIO;
974 goto maybe_reduce;
975 case ':':
976 lprio = COND_PRIO; rprio = COND_PRIO;
977 goto maybe_reduce;
978 case '?':
979 lprio = COND_PRIO + 1; rprio = COND_PRIO;
980 goto maybe_reduce;
981 binop:
982 flags = LEFT_OPERAND_REQUIRED | RIGHT_OPERAND_REQUIRED;
983 rprio = lprio + 1;
984 goto maybe_reduce;
985 default:
986 cppReader_error
987 (pfile,
988 message ("Invalid character in #if: %c",
989 (char) op.op));
990 goto syntax_error;
991 }
992
993 set_value:
994 /* Push a value onto the stack. */
995 if ((top->flags & HAVE_VALUE) != 0)
996 {
997 cppReader_errorLit (pfile,
80489f0a 998 cstring_makeLiteralTemp ("syntax error in #if"));
616915dd 999 goto syntax_error;
1000 }
1001 top->flags |= HAVE_VALUE;
1002 continue;
1003
1004 maybe_reduce:
1005 /* Push an operator, and check if we can reduce now. */
1006 while (top->rprio > lprio)
1007 {
1008 /*@-usedef@*/
2f2892c2 1009 HOST_WIDE_INT v1 = top[-1].value;
1010 HOST_WIDE_INT v2 = top[0].value;
616915dd 1011 bool unsigned1 = top[-1].unsignedp;
1012 bool unsigned2 = top[0].unsignedp;
1013
1014 top--;
1015
1016 if (((top[1].flags & LEFT_OPERAND_REQUIRED) != 0)
1017 && ((top[0].flags & HAVE_VALUE) == 0))
1018 {
1019 cppReader_errorLit (pfile,
80489f0a 1020 cstring_makeLiteralTemp ("syntax error - missing left operand"));
616915dd 1021 goto syntax_error;
1022 }
1023 if (((top[1].flags & RIGHT_OPERAND_REQUIRED) != 0)
1024 && ((top[1].flags & HAVE_VALUE) == 0))
1025 {
1026 cppReader_errorLit (pfile,
80489f0a 1027 cstring_makeLiteralTemp ("syntax error - missing right operand"));
616915dd 1028 goto syntax_error;
1029 }
1030 /* top[0].value = (top[1].op)(v1, v2);*/
1031 switch (top[1].op)
1032 {
1033 case '+':
1034 if ((top->flags & HAVE_VALUE) == 0)
1035 { /* Unary '+' */
1036 top->value = v2;
1037 top->unsignedp = unsigned2;
1038 top->flags |= HAVE_VALUE;
1039 }
1040 else
1041 {
1042 top->value = v1 + v2;
1043 top->unsignedp = unsigned1 || unsigned2;
1044 if (!top->unsignedp && (skip_evaluation == 0)
1045 && ! possibleSumSign (v1, v2, top->value))
1046 integer_overflow (pfile);
1047 }
1048 /*@switchbreak@*/ break;
1049 case '-':
1050 if ((top->flags & HAVE_VALUE) == 0)
1051 { /* Unary '-' */
1052 top->value = - v2;
1053 if ((skip_evaluation == 0)
1054 && (top->value & v2) < 0 && !unsigned2)
1055 integer_overflow (pfile);
1056 top->unsignedp = unsigned2;
1057 top->flags |= HAVE_VALUE;
1058 }
1059 else
1060 { /* Binary '-' */
1061 top->value = v1 - v2;
1062 top->unsignedp = unsigned1 || unsigned2;
1063 if (!top->unsignedp && (skip_evaluation == 0)
1064 && !possibleSumSign (top->value, v2, v1))
1065 {
1066 integer_overflow (pfile);
1067 }
1068 }
1069 /*@switchbreak@*/ break;
1070 case '*':
1071 top->unsignedp = unsigned1 || unsigned2;
1072
1073 if (top->unsignedp)
1074 {
1075 top->value = (unsigned long) v1 * v2;
1076 }
1077 else if (skip_evaluation == 0)
1078 {
1079 top->value = v1 * v2;
1080 if ((v1 != 0)
1081 && (top->value / v1 != v2
1082 || (top->value & v1 & v2) < 0))
1083 {
1084 integer_overflow (pfile);
1085 }
1086 }
1087 else
1088 {
1089 ;
1090 }
1091
1092 /*@switchbreak@*/ break;
1093 case '/':
1094 if (skip_evaluation != 0)
1095 /*@switchbreak@*/ break;
1096 if (v2 == 0)
1097 {
1098 cppReader_errorLit (pfile,
80489f0a 1099 cstring_makeLiteralTemp ("Division by zero in #if"));
616915dd 1100 v2 = 1;
1101 }
1102 top->unsignedp = unsigned1 || unsigned2;
1103 if (top->unsignedp)
1104 top->value = (unsigned long) v1 / v2;
1105 else
1106 {
1107 top->value = v1 / v2;
1108 if ((top->value & v1 & v2) < 0)
1109 integer_overflow (pfile);
1110 }
1111 /*@switchbreak@*/ break;
1112 case '%':
1113 if (skip_evaluation != 0)
1114 /*@switchbreak@*/ break;
1115 if (v2 == 0)
1116 {
1117 cppReader_errorLit (pfile,
80489f0a 1118 cstring_makeLiteralTemp ("Division by zero in #if"));
616915dd 1119 v2 = 1;
1120 }
1121 top->unsignedp = unsigned1 || unsigned2;
1122 if (top->unsignedp)
1123 top->value = (unsigned long) v1 % v2;
1124 else
1125 top->value = v1 % v2;
1126 /*@switchbreak@*/ break;
1127 case '!':
1128 if ((top->flags & HAVE_VALUE) != 0)
1129 {
1130 cppReader_errorLit (pfile,
1131 cstring_makeLiteralTemp ("Syntax error"));
1132 goto syntax_error;
1133 }
1134
1135 top->value = (v2 == 0) ? 1 : 0;
1136 top->unsignedp = FALSE;
1137 top->flags |= HAVE_VALUE;
1138 /*@switchbreak@*/ break;
1139 case '~':
1140 if ((top->flags & HAVE_VALUE) != 0)
1141 {
1142 cppReader_errorLit (pfile,
80489f0a 1143 cstring_makeLiteralTemp ("syntax error"));
616915dd 1144 goto syntax_error;
1145 }
1146 top->value = ~ v2;
1147 top->unsignedp = unsigned2;
1148 top->flags |= HAVE_VALUE;
1149 /*@switchbreak@*/ break;
1150 case '<': COMPARE(<); /*@switchbreak@*/ break;
1151 case '>': COMPARE(>); /*@switchbreak@*/ break;
1152 case LEQ: COMPARE(<=); /*@switchbreak@*/ break;
1153 case GEQ: COMPARE(>=); /*@switchbreak@*/ break;
1154 case CPP_EQUALTOK:
1155 top->value = (v1 == v2) ? 1 : 0;
1156 top->unsignedp = FALSE;
1157 /*@switchbreak@*/ break;
1158 case NOTEQUAL:
1159 top->value = (v1 != v2) ? 1 : 0;
1160 top->unsignedp = FALSE;
1161 /*@switchbreak@*/ break;
1162 case LSH:
1163 if (skip_evaluation != 0)
1164 {
1165 /*@switchbreak@*/ break;
1166 }
1167
1168 top->unsignedp = unsigned1;
1169 if (v2 < 0 && ! unsigned2)
1170 top->value = right_shift (v1, unsigned1, -v2);
1171 else
1172 top->value = left_shift (pfile, v1, unsigned1, v2);
1173 /*@switchbreak@*/ break;
1174 case RSH:
1175 if (skip_evaluation != 0)
1176 {
1177 /*@switchbreak@*/ break;
1178 }
1179 top->unsignedp = unsigned1;
1180 if (v2 < 0 && ! unsigned2)
1181 top->value = left_shift (pfile, v1, unsigned1, -v2);
1182 else
1183 top->value = right_shift (v1, unsigned1, v2);
1184 /*@switchbreak@*/ break;
1185
1186/*@notfunction@*/
1187#define LOGICAL(OP) \
1188 top->value = v1 OP v2;\
1189 top->unsignedp = unsigned1 || unsigned2;
1190
1191 case '&': LOGICAL(&); /*@switchbreak@*/ break;
1192 case '^': LOGICAL(^); /*@switchbreak@*/ break;
1193 case '|': LOGICAL(|); /*@switchbreak@*/ break;
1194 case ANDAND:
1195 top->value = ((v1 != 0) && (v2 != 0)) ? 1 : 0;
1196 top->unsignedp = FALSE;
1197
1198 if (v1 == 0)
1199 {
1200 skip_evaluation--;
1201 }
1202 /*@switchbreak@*/ break;
1203 case OROR:
1204 top->value = ((v1 != 0) || (v2 != 0)) ? 1 : 0;
1205 top->unsignedp = FALSE;
1206 if (v1 != 0)
1207 {
1208 skip_evaluation--;
1209 }
1210 /*@switchbreak@*/ break;
1211 case ',':
1212 if (cppReader_isPedantic (pfile))
1213 cppReader_pedwarnLit (pfile,
1214 cstring_makeLiteralTemp ("comma operator in operand of `#if'"));
1215 top->value = v2;
1216 top->unsignedp = unsigned2;
1217 /*@switchbreak@*/ break;
1218 case '(': case '?':
1219 cppReader_errorLit (pfile,
80489f0a 1220 cstring_makeLiteralTemp ("syntax error in #if"));
616915dd 1221 goto syntax_error;
1222 case ':':
1223 if (top[0].op != '?')
1224 {
1225 cppReader_errorLit (pfile,
80489f0a 1226 cstring_makeLiteralTemp ("syntax error ':' without preceding '?'"));
616915dd 1227 goto syntax_error;
1228 }
1229 else if (((top[1].flags & HAVE_VALUE) == 0)
1230 || ((top[-1].flags & HAVE_VALUE) == 0)
1231 || ((top[0].flags & HAVE_VALUE) == 0))
1232 {
1233 cppReader_errorLit (pfile,
80489f0a 1234 cstring_makeLiteralTemp ("bad syntax for ?: operator"));
616915dd 1235 goto syntax_error;
1236 }
1237 else
1238 {
1239 top--;
1240 if (top->value != 0)
1241 {
1242 skip_evaluation--;
1243 }
1244
1245 top->value = (top->value != 0) ? v1 : v2;
1246 top->unsignedp = unsigned1 || unsigned2;
1247 }
1248 /*@switchbreak@*/ break;
1249 case ')':
1250 if (((top[1].flags & HAVE_VALUE) != 0)
1251 || ((top[0].flags & HAVE_VALUE) == 0)
1252 || top[0].op != '('
1253 || ((top[-1].flags & HAVE_VALUE) != 0))
1254 {
1255 cppReader_errorLit (pfile,
80489f0a 1256 cstring_makeLiteralTemp ("mismatched parentheses in #if"));
616915dd 1257 goto syntax_error;
1258 }
1259 else
1260 {
1261 top--;
1262 top->value = v1;
1263 top->unsignedp = unsigned1;
1264 top->flags |= HAVE_VALUE;
1265 }
1266 /*@switchbreak@*/ break;
1267 default:
28bf4b0b 1268 /*@-formatconst@*/
616915dd 1269 fprintf (stderr,
1270 top[1].op >= ' ' && top[1].op <= '~'
1271 ? "unimplemented operator '%c'\n"
1272 : "unimplemented operator '\\%03o'\n",
1273 top[1].op);
28bf4b0b 1274 /*@=formatconst@*/
616915dd 1275 }
1276 }
1277 if (op.op == 0)
1278 {
1279 long val;
1280
1281 if (top != stack)
1282 {
1283 cppReader_errorLit (pfile,
80489f0a 1284 cstring_makeLiteralTemp ("internal error in #if expression"));
616915dd 1285 }
1286
1287 val = top->value;
1288
1289 if (stack != init_stack)
1290 {
1291 sfree (stack);
1292 /*@-branchstate@*/
1293 } /*@=branchstate@*/
1294
1295 return val;
1296 }
1297 top++;
1298
1299 /* Check for and handle stack overflow. */
1300 if (top == limit)
1301 {
1302 struct operation *new_stack;
2f2892c2 1303 size_t old_size = size_fromInt ((char *) limit - (char *) stack);
53306cab 1304 size_t new_size = (size_t) (2 * old_size);
616915dd 1305
1306 if (stack != init_stack)
1307 {
1308 new_stack = (struct operation *) drealloc ((char *) stack,
1309 new_size);
1310 }
1311 else
1312 {
1313 new_stack = (struct operation *) dmalloc (new_size);
1314
1315 /* Bug: the parameters were in the wrong order! */
1316 memcpy ((char *) new_stack, (char *) stack, old_size);
1317 /*@-branchstate@*/
1318 } /*@=branchstate@*/
1319
1320 stack = new_stack;
1321 top = (struct operation *) ((char *) new_stack + old_size);
1322 limit = (struct operation *) ((char *) new_stack + new_size);
1323 /*@-branchstate@*/
1324 } /*@=branchstate@*/
1325
1326 top->flags = flags;
1327 top->rprio = rprio;
1328 top->op = op.op;
1329 if ((op.op == OROR && (top[-1].value != 0))
1330 || (op.op == ANDAND && (top[-1].value == 0))
1331 || (op.op == '?' && (top[-1].value == 0)))
1332 {
1333 skip_evaluation++;
1334 }
1335 else if (op.op == ':')
1336 {
1337 if (top[-2].value != 0) /* Was condition true? */
1338 {
1339 skip_evaluation++;
1340 }
1341 else
1342 {
1343 skip_evaluation--;
1344 }
1345 }
1346 else
1347 {
1348 ;
1349 }
1350 }
1351 syntax_error:
1352 /*@-usereleased@*/
1353 if (stack != init_stack)
1354 {
1355 sfree (stack);
1356 /*@-branchstate@*/
1357 } /*@=branchstate@*/
1358 /*@=usereleased@*/
1359
1360 cppReader_skipRestOfLine (pfile);
1361 return 0;
1362}
This page took 0.302215 seconds and 5 git commands to generate.