#include <string.h>#include "lclintMacros.nf"#include "llbasic.h"#include "cpp.h"#include "cpplib.h"#include "cpphash.h"#include "cppexp.h"#include "cpperror.h"#include <stdio.h>Go to the source code of this file.
Compounds | |
| struct | operation |
| struct | token |
Defines | |
| #define | possibleSumSign(a, b, sum) ((((a) ^ (b)) | ~ ((a) ^ (sum))) < 0) |
| #define | BITS_PER_UNIT 8 |
| #define | BITS_PER_CHAR 8 |
| #define | BITS_PER_WORD 32 |
| #define | HOST_BITS_PER_INT 32 |
| #define | HOST_BITS_PER_LONG 32 |
| #define | TARGET_BELL (char) 6 |
| #define | TARGET_BS (char) 7 |
| #define | TARGET_FF (char) 8 |
| #define | TARGET_NEWLINE '\n' |
| #define | TARGET_CR '\n' |
| #define | TARGET_TAB '\t' |
| #define | TARGET_VT '\v' |
| #define | INT_TYPE_SIZE BITS_PER_WORD |
| #define | LONG_TYPE_SIZE BITS_PER_WORD |
| #define | WCHAR_TYPE_SIZE INT_TYPE_SIZE |
| #define | CHAR_TYPE_SIZE BITS_PER_CHAR |
| #define | MAX_CHAR_TYPE_SIZE CHAR_TYPE_SIZE |
| #define | MAX_LONG_TYPE_SIZE LONG_TYPE_SIZE |
| #define | MAX_WCHAR_TYPE_SIZE WCHAR_TYPE_SIZE |
| #define | CPPREADER_ERRORTOK 299 |
| #define | OROR 300 |
| #define | ANDAND 301 |
| #define | CPP_EQUALTOK 302 |
| #define | NOTEQUAL 303 |
| #define | LEQ 304 |
| #define | GEQ 305 |
| #define | LSH 306 |
| #define | RSH 307 |
| #define | NAME 308 |
| #define | CPPEXP_INT 309 |
| #define | CPPEXP_CHAR 310 |
| #define | LEFT_OPERAND_REQUIRED 1 |
| #define | RIGHT_OPERAND_REQUIRED 2 |
| #define | HAVE_VALUE 4 |
| #define | HOST_BITS_PER_WIDE_INT HOST_BITS_PER_INT |
| #define | HOST_WIDE_INT long |
| #define | PAREN_INNER_PRIO 0 |
| #define | COMMA_PRIO 4 |
| #define | COND_PRIO (COMMA_PRIO+2) |
| #define | OROR_PRIO (COND_PRIO+2) |
| #define | ANDAND_PRIO (OROR_PRIO+2) |
| #define | OR_PRIO (ANDAND_PRIO+2) |
| #define | XOR_PRIO (OR_PRIO+2) |
| #define | AND_PRIO (XOR_PRIO+2) |
| #define | CPP_EQUAL_PRIO (AND_PRIO+2) |
| #define | LESS_PRIO (CPP_EQUAL_PRIO+2) |
| #define | SHIFT_PRIO (LESS_PRIO+2) |
| #define | PLUS_PRIO (SHIFT_PRIO+2) |
| #define | MUL_PRIO (PLUS_PRIO+2) |
| #define | UNARY_PRIO (MUL_PRIO+2) |
| #define | PAREN_OUTER_PRIO (UNARY_PRIO+2) |
| #define | COMPARE(OP) |
| #define | INIT_STACK_SIZE 20 |
| #define | LOGICAL(OP) |
Functions | |
| struct operation | cppReader_parseNumber (cppReader *pfile, char *start, int olen) |
| int | cppReader_parseEscape (cppReader *pfile, char **string_ptr) |
| HOST_WIDE_INT | cppReader_parseExpression (cppReader *pfile) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Initializer: \
top->unsignedp = FALSE;\
top->value = ((unsigned1 || unsigned2) \
? (unsigned long) v1 OP (unsigned long) v2 \
: ((long) v1 OP (long) v2)) ? 1 : 0Definition at line 866 of file cppexp.c. Referenced by cppReader_parseExpression(). |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Initializer: \
top->value = v1 OP v2;\
top->unsignedp = unsigned1 || unsigned2;Referenced by cppReader_parseExpression(). |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Definition at line 74 of file cppexp.c. Referenced by cppReader_parseExpression(). |
|
|
Definition at line 653 of file cppexp.c. 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 /*@loopbreak@*/ 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 /*@loopbreak@*/ 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 }
|
|
|
Definition at line 879 of file cppexp.c. 00880 {
00881 /* The implementation is an operator precedence parser,
00882 i.e. a bottom-up parser, using a stack for not-yet-reduced tokens.
00883
00884 The stack base is 'stack', and the current stack pointer is 'top'.
00885 There is a stack element for each operator (only),
00886 and the most recently pushed operator is 'top->op'.
00887 An operand (value) is stored in the 'value' field of the stack
00888 element of the operator that precedes it.
00889 In that case the 'flags' field has the HAVE_VALUE flag set. */
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 /* Read a token */
00907 op = cppReader_lex (pfile);
00908
00909 /* See if the token is an operand, in which case go to set_value.
00910 If the token is an operator, figure out its left and right
00911 priorities, and then goto maybe_reduce. */
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 /* Is this correct if unary ? FIXME */
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 /* Push a value onto the stack. */
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 /* Push an operator, and check if we can reduce now. */
00984 while (top->rprio > lprio)
00985 {
00986 /*@-usedef@*/
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 /* top[0].value = (top[1].op)(v1, v2);*/
01008 switch (top[1].op)
01009 {
01010 case '+':
01011 if ((top->flags & HAVE_VALUE) == 0)
01012 { /* Unary '+' */
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 /*@switchbreak@*/ break;
01026 case '-':
01027 if ((top->flags & HAVE_VALUE) == 0)
01028 { /* Unary '-' */
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 { /* Binary '-' */
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 /*@switchbreak@*/ 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 /*@switchbreak@*/ break;
01070 case '/':
01071 if (skip_evaluation != 0)
01072 /*@switchbreak@*/ 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 /*@switchbreak@*/ break;
01089 case '%':
01090 if (skip_evaluation != 0)
01091 /*@switchbreak@*/ 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 /*@switchbreak@*/ 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 /*@switchbreak@*/ 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 /*@switchbreak@*/ break;
01127 case '<': COMPARE(<); /*@switchbreak@*/ break;
01128 case '>': COMPARE(>); /*@switchbreak@*/ break;
01129 case LEQ: COMPARE(<=); /*@switchbreak@*/ break;
01130 case GEQ: COMPARE(>=); /*@switchbreak@*/ break;
01131 case CPP_EQUALTOK:
01132 top->value = (v1 == v2) ? 1 : 0;
01133 top->unsignedp = FALSE;
01134 /*@switchbreak@*/ break;
01135 case NOTEQUAL:
01136 top->value = (v1 != v2) ? 1 : 0;
01137 top->unsignedp = FALSE;
01138 /*@switchbreak@*/ break;
01139 case LSH:
01140 if (skip_evaluation != 0)
01141 {
01142 /*@switchbreak@*/ 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 /*@switchbreak@*/ break;
01151 case RSH:
01152 if (skip_evaluation != 0)
01153 {
01154 /*@switchbreak@*/ 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 /*@switchbreak@*/ break;
01162
01163 /*@notfunction@*/
01164 #define LOGICAL(OP) \
01165 top->value = v1 OP v2;\
01166 top->unsignedp = unsigned1 || unsigned2;
01167
01168 case '&': LOGICAL(&); /*@switchbreak@*/ break;
01169 case '^': LOGICAL(^); /*@switchbreak@*/ break;
01170 case '|': LOGICAL(|); /*@switchbreak@*/ 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 /*@switchbreak@*/ 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 /*@switchbreak@*/ 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 /*@switchbreak@*/ 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 /*@switchbreak@*/ 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 /*@switchbreak@*/ 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 /*@-branchstate@*/
01268 } /*@=branchstate@*/
01269
01270 return val;
01271 }
01272 top++;
01273
01274 /* Check for and handle stack overflow. */
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 /* Bug: the parameters were in the wrong order! */
01291 memcpy ((char *) new_stack, (char *) stack, old_size);
01292 /*@-branchstate@*/
01293 } /*@=branchstate@*/
01294
01295 stack = new_stack;
01296 top = (struct operation *) ((char *) new_stack + old_size);
01297 limit = (struct operation *) ((char *) new_stack + new_size);
01298 /*@-branchstate@*/
01299 } /*@=branchstate@*/
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) /* Was condition true? */
01313 {
01314 skip_evaluation++;
01315 }
01316 else
01317 {
01318 skip_evaluation--;
01319 }
01320 }
01321 else
01322 {
01323 ;
01324 }
01325 }
01326 syntax_error:
01327 /*@-usereleased@*/
01328 if (stack != init_stack)
01329 {
01330 sfree (stack);
01331 /*@-branchstate@*/
01332 } /*@=branchstate@*/
01333 /*@=usereleased@*/
01334
01335 cppReader_skipRestOfLine (pfile);
01336 return 0;
01337 }
|
|
|
Definition at line 243 of file cppexp.c. 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 /* It's a float since it contains a point. */
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 /* Some buggy compilers (e.g. MPW C) seem to need both casts. */
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 /* `l' means long, and `u' means unsigned. */
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 /*@innerbreak@*/ break;
00328 }
00329
00330 if (--len == 0)
00331 {
00332 /*@innerbreak@*/ break;
00333 }
00334
00335 c = *p++;
00336 }
00337 /* Don't look for any more digits after the suffixes. */
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 /* If too big to be signed, consider it unsigned. */
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 }
|
1.2.3 written by Dimitri van Heesch,
© 1997-2000