X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fcppexp.c;h=4d1cf10eeb65e1c12b154b47dfbc96c5b9fa4b54;hb=02e7a332077569bfa13ac57067d817db087a189b;hp=093412e3b2663d5581e35d868ff5db86736b3376;hpb=963e5f16de1a3f9a79b4a5949626f83868e513a0;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/cppexp.c b/gcc/cppexp.c index 093412e3b26..4d1cf10eeb6 100644 --- a/gcc/cppexp.c +++ b/gcc/cppexp.c @@ -1,5 +1,5 @@ -/* Parse C expressions for CCCP. - Copyright (C) 1987, 92, 94, 95, 97, 98, 1999 Free Software Foundation. +/* Parse C expressions for cpplib. + Copyright (C) 1987, 92, 94, 95, 97, 98, 1999, 2000 Free Software Foundation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -27,10 +27,7 @@ Written by Per Bothner 1994. */ #include "config.h" #include "system.h" #include "cpplib.h" - -#ifdef MULTIBYTE_CHARS -#include -#endif +#include "cpphash.h" #ifndef CHAR_TYPE_SIZE #define CHAR_TYPE_SIZE BITS_PER_UNIT @@ -64,21 +61,34 @@ Written by Per Bothner 1994. */ #define MAX_WCHAR_TYPE_SIZE WCHAR_TYPE_SIZE #endif -#define MAX_CHAR_TYPE_MASK (MAX_CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT \ - ? (~ (~ (HOST_WIDE_INT) 0 << MAX_CHAR_TYPE_SIZE)) \ - : ~ (HOST_WIDE_INT) 0) +#define MAX_CHAR_TYPE_MASK (MAX_CHAR_TYPE_SIZE < HOST_BITS_PER_WIDEST_INT \ + ? (~(~(HOST_WIDEST_INT) 0 << MAX_CHAR_TYPE_SIZE)) \ + : ~ (HOST_WIDEST_INT) 0) -#define MAX_WCHAR_TYPE_MASK (MAX_WCHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT \ - ? ~ (~ (HOST_WIDE_INT) 0 << MAX_WCHAR_TYPE_SIZE) \ - : ~ (HOST_WIDE_INT) 0) +#define MAX_WCHAR_TYPE_MASK (MAX_WCHAR_TYPE_SIZE < HOST_BITS_PER_WIDEST_INT \ + ? ~(~(HOST_WIDEST_INT) 0 << MAX_WCHAR_TYPE_SIZE) \ + : ~ (HOST_WIDEST_INT) 0) /* Yield nonzero if adding two numbers with A's and B's signs can yield a number with SUM's sign, where A, B, and SUM are all C integers. */ #define possible_sum_sign(a, b, sum) ((((a) ^ (b)) | ~ ((a) ^ (sum))) < 0) static void integer_overflow PARAMS ((cpp_reader *)); -static long left_shift PARAMS ((cpp_reader *, long, int, unsigned long)); -static long right_shift PARAMS ((cpp_reader *, long, int, unsigned long)); +static HOST_WIDEST_INT left_shift PARAMS ((cpp_reader *, HOST_WIDEST_INT, + unsigned int, + unsigned HOST_WIDEST_INT)); +static HOST_WIDEST_INT right_shift PARAMS ((cpp_reader *, HOST_WIDEST_INT, + unsigned int, + unsigned HOST_WIDEST_INT)); +static struct operation parse_number PARAMS ((cpp_reader *, U_CHAR *, + U_CHAR *)); +static struct operation parse_charconst PARAMS ((cpp_reader *, U_CHAR *, + U_CHAR *)); +static struct operation parse_defined PARAMS ((cpp_reader *)); +static HOST_WIDEST_INT parse_escape PARAMS ((cpp_reader *, U_CHAR **, + HOST_WIDEST_INT)); +static struct operation lex PARAMS ((cpp_reader *, int)); + #define ERROR 299 #define OROR 300 @@ -99,24 +109,14 @@ static long right_shift PARAMS ((cpp_reader *, long, int, unsigned long)); /* SKIP_OPERAND is set for '&&' '||' '?' and ':' when the following operand should be short-circuited instead of evaluated. */ #define SKIP_OPERAND 8 -/*#define UNSIGNEDP 16*/ - -#ifndef CHAR_BIT -#define CHAR_BIT 8 -#endif -#ifndef HOST_BITS_PER_WIDE_INT -#define HOST_BITS_PER_WIDE_INT (CHAR_BIT * sizeof (HOST_WIDE_INT)) -#endif - -#define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0) - -struct operation { - short op; - char rprio; /* Priority of op (relative to it right operand). */ - char flags; - char unsignedp; /* true if value should be treated as unsigned */ - HOST_WIDE_INT value; /* The value logically "right" of op. */ +struct operation +{ + short op; + U_CHAR rprio; /* Priority of op (relative to it right operand). */ + U_CHAR flags; + U_CHAR unsignedp; /* true if value should be treated as unsigned */ + HOST_WIDEST_INT value; /* The value logically "right" of op. */ }; /* Parse and convert an integer for #if. Accepts decimal, hex, or octal @@ -131,7 +131,7 @@ parse_number (pfile, start, end) struct operation op; U_CHAR *p = start; int c; - unsigned HOST_WIDE_INT n = 0, nd, MAX_over_base; + unsigned HOST_WIDEST_INT n = 0, nd, MAX_over_base; int base = 10; int overflow = 0; int digit, largest_digit = 0; @@ -154,8 +154,8 @@ parse_number (pfile, start, end) } /* Some buggy compilers (e.g. MPW C) seem to need both casts. */ - MAX_over_base = (((unsigned HOST_WIDE_INT) -1) - / ((unsigned HOST_WIDE_INT) base)); + MAX_over_base = (((unsigned HOST_WIDEST_INT) -1) + / ((unsigned HOST_WIDEST_INT) base)); while (p < end) { @@ -229,7 +229,7 @@ parse_number (pfile, start, end) cpp_pedwarn (pfile, "integer constant out of range"); /* If too big to be signed, consider it unsigned. */ - else if ((HOST_WIDE_INT) n < 0 && ! op.unsignedp) + else if ((HOST_WIDEST_INT) n < 0 && ! op.unsignedp) { if (base == 10) cpp_warning (pfile, @@ -255,20 +255,14 @@ parse_charconst (pfile, start, end) U_CHAR *end; { struct operation op; - HOST_WIDE_INT result = 0; + HOST_WIDEST_INT result = 0; int num_chars = 0; int num_bits; unsigned int width = MAX_CHAR_TYPE_SIZE, mask = MAX_CHAR_TYPE_MASK; int max_chars; U_CHAR *ptr = start; - /* FIXME: Should use reentrant multibyte functions. */ -#ifdef MULTIBYTE_CHARS - wchar_t c; - (void) mbtowc (NULL_PTR, NULL_PTR, 0); -#else - int c; -#endif + int c = -1; if (*ptr == 'L') { @@ -281,22 +275,12 @@ parse_charconst (pfile, start, end) while (ptr < end) { -#ifndef MULTIBYTE_CHARS c = *ptr++; -#else - ptr += mbtowc (&c, ptr, end - ptr); -#endif if (c == '\'' || c == '\0') break; else if (c == '\\') { - /* Hopefully valid assumption: if mbtowc returns a backslash, - we are in initial shift state. No valid escape-sequence - character can take us out of initial shift state or begin - an unshifted multibyte char, so cpp_parse_escape doesn't - need to know about multibyte chars. */ - - c = cpp_parse_escape (pfile, (char **) &ptr, mask); + c = parse_escape (pfile, &ptr, mask); if (width < HOST_BITS_PER_INT && (unsigned int) c >= (unsigned int)(1 << width)) cpp_pedwarn (pfile, "escape sequence out of range for character"); @@ -335,14 +319,14 @@ parse_charconst (pfile, start, end) /* If char type is signed, sign-extend the constant. */ num_bits = num_chars * width; - if (cpp_lookup (pfile, (U_CHAR *)"__CHAR_UNSIGNED__", - sizeof ("__CHAR_UNSIGNED__")-1, -1) + if (cpp_defined (pfile, (const U_CHAR *)"__CHAR_UNSIGNED__", + sizeof ("__CHAR_UNSIGNED__")-1) || ((result >> (num_bits - 1)) & 1) == 0) - op.value = result & ((unsigned long) ~0 - >> (HOST_BITS_PER_LONG - num_bits)); + op.value = result & ((unsigned HOST_WIDEST_INT) ~0 + >> (HOST_BITS_PER_WIDEST_INT - num_bits)); else - op.value = result | ~((unsigned long) ~0 - >> (HOST_BITS_PER_LONG - num_bits)); + op.value = result | ~((unsigned HOST_WIDEST_INT) ~0 + >> (HOST_BITS_PER_WIDEST_INT - num_bits)); /* This is always a signed type. */ op.unsignedp = 0; @@ -354,13 +338,60 @@ parse_charconst (pfile, start, end) return op; } +static struct operation +parse_defined (pfile) + cpp_reader *pfile; +{ + int paren = 0, len; + U_CHAR *tok; + enum cpp_token token; + struct operation op; + long old_written = CPP_WRITTEN (pfile); + + op.unsignedp = 0; + op.op = INT; + + pfile->no_macro_expand++; + token = _cpp_get_directive_token (pfile); + if (token == CPP_LPAREN) + { + paren++; + CPP_SET_WRITTEN (pfile, old_written); + token = _cpp_get_directive_token (pfile); + } + + if (token != CPP_NAME) + goto oops; + + tok = pfile->token_buffer + old_written; + len = CPP_PWRITTEN (pfile) - tok; + op.value = cpp_defined (pfile, tok, len); + + if (paren) + { + if (_cpp_get_directive_token (pfile) != CPP_RPAREN) + goto oops; + } + CPP_SET_WRITTEN (pfile, old_written); + pfile->no_macro_expand--; + return op; + + oops: + CPP_SET_WRITTEN (pfile, old_written); + pfile->no_macro_expand--; + cpp_error (pfile, "`defined' without an identifier"); + + op.op = ERROR; + return op; +} + struct token { - char *operator; + const char *operator; int token; }; -static struct token tokentab2[] = { +static const struct token tokentab2[] = { {"&&", ANDAND}, {"||", OROR}, {"<<", LSH}, @@ -376,113 +407,58 @@ static struct token tokentab2[] = { /* Read one token. */ -struct operation -cpp_lex (pfile, skip_evaluation) +static struct operation +lex (pfile, skip_evaluation) cpp_reader *pfile; int skip_evaluation; { - U_CHAR c; - struct token *toktab; + const struct token *toktab; enum cpp_token token; struct operation op; U_CHAR *tok_start, *tok_end; - int old_written; - - retry: + long old_written; old_written = CPP_WRITTEN (pfile); - cpp_skip_hspace (pfile); - c = CPP_BUF_PEEK (CPP_BUFFER (pfile)); - if (c == '#') - { - op.op = INT; - op.value = cpp_read_check_assertion (pfile); - return op; - } + token = _cpp_get_directive_token (pfile); - if (c == '\n') - { - op.op = 0; - return op; - } - - token = cpp_get_token (pfile); tok_start = pfile->token_buffer + old_written; tok_end = CPP_PWRITTEN (pfile); - pfile->limit = tok_start; + CPP_SET_WRITTEN (pfile, old_written); switch (token) - { + { case CPP_EOF: /* Should not happen ... */ case CPP_VSPACE: op.op = 0; return op; - case CPP_POP: - if (CPP_BUFFER (pfile)->fname != NULL) - { - op.op = 0; - return op; - } - cpp_pop_buffer (pfile); - goto retry; - case CPP_HSPACE: - case CPP_COMMENT: - goto retry; case CPP_NUMBER: return parse_number (pfile, tok_start, tok_end); case CPP_STRING: - cpp_error (pfile, "string constants not allowed in #if expressions"); + case CPP_WSTRING: + cpp_error (pfile, "string constants are not allowed in #if expressions"); op.op = ERROR; return op; + case CPP_CHAR: + case CPP_WCHAR: return parse_charconst (pfile, tok_start, tok_end); case CPP_NAME: + if (!strcmp (tok_start, "defined")) + return parse_defined (pfile); + op.op = INT; op.unsignedp = 0; op.value = 0; - if (strcmp (tok_start, "defined")) - { - if (CPP_WARN_UNDEF (pfile) && !skip_evaluation) - cpp_warning (pfile, "`%.*s' is not defined", - (int) (tok_end - tok_start), tok_start); - } - else - { - int paren = 0, len; - cpp_buffer *ip = CPP_BUFFER (pfile); - U_CHAR *tok; - - SKIP_WHITE_SPACE (ip->cur); - if (*ip->cur == '(') - { - paren++; - ip->cur++; /* Skip over the paren */ - SKIP_WHITE_SPACE (ip->cur); - } - if (!is_idstart[*ip->cur]) - goto oops; - if (ip->cur[0] == 'L' && (ip->cur[1] == '\'' || ip->cur[1] == '"')) - goto oops; - tok = ip->cur; - while (is_idchar[*ip->cur]) - ++ip->cur; - len = ip->cur - tok; - SKIP_WHITE_SPACE (ip->cur); - if (paren) - { - if (*ip->cur != ')') - goto oops; - ++ip->cur; - } - if (cpp_lookup (pfile, tok, len, -1)) - op.value = 1; - - } + if (CPP_OPTIONS (pfile)->warn_undef && !skip_evaluation) + cpp_warning (pfile, "`%.*s' is not defined", + (int) (tok_end - tok_start), tok_start); return op; - oops: - cpp_error (pfile, "`defined' without an identifier"); + case CPP_ASSERTION: + op.op = INT; + op.unsignedp = 0; + op.value = cpp_defined (pfile, tok_start, tok_end - tok_start); return op; case CPP_OTHER: @@ -521,11 +497,11 @@ cpp_lex (pfile, skip_evaluation) If \ is followed by 000, we return 0 and leave the string pointer after the zeros. A value of 0 does not mean end of string. */ -HOST_WIDE_INT -cpp_parse_escape (pfile, string_ptr, result_mask) +static HOST_WIDEST_INT +parse_escape (pfile, string_ptr, result_mask) cpp_reader *pfile; - char **string_ptr; - HOST_WIDE_INT result_mask; + U_CHAR **string_ptr; + HOST_WIDEST_INT result_mask; { register int c = *(*string_ptr)++; switch (c) @@ -538,7 +514,7 @@ cpp_parse_escape (pfile, string_ptr, result_mask) case 'E': if (CPP_OPTIONS (pfile)->pedantic) cpp_pedwarn (pfile, "non-ANSI-standard escape sequence, `\\%c'", c); - return 033; + return TARGET_ESC; case 'f': return TARGET_FF; case 'n': @@ -564,7 +540,7 @@ cpp_parse_escape (pfile, string_ptr, result_mask) case '6': case '7': { - register HOST_WIDE_INT i = c - '0'; + register HOST_WIDEST_INT i = c - '0'; register int count = 0; while (++count < 3) { @@ -586,7 +562,7 @@ cpp_parse_escape (pfile, string_ptr, result_mask) } case 'x': { - register unsigned HOST_WIDE_INT i = 0, overflow = 0; + register unsigned HOST_WIDEST_INT i = 0, overflow = 0; register int digits_found = 0, digit; for (;;) { @@ -628,41 +604,41 @@ integer_overflow (pfile) cpp_pedwarn (pfile, "integer overflow in preprocessor expression"); } -static long +static HOST_WIDEST_INT left_shift (pfile, a, unsignedp, b) cpp_reader *pfile; - long a; - int unsignedp; - unsigned long b; + HOST_WIDEST_INT a; + unsigned int unsignedp; + unsigned HOST_WIDEST_INT b; { - if (b >= HOST_BITS_PER_LONG) + if (b >= HOST_BITS_PER_WIDEST_INT) { if (! unsignedp && a != 0) integer_overflow (pfile); return 0; } else if (unsignedp) - return (unsigned long) a << b; + return (unsigned HOST_WIDEST_INT) a << b; else { - long l = a << b; + HOST_WIDEST_INT l = a << b; if (l >> b != a) integer_overflow (pfile); return l; } } -static long +static HOST_WIDEST_INT right_shift (pfile, a, unsignedp, b) cpp_reader *pfile ATTRIBUTE_UNUSED; - long a; - int unsignedp; - unsigned long b; + HOST_WIDEST_INT a; + unsigned int unsignedp; + unsigned HOST_WIDEST_INT b; { - if (b >= HOST_BITS_PER_LONG) - return unsignedp ? 0 : a >> (HOST_BITS_PER_LONG - 1); + if (b >= HOST_BITS_PER_WIDEST_INT) + return unsignedp ? 0 : a >> (HOST_BITS_PER_WIDEST_INT - 1); else if (unsignedp) - return (unsigned long) a >> b; + return (unsigned HOST_WIDEST_INT) a >> b; else return a >> b; } @@ -687,13 +663,13 @@ right_shift (pfile, a, unsignedp, b) #define COMPARE(OP) \ top->unsignedp = 0;\ top->value = (unsigned1 || unsigned2) \ - ? (unsigned long) v1 OP (unsigned long) v2 : (v1 OP v2) + ? (unsigned HOST_WIDEST_INT) v1 OP (unsigned HOST_WIDEST_INT) v2 : (v1 OP v2) /* Parse and evaluate a C expression, reading from PFILE. - Returns the value of the expression. */ + Returns the truth value of the expression. */ -HOST_WIDE_INT -cpp_parse_expr (pfile) +int +_cpp_parse_expr (pfile) cpp_reader *pfile; { /* The implementation is an operator precedence parser, @@ -711,18 +687,21 @@ cpp_parse_expr (pfile) struct operation *stack = init_stack; struct operation *limit = stack + INIT_STACK_SIZE; register struct operation *top = stack; - int lprio, rprio; + unsigned int lprio, rprio = 0; int skip_evaluation = 0; + long old_written = CPP_WRITTEN (pfile); + int result; + pfile->parsing_if_directive++; top->rprio = 0; top->flags = 0; for (;;) { struct operation op; - char flags = 0; + U_CHAR flags = 0; /* Read a token */ - op = cpp_lex (pfile, skip_evaluation); + op = lex (pfile, skip_evaluation); /* 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 @@ -731,17 +710,19 @@ cpp_parse_expr (pfile) switch (op.op) { case NAME: - abort (); + cpp_ice (pfile, "lex returns a NAME"); + goto syntax_error; 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; + if (top->flags & HAVE_VALUE) + { + lprio = PLUS_PRIO; + goto binop; + } + /* else fall through */ case '!': case '~': flags = RIGHT_OPERAND_REQUIRED; rprio = UNARY_PRIO; lprio = rprio + 1; goto maybe_reduce; @@ -774,10 +755,6 @@ cpp_parse_expr (pfile) goto maybe_reduce; case ERROR: goto syntax_error; - 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; @@ -790,15 +767,22 @@ cpp_parse_expr (pfile) cpp_error (pfile, "syntax error in #if"); goto syntax_error; } + top->value = op.value; + top->unsignedp = op.unsignedp; top->flags |= HAVE_VALUE; continue; + binop: + flags = LEFT_OPERAND_REQUIRED|RIGHT_OPERAND_REQUIRED; + rprio = lprio + 1; + 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; + HOST_WIDEST_INT v1 = top[-1].value, v2 = top[0].value; + unsigned int unsigned1 = top[-1].unsignedp; + unsigned int unsigned2 = top[0].unsignedp; top--; if ((top[1].flags & LEFT_OPERAND_REQUIRED) && ! (top[0].flags & HAVE_VALUE)) @@ -852,7 +836,7 @@ cpp_parse_expr (pfile) case '*': top->unsignedp = unsigned1 || unsigned2; if (top->unsignedp) - top->value = (unsigned long) v1 * v2; + top->value = (unsigned HOST_WIDEST_INT) v1 * v2; else if (!skip_evaluation) { top->value = v1 * v2; @@ -872,7 +856,7 @@ cpp_parse_expr (pfile) } top->unsignedp = unsigned1 || unsigned2; if (top->unsignedp) - top->value = (unsigned long) v1 / v2; + top->value = (unsigned HOST_WIDEST_INT) v1 / v2; else { top->value = v1 / v2; @@ -890,7 +874,7 @@ cpp_parse_expr (pfile) } top->unsignedp = unsigned1 || unsigned2; if (top->unsignedp) - top->value = (unsigned long) v1 % v2; + top->value = (unsigned HOST_WIDEST_INT) v1 % v2; else top->value = v1 % v2; break; @@ -1007,20 +991,19 @@ cpp_parse_expr (pfile) } break; default: - cpp_error (pfile, - (top[1].op >= ' ' && top[1].op <= '~' - ? "unimplemented operator '%c'\n" - : "unimplemented operator '\\%03o'\n"), - top[1].op); + if (ISGRAPH (top[1].op)) + cpp_error (pfile, "unimplemented operator '%c'\n", top[1].op); + else + cpp_error (pfile, "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; + cpp_ice (pfile, "unbalanced stack in #if expression"); + result = (top->value != 0); + goto done; } top++; @@ -1035,7 +1018,7 @@ cpp_parse_expr (pfile) else { new_stack = (struct operation *) xmalloc (new_size); - bcopy ((char *) stack, (char *) new_stack, old_size); + memcpy (new_stack, stack, old_size); } stack = new_stack; top = (struct operation *) ((char *) new_stack + old_size); @@ -1060,8 +1043,12 @@ cpp_parse_expr (pfile) } } syntax_error: + _cpp_skip_rest_of_line (pfile); + result = 0; + done: + pfile->parsing_if_directive--; + CPP_SET_WRITTEN (pfile, old_written); if (stack != init_stack) free (stack); - skip_rest_of_line (pfile); - return 0; + return result; }