aboutsummaryrefslogtreecommitdiff
path: root/gcc/cpplib.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/cpplib.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/cpplib.c')
-rw-r--r--gcc/cpplib.c245
1 files changed, 152 insertions, 93 deletions
diff --git a/gcc/cpplib.c b/gcc/cpplib.c
index e249555..23b522c 100644
--- a/gcc/cpplib.c
+++ b/gcc/cpplib.c
@@ -160,14 +160,15 @@ _cpp_check_directive (list, token)
size_t len = token->val.name.len;
unsigned int i;
- list->dir_handler = 0;
- list->dir_flags = 0;
+ list->dirno = -1;
+ list->flags &= ~SYNTAX_INCLUDE;
for (i = 0; i < N_DIRECTIVES; i++)
if (dtable[i].length == len && !ustrncmp (dtable[i].name, name, len))
{
- list->dir_handler = dtable[i].func;
- list->dir_flags = dtable[i].flags;
+ list->dirno = i;
+ if (dtable[i].flags & SYNTAX_INCLUDE)
+ list->flags |= SYNTAX_INCLUDE;
break;
}
}
@@ -219,8 +220,8 @@ _cpp_handle_directive (pfile)
&& CPP_BUFFER (pfile)->ihash
&& ! CPP_OPTION (pfile, preprocessed))
cpp_pedwarn (pfile, "# followed by integer");
- do_line (pfile);
- return 1;
+ i = T_LINE;
+ goto process_directive;
}
/* If we are rescanning preprocessed input, don't obey any directives
@@ -300,6 +301,7 @@ _cpp_handle_directive (pfile)
pfile->no_macro_expand--;
CPP_SET_WRITTEN (pfile, old_written);
+ process_directive:
/* Some directives (e.g. #if) may return a request to execute
another directive handler immediately. No directive ever
requests that #define be executed immediately, so it is safe for
@@ -343,14 +345,14 @@ do_define (pfile)
cpp_toklist *list = &pfile->directbuf;
pfile->no_macro_expand++;
- pfile->parsing_define_directive++;
CPP_OPTION (pfile, discard_comments)++;
- _cpp_scan_line (pfile, list);
+ _cpp_scan_until (pfile, list, CPP_VSPACE);
- /* First token on the line must be a NAME. There must be at least
- one token (the VSPACE at the end). */
- if (TOK_TYPE (list, 0) != CPP_NAME)
+ /* First token on the line must be a NAME. There may not be any
+ tokens in the list (if we had #define all by itself on a line). */
+ if (list->tokens_used == 0
+ || TOK_TYPE (list, 0) != CPP_NAME)
{
cpp_error_with_line (pfile, list->line, TOK_COL (list, 0),
"#define must be followed by an identifier");
@@ -389,7 +391,6 @@ do_define (pfile)
out:
pfile->no_macro_expand--;
- pfile->parsing_define_directive--;
CPP_OPTION (pfile, discard_comments)--;
return 0;
}
@@ -1097,8 +1098,16 @@ static int
do_if (pfile)
cpp_reader *pfile;
{
- U_CHAR *control_macro = detect_if_not_defined (pfile);
- int value = _cpp_parse_expr (pfile);
+ U_CHAR *control_macro;
+ int value;
+ int save_only_seen_white = pfile->only_seen_white;
+
+ control_macro = detect_if_not_defined (pfile);
+
+ pfile->only_seen_white = 0;
+ value = _cpp_parse_expr (pfile);
+ pfile->only_seen_white = save_only_seen_white;
+
return conditional_skip (pfile, value == 0, T_IF, control_macro);
}
@@ -1383,7 +1392,7 @@ skip_if_group (pfile)
token = _cpp_get_directive_token (pfile);
- if (token == CPP_DIRECTIVE)
+ if (token == CPP_HASH)
{
ret = consider_directive_while_skipping (pfile, save_if_stack);
if (ret)
@@ -1509,56 +1518,84 @@ _cpp_unwind_if_stack (pfile, pbuf)
pfile->if_stack = ifs;
}
+#define WARNING(msgid) do { cpp_warning(pfile, msgid); goto error; } while (0)
+#define ERROR(msgid) do { cpp_error(pfile, msgid); goto error; } while (0)
+#define ICE(msgid) do { cpp_ice(pfile, msgid); goto error; } while (0)
static int
do_assert (pfile)
cpp_reader *pfile;
{
long old_written;
U_CHAR *sym;
- int ret;
- HASHNODE *base, *this;
- size_t blen, tlen;
+ size_t len;
+ HASHNODE *hp;
+ struct predicate *pred = 0;
+ enum cpp_ttype type;
- old_written = CPP_WRITTEN (pfile); /* remember where it starts */
- ret = _cpp_parse_assertion (pfile);
- if (ret == 0)
- goto error;
- else if (ret == 1)
- {
- cpp_error (pfile, "missing token-sequence in #assert");
- goto error;
- }
- tlen = CPP_WRITTEN (pfile) - old_written;
+ old_written = CPP_WRITTEN (pfile);
+ pfile->no_macro_expand++;
+
+ CPP_PUTC (pfile, '#'); /* force token out of macro namespace */
+ type = _cpp_get_directive_token (pfile);
+ if (type == CPP_VSPACE)
+ ERROR ("#assert without predicate");
+ else if (type != CPP_NAME)
+ ERROR ("assertion predicate is not an identifier");
- if (_cpp_get_directive_token (pfile) != CPP_VSPACE)
- {
- cpp_error (pfile, "junk at end of #assert");
- goto error;
- }
sym = pfile->token_buffer + old_written;
+ len = CPP_WRITTEN (pfile) - old_written;
+ hp = _cpp_lookup (pfile, sym, len);
+
+ if (_cpp_get_directive_token (pfile) != CPP_OPEN_PAREN)
+ ERROR ("missing token-sequence in #assert");
+
+ pred = (struct predicate *) xmalloc (sizeof (struct predicate));
+ _cpp_init_toklist (&pred->answer);
+
+ if (_cpp_scan_until (pfile, &pred->answer, CPP_CLOSE_PAREN)
+ != CPP_CLOSE_PAREN)
+ ERROR ("missing close paren in #assert");
- this = _cpp_lookup (pfile, sym, tlen);
- if (this->type == T_ASSERT)
+ if (_cpp_get_directive_token (pfile) != CPP_CLOSE_PAREN)
+ ICE ("impossible token, expecting ) in do_assert");
+
+ if (_cpp_get_directive_token (pfile) != CPP_VSPACE)
+ ERROR ("junk at end of #assert");
+
+ if (hp->type == T_ASSERTION)
{
- cpp_warning (pfile, "%s re-asserted", sym);
- goto error;
+ /* Check for reassertion. */
+ const struct predicate *old;
+
+ for (old = hp->value.pred; old; old = old->next)
+ if (_cpp_equiv_toklists (&pred->answer, &old->answer))
+ /* We used to warn about this, but SVR4 cc doesn't, so let's
+ match that (also consistent with #define). goto error will
+ clean up. */
+ goto error;
+ pred->next = hp->value.pred;
}
-
- blen = ustrchr (sym, '(') - sym;
- base = _cpp_lookup (pfile, sym, blen);
- if (base->type == T_VOID)
+ else
{
- base->type = T_ASSERT;
- base->value.aschain = 0;
+ hp->type = T_ASSERTION;
+ pred->next = 0;
}
-
- this->type = T_ASSERT;
- this->value.aschain = base->value.aschain;
- base->value.aschain = this;
+
+ _cpp_squeeze_toklist (&pred->answer);
+ hp->value.pred = pred;
+ pfile->no_macro_expand--;
+ CPP_SET_WRITTEN (pfile, old_written);
+ return 0;
error:
_cpp_skip_rest_of_line (pfile);
+ pfile->no_macro_expand--;
CPP_SET_WRITTEN (pfile, old_written);
+ if (pred)
+ {
+ _cpp_free_toklist (&pred->answer);
+ free (pred);
+ }
return 0;
}
@@ -1566,68 +1603,90 @@ static int
do_unassert (pfile)
cpp_reader *pfile;
{
- int ret;
long old_written;
U_CHAR *sym;
- long baselen, thislen;
- HASHNODE *base, *this, *next;
+ size_t len;
+ HASHNODE *hp;
+ struct predicate *pred = 0;
+ enum cpp_ttype type;
old_written = CPP_WRITTEN (pfile);
- ret = _cpp_parse_assertion (pfile);
- if (ret == 0)
- goto out;
- thislen = CPP_WRITTEN (pfile) - old_written;
+ pfile->no_macro_expand++;
- if (_cpp_get_directive_token (pfile) != CPP_VSPACE)
+ CPP_PUTC (pfile, '#'); /* force token out of macro namespace */
+ if (_cpp_get_directive_token (pfile) != CPP_NAME)
+ ERROR ("#unassert must be followed by an identifier");
+
+ sym = pfile->token_buffer + old_written;
+ len = CPP_WRITTEN (pfile) - old_written;
+ hp = _cpp_lookup (pfile, sym, len);
+
+ type = _cpp_get_directive_token (pfile);
+ if (type == CPP_OPEN_PAREN)
{
- cpp_error (pfile, "junk at end of #unassert");
- goto out;
+ pred = (struct predicate *) xmalloc (sizeof (struct predicate));
+ _cpp_init_toklist (&pred->answer);
+
+ if (_cpp_scan_until (pfile, &pred->answer, CPP_CLOSE_PAREN)
+ != CPP_CLOSE_PAREN)
+ ERROR ("missing close paren in #unassert");
+
+ if (_cpp_get_directive_token (pfile) != CPP_CLOSE_PAREN)
+ ICE ("impossible token, expecting ) in do_unassert");
+
+ type = _cpp_get_directive_token (pfile);
}
- sym = pfile->token_buffer + old_written;
- CPP_SET_WRITTEN (pfile, old_written);
- if (ret == 1)
+ if (type != CPP_VSPACE)
+ ERROR ("junk at end of #unassert");
+
+ if (hp->type != T_ASSERTION)
+ /* Not an error to #unassert something that isn't asserted.
+ goto error to clean up. */
+ goto error;
+
+ if (pred)
{
- base = _cpp_lookup (pfile, sym, thislen);
- if (base->type == T_VOID)
- goto out; /* It isn't an error to #undef what isn't #defined,
- so it isn't an error to #unassert what isn't
- #asserted either. */
-
- for (this = base->value.aschain; this; this = next)
- {
- next = this->value.aschain;
- this->value.aschain = NULL;
- this->type = T_VOID;
- }
- base->value.aschain = NULL;
- base->type = T_VOID;
+ /* Find this specific answer and remove it. */
+ struct predicate *o, *p;
+
+ for (p = NULL, o = hp->value.pred; o; p = o, o = o->next)
+ if (_cpp_equiv_toklists (&pred->answer, &o->answer))
+ {
+ if (p)
+ p->next = o->next;
+ else
+ hp->value.pred = o->next;
+
+ _cpp_free_toklist (&o->answer);
+ free (o);
+ break;
+ }
}
else
{
- baselen = ustrchr (sym, '(') - sym;
- base = _cpp_lookup (pfile, sym, baselen);
- if (base->type == T_VOID) goto out;
- this = _cpp_lookup (pfile, sym, thislen);
- if (this->type == T_VOID) goto out;
-
- next = base;
- while (next->value.aschain != this)
- next = next->value.aschain;
-
- next->value.aschain = this->value.aschain;
- this->value.aschain = NULL;
- this->type = T_VOID;
-
- if (base->value.aschain == NULL)
- /* Last answer for this predicate deleted. */
- base->type = T_VOID;
+ struct predicate *o, *p;
+ for (o = hp->value.pred; o; o = p)
+ {
+ p = o->next;
+ _cpp_free_toklist ((cpp_toklist *) &o->answer);
+ free (o);
+ }
+ hp->value.pred = NULL;
}
- return 0;
- out:
+ if (hp->value.pred == NULL)
+ hp->type = T_VOID; /* Last answer for this predicate deleted. */
+
+ error:
_cpp_skip_rest_of_line (pfile);
+ pfile->no_macro_expand--;
CPP_SET_WRITTEN (pfile, old_written);
+ if (pred)
+ {
+ _cpp_free_toklist (&pred->answer);
+ free (pred);
+ }
return 0;
}