aboutsummaryrefslogtreecommitdiff
path: root/gcc/cppexp.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cppexp.c')
-rw-r--r--gcc/cppexp.c588
1 files changed, 309 insertions, 279 deletions
diff --git a/gcc/cppexp.c b/gcc/cppexp.c
index 44f8a66547c..eaec4686d75 100644
--- a/gcc/cppexp.c
+++ b/gcc/cppexp.c
@@ -1,5 +1,5 @@
/* Parse C expressions for CCCP.
- Copyright (C) 1987, 1992, 1994, 1995, 1997, 1998 Free Software Foundation.
+ Copyright (C) 1987, 92, 94, 95, 97, 98, 1999 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
@@ -26,24 +26,12 @@ Written by Per Bothner 1994. */
#include "config.h"
#include "system.h"
-#include "gansidecl.h"
#include "cpplib.h"
-extern char *xmalloc PARAMS ((unsigned));
-extern char *xrealloc PARAMS ((void *, unsigned));
-
#ifdef MULTIBYTE_CHARS
#include <locale.h>
#endif
-/* This is used for communicating lists of keywords with cccp.c. */
-struct arglist {
- struct arglist *next;
- U_CHAR *name;
- int length;
- int argno;
-};
-
#ifndef CHAR_TYPE_SIZE
#define CHAR_TYPE_SIZE BITS_PER_UNIT
#endif
@@ -76,13 +64,21 @@ struct arglist {
#define MAX_WCHAR_TYPE_SIZE WCHAR_TYPE_SIZE
#endif
+#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_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, int, unsigned HOST_WIDEST_INT));
+static HOST_WIDEST_INT right_shift PARAMS ((cpp_reader *, HOST_WIDEST_INT, int, unsigned HOST_WIDEST_INT));
#define ERROR 299
#define OROR 300
@@ -105,135 +101,117 @@ static long right_shift PARAMS ((cpp_reader *, long, int, unsigned long));
#define SKIP_OPERAND 8
/*#define UNSIGNEDP 16*/
-/* Find the largest host integer type and set its size and type.
- Watch out: on some crazy hosts `long' is shorter than `int'. */
-
-#ifndef HOST_WIDE_INT
-# if HAVE_INTTYPES_H
-# include <inttypes.h>
-# define HOST_WIDE_INT intmax_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
-
-#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
-
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. */
+ HOST_WIDEST_INT value; /* The value logically "right" of op. */
};
-
-/* Take care of parsing a number (anything that starts with a digit).
- LEN is the number of characters in it. */
-/* maybe needs to actually deal with floating point numbers */
+/* Parse and convert an integer for #if. Accepts decimal, hex, or octal
+ with or without size suffixes. */
-struct operation
-parse_number (pfile, start, olen)
+static struct operation
+parse_number (pfile, start, end)
cpp_reader *pfile;
- char *start;
- int olen;
+ U_CHAR *start;
+ U_CHAR *end;
{
struct operation op;
- register char *p = start;
- register int c;
- register unsigned long n = 0, nd, ULONG_MAX_over_base;
- register int base = 10;
- register int len = olen;
- register int overflow = 0;
- register int digit, largest_digit = 0;
+ U_CHAR *p = start;
+ int c;
+ unsigned HOST_WIDEST_INT n = 0, nd, MAX_over_base;
+ int base = 10;
+ int overflow = 0;
+ int digit, largest_digit = 0;
int spec_long = 0;
op.unsignedp = 0;
- for (c = 0; c < len; c++)
- if (p[c] == '.') {
- /* It's a float since it contains a point. */
- cpp_error (pfile,
- "floating point numbers not allowed in #if expressions");
- op.op = ERROR;
- return op;
+ if (p[0] == '0')
+ {
+ if (end - start >= 3 && (p[1] == 'x' || p[1] == 'X'))
+ {
+ p += 2;
+ base = 16;
+ }
+ else
+ {
+ p += 1;
+ base = 8;
+ }
}
- if (len >= 3 && (!strncmp (p, "0x", 2) || !strncmp (p, "0X", 2))) {
- p += 2;
- base = 16;
- len -= 2;
- }
- else if (*p == '0')
- base = 8;
-
/* Some buggy compilers (e.g. MPW C) seem to need both casts. */
- ULONG_MAX_over_base = ((unsigned long) -1) / ((unsigned long) base);
-
- for (; len > 0; len--) {
- c = *p++;
-
- if (c >= '0' && c <= '9')
- digit = c - '0';
- else if (base == 16 && c >= 'a' && c <= 'f')
- digit = c - 'a' + 10;
- else if (base == 16 && c >= 'A' && c <= 'F')
- digit = c - 'A' + 10;
- else {
- /* `l' means long, and `u' means unsigned. */
- while (1) {
- if (c == 'l' || c == 'L')
- {
- if (spec_long)
- cpp_error (pfile, "two `l's in integer constant");
- spec_long = 1;
- }
- else if (c == 'u' || c == 'U')
- {
- if (op.unsignedp)
- cpp_error (pfile, "two `u's in integer constant");
- op.unsignedp = 1;
- }
- else
- break;
+ MAX_over_base = (((unsigned HOST_WIDEST_INT) -1)
+ / ((unsigned HOST_WIDEST_INT) base));
- if (--len == 0)
+ while (p < end)
+ {
+ c = *p++;
+
+ if (c >= '0' && c <= '9')
+ digit = c - '0';
+ else if (base == 16 && c >= 'a' && c <= 'f') /* FIXME: assumes ASCII */
+ digit = c - 'a' + 10;
+ else if (base == 16 && c >= 'A' && c <= 'F')
+ digit = c - 'A' + 10;
+ else if (c == '.')
+ {
+ /* It's a float since it contains a point. */
+ cpp_error (pfile,
+ "floating point numbers are not allowed in #if expressions");
+ goto error;
+ }
+ else
+ {
+ /* `l' means long, and `u' means unsigned. */
+ for (;;)
+ {
+ if (c == 'l' || c == 'L')
+ spec_long++;
+ else if (c == 'u' || c == 'U')
+ op.unsignedp++;
+ else
+ {
+ /* Decrement p here so that the error for an invalid number
+ will be generated below in the case where this is the
+ last character in the buffer. */
+ p--;
+ break;
+ }
+ if (p == end)
+ break;
+ c = *p++;
+ }
+ /* Don't look for any more digits after the suffixes. */
break;
- c = *p++;
- }
- /* Don't look for any more digits after the suffixes. */
- break;
+ }
+
+ if (largest_digit < digit)
+ largest_digit = digit;
+ nd = n * base + digit;
+ overflow |= MAX_over_base < n || nd < n;
+ n = nd;
}
- if (largest_digit < digit)
- largest_digit = digit;
- nd = n * base + digit;
- overflow |= ULONG_MAX_over_base < n || nd < n;
- n = nd;
- }
- if (len != 0)
+ if (p != end)
{
- cpp_error (pfile, "Invalid number in #if expression");
- op.op = ERROR;
- return op;
+ cpp_error (pfile, "invalid number in #if expression");
+ goto error;
}
-
+ else if (spec_long > (CPP_OPTIONS (pfile)->c89 ? 1 : 2))
+ {
+ cpp_error (pfile, "too many `l' suffixes in integer constant");
+ goto error;
+ }
+ else if (op.unsignedp > 1)
+ {
+ cpp_error (pfile, "too many `u' suffixes in integer constant");
+ goto error;
+ }
+
if (base <= largest_digit)
cpp_pedwarn (pfile, "integer constant contains digits beyond the radix");
@@ -241,18 +219,132 @@ parse_number (pfile, start, olen)
cpp_pedwarn (pfile, "integer constant out of range");
/* If too big to be signed, consider it unsigned. */
- if ((long) n < 0 && ! op.unsignedp)
+ else if ((HOST_WIDEST_INT) n < 0 && ! op.unsignedp)
{
if (base == 10)
- cpp_warning (pfile, "integer constant is so large that it is unsigned");
+ cpp_warning (pfile,
+ "integer constant is so large that it is unsigned");
op.unsignedp = 1;
}
op.value = n;
op.op = INT;
return op;
+
+ error:
+ op.op = ERROR;
+ return op;
}
+/* Parse and convert a character constant for #if. Understands backslash
+ escapes (\n, \031) and multibyte characters (if so configured). */
+static struct operation
+parse_charconst (pfile, start, end)
+ cpp_reader *pfile;
+ U_CHAR *start;
+ U_CHAR *end;
+{
+ struct operation op;
+ 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
+
+ if (*ptr == 'L')
+ {
+ ++ptr;
+ width = MAX_WCHAR_TYPE_SIZE, mask = MAX_WCHAR_TYPE_MASK;
+ }
+ max_chars = MAX_LONG_TYPE_SIZE / width;
+
+ ++ptr; /* skip initial quote */
+
+ 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);
+ if (width < HOST_BITS_PER_INT
+ && (unsigned int) c >= (unsigned int)(1 << width))
+ cpp_pedwarn (pfile, "escape sequence out of range for character");
+ }
+
+ /* Merge character into result; ignore excess chars. */
+ if (++num_chars <= max_chars)
+ {
+ if (width < HOST_BITS_PER_INT)
+ result = (result << width) | (c & ((1 << width) - 1));
+ else
+ result = c;
+ }
+ }
+
+ if (num_chars == 0)
+ {
+ cpp_error (pfile, "empty character constant");
+ goto error;
+ }
+ else if (c != '\'')
+ {
+ /* cpp_get_token has already emitted an error if !traditional. */
+ if (! CPP_TRADITIONAL (pfile))
+ cpp_error (pfile, "malformatted character constant");
+ goto error;
+ }
+ else if (num_chars > max_chars)
+ {
+ cpp_error (pfile, "character constant too long");
+ goto error;
+ }
+ else if (num_chars != 1 && ! CPP_TRADITIONAL (pfile))
+ cpp_warning (pfile, "multi-character character constant");
+
+ /* 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)
+ || ((result >> (num_bits - 1)) & 1) == 0)
+ op.value = result & ((unsigned HOST_WIDEST_INT) ~0
+ >> (HOST_BITS_PER_WIDEST_INT - num_bits));
+ else
+ op.value = result | ~((unsigned HOST_WIDEST_INT) ~0
+ >> (HOST_BITS_PER_WIDEST_INT - num_bits));
+
+ /* This is always a signed type. */
+ op.unsignedp = 0;
+ op.op = CHAR;
+ return op;
+
+ error:
+ op.op = ERROR;
+ return op;
+}
+
+
struct token {
char *operator;
int token;
@@ -274,13 +366,13 @@ static struct token tokentab2[] = {
/* Read one token. */
-struct operation
+static struct operation
cpp_lex (pfile, skip_evaluation)
cpp_reader *pfile;
int skip_evaluation;
{
- register int c;
- register struct token *toktab;
+ U_CHAR c;
+ struct token *toktab;
enum cpp_token token;
struct operation op;
U_CHAR *tok_start, *tok_end;
@@ -292,8 +384,11 @@ cpp_lex (pfile, skip_evaluation)
cpp_skip_hspace (pfile);
c = CPP_BUF_PEEK (CPP_BUFFER (pfile));
if (c == '#')
- return parse_number (pfile,
- cpp_read_check_assertion (pfile) ? "1" : "0", 1);
+ {
+ op.op = INT;
+ op.value = cpp_read_check_assertion (pfile);
+ return op;
+ }
if (c == '\n')
{
@@ -319,131 +414,66 @@ cpp_lex (pfile, skip_evaluation)
}
cpp_pop_buffer (pfile);
goto retry;
- case CPP_HSPACE: case CPP_COMMENT:
+ case CPP_HSPACE:
+ case CPP_COMMENT:
goto retry;
case CPP_NUMBER:
- return parse_number (pfile, tok_start, tok_end - tok_start);
+ return parse_number (pfile, tok_start, tok_end);
case CPP_STRING:
cpp_error (pfile, "string constants not allowed in #if expressions");
op.op = ERROR;
return op;
case CPP_CHAR:
- /* This code for reading a character constant
- handles multicharacter constants and wide characters.
- It is mostly copied from c-lex.c. */
- {
- register int result = 0;
- register int num_chars = 0;
- unsigned width = MAX_CHAR_TYPE_SIZE;
- int wide_flag = 0;
- int max_chars;
- U_CHAR *ptr = tok_start;
-#ifdef MULTIBYTE_CHARS
- char token_buffer[MAX_LONG_TYPE_SIZE/MAX_CHAR_TYPE_SIZE + MB_CUR_MAX];
-#else
- char token_buffer[MAX_LONG_TYPE_SIZE/MAX_CHAR_TYPE_SIZE + 1];
-#endif
-
- if (*ptr == 'L')
- {
- ptr++;
- wide_flag = 1;
- width = MAX_WCHAR_TYPE_SIZE;
-#ifdef MULTIBYTE_CHARS
- max_chars = MB_CUR_MAX;
-#else
- max_chars = 1;
-#endif
- }
- else
- max_chars = MAX_LONG_TYPE_SIZE / width;
+ return parse_charconst (pfile, tok_start, tok_end);
- ++ptr;
- while (ptr < tok_end && ((c = *ptr++) != '\''))
- {
- if (c == '\\')
- {
- c = cpp_parse_escape (pfile, (char **) &ptr);
- if (width < HOST_BITS_PER_INT
- && (unsigned) c >= (1 << width))
- cpp_pedwarn (pfile,
- "escape sequence out of range for character");
- }
-
- num_chars++;
-
- /* Merge character into result; ignore excess chars. */
- if (num_chars < max_chars + 1)
- {
- if (width < HOST_BITS_PER_INT)
- result = (result << width) | (c & ((1 << width) - 1));
- else
- result = c;
- token_buffer[num_chars - 1] = c;
- }
- }
-
- token_buffer[num_chars] = 0;
-
- if (c != '\'')
- cpp_error (pfile, "malformatted character constant");
- else if (num_chars == 0)
- cpp_error (pfile, "empty character constant");
- else if (num_chars > max_chars)
- {
- num_chars = max_chars;
- cpp_error (pfile, "character constant too long");
- }
- else if (num_chars != 1 && ! CPP_TRADITIONAL (pfile))
- cpp_warning (pfile, "multi-character character constant");
+ case CPP_NAME:
+ 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;
- /* If char type is signed, sign-extend the constant. */
- if (! wide_flag)
- {
- int num_bits = num_chars * width;
+ cpp_skip_hspace (pfile);
+ if (*ip->cur == '(')
+ {
+ paren++;
+ ip->cur++; /* Skip over the paren */
+ cpp_skip_hspace (pfile);
+ }
- if (cpp_lookup (pfile, (U_CHAR *)"__CHAR_UNSIGNED__",
- sizeof ("__CHAR_UNSIGNED__")-1, -1)
- || ((result >> (num_bits - 1)) & 1) == 0)
- op.value
- = result & ((unsigned long) ~0 >> (HOST_BITS_PER_LONG - num_bits));
- else
- op.value
- = result | ~((unsigned long) ~0 >> (HOST_BITS_PER_LONG - num_bits));
- }
- else
- {
-#ifdef MULTIBYTE_CHARS
- /* Set the initial shift state and convert the next sequence. */
- result = 0;
- /* In all locales L'\0' is zero and mbtowc will return zero,
- so don't use it. */
- if (num_chars > 1
- || (num_chars == 1 && token_buffer[0] != '\0'))
- {
- wchar_t wc;
- (void) mbtowc (NULL_PTR, NULL_PTR, 0);
- if (mbtowc (& wc, token_buffer, num_chars) == num_chars)
- result = wc;
- else
- cpp_pedwarn (pfile,"Ignoring invalid multibyte character");
- }
-#endif
- op.value = result;
+ 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;
+ cpp_skip_hspace (pfile);
+ if (paren)
+ {
+ if (*ip->cur != ')')
+ goto oops;
+ ++ip->cur;
}
- }
+ if (cpp_lookup (pfile, tok, len, -1))
+ op.value = 1;
- /* This is always a signed type. */
- op.unsignedp = 0;
- op.op = CHAR;
-
+ }
return op;
- case CPP_NAME:
- if (CPP_WARN_UNDEF (pfile) && !skip_evaluation)
- cpp_warning (pfile, "`%.*s' is not defined",
- (int) (tok_end - tok_start), tok_start);
- return parse_number (pfile, "0", 0);
+ oops:
+ cpp_error (pfile, "`defined' without an identifier");
+ return op;
case CPP_OTHER:
/* See if it is a special token of length 2. */
@@ -454,11 +484,8 @@ cpp_lex (pfile, skip_evaluation)
&& tok_start[1] == toktab->operator[1])
break;
if (toktab->token == ERROR)
- {
- char *buf = (char *) alloca (40);
- sprintf (buf, "`%s' not allowed in operand of `#if'", tok_start);
- cpp_error (pfile, buf);
- }
+ cpp_error (pfile, "`%s' not allowed in operand of `#if'",
+ tok_start);
op.op = toktab->token;
return op;
}
@@ -484,10 +511,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. */
-int
-cpp_parse_escape (pfile, string_ptr)
+HOST_WIDEST_INT
+cpp_parse_escape (pfile, string_ptr, result_mask)
cpp_reader *pfile;
char **string_ptr;
+ HOST_WIDEST_INT result_mask;
{
register int c = *(*string_ptr)++;
switch (c)
@@ -498,7 +526,7 @@ cpp_parse_escape (pfile, string_ptr)
return TARGET_BS;
case 'e':
case 'E':
- if (CPP_PEDANTIC (pfile))
+ if (CPP_OPTIONS (pfile)->pedantic)
cpp_pedwarn (pfile, "non-ANSI-standard escape sequence, `\\%c'", c);
return 033;
case 'f':
@@ -526,7 +554,7 @@ cpp_parse_escape (pfile, string_ptr)
case '6':
case '7':
{
- register int i = c - '0';
+ register HOST_WIDEST_INT i = c - '0';
register int count = 0;
while (++count < 3)
{
@@ -539,17 +567,17 @@ cpp_parse_escape (pfile, string_ptr)
break;
}
}
- if ((i & ~((1 << MAX_CHAR_TYPE_SIZE) - 1)) != 0)
+ if (i != (i & result_mask))
{
- i &= (1 << MAX_CHAR_TYPE_SIZE) - 1;
- cpp_pedwarn (pfile,
- "octal character constant does not fit in a byte");
+ i &= result_mask;
+ cpp_pedwarn (pfile, "octal escape sequence out of range");
}
return i;
}
case 'x':
{
- register unsigned i = 0, overflow = 0, digits_found = 0, digit;
+ register unsigned HOST_WIDEST_INT i = 0, overflow = 0;
+ register int digits_found = 0, digit;
for (;;)
{
c = *(*string_ptr)++;
@@ -570,11 +598,10 @@ cpp_parse_escape (pfile, string_ptr)
}
if (!digits_found)
cpp_error (pfile, "\\x used with no following hex digits");
- if (overflow | (i & ~((1 << BITS_PER_UNIT) - 1)))
+ if (overflow | (i != (i & result_mask)))
{
- i &= (1 << BITS_PER_UNIT) - 1;
- cpp_pedwarn (pfile,
- "hex character constant does not fit in a byte");
+ i &= result_mask;
+ cpp_pedwarn (pfile, "hex escape sequence out of range");
}
return i;
}
@@ -591,41 +618,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;
+ HOST_WIDEST_INT a;
int unsignedp;
- unsigned long b;
+ 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;
+ HOST_WIDEST_INT a;
int unsignedp;
- unsigned long b;
+ 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;
}
@@ -649,12 +676,13 @@ right_shift (pfile, a, unsignedp, b)
#define COMPARE(OP) \
top->unsignedp = 0;\
- top->value = (unsigned1 || unsigned2) ? (unsigned long) v1 OP v2 : (v1 OP v2)
+ top->value = (unsigned1 || unsigned2) \
+ ? (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. */
-HOST_WIDE_INT
+HOST_WIDEST_INT
cpp_parse_expr (pfile)
cpp_reader *pfile;
{
@@ -734,6 +762,8 @@ cpp_parse_expr (pfile)
case '?':
lprio = COND_PRIO + 1; rprio = COND_PRIO;
goto maybe_reduce;
+ case ERROR:
+ goto syntax_error;
binop:
flags = LEFT_OPERAND_REQUIRED|RIGHT_OPERAND_REQUIRED;
rprio = lprio + 1;
@@ -757,7 +787,7 @@ cpp_parse_expr (pfile)
/* Push an operator, and check if we can reduce now. */
while (top->rprio > lprio)
{
- long v1 = top[-1].value, v2 = top[0].value;
+ HOST_WIDEST_INT 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)
@@ -812,7 +842,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;
@@ -832,7 +862,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;
@@ -850,7 +880,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;
@@ -967,11 +997,11 @@ cpp_parse_expr (pfile)
}
break;
default:
- fprintf (stderr,
- top[1].op >= ' ' && top[1].op <= '~'
- ? "unimplemented operator '%c'\n"
- : "unimplemented operator '\\%03o'\n",
- top[1].op);
+ cpp_error (pfile,
+ (top[1].op >= ' ' && top[1].op <= '~'
+ ? "unimplemented operator '%c'\n"
+ : "unimplemented operator '\\%03o'\n"),
+ top[1].op);
}
}
if (op.op == 0)