diff options
Diffstat (limited to 'gcc/cexp.y')
-rw-r--r-- | gcc/cexp.y | 168 |
1 files changed, 104 insertions, 64 deletions
@@ -29,29 +29,19 @@ Boston, MA 02111-1307, USA. #include <setjmp.h> /* #define YYDEBUG 1 */ -/* The following symbols should be autoconfigured: - HAVE_STDLIB_H - STDC_HEADERS - In the mean time, we'll get by with approximations based - on existing GCC configuration symbols. */ - -#ifdef POSIX -# ifndef HAVE_STDLIB_H -# define HAVE_STDLIB_H 1 -# endif -# ifndef STDC_HEADERS -# define STDC_HEADERS 1 -# endif -#endif /* defined (POSIX) */ -#if STDC_HEADERS +#ifdef HAVE_STRING_H # include <string.h> #endif -#if HAVE_STDLIB_H || defined (MULTIBYTE_CHARS) +#ifdef HAVE_STDLIB_H # include <stdlib.h> #endif +#ifdef HAVE_LIMITS_H +# include <limits.h> +#endif + #ifdef MULTIBYTE_CHARS #include <locale.h> #endif @@ -87,18 +77,36 @@ struct arglist { #endif /* Find the largest host integer type and set its size and type. - Don't blindly use `long'; on some crazy hosts it is shorter than `int'. */ + Watch out: on some crazy hosts `long' is shorter than `int'. */ -#ifndef HOST_BITS_PER_WIDE_INT +#ifndef HOST_WIDE_INT +# if HAVE_INTTYPES_H +# include <inttypes.h> +# define HOST_WIDE_INT intmax_t +# define unsigned_HOST_WIDE_INT uintmax_t +# else +# if (HOST_BITS_PER_LONG <= HOST_BITS_PER_INT && HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_INT) +# define HOST_WIDE_INT int +# else +# if (HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_LONG || ! (defined LONG_LONG_MAX || defined LLONG_MAX)) +# define HOST_WIDE_INT long +# else +# define HOST_WIDE_INT long long +# endif +# endif +# endif +#endif -#if HOST_BITS_PER_LONG > HOST_BITS_PER_INT -#define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_LONG -#define HOST_WIDE_INT long -#else -#define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_INT -#define HOST_WIDE_INT int +#ifndef unsigned_HOST_WIDE_INT +#define unsigned_HOST_WIDE_INT unsigned HOST_WIDE_INT #endif +#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 #if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) @@ -137,11 +145,14 @@ struct arglist { #define PRINTF_PROTO_1(ARGS) PRINTF_PROTO(ARGS, 1, 2) -HOST_WIDE_INT parse_c_expression PROTO((char *)); +HOST_WIDE_INT parse_c_expression PROTO((char *, int)); static int yylex PROTO((void)); static void yyerror PROTO((char *)) __attribute__ ((noreturn)); static HOST_WIDE_INT expression_value; +#ifdef TEST_EXP_READER +static int expression_signedp; +#endif static jmp_buf parse_return_error; @@ -152,6 +163,9 @@ static int keyword_parsing = 0; This is a count, since unevaluated expressions can nest. */ static int skip_evaluation; +/* Nonzero means warn if undefined identifiers are evaluated. */ +static int warn_undef; + /* some external tables of character types */ extern unsigned char is_idstart[], is_idchar[], is_space[]; @@ -164,9 +178,6 @@ extern int traditional; /* Flag for -lang-c89. */ extern int c89; -/* Flag for -Wundef. */ -extern int warn_undef; - #ifndef CHAR_TYPE_SIZE #define CHAR_TYPE_SIZE BITS_PER_UNIT #endif @@ -199,17 +210,13 @@ extern int warn_undef; #define MAX_WCHAR_TYPE_SIZE WCHAR_TYPE_SIZE #endif -#if MAX_CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT -#define MAX_CHAR_TYPE_MASK (~ (~ (HOST_WIDE_INT) 0 << MAX_CHAR_TYPE_SIZE)) -#else -#define MAX_CHAR_TYPE_MASK (~ (HOST_WIDE_INT) 0) -#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) -#if MAX_WCHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT -#define MAX_WCHAR_TYPE_MASK (~ (~ (HOST_WIDE_INT) 0 << MAX_WCHAR_TYPE_SIZE)) -#else -#define MAX_WCHAR_TYPE_MASK (~ (HOST_WIDE_INT) 0) -#endif +#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) /* Suppose A1 + B1 = SUM1, using 2's complement arithmetic ignoring overflow. Suppose A, B and SUM have the same respective signs as A1, B1, and SUM1. @@ -232,8 +239,8 @@ void pedwarn PRINTF_PROTO_1((char *, ...)); void warning PRINTF_PROTO_1((char *, ...)); static int parse_number PROTO((int)); -static HOST_WIDE_INT left_shift PROTO((struct constant *, unsigned HOST_WIDE_INT)); -static HOST_WIDE_INT right_shift PROTO((struct constant *, unsigned HOST_WIDE_INT)); +static HOST_WIDE_INT left_shift PROTO((struct constant *, unsigned_HOST_WIDE_INT)); +static HOST_WIDE_INT right_shift PROTO((struct constant *, unsigned_HOST_WIDE_INT)); static void integer_overflow PROTO((void)); /* `signedp' values */ @@ -272,7 +279,12 @@ static void integer_overflow PROTO((void)); %% start : exp1 - { expression_value = $1.value; } + { + expression_value = $1.value; +#ifdef TEST_EXP_READER + expression_signedp = $1.signedp; +#endif + } ; /* Expressions, including the comma operator. */ @@ -324,7 +336,7 @@ exp : exp '*' exp integer_overflow (); } else - $$.value = ((unsigned HOST_WIDE_INT) $1.value + $$.value = ((unsigned_HOST_WIDE_INT) $1.value * $3.value); } | exp '/' exp { if ($3.value == 0) @@ -341,7 +353,7 @@ exp : exp '*' exp integer_overflow (); } else - $$.value = ((unsigned HOST_WIDE_INT) $1.value + $$.value = ((unsigned_HOST_WIDE_INT) $1.value / $3.value); } | exp '%' exp { if ($3.value == 0) @@ -354,7 +366,7 @@ exp : exp '*' exp if ($$.signedp) $$.value = $1.value % $3.value; else - $$.value = ((unsigned HOST_WIDE_INT) $1.value + $$.value = ((unsigned_HOST_WIDE_INT) $1.value % $3.value); } | exp '+' exp { $$.value = $1.value + $3.value; @@ -391,28 +403,28 @@ exp : exp '*' exp if ($1.signedp & $3.signedp) $$.value = $1.value <= $3.value; else - $$.value = ((unsigned HOST_WIDE_INT) $1.value + $$.value = ((unsigned_HOST_WIDE_INT) $1.value <= $3.value); } | exp GEQ exp { $$.signedp = SIGNED; if ($1.signedp & $3.signedp) $$.value = $1.value >= $3.value; else - $$.value = ((unsigned HOST_WIDE_INT) $1.value + $$.value = ((unsigned_HOST_WIDE_INT) $1.value >= $3.value); } | exp '<' exp { $$.signedp = SIGNED; if ($1.signedp & $3.signedp) $$.value = $1.value < $3.value; else - $$.value = ((unsigned HOST_WIDE_INT) $1.value + $$.value = ((unsigned_HOST_WIDE_INT) $1.value < $3.value); } | exp '>' exp { $$.signedp = SIGNED; if ($1.signedp & $3.signedp) $$.value = $1.value > $3.value; else - $$.value = ((unsigned HOST_WIDE_INT) $1.value + $$.value = ((unsigned_HOST_WIDE_INT) $1.value > $3.value); } | exp '&' exp { $$.value = $1.value & $3.value; @@ -495,7 +507,7 @@ parse_number (olen) { register char *p = lexptr; register int c; - register unsigned HOST_WIDE_INT n = 0, nd, max_over_base; + register unsigned_HOST_WIDE_INT n = 0, nd, max_over_base; register int base = 10; register int len = olen; register int overflow = 0; @@ -513,7 +525,7 @@ parse_number (olen) } } - max_over_base = (unsigned HOST_WIDE_INT) -1 / base; + max_over_base = (unsigned_HOST_WIDE_INT) -1 / base; for (; len > 0; len--) { c = *p++; @@ -684,7 +696,7 @@ yylex () It is mostly copied from c-lex.c. */ { register HOST_WIDE_INT result = 0; - register num_chars = 0; + register int num_chars = 0; unsigned width = MAX_CHAR_TYPE_SIZE; int max_chars; char *token_buffer; @@ -751,11 +763,11 @@ yylex () sizeof ("__CHAR_UNSIGNED__") - 1, -1) || ((result >> (num_bits - 1)) & 1) == 0) yylval.integer.value - = result & (~ (unsigned HOST_WIDE_INT) 0 + = result & (~ (unsigned_HOST_WIDE_INT) 0 >> (HOST_BITS_PER_WIDE_INT - num_bits)); else yylval.integer.value - = result | ~(~ (unsigned HOST_WIDE_INT) 0 + = result | ~(~ (unsigned_HOST_WIDE_INT) 0 >> (HOST_BITS_PER_WIDE_INT - num_bits)); } else @@ -962,7 +974,7 @@ parse_escape (string_ptr, result_mask) } case 'x': { - register unsigned HOST_WIDE_INT i = 0, overflow = 0; + register unsigned_HOST_WIDE_INT i = 0, overflow = 0; register int digits_found = 0, digit; for (;;) { @@ -1015,7 +1027,7 @@ integer_overflow () static HOST_WIDE_INT left_shift (a, b) struct constant *a; - unsigned HOST_WIDE_INT b; + unsigned_HOST_WIDE_INT b; { /* It's unclear from the C standard whether shifts can overflow. The following code ignores overflow; perhaps a C standard @@ -1023,36 +1035,39 @@ left_shift (a, b) if (b >= HOST_BITS_PER_WIDE_INT) return 0; else - return (unsigned HOST_WIDE_INT) a->value << b; + return (unsigned_HOST_WIDE_INT) a->value << b; } static HOST_WIDE_INT right_shift (a, b) struct constant *a; - unsigned HOST_WIDE_INT b; + unsigned_HOST_WIDE_INT b; { if (b >= HOST_BITS_PER_WIDE_INT) return a->signedp ? a->value >> (HOST_BITS_PER_WIDE_INT - 1) : 0; else if (a->signedp) return a->value >> b; else - return (unsigned HOST_WIDE_INT) a->value >> b; + return (unsigned_HOST_WIDE_INT) a->value >> b; } /* This page contains the entry point to this file. */ /* Parse STRING as an expression, and complain if this fails - to use up all of the contents of STRING. */ -/* STRING may contain '\0' bytes; it is terminated by the first '\n' - outside a string constant, so that we can diagnose '\0' properly. */ -/* We do not support C comments. They should be removed before + to use up all of the contents of STRING. + STRING may contain '\0' bytes; it is terminated by the first '\n' + outside a string constant, so that we can diagnose '\0' properly. + If WARN_UNDEFINED is nonzero, warn if undefined identifiers are evaluated. + We do not support C comments. They should be removed before this function is called. */ HOST_WIDE_INT -parse_c_expression (string) +parse_c_expression (string, warn_undefined) char *string; + int warn_undefined; { lexptr = string; + warn_undef = warn_undefined; /* if there is some sort of scanning error, just return 0 and assume the parsing routine has printed an error message somewhere. @@ -1080,6 +1095,7 @@ int traditional; int main PROTO((int, char **)); static void initialize_random_junk PROTO((void)); +static void print_unsigned_host_wide_int PROTO((unsigned_HOST_WIDE_INT)); /* Main program for testing purposes. */ int @@ -1089,6 +1105,7 @@ main (argc, argv) { int n, c; char buf[1024]; + unsigned_HOST_WIDE_INT u; pedantic = 1 < argc; traditional = 2 < argc; @@ -1104,12 +1121,35 @@ main (argc, argv) n++; if (c == EOF) break; - printf ("parser returned %ld\n", (long) parse_c_expression (buf)); + parse_c_expression (buf, 1); + printf ("parser returned "); + u = (unsigned_HOST_WIDE_INT) expression_value; + if (expression_value < 0 && expression_signedp) { + u = -u; + printf ("-"); + } + if (u == 0) + printf ("0"); + else + print_unsigned_host_wide_int (u); + if (! expression_signedp) + printf("u"); + printf ("\n"); } return 0; } +static void +print_unsigned_host_wide_int (u) + unsigned_HOST_WIDE_INT u; +{ + if (u) { + print_unsigned_host_wide_int (u / 10); + putchar ('0' + (int) (u % 10)); + } +} + /* table to tell if char can be part of a C identifier. */ unsigned char is_idchar[256]; /* table to tell if char can be first char of a c identifier. */ |