aboutsummaryrefslogtreecommitdiff
path: root/gcc/cexp.y
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cexp.y')
-rw-r--r--gcc/cexp.y168
1 files changed, 104 insertions, 64 deletions
diff --git a/gcc/cexp.y b/gcc/cexp.y
index 133539f..5269c5b 100644
--- a/gcc/cexp.y
+++ b/gcc/cexp.y
@@ -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. */