📄 cppexp.c
字号:
case 'f': return TARGET_FF; case 'n': return TARGET_NEWLINE; case 'r': return TARGET_CR; case 't': return TARGET_TAB; case 'v': return TARGET_VT; case '\n': return -2; case 0: (*string_ptr)--; return 0; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': { register int i = c - '0'; register int count = 0; while (++count < 3) { c = *(*string_ptr)++; if (c >= '0' && c <= '7') i = (i << 3) + c - '0'; else { (*string_ptr)--; break; } } if ((i & ~((1 << MAX_CHAR_TYPE_SIZE) - 1)) != 0) { i &= (1 << MAX_CHAR_TYPE_SIZE) - 1; cpp_warning (pfile, "octal character constant does not fit in a byte"); } return i; } case 'x': { register unsigned i = 0, overflow = 0, digits_found = 0, digit; for (;;) { c = *(*string_ptr)++; if (c >= '0' && c <= '9') digit = c - '0'; else if (c >= 'a' && c <= 'f') digit = c - 'a' + 10; else if (c >= 'A' && c <= 'F') digit = c - 'A' + 10; else { (*string_ptr)--; break; } overflow |= i ^ (i << 4 >> 4); i = (i << 4) + digit; digits_found = 1; } if (!digits_found) cpp_error (pfile, "\\x used with no following hex digits"); if (overflow | (i & ~((1 << BITS_PER_UNIT) - 1))) { i &= (1 << BITS_PER_UNIT) - 1; cpp_warning (pfile, "hex character constant does not fit in a byte"); } return i; } default: return c; }}static voidinteger_overflow (pfile) cpp_reader *pfile;{ if (CPP_PEDANTIC (pfile)) cpp_pedwarn (pfile, "integer overflow in preprocessor expression");}static longleft_shift (pfile, a, unsignedp, b) cpp_reader *pfile; long a; int unsignedp; unsigned long b;{ if (b >= HOST_BITS_PER_LONG) { if (! unsignedp && a != 0) integer_overflow (pfile); return 0; } else if (unsignedp) return (unsigned long) a << b; else { long l = a << b; if (l >> b != a) integer_overflow (pfile); return l; }}static longright_shift (pfile, a, unsignedp, b) cpp_reader *pfile; long a; int unsignedp; unsigned long b;{ if (b >= HOST_BITS_PER_LONG) return unsignedp ? 0 : a >> (HOST_BITS_PER_LONG - 1); else if (unsignedp) return (unsigned long) a >> b; else return a >> b;}/* These priorities are all even, so we can handle associatively. */#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 EQUAL_PRIO (AND_PRIO+2)#define LESS_PRIO (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) \ top->unsignedp = 0;\ top->value = (unsigned1 || unsigned2) ? (unsigned long) v1 OP v2 : (v1 OP v2)/* Parse and evaluate a C expression, reading from PFILE. Returns the value of the expression. */HOST_WIDE_INTcpp_parse_expr (pfile) cpp_reader *pfile;{ /* The implementation is an operator precedence parser, i.e. a bottom-up parser, using a stack for not-yet-reduced tokens. The stack base is 'stack', and the current stack pointer is 'top'. There is a stack element for each operator (only), and the most recently pushed operator is 'top->op'. An operand (value) is stored in the 'value' field of the stack element of the operator that precedes it. In that case the 'flags' field has the HAVE_VALUE flag set. */#define INIT_STACK_SIZE 20 struct operation init_stack[INIT_STACK_SIZE]; struct operation *stack = init_stack; struct operation *limit = stack + INIT_STACK_SIZE; register struct operation *top = stack; int lprio, rprio; top->rprio = 0; top->flags = 0; for (;;) { struct operation op; char flags = 0; /* Read a token */ op = cpp_lex (pfile); /* See if the token is an operand, in which case go to set_value. If the token is an operator, figure out its left and right priorities, and then goto maybe_reduce. */ switch (op.op) { case NAME: top->value = 0, top->unsignedp = 0; goto set_value; case INT: case CHAR: top->value = op.value; top->unsignedp = op.unsignedp; goto set_value; case 0: lprio = 0; goto maybe_reduce; case '+': case '-': /* Is this correct if unary ? FIXME */ flags = RIGHT_OPERAND_REQUIRED; lprio = PLUS_PRIO; rprio = lprio + 1; goto maybe_reduce; case '!': case '~': flags = RIGHT_OPERAND_REQUIRED; rprio = UNARY_PRIO; lprio = rprio + 1; goto maybe_reduce; case '*': case '/': case '%': lprio = MUL_PRIO; goto binop; case '<': case '>': case LEQ: case GEQ: lprio = LESS_PRIO; goto binop; case EQUAL: case NOTEQUAL: lprio = EQUAL_PRIO; goto binop; case LSH: case RSH: lprio = SHIFT_PRIO; goto binop; case '&': lprio = AND_PRIO; goto binop; case '^': lprio = XOR_PRIO; goto binop; case '|': lprio = OR_PRIO; goto binop; case ANDAND: lprio = ANDAND_PRIO; goto binop; case OROR: lprio = OROR_PRIO; goto binop; case ',': lprio = COMMA_PRIO; goto binop; case '(': lprio = PAREN_OUTER_PRIO; rprio = PAREN_INNER_PRIO; goto maybe_reduce; case ')': lprio = PAREN_INNER_PRIO; rprio = PAREN_OUTER_PRIO; goto maybe_reduce; case ':': lprio = COND_PRIO; rprio = COND_PRIO; goto maybe_reduce; case '?': lprio = COND_PRIO + 1; rprio = COND_PRIO; goto maybe_reduce; binop: flags = LEFT_OPERAND_REQUIRED|RIGHT_OPERAND_REQUIRED; rprio = lprio + 1; goto maybe_reduce; default: cpp_error (pfile, "invalid character in #if"); goto syntax_error; } set_value: /* Push a value onto the stack. */ if (top->flags & HAVE_VALUE) { cpp_error (pfile, "syntax error in #if"); goto syntax_error; } top->flags |= HAVE_VALUE; continue; maybe_reduce: /* Push an operator, and check if we can reduce now. */ while (top->rprio > lprio) { long v1 = top[-1].value, v2 = top[0].value; int unsigned1 = top[-1].unsignedp, unsigned2 = top[0].unsignedp; top--; if ((top[1].flags & LEFT_OPERAND_REQUIRED) && ! (top[0].flags & HAVE_VALUE)) { cpp_error (pfile, "syntax error - missing left operand"); goto syntax_error; } if ((top[1].flags & RIGHT_OPERAND_REQUIRED) && ! (top[1].flags & HAVE_VALUE)) { cpp_error (pfile, "syntax error - missing right operand"); goto syntax_error; } /* top[0].value = (top[1].op)(v1, v2);*/ switch (top[1].op) { case '+': if (!(top->flags & HAVE_VALUE)) { /* Unary '+' */ top->value = v2; top->unsignedp = unsigned2; top->flags |= HAVE_VALUE; } else { top->value = v1 + v2; top->unsignedp = unsigned1 || unsigned2; if (! top->unsignedp && ! possible_sum_sign (v1, v2, top->value)) integer_overflow (pfile); } break; case '-': if (!(top->flags & HAVE_VALUE)) { /* Unary '-' */ top->value = - v2; if ((top->value & v2) < 0 && ! unsigned2) integer_overflow (pfile); top->unsignedp = unsigned2; top->flags |= HAVE_VALUE; } else { /* Binary '-' */ top->value = v1 - v2; top->unsignedp = unsigned1 || unsigned2; if (! top->unsignedp && ! possible_sum_sign (top->value, v2, v1)) integer_overflow (pfile); } break; case '*': top->unsignedp = unsigned1 || unsigned2; if (top->unsignedp) top->value = (unsigned long) v1 * v2; else { top->value = v1 * v2; if (v1 && (top->value / v1 != v2 || (top->value & v1 & v2) < 0)) integer_overflow (pfile); } break; case '/': if (v2 == 0) { cpp_error (pfile, "division by zero in #if"); v2 = 1; } top->unsignedp = unsigned1 || unsigned2; if (top->unsignedp) top->value = (unsigned long) v1 / v2; else { top->value = v1 / v2; if ((top->value & v1 & v2) < 0) integer_overflow (pfile); } break; case '%': if (v2 == 0) { cpp_error (pfile, "division by zero in #if"); v2 = 1; } top->unsignedp = unsigned1 || unsigned2; if (top->unsignedp) top->value = (unsigned long) v1 % v2; else top->value = v1 % v2; break; case '!': if (top->flags & HAVE_VALUE) { cpp_error (pfile, "syntax error"); goto syntax_error; } top->value = ! v2; top->unsignedp = 0; top->flags |= HAVE_VALUE; break; case '~': if (top->flags & HAVE_VALUE) { cpp_error (pfile, "syntax error"); goto syntax_error; } top->value = ~ v2; top->unsignedp = unsigned2; top->flags |= HAVE_VALUE; break; case '<': COMPARE(<); break; case '>': COMPARE(>); break; case LEQ: COMPARE(<=); break; case GEQ: COMPARE(>=); break; case EQUAL: top->value = (v1 == v2); top->unsignedp = 0; break; case NOTEQUAL: top->value = (v1 != v2); top->unsignedp = 0; break; case LSH: top->unsignedp = unsigned1; if (v2 < 0 && ! unsigned2) top->value = right_shift (pfile, v1, unsigned1, -v2); else top->value = left_shift (pfile, v1, unsigned1, v2); break; case RSH: top->unsignedp = unsigned1; if (v2 < 0 && ! unsigned2) top->value = left_shift (pfile, v1, unsigned1, -v2); else top->value = right_shift (pfile, v1, unsigned1, v2); break;#define LOGICAL(OP) \ top->value = v1 OP v2;\ top->unsignedp = unsigned1 || unsigned2; case '&': LOGICAL(&); break; case '^': LOGICAL(^); break; case '|': LOGICAL(|); break; case ANDAND: top->value = v1 && v2; top->unsignedp = 0; break; case OROR: top->value = v1 || v2; top->unsignedp = 0; break; case ',': if (CPP_PEDANTIC (pfile)) cpp_pedwarn (pfile, "comma operator in operand of `#if'"); top->value = v2; top->unsignedp = unsigned2; break; case '(': case '?': cpp_error (pfile, "syntax error in #if"); goto syntax_error; case ':': if (top[0].op != '?') { cpp_error (pfile, "syntax error ':' without preceding '?'"); goto syntax_error; } else if (! (top[1].flags & HAVE_VALUE) || !(top[-1].flags & HAVE_VALUE) || !(top[0].flags & HAVE_VALUE)) { cpp_error (pfile, "bad syntax for ?: operator"); goto syntax_error; } else { top--; top->value = top->value ? v1 : v2; top->unsignedp = unsigned1 || unsigned2; } break; case ')': if ((top[1].flags & HAVE_VALUE) || ! (top[0].flags & HAVE_VALUE) || top[0].op != '(' || (top[-1].flags & HAVE_VALUE)) { cpp_error (pfile, "mismatched parentheses in #if"); goto syntax_error; } else { top--; top->value = v1; top->unsignedp = unsigned1; top->flags |= HAVE_VALUE; } break; default: fprintf (stderr, top[1].op >= ' ' && top[1].op <= '~' ? "unimplemented operator '%c'\n" : "unimplemented operator '\\%03o'\n", top[1].op); } } if (op.op == 0) { if (top != stack) cpp_error (pfile, "internal error in #if expression"); if (stack != init_stack) free (stack); return top->value; } top++; /* Check for and handle stack overflow. */ if (top == limit) { struct operation *new_stack; int old_size = (char*)limit - (char*)stack; int new_size = 2 * old_size; if (stack != init_stack) new_stack = (struct operation*) xrealloc (stack, new_size); else { new_stack = (struct operation*) xmalloc (new_size); bcopy ((char *) stack, (char *) new_stack, old_size); } stack = new_stack; top = (struct operation*)((char*) new_stack + old_size); limit = (struct operation*)((char*) new_stack + new_size); } top->flags = flags; top->rprio = rprio; top->op = op.op; } syntax_error: if (stack != init_stack) free (stack); skip_rest_of_line (pfile); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -