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