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
This commit is contained in:
parent
7021bb50d4
commit
15dad1d908
7 changed files with 555 additions and 345 deletions
|
@ -1,3 +1,50 @@
|
|||
2000-05-18 Zack Weinberg <zack@wolery.cumb.org>
|
||||
|
||||
* 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.
|
||||
|
||||
2000-05-18 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
|
||||
|
||||
* fixinc/inclhack.def (broken_cabs): Update fix to handle comments
|
||||
|
|
108
gcc/cppexp.c
108
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;
|
||||
}
|
||||
|
|
|
@ -480,12 +480,6 @@ collect_objlike_expansion (pfile, list)
|
|||
{
|
||||
switch (TOK_TYPE (list, i))
|
||||
{
|
||||
case CPP_EOF:
|
||||
cpp_ice (pfile, "EOF in collect_expansion");
|
||||
/* fall through */
|
||||
case CPP_VSPACE:
|
||||
goto done;
|
||||
|
||||
case CPP_PASTE:
|
||||
/* ## is not special if it appears right after another ##;
|
||||
nor is it special if -traditional. */
|
||||
|
@ -506,7 +500,6 @@ collect_objlike_expansion (pfile, list)
|
|||
CPP_PUTS (pfile, TOK_NAME (list, i), TOK_LEN (list, i));
|
||||
last_was_paste = 0;
|
||||
}
|
||||
done:
|
||||
|
||||
if (last_was_paste)
|
||||
cpp_error (pfile, "`##' at end of macro definition");
|
||||
|
@ -568,12 +561,6 @@ collect_funlike_expansion (pfile, list, arglist, replacement)
|
|||
len = TOK_LEN (list, i);
|
||||
switch (token)
|
||||
{
|
||||
case CPP_EOF:
|
||||
cpp_ice (pfile, "EOF in collect_expansion");
|
||||
/* fall through */
|
||||
case CPP_VSPACE:
|
||||
goto done;
|
||||
|
||||
case CPP_HASH:
|
||||
/* # is special in function-like macros with no args.
|
||||
(6.10.3.2 para 1.) However, it is not special after
|
||||
|
@ -677,7 +664,6 @@ collect_funlike_expansion (pfile, list, arglist, replacement)
|
|||
}
|
||||
last_token = ARG;
|
||||
}
|
||||
done:
|
||||
|
||||
if (last_token == STRIZE)
|
||||
cpp_error (pfile, "`#' is not followed by a macro argument name");
|
||||
|
@ -759,8 +745,8 @@ collect_params (pfile, list, arglist)
|
|||
case CPP_CLOSE_PAREN:
|
||||
goto scanned;
|
||||
case CPP_VSPACE:
|
||||
cpp_error_with_line (pfile, list->line, TOK_COL (list, i),
|
||||
"missing right paren in macro argument list");
|
||||
case CPP_EOF:
|
||||
cpp_ice (pfile, "impossible token in macro argument list");
|
||||
return 0;
|
||||
|
||||
default:
|
||||
|
@ -783,9 +769,8 @@ collect_params (pfile, list, arglist)
|
|||
}
|
||||
goto scanned;
|
||||
}
|
||||
|
||||
cpp_ice (pfile, "collect_params: unreachable - i=%d, ntokens=%d, type=%d",
|
||||
i, list->tokens_used, TOK_TYPE (list, i-1));
|
||||
cpp_error_with_line (pfile, list->line, TOK_COL (list, i-1),
|
||||
"missing right paren in macro argument list");
|
||||
return 0;
|
||||
|
||||
scanned:
|
||||
|
@ -892,9 +877,9 @@ _cpp_create_definition (pfile, list, hp)
|
|||
#define FUNC(a, b, ...) // nothing
|
||||
#define FUNC(a, b, c) FUNC(a, b, c) */
|
||||
|
||||
if (list->tokens_used == 2)
|
||||
if (list->tokens_used == 1)
|
||||
ntype = T_EMPTY; /* Empty definition of object-like macro. */
|
||||
else if (list->tokens_used == 3 && TOK_TYPE (list, 1) == CPP_NAME
|
||||
else if (list->tokens_used == 2 && TOK_TYPE (list, 1) == CPP_NAME
|
||||
&& TOK_LEN (list, 0) == TOK_LEN (list, 1)
|
||||
&& !ustrncmp (TOK_NAME (list, 0), TOK_NAME (list, 1),
|
||||
TOK_LEN (list, 0)))
|
||||
|
|
|
@ -49,7 +49,8 @@ enum node_type
|
|||
T_MACRO, /* object-like macro */
|
||||
T_FMACRO, /* function-like macro */
|
||||
T_IDENTITY, /* macro defined to itself */
|
||||
T_EMPTY /* macro defined to nothing */
|
||||
T_EMPTY, /* macro defined to nothing */
|
||||
T_ASSERTION /* predicate for #assert */
|
||||
};
|
||||
|
||||
typedef struct hashnode HASHNODE;
|
||||
|
@ -64,12 +65,19 @@ struct hashnode
|
|||
const U_CHAR *cpval; /* some predefined macros */
|
||||
const struct object_defn *odefn; /* #define foo bar */
|
||||
const struct funct_defn *fdefn; /* #define foo(x) bar(x) */
|
||||
struct hashnode *aschain; /* #assert */
|
||||
struct predicate *pred; /* #assert */
|
||||
} value;
|
||||
|
||||
const U_CHAR name[1]; /* name[length] */
|
||||
};
|
||||
|
||||
/* Structure used for assertion predicates. */
|
||||
struct predicate
|
||||
{
|
||||
struct predicate *next;
|
||||
struct cpp_toklist answer;
|
||||
};
|
||||
|
||||
/* List of directories to look for include files in. */
|
||||
struct file_name_list
|
||||
{
|
||||
|
@ -250,7 +258,20 @@ extern enum cpp_ttype _cpp_get_directive_token
|
|||
PARAMS ((cpp_reader *));
|
||||
extern enum cpp_ttype _cpp_get_define_token
|
||||
PARAMS ((cpp_reader *));
|
||||
extern void _cpp_scan_line PARAMS ((cpp_reader *, cpp_toklist *));
|
||||
extern enum cpp_ttype _cpp_scan_until PARAMS ((cpp_reader *, cpp_toklist *,
|
||||
enum cpp_ttype));
|
||||
extern void _cpp_init_toklist PARAMS ((cpp_toklist *));
|
||||
extern void _cpp_clear_toklist PARAMS ((cpp_toklist *));
|
||||
extern void _cpp_free_toklist PARAMS ((cpp_toklist *));
|
||||
extern void _cpp_slice_toklist PARAMS ((cpp_toklist *,
|
||||
const cpp_token *,
|
||||
const cpp_token *));
|
||||
extern void _cpp_squeeze_toklist PARAMS ((cpp_toklist *));
|
||||
extern int _cpp_equiv_tokens PARAMS ((const cpp_token *,
|
||||
const cpp_token *));
|
||||
extern int _cpp_equiv_toklists PARAMS ((const cpp_toklist *,
|
||||
const cpp_toklist *));
|
||||
|
||||
|
||||
/* In cpplib.c */
|
||||
extern int _cpp_handle_directive PARAMS ((cpp_reader *));
|
||||
|
|
420
gcc/cpplex.c
420
gcc/cpplex.c
|
@ -55,7 +55,6 @@ static void bump_column PARAMS ((cpp_printer *, unsigned int,
|
|||
unsigned int));
|
||||
static void expand_name_space PARAMS ((cpp_toklist *, unsigned int));
|
||||
static void expand_token_space PARAMS ((cpp_toklist *));
|
||||
static void init_token_list PARAMS ((cpp_reader *, cpp_toklist *, int));
|
||||
static void pedantic_whitespace PARAMS ((cpp_reader *, U_CHAR *,
|
||||
unsigned int));
|
||||
|
||||
|
@ -491,7 +490,7 @@ cpp_scan_buffer (pfile, print)
|
|||
for (;;)
|
||||
{
|
||||
token = cpp_get_token (pfile);
|
||||
if (token == CPP_EOF || token == CPP_VSPACE
|
||||
if (token == CPP_VSPACE || token == CPP_EOF
|
||||
/* XXX Temporary kluge - force flush after #include only */
|
||||
|| (token == CPP_DIRECTIVE
|
||||
&& CPP_BUFFER (pfile)->nominal_fname != print->last_fname))
|
||||
|
@ -548,63 +547,212 @@ expand_token_space (list)
|
|||
cpp_toklist *list;
|
||||
{
|
||||
list->tokens_cap *= 2;
|
||||
if (list->flags & LIST_OFFSET)
|
||||
list->tokens--;
|
||||
list->tokens = (cpp_token *)
|
||||
xrealloc (list->tokens - 1, (list->tokens_cap + 1) * sizeof (cpp_token));
|
||||
list->tokens++; /* Skip the dummy. */
|
||||
xrealloc (list->tokens, (list->tokens_cap + 1) * sizeof (cpp_token));
|
||||
if (list->flags & LIST_OFFSET)
|
||||
list->tokens++; /* Skip the dummy. */
|
||||
}
|
||||
|
||||
/* Initialize a token list. We allocate an extra token in front of
|
||||
the token list, as this allows us to always peek at the previous
|
||||
token without worrying about underflowing the list. */
|
||||
static void
|
||||
init_token_list (pfile, list, recycle)
|
||||
cpp_reader *pfile;
|
||||
void
|
||||
_cpp_init_toklist (list)
|
||||
cpp_toklist *list;
|
||||
int recycle;
|
||||
{
|
||||
/* Recycling a used list saves 3 free-malloc pairs. */
|
||||
if (!recycle)
|
||||
{
|
||||
/* Initialize token space. Put a dummy token before the start
|
||||
that will fail matches. */
|
||||
list->tokens_cap = 256; /* 4K's worth. */
|
||||
list->tokens = (cpp_token *)
|
||||
xmalloc ((list->tokens_cap + 1) * sizeof (cpp_token));
|
||||
list->tokens[0].type = CPP_EOF;
|
||||
list->tokens++;
|
||||
/* Initialize token space. Put a dummy token before the start
|
||||
that will fail matches. */
|
||||
list->tokens_cap = 256; /* 4K's worth. */
|
||||
list->tokens = (cpp_token *)
|
||||
xmalloc ((list->tokens_cap + 1) * sizeof (cpp_token));
|
||||
list->tokens[0].type = CPP_EOF;
|
||||
list->tokens++;
|
||||
|
||||
/* Initialize name space. */
|
||||
list->name_cap = 1024;
|
||||
list->namebuf = (unsigned char *) xmalloc (list->name_cap);
|
||||
/* Initialize name space. */
|
||||
list->name_cap = 1024;
|
||||
list->namebuf = (unsigned char *) xmalloc (list->name_cap);
|
||||
|
||||
/* Only create a comment space on demand. */
|
||||
list->comments_cap = 0;
|
||||
list->comments = 0;
|
||||
}
|
||||
/* Only create a comment space on demand. */
|
||||
list->comments_cap = 0;
|
||||
list->comments = 0;
|
||||
|
||||
list->flags = LIST_OFFSET;
|
||||
_cpp_clear_toklist (list);
|
||||
}
|
||||
|
||||
/* Clear a token list. */
|
||||
void
|
||||
_cpp_clear_toklist (list)
|
||||
cpp_toklist *list;
|
||||
{
|
||||
list->tokens_used = 0;
|
||||
list->name_used = 0;
|
||||
list->comments_used = 0;
|
||||
if (pfile->buffer)
|
||||
list->line = pfile->buffer->lineno;
|
||||
list->dir_handler = 0;
|
||||
list->dir_flags = 0;
|
||||
list->dirno = -1;
|
||||
list->flags &= LIST_OFFSET; /* clear all but that one */
|
||||
}
|
||||
|
||||
/* Scan an entire line and create a token list for it. Does not
|
||||
macro-expand or execute directives. */
|
||||
|
||||
/* Free a token list. Does not free the list itself, which may be
|
||||
embedded in a larger structure. */
|
||||
void
|
||||
_cpp_scan_line (pfile, list)
|
||||
_cpp_free_toklist (list)
|
||||
cpp_toklist *list;
|
||||
{
|
||||
if (list->comments)
|
||||
free (list->comments);
|
||||
if (list->flags & LIST_OFFSET)
|
||||
free (list->tokens - 1); /* Backup over dummy token. */
|
||||
else
|
||||
free (list->tokens);
|
||||
free (list->namebuf);
|
||||
}
|
||||
|
||||
/* Slice a token list: copy the sublist [START, FINISH) into COPY.
|
||||
COPY is assumed not to be initialized. The comment space is not
|
||||
copied. */
|
||||
void
|
||||
_cpp_slice_toklist (copy, start, finish)
|
||||
cpp_toklist *copy;
|
||||
const cpp_token *start, *finish;
|
||||
{
|
||||
unsigned int i, n;
|
||||
size_t bytes;
|
||||
|
||||
n = finish - start;
|
||||
copy->tokens_cap = n;
|
||||
copy->tokens = (cpp_token *) xmalloc (n * sizeof (cpp_token));
|
||||
memcpy (copy->tokens, start, n * sizeof (cpp_token));
|
||||
|
||||
bytes = 0;
|
||||
for (i = 0; i < n; i++)
|
||||
if (token_spellings[start[i].type].type > SPELL_NONE)
|
||||
bytes += start[i].val.name.len;
|
||||
|
||||
copy->namebuf = xmalloc (bytes);
|
||||
bytes = 0;
|
||||
for (i = 0; i < n; i++)
|
||||
if (token_spellings[start[i].type].type > SPELL_NONE)
|
||||
{
|
||||
memcpy (copy->namebuf + bytes,
|
||||
start[i].val.name.text, start[i].val.name.len);
|
||||
copy->tokens[i].val.name.text = copy->namebuf + bytes;
|
||||
bytes += start[i].val.name.len;
|
||||
}
|
||||
|
||||
copy->tokens_cap = n;
|
||||
copy->tokens_used = n;
|
||||
copy->name_used = bytes;
|
||||
copy->name_cap = bytes;
|
||||
copy->comments = 0;
|
||||
copy->comments_cap = 0;
|
||||
copy->comments_used = 0;
|
||||
|
||||
copy->flags = 0;
|
||||
copy->dirno = -1;
|
||||
}
|
||||
|
||||
/* Shrink a token list down to the minimum size. */
|
||||
void
|
||||
_cpp_squeeze_toklist (list)
|
||||
cpp_toklist *list;
|
||||
{
|
||||
long delta;
|
||||
const U_CHAR *old_namebuf;
|
||||
|
||||
if (list->flags & LIST_OFFSET)
|
||||
{
|
||||
list->tokens--;
|
||||
memmove (list->tokens, list->tokens + 1,
|
||||
list->tokens_used * sizeof (cpp_token));
|
||||
list->tokens = xrealloc (list->tokens,
|
||||
list->tokens_used * sizeof (cpp_token));
|
||||
list->flags &= ~LIST_OFFSET;
|
||||
}
|
||||
else
|
||||
list->tokens = xrealloc (list->tokens,
|
||||
list->tokens_used * sizeof (cpp_token));
|
||||
list->tokens_cap = list->tokens_used;
|
||||
|
||||
old_namebuf = list->namebuf;
|
||||
list->namebuf = xrealloc (list->namebuf, list->name_used);
|
||||
list->name_cap = list->name_used;
|
||||
|
||||
/* Fix up token text pointers. */
|
||||
delta = list->namebuf - old_namebuf;
|
||||
if (delta)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < list->tokens_used; i++)
|
||||
if (token_spellings[list->tokens[i].type].type > SPELL_NONE)
|
||||
list->tokens[i].val.name.text += delta;
|
||||
}
|
||||
|
||||
if (list->comments_cap)
|
||||
{
|
||||
list->comments = xrealloc (list->comments,
|
||||
list->comments_used * sizeof (cpp_token));
|
||||
list->comments_cap = list->comments_used;
|
||||
}
|
||||
}
|
||||
|
||||
/* Compare two tokens. */
|
||||
int
|
||||
_cpp_equiv_tokens (a, b)
|
||||
const cpp_token *a, *b;
|
||||
{
|
||||
if (a->type != b->type
|
||||
|| a->flags != b->flags
|
||||
|| a->aux != b->aux)
|
||||
return 0;
|
||||
|
||||
if (token_spellings[a->type].type > SPELL_NONE)
|
||||
{
|
||||
if (a->val.name.len != b->val.name.len
|
||||
|| ustrncmp(a->val.name.text,
|
||||
b->val.name.text,
|
||||
a->val.name.len))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Compare two token lists. */
|
||||
int
|
||||
_cpp_equiv_toklists (a, b)
|
||||
const cpp_toklist *a, *b;
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (a->tokens_used != b->tokens_used)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < a->tokens_used; i++)
|
||||
if (! _cpp_equiv_tokens (&a->tokens[i], &b->tokens[i]))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Scan until we encounter a token of type STOP or a newline, and
|
||||
create a token list for it. Does not macro-expand or execute
|
||||
directives. The final token is not included in the list or
|
||||
consumed from the input. Returns the type of the token stopped at. */
|
||||
|
||||
enum cpp_ttype
|
||||
_cpp_scan_until (pfile, list, stop)
|
||||
cpp_reader *pfile;
|
||||
cpp_toklist *list;
|
||||
enum cpp_ttype stop;
|
||||
{
|
||||
int i, col;
|
||||
long written, len;
|
||||
enum cpp_ttype type;
|
||||
int space_before;
|
||||
|
||||
init_token_list (pfile, list, 1);
|
||||
_cpp_clear_toklist (list);
|
||||
list->line = CPP_BUF_LINE (CPP_BUFFER (pfile));
|
||||
|
||||
written = CPP_WRITTEN (pfile);
|
||||
i = 0;
|
||||
|
@ -636,14 +784,14 @@ _cpp_scan_line (pfile, list)
|
|||
if (type == CPP_MACRO)
|
||||
type = CPP_NAME;
|
||||
|
||||
if (type == CPP_VSPACE || type == stop)
|
||||
break;
|
||||
|
||||
list->tokens_used++;
|
||||
TOK_TYPE (list, i) = type;
|
||||
TOK_COL (list, i) = col;
|
||||
TOK_FLAGS (list, i) = space_before ? PREV_WHITESPACE : 0;
|
||||
|
||||
if (type == CPP_VSPACE)
|
||||
break;
|
||||
|
||||
TOK_LEN (list, i) = len;
|
||||
if (token_spellings[type].type > SPELL_NONE)
|
||||
{
|
||||
|
@ -656,12 +804,14 @@ _cpp_scan_line (pfile, list)
|
|||
i++;
|
||||
space_before = 0;
|
||||
}
|
||||
TOK_AUX (list, i) = CPP_BUFFER (pfile)->lineno + 1;
|
||||
|
||||
/* XXX Temporary kluge: put back the newline. */
|
||||
/* XXX Temporary kluge: put back the newline (or whatever). */
|
||||
FORWARD(-1);
|
||||
}
|
||||
|
||||
/* Don't consider the first token to have white before. */
|
||||
TOK_FLAGS (list, 0) &= ~PREV_WHITESPACE;
|
||||
return type;
|
||||
}
|
||||
|
||||
/* Skip a C-style block comment. We know it's a comment, and point is
|
||||
at the second character of the starter. */
|
||||
|
@ -1060,85 +1210,6 @@ parse_string (pfile, c)
|
|||
CPP_PUTC_Q (pfile, *start);
|
||||
}
|
||||
|
||||
/* Read an assertion into the token buffer, converting to
|
||||
canonical form: `#predicate(a n swe r)' The next non-whitespace
|
||||
character to read should be the first letter of the predicate.
|
||||
Returns 0 for syntax error, 1 for bare predicate, 2 for predicate
|
||||
with answer (see callers for why). In case of 0, an error has been
|
||||
printed. */
|
||||
int
|
||||
_cpp_parse_assertion (pfile)
|
||||
cpp_reader *pfile;
|
||||
{
|
||||
int c, dropwhite;
|
||||
_cpp_skip_hspace (pfile);
|
||||
c = PEEKC();
|
||||
if (c == '\n')
|
||||
{
|
||||
cpp_error (pfile, "assertion without predicate");
|
||||
return 0;
|
||||
}
|
||||
else if (! is_idstart(c))
|
||||
{
|
||||
cpp_error (pfile, "assertion predicate is not an identifier");
|
||||
return 0;
|
||||
}
|
||||
CPP_PUTC(pfile, '#');
|
||||
FORWARD(1);
|
||||
_cpp_parse_name (pfile, c);
|
||||
|
||||
c = PEEKC();
|
||||
if (c != '(')
|
||||
{
|
||||
if (is_hspace(c) || c == '\r')
|
||||
_cpp_skip_hspace (pfile);
|
||||
c = PEEKC();
|
||||
}
|
||||
if (c != '(')
|
||||
return 1;
|
||||
|
||||
CPP_PUTC(pfile, '(');
|
||||
FORWARD(1);
|
||||
dropwhite = 1;
|
||||
while ((c = GETC()) != ')')
|
||||
{
|
||||
if (is_space(c))
|
||||
{
|
||||
if (! dropwhite)
|
||||
{
|
||||
CPP_PUTC(pfile, ' ');
|
||||
dropwhite = 1;
|
||||
}
|
||||
}
|
||||
else if (c == '\n' || c == EOF)
|
||||
{
|
||||
if (c == '\n') FORWARD(-1);
|
||||
cpp_error (pfile, "un-terminated assertion answer");
|
||||
return 0;
|
||||
}
|
||||
else if (c == '\r')
|
||||
/* \r cannot be a macro escape here. */
|
||||
CPP_BUMP_LINE (pfile);
|
||||
else
|
||||
{
|
||||
CPP_PUTC (pfile, c);
|
||||
dropwhite = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (pfile->limit[-1] == ' ')
|
||||
pfile->limit[-1] = ')';
|
||||
else if (pfile->limit[-1] == '(')
|
||||
{
|
||||
cpp_error (pfile, "empty token sequence in assertion");
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
CPP_PUTC (pfile, ')');
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* Get the next token, and add it to the text in pfile->token_buffer.
|
||||
Return the kind of token we got. */
|
||||
|
||||
|
@ -1176,11 +1247,7 @@ _cpp_lex_token (pfile)
|
|||
if (!CPP_OPTION (pfile, discard_comments))
|
||||
return CPP_COMMENT;
|
||||
else if (CPP_TRADITIONAL (pfile))
|
||||
{
|
||||
if (pfile->parsing_define_directive)
|
||||
return CPP_COMMENT;
|
||||
goto get_next;
|
||||
}
|
||||
goto get_next;
|
||||
else
|
||||
{
|
||||
CPP_PUTC (pfile, c);
|
||||
|
@ -1191,42 +1258,24 @@ _cpp_lex_token (pfile)
|
|||
CPP_PUTC (pfile, c);
|
||||
|
||||
hash:
|
||||
if (pfile->parsing_if_directive)
|
||||
c2 = PEEKC ();
|
||||
if (c2 == '#')
|
||||
{
|
||||
CPP_ADJUST_WRITTEN (pfile, -1);
|
||||
if (_cpp_parse_assertion (pfile))
|
||||
return CPP_ASSERTION;
|
||||
return CPP_OTHER;
|
||||
}
|
||||
|
||||
if (pfile->parsing_define_directive)
|
||||
{
|
||||
c2 = PEEKC ();
|
||||
if (c2 == '#')
|
||||
{
|
||||
FORWARD (1);
|
||||
CPP_PUTC (pfile, c2);
|
||||
}
|
||||
else if (c2 == '%' && PEEKN (1) == ':')
|
||||
{
|
||||
/* Digraph: "%:" == "#". */
|
||||
FORWARD (1);
|
||||
CPP_RESERVE (pfile, 2);
|
||||
CPP_PUTC_Q (pfile, c2);
|
||||
CPP_PUTC_Q (pfile, GETC ());
|
||||
}
|
||||
else
|
||||
return CPP_HASH;
|
||||
|
||||
FORWARD (1);
|
||||
CPP_PUTC (pfile, c2);
|
||||
return CPP_PASTE;
|
||||
}
|
||||
|
||||
if (!pfile->only_seen_white)
|
||||
return CPP_OTHER;
|
||||
|
||||
/* Remove the "#" or "%:" from the token buffer. */
|
||||
CPP_ADJUST_WRITTEN (pfile, (c == '#' ? -1 : -2));
|
||||
return CPP_DIRECTIVE;
|
||||
else if (c2 == '%' && PEEKN (1) == ':')
|
||||
{
|
||||
/* Digraph: "%:" == "#". */
|
||||
FORWARD (1);
|
||||
CPP_RESERVE (pfile, 2);
|
||||
CPP_PUTC_Q (pfile, c2);
|
||||
CPP_PUTC_Q (pfile, GETC ());
|
||||
return CPP_PASTE;
|
||||
}
|
||||
else
|
||||
return CPP_HASH;
|
||||
|
||||
case '\"':
|
||||
case '\'':
|
||||
|
@ -1697,13 +1746,22 @@ cpp_get_token (pfile)
|
|||
case CPP_COMMENT:
|
||||
return token;
|
||||
|
||||
case CPP_DIRECTIVE:
|
||||
case CPP_HASH:
|
||||
pfile->potential_control_macro = 0;
|
||||
if (!pfile->only_seen_white)
|
||||
return CPP_HASH;
|
||||
/* XXX shouldn't have to do this - remove the hash or %: from
|
||||
the token buffer. */
|
||||
if (CPP_PWRITTEN (pfile)[-1] == '#')
|
||||
CPP_ADJUST_WRITTEN (pfile, -1);
|
||||
else
|
||||
CPP_ADJUST_WRITTEN (pfile, -2);
|
||||
|
||||
if (_cpp_handle_directive (pfile))
|
||||
return CPP_DIRECTIVE;
|
||||
return CPP_DIRECTIVE;
|
||||
pfile->only_seen_white = 0;
|
||||
CPP_PUTC (pfile, '#');
|
||||
return CPP_OTHER;
|
||||
return CPP_HASH;
|
||||
|
||||
case CPP_MACRO:
|
||||
pfile->potential_control_macro = 0;
|
||||
|
@ -1777,11 +1835,6 @@ _cpp_get_directive_token (pfile)
|
|||
goto get_next;
|
||||
return CPP_HSPACE;
|
||||
|
||||
case CPP_DIRECTIVE:
|
||||
/* Don't execute the directive, but don't smash it to OTHER either. */
|
||||
CPP_PUTC (pfile, '#');
|
||||
return CPP_DIRECTIVE;
|
||||
|
||||
case CPP_MACRO:
|
||||
if (! pfile->no_macro_expand
|
||||
&& maybe_macroexpand (pfile, old_written))
|
||||
|
@ -2134,7 +2187,7 @@ _cpp_init_input_buffer (pfile)
|
|||
U_CHAR *tmp;
|
||||
|
||||
init_chartab ();
|
||||
init_token_list (pfile, &pfile->directbuf, 0);
|
||||
_cpp_init_toklist (&pfile->directbuf);
|
||||
|
||||
/* Determine the appropriate size for the input buffer. Normal C
|
||||
source files are smaller than eight K. */
|
||||
|
@ -2294,17 +2347,6 @@ expand_comment_space (list)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
cpp_free_token_list (list)
|
||||
cpp_toklist *list;
|
||||
{
|
||||
if (list->comments)
|
||||
free (list->comments);
|
||||
free (list->tokens - 1); /* Backup over dummy token. */
|
||||
free (list->namebuf);
|
||||
free (list);
|
||||
}
|
||||
|
||||
void
|
||||
init_trigraph_map ()
|
||||
{
|
||||
|
@ -3175,7 +3217,7 @@ _cpp_lex_line (pfile, list)
|
|||
break;
|
||||
}
|
||||
/* Is this the beginning of a header name? */
|
||||
if (list->dir_flags & SYNTAX_INCLUDE)
|
||||
if (list->flags & SYNTAX_INCLUDE)
|
||||
{
|
||||
c = '>'; /* Terminator. */
|
||||
cur_token->type = CPP_HEADER_NAME;
|
||||
|
@ -3304,7 +3346,7 @@ _cpp_lex_line (pfile, list)
|
|||
invalid directives in assembly source, we don't know where the
|
||||
comments are, and # may introduce assembler pseudo-ops. */
|
||||
|
||||
if (IS_DIRECTIVE (list) && list->dir_handler == 0
|
||||
if (IS_DIRECTIVE (list) && list->dirno == -1
|
||||
&& list->tokens[1].type != CPP_VSPACE
|
||||
&& !CPP_OPTION (pfile, lang_asm))
|
||||
cpp_error_with_line (pfile, list->line, list->tokens[1].col,
|
||||
|
@ -3385,31 +3427,25 @@ void
|
|||
_cpp_lex_file (pfile)
|
||||
cpp_reader* pfile;
|
||||
{
|
||||
int recycle;
|
||||
cpp_toklist* list;
|
||||
|
||||
init_trigraph_map ();
|
||||
list = (cpp_toklist *) xmalloc (sizeof (cpp_toklist));
|
||||
_cpp_init_toklist (list);
|
||||
|
||||
for (recycle = 0; ;)
|
||||
for (;;)
|
||||
{
|
||||
init_token_list (pfile, list, recycle);
|
||||
recycle = 1;
|
||||
|
||||
_cpp_lex_line (pfile, list);
|
||||
if (list->tokens[0].type == CPP_EOF)
|
||||
break;
|
||||
|
||||
if (list->dir_handler)
|
||||
{
|
||||
if (list->dir_handler (pfile))
|
||||
{
|
||||
list = (cpp_toklist *) xmalloc (sizeof (cpp_toklist));
|
||||
recycle = 0;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
if (list->dirno)
|
||||
_cpp_handle_directive (pfile, list);
|
||||
else
|
||||
#endif
|
||||
_cpp_output_list (pfile, list);
|
||||
_cpp_clear_toklist (list);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
249
gcc/cpplib.c
249
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");
|
||||
|
||||
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");
|
||||
|
||||
if (_cpp_get_directive_token (pfile) != CPP_CLOSE_PAREN)
|
||||
ICE ("impossible token, expecting ) in do_assert");
|
||||
|
||||
if (_cpp_get_directive_token (pfile) != CPP_VSPACE)
|
||||
{
|
||||
cpp_error (pfile, "junk at end of #assert");
|
||||
goto error;
|
||||
}
|
||||
sym = pfile->token_buffer + old_written;
|
||||
ERROR ("junk at end of #assert");
|
||||
|
||||
this = _cpp_lookup (pfile, sym, tlen);
|
||||
if (this->type == T_ASSERT)
|
||||
if (hp->type == T_ASSERTION)
|
||||
{
|
||||
cpp_warning (pfile, "%s re-asserted", sym);
|
||||
goto error;
|
||||
}
|
||||
|
||||
blen = ustrchr (sym, '(') - sym;
|
||||
base = _cpp_lookup (pfile, sym, blen);
|
||||
if (base->type == T_VOID)
|
||||
{
|
||||
base->type = T_ASSERT;
|
||||
base->value.aschain = 0;
|
||||
}
|
||||
/* Check for reassertion. */
|
||||
const struct predicate *old;
|
||||
|
||||
this->type = T_ASSERT;
|
||||
this->value.aschain = base->value.aschain;
|
||||
base->value.aschain = this;
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
hp->type = T_ASSERTION;
|
||||
pred->next = 0;
|
||||
}
|
||||
|
||||
_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++;
|
||||
|
||||
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");
|
||||
|
||||
if (_cpp_get_directive_token (pfile) != CPP_VSPACE)
|
||||
{
|
||||
cpp_error (pfile, "junk at end of #unassert");
|
||||
goto out;
|
||||
}
|
||||
sym = pfile->token_buffer + old_written;
|
||||
CPP_SET_WRITTEN (pfile, old_written);
|
||||
len = CPP_WRITTEN (pfile) - old_written;
|
||||
hp = _cpp_lookup (pfile, sym, len);
|
||||
|
||||
if (ret == 1)
|
||||
type = _cpp_get_directive_token (pfile);
|
||||
if (type == CPP_OPEN_PAREN)
|
||||
{
|
||||
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. */
|
||||
pred = (struct predicate *) xmalloc (sizeof (struct predicate));
|
||||
_cpp_init_toklist (&pred->answer);
|
||||
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
|
22
gcc/cpplib.h
22
gcc/cpplib.h
|
@ -124,7 +124,6 @@ typedef struct cpp_name cpp_name;
|
|||
T(CPP_VSPACE, "\n") /* End of line. */ \
|
||||
N(CPP_EOF, 0) /* End of file. */ \
|
||||
N(CPP_HEADER_NAME, 0) /* <stdio.h> in #include */ \
|
||||
N(CPP_ASSERTION, 0) /* (...) in #assert */ \
|
||||
\
|
||||
/* Obsolete - will be removed when no code uses them still. */ \
|
||||
N(CPP_HSPACE, 0) /* Horizontal white space. */ \
|
||||
|
@ -189,6 +188,9 @@ struct cpp_token
|
|||
} val;
|
||||
};
|
||||
|
||||
/* General flags. */
|
||||
#define LIST_OFFSET (1 << 0)
|
||||
|
||||
/* Directive flags. */
|
||||
#define SYNTAX_INCLUDE (1 << 8)
|
||||
|
||||
|
@ -211,12 +213,12 @@ struct cpp_toklist
|
|||
unsigned int comments_used; /* comment tokens used. */
|
||||
unsigned int comments_cap; /* comment token capacity. */
|
||||
|
||||
/* Only used if tokens[0].type == CPP_DIRECTIVE. This is the
|
||||
handler to call after lexing the rest of this line. The flags
|
||||
indicate whether the rest of the line gets special treatment
|
||||
during lexing (#include, #if, #assert, #unassert). */
|
||||
directive_handler dir_handler;
|
||||
unsigned short dir_flags;
|
||||
/* The handler to call after lexing the rest of this line.
|
||||
-1 for none */
|
||||
short dirno;
|
||||
|
||||
/* Per-list flags, see above */
|
||||
unsigned short flags;
|
||||
};
|
||||
|
||||
struct cpp_buffer
|
||||
|
@ -544,12 +546,6 @@ struct cpp_reader
|
|||
/* If true, characters between '<' and '>' are a single (string) token. */
|
||||
unsigned char parsing_include_directive;
|
||||
|
||||
/* If true, # introduces an assertion (see do_assert) */
|
||||
unsigned char parsing_if_directive;
|
||||
|
||||
/* If true, # and ## are the STRINGIZE and TOKPASTE operators */
|
||||
unsigned char parsing_define_directive;
|
||||
|
||||
/* True if escape sequences (as described for has_escapes in
|
||||
parse_buffer) should be emitted. */
|
||||
unsigned char output_escapes;
|
||||
|
|
Loading…
Add table
Reference in a new issue