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