/* Parse C expressions for cpplib.
- Copyright (C) 1987, 1992, 1994, 1995, 1997, 1998, 1999, 2000, 2001
- Free Software Foundation.
+ Copyright (C) 1987, 1992, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
+ 2002 Free Software Foundation.
Contributed by Per Bothner, 1994.
This program is free software; you can redistribute it and/or modify it
unsigned HOST_WIDEST_INT));
static struct op parse_number PARAMS ((cpp_reader *, const cpp_token *));
static struct op parse_defined PARAMS ((cpp_reader *));
-static struct op lex PARAMS ((cpp_reader *, int, cpp_token *));
+static struct op lex PARAMS ((cpp_reader *, int));
static const unsigned char *op_as_text PARAMS ((cpp_reader *, enum cpp_ttype));
struct op
{
enum cpp_ttype op;
- U_CHAR prio; /* Priority of op. */
- U_CHAR flags;
- U_CHAR unsignedp; /* True if value should be treated as unsigned. */
+ uchar prio; /* Priority of op. */
+ uchar flags;
+ uchar unsignedp; /* True if value should be treated as unsigned. */
HOST_WIDEST_INT value; /* The value logically "right" of op. */
};
/* With -O2, gcc appears to produce nice code, moving the error
message load and subsequent jump completely out of the main path. */
-#define CPP_ICE(msgid) \
- do { cpp_ice (pfile, msgid); goto syntax_error; } while(0)
#define SYNTAX_ERROR(msgid) \
- do { cpp_error (pfile, msgid); goto syntax_error; } while(0)
+ do { cpp_error (pfile, DL_ERROR, msgid); goto syntax_error; } while(0)
#define SYNTAX_ERROR2(msgid, arg) \
- do { cpp_error (pfile, msgid, arg); goto syntax_error; } while(0)
+ do { cpp_error (pfile, DL_ERROR, msgid, arg); goto syntax_error; } while(0)
struct suffix
{
- unsigned char s[4];
- unsigned char u;
- unsigned char l;
+ const unsigned char s[4];
+ const unsigned char u;
+ const unsigned char l;
};
-const struct suffix vsuf_1[] = {
+static const struct suffix vsuf_1[] = {
{ "u", 1, 0 }, { "U", 1, 0 },
{ "l", 0, 1 }, { "L", 0, 1 }
};
-const struct suffix vsuf_2[] = {
+static const struct suffix vsuf_2[] = {
{ "ul", 1, 1 }, { "UL", 1, 1 }, { "uL", 1, 1 }, { "Ul", 1, 1 },
{ "lu", 1, 1 }, { "LU", 1, 1 }, { "Lu", 1, 1 }, { "lU", 1, 1 },
{ "ll", 0, 2 }, { "LL", 0, 2 }
};
-const struct suffix vsuf_3[] = {
+static const struct suffix vsuf_3[] = {
{ "ull", 1, 2 }, { "ULL", 1, 2 }, { "uLL", 1, 2 }, { "Ull", 1, 2 },
{ "llu", 1, 2 }, { "LLU", 1, 2 }, { "LLu", 1, 2 }, { "llU", 1, 2 }
};
-#define Nsuff(tab) (sizeof tab / sizeof (struct suffix))
-
-/* Parse and convert an integer for #if. Accepts decimal, hex, or
- octal with or without size suffixes. Returned op is CPP_ERROR on
- error, otherwise it is a CPP_NUMBER. */
+/* Parse and convert what is presumably an integer in TOK. Accepts
+ decimal, hex, or octal with or without size suffixes. Returned op
+ is CPP_ERROR on error, otherwise it is a CPP_NUMBER. */
static struct op
parse_number (pfile, tok)
cpp_reader *pfile;
const cpp_token *tok;
{
struct op op;
- const U_CHAR *start = tok->val.str.text;
- const U_CHAR *end = start + tok->val.str.len;
- const U_CHAR *p = start;
+ const uchar *start = tok->val.str.text;
+ const uchar *end = start + tok->val.str.len;
+ const uchar *p = start;
int c = 0, i, nsuff;
unsigned HOST_WIDEST_INT n = 0, nd, MAX_over_base;
int base = 10;
{
c = *p;
- if (c >= '0' && c <= '9')
- digit = c - '0';
- /* We believe that in all live character sets, a-f are
- consecutive, and so are A-F. */
- else if (base == 16 && c >= 'a' && c <= 'f')
- digit = c - 'a' + 10;
- else if (base == 16 && c >= 'A' && c <= 'F')
- digit = c - 'A' + 10;
+ if (ISDIGIT (c)
+ || (base == 16 && ISXDIGIT (c)))
+ digit = hex_value (c);
else
break;
See the suffix tables, above. */
switch (end - p)
{
- case 1: sufftab = vsuf_1; nsuff = Nsuff(vsuf_1); break;
- case 2: sufftab = vsuf_2; nsuff = Nsuff(vsuf_2); break;
- case 3: sufftab = vsuf_3; nsuff = Nsuff(vsuf_3); break;
+ case 1: sufftab = vsuf_1; nsuff = ARRAY_SIZE (vsuf_1); break;
+ case 2: sufftab = vsuf_2; nsuff = ARRAY_SIZE (vsuf_2); break;
+ case 3: sufftab = vsuf_3; nsuff = ARRAY_SIZE (vsuf_3); break;
default: goto invalid_suffix;
}
if (CPP_WTRADITIONAL (pfile)
&& sufftab[i].u
&& ! cpp_sys_macro_p (pfile))
- cpp_warning (pfile, "traditional C rejects the `U' suffix");
+ cpp_error (pfile, DL_WARNING, "traditional C rejects the `U' suffix");
if (sufftab[i].l == 2 && CPP_OPTION (pfile, pedantic)
&& ! CPP_OPTION (pfile, c99))
- cpp_pedwarn (pfile, "too many 'l' suffixes in integer constant");
+ cpp_error (pfile, DL_PEDWARN,
+ "too many 'l' suffixes in integer constant");
}
if (base <= largest_digit)
- cpp_pedwarn (pfile, "integer constant contains digits beyond the radix");
+ cpp_error (pfile, DL_PEDWARN,
+ "integer constant contains digits beyond the radix");
if (overflow)
- cpp_pedwarn (pfile, "integer constant out of range");
+ cpp_error (pfile, DL_PEDWARN, "integer constant out of range");
/* If too big to be signed, consider it unsigned. */
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_error (pfile, DL_WARNING,
+ "integer constant is so large that it is unsigned");
op.unsignedp = 1;
}
return op;
invalid_suffix:
- cpp_error (pfile, "invalid suffix '%.*s' on integer constant",
+ cpp_error (pfile, DL_ERROR, "invalid suffix '%.*s' on integer constant",
(int) (end - p), p);
syntax_error:
op.op = CPP_ERROR;
return op;
}
+/* Handle meeting "defined" in a preprocessor expression. */
static struct op
parse_defined (pfile)
cpp_reader *pfile;
{
int paren = 0;
cpp_hashnode *node = 0;
- cpp_token token;
+ const cpp_token *token;
struct op op;
+ cpp_context *initial_context = pfile->context;
/* Don't expand macros. */
pfile->state.prevent_expansion++;
- cpp_get_token (pfile, &token);
- if (token.type == CPP_OPEN_PAREN)
+ token = cpp_get_token (pfile);
+ if (token->type == CPP_OPEN_PAREN)
{
paren = 1;
- cpp_get_token (pfile, &token);
+ token = cpp_get_token (pfile);
}
- if (token.type == CPP_NAME)
+ if (token->type == CPP_NAME)
{
- node = token.val.node;
- if (paren)
+ node = token->val.node;
+ if (paren && cpp_get_token (pfile)->type != CPP_CLOSE_PAREN)
{
- cpp_get_token (pfile, &token);
- if (token.type != CPP_CLOSE_PAREN)
- {
- cpp_error (pfile, "missing ')' after \"defined\"");
- node = 0;
- }
+ cpp_error (pfile, DL_ERROR, "missing ')' after \"defined\"");
+ node = 0;
}
}
else
{
- cpp_error (pfile, "operator \"defined\" requires an identifier");
- if (token.flags & NAMED_OP)
+ cpp_error (pfile, DL_ERROR,
+ "operator \"defined\" requires an identifier");
+ if (token->flags & NAMED_OP)
{
cpp_token op;
op.flags = 0;
- op.type = token.type;
- cpp_error (pfile,
+ op.type = token->type;
+ cpp_error (pfile, DL_ERROR,
"(\"%s\" is an alternative token for \"%s\" in C++)",
- cpp_token_as_text (pfile, &token),
+ cpp_token_as_text (pfile, token),
cpp_token_as_text (pfile, &op));
}
}
op.op = CPP_ERROR;
else
{
+ if (pfile->context != initial_context)
+ cpp_error (pfile, DL_WARNING,
+ "this use of \"defined\" may not be portable");
+
op.value = node->type == NT_MACRO;
op.unsignedp = 0;
op.op = CPP_NUMBER;
(an interpreted preprocessing number or character constant, or the
result of the "defined" or "#" operators), CPP_ERROR on error,
CPP_EOF, or the type of an operator token. */
-
static struct op
-lex (pfile, skip_evaluation, token)
+lex (pfile, skip_evaluation)
cpp_reader *pfile;
int skip_evaluation;
- cpp_token *token;
{
struct op op;
-
- cpp_get_token (pfile, token);
+ const cpp_token *token = cpp_get_token (pfile);
switch (token->type)
{
{
unsigned int chars_seen;
- /* This is always a signed type. */
- op.unsignedp = 0;
+ if (token->type == CPP_CHAR)
+ op.unsignedp = 0;
+ else
+ op.unsignedp = WCHAR_UNSIGNED;
op.op = CPP_NUMBER;
- op.value = cpp_interpret_charconst (pfile, token, 1, 0, &chars_seen);
+ op.value = cpp_interpret_charconst (pfile, token, 1, &chars_seen);
return op;
}
case CPP_NAME:
if (token->val.node == pfile->spec_nodes.n_defined)
- {
- if (pfile->context->prev && CPP_PEDANTIC (pfile))
- cpp_pedwarn (pfile, "\"defined\" operator appears during macro expansion");
-
- return parse_defined (pfile);
- }
+ return parse_defined (pfile);
else if (CPP_OPTION (pfile, cplusplus)
&& (token->val.node == pfile->spec_nodes.n_true
|| token->val.node == pfile->spec_nodes.n_false))
and stdbool.h has not been included. */
if (CPP_PEDANTIC (pfile)
&& ! cpp_defined (pfile, DSC("__bool_true_false_are_defined")))
- cpp_pedwarn (pfile, "ISO C++ does not permit \"%s\" in #if",
- NODE_NAME (token->val.node));
+ cpp_error (pfile, DL_PEDWARN,
+ "ISO C++ does not permit \"%s\" in #if",
+ NODE_NAME (token->val.node));
return op;
}
else
op.value = 0;
if (CPP_OPTION (pfile, warn_undef) && !skip_evaluation)
- cpp_warning (pfile, "\"%s\" is not defined",
- NODE_NAME (token->val.node));
+ cpp_error (pfile, DL_WARNING, "\"%s\" is not defined",
+ NODE_NAME (token->val.node));
return op;
}
return op;
}
+/* Warn if appropriate on overflow. */
static void
integer_overflow (pfile)
cpp_reader *pfile;
{
if (CPP_PEDANTIC (pfile))
- cpp_pedwarn (pfile, "integer overflow in preprocessor expression");
+ cpp_error (pfile, DL_PEDWARN,
+ "integer overflow in preprocessor expression");
}
+/* Handle shifting A left by B bits. UNSIGNEDP is non-zero if A is
+ unsigned. */
static HOST_WIDEST_INT
left_shift (pfile, a, unsignedp, b)
cpp_reader *pfile;
}
}
+/* Handle shifting A right by B bits. UNSIGNEDP is non-zero if A is
+ unsigned. */
static HOST_WIDEST_INT
right_shift (pfile, a, unsignedp, b)
cpp_reader *pfile ATTRIBUTE_UNUSED;
#define FLAG_BITS 8
#define FLAG_MASK ((1 << FLAG_BITS) - 1)
#define PRIO_SHIFT (FLAG_BITS + 1)
-#define EXTRACT_PRIO(cnst) (cnst >> FLAG_BITS)
-#define EXTRACT_FLAGS(cnst) (cnst & FLAG_MASK)
+#define EXTRACT_PRIO(CNST) ((CNST) >> FLAG_BITS)
+#define EXTRACT_FLAGS(CNST) ((CNST) & FLAG_MASK)
/* Flags. */
#define HAVE_VALUE (1 << 0)
/* Parse and evaluate a C expression, reading from PFILE.
Returns the truth value of the expression. */
-
int
_cpp_parse_expr (pfile)
cpp_reader *pfile;
struct op init_stack[INIT_STACK_SIZE];
struct op *stack = init_stack;
struct op *limit = stack + INIT_STACK_SIZE;
- cpp_token token;
- register struct op *top = stack + 1;
+ struct op *top = stack + 1;
int skip_evaluation = 0;
int result;
unsigned int lex_count, saw_leading_not;
struct op op;
/* Read a token */
- op = lex (pfile, skip_evaluation, &token);
+ op = lex (pfile, skip_evaluation);
lex_count++;
/* If the token is an operand, push its value and get next
switch (top[1].op)
{
default:
- cpp_ice (pfile, "impossible operator '%s'",
- op_as_text (pfile, top[1].op));
+ cpp_error (pfile, DL_ICE, "impossible operator '%s'",
+ op_as_text (pfile, top[1].op));
goto syntax_error;
case CPP_NOT: UNARY(!); break;
top->flags |= HAVE_VALUE;
if (CPP_WTRADITIONAL (pfile))
- cpp_warning (pfile,
+ cpp_error (pfile, DL_WARNING,
"traditional C rejects the unary plus operator");
}
else
break;
case CPP_COMMA:
if (CPP_PEDANTIC (pfile))
- cpp_pedwarn (pfile, "comma operator in operand of #if");
+ cpp_error (pfile, DL_PEDWARN,
+ "comma operator in operand of #if");
top->value = v2;
top->unsignedp = unsigned2;
break;
{
if (top->flags & HAVE_VALUE)
SYNTAX_ERROR2 ("missing binary operator before '%s'",
- op_as_text (pfile, top->op));
+ op_as_text (pfile, op.op));
}
else
{
if (!(top->flags & HAVE_VALUE))
SYNTAX_ERROR2 ("operator '%s' has no left operand",
- op_as_text (pfile, top->op));
+ op_as_text (pfile, op.op));
}
/* Check for and handle stack overflow. */
result = (top[1].value != 0);
if (top != stack)
- CPP_ICE ("unbalanced stack in #if");
+ {
+ cpp_error (pfile, DL_ICE, "unbalanced stack in #if");
+ goto syntax_error;
+ }
else if (!(top[1].flags & HAVE_VALUE))
{
SYNTAX_ERROR ("#if with no expression");
return result;
}
+/* Output OP as text for diagnostics. */
static const unsigned char *
op_as_text (pfile, op)
cpp_reader *pfile;