]> andersk Git - splint.git/blob - src/cppexp.c
Fixed problem with assertion checking for negative shifts in
[splint.git] / src / cppexp.c
1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
4 **         Massachusetts Institute of Technology
5 **
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
10 ** 
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 ** General Public License for more details.
15 ** 
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
19 **
20 ** For information on splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
23 */
24 /*
25 ** cppexp.c
26 */
27 /* Parse C expressions for CCCP.
28    Copyright (C) 1987, 1992, 1994, 1995, 1997 Free Software Foundation.
29
30 This program is free software; you can redistribute it and/or modify it
31 under the terms of the GNU General Public License as published by the
32 Free Software Foundation; either version 2, or (at your option) any
33 later version.
34
35 This program is distributed in the hope that it will be useful,
36 but WITHOUT ANY WARRANTY; without even the implied warranty of
37 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
38 GNU General Public License for more details.
39
40 You should have received a copy of the GNU General Public License
41 along with this program; if not, write to the Free Software
42 Foundation, 59 Temple Place - Suite 330,
43 Boston, MA 02111-1307, USA.
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
49 Written by Per Bothner 1994.  */
50
51 /* Parse a C expression from text in a string  */
52
53 /*@+charint@*/
54 /*@+ignorequals@*/
55 /*@+ignoresigns@*/
56 /*@+matchanyintegral@*/
57
58 # include <string.h> 
59 # include "splintMacros.nf"
60 # include "basic.h"
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
76 /*@constant int BITS_PER_UNIT = 8@*/
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
88 /*@constant size_t HOST_BITS_PER_LONG = 32@*/
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
154 static struct operation cppexp_lex (cppReader *);
155 static void integer_overflow (cppReader *);
156 static long left_shift (cppReader *, long, bool p_unsignedp, unsigned long);
157 static 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
220 struct 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
240 struct operation
241 cppReader_parseNumber (cppReader *pfile, char *start, int olen) /*@requires maxRead(start) >= (olen - 1) @*/
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     {
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;
389   DPRINTF (("Parse number: %d", op.value));
390   return op;
391 }
392
393 struct token {
394   /*@null@*/ /*@observer@*/ char *operator;
395   int token;
396 };
397
398 static 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
414 struct operation cppexp_lex (cppReader *pfile)
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:
425   
426   old_written = size_toInt (cpplib_getWritten (pfile));
427   cppSkipHspace (pfile);
428   ic = cpplib_bufPeek (cppReader_getBufferSafe (pfile));
429
430   c = (char) ic;
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
439   DPRINTF (("Read: %c", c));
440
441   if (c == '\n')
442     {
443       op.op = 0;
444       return op;
445     }
446
447   token = cpplib_getTokenForceExpand (pfile);
448
449   tok_start = pfile->token_buffer + old_written;
450   tok_end = cpplib_getPWritten (pfile);
451
452   DPRINTF (("Token: %s < %s", tok_start, tok_end));
453
454   pfile->limit = tok_start;
455
456   switch (token)
457     {
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, 
476                           cstring_makeLiteralTemp ("string constants not allowed in #if expressions"));
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
495         
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           }
511         
512         ++ptr;
513          while (ptr < tok_end && ((c = *ptr++) != '\''))
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
544          token_buffer[num_chars] = 0;
545
546         if (c != '\'')
547           cppReader_errorLit (pfile,
548                               cstring_makeLiteralTemp ("malformatted character constant"));
549         else if (num_chars == 0)
550           cppReader_errorLit (pfile, 
551                               cstring_makeLiteralTemp ("empty character constant"));
552         else if (num_chars > max_chars)
553           {
554             num_chars = max_chars;
555             cppReader_errorLit (pfile, 
556                                 cstring_makeLiteralTemp ("character constant too long"));
557           }
558         else if (num_chars != 1 && ! cppReader_isTraditional (pfile))
559           {
560             cppReader_warningLit (pfile, 
561                                   cstring_makeLiteralTemp ("multi-character character constant"));
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
573             if ((cpphash_lookup ("__CHAR_UNSIGNED__",
574                              sizeof ("__CHAR_UNSIGNED__") - 1, -1) != NULL)
575                 || (((unsigned) result >> (int_toNonNegative (num_bits - 1))) & 1) == 0)
576               {
577                 op.value
578                   = result & ((unsigned long) ~0 
579                               >> int_toNonNegative ((HOST_BITS_PER_LONG - num_bits)));
580               }
581             else
582               {
583                 op.value
584                   = result | ~((unsigned long) ~0 
585                                >> int_toNonNegative ((HOST_BITS_PER_LONG - num_bits)));
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:
617       DPRINTF (("Name!"));
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             {
626              if (tok_start[0] == toktab->operator[0]  &&
627                  tok_start[1] == toktab->operator[1])
628                 {
629                   /*@loopbreak@*/ break;
630                 }
631             }
632
633           if (toktab->token == CPPREADER_ERRORTOK)
634             {
635               cppReader_error (pfile, 
636                                message ("`%s' not allowed in operand of `#if'",
637                                         cstring_fromChars (tok_start)));
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
668 int
669 cppReader_parseEscape (cppReader *pfile, char **string_ptr)
670 {
671    char c = *(*string_ptr)++;
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, 
684                        message ("non-standard escape sequence, `\\%c'", c));
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               {
725                 (*string_ptr)--;
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
772         if ((overflow | (i & ~((1 << int_toNonNegative (BITS_PER_UNIT)) - 1))) != 0)
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
786 static void
787 integer_overflow (cppReader *pfile)
788 {
789   if (cppReader_isPedantic (pfile))
790     cppReader_pedwarnLit (pfile, 
791                     cstring_makeLiteralTemp ("integer overflow in preprocessor expression"));
792 }
793
794 static long
795 left_shift (cppReader *pfile, long a, bool unsignedp, unsigned long b)
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     {
812       /*@-shiftimplementation@*/
813       long l = a << b; /* int_toNonNegative removed (allow shifts of negative values) */ 
814
815 # ifdef WIN32
816 # pragma warning( disable : 4018 )
817 # endif
818
819       if (l >> b != a) /* int_toNonNegative removed (allow shifts of negative values) */ 
820         {
821           integer_overflow (pfile);
822         }
823
824       return l;
825     }
826 }
827
828 static long
829 right_shift (long a, bool unsignedp, unsigned long b)
830 {
831   if (b >= HOST_BITS_PER_LONG)
832     return (unsignedp ? 0 : int_toNonNegative (a) >> (HOST_BITS_PER_LONG - 1));
833   else if (unsignedp)
834     return (unsigned long) a >> b;
835   else
836     return a >> b; /* int_toNonNegative removed (allow shifts of negative values) */ 
837   /*@=shiftimplementation@*/
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
900 HOST_WIDE_INT
901 cppReader_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 */
929       op = cppexp_lex (pfile);
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, 
998                               cstring_makeLiteralTemp ("syntax error in #if"));
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@*/
1009           HOST_WIDE_INT v1 = top[-1].value;
1010           HOST_WIDE_INT v2 = top[0].value;
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, 
1020                                   cstring_makeLiteralTemp ("syntax error - missing left operand"));
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, 
1027                                   cstring_makeLiteralTemp ("syntax error - missing right operand"));
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, 
1099                                       cstring_makeLiteralTemp ("Division by zero in #if"));
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, 
1118                                       cstring_makeLiteralTemp ("Division by zero in #if"));
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, 
1143                                       cstring_makeLiteralTemp ("syntax error"));
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, 
1220                                   cstring_makeLiteralTemp ("syntax error in #if"));
1221               goto syntax_error;
1222             case ':':
1223               if (top[0].op != '?')
1224                 {
1225                   cppReader_errorLit (pfile,
1226                                       cstring_makeLiteralTemp ("syntax error ':' without preceding '?'"));
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, 
1234                                       cstring_makeLiteralTemp ("bad syntax for ?: operator"));
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, 
1256                                       cstring_makeLiteralTemp ("mismatched parentheses in #if"));
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:
1268               /*@-formatconst@*/
1269               fprintf (stderr,
1270                        top[1].op >= ' ' && top[1].op <= '~'
1271                        ? "unimplemented operator '%c'\n"
1272                        : "unimplemented operator '\\%03o'\n",
1273                        top[1].op);
1274               /*@=formatconst@*/
1275             }
1276         }
1277       if (op.op == 0)
1278         {
1279           long val;
1280
1281           if (top != stack)
1282             {
1283               cppReader_errorLit (pfile, 
1284                                   cstring_makeLiteralTemp ("internal error in #if expression"));
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;
1303           size_t old_size = size_fromInt ((char *) limit - (char *) stack);
1304           size_t new_size = (size_t) (2 * old_size);
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.146023 seconds and 5 git commands to generate.