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