summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/cppexp.c
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>1999-08-26 09:30:50 +0000
committerobrien <obrien@FreeBSD.org>1999-08-26 09:30:50 +0000
commit0bedf4fb30066e5e1d4342a1d3914dae7d37cba7 (patch)
tree68d8110b41afd0ebbf39167b1a4918eea667a7c5 /contrib/gcc/cppexp.c
parentd4db5fb866b7ad5216abd5047774a3973b9901a9 (diff)
downloadFreeBSD-src-0bedf4fb30066e5e1d4342a1d3914dae7d37cba7.zip
FreeBSD-src-0bedf4fb30066e5e1d4342a1d3914dae7d37cba7.tar.gz
Virgin import of gcc from EGCS 1.1.2
Diffstat (limited to 'contrib/gcc/cppexp.c')
-rw-r--r--contrib/gcc/cppexp.c182
1 files changed, 106 insertions, 76 deletions
diff --git a/contrib/gcc/cppexp.c b/contrib/gcc/cppexp.c
index 6b73ad3..44f8a66 100644
--- a/contrib/gcc/cppexp.c
+++ b/contrib/gcc/cppexp.c
@@ -1,5 +1,5 @@
/* Parse C expressions for CCCP.
- Copyright (C) 1987, 1992, 1994, 1995 Free Software Foundation.
+ Copyright (C) 1987, 1992, 1994, 1995, 1997, 1998 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
@@ -20,23 +20,22 @@ Boston, MA 02111-1307, USA.
You are forbidden to forbid anyone else to use, share and improve
what you give them. Help stamp out software-hoarding!
-Written by Per Bothner 1994. */
+Written by Per Bothner 1994. */
/* Parse a C expression from text in a string */
#include "config.h"
+#include "system.h"
+#include "gansidecl.h"
#include "cpplib.h"
extern char *xmalloc PARAMS ((unsigned));
-extern char *xrealloc PARAMS ((char *, unsigned));
+extern char *xrealloc PARAMS ((void *, unsigned));
#ifdef MULTIBYTE_CHARS
-#include <stdlib.h>
#include <locale.h>
#endif
-#include <stdio.h>
-
/* This is used for communicating lists of keywords with cccp.c. */
struct arglist {
struct arglist *next;
@@ -45,26 +44,6 @@ struct arglist {
int argno;
};
-/* Define a generic NULL if one hasn't already been defined. */
-
-#ifndef NULL
-#define NULL 0
-#endif
-
-#ifndef GENERIC_PTR
-#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
-#define GENERIC_PTR void *
-#else
-#define GENERIC_PTR char *
-#endif
-#endif
-
-#ifndef NULL_PTR
-#define NULL_PTR ((GENERIC_PTR)0)
-#endif
-
-extern char *xmalloc ();
-
#ifndef CHAR_TYPE_SIZE
#define CHAR_TYPE_SIZE BITS_PER_UNIT
#endif
@@ -101,9 +80,9 @@ extern char *xmalloc ();
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 ();
-static long left_shift ();
-static long right_shift ();
+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));
#define ERROR 299
#define OROR 300
@@ -121,26 +100,47 @@ static long right_shift ();
#define LEFT_OPERAND_REQUIRED 1
#define RIGHT_OPERAND_REQUIRED 2
#define HAVE_VALUE 4
-/*#define UNSIGNEDP 8*/
-
-#ifndef HOST_BITS_PER_WIDE_INT
+/* SKIP_OPERAND is set for '&&' '||' '?' and ':' when the
+ following operand should be short-circuited instead of evaluated. */
+#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
-#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 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 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_WIDE_INT value; /* The value logically "right" of op. */
};
/* Take care of parsing a number (anything that starts with a digit).
@@ -183,7 +183,7 @@ parse_number (pfile, start, olen)
else if (*p == '0')
base = 8;
- /* Some buggy compilers (e.g. MPW C) seem to need both casts. */
+ /* 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--) {
@@ -223,7 +223,7 @@ parse_number (pfile, start, olen)
if (largest_digit < digit)
largest_digit = digit;
nd = n * base + digit;
- overflow |= ULONG_MAX_over_base < n | nd < n;
+ overflow |= ULONG_MAX_over_base < n || nd < n;
n = nd;
}
@@ -235,10 +235,10 @@ parse_number (pfile, start, olen)
}
if (base <= largest_digit)
- cpp_warning (pfile, "integer constant contains digits beyond the radix");
+ cpp_pedwarn (pfile, "integer constant contains digits beyond the radix");
if (overflow)
- cpp_warning (pfile, "integer constant out of range");
+ cpp_pedwarn (pfile, "integer constant out of range");
/* If too big to be signed, consider it unsigned. */
if ((long) n < 0 && ! op.unsignedp)
@@ -272,14 +272,14 @@ static struct token tokentab2[] = {
{NULL, ERROR}
};
-/* Read one token. */
+/* Read one token. */
struct operation
-cpp_lex (pfile)
-cpp_reader *pfile;
+cpp_lex (pfile, skip_evaluation)
+ cpp_reader *pfile;
+ int skip_evaluation;
{
register int c;
- register int namelen;
register struct token *toktab;
enum cpp_token token;
struct operation op;
@@ -307,16 +307,17 @@ cpp_reader *pfile;
pfile->limit = tok_start;
switch (token)
{
- case CPP_EOF: /* Should not happen ... */
+ case CPP_EOF: /* Should not happen ... */
+ case CPP_VSPACE:
op.op = 0;
return op;
- case CPP_VSPACE:
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;
@@ -332,7 +333,7 @@ cpp_reader *pfile;
It is mostly copied from c-lex.c. */
{
register int result = 0;
- register num_chars = 0;
+ register int num_chars = 0;
unsigned width = MAX_CHAR_TYPE_SIZE;
int wide_flag = 0;
int max_chars;
@@ -362,7 +363,7 @@ cpp_reader *pfile;
{
if (c == '\\')
{
- c = cpp_parse_escape (pfile, &ptr);
+ c = cpp_parse_escape (pfile, (char **) &ptr);
if (width < HOST_BITS_PER_INT
&& (unsigned) c >= (1 << width))
cpp_pedwarn (pfile,
@@ -401,7 +402,7 @@ cpp_reader *pfile;
{
int num_bits = num_chars * width;
- if (cpp_lookup (pfile, "__CHAR_UNSIGNED__",
+ if (cpp_lookup (pfile, (U_CHAR *)"__CHAR_UNSIGNED__",
sizeof ("__CHAR_UNSIGNED__")-1, -1)
|| ((result >> (num_bits - 1)) & 1) == 0)
op.value
@@ -425,7 +426,7 @@ cpp_reader *pfile;
if (mbtowc (& wc, token_buffer, num_chars) == num_chars)
result = wc;
else
- cpp_warning (pfile,"Ignoring invalid multibyte character");
+ cpp_pedwarn (pfile,"Ignoring invalid multibyte character");
}
#endif
op.value = result;
@@ -439,6 +440,9 @@ cpp_reader *pfile;
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);
case CPP_OTHER:
@@ -538,7 +542,7 @@ cpp_parse_escape (pfile, string_ptr)
if ((i & ~((1 << MAX_CHAR_TYPE_SIZE) - 1)) != 0)
{
i &= (1 << MAX_CHAR_TYPE_SIZE) - 1;
- cpp_warning (pfile,
+ cpp_pedwarn (pfile,
"octal character constant does not fit in a byte");
}
return i;
@@ -569,7 +573,7 @@ cpp_parse_escape (pfile, string_ptr)
if (overflow | (i & ~((1 << BITS_PER_UNIT) - 1)))
{
i &= (1 << BITS_PER_UNIT) - 1;
- cpp_warning (pfile,
+ cpp_pedwarn (pfile,
"hex character constant does not fit in a byte");
}
return i;
@@ -613,7 +617,7 @@ left_shift (pfile, a, unsignedp, b)
static long
right_shift (pfile, a, unsignedp, b)
- cpp_reader *pfile;
+ cpp_reader *pfile ATTRIBUTE_UNUSED;
long a;
int unsignedp;
unsigned long b;
@@ -626,7 +630,7 @@ right_shift (pfile, a, unsignedp, b)
return a >> b;
}
-/* These priorities are all even, so we can handle associatively. */
+/* 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)
@@ -670,6 +674,7 @@ cpp_parse_expr (pfile)
struct operation *limit = stack + INIT_STACK_SIZE;
register struct operation *top = stack;
int lprio, rprio;
+ int skip_evaluation = 0;
top->rprio = 0;
top->flags = 0;
@@ -679,17 +684,16 @@ cpp_parse_expr (pfile)
char flags = 0;
/* Read a token */
- op = cpp_lex (pfile);
+ op = cpp_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
- priorities, and then goto maybe_reduce. */
+ priorities, and then goto maybe_reduce. */
switch (op.op)
{
case NAME:
- top->value = 0, top->unsignedp = 0;
- goto set_value;
+ abort ();
case INT: case CHAR:
top->value = op.value;
top->unsignedp = op.unsignedp;
@@ -740,7 +744,7 @@ cpp_parse_expr (pfile)
}
set_value:
- /* Push a value onto the stack. */
+ /* Push a value onto the stack. */
if (top->flags & HAVE_VALUE)
{
cpp_error (pfile, "syntax error in #if");
@@ -750,7 +754,7 @@ cpp_parse_expr (pfile)
continue;
maybe_reduce:
- /* Push an operator, and check if we can reduce now. */
+ /* Push an operator, and check if we can reduce now. */
while (top->rprio > lprio)
{
long v1 = top[-1].value, v2 = top[0].value;
@@ -782,7 +786,7 @@ cpp_parse_expr (pfile)
{
top->value = v1 + v2;
top->unsignedp = unsigned1 || unsigned2;
- if (! top->unsignedp
+ if (! top->unsignedp && ! skip_evaluation
&& ! possible_sum_sign (v1, v2, top->value))
integer_overflow (pfile);
}
@@ -791,7 +795,7 @@ cpp_parse_expr (pfile)
if (!(top->flags & HAVE_VALUE))
{ /* Unary '-' */
top->value = - v2;
- if ((top->value & v2) < 0 && ! unsigned2)
+ if (!skip_evaluation && (top->value & v2) < 0 && !unsigned2)
integer_overflow (pfile);
top->unsignedp = unsigned2;
top->flags |= HAVE_VALUE;
@@ -800,7 +804,7 @@ cpp_parse_expr (pfile)
{ /* Binary '-' */
top->value = v1 - v2;
top->unsignedp = unsigned1 || unsigned2;
- if (! top->unsignedp
+ if (! top->unsignedp && ! skip_evaluation
&& ! possible_sum_sign (top->value, v2, v1))
integer_overflow (pfile);
}
@@ -809,7 +813,7 @@ cpp_parse_expr (pfile)
top->unsignedp = unsigned1 || unsigned2;
if (top->unsignedp)
top->value = (unsigned long) v1 * v2;
- else
+ else if (!skip_evaluation)
{
top->value = v1 * v2;
if (v1
@@ -819,6 +823,8 @@ cpp_parse_expr (pfile)
}
break;
case '/':
+ if (skip_evaluation)
+ break;
if (v2 == 0)
{
cpp_error (pfile, "division by zero in #if");
@@ -835,6 +841,8 @@ cpp_parse_expr (pfile)
}
break;
case '%':
+ if (skip_evaluation)
+ break;
if (v2 == 0)
{
cpp_error (pfile, "division by zero in #if");
@@ -879,6 +887,8 @@ cpp_parse_expr (pfile)
top->unsignedp = 0;
break;
case LSH:
+ if (skip_evaluation)
+ break;
top->unsignedp = unsigned1;
if (v2 < 0 && ! unsigned2)
top->value = right_shift (pfile, v1, unsigned1, -v2);
@@ -886,6 +896,8 @@ cpp_parse_expr (pfile)
top->value = left_shift (pfile, v1, unsigned1, v2);
break;
case RSH:
+ if (skip_evaluation)
+ break;
top->unsignedp = unsigned1;
if (v2 < 0 && ! unsigned2)
top->value = left_shift (pfile, v1, unsigned1, -v2);
@@ -899,9 +911,13 @@ cpp_parse_expr (pfile)
case '^': LOGICAL(^); break;
case '|': LOGICAL(|); break;
case ANDAND:
- top->value = v1 && v2; top->unsignedp = 0; break;
+ top->value = v1 && v2; top->unsignedp = 0;
+ if (!v1) skip_evaluation--;
+ break;
case OROR:
- top->value = v1 || v2; top->unsignedp = 0; break;
+ top->value = v1 || v2; top->unsignedp = 0;
+ if (v1) skip_evaluation--;
+ break;
case ',':
if (CPP_PEDANTIC (pfile))
cpp_pedwarn (pfile, "comma operator in operand of `#if'");
@@ -928,6 +944,7 @@ cpp_parse_expr (pfile)
else
{
top--;
+ if (top->value) skip_evaluation--;
top->value = top->value ? v1 : v2;
top->unsignedp = unsigned1 || unsigned2;
}
@@ -967,27 +984,40 @@ cpp_parse_expr (pfile)
}
top++;
- /* Check for and handle stack overflow. */
+ /* Check for and handle stack overflow. */
if (top == limit)
{
struct operation *new_stack;
- int old_size = (char*)limit - (char*)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);
+ new_stack = (struct operation *) xrealloc (stack, new_size);
else
{
- new_stack = (struct operation*) xmalloc (new_size);
+ 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 = (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;
+ if ((op.op == OROR && top[-1].value)
+ || (op.op == ANDAND && !top[-1].value)
+ || (op.op == '?' && !top[-1].value))
+ {
+ skip_evaluation++;
+ }
+ else if (op.op == ':')
+ {
+ if (top[-2].value) /* Was condition true? */
+ skip_evaluation++;
+ else
+ skip_evaluation--;
+ }
}
syntax_error:
if (stack != init_stack)
OpenPOWER on IntegriCloud