diff options
author | obrien <obrien@FreeBSD.org> | 1999-08-26 09:30:50 +0000 |
---|---|---|
committer | obrien <obrien@FreeBSD.org> | 1999-08-26 09:30:50 +0000 |
commit | 0bedf4fb30066e5e1d4342a1d3914dae7d37cba7 (patch) | |
tree | 68d8110b41afd0ebbf39167b1a4918eea667a7c5 /contrib/gcc/cppexp.c | |
parent | d4db5fb866b7ad5216abd5047774a3973b9901a9 (diff) | |
download | FreeBSD-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.c | 182 |
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) |