/* Parse C expressions for cpplib.
Copyright (C) 1987, 92, 94, 95, 97, 98, 1999, 2000 Free Software Foundation.
+ Contributed by Per Bothner, 1994.
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
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
-
- In other words, you are welcome to use, share and improve this program.
- 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. */
+Boston, MA 02111-1307, USA. */
/* Parse a C expression from text in a string */
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)
-typedef short op_t;
+typedef int op_t;
static void integer_overflow PARAMS ((cpp_reader *));
static HOST_WIDEST_INT left_shift PARAMS ((cpp_reader *, HOST_WIDEST_INT,
static struct operation parse_charconst PARAMS ((cpp_reader *, U_CHAR *,
U_CHAR *));
static struct operation parse_defined PARAMS ((cpp_reader *));
+static struct operation parse_assertion PARAMS ((cpp_reader *));
static HOST_WIDEST_INT parse_escape PARAMS ((cpp_reader *, U_CHAR **,
HOST_WIDEST_INT));
static struct operation lex PARAMS ((cpp_reader *, int));
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)
+#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. */
/* If char type is signed, sign-extend the constant. */
num_bits = num_chars * width;
- if (cpp_defined (pfile, (const U_CHAR *)"__CHAR_UNSIGNED__",
+ if (cpp_defined (pfile, U"__CHAR_UNSIGNED__",
sizeof ("__CHAR_UNSIGNED__")-1)
|| ((result >> (num_bits - 1)) & 1) == 0)
op.value = result & ((unsigned HOST_WIDEST_INT) ~0
pfile->no_macro_expand++;
token = _cpp_get_directive_token (pfile);
- if (token == CPP_LPAREN)
+ if (token == CPP_OPEN_PAREN)
{
paren++;
CPP_SET_WRITTEN (pfile, old_written);
if (paren)
{
- if (_cpp_get_directive_token (pfile) != CPP_RPAREN)
+ if (_cpp_get_directive_token (pfile) != CPP_CLOSE_PAREN)
goto oops;
}
CPP_SET_WRITTEN (pfile, old_written);
return op;
}
+static struct operation
+parse_assertion (pfile)
+ cpp_reader *pfile;
+{
+ struct operation op;
+ cpp_hashnode *hp;
+ struct predicate *pred;
+ cpp_toklist query;
+ enum cpp_ttype type;
+ U_CHAR *tok;
+ size_t len;
+ unsigned int old_written;
+ int specific = 0;
+
+ old_written = CPP_WRITTEN (pfile);
+ CPP_PUTC (pfile, '#');
+ pfile->no_macro_expand++;
+ type = _cpp_get_directive_token (pfile);
+ if (type == CPP_VSPACE)
+ SYNTAX_ERROR ("assertion without predicate");
+ else if (type != CPP_NAME)
+ SYNTAX_ERROR ("assertion predicate is not an identifier");
+
+ tok = pfile->token_buffer + old_written;
+ len = CPP_WRITTEN (pfile) - old_written;
+ hp = cpp_lookup (pfile, tok, len);
+
+ /* Look ahead for an open paren. */
+ _cpp_skip_hspace (pfile);
+ if (CPP_BUF_PEEK (CPP_BUFFER (pfile)) == '(')
+ {
+ if (_cpp_get_directive_token (pfile) != CPP_OPEN_PAREN)
+ CPP_ICE ("impossible token, expecting ( in parse_assertion");
+
+ _cpp_init_toklist (&query, NO_DUMMY_TOKEN);
+ specific = 1;
+ if (_cpp_scan_until (pfile, &query, CPP_CLOSE_PAREN) != CPP_CLOSE_PAREN)
+ SYNTAX_ERROR ("missing close paren on assertion answer");
+
+ if (_cpp_get_directive_token (pfile) != CPP_CLOSE_PAREN)
+ CPP_ICE ("impossible token, expecting ) in parse_assertion");
+ }
+
+ /* If we get here, the syntax is valid. */
+ op.op = INT;
+ op.value = 0;
+ /* Has this predicate been asserted at all? */
+ if (hp->type == T_ASSERTION)
+ {
+ if (specific)
+ {
+ for (pred = hp->value.pred; pred; pred = pred->next)
+ if (_cpp_equiv_toklists (&query, &pred->answer))
+ {
+ op.value = 1;
+ break;
+ }
+ _cpp_free_toklist (&query);
+ }
+ else
+ op.value = 1;
+ }
+
+ out:
+ pfile->no_macro_expand--;
+ CPP_SET_WRITTEN (pfile, old_written);
+ return op;
+
+ syntax_error:
+ if (specific)
+ _cpp_free_toklist (&query);
+ op.op = ERROR;
+ goto out;
+}
+
struct token
{
const char *operator;
return parse_charconst (pfile, tok_start, tok_end);
case CPP_NAME:
- if (!strncmp (tok_start, "defined", 7))
+ if (!ustrncmp (tok_start, U"defined", 7))
return parse_defined (pfile);
op.op = INT;
(int) (tok_end - tok_start), tok_start);
return op;
- case CPP_ASSERTION:
- op.op = INT;
- op.unsignedp = 0;
- op.value = cpp_defined (pfile, tok_start, tok_end - tok_start);
- return op;
+ case CPP_HASH:
+ return parse_assertion (pfile);
case CPP_OTHER:
/* See if it is a special token of length 2. */
&& tok_start[1] == toktab->operator[1])
break;
if (toktab->token == ERROR)
- cpp_error (pfile, "'%s' not allowed in operand of #if",
- tok_start);
+ cpp_error (pfile, "'%.*s' is not allowed in #if expressions",
+ (int) (tok_end - tok_start), tok_start);
op.op = toktab->token;
return op;
}
top->value = v1 OP v2; \
top->unsignedp = unsigned1 | unsigned2;
-/* 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)
-#define SYNTAX_ERROR2(msgid, arg) \
- do { cpp_error (pfile, msgid, arg); goto syntax_error; } while(0)
-
/* Parse and evaluate a C expression, reading from PFILE.
Returns the truth value of the expression. */
int result;
char buff[5];
- pfile->parsing_if_directive++;
+ /* Save parser state and set it to something sane. */
+ int save_only_seen_white = pfile->only_seen_white;
+ int save_skipping = pfile->skipping;
+ pfile->only_seen_white = 0;
+ pfile->skipping = 0;
+
/* We've finished when we try to reduce this. */
top->op = FINISHED;
/* Nifty way to catch missing '('. */
CPP_ICE ("lex returns a NAME");
case ERROR:
goto syntax_error;
- case '#':
- /* We get '#' when get_directive_token hits a syntactically
- invalid assertion predicate. _cpp_parse_assertion has
- already issued an error. */
- goto syntax_error;
default:
SYNTAX_ERROR ("invalid character in #if");
/* Free dynamic stack if we allocated one. */
if (stack != init_stack)
free (stack);
- pfile->parsing_if_directive--;
CPP_SET_WRITTEN (pfile, old_written);
+ pfile->only_seen_white = save_only_seen_white;
+ pfile->skipping = save_skipping;
return result;
}