]> andersk Git - splint.git/blob - src/cppexp.c
o Make lltok an abstract type, a pointer to structure instead of a plain
[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: 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, 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
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          /*drl bee: hda*/ 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          /*drl bee: dad*/ 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              /*drl bee: hda*/   if (tok_start[0] == /*drl bee: hda*/  toktab->operator[0]
633                   && /*drl bee: hda*/  tok_start[1] ==  /*drl bee: hda*/ 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   /*drl bee: pbr*/  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          /*drl bee: pbr*/       (*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, size_t 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           long v1 = top[-1].value, v2 = top[0].value;
1014           bool unsigned1 = top[-1].unsignedp;
1015           bool unsigned2 = top[0].unsignedp;
1016
1017           top--;
1018
1019           if (((top[1].flags & LEFT_OPERAND_REQUIRED) != 0)
1020               && ((top[0].flags & HAVE_VALUE) == 0))
1021             {
1022               cppReader_errorLit (pfile, 
1023                                   cstring_makeLiteralTemp ("syntax error - missing left operand"));
1024               goto syntax_error;
1025             }
1026           if (((top[1].flags & RIGHT_OPERAND_REQUIRED) != 0)
1027               && ((top[1].flags & HAVE_VALUE) == 0))
1028             {
1029               cppReader_errorLit (pfile, 
1030                                   cstring_makeLiteralTemp ("syntax error - missing right operand"));
1031               goto syntax_error;
1032             }
1033           /* top[0].value = (top[1].op)(v1, v2);*/
1034           switch (top[1].op)
1035             {
1036             case '+':
1037               if ((top->flags & HAVE_VALUE) == 0)
1038                 { /* Unary '+' */
1039                   top->value = v2;
1040                   top->unsignedp = unsigned2;
1041                   top->flags |= HAVE_VALUE;
1042                 }
1043               else
1044                 {
1045                   top->value = v1 + v2;
1046                   top->unsignedp = unsigned1 || unsigned2;
1047                   if (!top->unsignedp && (skip_evaluation == 0)
1048                       && ! possibleSumSign (v1, v2, top->value))
1049                     integer_overflow (pfile);
1050                 }
1051               /*@switchbreak@*/ break;
1052             case '-':
1053               if ((top->flags & HAVE_VALUE) == 0)
1054                 { /* Unary '-' */
1055                   top->value = - v2;
1056                   if ((skip_evaluation == 0) 
1057                       && (top->value & v2) < 0 && !unsigned2)
1058                     integer_overflow (pfile);
1059                   top->unsignedp = unsigned2;
1060                   top->flags |= HAVE_VALUE;
1061                 }
1062               else
1063                 { /* Binary '-' */
1064                   top->value = v1 - v2;
1065                   top->unsignedp = unsigned1 || unsigned2;
1066                   if (!top->unsignedp && (skip_evaluation == 0)
1067                       && !possibleSumSign (top->value, v2, v1))
1068                     {
1069                       integer_overflow (pfile);
1070                     }
1071                 }
1072               /*@switchbreak@*/ break;
1073             case '*':
1074               top->unsignedp = unsigned1 || unsigned2;
1075
1076               if (top->unsignedp)
1077                 {
1078                   top->value = (unsigned long) v1 * v2;
1079                 }
1080               else if (skip_evaluation == 0)
1081                 {
1082                   top->value = v1 * v2;
1083                   if ((v1 != 0)
1084                       && (top->value / v1 != v2
1085                           || (top->value & v1 & v2) < 0))
1086                     {
1087                       integer_overflow (pfile);
1088                     }
1089                 }
1090               else
1091                 {
1092                   ;
1093                 }
1094
1095               /*@switchbreak@*/ break;
1096             case '/':
1097               if (skip_evaluation != 0)
1098                 /*@switchbreak@*/ break;
1099               if (v2 == 0)
1100                 {
1101                   cppReader_errorLit (pfile, 
1102                                       cstring_makeLiteralTemp ("Division by zero in #if"));
1103                   v2 = 1;
1104                 }
1105               top->unsignedp = unsigned1 || unsigned2;
1106               if (top->unsignedp)
1107                 top->value = (unsigned long) v1 / v2;
1108               else
1109                 {
1110                   top->value = v1 / v2;
1111                   if ((top->value & v1 & v2) < 0)
1112                     integer_overflow (pfile);
1113                 }
1114               /*@switchbreak@*/ break;
1115             case '%':
1116               if (skip_evaluation != 0)
1117                 /*@switchbreak@*/ break;
1118               if (v2 == 0)
1119                 {
1120                   cppReader_errorLit (pfile, 
1121                                       cstring_makeLiteralTemp ("Division by zero in #if"));
1122                   v2 = 1;
1123                 }
1124               top->unsignedp = unsigned1 || unsigned2;
1125               if (top->unsignedp)
1126                 top->value = (unsigned long) v1 % v2;
1127               else
1128                 top->value = v1 % v2;
1129               /*@switchbreak@*/ break;
1130             case '!':
1131               if ((top->flags & HAVE_VALUE) != 0)
1132                 {
1133                   cppReader_errorLit (pfile, 
1134                                       cstring_makeLiteralTemp ("Syntax error"));
1135                   goto syntax_error;
1136                 }
1137
1138               top->value = (v2 == 0) ? 1 : 0;
1139               top->unsignedp = FALSE;
1140               top->flags |= HAVE_VALUE;
1141               /*@switchbreak@*/ break;
1142             case '~':
1143               if ((top->flags & HAVE_VALUE) != 0)
1144                 {
1145                   cppReader_errorLit (pfile, 
1146                                       cstring_makeLiteralTemp ("syntax error"));
1147                   goto syntax_error;
1148                 }
1149               top->value = ~ v2;
1150               top->unsignedp = unsigned2;
1151               top->flags |= HAVE_VALUE;
1152               /*@switchbreak@*/ break;
1153             case '<':  COMPARE(<);  /*@switchbreak@*/ break;
1154             case '>':  COMPARE(>);  /*@switchbreak@*/ break;
1155             case LEQ:  COMPARE(<=); /*@switchbreak@*/ break;
1156             case GEQ:  COMPARE(>=); /*@switchbreak@*/ break;
1157             case CPP_EQUALTOK:
1158               top->value = (v1 == v2) ? 1 : 0;
1159               top->unsignedp = FALSE;
1160               /*@switchbreak@*/ break;
1161             case NOTEQUAL:
1162               top->value = (v1 != v2) ? 1 : 0;
1163               top->unsignedp = FALSE;
1164               /*@switchbreak@*/ break;
1165             case LSH:
1166               if (skip_evaluation != 0)
1167                 {
1168                   /*@switchbreak@*/ break;
1169                 }
1170
1171               top->unsignedp = unsigned1;
1172               if (v2 < 0 && ! unsigned2)
1173                 top->value = right_shift (v1, unsigned1, -v2);
1174               else
1175                 top->value = left_shift (pfile, v1, unsigned1, v2);
1176               /*@switchbreak@*/ break;
1177             case RSH:
1178               if (skip_evaluation != 0)
1179                 {
1180                   /*@switchbreak@*/ break;
1181                 }
1182               top->unsignedp = unsigned1;
1183               if (v2 < 0 && ! unsigned2)
1184                 top->value = left_shift (pfile, v1, unsigned1, -v2);
1185               else
1186                 top->value = right_shift (v1, unsigned1, v2);
1187               /*@switchbreak@*/ break;
1188
1189 /*@notfunction@*/
1190 #define LOGICAL(OP) \
1191               top->value = v1 OP v2;\
1192               top->unsignedp = unsigned1 || unsigned2;
1193
1194             case '&':  LOGICAL(&); /*@switchbreak@*/ break;
1195             case '^':  LOGICAL(^); /*@switchbreak@*/ break;
1196             case '|':  LOGICAL(|); /*@switchbreak@*/ break;
1197             case ANDAND:
1198               top->value = ((v1 != 0) && (v2 != 0)) ? 1 : 0;
1199               top->unsignedp = FALSE;
1200
1201               if (v1 == 0)
1202                 {
1203                   skip_evaluation--;
1204                 }
1205               /*@switchbreak@*/ break;
1206             case OROR:
1207               top->value = ((v1 != 0) || (v2 != 0)) ? 1 : 0;
1208               top->unsignedp = FALSE;
1209               if (v1 != 0)
1210                 {
1211                   skip_evaluation--;
1212                 }
1213               /*@switchbreak@*/ break;
1214             case ',':
1215               if (cppReader_isPedantic (pfile))
1216                 cppReader_pedwarnLit (pfile, 
1217                                 cstring_makeLiteralTemp ("comma operator in operand of `#if'"));
1218               top->value = v2;
1219               top->unsignedp = unsigned2;
1220               /*@switchbreak@*/ break;
1221             case '(':  case '?':
1222               cppReader_errorLit (pfile, 
1223                                   cstring_makeLiteralTemp ("syntax error in #if"));
1224               goto syntax_error;
1225             case ':':
1226               if (top[0].op != '?')
1227                 {
1228                   cppReader_errorLit (pfile,
1229                                       cstring_makeLiteralTemp ("syntax error ':' without preceding '?'"));
1230                   goto syntax_error;
1231                 }
1232               else if (((top[1].flags & HAVE_VALUE) == 0)
1233                        || ((top[-1].flags & HAVE_VALUE) == 0)
1234                        || ((top[0].flags & HAVE_VALUE) == 0))
1235                 {
1236                   cppReader_errorLit (pfile, 
1237                                       cstring_makeLiteralTemp ("bad syntax for ?: operator"));
1238                   goto syntax_error;
1239                 }
1240               else
1241                 {
1242                   top--;
1243                   if (top->value != 0)
1244                     {
1245                       skip_evaluation--;
1246                     }
1247
1248                   top->value = (top->value != 0) ? v1 : v2;
1249                   top->unsignedp = unsigned1 || unsigned2;
1250                 }
1251               /*@switchbreak@*/ break;
1252             case ')':
1253               if (((top[1].flags & HAVE_VALUE) != 0)
1254                   || ((top[0].flags & HAVE_VALUE) == 0)
1255                   || top[0].op != '('
1256                   || ((top[-1].flags & HAVE_VALUE) != 0))
1257                 {
1258                   cppReader_errorLit (pfile, 
1259                                       cstring_makeLiteralTemp ("mismatched parentheses in #if"));
1260                   goto syntax_error;
1261                 }
1262               else
1263                 {
1264                   top--;
1265                   top->value = v1;
1266                   top->unsignedp = unsigned1;
1267                   top->flags |= HAVE_VALUE;
1268                 }
1269               /*@switchbreak@*/ break;
1270             default:
1271               /*@-formatconst@*/
1272               fprintf (stderr,
1273                        top[1].op >= ' ' && top[1].op <= '~'
1274                        ? "unimplemented operator '%c'\n"
1275                        : "unimplemented operator '\\%03o'\n",
1276                        top[1].op);
1277               /*@=formatconst@*/
1278             }
1279         }
1280       if (op.op == 0)
1281         {
1282           long val;
1283
1284           if (top != stack)
1285             {
1286               cppReader_errorLit (pfile, 
1287                                   cstring_makeLiteralTemp ("internal error in #if expression"));
1288             }
1289
1290           val = top->value;
1291
1292           if (stack != init_stack)
1293             {
1294               sfree (stack);
1295               /*@-branchstate@*/
1296             } /*@=branchstate@*/
1297
1298           return val;
1299         }
1300       top++;
1301       
1302       /* Check for and handle stack overflow.  */
1303       if (top == limit)
1304         {
1305           struct operation *new_stack;
1306           int old_size = (char *) limit - (char *) stack;
1307           size_t new_size = size_fromInt (2 * old_size);
1308
1309           if (stack != init_stack)
1310             {
1311               new_stack = (struct operation *) drealloc ((char *) stack,
1312                                                          new_size);
1313             }
1314           else
1315             {
1316               new_stack = (struct operation *) dmalloc (new_size);
1317
1318               /* Bug: the parameters were in the wrong order! */
1319               memcpy ((char *) new_stack, (char *) stack, old_size);
1320               /*@-branchstate@*/
1321             } /*@=branchstate@*/
1322
1323           stack = new_stack;
1324           top = (struct operation *) ((char *) new_stack + old_size);
1325           limit = (struct operation *) ((char *) new_stack + new_size);
1326           /*@-branchstate@*/ 
1327         } /*@=branchstate@*/ 
1328       
1329       top->flags = flags;
1330       top->rprio = rprio;
1331       top->op = op.op;
1332       if ((op.op == OROR && (top[-1].value != 0))
1333           || (op.op == ANDAND && (top[-1].value == 0))
1334           || (op.op == '?' && (top[-1].value == 0)))
1335         {
1336           skip_evaluation++;
1337         }
1338       else if (op.op == ':')
1339         {
1340           if (top[-2].value != 0) /* Was condition true? */
1341             {
1342               skip_evaluation++;
1343             }
1344           else
1345             {
1346               skip_evaluation--;
1347             }
1348         }
1349       else
1350         {
1351           ;
1352         }
1353     }
1354  syntax_error:
1355   /*@-usereleased@*/
1356   if (stack != init_stack)
1357     {
1358       sfree (stack);
1359       /*@-branchstate@*/
1360     } /*@=branchstate@*/
1361   /*@=usereleased@*/
1362
1363   cppReader_skipRestOfLine (pfile);
1364   return 0;
1365 }
This page took 2.078258 seconds and 5 git commands to generate.