]> andersk Git - splint.git/blob - src/cppexp.c
60f16b015340d9a2c167b41b2b7cd68ee65c1371
[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       long l = int_toNonNegative (a) << b;
813
814 # ifdef WIN32
815 # pragma warning( disable : 4018 )
816 # endif
817
818       if (int_toNonNegative (l) >> b != a)
819         {
820           integer_overflow (pfile);
821         }
822
823       return l;
824     }
825 }
826
827 static long
828 right_shift (long a, bool unsignedp, unsigned long b)
829 {
830   if (b >= HOST_BITS_PER_LONG)
831     return (unsignedp ? 0 : int_toNonNegative (a) >> (HOST_BITS_PER_LONG - 1));
832   else if (unsignedp)
833     return (unsigned long) a >> b;
834   else
835     return int_toNonNegative (a) >> b;
836 }
837
838 /* These priorities are all even, so we can handle associatively.  */
839
840 /*@constant int PAREN_INNER_PRIO@*/
841 #define PAREN_INNER_PRIO 0
842
843 /*@constant int COMMA_PRIO@*/
844 #define COMMA_PRIO 4
845
846 /*@constant int COND_PRIO@*/
847 #define COND_PRIO (COMMA_PRIO+2)
848
849 /*@constant int OROR_PRIO@*/
850 #define OROR_PRIO (COND_PRIO+2)
851
852 /*@constant int ANDAND_PRIO@*/
853 #define ANDAND_PRIO (OROR_PRIO+2)
854
855 /*@constant int OR_PRIO@*/
856 #define OR_PRIO (ANDAND_PRIO+2)
857
858 /*@constant int XOR_PRIO@*/
859 #define XOR_PRIO (OR_PRIO+2)
860
861 /*@constant int AND_PRIO@*/
862 #define AND_PRIO (XOR_PRIO+2)
863
864 /*@constant int CPP_EQUAL_PRIO@*/
865 #define CPP_EQUAL_PRIO (AND_PRIO+2)
866
867 /*@constant int LESS_PRIO@*/
868 #define LESS_PRIO (CPP_EQUAL_PRIO+2)
869
870 /*@constant int SHIFT_PRIO@*/
871 #define SHIFT_PRIO (LESS_PRIO+2)
872
873 /*@constant int PLUS_PRIO@*/
874 #define PLUS_PRIO (SHIFT_PRIO+2)
875
876 /*@constant int MUL_PRIO@*/
877 #define MUL_PRIO (PLUS_PRIO+2)
878
879 /*@constant int UNARY_PRIO@*/
880 #define UNARY_PRIO (MUL_PRIO+2)
881
882 /*@constant int PAREN_OUTER_PRIO@*/
883 #define PAREN_OUTER_PRIO (UNARY_PRIO+2)
884
885 /*@notfunction@*/
886 #define COMPARE(OP) \
887   top->unsignedp = FALSE;\
888   top->value = ((unsigned1 || unsigned2) \
889                  ? (unsigned long) v1 OP (unsigned long) v2 \
890                  : ((long) v1 OP (long) v2)) ? 1 : 0
891
892 /* Parse and evaluate a C expression, reading from PFILE.
893    Returns the value of the expression.  */
894
895 /*@constant int INIT_STACK_SIZE@*/
896 # define INIT_STACK_SIZE 20
897
898 HOST_WIDE_INT
899 cppReader_parseExpression (cppReader *pfile)
900 {
901   /* The implementation is an operator precedence parser,
902      i.e. a bottom-up parser, using a stack for not-yet-reduced tokens.
903
904      The stack base is 'stack', and the current stack pointer is 'top'.
905      There is a stack element for each operator (only),
906      and the most recently pushed operator is 'top->op'.
907      An operand (value) is stored in the 'value' field of the stack
908      element of the operator that precedes it.
909      In that case the 'flags' field has the HAVE_VALUE flag set.  */
910
911   struct operation init_stack[INIT_STACK_SIZE];
912   struct operation *stack = init_stack;
913   struct operation *limit = stack + INIT_STACK_SIZE;
914   register struct operation *top = stack;
915   int lprio, rprio = 0;
916   int skip_evaluation = 0;
917
918   top->rprio = 0;
919   top->flags = 0;
920
921   for (;;)
922     {
923       struct operation op;
924       int flags = 0;
925
926       /* Read a token */
927       op = cppexp_lex (pfile);
928
929       /* See if the token is an operand, in which case go to set_value.
930          If the token is an operator, figure out its left and right
931          priorities, and then goto maybe_reduce.  */
932
933       switch (op.op)
934         {
935         case NAME:
936           top->value = 0, top->unsignedp = FALSE;
937           goto set_value;
938         case CPPEXP_INT:
939         case CPPEXP_CHAR:
940           top->value = op.value;
941           top->unsignedp = op.unsignedp;
942           goto set_value;
943         case 0:
944           lprio = 0;  goto maybe_reduce;
945         case '+':  case '-':
946           /* Is this correct if unary ? FIXME */
947           flags = RIGHT_OPERAND_REQUIRED;
948           lprio = PLUS_PRIO;  rprio = lprio + 1;  goto maybe_reduce;
949         case '!':  case '~':
950           flags = RIGHT_OPERAND_REQUIRED;
951           rprio = UNARY_PRIO;  lprio = rprio + 1;  goto maybe_reduce;
952         case '*':  case '/':  case '%':
953           lprio = MUL_PRIO;  goto binop;
954         case '<':  case '>':  case LEQ:  case GEQ:
955           lprio = LESS_PRIO;  goto binop;
956         case CPP_EQUALTOK:  case NOTEQUAL:
957           lprio = CPP_EQUAL_PRIO;  goto binop;
958         case LSH:  case RSH:
959           lprio = SHIFT_PRIO;  goto binop;
960         case '&':  lprio = AND_PRIO;  goto binop;
961         case '^':  lprio = XOR_PRIO;  goto binop;
962         case '|':  lprio = OR_PRIO;  goto binop;
963         case ANDAND:  lprio = ANDAND_PRIO;  goto binop;
964         case OROR:  lprio = OROR_PRIO;  goto binop;
965         case ',':
966           lprio = COMMA_PRIO;  goto binop;
967         case '(':
968           lprio = PAREN_OUTER_PRIO;  rprio = PAREN_INNER_PRIO;
969           goto maybe_reduce;
970         case ')':
971           lprio = PAREN_INNER_PRIO;  rprio = PAREN_OUTER_PRIO;
972           goto maybe_reduce;
973         case ':':
974           lprio = COND_PRIO;  rprio = COND_PRIO;
975           goto maybe_reduce;
976         case '?':
977           lprio = COND_PRIO + 1;  rprio = COND_PRIO;
978           goto maybe_reduce;
979         binop:
980           flags = LEFT_OPERAND_REQUIRED | RIGHT_OPERAND_REQUIRED;
981           rprio = lprio + 1;
982           goto maybe_reduce;
983         default:
984           cppReader_error 
985             (pfile, 
986              message ("Invalid character in #if: %c", 
987                       (char) op.op));
988           goto syntax_error;
989         }
990
991     set_value:
992       /* Push a value onto the stack.  */
993       if ((top->flags & HAVE_VALUE) != 0)
994         {
995           cppReader_errorLit (pfile, 
996                               cstring_makeLiteralTemp ("syntax error in #if"));
997           goto syntax_error;
998         }
999       top->flags |= HAVE_VALUE;
1000       continue;
1001
1002     maybe_reduce:
1003       /* Push an operator, and check if we can reduce now.  */
1004       while (top->rprio > lprio)
1005         {
1006           /*@-usedef@*/
1007           HOST_WIDE_INT v1 = top[-1].value;
1008           HOST_WIDE_INT v2 = top[0].value;
1009           bool unsigned1 = top[-1].unsignedp;
1010           bool unsigned2 = top[0].unsignedp;
1011
1012           top--;
1013
1014           if (((top[1].flags & LEFT_OPERAND_REQUIRED) != 0)
1015               && ((top[0].flags & HAVE_VALUE) == 0))
1016             {
1017               cppReader_errorLit (pfile, 
1018                                   cstring_makeLiteralTemp ("syntax error - missing left operand"));
1019               goto syntax_error;
1020             }
1021           if (((top[1].flags & RIGHT_OPERAND_REQUIRED) != 0)
1022               && ((top[1].flags & HAVE_VALUE) == 0))
1023             {
1024               cppReader_errorLit (pfile, 
1025                                   cstring_makeLiteralTemp ("syntax error - missing right operand"));
1026               goto syntax_error;
1027             }
1028           /* top[0].value = (top[1].op)(v1, v2);*/
1029           switch (top[1].op)
1030             {
1031             case '+':
1032               if ((top->flags & HAVE_VALUE) == 0)
1033                 { /* Unary '+' */
1034                   top->value = v2;
1035                   top->unsignedp = unsigned2;
1036                   top->flags |= HAVE_VALUE;
1037                 }
1038               else
1039                 {
1040                   top->value = v1 + v2;
1041                   top->unsignedp = unsigned1 || unsigned2;
1042                   if (!top->unsignedp && (skip_evaluation == 0)
1043                       && ! possibleSumSign (v1, v2, top->value))
1044                     integer_overflow (pfile);
1045                 }
1046               /*@switchbreak@*/ break;
1047             case '-':
1048               if ((top->flags & HAVE_VALUE) == 0)
1049                 { /* Unary '-' */
1050                   top->value = - v2;
1051                   if ((skip_evaluation == 0) 
1052                       && (top->value & v2) < 0 && !unsigned2)
1053                     integer_overflow (pfile);
1054                   top->unsignedp = unsigned2;
1055                   top->flags |= HAVE_VALUE;
1056                 }
1057               else
1058                 { /* Binary '-' */
1059                   top->value = v1 - v2;
1060                   top->unsignedp = unsigned1 || unsigned2;
1061                   if (!top->unsignedp && (skip_evaluation == 0)
1062                       && !possibleSumSign (top->value, v2, v1))
1063                     {
1064                       integer_overflow (pfile);
1065                     }
1066                 }
1067               /*@switchbreak@*/ break;
1068             case '*':
1069               top->unsignedp = unsigned1 || unsigned2;
1070
1071               if (top->unsignedp)
1072                 {
1073                   top->value = (unsigned long) v1 * v2;
1074                 }
1075               else if (skip_evaluation == 0)
1076                 {
1077                   top->value = v1 * v2;
1078                   if ((v1 != 0)
1079                       && (top->value / v1 != v2
1080                           || (top->value & v1 & v2) < 0))
1081                     {
1082                       integer_overflow (pfile);
1083                     }
1084                 }
1085               else
1086                 {
1087                   ;
1088                 }
1089
1090               /*@switchbreak@*/ break;
1091             case '/':
1092               if (skip_evaluation != 0)
1093                 /*@switchbreak@*/ break;
1094               if (v2 == 0)
1095                 {
1096                   cppReader_errorLit (pfile, 
1097                                       cstring_makeLiteralTemp ("Division by zero in #if"));
1098                   v2 = 1;
1099                 }
1100               top->unsignedp = unsigned1 || unsigned2;
1101               if (top->unsignedp)
1102                 top->value = (unsigned long) v1 / v2;
1103               else
1104                 {
1105                   top->value = v1 / v2;
1106                   if ((top->value & v1 & v2) < 0)
1107                     integer_overflow (pfile);
1108                 }
1109               /*@switchbreak@*/ break;
1110             case '%':
1111               if (skip_evaluation != 0)
1112                 /*@switchbreak@*/ break;
1113               if (v2 == 0)
1114                 {
1115                   cppReader_errorLit (pfile, 
1116                                       cstring_makeLiteralTemp ("Division by zero in #if"));
1117                   v2 = 1;
1118                 }
1119               top->unsignedp = unsigned1 || unsigned2;
1120               if (top->unsignedp)
1121                 top->value = (unsigned long) v1 % v2;
1122               else
1123                 top->value = v1 % v2;
1124               /*@switchbreak@*/ break;
1125             case '!':
1126               if ((top->flags & HAVE_VALUE) != 0)
1127                 {
1128                   cppReader_errorLit (pfile, 
1129                                       cstring_makeLiteralTemp ("Syntax error"));
1130                   goto syntax_error;
1131                 }
1132
1133               top->value = (v2 == 0) ? 1 : 0;
1134               top->unsignedp = FALSE;
1135               top->flags |= HAVE_VALUE;
1136               /*@switchbreak@*/ break;
1137             case '~':
1138               if ((top->flags & HAVE_VALUE) != 0)
1139                 {
1140                   cppReader_errorLit (pfile, 
1141                                       cstring_makeLiteralTemp ("syntax error"));
1142                   goto syntax_error;
1143                 }
1144               top->value = ~ v2;
1145               top->unsignedp = unsigned2;
1146               top->flags |= HAVE_VALUE;
1147               /*@switchbreak@*/ break;
1148             case '<':  COMPARE(<);  /*@switchbreak@*/ break;
1149             case '>':  COMPARE(>);  /*@switchbreak@*/ break;
1150             case LEQ:  COMPARE(<=); /*@switchbreak@*/ break;
1151             case GEQ:  COMPARE(>=); /*@switchbreak@*/ break;
1152             case CPP_EQUALTOK:
1153               top->value = (v1 == v2) ? 1 : 0;
1154               top->unsignedp = FALSE;
1155               /*@switchbreak@*/ break;
1156             case NOTEQUAL:
1157               top->value = (v1 != v2) ? 1 : 0;
1158               top->unsignedp = FALSE;
1159               /*@switchbreak@*/ break;
1160             case LSH:
1161               if (skip_evaluation != 0)
1162                 {
1163                   /*@switchbreak@*/ break;
1164                 }
1165
1166               top->unsignedp = unsigned1;
1167               if (v2 < 0 && ! unsigned2)
1168                 top->value = right_shift (v1, unsigned1, -v2);
1169               else
1170                 top->value = left_shift (pfile, v1, unsigned1, v2);
1171               /*@switchbreak@*/ break;
1172             case RSH:
1173               if (skip_evaluation != 0)
1174                 {
1175                   /*@switchbreak@*/ break;
1176                 }
1177               top->unsignedp = unsigned1;
1178               if (v2 < 0 && ! unsigned2)
1179                 top->value = left_shift (pfile, v1, unsigned1, -v2);
1180               else
1181                 top->value = right_shift (v1, unsigned1, v2);
1182               /*@switchbreak@*/ break;
1183
1184 /*@notfunction@*/
1185 #define LOGICAL(OP) \
1186               top->value = v1 OP v2;\
1187               top->unsignedp = unsigned1 || unsigned2;
1188
1189             case '&':  LOGICAL(&); /*@switchbreak@*/ break;
1190             case '^':  LOGICAL(^); /*@switchbreak@*/ break;
1191             case '|':  LOGICAL(|); /*@switchbreak@*/ break;
1192             case ANDAND:
1193               top->value = ((v1 != 0) && (v2 != 0)) ? 1 : 0;
1194               top->unsignedp = FALSE;
1195
1196               if (v1 == 0)
1197                 {
1198                   skip_evaluation--;
1199                 }
1200               /*@switchbreak@*/ break;
1201             case OROR:
1202               top->value = ((v1 != 0) || (v2 != 0)) ? 1 : 0;
1203               top->unsignedp = FALSE;
1204               if (v1 != 0)
1205                 {
1206                   skip_evaluation--;
1207                 }
1208               /*@switchbreak@*/ break;
1209             case ',':
1210               if (cppReader_isPedantic (pfile))
1211                 cppReader_pedwarnLit (pfile, 
1212                                 cstring_makeLiteralTemp ("comma operator in operand of `#if'"));
1213               top->value = v2;
1214               top->unsignedp = unsigned2;
1215               /*@switchbreak@*/ break;
1216             case '(':  case '?':
1217               cppReader_errorLit (pfile, 
1218                                   cstring_makeLiteralTemp ("syntax error in #if"));
1219               goto syntax_error;
1220             case ':':
1221               if (top[0].op != '?')
1222                 {
1223                   cppReader_errorLit (pfile,
1224                                       cstring_makeLiteralTemp ("syntax error ':' without preceding '?'"));
1225                   goto syntax_error;
1226                 }
1227               else if (((top[1].flags & HAVE_VALUE) == 0)
1228                        || ((top[-1].flags & HAVE_VALUE) == 0)
1229                        || ((top[0].flags & HAVE_VALUE) == 0))
1230                 {
1231                   cppReader_errorLit (pfile, 
1232                                       cstring_makeLiteralTemp ("bad syntax for ?: operator"));
1233                   goto syntax_error;
1234                 }
1235               else
1236                 {
1237                   top--;
1238                   if (top->value != 0)
1239                     {
1240                       skip_evaluation--;
1241                     }
1242
1243                   top->value = (top->value != 0) ? v1 : v2;
1244                   top->unsignedp = unsigned1 || unsigned2;
1245                 }
1246               /*@switchbreak@*/ break;
1247             case ')':
1248               if (((top[1].flags & HAVE_VALUE) != 0)
1249                   || ((top[0].flags & HAVE_VALUE) == 0)
1250                   || top[0].op != '('
1251                   || ((top[-1].flags & HAVE_VALUE) != 0))
1252                 {
1253                   cppReader_errorLit (pfile, 
1254                                       cstring_makeLiteralTemp ("mismatched parentheses in #if"));
1255                   goto syntax_error;
1256                 }
1257               else
1258                 {
1259                   top--;
1260                   top->value = v1;
1261                   top->unsignedp = unsigned1;
1262                   top->flags |= HAVE_VALUE;
1263                 }
1264               /*@switchbreak@*/ break;
1265             default:
1266               /*@-formatconst@*/
1267               fprintf (stderr,
1268                        top[1].op >= ' ' && top[1].op <= '~'
1269                        ? "unimplemented operator '%c'\n"
1270                        : "unimplemented operator '\\%03o'\n",
1271                        top[1].op);
1272               /*@=formatconst@*/
1273             }
1274         }
1275       if (op.op == 0)
1276         {
1277           long val;
1278
1279           if (top != stack)
1280             {
1281               cppReader_errorLit (pfile, 
1282                                   cstring_makeLiteralTemp ("internal error in #if expression"));
1283             }
1284
1285           val = top->value;
1286
1287           if (stack != init_stack)
1288             {
1289               sfree (stack);
1290               /*@-branchstate@*/
1291             } /*@=branchstate@*/
1292
1293           return val;
1294         }
1295       top++;
1296       
1297       /* Check for and handle stack overflow.  */
1298       if (top == limit)
1299         {
1300           struct operation *new_stack;
1301           size_t old_size = size_fromInt ((char *) limit - (char *) stack);
1302           size_t new_size = (size_t) (2 * old_size);
1303
1304           if (stack != init_stack)
1305             {
1306               new_stack = (struct operation *) drealloc ((char *) stack,
1307                                                          new_size);
1308             }
1309           else
1310             {
1311               new_stack = (struct operation *) dmalloc (new_size);
1312
1313               /* Bug: the parameters were in the wrong order! */
1314               memcpy ((char *) new_stack, (char *) stack, old_size);
1315               /*@-branchstate@*/
1316             } /*@=branchstate@*/
1317
1318           stack = new_stack;
1319           top = (struct operation *) ((char *) new_stack + old_size);
1320           limit = (struct operation *) ((char *) new_stack + new_size);
1321           /*@-branchstate@*/ 
1322         } /*@=branchstate@*/ 
1323       
1324       top->flags = flags;
1325       top->rprio = rprio;
1326       top->op = op.op;
1327       if ((op.op == OROR && (top[-1].value != 0))
1328           || (op.op == ANDAND && (top[-1].value == 0))
1329           || (op.op == '?' && (top[-1].value == 0)))
1330         {
1331           skip_evaluation++;
1332         }
1333       else if (op.op == ':')
1334         {
1335           if (top[-2].value != 0) /* Was condition true? */
1336             {
1337               skip_evaluation++;
1338             }
1339           else
1340             {
1341               skip_evaluation--;
1342             }
1343         }
1344       else
1345         {
1346           ;
1347         }
1348     }
1349  syntax_error:
1350   /*@-usereleased@*/
1351   if (stack != init_stack)
1352     {
1353       sfree (stack);
1354       /*@-branchstate@*/
1355     } /*@=branchstate@*/
1356   /*@=usereleased@*/
1357
1358   cppReader_skipRestOfLine (pfile);
1359   return 0;
1360 }
This page took 0.14826 seconds and 3 git commands to generate.