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