aboutsummaryrefslogtreecommitdiff
path: root/gcc/cppexp.c
diff options
context:
space:
mode:
authorZack Weinberg <zack@wolery.cumb.org>2000-05-18 15:55:46 +0000
committerZack Weinberg <zack@gcc.gnu.org>2000-05-18 15:55:46 +0000
commit15dad1d9085624c3bce83e0fa0d9b2764f65bccb (patch)
treeeae8b6ec3c589f4957c72e8c82be5c3cc2ea4bbf /gcc/cppexp.c
parent7021bb50d4366bf1630d5a685704d0118b06621a (diff)
downloadgcc-15dad1d9085624c3bce83e0fa0d9b2764f65bccb.zip
gcc-15dad1d9085624c3bce83e0fa0d9b2764f65bccb.tar.gz
gcc-15dad1d9085624c3bce83e0fa0d9b2764f65bccb.tar.bz2
cppexp.c (parse_assertion): New.
* cppexp.c (parse_assertion): New. (lex): Call it for CPP_HASH. Remove CPP_ASSERTION case. (_cpp_parse_expr): Remove case '#'. Don't set parsing_if_directive. * cpphash.c (collect_objlike_expansion, collect_funlike_expansion, collect_params, _cpp_create_definition): The list no longer has a trailing VSPACE token. * cpphash.h (enum node_type): Add T_ASSERTION. (struct hashnode): Remove aschain, add pred. (struct predicate): New. Update prototypes. * cpplex.c (expand_token_space): Handle both offset and nonoffset lists. (init_token_list, _cpp_free_token_list, _cpp_parse_assertion): Delete. (_cpp_init_toklist, _cpp_clear_toklist, _cpp_free_toklist, _cpp_slice_toklist, _cpp_squeeze_toklist, _cpp_equiv_tokens, _cpp_equiv_toklists): New. (_cpp_scan_line): Rename to _cpp_scan_until; add ability to stop at any single-character token, not just newline. (_cpp_lex_token): Remove special cases for #define and #if. (cpp_get_token): Expect # as a separate token type. Remove DIRECTIVE case. (_cpp_get_directive_token): Remove DIRECTIVE case. (_cpp_lex_line, _cpp_lex_file, _cpp_init_input_buffer): Update. * cpplib.c (_cpp_check_directive): Set dirno and SYNTAX_INCLUDE bit of flags, not dir_handler and dir_flags. (_cpp_handle_directive): Run # <number> through the same logic as normal directives. (do_define): Don't set parsing_define_directive. Use _cpp_scan_until. The list does not have a VSPACE at the end. (do_if): Save, clear, and restore only_seen_white around _cpp_parse_expr. (skip_if_group): s/CPP_DIRECTIVE/CPP_HASH/ (do_assert, do_unassert): Rewrite. * cpplib.h (TTYPE_TABLE): Remove CPP_ASSERTION. (LIST_OFFSET): New flag. (struct cpp_toklist): Replace dir_handler and dir_flags with dirno and flags. (struct cpp_reader): Remove parsing_if_directive and parsing_define_directive. From-SVN: r33984
Diffstat (limited to 'gcc/cppexp.c')
-rw-r--r--gcc/cppexp.c108
1 files changed, 87 insertions, 21 deletions
diff --git a/gcc/cppexp.c b/gcc/cppexp.c
index 7e99292..4e61915 100644
--- a/gcc/cppexp.c
+++ b/gcc/cppexp.c
@@ -82,6 +82,7 @@ static struct operation parse_number PARAMS ((cpp_reader *, U_CHAR *,
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));
@@ -110,6 +111,15 @@ struct operation
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. */
@@ -379,6 +389,81 @@ parse_defined (pfile)
return op;
}
+static struct operation
+parse_assertion (pfile)
+ cpp_reader *pfile;
+{
+ struct operation op;
+ 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);
+ 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;
@@ -451,11 +536,8 @@ lex (pfile, skip_evaluation)
(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. */
@@ -734,15 +816,6 @@ be handled with operator-specific code. */
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. */
@@ -770,7 +843,6 @@ _cpp_parse_expr (pfile)
int result;
char buff[5];
- pfile->parsing_if_directive++;
/* We've finished when we try to reduce this. */
top->op = FINISHED;
/* Nifty way to catch missing '('. */
@@ -796,11 +868,6 @@ _cpp_parse_expr (pfile)
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");
@@ -1094,7 +1161,6 @@ _cpp_parse_expr (pfile)
/* Free dynamic stack if we allocated one. */
if (stack != init_stack)
free (stack);
- pfile->parsing_if_directive--;
CPP_SET_WRITTEN (pfile, old_written);
return result;
}