00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 # include <string.h>
00060 # include "lclintMacros.nf"
00061 # include "llbasic.h"
00062 # include "cpp.h"
00063 # include "cpplib.h"
00064 # include "cpphash.h"
00065 # include "cppexp.h"
00066 # include "cpperror.h"
00067
00068
00069
00070
00071
00072
00073
00074 #define possibleSumSign(a, b, sum) ((((a) ^ (b)) | ~ ((a) ^ (sum))) < 0)
00075
00076
00077
00078
00079 # define BITS_PER_UNIT 8
00080
00081
00082 # define BITS_PER_CHAR 8
00083
00084
00085 # define BITS_PER_WORD 32
00086
00087
00088 # define HOST_BITS_PER_INT 32
00089
00090
00091 # define HOST_BITS_PER_LONG 32
00092
00093
00094 # define TARGET_BELL (char) 6
00095
00096
00097 # define TARGET_BS (char) 7
00098
00099
00100 # define TARGET_FF (char) 8
00101
00102
00103 # define TARGET_NEWLINE '\n'
00104
00105
00106 # define TARGET_CR '\n'
00107
00108
00109 # define TARGET_TAB '\t'
00110
00111
00112 # define TARGET_VT '\v'
00113
00114 #ifdef MULTIBYTE_CHARS
00115 #include <stdlib.h>
00116 #include <locale.h>
00117 #endif
00118
00119 #include <stdio.h>
00120
00121 #ifndef INT_TYPE_SIZE
00122
00123 #define INT_TYPE_SIZE BITS_PER_WORD
00124 #endif
00125
00126 #ifndef LONG_TYPE_SIZE
00127
00128 #define LONG_TYPE_SIZE BITS_PER_WORD
00129 #endif
00130
00131 #ifndef WCHAR_TYPE_SIZE
00132
00133 #define WCHAR_TYPE_SIZE INT_TYPE_SIZE
00134 #endif
00135
00136 # ifndef CHAR_TYPE_SIZE
00137
00138 # define CHAR_TYPE_SIZE BITS_PER_CHAR
00139 # endif
00140
00141 #ifndef MAX_CHAR_TYPE_SIZE
00142
00143 #define MAX_CHAR_TYPE_SIZE CHAR_TYPE_SIZE
00144 #endif
00145
00146 #ifndef MAX_LONG_TYPE_SIZE
00147
00148 #define MAX_LONG_TYPE_SIZE LONG_TYPE_SIZE
00149 #endif
00150
00151 #ifndef MAX_WCHAR_TYPE_SIZE
00152
00153 #define MAX_WCHAR_TYPE_SIZE WCHAR_TYPE_SIZE
00154 #endif
00155
00156 static struct operation cppReader_lex (cppReader *);
00157 static void integer_overflow (cppReader *);
00158 static long left_shift (cppReader *, long, bool p_unsignedp, size_t);
00159 static long right_shift (long, bool p_unsignedp, unsigned long);
00160
00161
00162 #define CPPREADER_ERRORTOK 299
00163
00164
00165 #define OROR 300
00166
00167
00168 #define ANDAND 301
00169
00170
00171 #define CPP_EQUALTOK 302
00172
00173
00174 #define NOTEQUAL 303
00175
00176
00177 #define LEQ 304
00178
00179
00180 #define GEQ 305
00181
00182
00183 #define LSH 306
00184
00185
00186 #define RSH 307
00187
00188
00189 #define NAME 308
00190
00191
00192 #define CPPEXP_INT 309
00193
00194
00195 #define CPPEXP_CHAR 310
00196
00197
00198 #define LEFT_OPERAND_REQUIRED 1
00199
00200
00201 #define RIGHT_OPERAND_REQUIRED 2
00202
00203
00204 #define HAVE_VALUE 4
00205
00206 #ifndef HOST_BITS_PER_WIDE_INT
00207
00208 #if HOST_BITS_PER_LONG > HOST_BITS_PER_INT
00209
00210 #define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_LONG
00211
00212 #define HOST_WIDE_INT long
00213 #else
00214
00215 #define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_INT
00216
00217 #define HOST_WIDE_INT long
00218 #endif
00219
00220 #endif
00221
00222 struct operation {
00223 short op;
00224
00225
00226 char rprio;
00227
00228 char flags;
00229
00230
00231 bool unsignedp;
00232
00233
00234 HOST_WIDE_INT value;
00235 } ;
00236
00237
00238
00239
00240
00241
00242 struct operation
00243 cppReader_parseNumber (cppReader *pfile, char *start, int olen)
00244 {
00245 struct operation op;
00246 char *p = start;
00247 char c;
00248 int i;
00249 long n = 0;
00250 unsigned long nd, ULONG_MAX_over_base;
00251 int base = 10;
00252 int len = olen;
00253 bool overflow = FALSE;
00254 int digit, largest_digit = 0;
00255 bool spec_long = FALSE;
00256
00257 op.unsignedp = FALSE;
00258
00259 for (i = 0; i < len; i++)
00260 {
00261 if (p[i] == '.') {
00262
00263 cppReader_errorLit
00264 (pfile,
00265 cstring_makeLiteralTemp
00266 ("Floating point numbers not allowed in #if expressions"));
00267 op.op = CPPREADER_ERRORTOK;
00268 return op;
00269 }
00270 }
00271
00272 if (len >= 3 && (mstring_equalPrefix (p, "0x")
00273 || mstring_equalPrefix (p, "0X")))
00274 {
00275 p += 2;
00276 base = 16;
00277 len -= 2;
00278 }
00279 else if (*p == '0')
00280 {
00281 base = 8;
00282 }
00283 else
00284 {
00285 ;
00286 }
00287
00288
00289 ULONG_MAX_over_base = ((unsigned long) -1) / ((unsigned long) base);
00290
00291 for (; len > 0; len--) {
00292 c = *p++;
00293
00294 if (c >= '0' && c <= '9')
00295 {
00296 digit = (int) (c - '0');
00297 }
00298 else if (base == 16 && c >= 'a' && c <= 'f')
00299 {
00300 digit = (int) (c - 'a') + 10;
00301 }
00302 else if (base == 16 && c >= 'A' && c <= 'F')
00303 {
00304 digit = (int) (c - 'A') + 10;
00305 }
00306 else
00307 {
00308
00309 while (TRUE)
00310 {
00311 if (c == 'l' || c == 'L')
00312 {
00313 if (spec_long)
00314 cppReader_errorLit (pfile,
00315 cstring_makeLiteralTemp ("two `l's in integer constant"));
00316 spec_long = TRUE;
00317 }
00318 else if (c == 'u' || c == 'U')
00319 {
00320 if (op.unsignedp)
00321 cppReader_errorLit (pfile,
00322 cstring_makeLiteralTemp ("two `u's in integer constant"));
00323 op.unsignedp = TRUE;
00324 }
00325 else
00326 {
00327 break;
00328 }
00329
00330 if (--len == 0)
00331 {
00332 break;
00333 }
00334
00335 c = *p++;
00336 }
00337
00338 break;
00339 }
00340
00341 if (largest_digit < digit)
00342 {
00343 largest_digit = digit;
00344 }
00345
00346 nd = (long unsigned) (n * base + digit);
00347 overflow |= (ULONG_MAX_over_base < (unsigned long) n)
00348 | (nd < (unsigned long) n);
00349 n = (long) nd;
00350 }
00351
00352 if (len != 0)
00353 {
00354 cppReader_errorLit
00355 (pfile,
00356 cstring_makeLiteralTemp ("Invalid number in #if expression"));
00357 op.op = CPPREADER_ERRORTOK;
00358 return op;
00359 }
00360
00361 if (base <= largest_digit)
00362 {
00363 cppReader_pedwarnLit
00364 (pfile,
00365 cstring_makeLiteralTemp
00366 ("Integer constant contains digits beyond the radix"));
00367 }
00368
00369 if (overflow)
00370 {
00371 cppReader_pedwarnLit
00372 (pfile,
00373 cstring_makeLiteralTemp ("Integer constant out of range"));
00374 }
00375
00376
00377 if ((long) n < 0 && ! op.unsignedp)
00378 {
00379 if (base == 10)
00380 {
00381 cppReader_warningLit
00382 (pfile,
00383 cstring_makeLiteralTemp ("Integer constant is so large that it is unsigned"));
00384 }
00385
00386 op.unsignedp = TRUE;
00387 }
00388
00389 op.value = n;
00390 op.op = CPPEXP_INT;
00391 return op;
00392 }
00393
00394 struct token {
00395 char *operator;
00396 int token;
00397 };
00398
00399 static struct token tokentab2[] = {
00400 { "&&", ANDAND },
00401 { "||", OROR },
00402 { "<<", LSH },
00403 { ">>", RSH },
00404 { "==", CPP_EQUALTOK },
00405 { "!=", NOTEQUAL },
00406 { "<=", LEQ },
00407 { ">=", GEQ },
00408 { "++", CPPREADER_ERRORTOK },
00409 { "--", CPPREADER_ERRORTOK },
00410 { NULL, CPPREADER_ERRORTOK }
00411 } ;
00412
00413
00414
00415 struct operation cppReader_lex (cppReader *pfile)
00416 {
00417 int ic;
00418 char c;
00419 register struct token *toktab;
00420 enum cpp_token token;
00421 struct operation op;
00422 char *tok_start, *tok_end;
00423 int old_written;
00424
00425 retry:
00426
00427 old_written = size_toInt (cppReader_getWritten (pfile));
00428 cppSkipHspace (pfile);
00429 ic = cppBufPeek (cppReader_getBufferSafe (pfile));
00430
00431 c = (char) ic;
00432 llassert (c != '#');
00433
00434 if (c == '\n')
00435 {
00436 op.op = 0;
00437 return op;
00438 }
00439
00440 token = cppGetToken (pfile);
00441 tok_start = pfile->token_buffer + old_written;
00442 tok_end = cppReader_getPWritten (pfile);
00443 pfile->limit = tok_start;
00444
00445 switch (token)
00446 {
00447 case CPP_EOF:
00448 case CPP_VSPACE:
00449 op.op = 0;
00450 return op;
00451 case CPP_POP:
00452 if (cstring_isDefined (cppReader_getBufferSafe (pfile)->fname))
00453 {
00454 op.op = 0;
00455 return op;
00456 }
00457 (void) cppReader_popBuffer (pfile);
00458 goto retry;
00459 case CPP_HSPACE: case CPP_COMMENT:
00460 goto retry;
00461 case CPP_NUMBER:
00462 return cppReader_parseNumber (pfile, tok_start, tok_end - tok_start);
00463 case CPP_STRING:
00464 cppReader_errorLit (pfile,
00465 cstring_makeLiteralTemp ("string constants not allowed in #if expressions"));
00466 op.op = CPPREADER_ERRORTOK;
00467 return op;
00468 case CPP_CHAR:
00469
00470
00471
00472 {
00473 int result = 0;
00474 int num_chars = 0;
00475 size_t width = MAX_CHAR_TYPE_SIZE;
00476 int wide_flag = 0;
00477 int max_chars;
00478 char *ptr = tok_start;
00479 #ifdef MULTIBYTE_CHARS
00480 char token_buffer[MAX_LONG_TYPE_SIZE/MAX_CHAR_TYPE_SIZE + MB_CUR_MAX];
00481 #else
00482 char token_buffer[MAX_LONG_TYPE_SIZE/MAX_CHAR_TYPE_SIZE + 1];
00483 #endif
00484
00485 if (*ptr == 'L')
00486 {
00487 ptr++;
00488 wide_flag = 1;
00489 width = MAX_WCHAR_TYPE_SIZE;
00490 #ifdef MULTIBYTE_CHARS
00491 max_chars = MB_CUR_MAX;
00492 #else
00493 max_chars = 1;
00494 #endif
00495 }
00496 else
00497 {
00498 max_chars = size_toInt (MAX_LONG_TYPE_SIZE / width);
00499 }
00500
00501 ++ptr;
00502 while (ptr < tok_end && ((c = *ptr++) != '\''))
00503 {
00504 if (c == '\\')
00505 {
00506 c = cppReader_parseEscape (pfile, &ptr);
00507 if (width < HOST_BITS_PER_INT && c >= (1 << width))
00508 {
00509 cppReader_pedwarnLit
00510 (pfile,
00511 cstring_makeLiteralTemp ("Escape sequence out of range for character"));
00512 }
00513 }
00514
00515 num_chars++;
00516
00517
00518 if (num_chars < max_chars + 1)
00519 {
00520 if (width < HOST_BITS_PER_INT)
00521 {
00522 result = (int) ((unsigned) result << width) | (c & ((1 << width) - 1));
00523 }
00524 else
00525 {
00526 result = c;
00527 }
00528
00529 token_buffer[num_chars - 1] = c;
00530 }
00531 }
00532
00533 token_buffer[num_chars] = 0;
00534
00535 if (c != '\'')
00536 cppReader_errorLit (pfile,
00537 cstring_makeLiteralTemp ("malformatted character constant"));
00538 else if (num_chars == 0)
00539 cppReader_errorLit (pfile,
00540 cstring_makeLiteralTemp ("empty character constant"));
00541 else if (num_chars > max_chars)
00542 {
00543 num_chars = max_chars;
00544 cppReader_errorLit (pfile,
00545 cstring_makeLiteralTemp ("character constant too long"));
00546 }
00547 else if (num_chars != 1 && ! cppReader_isTraditional (pfile))
00548 {
00549 cppReader_warningLit (pfile,
00550 cstring_makeLiteralTemp ("multi-character character constant"));
00551 }
00552 else
00553 {
00554 ;
00555 }
00556
00557
00558 if (wide_flag == 0)
00559 {
00560 int num_bits = num_chars * width;
00561
00562 if ((cppReader_lookup ("__CHAR_UNSIGNED__",
00563 sizeof ("__CHAR_UNSIGNED__") - 1, -1) != NULL)
00564 || (((unsigned) result >> (num_bits - 1)) & 1) == 0)
00565 {
00566 op.value
00567 = result & ((unsigned long) ~0 >> (HOST_BITS_PER_LONG - num_bits));
00568 }
00569 else
00570 {
00571 op.value
00572 = result | ~((unsigned long) ~0 >> (HOST_BITS_PER_LONG - num_bits));
00573 }
00574 }
00575 else
00576 {
00577 #ifdef MULTIBYTE_CHARS
00578
00579 result = 0;
00580
00581
00582 if (num_chars > 1
00583 || (num_chars == 1 && token_buffer[0] != '\0'))
00584 {
00585 wchar_t wc;
00586 (void) mbtowc (NULL, NULL, 0);
00587 if (mbtowc (& wc, token_buffer, num_chars) == num_chars)
00588 result = wc;
00589 else
00590 cppReader_pedwarn (pfile,"Ignoring invalid multibyte character");
00591 }
00592 #endif
00593 op.value = result;
00594 }
00595 }
00596
00597
00598 op.unsignedp = FALSE;
00599 op.op = CPPEXP_CHAR;
00600
00601 return op;
00602
00603 case CPP_NAME:
00604 return cppReader_parseNumber (pfile, "0", 0);
00605
00606 case CPP_OTHER:
00607
00608 if (tok_start + 2 == tok_end)
00609 {
00610 for (toktab = tokentab2; toktab->operator != NULL; toktab++)
00611 {
00612 if (tok_start[0] == toktab->operator[0]
00613 && tok_start[1] == toktab->operator[1])
00614 {
00615 break;
00616 }
00617 }
00618
00619 if (toktab->token == CPPREADER_ERRORTOK)
00620 {
00621 cppReader_error (pfile, message ("`%s' not allowed in operand of `#if'", cstring_fromChars (tok_start)));
00622 }
00623
00624 op.op = toktab->token;
00625 return op;
00626 }
00627
00628 default:
00629 op.op = *tok_start;
00630 return op;
00631 }
00632
00633 BADEXIT;
00634
00635 }
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652 int
00653 cppReader_parseEscape (cppReader *pfile, char **string_ptr)
00654 {
00655 char c = *(*string_ptr)++;
00656
00657 switch (c)
00658 {
00659 case 'a':
00660 return TARGET_BELL;
00661 case 'b':
00662 return TARGET_BS;
00663 case 'e':
00664 case 'E':
00665 if (cppReader_isPedantic (pfile))
00666 {
00667 cppReader_pedwarn (pfile,
00668 message ("non-ANSI-standard escape sequence, `\\%c'", c));
00669 }
00670 return (char) 033;
00671 case 'f':
00672 return TARGET_FF;
00673 case 'n':
00674 return TARGET_NEWLINE;
00675 case 'r':
00676 return TARGET_CR;
00677 case 't':
00678 return TARGET_TAB;
00679 case 'v':
00680 return TARGET_VT;
00681 case '\n':
00682 return -2;
00683 case 0:
00684 (*string_ptr)--;
00685 return 0;
00686
00687 case '0':
00688 case '1':
00689 case '2':
00690 case '3':
00691 case '4':
00692 case '5':
00693 case '6':
00694 case '7':
00695 {
00696 int i = (int) c - '0';
00697 int count = 0;
00698
00699 while (++count < 3)
00700 {
00701 c = *(*string_ptr)++;
00702 if (c >= '0' && c <= '7')
00703 {
00704 i = ((unsigned) i << 3) + c - '0';
00705 }
00706
00707 else
00708 {
00709 (*string_ptr)--;
00710 break;
00711 }
00712 }
00713 if ((i & ~((1 << MAX_CHAR_TYPE_SIZE) - 1)) != 0)
00714 {
00715 i &= (1 << MAX_CHAR_TYPE_SIZE) - 1;
00716 cppReader_pedwarnLit (pfile,
00717 cstring_makeLiteralTemp ("octal character constant does not fit in a byte"));
00718 }
00719 return i;
00720 }
00721 case 'x':
00722 {
00723 register unsigned i = 0, overflow = 0, digits_found = 0, digit;
00724 for (;;)
00725 {
00726 c = *(*string_ptr)++;
00727
00728 if (c >= '0' && c <= '9')
00729 {
00730 digit = (unsigned int) (c - '0');
00731 }
00732 else if (c >= 'a' && c <= 'f')
00733 {
00734 digit = (unsigned int) (c - 'a') + 10;
00735 }
00736 else if (c >= 'A' && c <= 'F')
00737 {
00738 digit = (unsigned int) (c - 'A') + 10;
00739 }
00740 else
00741 {
00742 (*string_ptr)--;
00743 break;
00744 }
00745 overflow |= i ^ (i << 4 >> 4);
00746 i = (i << 4) + digit;
00747 digits_found = 1;
00748 }
00749
00750 if (digits_found == 0)
00751 {
00752 cppReader_errorLit (pfile,
00753 cstring_makeLiteralTemp ("\\x used with no following hex digits"));
00754 }
00755
00756 if ((overflow | (i & ~((1 << BITS_PER_UNIT) - 1))) != 0)
00757 {
00758 i &= (1 << BITS_PER_UNIT) - 1;
00759 cppReader_pedwarnLit (pfile,
00760 cstring_makeLiteralTemp ("hex character constant does not fit in a byte"));
00761 }
00762
00763 return i;
00764 }
00765 default:
00766 return c;
00767 }
00768 }
00769
00770 static void
00771 integer_overflow (cppReader *pfile)
00772 {
00773 if (cppReader_isPedantic (pfile))
00774 cppReader_pedwarnLit (pfile,
00775 cstring_makeLiteralTemp ("integer overflow in preprocessor expression"));
00776 }
00777
00778 static long
00779 left_shift (cppReader *pfile, long a, bool unsignedp, size_t b)
00780 {
00781 if (b >= HOST_BITS_PER_LONG)
00782 {
00783 if (!unsignedp && a != 0)
00784 {
00785 integer_overflow (pfile);
00786 }
00787
00788 return 0;
00789 }
00790 else if (unsignedp)
00791 {
00792 return (unsigned long) a << b;
00793 }
00794 else
00795 {
00796 long l = a << b;
00797
00798 if (l >> b != a)
00799 {
00800 integer_overflow (pfile);
00801 }
00802
00803 return l;
00804 }
00805 }
00806
00807 static long
00808 right_shift (long a, bool unsignedp, unsigned long b)
00809 {
00810 if (b >= HOST_BITS_PER_LONG)
00811 return (unsignedp ? 0 : a >> (HOST_BITS_PER_LONG - 1));
00812 else if (unsignedp)
00813 return (unsigned long) a >> b;
00814 else
00815 return a >> b;
00816 }
00817
00818
00819
00820
00821 #define PAREN_INNER_PRIO 0
00822
00823
00824 #define COMMA_PRIO 4
00825
00826
00827 #define COND_PRIO (COMMA_PRIO+2)
00828
00829
00830 #define OROR_PRIO (COND_PRIO+2)
00831
00832
00833 #define ANDAND_PRIO (OROR_PRIO+2)
00834
00835
00836 #define OR_PRIO (ANDAND_PRIO+2)
00837
00838
00839 #define XOR_PRIO (OR_PRIO+2)
00840
00841
00842 #define AND_PRIO (XOR_PRIO+2)
00843
00844
00845 #define CPP_EQUAL_PRIO (AND_PRIO+2)
00846
00847
00848 #define LESS_PRIO (CPP_EQUAL_PRIO+2)
00849
00850
00851 #define SHIFT_PRIO (LESS_PRIO+2)
00852
00853
00854 #define PLUS_PRIO (SHIFT_PRIO+2)
00855
00856
00857 #define MUL_PRIO (PLUS_PRIO+2)
00858
00859
00860 #define UNARY_PRIO (MUL_PRIO+2)
00861
00862
00863 #define PAREN_OUTER_PRIO (UNARY_PRIO+2)
00864
00865
00866 #define COMPARE(OP) \
00867 top->unsignedp = FALSE;\
00868 top->value = ((unsigned1 || unsigned2) \
00869 ? (unsigned long) v1 OP (unsigned long) v2 \
00870 : ((long) v1 OP (long) v2)) ? 1 : 0
00871
00872
00873
00874
00875
00876 # define INIT_STACK_SIZE 20
00877
00878 HOST_WIDE_INT
00879 cppReader_parseExpression (cppReader *pfile)
00880 {
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891 struct operation init_stack[INIT_STACK_SIZE];
00892 struct operation *stack = init_stack;
00893 struct operation *limit = stack + INIT_STACK_SIZE;
00894 register struct operation *top = stack;
00895 int lprio, rprio = 0;
00896 int skip_evaluation = 0;
00897
00898 top->rprio = 0;
00899 top->flags = 0;
00900
00901 for (;;)
00902 {
00903 struct operation op;
00904 int flags = 0;
00905
00906
00907 op = cppReader_lex (pfile);
00908
00909
00910
00911
00912
00913 switch (op.op)
00914 {
00915 case NAME:
00916 top->value = 0, top->unsignedp = FALSE;
00917 goto set_value;
00918 case CPPEXP_INT:
00919 case CPPEXP_CHAR:
00920 top->value = op.value;
00921 top->unsignedp = op.unsignedp;
00922 goto set_value;
00923 case 0:
00924 lprio = 0; goto maybe_reduce;
00925 case '+': case '-':
00926
00927 flags = RIGHT_OPERAND_REQUIRED;
00928 lprio = PLUS_PRIO; rprio = lprio + 1; goto maybe_reduce;
00929 case '!': case '~':
00930 flags = RIGHT_OPERAND_REQUIRED;
00931 rprio = UNARY_PRIO; lprio = rprio + 1; goto maybe_reduce;
00932 case '*': case '/': case '%':
00933 lprio = MUL_PRIO; goto binop;
00934 case '<': case '>': case LEQ: case GEQ:
00935 lprio = LESS_PRIO; goto binop;
00936 case CPP_EQUALTOK: case NOTEQUAL:
00937 lprio = CPP_EQUAL_PRIO; goto binop;
00938 case LSH: case RSH:
00939 lprio = SHIFT_PRIO; goto binop;
00940 case '&': lprio = AND_PRIO; goto binop;
00941 case '^': lprio = XOR_PRIO; goto binop;
00942 case '|': lprio = OR_PRIO; goto binop;
00943 case ANDAND: lprio = ANDAND_PRIO; goto binop;
00944 case OROR: lprio = OROR_PRIO; goto binop;
00945 case ',':
00946 lprio = COMMA_PRIO; goto binop;
00947 case '(':
00948 lprio = PAREN_OUTER_PRIO; rprio = PAREN_INNER_PRIO;
00949 goto maybe_reduce;
00950 case ')':
00951 lprio = PAREN_INNER_PRIO; rprio = PAREN_OUTER_PRIO;
00952 goto maybe_reduce;
00953 case ':':
00954 lprio = COND_PRIO; rprio = COND_PRIO;
00955 goto maybe_reduce;
00956 case '?':
00957 lprio = COND_PRIO + 1; rprio = COND_PRIO;
00958 goto maybe_reduce;
00959 binop:
00960 flags = LEFT_OPERAND_REQUIRED | RIGHT_OPERAND_REQUIRED;
00961 rprio = lprio + 1;
00962 goto maybe_reduce;
00963 default:
00964 cppReader_error
00965 (pfile,
00966 message ("Invalid character in #if: %c",
00967 (char) op.op));
00968 goto syntax_error;
00969 }
00970
00971 set_value:
00972
00973 if ((top->flags & HAVE_VALUE) != 0)
00974 {
00975 cppReader_errorLit (pfile,
00976 cstring_makeLiteralTemp ("syntax error in #if"));
00977 goto syntax_error;
00978 }
00979 top->flags |= HAVE_VALUE;
00980 continue;
00981
00982 maybe_reduce:
00983
00984 while (top->rprio > lprio)
00985 {
00986
00987 long v1 = top[-1].value, v2 = top[0].value;
00988 bool unsigned1 = top[-1].unsignedp;
00989 bool unsigned2 = top[0].unsignedp;
00990
00991 top--;
00992
00993 if (((top[1].flags & LEFT_OPERAND_REQUIRED) != 0)
00994 && ((top[0].flags & HAVE_VALUE) == 0))
00995 {
00996 cppReader_errorLit (pfile,
00997 cstring_makeLiteralTemp ("syntax error - missing left operand"));
00998 goto syntax_error;
00999 }
01000 if (((top[1].flags & RIGHT_OPERAND_REQUIRED) != 0)
01001 && ((top[1].flags & HAVE_VALUE) == 0))
01002 {
01003 cppReader_errorLit (pfile,
01004 cstring_makeLiteralTemp ("syntax error - missing right operand"));
01005 goto syntax_error;
01006 }
01007
01008 switch (top[1].op)
01009 {
01010 case '+':
01011 if ((top->flags & HAVE_VALUE) == 0)
01012 {
01013 top->value = v2;
01014 top->unsignedp = unsigned2;
01015 top->flags |= HAVE_VALUE;
01016 }
01017 else
01018 {
01019 top->value = v1 + v2;
01020 top->unsignedp = unsigned1 || unsigned2;
01021 if (!top->unsignedp && (skip_evaluation == 0)
01022 && ! possibleSumSign (v1, v2, top->value))
01023 integer_overflow (pfile);
01024 }
01025 break;
01026 case '-':
01027 if ((top->flags & HAVE_VALUE) == 0)
01028 {
01029 top->value = - v2;
01030 if ((skip_evaluation == 0)
01031 && (top->value & v2) < 0 && !unsigned2)
01032 integer_overflow (pfile);
01033 top->unsignedp = unsigned2;
01034 top->flags |= HAVE_VALUE;
01035 }
01036 else
01037 {
01038 top->value = v1 - v2;
01039 top->unsignedp = unsigned1 || unsigned2;
01040 if (!top->unsignedp && (skip_evaluation == 0)
01041 && !possibleSumSign (top->value, v2, v1))
01042 {
01043 integer_overflow (pfile);
01044 }
01045 }
01046 break;
01047 case '*':
01048 top->unsignedp = unsigned1 || unsigned2;
01049
01050 if (top->unsignedp)
01051 {
01052 top->value = (unsigned long) v1 * v2;
01053 }
01054 else if (skip_evaluation == 0)
01055 {
01056 top->value = v1 * v2;
01057 if ((v1 != 0)
01058 && (top->value / v1 != v2
01059 || (top->value & v1 & v2) < 0))
01060 {
01061 integer_overflow (pfile);
01062 }
01063 }
01064 else
01065 {
01066 ;
01067 }
01068
01069 break;
01070 case '/':
01071 if (skip_evaluation != 0)
01072 break;
01073 if (v2 == 0)
01074 {
01075 cppReader_errorLit (pfile,
01076 cstring_makeLiteralTemp ("Division by zero in #if"));
01077 v2 = 1;
01078 }
01079 top->unsignedp = unsigned1 || unsigned2;
01080 if (top->unsignedp)
01081 top->value = (unsigned long) v1 / v2;
01082 else
01083 {
01084 top->value = v1 / v2;
01085 if ((top->value & v1 & v2) < 0)
01086 integer_overflow (pfile);
01087 }
01088 break;
01089 case '%':
01090 if (skip_evaluation != 0)
01091 break;
01092 if (v2 == 0)
01093 {
01094 cppReader_errorLit (pfile,
01095 cstring_makeLiteralTemp ("Division by zero in #if"));
01096 v2 = 1;
01097 }
01098 top->unsignedp = unsigned1 || unsigned2;
01099 if (top->unsignedp)
01100 top->value = (unsigned long) v1 % v2;
01101 else
01102 top->value = v1 % v2;
01103 break;
01104 case '!':
01105 if ((top->flags & HAVE_VALUE) != 0)
01106 {
01107 cppReader_errorLit (pfile,
01108 cstring_makeLiteralTemp ("Syntax error"));
01109 goto syntax_error;
01110 }
01111
01112 top->value = (v2 == 0) ? 1 : 0;
01113 top->unsignedp = FALSE;
01114 top->flags |= HAVE_VALUE;
01115 break;
01116 case '~':
01117 if ((top->flags & HAVE_VALUE) != 0)
01118 {
01119 cppReader_errorLit (pfile,
01120 cstring_makeLiteralTemp ("syntax error"));
01121 goto syntax_error;
01122 }
01123 top->value = ~ v2;
01124 top->unsignedp = unsigned2;
01125 top->flags |= HAVE_VALUE;
01126 break;
01127 case '<': COMPARE(<); break;
01128 case '>': COMPARE(>); break;
01129 case LEQ: COMPARE(<=); break;
01130 case GEQ: COMPARE(>=); break;
01131 case CPP_EQUALTOK:
01132 top->value = (v1 == v2) ? 1 : 0;
01133 top->unsignedp = FALSE;
01134 break;
01135 case NOTEQUAL:
01136 top->value = (v1 != v2) ? 1 : 0;
01137 top->unsignedp = FALSE;
01138 break;
01139 case LSH:
01140 if (skip_evaluation != 0)
01141 {
01142 break;
01143 }
01144
01145 top->unsignedp = unsigned1;
01146 if (v2 < 0 && ! unsigned2)
01147 top->value = right_shift (v1, unsigned1, -v2);
01148 else
01149 top->value = left_shift (pfile, v1, unsigned1, v2);
01150 break;
01151 case RSH:
01152 if (skip_evaluation != 0)
01153 {
01154 break;
01155 }
01156 top->unsignedp = unsigned1;
01157 if (v2 < 0 && ! unsigned2)
01158 top->value = left_shift (pfile, v1, unsigned1, -v2);
01159 else
01160 top->value = right_shift (v1, unsigned1, v2);
01161 break;
01162
01163
01164 #define LOGICAL(OP) \
01165 top->value = v1 OP v2;\
01166 top->unsignedp = unsigned1 || unsigned2;
01167
01168 case '&': LOGICAL(&); break;
01169 case '^': LOGICAL(^); break;
01170 case '|': LOGICAL(|); break;
01171 case ANDAND:
01172 top->value = ((v1 != 0) && (v2 != 0)) ? 1 : 0;
01173 top->unsignedp = FALSE;
01174
01175 if (v1 == 0)
01176 {
01177 skip_evaluation--;
01178 }
01179 break;
01180 case OROR:
01181 top->value = ((v1 != 0) || (v2 != 0)) ? 1 : 0;
01182 top->unsignedp = FALSE;
01183 if (v1 != 0)
01184 {
01185 skip_evaluation--;
01186 }
01187 break;
01188 case ',':
01189 if (cppReader_isPedantic (pfile))
01190 cppReader_pedwarnLit (pfile,
01191 cstring_makeLiteralTemp ("comma operator in operand of `#if'"));
01192 top->value = v2;
01193 top->unsignedp = unsigned2;
01194 break;
01195 case '(': case '?':
01196 cppReader_errorLit (pfile,
01197 cstring_makeLiteralTemp ("syntax error in #if"));
01198 goto syntax_error;
01199 case ':':
01200 if (top[0].op != '?')
01201 {
01202 cppReader_errorLit (pfile,
01203 cstring_makeLiteralTemp ("syntax error ':' without preceding '?'"));
01204 goto syntax_error;
01205 }
01206 else if (((top[1].flags & HAVE_VALUE) == 0)
01207 || ((top[-1].flags & HAVE_VALUE) == 0)
01208 || ((top[0].flags & HAVE_VALUE) == 0))
01209 {
01210 cppReader_errorLit (pfile,
01211 cstring_makeLiteralTemp ("bad syntax for ?: operator"));
01212 goto syntax_error;
01213 }
01214 else
01215 {
01216 top--;
01217 if (top->value != 0)
01218 {
01219 skip_evaluation--;
01220 }
01221
01222 top->value = (top->value != 0) ? v1 : v2;
01223 top->unsignedp = unsigned1 || unsigned2;
01224 }
01225 break;
01226 case ')':
01227 if (((top[1].flags & HAVE_VALUE) != 0)
01228 || ((top[0].flags & HAVE_VALUE) == 0)
01229 || top[0].op != '('
01230 || ((top[-1].flags & HAVE_VALUE) != 0))
01231 {
01232 cppReader_errorLit (pfile,
01233 cstring_makeLiteralTemp ("mismatched parentheses in #if"));
01234 goto syntax_error;
01235 }
01236 else
01237 {
01238 top--;
01239 top->value = v1;
01240 top->unsignedp = unsigned1;
01241 top->flags |= HAVE_VALUE;
01242 }
01243 break;
01244 default:
01245 fprintf (stderr,
01246 top[1].op >= ' ' && top[1].op <= '~'
01247 ? "unimplemented operator '%c'\n"
01248 : "unimplemented operator '\\%03o'\n",
01249 top[1].op);
01250 }
01251 }
01252 if (op.op == 0)
01253 {
01254 long val;
01255
01256 if (top != stack)
01257 {
01258 cppReader_errorLit (pfile,
01259 cstring_makeLiteralTemp ("internal error in #if expression"));
01260 }
01261
01262 val = top->value;
01263
01264 if (stack != init_stack)
01265 {
01266 sfree (stack);
01267
01268 }
01269
01270 return val;
01271 }
01272 top++;
01273
01274
01275 if (top == limit)
01276 {
01277 struct operation *new_stack;
01278 int old_size = (char *) limit - (char *) stack;
01279 size_t new_size = size_fromInt (2 * old_size);
01280
01281 if (stack != init_stack)
01282 {
01283 new_stack = (struct operation *) drealloc ((char *) stack,
01284 new_size);
01285 }
01286 else
01287 {
01288 new_stack = (struct operation *) dmalloc (new_size);
01289
01290
01291 memcpy ((char *) new_stack, (char *) stack, old_size);
01292
01293 }
01294
01295 stack = new_stack;
01296 top = (struct operation *) ((char *) new_stack + old_size);
01297 limit = (struct operation *) ((char *) new_stack + new_size);
01298
01299 }
01300
01301 top->flags = flags;
01302 top->rprio = rprio;
01303 top->op = op.op;
01304 if ((op.op == OROR && (top[-1].value != 0))
01305 || (op.op == ANDAND && (top[-1].value == 0))
01306 || (op.op == '?' && (top[-1].value == 0)))
01307 {
01308 skip_evaluation++;
01309 }
01310 else if (op.op == ':')
01311 {
01312 if (top[-2].value != 0)
01313 {
01314 skip_evaluation++;
01315 }
01316 else
01317 {
01318 skip_evaluation--;
01319 }
01320 }
01321 else
01322 {
01323 ;
01324 }
01325 }
01326 syntax_error:
01327
01328 if (stack != init_stack)
01329 {
01330 sfree (stack);
01331
01332 }
01333
01334
01335 cppReader_skipRestOfLine (pfile);
01336 return 0;
01337 }