]> andersk Git - splint.git/blob - src/cppexp.c
Fixed /*@i@*/ warning in splintme
[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 "llbasic.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       /*@i23 add flags for all these...*/
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;
390   DPRINTF (("Parse number: %d", op.value));
391   return op;
392 }
393
394 struct token {
395   /*@null@*/ /*@observer@*/ char *operator;
396   int token;
397 };
398
399 static 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
415 struct operation cppexp_lex (cppReader *pfile)
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:
426   
427   old_written = size_toInt (cpplib_getWritten (pfile));
428   cppSkipHspace (pfile);
429   ic = cpplib_bufPeek (cppReader_getBufferSafe (pfile));
430
431   c = (char) ic;
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
440   DPRINTF (("Read: %c", c));
441
442   if (c == '\n')
443     {
444       op.op = 0;
445       return op;
446     }
447
448   token = cpplib_getTokenForceExpand (pfile);
449
450   tok_start = pfile->token_buffer + old_written;
451   tok_end = cpplib_getPWritten (pfile);
452
453   DPRINTF (("Token: %s < %s", tok_start, tok_end));
454
455   pfile->limit = tok_start;
456
457   switch (token)
458     {
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, 
477                           cstring_makeLiteralTemp ("string constants not allowed in #if expressions"));
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
496         
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           }
512         
513         ++ptr;
514          while (ptr < tok_end && ((c = *ptr++) != '\''))
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
545          token_buffer[num_chars] = 0;
546
547         if (c != '\'')
548           cppReader_errorLit (pfile,
549                               cstring_makeLiteralTemp ("malformatted character constant"));
550         else if (num_chars == 0)
551           cppReader_errorLit (pfile, 
552                               cstring_makeLiteralTemp ("empty character constant"));
553         else if (num_chars > max_chars)
554           {
555             num_chars = max_chars;
556             cppReader_errorLit (pfile, 
557                                 cstring_makeLiteralTemp ("character constant too long"));
558           }
559         else if (num_chars != 1 && ! cppReader_isTraditional (pfile))
560           {
561             cppReader_warningLit (pfile, 
562                                   cstring_makeLiteralTemp ("multi-character character constant"));
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
574             if ((cpphash_lookup ("__CHAR_UNSIGNED__",
575                              sizeof ("__CHAR_UNSIGNED__") - 1, -1) != NULL)
576                 || (((unsigned) result >> (int_toNonNegative (num_bits - 1))) & 1) == 0)
577               {
578                 op.value
579                   = result & ((unsigned long) ~0 
580                               >> int_toNonNegative ((HOST_BITS_PER_LONG - num_bits)));
581               }
582             else
583               {
584                 op.value
585                   = result | ~((unsigned long) ~0 
586                                >> int_toNonNegative ((HOST_BITS_PER_LONG - num_bits)));
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:
618       DPRINTF (("Name!"));
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             {
627              if (tok_start[0] == toktab->operator[0]  &&
628                  tok_start[1] == toktab->operator[1])
629                 {
630                   /*@loopbreak@*/ break;
631                 }
632             }
633
634           if (toktab->token == CPPREADER_ERRORTOK)
635             {
636               cppReader_error (pfile, 
637                                message ("`%s' not allowed in operand of `#if'",
638                                         cstring_fromChars (tok_start)));
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
669 int
670 cppReader_parseEscape (cppReader *pfile, char **string_ptr)
671 {
672    char c = *(*string_ptr)++;
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, 
685                        message ("non-standard escape sequence, `\\%c'", c));
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               {
726                 (*string_ptr)--;
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
773         if ((overflow | (i & ~((1 << int_toNonNegative (BITS_PER_UNIT)) - 1))) != 0)
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
787 static void
788 integer_overflow (cppReader *pfile)
789 {
790   if (cppReader_isPedantic (pfile))
791     cppReader_pedwarnLit (pfile, 
792                     cstring_makeLiteralTemp ("integer overflow in preprocessor expression"));
793 }
794
795 static long
796 left_shift (cppReader *pfile, long a, bool unsignedp, unsigned long b)
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     {
813       long l = int_toNonNegative (a) << b;
814
815 # ifdef WIN32
816 # pragma warning( disable : 4018 )
817 # endif
818
819       if (int_toNonNegative (l) >> b != a)
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 int_toNonNegative (a) >> b;
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
899 HOST_WIDE_INT
900 cppReader_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 */
928       op = cppexp_lex (pfile);
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, 
997                               cstring_makeLiteralTemp ("syntax error in #if"));
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@*/
1008           HOST_WIDE_INT v1 = top[-1].value;
1009           HOST_WIDE_INT v2 = top[0].value;
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, 
1019                                   cstring_makeLiteralTemp ("syntax error - missing left operand"));
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, 
1026                                   cstring_makeLiteralTemp ("syntax error - missing right operand"));
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, 
1098                                       cstring_makeLiteralTemp ("Division by zero in #if"));
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, 
1117                                       cstring_makeLiteralTemp ("Division by zero in #if"));
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, 
1142                                       cstring_makeLiteralTemp ("syntax error"));
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, 
1219                                   cstring_makeLiteralTemp ("syntax error in #if"));
1220               goto syntax_error;
1221             case ':':
1222               if (top[0].op != '?')
1223                 {
1224                   cppReader_errorLit (pfile,
1225                                       cstring_makeLiteralTemp ("syntax error ':' without preceding '?'"));
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, 
1233                                       cstring_makeLiteralTemp ("bad syntax for ?: operator"));
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, 
1255                                       cstring_makeLiteralTemp ("mismatched parentheses in #if"));
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:
1267               /*@-formatconst@*/
1268               fprintf (stderr,
1269                        top[1].op >= ' ' && top[1].op <= '~'
1270                        ? "unimplemented operator '%c'\n"
1271                        : "unimplemented operator '\\%03o'\n",
1272                        top[1].op);
1273               /*@=formatconst@*/
1274             }
1275         }
1276       if (op.op == 0)
1277         {
1278           long val;
1279
1280           if (top != stack)
1281             {
1282               cppReader_errorLit (pfile, 
1283                                   cstring_makeLiteralTemp ("internal error in #if expression"));
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;
1302           size_t old_size = size_fromInt ((char *) limit - (char *) stack);
1303           size_t new_size = (size_t) (2 * old_size);
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.141783 seconds and 5 git commands to generate.