]> andersk Git - splint.git/blob - src/cppexp.c
3c97c988fcb878dc9fa7090396a307e8568f8087
[splint.git] / src / cppexp.c
1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
4 **         Massachusetts Institute of Technology
5 **
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
10 ** 
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 ** General Public License for more details.
15 ** 
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
19 **
20 ** For information on splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
23 */
24 /*
25 ** cppexp.c
26 */
27 /* Parse C expressions for CCCP.
28    Copyright (C) 1987, 1992, 1994, 1995, 1997 Free Software Foundation.
29
30 This program is free software; you can redistribute it and/or modify it
31 under the terms of the GNU General Public License as published by the
32 Free Software Foundation; either version 2, or (at your option) any
33 later version.
34
35 This program is distributed in the hope that it will be useful,
36 but WITHOUT ANY WARRANTY; without even the implied warranty of
37 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
38 GNU General Public License for more details.
39
40 You should have received a copy of the GNU General Public License
41 along with this program; if not, write to the Free Software
42 Foundation, 59 Temple Place - Suite 330,
43 Boston, MA 02111-1307, USA.
44
45  In other words, you are welcome to use, share and improve this program.
46  You are forbidden to forbid anyone else to use, share and improve
47  what you give them.   Help stamp out software-hoarding!
48
49 Written by Per Bothner 1994.  */
50
51 /* Parse a C expression from text in a string  */
52
53 /*@+charint@*/
54 /*@+ignorequals@*/
55 /*@+ignoresigns@*/
56 /*@+matchanyintegral@*/
57
58 # include <string.h> 
59 # include "splintMacros.nf"
60 # include "llbasic.h"
61 # include "cpplib.h"
62 # include "cpphash.h"
63 # include "cppexp.h"
64 # include "cpperror.h"
65
66 /* Yield nonzero if adding two numbers with A's and B's signs can yield a
67    number with SUM's sign, where A, B, and SUM are all C integers.  */
68
69 /*@function static bool possibleSumSign (sef int, int, int) 
70       modifies nothing ; @*/
71
72 #define possibleSumSign(a, b, sum) ((((a) ^ (b)) | ~ ((a) ^ (sum))) < 0)
73
74 /* these are guesses! */ 
75
76 /*@constant int BITS_PER_UNIT = 8@*/
77 # define BITS_PER_UNIT 8
78
79 /*@constant size_t BITS_PER_CHAR@*/
80 # define BITS_PER_CHAR 8
81
82 /*@constant size_t BITS_PER_WORD@*/
83 # define BITS_PER_WORD 32
84
85 /*@constant size_t HOST_BITS_PER_INT@*/
86 # define HOST_BITS_PER_INT 32
87
88 /*@constant size_t HOST_BITS_PER_LONG = 32@*/
89 # define HOST_BITS_PER_LONG 32
90
91 /*@constant char TARGET_BELL@*/
92 # define TARGET_BELL (char) 6 
93
94 /*@constant char TARGET_BS@*/
95 # define TARGET_BS   (char) 7
96
97 /*@constant char TARGET_FF@*/
98 # define TARGET_FF   (char) 8
99
100 /*@constant char TARGET_NEWLINE@*/
101 # define TARGET_NEWLINE '\n' 
102
103 /*@constant char TARGET_CR@*/
104 # define TARGET_CR '\n'
105
106 /*@constant char TARGET_TAB@*/
107 # define TARGET_TAB '\t'
108
109 /*@constant char TARGET_VT@*/
110 # define TARGET_VT '\v'
111
112 #ifdef MULTIBYTE_CHARS
113 #include <stdlib.h>
114 #include <locale.h>
115 #endif
116
117 #include <stdio.h>
118
119 #ifndef INT_TYPE_SIZE
120 /*@constant size_t INT_TYPE_SIZE@*/
121 #define INT_TYPE_SIZE BITS_PER_WORD
122 #endif
123
124 #ifndef LONG_TYPE_SIZE
125 /*@constant size_t LONG_TYPE_SIZE@*/
126 #define LONG_TYPE_SIZE BITS_PER_WORD
127 #endif
128
129 #ifndef WCHAR_TYPE_SIZE
130 /*@constant size_t WCHAR_TYPE_SIZE@*/
131 #define WCHAR_TYPE_SIZE INT_TYPE_SIZE
132 #endif
133
134 # ifndef CHAR_TYPE_SIZE
135 /*@constant size_t CHAR_TYPE_SIZE@*/
136 # define CHAR_TYPE_SIZE BITS_PER_CHAR
137 # endif
138
139 #ifndef MAX_CHAR_TYPE_SIZE
140 /*@constant size_t MAX_CHAR_TYPE_SIZE@*/
141 #define MAX_CHAR_TYPE_SIZE CHAR_TYPE_SIZE
142 #endif
143
144 #ifndef MAX_LONG_TYPE_SIZE
145 /*@constant size_t MAX_LONG_TYPE_SIZE@*/
146 #define MAX_LONG_TYPE_SIZE LONG_TYPE_SIZE
147 #endif
148
149 #ifndef MAX_WCHAR_TYPE_SIZE
150 /*@constant size_t MAX_WCHAR_TYPE_SIZE@*/
151 #define MAX_WCHAR_TYPE_SIZE WCHAR_TYPE_SIZE
152 #endif
153
154 static struct operation cppexp_lex (cppReader *);
155 static void integer_overflow (cppReader *);
156 static long left_shift (cppReader *, long, bool p_unsignedp, unsigned long);
157 static long right_shift (long, bool p_unsignedp, unsigned long);
158
159 /*@constant short CPPREADER_ERRORTOK@*/
160 #define CPPREADER_ERRORTOK 299
161
162 /*@constant int OROR@*/
163 #define OROR 300
164
165 /*@constant int ANDAND@*/
166 #define ANDAND 301
167
168 /*@constant int CPP_EQUALTOK@*/
169 #define CPP_EQUALTOK 302
170
171 /*@constant int NOTEQUAL@*/
172 #define NOTEQUAL 303
173
174 /*@constant int LEQ@*/
175 #define LEQ 304
176
177 /*@constant int GEQ@*/
178 #define GEQ 305
179
180 /*@constant int LSH@*/
181 #define LSH 306
182
183 /*@constant int RSH@*/
184 #define RSH 307
185
186 /*@constant int NAME@*/
187 #define NAME 308
188
189 /*@constant short CPPEXP_INT@*/
190 #define CPPEXP_INT 309
191
192 /*@constant short CPPEXP_CHAR@*/
193 #define CPPEXP_CHAR 310
194
195 /*@constant int LEFT_OPERAND_REQUIRED@*/
196 #define LEFT_OPERAND_REQUIRED 1
197
198 /*@constant int RIGHT_OPERAND_REQUIRED@*/
199 #define RIGHT_OPERAND_REQUIRED 2
200
201 /*@constant int HAVE_VALUE@*/
202 #define HAVE_VALUE 4
203
204 #ifndef HOST_BITS_PER_WIDE_INT
205
206 #if HOST_BITS_PER_LONG > HOST_BITS_PER_INT
207 /*@constant int HOST_BITS_PER_WIDE_INT@*/
208 #define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_LONG
209 /*@notfunction@*/
210 #define HOST_WIDE_INT long
211 #else
212 /*@constant int HOST_BITS_PER_WIDE_INT@*/
213 #define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_INT
214 /*@notfunction@*/
215 #define HOST_WIDE_INT long
216 #endif
217
218 #endif
219
220 struct operation {
221   short op;
222
223   /* Priority of op (relative to it right operand).  */
224   /*@reldef@*/ char rprio;
225
226   /*@reldef@*/ char flags;
227
228   /* true if value should be treated as unsigned */
229   /*@reldef@*/ bool unsignedp;
230
231   /* The value logically "right" of op.  */
232   /*@reldef@*/ HOST_WIDE_INT value;
233 } ;
234
235 /* Take care of parsing a number (anything that starts with a digit).
236    LEN is the number of characters in it.  */
237
238 /* maybe needs to actually deal with floating point numbers */
239
240 struct operation
241 cppReader_parseNumber (cppReader *pfile, char *start, int olen) /*@requires maxRead(start) >= (olen - 1) @*/
242 {
243   struct operation op;
244   char *p = start;
245   char c;
246   int i;
247   long n = 0;
248   unsigned long nd, ULONG_MAX_over_base;
249   int base = 10;
250   int len = olen;
251   bool overflow = FALSE;
252   int digit, largest_digit = 0;
253   bool spec_long = FALSE;
254
255   op.unsignedp = FALSE;
256
257   for (i = 0; i < len; i++)
258     {
259        if (p[i] == '.') {
260         /* It's a float since it contains a point.  */
261         cppReader_errorLit
262           (pfile,
263            cstring_makeLiteralTemp
264            ("Floating point numbers not allowed in #if expressions"));
265         op.op = CPPREADER_ERRORTOK;
266         return op;
267       }
268     }
269       
270   if (len >= 3 && (mstring_equalPrefix (p, "0x") 
271                    || mstring_equalPrefix (p, "0X")))
272     {
273       p += 2;
274       base = 16;
275       len -= 2;
276     }
277   else if (*p == '0')
278     {
279       /*@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              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
438   if  (c == '#') 
439     {
440       /* was: llassert (c != '#'); - Solaris uses this, attempt to continue anyway... */
441       cppReader_pedwarn (pfile, 
442                          message ("non-standard pre-processor directive: %c", c));
443     }
444
445   DPRINTF (("Read: %c", c));
446
447   if (c == '\n')
448     {
449       op.op = 0;
450       return op;
451     }
452
453   token = cpplib_getTokenForceExpand (pfile);
454
455   tok_start = pfile->token_buffer + old_written;
456   tok_end = cpplib_getPWritten (pfile);
457
458   DPRINTF (("Token: %s < %s", tok_start, tok_end));
459
460   pfile->limit = tok_start;
461
462   switch (token)
463     {
464     case CPP_EOF: /* Should not happen ...  */
465     case CPP_VSPACE:
466       op.op = 0;
467       return op;
468     case CPP_POP:
469       if (cstring_isDefined (cppReader_getBufferSafe (pfile)->fname))
470         {
471           op.op = 0;
472           return op;
473         }
474       (void) cppReader_popBuffer (pfile);
475       goto retry;
476     case CPP_HSPACE:   case CPP_COMMENT: 
477       goto retry;
478     case CPP_NUMBER:
479       return cppReader_parseNumber (pfile, tok_start, tok_end - tok_start);
480     case CPP_STRING:
481       cppReader_errorLit (pfile, 
482                           cstring_makeLiteralTemp ("string constants not allowed in #if expressions"));
483       op.op = CPPREADER_ERRORTOK;
484       return op;
485     case CPP_CHAR:
486       /* This code for reading a character constant
487          handles multicharacter constants and wide characters.
488          It is mostly copied from c-lex.c.  */
489       {
490         int result = 0;
491         int num_chars = 0;
492         size_t width = MAX_CHAR_TYPE_SIZE;
493         int wide_flag = 0;
494         int max_chars;
495         char *ptr = tok_start;
496 #ifdef MULTIBYTE_CHARS
497         char token_buffer[MAX_LONG_TYPE_SIZE/MAX_CHAR_TYPE_SIZE + MB_CUR_MAX];
498 #else
499         char token_buffer[MAX_LONG_TYPE_SIZE/MAX_CHAR_TYPE_SIZE + 1];
500 #endif
501         
502         if (*ptr == 'L')
503           {
504             ptr++;
505             wide_flag = 1;
506             width = MAX_WCHAR_TYPE_SIZE;
507 #ifdef MULTIBYTE_CHARS
508             max_chars = MB_CUR_MAX;
509 #else
510             max_chars = 1;
511 #endif
512           }
513         else
514           {
515             max_chars = size_toInt (MAX_LONG_TYPE_SIZE / width);
516           }
517         
518         ++ptr;
519          while (ptr < tok_end && ((c = *ptr++) != '\''))
520           {
521             if (c == '\\')
522               {
523                 c = cppReader_parseEscape (pfile, &ptr);
524                 if (width < HOST_BITS_PER_INT && c >= (1 << width))
525                   {
526                     cppReader_pedwarnLit 
527                       (pfile,
528                        cstring_makeLiteralTemp ("Escape sequence out of range for character"));
529                   }
530               }
531                 
532             num_chars++;
533             
534             /* Merge character into result; ignore excess chars.  */
535             if (num_chars < max_chars + 1)
536               {
537                 if (width < HOST_BITS_PER_INT)
538                   {
539                     result = (int) ((unsigned) result << width) | (c & ((1 << width) - 1));
540                   }
541                 else
542                   {
543                     result = c;
544                   }
545
546                 token_buffer[num_chars - 1] = c;
547               }
548           }
549
550          token_buffer[num_chars] = 0;
551
552         if (c != '\'')
553           cppReader_errorLit (pfile,
554                               cstring_makeLiteralTemp ("malformatted character constant"));
555         else if (num_chars == 0)
556           cppReader_errorLit (pfile, 
557                               cstring_makeLiteralTemp ("empty character constant"));
558         else if (num_chars > max_chars)
559           {
560             num_chars = max_chars;
561             cppReader_errorLit (pfile, 
562                                 cstring_makeLiteralTemp ("character constant too long"));
563           }
564         else if (num_chars != 1 && ! cppReader_isTraditional (pfile))
565           {
566             cppReader_warningLit (pfile, 
567                                   cstring_makeLiteralTemp ("multi-character character constant"));
568           }
569         else
570           {
571             ;
572           }
573
574         /* If char type is signed, sign-extend the constant.  */
575         if (wide_flag == 0)
576           {
577             int num_bits = num_chars * width;
578
579             if ((cpphash_lookup ("__CHAR_UNSIGNED__",
580                              sizeof ("__CHAR_UNSIGNED__") - 1, -1) != NULL)
581                 || (((unsigned) result >> (int_toNonNegative (num_bits - 1))) & 1) == 0)
582               {
583                 op.value
584                   = result & ((unsigned long) ~0 
585                               >> int_toNonNegative ((HOST_BITS_PER_LONG - num_bits)));
586               }
587             else
588               {
589                 op.value
590                   = result | ~((unsigned long) ~0 
591                                >> int_toNonNegative ((HOST_BITS_PER_LONG - num_bits)));
592               }
593           }
594         else
595           {
596 #ifdef MULTIBYTE_CHARS
597             /* Set the initial shift state and convert the next sequence.  */
598               result = 0;
599               /* In all locales L'\0' is zero and mbtowc will return zero,
600                  so don't use it.  */
601               if (num_chars > 1
602                   || (num_chars == 1 && token_buffer[0] != '\0'))
603                 {
604                   wchar_t wc;
605                   (void) mbtowc (NULL, NULL, 0);
606                   if (mbtowc (& wc, token_buffer, num_chars) == num_chars)
607                     result = wc;
608                   else
609                     cppReader_pedwarn (pfile,"Ignoring invalid multibyte character");
610                 }
611 #endif
612               op.value = result;
613             }
614         }
615
616       /* This is always a signed type.  */
617       op.unsignedp = FALSE;
618       op.op = CPPEXP_CHAR;
619     
620       return op;
621
622     case CPP_NAME:
623       DPRINTF (("Name!"));
624       return cppReader_parseNumber (pfile, "0", 0);
625
626     case CPP_OTHER:
627       /* See if it is a special token of length 2.  */
628       if (tok_start + 2 == tok_end)
629         {
630           for (toktab = tokentab2; toktab->operator != NULL; toktab++)
631             {
632              if (tok_start[0] == toktab->operator[0]  &&
633                  tok_start[1] == toktab->operator[1])
634                 {
635                   /*@loopbreak@*/ break;
636                 }
637             }
638
639           if (toktab->token == CPPREADER_ERRORTOK)
640             {
641               cppReader_error (pfile, 
642                                message ("`%s' not allowed in operand of `#if'",
643                                         cstring_fromChars (tok_start)));
644             }
645
646           op.op = toktab->token; 
647           return op;
648         }
649       /*@fallthrough@*/ 
650     default:
651       op.op = *tok_start;
652       return op;
653   }
654
655   BADEXIT;
656   /*@notreached@*/ 
657 }
658
659
660 /* Parse a C escape sequence.  STRING_PTR points to a variable
661    containing a pointer to the string to parse.  That pointer
662    is updated past the characters we use.  The value of the
663    escape sequence is returned.
664
665    A negative value means the sequence \ newline was seen,
666    which is supposed to be equivalent to nothing at all.
667
668    If \ is followed by a null character, we return a negative
669    value and leave the string pointer pointing at the null character.
670
671    If \ is followed by 000, we return 0 and leave the string pointer
672    after the zeros.  A value of 0 does not mean end of string.  */
673
674 int
675 cppReader_parseEscape (cppReader *pfile, char **string_ptr)
676 {
677    char c = *(*string_ptr)++;
678
679   switch (c)
680     {
681     case 'a':
682       return TARGET_BELL;
683     case 'b':
684       return TARGET_BS;
685     case 'e':
686     case 'E':
687       if (cppReader_isPedantic (pfile))
688         {
689           cppReader_pedwarn (pfile, 
690                        message ("non-standard escape sequence, `\\%c'", c));
691         }
692       return (char) 033;
693     case 'f':
694       return TARGET_FF;
695     case 'n':
696       return TARGET_NEWLINE;
697     case 'r':
698       return TARGET_CR;
699     case 't':
700       return TARGET_TAB;
701     case 'v':
702       return TARGET_VT;
703     case '\n':
704       return -2;
705     case 0:
706       (*string_ptr)--;
707       return 0;
708       
709     case '0':
710     case '1':
711     case '2':
712     case '3':
713     case '4':
714     case '5':
715     case '6':
716     case '7':
717       {
718         int i = (int) c - '0';
719         int count = 0;
720
721         while (++count < 3)
722           {
723             c = *(*string_ptr)++;
724             if (c >= '0' && c <= '7')
725               {
726                 i = ((unsigned) i << 3) + c - '0';
727               }
728
729             else
730               {
731                 (*string_ptr)--;
732                 /*@loopbreak@*/ break;
733               }
734           }
735         if ((i & ~((1 << MAX_CHAR_TYPE_SIZE) - 1)) != 0)
736           {
737             i &= (1 << MAX_CHAR_TYPE_SIZE) - 1;
738             cppReader_pedwarnLit (pfile,
739                             cstring_makeLiteralTemp ("octal character constant does not fit in a byte"));
740           }
741         return i;
742       }
743     case 'x':
744       {
745         register unsigned i = 0, overflow = 0, digits_found = 0, digit;
746         for (;;)
747           {
748             c = *(*string_ptr)++;
749
750             if (c >= '0' && c <= '9')
751               {
752                 digit = (unsigned int) (c - '0');
753               }
754             else if (c >= 'a' && c <= 'f')
755               {
756                 digit = (unsigned int) (c - 'a') + 10;
757               }
758             else if (c >= 'A' && c <= 'F')
759               {
760                 digit = (unsigned int) (c - 'A') + 10;
761               }
762             else
763               {
764                 (*string_ptr)--;
765                 /*@loopbreak@*/ break;
766               }
767             overflow |= i ^ (i << 4 >> 4);
768             i = (i << 4) + digit;
769             digits_found = 1;
770           }
771         
772         if (digits_found == 0)
773           {
774             cppReader_errorLit (pfile,
775                                 cstring_makeLiteralTemp ("\\x used with no following hex digits"));
776           }
777
778         if ((overflow | (i & ~((1 << int_toNonNegative (BITS_PER_UNIT)) - 1))) != 0)
779           {
780             i &= (1 << BITS_PER_UNIT) - 1;
781             cppReader_pedwarnLit (pfile,
782                             cstring_makeLiteralTemp ("hex character constant does not fit in a byte"));
783           }
784
785         return i;
786       }
787     default:
788       return c;
789     }
790 }
791
792 static void
793 integer_overflow (cppReader *pfile)
794 {
795   if (cppReader_isPedantic (pfile))
796     cppReader_pedwarnLit (pfile, 
797                     cstring_makeLiteralTemp ("integer overflow in preprocessor expression"));
798 }
799
800 static long
801 left_shift (cppReader *pfile, long a, bool unsignedp, unsigned long b)
802 {
803   if (b >= HOST_BITS_PER_LONG)
804     {
805       if (!unsignedp && a != 0)
806         {
807           integer_overflow (pfile);
808         }
809
810       return 0;
811     }
812   else if (unsignedp)
813     {
814       return (unsigned long) a << b;
815     }
816   else
817     {
818       long l = int_toNonNegative (a) << b;
819
820 # ifdef WIN32
821 # pragma warning( disable : 4018 )
822 # endif
823
824       if (int_toNonNegative (l) >> b != a)
825         {
826           integer_overflow (pfile);
827         }
828
829       return l;
830     }
831 }
832
833 static long
834 right_shift (long a, bool unsignedp, unsigned long b)
835 {
836   if (b >= HOST_BITS_PER_LONG)
837     return (unsignedp ? 0 : int_toNonNegative (a) >> (HOST_BITS_PER_LONG - 1));
838   else if (unsignedp)
839     return (unsigned long) a >> b;
840   else
841     return int_toNonNegative (a) >> b;
842 }
843
844 /* These priorities are all even, so we can handle associatively.  */
845
846 /*@constant int PAREN_INNER_PRIO@*/
847 #define PAREN_INNER_PRIO 0
848
849 /*@constant int COMMA_PRIO@*/
850 #define COMMA_PRIO 4
851
852 /*@constant int COND_PRIO@*/
853 #define COND_PRIO (COMMA_PRIO+2)
854
855 /*@constant int OROR_PRIO@*/
856 #define OROR_PRIO (COND_PRIO+2)
857
858 /*@constant int ANDAND_PRIO@*/
859 #define ANDAND_PRIO (OROR_PRIO+2)
860
861 /*@constant int OR_PRIO@*/
862 #define OR_PRIO (ANDAND_PRIO+2)
863
864 /*@constant int XOR_PRIO@*/
865 #define XOR_PRIO (OR_PRIO+2)
866
867 /*@constant int AND_PRIO@*/
868 #define AND_PRIO (XOR_PRIO+2)
869
870 /*@constant int CPP_EQUAL_PRIO@*/
871 #define CPP_EQUAL_PRIO (AND_PRIO+2)
872
873 /*@constant int LESS_PRIO@*/
874 #define LESS_PRIO (CPP_EQUAL_PRIO+2)
875
876 /*@constant int SHIFT_PRIO@*/
877 #define SHIFT_PRIO (LESS_PRIO+2)
878
879 /*@constant int PLUS_PRIO@*/
880 #define PLUS_PRIO (SHIFT_PRIO+2)
881
882 /*@constant int MUL_PRIO@*/
883 #define MUL_PRIO (PLUS_PRIO+2)
884
885 /*@constant int UNARY_PRIO@*/
886 #define UNARY_PRIO (MUL_PRIO+2)
887
888 /*@constant int PAREN_OUTER_PRIO@*/
889 #define PAREN_OUTER_PRIO (UNARY_PRIO+2)
890
891 /*@notfunction@*/
892 #define COMPARE(OP) \
893   top->unsignedp = FALSE;\
894   top->value = ((unsigned1 || unsigned2) \
895                  ? (unsigned long) v1 OP (unsigned long) v2 \
896                  : ((long) v1 OP (long) v2)) ? 1 : 0
897
898 /* Parse and evaluate a C expression, reading from PFILE.
899    Returns the value of the expression.  */
900
901 /*@constant int INIT_STACK_SIZE@*/
902 # define INIT_STACK_SIZE 20
903
904 HOST_WIDE_INT
905 cppReader_parseExpression (cppReader *pfile)
906 {
907   /* The implementation is an operator precedence parser,
908      i.e. a bottom-up parser, using a stack for not-yet-reduced tokens.
909
910      The stack base is 'stack', and the current stack pointer is 'top'.
911      There is a stack element for each operator (only),
912      and the most recently pushed operator is 'top->op'.
913      An operand (value) is stored in the 'value' field of the stack
914      element of the operator that precedes it.
915      In that case the 'flags' field has the HAVE_VALUE flag set.  */
916
917   struct operation init_stack[INIT_STACK_SIZE];
918   struct operation *stack = init_stack;
919   struct operation *limit = stack + INIT_STACK_SIZE;
920   register struct operation *top = stack;
921   int lprio, rprio = 0;
922   int skip_evaluation = 0;
923
924   top->rprio = 0;
925   top->flags = 0;
926
927   for (;;)
928     {
929       struct operation op;
930       int flags = 0;
931
932       /* Read a token */
933       op = cppexp_lex (pfile);
934
935       /* See if the token is an operand, in which case go to set_value.
936          If the token is an operator, figure out its left and right
937          priorities, and then goto maybe_reduce.  */
938
939       switch (op.op)
940         {
941         case NAME:
942           top->value = 0, top->unsignedp = FALSE;
943           goto set_value;
944         case CPPEXP_INT:
945         case CPPEXP_CHAR:
946           top->value = op.value;
947           top->unsignedp = op.unsignedp;
948           goto set_value;
949         case 0:
950           lprio = 0;  goto maybe_reduce;
951         case '+':  case '-':
952           /* Is this correct if unary ? FIXME */
953           flags = RIGHT_OPERAND_REQUIRED;
954           lprio = PLUS_PRIO;  rprio = lprio + 1;  goto maybe_reduce;
955         case '!':  case '~':
956           flags = RIGHT_OPERAND_REQUIRED;
957           rprio = UNARY_PRIO;  lprio = rprio + 1;  goto maybe_reduce;
958         case '*':  case '/':  case '%':
959           lprio = MUL_PRIO;  goto binop;
960         case '<':  case '>':  case LEQ:  case GEQ:
961           lprio = LESS_PRIO;  goto binop;
962         case CPP_EQUALTOK:  case NOTEQUAL:
963           lprio = CPP_EQUAL_PRIO;  goto binop;
964         case LSH:  case RSH:
965           lprio = SHIFT_PRIO;  goto binop;
966         case '&':  lprio = AND_PRIO;  goto binop;
967         case '^':  lprio = XOR_PRIO;  goto binop;
968         case '|':  lprio = OR_PRIO;  goto binop;
969         case ANDAND:  lprio = ANDAND_PRIO;  goto binop;
970         case OROR:  lprio = OROR_PRIO;  goto binop;
971         case ',':
972           lprio = COMMA_PRIO;  goto binop;
973         case '(':
974           lprio = PAREN_OUTER_PRIO;  rprio = PAREN_INNER_PRIO;
975           goto maybe_reduce;
976         case ')':
977           lprio = PAREN_INNER_PRIO;  rprio = PAREN_OUTER_PRIO;
978           goto maybe_reduce;
979         case ':':
980           lprio = COND_PRIO;  rprio = COND_PRIO;
981           goto maybe_reduce;
982         case '?':
983           lprio = COND_PRIO + 1;  rprio = COND_PRIO;
984           goto maybe_reduce;
985         binop:
986           flags = LEFT_OPERAND_REQUIRED | RIGHT_OPERAND_REQUIRED;
987           rprio = lprio + 1;
988           goto maybe_reduce;
989         default:
990           cppReader_error 
991             (pfile, 
992              message ("Invalid character in #if: %c", 
993                       (char) op.op));
994           goto syntax_error;
995         }
996
997     set_value:
998       /* Push a value onto the stack.  */
999       if ((top->flags & HAVE_VALUE) != 0)
1000         {
1001           cppReader_errorLit (pfile, 
1002                               cstring_makeLiteralTemp ("syntax error in #if"));
1003           goto syntax_error;
1004         }
1005       top->flags |= HAVE_VALUE;
1006       continue;
1007
1008     maybe_reduce:
1009       /* Push an operator, and check if we can reduce now.  */
1010       while (top->rprio > lprio)
1011         {
1012           /*@-usedef@*/
1013           HOST_WIDE_INT v1 = top[-1].value;
1014           HOST_WIDE_INT v2 = top[0].value;
1015           bool unsigned1 = top[-1].unsignedp;
1016           bool unsigned2 = top[0].unsignedp;
1017
1018           top--;
1019
1020           if (((top[1].flags & LEFT_OPERAND_REQUIRED) != 0)
1021               && ((top[0].flags & HAVE_VALUE) == 0))
1022             {
1023               cppReader_errorLit (pfile, 
1024                                   cstring_makeLiteralTemp ("syntax error - missing left operand"));
1025               goto syntax_error;
1026             }
1027           if (((top[1].flags & RIGHT_OPERAND_REQUIRED) != 0)
1028               && ((top[1].flags & HAVE_VALUE) == 0))
1029             {
1030               cppReader_errorLit (pfile, 
1031                                   cstring_makeLiteralTemp ("syntax error - missing right operand"));
1032               goto syntax_error;
1033             }
1034           /* top[0].value = (top[1].op)(v1, v2);*/
1035           switch (top[1].op)
1036             {
1037             case '+':
1038               if ((top->flags & HAVE_VALUE) == 0)
1039                 { /* Unary '+' */
1040                   top->value = v2;
1041                   top->unsignedp = unsigned2;
1042                   top->flags |= HAVE_VALUE;
1043                 }
1044               else
1045                 {
1046                   top->value = v1 + v2;
1047                   top->unsignedp = unsigned1 || unsigned2;
1048                   if (!top->unsignedp && (skip_evaluation == 0)
1049                       && ! possibleSumSign (v1, v2, top->value))
1050                     integer_overflow (pfile);
1051                 }
1052               /*@switchbreak@*/ break;
1053             case '-':
1054               if ((top->flags & HAVE_VALUE) == 0)
1055                 { /* Unary '-' */
1056                   top->value = - v2;
1057                   if ((skip_evaluation == 0) 
1058                       && (top->value & v2) < 0 && !unsigned2)
1059                     integer_overflow (pfile);
1060                   top->unsignedp = unsigned2;
1061                   top->flags |= HAVE_VALUE;
1062                 }
1063               else
1064                 { /* Binary '-' */
1065                   top->value = v1 - v2;
1066                   top->unsignedp = unsigned1 || unsigned2;
1067                   if (!top->unsignedp && (skip_evaluation == 0)
1068                       && !possibleSumSign (top->value, v2, v1))
1069                     {
1070                       integer_overflow (pfile);
1071                     }
1072                 }
1073               /*@switchbreak@*/ break;
1074             case '*':
1075               top->unsignedp = unsigned1 || unsigned2;
1076
1077               if (top->unsignedp)
1078                 {
1079                   top->value = (unsigned long) v1 * v2;
1080                 }
1081               else if (skip_evaluation == 0)
1082                 {
1083                   top->value = v1 * v2;
1084                   if ((v1 != 0)
1085                       && (top->value / v1 != v2
1086                           || (top->value & v1 & v2) < 0))
1087                     {
1088                       integer_overflow (pfile);
1089                     }
1090                 }
1091               else
1092                 {
1093                   ;
1094                 }
1095
1096               /*@switchbreak@*/ break;
1097             case '/':
1098               if (skip_evaluation != 0)
1099                 /*@switchbreak@*/ break;
1100               if (v2 == 0)
1101                 {
1102                   cppReader_errorLit (pfile, 
1103                                       cstring_makeLiteralTemp ("Division by zero in #if"));
1104                   v2 = 1;
1105                 }
1106               top->unsignedp = unsigned1 || unsigned2;
1107               if (top->unsignedp)
1108                 top->value = (unsigned long) v1 / v2;
1109               else
1110                 {
1111                   top->value = v1 / v2;
1112                   if ((top->value & v1 & v2) < 0)
1113                     integer_overflow (pfile);
1114                 }
1115               /*@switchbreak@*/ break;
1116             case '%':
1117               if (skip_evaluation != 0)
1118                 /*@switchbreak@*/ break;
1119               if (v2 == 0)
1120                 {
1121                   cppReader_errorLit (pfile, 
1122                                       cstring_makeLiteralTemp ("Division by zero in #if"));
1123                   v2 = 1;
1124                 }
1125               top->unsignedp = unsigned1 || unsigned2;
1126               if (top->unsignedp)
1127                 top->value = (unsigned long) v1 % v2;
1128               else
1129                 top->value = v1 % v2;
1130               /*@switchbreak@*/ break;
1131             case '!':
1132               if ((top->flags & HAVE_VALUE) != 0)
1133                 {
1134                   cppReader_errorLit (pfile, 
1135                                       cstring_makeLiteralTemp ("Syntax error"));
1136                   goto syntax_error;
1137                 }
1138
1139               top->value = (v2 == 0) ? 1 : 0;
1140               top->unsignedp = FALSE;
1141               top->flags |= HAVE_VALUE;
1142               /*@switchbreak@*/ break;
1143             case '~':
1144               if ((top->flags & HAVE_VALUE) != 0)
1145                 {
1146                   cppReader_errorLit (pfile, 
1147                                       cstring_makeLiteralTemp ("syntax error"));
1148                   goto syntax_error;
1149                 }
1150               top->value = ~ v2;
1151               top->unsignedp = unsigned2;
1152               top->flags |= HAVE_VALUE;
1153               /*@switchbreak@*/ break;
1154             case '<':  COMPARE(<);  /*@switchbreak@*/ break;
1155             case '>':  COMPARE(>);  /*@switchbreak@*/ break;
1156             case LEQ:  COMPARE(<=); /*@switchbreak@*/ break;
1157             case GEQ:  COMPARE(>=); /*@switchbreak@*/ break;
1158             case CPP_EQUALTOK:
1159               top->value = (v1 == v2) ? 1 : 0;
1160               top->unsignedp = FALSE;
1161               /*@switchbreak@*/ break;
1162             case NOTEQUAL:
1163               top->value = (v1 != v2) ? 1 : 0;
1164               top->unsignedp = FALSE;
1165               /*@switchbreak@*/ break;
1166             case LSH:
1167               if (skip_evaluation != 0)
1168                 {
1169                   /*@switchbreak@*/ break;
1170                 }
1171
1172               top->unsignedp = unsigned1;
1173               if (v2 < 0 && ! unsigned2)
1174                 top->value = right_shift (v1, unsigned1, -v2);
1175               else
1176                 top->value = left_shift (pfile, v1, unsigned1, v2);
1177               /*@switchbreak@*/ break;
1178             case RSH:
1179               if (skip_evaluation != 0)
1180                 {
1181                   /*@switchbreak@*/ break;
1182                 }
1183               top->unsignedp = unsigned1;
1184               if (v2 < 0 && ! unsigned2)
1185                 top->value = left_shift (pfile, v1, unsigned1, -v2);
1186               else
1187                 top->value = right_shift (v1, unsigned1, v2);
1188               /*@switchbreak@*/ break;
1189
1190 /*@notfunction@*/
1191 #define LOGICAL(OP) \
1192               top->value = v1 OP v2;\
1193               top->unsignedp = unsigned1 || unsigned2;
1194
1195             case '&':  LOGICAL(&); /*@switchbreak@*/ break;
1196             case '^':  LOGICAL(^); /*@switchbreak@*/ break;
1197             case '|':  LOGICAL(|); /*@switchbreak@*/ break;
1198             case ANDAND:
1199               top->value = ((v1 != 0) && (v2 != 0)) ? 1 : 0;
1200               top->unsignedp = FALSE;
1201
1202               if (v1 == 0)
1203                 {
1204                   skip_evaluation--;
1205                 }
1206               /*@switchbreak@*/ break;
1207             case OROR:
1208               top->value = ((v1 != 0) || (v2 != 0)) ? 1 : 0;
1209               top->unsignedp = FALSE;
1210               if (v1 != 0)
1211                 {
1212                   skip_evaluation--;
1213                 }
1214               /*@switchbreak@*/ break;
1215             case ',':
1216               if (cppReader_isPedantic (pfile))
1217                 cppReader_pedwarnLit (pfile, 
1218                                 cstring_makeLiteralTemp ("comma operator in operand of `#if'"));
1219               top->value = v2;
1220               top->unsignedp = unsigned2;
1221               /*@switchbreak@*/ break;
1222             case '(':  case '?':
1223               cppReader_errorLit (pfile, 
1224                                   cstring_makeLiteralTemp ("syntax error in #if"));
1225               goto syntax_error;
1226             case ':':
1227               if (top[0].op != '?')
1228                 {
1229                   cppReader_errorLit (pfile,
1230                                       cstring_makeLiteralTemp ("syntax error ':' without preceding '?'"));
1231                   goto syntax_error;
1232                 }
1233               else if (((top[1].flags & HAVE_VALUE) == 0)
1234                        || ((top[-1].flags & HAVE_VALUE) == 0)
1235                        || ((top[0].flags & HAVE_VALUE) == 0))
1236                 {
1237                   cppReader_errorLit (pfile, 
1238                                       cstring_makeLiteralTemp ("bad syntax for ?: operator"));
1239                   goto syntax_error;
1240                 }
1241               else
1242                 {
1243                   top--;
1244                   if (top->value != 0)
1245                     {
1246                       skip_evaluation--;
1247                     }
1248
1249                   top->value = (top->value != 0) ? v1 : v2;
1250                   top->unsignedp = unsigned1 || unsigned2;
1251                 }
1252               /*@switchbreak@*/ break;
1253             case ')':
1254               if (((top[1].flags & HAVE_VALUE) != 0)
1255                   || ((top[0].flags & HAVE_VALUE) == 0)
1256                   || top[0].op != '('
1257                   || ((top[-1].flags & HAVE_VALUE) != 0))
1258                 {
1259                   cppReader_errorLit (pfile, 
1260                                       cstring_makeLiteralTemp ("mismatched parentheses in #if"));
1261                   goto syntax_error;
1262                 }
1263               else
1264                 {
1265                   top--;
1266                   top->value = v1;
1267                   top->unsignedp = unsigned1;
1268                   top->flags |= HAVE_VALUE;
1269                 }
1270               /*@switchbreak@*/ break;
1271             default:
1272               /*@-formatconst@*/
1273               fprintf (stderr,
1274                        top[1].op >= ' ' && top[1].op <= '~'
1275                        ? "unimplemented operator '%c'\n"
1276                        : "unimplemented operator '\\%03o'\n",
1277                        top[1].op);
1278               /*@=formatconst@*/
1279             }
1280         }
1281       if (op.op == 0)
1282         {
1283           long val;
1284
1285           if (top != stack)
1286             {
1287               cppReader_errorLit (pfile, 
1288                                   cstring_makeLiteralTemp ("internal error in #if expression"));
1289             }
1290
1291           val = top->value;
1292
1293           if (stack != init_stack)
1294             {
1295               sfree (stack);
1296               /*@-branchstate@*/
1297             } /*@=branchstate@*/
1298
1299           return val;
1300         }
1301       top++;
1302       
1303       /* Check for and handle stack overflow.  */
1304       if (top == limit)
1305         {
1306           struct operation *new_stack;
1307           size_t old_size = size_fromInt ((char *) limit - (char *) stack);
1308           size_t new_size = (size_t) (2 * old_size);
1309
1310           if (stack != init_stack)
1311             {
1312               new_stack = (struct operation *) drealloc ((char *) stack,
1313                                                          new_size);
1314             }
1315           else
1316             {
1317               new_stack = (struct operation *) dmalloc (new_size);
1318
1319               /* Bug: the parameters were in the wrong order! */
1320               memcpy ((char *) new_stack, (char *) stack, old_size);
1321               /*@-branchstate@*/
1322             } /*@=branchstate@*/
1323
1324           stack = new_stack;
1325           top = (struct operation *) ((char *) new_stack + old_size);
1326           limit = (struct operation *) ((char *) new_stack + new_size);
1327           /*@-branchstate@*/ 
1328         } /*@=branchstate@*/ 
1329       
1330       top->flags = flags;
1331       top->rprio = rprio;
1332       top->op = op.op;
1333       if ((op.op == OROR && (top[-1].value != 0))
1334           || (op.op == ANDAND && (top[-1].value == 0))
1335           || (op.op == '?' && (top[-1].value == 0)))
1336         {
1337           skip_evaluation++;
1338         }
1339       else if (op.op == ':')
1340         {
1341           if (top[-2].value != 0) /* Was condition true? */
1342             {
1343               skip_evaluation++;
1344             }
1345           else
1346             {
1347               skip_evaluation--;
1348             }
1349         }
1350       else
1351         {
1352           ;
1353         }
1354     }
1355  syntax_error:
1356   /*@-usereleased@*/
1357   if (stack != init_stack)
1358     {
1359       sfree (stack);
1360       /*@-branchstate@*/
1361     } /*@=branchstate@*/
1362   /*@=usereleased@*/
1363
1364   cppReader_skipRestOfLine (pfile);
1365   return 0;
1366 }
This page took 0.143043 seconds and 3 git commands to generate.