Commit ba412f14 by Zack Weinberg Committed by Zack Weinberg

cpplib.h (CPP_ASSERTION, [...]): New token types.

	* cpplib.h (CPP_ASSERTION, CPP_STRINGIZE, CPP_TOKPASTE): New
	token types.
	(struct cpp_reader): Add parsing_if_directive and
	parsing_define_directive flags.
	(struct cpp_options): Remove output_conditionals flag.
	(check_macro_name): Delete prototype.

	* cpphash.h (struct macrodef): Delete.
	(struct reflist): Separate from struct definition.
	(struct definition): Remove unused fields.  Add column number.
	(create_definition): Returns a DEFINITION *.  Takes a
	cpp_reader * and an int.

	* cpphash.c (SKIP_WHITE_SPACE): Delete.
	(PEEKC): Copy defn from cpplib.c.
	(rest_extension, REST_EXTENSION_LENGTH): Delete.
	(struct arg): New.
	(struct arglist): Simplify.
	(collect_expansion): Rewrite.  Get tokens by calling
	cpp_get_token.  Add more error checking.
	(collect_formal_parameters): New function, broken out of
	create_definition and reworked to use get_directive_token.
	(create_definition): All real work is now in collect_expansion
	and collect_formal_parameters.  do_define handles finding the
	macro name.  Return a DEFINITION, not a MACRODEF.
	(macroexpand): Replace bcopy with memcpy throughout.  Replace
	character-at-a-time copy loop with memcpy and pointer increments.
	(compare-defs): d1->argnames / d2->argnames might be null.

	* cpplib.c (copy_rest_of_line): Delete function.
	(skip_rest_of_line): Do all the work ourselves.
	(skip_string): New function.
	(parse_string): Use skip_string.
	(get_macro_name): New function.
	(check_macro_name): Delete.
	(copy_comment): Use CPP_RESERVE and CPP_PUTC_Q.
	(cpp_skip_hspace): Use CPP_BUMP_LINE.
	(handle_directive): ICE if we're called on a macro buffer.
	(do_define): Determine macro name and type (funlike/objlike)
	here.  Expunge all uses of MACRODEF.
	(cpp_push_buffer): Set line_base to NULL.
	(do_undef, read_line_number): Don't worry about getting a POP token.
	(eval_if_expression): Set/reset parsing_if_directive around
	cpp_parse_expr. Don't clear only_seen_white.
	(skip_if_group): Remove output_conditionals logic.  Use
	skip_rest_of_line.
	(cpp_get_token): Return ASSERTION, STRINGIZE, and TOKPASTE
	tokens under appropriate conditions.
	(cpp_unassert): Call do_unassert not do_assert.  Oops.

	* cppexp.c (parse_defined): New function, break out of
	cpp_lex.
	(cpp_lex): We now get CPP_ASSERTION tokens and can check them
	ourselves, with cpp_defined.
	* cppinit.c (cpp_handle_option, print_help): Delete -ifoutput.

	* gcc.dg/20000209-2.c: Turn off -pedantic-errors.
	* gcc.dg/strpaste-2.c: New.

From-SVN: r32274
parent 38769add
2000-02-29 Zack Weinberg <zack@wolery.cumb.org>
* cpplib.h (CPP_ASSERTION, CPP_STRINGIZE, CPP_TOKPASTE): New
token types.
(struct cpp_reader): Add parsing_if_directive and
parsing_define_directive flags.
(struct cpp_options): Remove output_conditionals flag.
(check_macro_name): Delete prototype.
* cpphash.h (struct macrodef): Delete.
(struct reflist): Separate from struct definition.
(struct definition): Remove unused fields. Add column number.
(create_definition): Returns a DEFINITION *. Takes a
cpp_reader * and an int.
* cpphash.c (SKIP_WHITE_SPACE): Delete.
(PEEKC): Copy defn from cpplib.c.
(rest_extension, REST_EXTENSION_LENGTH): Delete.
(struct arg): New.
(struct arglist): Simplify.
(collect_expansion): Rewrite. Get tokens by calling
cpp_get_token. Add more error checking.
(collect_formal_parameters): New function, broken out of
create_definition and reworked to use get_directive_token.
(create_definition): All real work is now in collect_expansion
and collect_formal_parameters. do_define handles finding the
macro name. Return a DEFINITION, not a MACRODEF.
(macroexpand): Replace bcopy with memcpy throughout. Replace
character-at-a-time copy loop with memcpy and pointer increments.
(compare-defs): d1->argnames / d2->argnames might be null.
* cpplib.c (copy_rest_of_line): Delete function.
(skip_rest_of_line): Do all the work ourselves.
(skip_string): New function.
(parse_string): Use skip_string.
(get_macro_name): New function.
(check_macro_name): Delete.
(copy_comment): Use CPP_RESERVE and CPP_PUTC_Q.
(cpp_skip_hspace): Use CPP_BUMP_LINE.
(handle_directive): ICE if we're called on a macro buffer.
(do_define): Determine macro name and type (funlike/objlike)
here. Expunge all uses of MACRODEF.
(cpp_push_buffer): Set line_base to NULL.
(do_undef, read_line_number): Don't worry about getting a POP token.
(eval_if_expression): Set/reset parsing_if_directive around
cpp_parse_expr. Don't clear only_seen_white.
(skip_if_group): Remove output_conditionals logic. Use
skip_rest_of_line.
(cpp_get_token): Return ASSERTION, STRINGIZE, and TOKPASTE
tokens under appropriate conditions.
(cpp_unassert): Call do_unassert not do_assert. Oops.
* cppexp.c (parse_defined): New function, break out of
cpp_lex.
(cpp_lex): We now get CPP_ASSERTION tokens and can check them
ourselves, with cpp_defined.
* cppinit.c (cpp_handle_option, print_help): Delete -ifoutput.
* gcc.dg/20000209-2.c: Turn off -pedantic-errors.
* gcc.dg/strpaste-2.c: New.
2000-02-29 Mark Mitchell <mark@codesourcery.com>
* fold-const.c (size_binop): Don't asert inputs are the same and
......
......@@ -81,6 +81,7 @@ static HOST_WIDEST_INT left_shift PARAMS ((cpp_reader *, HOST_WIDEST_INT, int, u
static HOST_WIDEST_INT right_shift PARAMS ((cpp_reader *, HOST_WIDEST_INT, int, unsigned HOST_WIDEST_INT));
static struct operation parse_number PARAMS ((cpp_reader *, U_CHAR *, 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 cpp_lex PARAMS ((cpp_reader *, int));
extern HOST_WIDEST_INT cpp_parse_expr PARAMS ((cpp_reader *));
static HOST_WIDEST_INT cpp_parse_escape PARAMS ((cpp_reader *, U_CHAR **, HOST_WIDEST_INT));
......@@ -349,6 +350,53 @@ parse_charconst (pfile, start, end)
return op;
}
static struct operation
parse_defined (pfile)
cpp_reader *pfile;
{
int paren = 0, len;
U_CHAR *tok;
enum cpp_token token;
struct operation op;
long old_written = CPP_WRITTEN (pfile);
op.unsignedp = 0;
op.op = INT;
pfile->no_macro_expand++;
token = get_directive_token (pfile);
if (token == CPP_LPAREN)
{
paren++;
CPP_SET_WRITTEN (pfile, old_written);
token = get_directive_token (pfile);
}
if (token != CPP_NAME)
goto oops;
tok = pfile->token_buffer + old_written;
len = CPP_PWRITTEN (pfile) - tok;
op.value = cpp_defined (pfile, tok, len);
if (paren)
{
if (get_directive_token (pfile) != CPP_RPAREN)
goto oops;
}
CPP_SET_WRITTEN (pfile, old_written);
pfile->no_macro_expand--;
return op;
oops:
CPP_SET_WRITTEN (pfile, old_written);
pfile->no_macro_expand--;
cpp_error (pfile, "`defined' without an identifier");
op.op = ERROR;
return op;
}
struct token {
const char *operator;
......@@ -407,51 +455,22 @@ cpp_lex (pfile, skip_evaluation)
return parse_charconst (pfile, tok_start, tok_end);
case CPP_NAME:
if (!strcmp (tok_start, "defined"))
return parse_defined (pfile);
op.op = INT;
op.unsignedp = 0;
op.value = 0;
if (strcmp (tok_start, "defined"))
{
if (CPP_WARN_UNDEF (pfile) && !skip_evaluation)
cpp_warning (pfile, "`%.*s' is not defined",
(int) (tok_end - tok_start), tok_start);
}
else
{
int paren = 0, len;
U_CHAR *tok;
pfile->no_macro_expand++;
token = get_directive_token (pfile);
if (token == CPP_LPAREN)
{
paren++;
CPP_SET_WRITTEN (pfile, old_written);
token = get_directive_token (pfile);
}
if (token != CPP_NAME)
goto oops;
tok = pfile->token_buffer + old_written;
len = CPP_PWRITTEN (pfile) - tok;
if (cpp_defined (pfile, tok, len))
op.value = 1;
if (paren)
{
if (get_directive_token (pfile) != CPP_RPAREN)
goto oops;
}
CPP_SET_WRITTEN (pfile, old_written);
pfile->no_macro_expand--;
}
return op;
oops:
CPP_SET_WRITTEN (pfile, old_written);
pfile->no_macro_expand--;
cpp_error (pfile, "`defined' without an identifier");
case CPP_ASSERTION:
op.op = INT;
op.unsignedp = 0;
op.value = cpp_defined (pfile, tok_start, tok_end - tok_start);
return op;
case CPP_OTHER:
......@@ -468,13 +487,6 @@ cpp_lex (pfile, skip_evaluation)
op.op = toktab->token;
return op;
}
else if (tok_start + 1 == tok_end && *tok_start == '#')
{
CPP_FORWARD (CPP_BUFFER (pfile), -1);
op.op = INT;
op.value = cpp_read_check_assertion (pfile);
return op;
}
/* fall through */
default:
op.op = *tok_start;
......
......@@ -41,10 +41,9 @@ static enum cpp_token macarg PARAMS ((cpp_reader *, int));
static struct tm *timestamp PARAMS ((cpp_reader *));
static void special_symbol PARAMS ((HASHNODE *, cpp_reader *));
#define SKIP_WHITE_SPACE(p) do { while (is_hspace(*p)) p++; } while (0)
#define CPP_IS_MACRO_BUFFER(PBUF) ((PBUF)->data != NULL)
#define FORWARD(N) CPP_FORWARD (CPP_BUFFER (pfile), (N))
#define PEEKC() CPP_BUF_PEEK (CPP_BUFFER (pfile))
/* The arglist structure is built by create_definition to tell
collect_expansion where the argument names begin. That
......@@ -57,17 +56,23 @@ static void special_symbol PARAMS ((HASHNODE *, cpp_reader *));
the current #define has been processed and entered into the
hash table. */
struct arglist
struct arg
{
struct arglist *next;
U_CHAR *name;
int length;
int argno;
char rest_args;
int len;
char rest_arg;
};
struct arglist
{
U_CHAR *namebuf;
struct arg *argv;
int argc;
};
static DEFINITION *collect_expansion PARAMS ((cpp_reader *, U_CHAR *, U_CHAR *,
int, struct arglist *));
static DEFINITION *collect_expansion PARAMS ((cpp_reader *, struct arglist *));
static struct arglist *collect_formal_parameters PARAMS ((cpp_reader *));
/* This structure represents one parsed argument in a macro call.
`raw' points to the argument text as written (`raw_length' is its length).
......@@ -251,502 +256,470 @@ macro_cleanup (pbuf, pfile)
}
/* Read a replacement list for a macro with parameters.
Build the DEFINITION structure.
Reads characters of text starting at BUF until END.
ARGLIST specifies the formal parameters to look for
in the text of the definition; NARGS is the number of args
in that list, or -1 for a macro name that wants no argument list.
MACRONAME is the macro name itself (so we can avoid recursive expansion)
and NAMELEN is its length in characters.
/* Read a replacement list for a macro, and build the DEFINITION
structure. ARGLIST specifies the formal parameters to look for in
the text of the definition. If ARGLIST is null, this is an
object-like macro; if it points to an empty arglist, this is a
function-like macro with no arguments.
Note that comments, backslash-newlines, and leading white space
have already been deleted from the argument. */
A good half of this is devoted to supporting -traditional.
Kill me now. */
static DEFINITION *
collect_expansion (pfile, buf, limit, nargs, arglist)
collect_expansion (pfile, arglist)
cpp_reader *pfile;
U_CHAR *buf, *limit;
int nargs;
struct arglist *arglist;
{
DEFINITION *defn;
register U_CHAR *p, *lastp, *exp_p;
struct reflist *endpat = NULL;
/* Pointer to first nonspace after last ## seen. */
U_CHAR *concat = 0;
/* Pointer to first nonspace after last single-# seen. */
U_CHAR *stringify = 0;
int maxsize;
int expected_delimiter = '\0';
/* Scan thru the replacement list, ignoring comments and quoted
strings, picking up on the macro calls. It does a linear search
thru the arg list on every potential symbol. Profiling might say
that something smarter should happen. */
struct reflist *pat = 0, *endpat = 0;
enum cpp_token token;
long start, here, last;
int i;
int argc;
size_t len;
struct arg *argv;
U_CHAR *tok, *exp;
enum { START = 0, NORM, ARG, STRIZE, PASTE } last_token = START;
if (limit < buf)
if (arglist)
{
cpp_ice (pfile, "limit < buf in collect_expansion");
limit = buf; /* treat it like a null defn */
argv = arglist->argv;
argc = arglist->argc;
}
/* Find the beginning of the trailing whitespace. */
p = buf;
while (p < limit && is_space(limit[-1]))
limit--;
/* Allocate space for the text in the macro definition.
Leading and trailing whitespace chars need 2 bytes each.
Each other input char may or may not need 1 byte,
so this is an upper bound. The extra 5 are for invented
leading and trailing escape-marker and final null. */
maxsize = (sizeof (DEFINITION)
+ (limit - p) + 5);
defn = (DEFINITION *) xcalloc (1, maxsize);
defn->nargs = nargs;
exp_p = defn->expansion = (U_CHAR *) defn + sizeof (DEFINITION);
lastp = exp_p;
p = buf;
/* Add one initial space escape-marker to prevent accidental
token-pasting (often removed by macroexpand). */
*exp_p++ = '\r';
*exp_p++ = ' ';
if (limit - p >= 2 && p[0] == '#' && p[1] == '#')
else
{
cpp_error (pfile, "`##' at start of macro definition");
p += 2;
argv = 0;
argc = 0;
}
/* Process the main body of the definition. */
while (p < limit)
last = start = CPP_WRITTEN (pfile);
last -= 2; /* two extra chars for the leading escape */
for (;;)
{
int skipped_arg = 0;
register U_CHAR c = *p++;
*exp_p++ = c;
/* We use cpp_get_token because get_directive_token would
discard whitespace and we can't cope with that yet. Macro
expansion is off, so we are guaranteed not to see POP or EOF. */
if (!CPP_TRADITIONAL (pfile))
while (PEEKC () == '\r')
{
switch (c)
{
case '\'':
case '\"':
if (expected_delimiter != '\0')
{
if (c == expected_delimiter)
expected_delimiter = '\0';
FORWARD (1);
CPP_BUMP_LINE (pfile);
}
else
expected_delimiter = c;
break;
case '\\':
if (p < limit && expected_delimiter)
if (PEEKC () == '\n')
goto done;
here = CPP_WRITTEN (pfile);
token = cpp_get_token (pfile);
tok = pfile->token_buffer + here;
switch (token)
{
/* In a string, backslash goes through
and makes next char ordinary. */
*exp_p++ = *p++;
}
case CPP_POP:
case CPP_EOF:
case CPP_VSPACE:
cpp_ice (pfile, "EOF or VSPACE in collect_expansion");
goto done;
case CPP_HSPACE:
if (last_token == STRIZE || last_token == PASTE
|| last_token == START)
CPP_SET_WRITTEN (pfile, here);
break;
case '#':
/* # is ordinary inside a string. */
if (expected_delimiter)
case CPP_STRINGIZE:
if (last_token == PASTE)
/* Not really a stringifier. */
goto norm;
last_token = STRIZE;
CPP_SET_WRITTEN (pfile, here); /* delete from replacement text */
break;
if (p < limit && *p == '#')
{
/* ##: concatenate preceding and following tokens. */
/* Take out the first #, discard preceding whitespace. */
exp_p--;
while (exp_p > lastp && is_hspace(exp_p[-1]))
--exp_p;
/* Skip the second #. */
p++;
/* Discard following whitespace. */
SKIP_WHITE_SPACE (p);
concat = p;
if (p == limit)
cpp_error (pfile, "`##' at end of macro definition");
}
else if (nargs >= 0)
case CPP_TOKPASTE:
/* If the last token was an argument, discard this token and
any hspace between it and the argument's position. Then
mark the arg raw_after. */
if (last_token == ARG)
{
/* Single #: stringify following argument ref.
Don't leave the # in the expansion. */
exp_p--;
SKIP_WHITE_SPACE (p);
if (p == limit || !is_idstart(*p)
|| (*p == 'L' && p + 1 < limit && (p[1] == '\'' ||
p[1] == '"')))
cpp_error (pfile,
"`#' operator is not followed by a macro argument name");
else
stringify = p;
}
endpat->raw_after = 1;
last_token = PASTE;
CPP_SET_WRITTEN (pfile, last);
break;
}
}
else
{
/* In -traditional mode, recognize arguments inside strings and
character constants, and ignore special properties of #.
Arguments inside strings are considered "stringified", but no
extra quote marks are supplied. */
switch (c)
{
case '\'':
case '\"':
if (expected_delimiter != '\0')
{
if (c == expected_delimiter)
expected_delimiter = '\0';
}
else
expected_delimiter = c;
break;
else if (last_token == PASTE)
/* ## ## - the second ## is ordinary. */
goto norm;
case '\\':
/* Backslash quotes delimiters and itself,
but not macro args. */
if (expected_delimiter != 0 && p < limit
&& (*p == expected_delimiter || *p == '\\'))
{
*exp_p++ = *p++;
continue;
}
/* Discard the token and any hspace before it. */
while (is_hspace (pfile->token_buffer[here-1]))
here--;
CPP_SET_WRITTEN (pfile, here);
if (last_token == STRIZE)
/* Oops - that wasn't a stringify operator. */
CPP_PUTC (pfile, '#');
last_token = PASTE;
break;
case '/':
if (expected_delimiter != '\0')
/* No comments inside strings. */
case CPP_COMMENT:
/* We must be in -traditional mode. Pretend this was a
token paste, but only if there was no leading or
trailing space. */
CPP_SET_WRITTEN (pfile, here);
if (is_hspace (pfile->token_buffer[here-1]))
break;
if (*p == '*')
{
/* If we find a comment that wasn't removed by
handle_directive, this must be -traditional.
So replace the comment with nothing at all. */
exp_p--;
p += 1;
while (p < limit && !(p[-2] == '*' && p[-1] == '/'))
p++;
}
if (is_hspace (PEEKC ()))
break;
if (last_token == ARG)
endpat->raw_after = 1;
last_token = PASTE;
break;
case CPP_STRING:
case CPP_CHAR:
if (last_token == STRIZE)
cpp_error (pfile, "`#' is not followed by a macro argument name");
if (CPP_TRADITIONAL (pfile) || CPP_OPTIONS (pfile)->warn_stringify)
goto maybe_trad_stringify;
else
goto norm;
case CPP_NAME:
for (i = 0; i < argc; i++)
if (!strncmp (tok, argv[i].name, argv[i].len)
&& ! is_idchar (tok[argv[i].len]))
goto addref;
/* fall through */
default:
norm:
if (last_token == STRIZE)
cpp_error (pfile, "`#' is not followed by a macro argument name");
last_token = NORM;
break;
}
}
continue;
/* Handle the start of a symbol. */
if (is_idchar(c) && nargs > 0)
addref:
{
U_CHAR *id_beg = p - 1;
int id_len;
struct reflist *tpat;
--exp_p;
while (p != limit && is_idchar(*p))
p++;
id_len = p - id_beg;
/* Make a pat node for this arg and add it to the pat list */
tpat = (struct reflist *) xmalloc (sizeof (struct reflist));
tpat->next = NULL;
tpat->raw_before = (last_token == PASTE);
tpat->raw_after = 0;
tpat->stringify = (last_token == STRIZE);
tpat->rest_args = argv[i].rest_arg;
tpat->argno = i;
tpat->nchars = here - last;
if (is_idstart(c)
&& !(id_len == 1 && c == 'L' && (*p == '\'' || *p == '"')))
{
register struct arglist *arg;
if (endpat == NULL)
pat = tpat;
else
endpat->next = tpat;
endpat = tpat;
last = here;
}
CPP_SET_WRITTEN (pfile, here); /* discard arg name */
last_token = ARG;
continue;
for (arg = arglist; arg != NULL; arg = arg->next)
maybe_trad_stringify:
{
U_CHAR *base, *p, *limit;
struct reflist *tpat;
if (arg->name[0] == c
&& arg->length == id_len
&& strncmp (arg->name, id_beg, id_len) == 0)
{
if (expected_delimiter && CPP_OPTIONS
(pfile)->warn_stringify)
{
if (CPP_TRADITIONAL (pfile))
base = p = pfile->token_buffer + here;
limit = CPP_PWRITTEN (pfile);
while (++p < limit)
{
cpp_warning (pfile,
"macro argument `%.*s' is stringified.",
id_len, arg->name);
}
else
if (is_idstart (*p))
continue;
for (i = 0; i < argc; i++)
if (!strncmp (tok, argv[i].name, argv[i].len)
&& ! is_idchar (tok[argv[i].len]))
goto mts_addref;
continue;
mts_addref:
if (!CPP_TRADITIONAL (pfile))
{
/* Must have got here because of -Wtraditional. */
cpp_warning (pfile,
"macro arg `%.*s' would be stringified with -traditional.",
id_len, arg->name);
}
"macro argument `%.*s' would be stringified with -traditional",
(int) argv[i].len, argv[i].name);
continue;
}
/* If ANSI, don't actually substitute
inside a string. */
if (!CPP_TRADITIONAL (pfile) && expected_delimiter)
break;
/* make a pat node for this arg and append it
to the end of the pat list */
tpat = (struct reflist *)
xmalloc (sizeof (struct reflist));
if (CPP_OPTIONS (pfile)->warn_stringify)
cpp_warning (pfile, "macro argument `%.*s' is stringified",
(int) argv[i].len, argv[i].name);
/* Remove the argument from the string. */
memmove (p, p + argv[i].len, limit - (p + argv[i].len));
limit -= argv[i].len;
/* Make a pat node for this arg and add it to the pat list */
tpat = (struct reflist *) xmalloc (sizeof (struct reflist));
tpat->next = NULL;
tpat->raw_before = concat == id_beg;
/* Don't attempt to paste this with anything. */
tpat->raw_before = 0;
tpat->raw_after = 0;
tpat->rest_args = arg->rest_args;
tpat->stringify = (CPP_TRADITIONAL (pfile)
? expected_delimiter != '\0'
: stringify == id_beg);
tpat->stringify = 1;
tpat->rest_args = argv[i].rest_arg;
tpat->argno = i;
tpat->nchars = (p - base) + here - last;
if (endpat == NULL)
defn->pattern = tpat;
pat = tpat;
else
endpat->next = tpat;
endpat = tpat;
tpat->argno = arg->argno;
tpat->nchars = exp_p - lastp;
{
register U_CHAR *p1 = p;
SKIP_WHITE_SPACE (p1);
if (p1 + 2 <= limit && p1[0] == '#' && p1[1] == '#')
tpat->raw_after = 1;
}
lastp = exp_p;
skipped_arg = 1;
break;
last = (p - base) + here;
}
CPP_ADJUST_WRITTEN (pfile, CPP_PWRITTEN (pfile) - limit);
}
}
done:
/* If this was not a macro arg, copy it into the expansion. */
if (!skipped_arg)
{
register U_CHAR *lim1 = p;
p = id_beg;
while (p != lim1)
*exp_p++ = *p++;
if (stringify == id_beg)
cpp_error (pfile,
"`#' operator should be followed by a macro argument name");
}
}
}
if (last_token == STRIZE)
cpp_error (pfile, "`#' is not followed by a macro argument name");
else if (last_token == PASTE)
cpp_error (pfile, "`##' at end of macro definition");
if (!CPP_TRADITIONAL (pfile) && expected_delimiter == 0)
CPP_NUL_TERMINATE (pfile);
len = CPP_WRITTEN (pfile) - start + 1;
exp = xmalloc (len + 4); /* space for no-concat markers at either end */
exp[0] = '\r';
exp[1] = ' ';
exp[len + 1] = '\r';
exp[len + 2] = ' ';
exp[len + 3] = '\0';
memcpy (&exp[2], pfile->token_buffer + start, len - 1);
CPP_SET_WRITTEN (pfile, start);
defn = (DEFINITION *) xmalloc (sizeof (DEFINITION));
defn->length = len + 3;
defn->expansion = exp;
defn->pattern = pat;
defn->rest_args = 0;
if (arglist)
{
defn->nargs = argc;
defn->argnames = arglist->namebuf;
if (argv)
{
defn->rest_args = argv[argc - 1].rest_arg;
free (argv);
}
free (arglist);
}
else
{
/* If ANSI, put in a "\r " marker to prevent token pasting.
But not if "inside a string" (which in ANSI mode
happens only for -D option). */
*exp_p++ = '\r';
*exp_p++ = ' ';
defn->nargs = -1;
defn->argnames = 0;
defn->rest_args = 0;
}
*exp_p = '\0';
defn->length = exp_p - defn->expansion;
/* Crash now if we overrun the allocated size. */
if (defn->length + 1 > maxsize)
abort ();
#if 0
/* This isn't worth the time it takes. */
/* give back excess storage */
defn->expansion = (U_CHAR *) xrealloc (defn->expansion, defn->length + 1);
#endif
return defn;
}
/*
* special extension string that can be added to the last macro argument to
* allow it to absorb the "rest" of the arguments when expanded. Ex:
* #define wow(a, b...) process (b, a, b)
* { wow (1, 2, 3); } -> { process (2, 3, 1, 2, 3); }
* { wow (one, two); } -> { process (two, one, two); }
* if this "rest_arg" is used with the concat token '##' and if it is not
* supplied then the token attached to with ## will not be outputted. Ex:
* #define wow (a, b...) process (b ## , a, ## b)
* { wow (1, 2); } -> { process (2, 1, 2); }
* { wow (one); } -> { process (one); {
*/
static char rest_extension[] = "...";
#define REST_EXTENSION_LENGTH (sizeof (rest_extension) - 1)
/* Create a DEFINITION node from a #define directive. Arguments are
as for do_define. */
MACRODEF
create_definition (buf, limit, pfile)
U_CHAR *buf, *limit;
static struct arglist *
collect_formal_parameters (pfile)
cpp_reader *pfile;
{
U_CHAR *bp; /* temp ptr into input buffer */
U_CHAR *symname; /* remember where symbol name starts */
int sym_length; /* and how long it is */
int rest_args = 0;
long line, col;
const char *file =
CPP_BUFFER (pfile) ? CPP_BUFFER (pfile)->nominal_fname : "";
DEFINITION *defn;
int arglengths = 0; /* Accumulate lengths of arg names
plus number of args. */
MACRODEF mdef;
cpp_buf_line_and_col (CPP_BUFFER (pfile), &line, &col);
bp = buf;
while (is_hspace(*bp))
bp++;
symname = bp; /* remember where it starts */
struct arglist *result = 0;
struct arg *argv = 0;
U_CHAR *namebuf = xstrdup ("");
sym_length = check_macro_name (pfile, bp);
bp += sym_length;
U_CHAR *name, *tok;
size_t argslen = 1;
int len;
int argc = 0;
int i;
enum cpp_token token;
long old_written;
/* Lossage will occur if identifiers or control keywords are broken
across lines using backslash. This is not the right place to take
care of that. */
old_written = CPP_WRITTEN (pfile);
token = get_directive_token (pfile);
if (token != CPP_LPAREN)
{
cpp_ice (pfile, "first token = %d not %d in collect_formal_parameters",
token, CPP_LPAREN);
goto invalid;
}
if (*bp == '(')
argv = (struct arg *) xmalloc (sizeof (struct arg));
argv[argc].len = 0;
argv[argc].rest_arg = 0;
for (;;)
{
CPP_SET_WRITTEN (pfile, old_written);
token = get_directive_token (pfile);
switch (token)
{
struct arglist *arg_ptrs = NULL;
int argno = 0;
case CPP_NAME:
tok = pfile->token_buffer + old_written;
len = CPP_PWRITTEN (pfile) - tok;
if (namebuf
&& (name = strstr (namebuf, tok))
&& name[len] == ','
&& (name == namebuf || name[-1] == ','))
{
cpp_error (pfile, "duplicate macro argument name `%s'", tok);
continue;
}
namebuf = xrealloc (namebuf, argslen + len + 1);
name = &namebuf[argslen - 1];
argslen += len + 1;
bp++; /* skip '(' */
SKIP_WHITE_SPACE (bp);
memcpy (name, tok, len);
name[len] = ',';
name[len+1] = '\0';
argv[argc].len = len;
argv[argc].rest_arg = 0;
break;
/* Loop over macro argument names. */
while (*bp != ')')
{
struct arglist *temp;
case CPP_COMMA:
argc++;
argv = xrealloc (argv, (argc + 1)*sizeof(struct arg));
argv[argc].len = 0;
break;
temp = (struct arglist *) alloca (sizeof (struct arglist));
temp->name = bp;
temp->next = arg_ptrs;
temp->argno = argno++;
temp->rest_args = 0;
arg_ptrs = temp;
case CPP_RPAREN:
goto done;
if (rest_args)
cpp_pedwarn (pfile, "another parameter follows `%s'",
rest_extension);
case CPP_3DOTS:
goto rest_arg;
if (!is_idstart(*bp))
cpp_pedwarn (pfile, "invalid character in macro parameter name");
case CPP_VSPACE:
cpp_error (pfile, "missing right paren in macro argument list");
goto invalid;
/* Find the end of the arg name. */
while (is_idchar(*bp))
{
bp++;
/* do we have a "special" rest-args extension here? */
if ((size_t) (limit - bp) > REST_EXTENSION_LENGTH
&& !strncmp (rest_extension, bp, REST_EXTENSION_LENGTH))
{
rest_args = 1;
temp->rest_args = 1;
break;
}
default:
cpp_error (pfile, "syntax error in #define");
goto invalid;
}
temp->length = bp - temp->name;
if (rest_args == 1)
bp += REST_EXTENSION_LENGTH;
arglengths += temp->length + 2;
SKIP_WHITE_SPACE (bp);
if (temp->length == 0 || (*bp != ',' && *bp != ')'))
{
cpp_error (pfile,
"badly punctuated parameter list in `#define'");
goto nope;
}
if (*bp == ',')
rest_arg:
/* There are two possible styles for a vararg macro:
the C99 way: #define foo(a, ...) a, __VA_ARGS__
the gnu way: #define foo(a, b...) a, b
The C99 way can be considered a special case of the gnu way.
There are also some constraints to worry about, but we'll handle
those elsewhere. */
if (argv[argc].len == 0)
{
bp++;
SKIP_WHITE_SPACE (bp);
if (CPP_PEDANTIC (pfile) && ! CPP_OPTIONS (pfile)->c99)
cpp_pedwarn (pfile, "C89 does not permit varargs macros");
len = sizeof "__VA_ARGS__" - 1;
namebuf = xrealloc (namebuf, argslen + len + 1);
name = &namebuf[argslen - 1];
argslen += len;
memcpy (name, "__VA_ARGS__", len);
argslen += len + 1;
argv[argc].len = len;
}
if (bp >= limit)
else
if (CPP_PEDANTIC (pfile))
cpp_pedwarn (pfile, "ISO C does not permit named varargs macros");
argv[argc].rest_arg = 1;
namebuf = xrealloc (namebuf, argslen + 3);
memcpy (&namebuf[argslen - 1], "...", 4);
argslen += 3;
token = get_directive_token (pfile);
if (token != CPP_RPAREN)
{
cpp_error (pfile, "unterminated parameter list in `#define'");
goto nope;
cpp_error (pfile, "another parameter follows `...'");
goto invalid;
}
{
struct arglist *otemp;
for (otemp = temp->next; otemp != NULL; otemp = otemp->next)
if (temp->length == otemp->length
&& strncmp (temp->name, otemp->name, temp->length) == 0)
done:
/* Go through argv and fix up the pointers. */
len = 0;
for (i = 0; i <= argc; i++)
{
U_CHAR *name;
name = (U_CHAR *) alloca (temp->length + 1);
(void) strncpy (name, temp->name, temp->length);
name[temp->length] = '\0';
cpp_error (pfile,
"duplicate argument name `%s' in `#define'",
name);
goto nope;
}
}
argv[i].name = namebuf + len;
len += argv[i].len + 1;
}
++bp; /* skip paren */
SKIP_WHITE_SPACE (bp);
/* now everything from bp before limit is the definition. */
defn = collect_expansion (pfile, bp, limit, argno, arg_ptrs);
defn->rest_args = rest_args;
CPP_SET_WRITTEN (pfile, old_written);
/* Now set defn->argnames to the result of concatenating
the argument names in reverse order
with comma-space between them. */
defn->argnames = (U_CHAR *) xmalloc (arglengths + 1);
{
struct arglist *temp;
int i = 0;
for (temp = arg_ptrs; temp; temp = temp->next)
result = (struct arglist *) xmalloc (sizeof (struct arglist));
if (namebuf[0] != '\0')
{
bcopy (temp->name, &defn->argnames[i], temp->length);
i += temp->length;
if (temp->next != 0)
{
defn->argnames[i++] = ',';
defn->argnames[i++] = ' ';
}
}
defn->argnames[i] = 0;
}
result->namebuf = namebuf;
result->argc = argc + 1;
result->argv = argv;
}
else
{
/* Simple expansion or empty definition. */
free (namebuf);
result->namebuf = 0;
result->argc = 0;
result->argv = 0;
}
if (bp < limit)
{
if (is_hspace(*bp))
return result;
invalid:
if (argv)
free (argv);
if (namebuf)
free (namebuf);
return 0;
}
/* Create a DEFINITION node for a macro. The reader's point is just
after the macro name. If FUNLIKE is true, this is a function-like
macro. */
DEFINITION *
create_definition (pfile, funlike)
cpp_reader *pfile;
int funlike;
{
struct arglist *args = 0;
long line, col;
const char *file;
DEFINITION *defn;
cpp_buf_line_and_col (CPP_BUFFER (pfile), &line, &col);
file = CPP_BUFFER (pfile)->nominal_fname;
pfile->no_macro_expand++;
pfile->parsing_define_directive++;
CPP_OPTIONS (pfile)->discard_comments++;
if (funlike)
{
bp++;
SKIP_WHITE_SPACE (bp);
}
else
/* Per C9x, missing white space after the name in a #define
of an object-like macro is always a constraint violation. */
cpp_pedwarn (pfile,
"missing white space after `#define %.*s'",
sym_length, symname);
}
/* now everything from bp before limit is the definition. */
defn = collect_expansion (pfile, bp, limit, -1, NULL_PTR);
defn->argnames = (U_CHAR *) "";
args = collect_formal_parameters (pfile);
if (args == 0)
goto err;
}
defn = collect_expansion (pfile, args);
if (defn == 0)
goto err;
defn->line = line;
defn->file = file;
defn->col = col;
mdef.defn = defn;
mdef.symnam = symname;
mdef.symlen = sym_length;
return mdef;
pfile->no_macro_expand--;
pfile->parsing_define_directive--;
CPP_OPTIONS (pfile)->discard_comments--;
return defn;
nope:
mdef.defn = 0;
return mdef;
err:
pfile->no_macro_expand--;
pfile->parsing_define_directive--;
CPP_OPTIONS (pfile)->discard_comments--;
return 0;
}
/*
......@@ -987,7 +960,7 @@ macroexpand (pfile, hp)
xbuf_len = CPP_WRITTEN (pfile) - old_written;
xbuf = (U_CHAR *) xmalloc (xbuf_len + 1);
CPP_SET_WRITTEN (pfile, old_written);
bcopy (CPP_PWRITTEN (pfile), xbuf, xbuf_len + 1);
memcpy (xbuf, CPP_PWRITTEN (pfile), xbuf_len + 1);
push_macro_expansion (pfile, xbuf, xbuf_len, hp);
CPP_BUFFER (pfile)->has_escapes = 1;
return;
......@@ -1244,8 +1217,10 @@ macroexpand (pfile, hp)
int count_before = totlen;
/* Add chars to XBUF. */
for (i = 0; i < ap->nchars; i++, offset++)
xbuf[totlen++] = exp[offset];
i = ap->nchars;
memcpy (&xbuf[totlen], &exp[offset], i);
totlen += i;
offset += i;
/* If followed by an empty rest arg with concatenation,
delete the last run of nonwhite chars. */
......@@ -1265,8 +1240,8 @@ macroexpand (pfile, hp)
if (ap->stringify != 0)
{
bcopy (ARG_BASE + arg->stringified,
xbuf + totlen, arg->stringified_length);
memcpy (xbuf + totlen, ARG_BASE + arg->stringified,
arg->stringified_length);
totlen += arg->stringified_length;
}
else if (ap->raw_before || ap->raw_after || CPP_TRADITIONAL (pfile))
......@@ -1314,7 +1289,7 @@ macroexpand (pfile, hp)
if (p1[0] == '\r' && p1[1] == '-')
p1 += 2;
bcopy (p1, xbuf + totlen, l1 - p1);
memcpy (xbuf + totlen, p1, l1 - p1);
totlen += l1 - p1;
}
else
......@@ -1328,7 +1303,7 @@ macroexpand (pfile, hp)
xbuf[totlen++] = ' ';
}
bcopy (expanded, xbuf + totlen, arg->expand_length);
memcpy (xbuf + totlen, expanded, arg->expand_length);
totlen += arg->expand_length;
if (!ap->raw_after && totlen > 0 && offset < defn->length
......@@ -1493,6 +1468,7 @@ compare_defs (pfile, d1, d2)
if (d1->nargs != d2->nargs)
return 1;
if (CPP_PEDANTIC (pfile)
&& d1->argnames && d2->argnames
&& strcmp ((char *) d1->argnames, (char *) d2->argnames))
return 1;
for (a1 = d1->pattern, a2 = d2->pattern; a1 && a2;
......
......@@ -18,15 +18,6 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef __GCC_CPPHASH__
#define __GCC_CPPHASH__
/* Structure returned by create_definition */
typedef struct macrodef MACRODEF;
struct macrodef
{
struct definition *defn;
const U_CHAR *symnam;
int symlen;
};
/* Structure allocated for every #define. For a simple replacement
such as
#define foo bar ,
......@@ -48,15 +39,8 @@ struct macrodef
{ (0, 1), (1, 1), (1, 1), ..., (1, 1), NULL }
where (x, y) means (nchars, argno). */
typedef struct definition DEFINITION;
struct definition {
int nargs;
int length; /* length of expansion string */
unsigned char *expansion;
int line; /* Line number of definition */
const char *file; /* File of definition */
char rest_args; /* Nonzero if last arg. absorbs the rest */
struct reflist {
struct reflist
{
struct reflist *next;
char stringify; /* nonzero if this arg was preceded by a
# operator. */
......@@ -66,12 +50,24 @@ struct definition {
int nchars; /* Number of literal chars to copy before
this arg occurrence. */
int argno; /* Number of arg to substitute (origin-0) */
} *pattern;
/* Names of macro args, concatenated in reverse order
with comma-space between them.
The only use of this is that we warn on redefinition
if this differs between the old and new definitions. */
unsigned char *argnames;
};
typedef struct definition DEFINITION;
struct definition
{
int nargs;
int length; /* length of expansion string */
U_CHAR *expansion;
int line; /* Line number of definition */
int col;
const char *file; /* File of definition */
char rest_args; /* Nonzero if last arg. absorbs the rest */
struct reflist *pattern;
/* Names of macro args, concatenated in order with commas between
them. The only use of this is that we warn on redefinition if
this differs between the old and new definitions. */
U_CHAR *argnames;
};
/* different kinds of things that can appear in the value field
......@@ -102,8 +98,7 @@ extern HASHNODE *cpp_lookup PARAMS ((cpp_reader *, const U_CHAR *, int));
extern void free_definition PARAMS ((DEFINITION *));
extern void delete_macro PARAMS ((HASHNODE *));
extern MACRODEF create_definition PARAMS ((U_CHAR *, U_CHAR *,
cpp_reader *));
extern DEFINITION *create_definition PARAMS ((cpp_reader *, int));
extern int compare_defs PARAMS ((cpp_reader *, DEFINITION *,
DEFINITION *));
extern void macroexpand PARAMS ((cpp_reader *, HASHNODE *));
......
......@@ -1256,9 +1256,6 @@ cpp_handle_option (pfile, argc, argv)
opts->include_prefix_len = strlen (argv[i]);
}
}
else if (!strcmp (argv[i], "-ifoutput"))
opts->output_conditionals = 1;
break;
case 'o':
......@@ -1736,7 +1733,6 @@ Switches:\n\
-dD Preserve macro definitions in output\n\
-dN As -dD except that only the names are preserved\n\
-dI Include #include directives in the output\n\
-ifoutput Describe skipped code blocks in output \n\
-P Do not generate #line directives\n\
-$ Do not allow '$' in identifiers\n\
-remap Remap file names when including files.\n\
......
......@@ -46,7 +46,8 @@ extern HOST_WIDEST_INT cpp_parse_expr PARAMS ((cpp_reader *));
/* `struct directive' defines one #-directive, including how to handle it. */
struct directive {
struct directive
{
int length; /* Length of name */
int (*func) /* Function to handle directive */
PARAMS ((cpp_reader *, const struct directive *));
......@@ -93,7 +94,7 @@ static enum cpp_token null_underflow PARAMS ((cpp_reader *));
static int null_cleanup PARAMS ((cpp_buffer *, cpp_reader *));
static int skip_comment PARAMS ((cpp_reader *, int));
static int copy_comment PARAMS ((cpp_reader *, int));
static void copy_rest_of_line PARAMS ((cpp_reader *));
static void skip_string PARAMS ((cpp_reader *, int));
static void skip_rest_of_line PARAMS ((cpp_reader *));
static void cpp_skip_hspace PARAMS ((cpp_reader *));
static int handle_directive PARAMS ((cpp_reader *));
......@@ -108,6 +109,7 @@ static void skip_block_comment PARAMS ((cpp_reader *));
static void skip_line_comment PARAMS ((cpp_reader *));
static void parse_set_mark PARAMS ((cpp_reader *));
static void parse_goto_mark PARAMS ((cpp_reader *));
static int get_macro_name PARAMS ((cpp_reader *));
/* Here is the actual list of #-directives.
This table is ordered by frequency of occurrence; the numbers
......@@ -410,10 +412,13 @@ copy_comment (pfile, m)
if (skip_comment (pfile, m) == m)
return m;
CPP_PUTC (pfile, m);
for (limit = CPP_BUFFER (pfile)->cur; start <= limit; start++)
limit = CPP_BUFFER (pfile)->cur;
CPP_RESERVE (pfile, limit - start + 2);
CPP_PUTC_Q (pfile, m);
for (; start <= limit; start++)
if (*start != '\r')
CPP_PUTC (pfile, *start);
CPP_PUTC_Q (pfile, *start);
return ' ';
}
......@@ -447,7 +452,7 @@ cpp_skip_hspace (pfile)
break;
}
else
CPP_BUFFER (pfile)->lineno++;
CPP_BUMP_LINE (pfile);
}
else if (c == '/' || c == '-')
{
......@@ -461,11 +466,10 @@ cpp_skip_hspace (pfile)
FORWARD(-1);
}
/* Read the rest of the current line.
The line is appended to PFILE's output buffer. */
/* Read and discard the rest of the current line. */
static void
copy_rest_of_line (pfile)
skip_rest_of_line (pfile)
cpp_reader *pfile;
{
for (;;)
......@@ -476,32 +480,21 @@ copy_rest_of_line (pfile)
case '\n':
FORWARD(-1);
case EOF:
CPP_NUL_TERMINATE (pfile);
return;
case '\r':
if (CPP_BUFFER (pfile)->has_escapes)
if (! CPP_BUFFER (pfile)->has_escapes)
CPP_BUMP_LINE (pfile);
break;
else
{
CPP_BUFFER (pfile)->lineno++;
continue;
}
case '\'':
case '\"':
parse_string (pfile, c);
continue;
skip_string (pfile, c);
break;
case '/':
if (PEEKC() == '*')
{
if (CPP_TRADITIONAL (pfile))
CPP_PUTS (pfile, "/**/", 4);
skip_block_comment (pfile);
continue;
}
/* else fall through */
case '-':
c = skip_comment (pfile, c);
skip_comment (pfile, c);
break;
case '\f':
......@@ -512,23 +505,9 @@ copy_rest_of_line (pfile)
break;
}
CPP_PUTC (pfile, c);
}
}
/* FIXME: It is almost definitely a performance win to make this do
the scan itself. >75% of calls to copy_r_o_l are from here or
skip_if_group, which means the common case is to copy stuff into the
token_buffer only to discard it. */
static void
skip_rest_of_line (pfile)
cpp_reader *pfile;
{
long old = CPP_WRITTEN (pfile);
copy_rest_of_line (pfile);
CPP_SET_WRITTEN (pfile, old);
}
/* Handle a possible # directive.
'#' has already been read. */
......@@ -542,6 +521,12 @@ handle_directive (pfile)
U_CHAR *ident;
long old_written = CPP_WRITTEN (pfile);
if (CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile)))
{
cpp_ice (pfile, "handle_directive called on macro buffer");
return 0;
}
cpp_skip_hspace (pfile);
c = PEEKC ();
......@@ -629,71 +614,88 @@ pass_thru_directive (buf, len, pfile, keyword)
CPP_PUTS_Q (pfile, buf, len);
}
/* Check a purported macro name SYMNAME, and yield its length. */
/* Subroutine of do_define: determine the name of the macro to be
defined. */
int
check_macro_name (pfile, symname)
static int
get_macro_name (pfile)
cpp_reader *pfile;
const U_CHAR *symname;
{
const U_CHAR *p;
int sym_length;
for (p = symname; is_idchar(*p); p++)
;
sym_length = p - symname;
if (sym_length == 0
|| (sym_length == 1 && *symname == 'L' && (*p == '\'' || *p == '"')))
cpp_error (pfile, "invalid macro name");
else if (!is_idstart(*symname)
|| (! strncmp (symname, "defined", 7) && sym_length == 7)) {
U_CHAR *msg; /* what pain... */
msg = (U_CHAR *) alloca (sym_length + 1);
bcopy (symname, msg, sym_length);
msg[sym_length] = 0;
cpp_error (pfile, "invalid macro name `%s'", msg);
}
return sym_length;
long here, len;
here = CPP_WRITTEN (pfile);
pfile->no_macro_expand++;
if (get_directive_token (pfile) != CPP_NAME)
{
cpp_error (pfile, "`#define' must be followed by an identifier");
goto invalid;
}
len = CPP_WRITTEN (pfile) - here;
if (len == 7 && !strncmp (pfile->token_buffer + here, "defined", 7))
{
cpp_error (pfile, "`defined' is not a legal macro name");
goto invalid;
}
pfile->no_macro_expand--;
return len;
invalid:
skip_rest_of_line (pfile);
pfile->no_macro_expand--;
return 0;
}
/* Process a #define command.
KEYWORD is the keyword-table entry for #define,
or NULL for a "predefined" macro,
or the keyword-table entry for #pragma in the case of a #pragma poison. */
or NULL for a "predefined" macro. */
static int
do_define (pfile, keyword)
cpp_reader *pfile;
const struct directive *keyword;
{
MACRODEF mdef;
HASHNODE *hp;
DEFINITION *def;
long here;
U_CHAR *macro, *buf, *end;
int len, c;
int funlike = 0;
U_CHAR *sym;
here = CPP_WRITTEN (pfile);
copy_rest_of_line (pfile);
/* Copy out the line so we can pop the token buffer. */
buf = pfile->token_buffer + here;
end = CPP_PWRITTEN (pfile);
macro = (U_CHAR *) alloca (end - buf + 1);
memcpy (macro, buf, end - buf + 1);
end = macro + (end - buf);
len = get_macro_name (pfile);
if (len == 0)
return 0;
/* Copy out the name so we can pop the token buffer. */
len = CPP_WRITTEN (pfile) - here;
sym = (U_CHAR *) alloca (len + 1);
memcpy (sym, pfile->token_buffer + here, len);
sym[len] = '\0';
CPP_SET_WRITTEN (pfile, here);
mdef = create_definition (macro, end, pfile);
if (mdef.defn == 0)
/* If the next character, with no intervening whitespace, is '(',
then this is a function-like macro. */
c = PEEKC ();
if (c == '(')
funlike = 1;
else if (c != '\n' && !is_hspace (c))
/* Otherwise, C99 requires white space after the name. We treat it
as an object-like macro if this happens, with a warning. */
cpp_pedwarn (pfile, "missing white space after `#define %.*s'", len, sym);
def = create_definition (pfile, funlike);
if (def == 0)
return 0;
if ((hp = cpp_lookup (pfile, mdef.symnam, mdef.symlen)) != NULL)
if ((hp = cpp_lookup (pfile, sym, len)) != NULL)
{
int ok;
/* Redefining a macro is ok if the definitions are the same. */
if (hp->type == T_MACRO)
ok = ! compare_defs (pfile, mdef.defn, hp->value.defn);
ok = ! compare_defs (pfile, def, hp->value.defn);
/* Redefining a constant is ok with -D. */
else if (hp->type == T_CONST || hp->type == T_STDC)
ok = ! CPP_OPTIONS (pfile)->done_initializing;
......@@ -704,34 +706,35 @@ do_define (pfile, keyword)
if (! ok)
{
if (hp->type == T_POISON)
cpp_error (pfile, "redefining poisoned `%.*s'",
mdef.symlen, mdef.symnam);
cpp_error (pfile, "redefining poisoned `%.*s'", len, sym);
else
cpp_pedwarn (pfile, "`%.*s' redefined", mdef.symlen, mdef.symnam);
cpp_pedwarn (pfile, "`%.*s' redefined", len, sym);
if (hp->type == T_MACRO && CPP_OPTIONS (pfile)->done_initializing)
cpp_pedwarn_with_file_and_line (pfile, hp->value.defn->file,
hp->value.defn->line, -1,
{
DEFINITION *d = hp->value.defn;
cpp_pedwarn_with_file_and_line (pfile, d->file, d->line, d->col,
"this is the location of the previous definition");
}
}
if (hp->type != T_POISON)
{
/* Replace the old definition. */
if (hp->type == T_MACRO)
free_definition (hp->value.defn);
hp->type = T_MACRO;
hp->value.defn = mdef.defn;
hp->value.defn = def;
}
}
else
cpp_install (pfile, mdef.symnam, mdef.symlen, T_MACRO, (char *)mdef.defn);
cpp_install (pfile, sym, len, T_MACRO, (char *) def);
if (keyword != NULL && keyword->type == T_DEFINE)
{
if (CPP_OPTIONS (pfile)->debug_output
|| CPP_OPTIONS (pfile)->dump_macros == dump_definitions)
dump_definition (pfile, mdef.symnam, mdef.symlen, mdef.defn);
dump_definition (pfile, sym, len, def);
else if (CPP_OPTIONS (pfile)->dump_macros == dump_names)
pass_thru_directive (mdef.symnam, mdef.symlen, pfile, keyword);
pass_thru_directive (sym, len, pfile, keyword);
}
return 0;
......@@ -766,6 +769,7 @@ cpp_push_buffer (pfile, buffer, length)
new->alimit = new->rlimit = buffer + length;
new->prev = buf;
new->mark = -1;
new->line_base = NULL;
CPP_BUFFER (pfile) = new;
return new;
......@@ -1309,7 +1313,7 @@ read_line_number (pfile, num)
}
else
{
if (token != CPP_VSPACE && token != CPP_EOF && token != CPP_POP)
if (token != CPP_VSPACE && token != CPP_EOF)
cpp_error (pfile, "invalid format `#line' command");
return 0;
}
......@@ -1467,15 +1471,14 @@ do_undef (pfile, keyword)
len = limit - buf;
name = (U_CHAR *) alloca (len + 1);
memcpy (name, buf, len);
name[limit - buf] = '\0';
name[len] = '\0';
token = get_directive_token (pfile);
if (token != CPP_VSPACE && token != CPP_POP)
if (token != CPP_VSPACE)
{
cpp_pedwarn (pfile, "junk on line after #undef");
skip_rest_of_line (pfile);
}
CPP_SET_WRITTEN (pfile, here);
while ((hp = cpp_lookup (pfile, name, len)) != NULL)
......@@ -1950,11 +1953,9 @@ eval_if_expression (pfile)
HOST_WIDEST_INT value;
long old_written = CPP_WRITTEN (pfile);
/* Work around bug in cpp_get_token where it may mistake an
assertion for a directive. */
pfile->only_seen_white = 0;
pfile->parsing_if_directive++;
value = cpp_parse_expr (pfile);
pfile->parsing_if_directive--;
skip_rest_of_line (pfile);
CPP_SET_WRITTEN (pfile, old_written); /* Pop */
......@@ -2148,13 +2149,6 @@ skip_if_group (pfile)
U_CHAR *beg_of_line;
long old_written;
if (CPP_OPTIONS (pfile)->output_conditionals)
{
CPP_PUTS (pfile, "#failed\n", 8);
pfile->lineno++;
output_line_command (pfile, same_file);
}
old_written = CPP_WRITTEN (pfile);
for (;;)
......@@ -2166,8 +2160,6 @@ skip_if_group (pfile)
c = GETC();
if (c == '\n')
{
if (CPP_OPTIONS (pfile)->output_conditionals)
CPP_PUTC (pfile, c);
CPP_BUMP_LINE (pfile);
continue;
}
......@@ -2180,41 +2172,19 @@ skip_if_group (pfile)
return; /* Caller will issue error. */
FORWARD(-1);
if (CPP_OPTIONS (pfile)->output_conditionals)
{
CPP_PUTS (pfile, beg_of_line, CPP_BUFFER (pfile)->cur - beg_of_line);
copy_rest_of_line (pfile);
}
else
{
copy_rest_of_line (pfile);
CPP_SET_WRITTEN (pfile, old_written); /* discard it */
}
skip_rest_of_line (pfile);
c = GETC();
if (c == EOF)
return; /* Caller will issue error. */
else
{
/* \n */
if (CPP_OPTIONS (pfile)->output_conditionals)
{
CPP_PUTC (pfile, c);
pfile->lineno++;
}
CPP_BUMP_LINE (pfile);
}
}
/* Back up to the beginning of this line. Caller will process the
directive. */
CPP_BUFFER (pfile)->cur = beg_of_line;
pfile->only_seen_white = 1;
if (CPP_OPTIONS (pfile)->output_conditionals)
{
CPP_PUTS (pfile, "#endfailed\n", 11);
pfile->lineno++;
}
}
/*
......@@ -2443,6 +2413,27 @@ cpp_get_token (pfile)
}
case '#':
if (pfile->parsing_if_directive)
{
cpp_skip_hspace (pfile);
parse_assertion (pfile);
return CPP_ASSERTION;
}
if (pfile->parsing_define_directive && ! CPP_TRADITIONAL (pfile))
{
CPP_RESERVE (pfile, 3);
CPP_PUTC_Q (pfile, '#');
CPP_NUL_TERMINATE_Q (pfile);
if (PEEKC () != '#')
return CPP_STRINGIZE;
FORWARD (1);
CPP_PUTC_Q (pfile, '#');
CPP_NUL_TERMINATE_Q (pfile);
return CPP_TOKPASTE;
}
if (!pfile->only_seen_white)
goto randomchar;
/* -traditional directives are recognized only with the # in
......@@ -2886,35 +2877,24 @@ parse_name (pfile, c)
return;
}
/* Parse a string starting with C. A single quoted string is treated
like a double -- some programs (e.g., troff) are perverse this way.
(However, a single quoted string is not allowed to extend over
multiple lines.) */
/* Parse and skip over a string starting with C. A single quoted
string is treated like a double -- some programs (e.g., troff) are
perverse this way. (However, a single quoted string is not allowed
to extend over multiple lines.) */
static void
parse_string (pfile, c)
skip_string (pfile, c)
cpp_reader *pfile;
int c;
{
long start_line, start_column;
cpp_buf_line_and_col (cpp_file_buffer (pfile), &start_line, &start_column);
CPP_PUTC (pfile, c);
while (1)
{
int cc = GETC();
if (cc == EOF)
{
if (CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile)))
switch (cc)
{
/* try harder: this string crosses a macro expansion
boundary. This can happen naturally if -traditional.
Otherwise, only -D can make a macro with an unmatched
quote. */
cpp_pop_buffer (pfile);
continue;
}
case EOF:
cpp_error_with_line (pfile, start_line, start_column,
"unterminated string or character constant");
if (pfile->multiline_string_line != start_line
......@@ -2923,22 +2903,20 @@ parse_string (pfile, c)
pfile->multiline_string_line, -1,
"possible real start of unterminated constant");
pfile->multiline_string_line = 0;
break;
}
CPP_PUTC (pfile, cc);
switch (cc)
{
return;
case '\n':
CPP_BUMP_LINE (pfile);
pfile->lineno++;
/* In Fortran and assembly language, silently terminate
strings of either variety at end of line. This is a
kludge around not knowing where comments are in these
languages. */
if (CPP_OPTIONS (pfile)->lang_fortran
|| CPP_OPTIONS (pfile)->lang_asm)
{
FORWARD(-1);
return;
}
/* Character constants may not extend over multiple lines.
In Standard C, neither may strings. We accept multiline
strings as an extension. */
......@@ -2946,6 +2924,7 @@ parse_string (pfile, c)
{
cpp_error_with_line (pfile, start_line, start_column,
"unterminated character constant");
FORWARD(-1);
return;
}
if (CPP_PEDANTIC (pfile) && pfile->multiline_string_line == 0)
......@@ -2956,7 +2935,6 @@ parse_string (pfile, c)
break;
case '\r':
CPP_ADJUST_WRITTEN (pfile, -1);
if (CPP_BUFFER (pfile)->has_escapes)
{
cpp_ice (pfile, "\\r escape inside string constant");
......@@ -2968,9 +2946,7 @@ parse_string (pfile, c)
break;
case '\\':
cc = GETC();
if (cc != EOF)
CPP_PUTC (pfile, cc);
FORWARD(1);
break;
case '\"':
......@@ -2982,6 +2958,26 @@ parse_string (pfile, c)
}
}
/* Parse a string and copy it to the output. */
static void
parse_string (pfile, c)
cpp_reader *pfile;
int c;
{
U_CHAR *start = CPP_BUFFER (pfile)->cur; /* XXX Layering violation */
U_CHAR *limit;
skip_string (pfile, c);
limit = CPP_BUFFER (pfile)->cur;
CPP_RESERVE (pfile, limit - start + 2);
CPP_PUTC_Q (pfile, c);
for (; start < limit; start++)
if (*start != '\r')
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.
......@@ -3199,33 +3195,11 @@ cpp_unassert (pfile, str)
{
if (cpp_push_buffer (pfile, str, strlen (str)) != NULL)
{
do_assert (pfile, NULL);
do_unassert (pfile, NULL);
cpp_pop_buffer (pfile);
}
}
int
cpp_read_check_assertion (pfile)
cpp_reader *pfile;
{
U_CHAR *name;
int result;
long written = CPP_WRITTEN (pfile);
FORWARD (1); /* Skip '#' */
cpp_skip_hspace (pfile);
if (! parse_assertion (pfile))
result = 0;
else
{
name = pfile->token_buffer + written;
result = cpp_defined (pfile, name, CPP_PWRITTEN (pfile) - name);
}
CPP_SET_WRITTEN (pfile, written);
return result;
}
/* Remember the current position of PFILE so it may be returned to
after looking ahead a bit.
......
......@@ -47,12 +47,15 @@ enum cpp_token {
CPP_STRING,
CPP_WSTRING,
CPP_DIRECTIVE,
CPP_ASSERTION, /* #machine(a29k) */
CPP_STRINGIZE, /* stringize macro argument */
CPP_TOKPASTE, /* paste macro arg with next/prev token */
CPP_LPAREN, /* "(" */
CPP_RPAREN, /* ")" */
CPP_LBRACE, /* "{" */
CPP_RBRACE, /* "}" */
CPP_COMMA, /* "," */
CPP_SEMICOLON,/* ";" */
CPP_SEMICOLON, /* ";" */
CPP_3DOTS, /* "..." */
CPP_POP /* We're about to pop the buffer stack. */
};
......@@ -193,7 +196,6 @@ struct cpp_reader
/* If non-zero, directives cause a hard error. Used when parsing
macro arguments. */
char no_directives;
/* Print column number in error messages. */
......@@ -205,6 +207,12 @@ struct cpp_reader
/* If true, character between '<' and '>' are a single (string) token. */
char parsing_include_directive;
/* If true, # introduces an assertion (see do_assert) */
char parsing_if_directive;
/* If true, # and ## are the STRINGIZE and TOKPASTE operators */
char parsing_define_directive;
/* True if escape sequences (as described for has_escapes in
parse_buffer) should be emitted. */
char output_escapes;
......@@ -217,7 +225,7 @@ struct cpp_reader
/* Nonzero means this file was included with a -imacros or -include
command line and should not be recorded as an include file. */
int no_record_file;
char no_record_file;
long lineno;
......@@ -427,11 +435,6 @@ struct cpp_options {
char no_line_commands;
/* Nonzero means output the text in failing conditionals,
inside #failed ... #endfailed. */
char output_conditionals;
/* Nonzero means -I- has been seen,
so don't look for #include "foo" the source-file directory. */
char ignore_srcdir;
......@@ -689,14 +692,12 @@ extern int cpp_defined PARAMS ((cpp_reader *, const U_CHAR *, int));
extern void cpp_reader_init PARAMS ((cpp_reader *));
extern void cpp_options_init PARAMS ((cpp_options *));
extern int cpp_start_read PARAMS ((cpp_reader *, char *));
extern int cpp_read_check_assertion PARAMS ((cpp_reader *));
extern void cpp_finish PARAMS ((cpp_reader *));
extern void quote_string PARAMS ((cpp_reader *, const char *));
extern void cpp_expand_to_buffer PARAMS ((cpp_reader *, const U_CHAR *,
int));
extern void cpp_scan_buffer PARAMS ((cpp_reader *));
extern int check_macro_name PARAMS ((cpp_reader *, const U_CHAR *));
/* Last arg to output_line_command. */
enum file_change_code {same_file, rename_file, enter_file, leave_file};
......
/* { dg-do compile } */
/* Distilled from glibc sources. Tests preprocessor corner cases. */
/* { dg-options "-Wall" } */
/* Distilled from glibc sources. Tests preprocessor corner cases.
Since it uses rest args, we must turn off -pedantic-errors. */
#define NO_PAREN(rest...) rest
#define DEFINE_CATEGORY(category, items) \
......
/* { dg-do run } */
/* Test for odd corner cases in stringizing/pasting.
Taken more or less verbatim from C99 section 6.10.3.3. */
#include <stdlib.h>
#include <string.h>
#define hash_hash # ## #
#define mkstr(a) # a
#define in_between(a) mkstr(a)
#define join(c, d) in_between(c hash_hash d)
const char p[] = join(x, y);
const char q[] = "x ## y";
int
main (void)
{
if (strcmp (p, q))
abort ();
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment