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