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
#define SYNTAX_ERROR2(msgid, arg) \
do { cpp_error (pfile, msgid, arg); goto syntax_error; } while(0)
-/* Parse and convert an integer for #if. Accepts decimal, hex, or octal
- with or without size suffixes. */
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. */
+
static struct op
parse_number (pfile, tok)
cpp_reader *pfile;
{
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;
}
op.value = n;
- op.op = CPP_INT;
+ op.op = CPP_NUMBER;
return op;
invalid_suffix:
{
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, "missing ')' after \"defined\"");
+ node = 0;
}
}
else
{
cpp_error (pfile, "operator \"defined\" requires an identifier");
- if (token.flags & NAMED_OP)
+ if (token->flags & NAMED_OP)
{
cpp_token op;
op.flags = 0;
- op.type = token.type;
+ op.type = token->type;
cpp_error (pfile,
"(\"%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_warning (pfile, "this use of \"defined\" may not be portable");
+
op.value = node->type == NT_MACRO;
op.unsignedp = 0;
- op.op = CPP_INT;
+ op.op = CPP_NUMBER;
- /* No macros? At top of file? */
- if (pfile->mi_state == MI_OUTSIDE && pfile->mi_cmacro == 0
- && pfile->mi_if_not_defined == MI_IND_NOT && pfile->mi_lexed == 1)
- {
- cpp_start_lookahead (pfile);
- cpp_get_token (pfile, &token);
- if (token.type == CPP_EOF)
- pfile->mi_ind_cmacro = node;
- cpp_stop_lookahead (pfile, 0);
- }
+ /* A possible controlling macro of the form #if !defined ().
+ _cpp_parse_expr checks there was no other junk on the line. */
+ pfile->mi_ind_cmacro = node;
}
pfile->state.prevent_expansion--;
return op;
}
-/* Read one token. */
+/* Read a token. The returned type is CPP_NUMBER for a valid 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)
{
- case CPP_INT:
case CPP_NUMBER:
return parse_number (pfile, token);
/* This is always a signed type. */
op.unsignedp = 0;
- op.op = CPP_INT;
+ op.op = CPP_NUMBER;
op.value = cpp_interpret_charconst (pfile, token, 1, 0, &chars_seen);
return op;
}
case CPP_WSTRING:
SYNTAX_ERROR ("string constants are not valid in #if");
- case CPP_FLOAT:
- SYNTAX_ERROR ("floating point numbers are not valid in #if");
-
case CPP_OTHER:
if (ISGRAPH (token->val.c))
SYNTAX_ERROR2 ("invalid character '%c' in #if", token->val.c);
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))
{
- op.op = CPP_INT;
+ op.op = CPP_NUMBER;
op.unsignedp = 0;
op.value = (token->val.node == pfile->spec_nodes.n_true);
if (CPP_PEDANTIC (pfile)
&& ! cpp_defined (pfile, DSC("__bool_true_false_are_defined")))
cpp_pedwarn (pfile, "ISO C++ does not permit \"%s\" in #if",
- token->val.node->name);
+ NODE_NAME (token->val.node));
return op;
}
else
{
- /* Controlling #if expressions cannot contain identifiers (they
- could become macros in the future). */
- pfile->mi_state = MI_FAILED;
-
- op.op = CPP_INT;
+ op.op = CPP_NUMBER;
op.unsignedp = 0;
op.value = 0;
if (CPP_OPTION (pfile, warn_undef) && !skip_evaluation)
- cpp_warning (pfile, "\"%s\" is not defined", token->val.node->name);
+ cpp_warning (pfile, "\"%s\" is not defined",
+ NODE_NAME (token->val.node));
return op;
}
{
int temp;
- op.op = CPP_INT;
+ op.op = CPP_NUMBER;
if (_cpp_test_assertion (pfile, &temp))
op.op = CPP_ERROR;
op.unsignedp = 0;
return op;
}
- case CPP_NOT:
- /* We don't worry about its position here. */
- pfile->mi_if_not_defined = MI_IND_NOT;
- /* Fall through. */
-
default:
if (((int) token->type > (int) CPP_EQ
&& (int) token->type < (int) CPP_PLUS_EQ)
#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)
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;
/* Set up detection of #if ! defined(). */
- pfile->mi_lexed = 0;
- pfile->mi_if_not_defined = MI_IND_NONE;
+ pfile->mi_ind_cmacro = 0;
+ saw_leading_not = 0;
+ lex_count = 0;
/* We've finished when we try to reduce this. */
top->op = CPP_EOF;
struct op op;
/* Read a token */
- op = lex (pfile, skip_evaluation, &token);
- pfile->mi_lexed++;
+ op = lex (pfile, skip_evaluation);
+ lex_count++;
/* If the token is an operand, push its value and get next
token. If it is an operator, get its priority and flags, and
case CPP_ERROR:
goto syntax_error;
push_immediate:
- case CPP_INT:
+ case CPP_NUMBER:
/* Push a value onto the stack. */
if (top->flags & HAVE_VALUE)
SYNTAX_ERROR ("missing binary operator");
continue;
case CPP_EOF: prio = FORCE_REDUCE_PRIO; break;
+
+ case CPP_NOT:
+ saw_leading_not = lex_count == 1;
+ prio = op_to_prio[op.op];
+ break;
case CPP_PLUS:
case CPP_MINUS: prio = PLUS_PRIO; if (top->flags & HAVE_VALUE) break;
/* else unary; fall through */
{
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. */
}
done:
+ /* The controlling macro expression is only valid if we called lex 3
+ times: <!> <defined expression> and <EOF>. push_conditional ()
+ checks that we are at top-of-file. */
+ if (pfile->mi_ind_cmacro && !(saw_leading_not && lex_count == 3))
+ pfile->mi_ind_cmacro = 0;
+
result = (top[1].value != 0);
+
if (top != stack)
CPP_ICE ("unbalanced stack in #if");
else if (!(top[1].flags & HAVE_VALUE))