cpphash.c (struct arg, [...]): Const-ify strings.

* cpphash.c (struct arg, struct arglist): Const-ify strings.
	(warn_trad_stringify, duplicate_arg_p): New helper functions.
	(collect_expansion): Rewrite to scan over a token list.
	Remove -traditional support.
	(collect_formal_parameters): Rename to collect_params; rewrite
	to scan over a token list.
	(_cpp_create_definition): Adjust to scan a token list.
	(_cpp_macroexpand): Remove -traditional support.
	(_cpp_compare_defs): Whitespace is now canonicalized.
	(comp_def_part): Delete function.

	* cpphash.h: Update prototypes.
	* cpplex.c (init_token_list): Don't set lineno if there is no
	buffer.
	(pedantic_whitespace): New function.
	(_cpp_scan_line): Mark tokens that had hspace before.  Don't
	consume a newline.  Use pedantic_whitespace.
	(_cpp_lex_token): Remove support for -traditional macros.
	(_cpp_get_define_token): Delete.
	(_cpp_get_directive_token): Do the real work here.  Use
	pedantic_whitespace.
	(_cpp_init_input_buffer): Initialize pfile->directbuf.

	* cpplib.c (get_macro_name): Delete.
	(do_define): Read the entire line into pfile->directbuf, then
	feed the token list to _cpp_create_definition.
	* cpplib.h (HSPACE_BEFORE): new define.
	(struct cpp_reader): Add a toklist member, "directbuf".

From-SVN: r33309
This commit is contained in:
Zack Weinberg 2000-04-21 17:18:50 +00:00 committed by Zack Weinberg
parent 152897b152
commit 9e62c8114f
6 changed files with 413 additions and 529 deletions

View file

@ -1,5 +1,34 @@
2000-04-21 Zack Weinberg <zack@wolery.cumb.org>
* cpphash.c (struct arg, struct arglist): Const-ify strings.
(warn_trad_stringify, duplicate_arg_p): New helper functions.
(collect_expansion): Rewrite to scan over a token list.
Remove -traditional support.
(collect_formal_parameters): Rename to collect_params; rewrite
to scan over a token list.
(_cpp_create_definition): Adjust to scan a token list.
(_cpp_macroexpand): Remove -traditional support.
(_cpp_compare_defs): Whitespace is now canonicalized.
(comp_def_part): Delete function.
* cpphash.h: Update prototypes.
* cpplex.c (init_token_list): Don't set lineno if there is no
buffer.
(pedantic_whitespace): New function.
(_cpp_scan_line): Mark tokens that had hspace before. Don't
consume a newline. Use pedantic_whitespace.
(_cpp_lex_token): Remove support for -traditional macros.
(_cpp_get_define_token): Delete.
(_cpp_get_directive_token): Do the real work here. Use
pedantic_whitespace.
(_cpp_init_input_buffer): Initialize pfile->directbuf.
* cpplib.c (get_macro_name): Delete.
(do_define): Read the entire line into pfile->directbuf, then
feed the token list to _cpp_create_definition.
* cpplib.h (HSPACE_BEFORE): new define.
(struct cpp_reader): Add a toklist member, "directbuf".
* predict.c (estimate_probability): New heuristic: if a jump
branches around a block with no successors, predict it taken.
Disentangle control flow.

View file

@ -36,8 +36,6 @@ static int eq_HASHNODE PARAMS ((const void *, const void *));
static void del_HASHNODE PARAMS ((void *));
static int dump_hash_helper PARAMS ((void **, void *));
static int comp_def_part PARAMS ((int, U_CHAR *, int, U_CHAR *,
int, int));
static void push_macro_expansion PARAMS ((cpp_reader *,
U_CHAR *, int, HASHNODE *));
static int unsafe_chars PARAMS ((cpp_reader *, int, int));
@ -61,21 +59,27 @@ static void special_symbol PARAMS ((HASHNODE *, cpp_reader *));
struct arg
{
U_CHAR *name;
int len;
const U_CHAR *name;
unsigned int len;
char rest_arg;
};
struct arglist
{
U_CHAR *namebuf;
struct arg *argv;
const struct arg *argv;
int argc;
};
static DEFINITION *collect_expansion PARAMS ((cpp_reader *, struct arglist *));
static struct arglist *collect_formal_parameters PARAMS ((cpp_reader *));
static DEFINITION *collect_expansion PARAMS ((cpp_reader *, cpp_toklist *,
struct arglist *, unsigned int));
static unsigned int collect_params PARAMS ((cpp_reader *, cpp_toklist *,
struct arglist *));
static void warn_trad_stringify PARAMS ((cpp_reader *, U_CHAR *, size_t,
unsigned int, const struct arg *));
static int duplicate_arg_p PARAMS ((U_CHAR *, U_CHAR *));
/* This structure represents one parsed argument in a macro call.
`raw' points to the argument text as written (`raw_length' is its length).
@ -275,28 +279,64 @@ macro_cleanup (pbuf, pfile)
return 0;
}
/* 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.
/* Issue warnings for macro argument names seen inside strings. */
static void
warn_trad_stringify (pfile, p, len, argc, argv)
cpp_reader *pfile;
U_CHAR *p;
size_t len;
unsigned int argc;
const struct arg *argv;
{
U_CHAR *limit;
unsigned int i;
A good half of this is devoted to supporting -traditional.
Kill me now. */
limit = p + len;
for (;;)
{
while (p < limit && !is_idstart (*p)) p++;
if (p >= limit)
break;
for (i = 0; i < argc; i++)
if (!strncmp (p, argv[i].name, argv[i].len)
&& ! is_idchar (p[argv[i].len]))
{
cpp_warning (pfile,
"macro argument \"%s\" would be stringified in traditional C",
argv[i].name);
break;
}
p++;
while (p < limit && is_idchar (*p)) p++;
if (p >= limit)
break;
}
}
/* Read a replacement list for a macro, and build the DEFINITION
structure. LIST contains the replacement list, beginning at
REPLACEMENT. 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. */
static DEFINITION *
collect_expansion (pfile, arglist)
collect_expansion (pfile, list, arglist, replacement)
cpp_reader *pfile;
cpp_toklist *list;
struct arglist *arglist;
unsigned int replacement;
{
DEFINITION *defn;
struct reflist *pat = 0, *endpat = 0;
enum cpp_ttype token;
long start, here, last;
int i;
int argc;
long start, last;
unsigned int i;
int j, argc;
size_t len;
struct arg *argv;
const struct arg *argv;
U_CHAR *tok, *exp;
enum { START = 0, NORM, ARG, STRIZE, PASTE } last_token = START;
@ -311,15 +351,16 @@ collect_expansion (pfile, arglist)
argc = 0;
}
/* We copy the expansion text into the token_buffer, then out to
its proper home. */
last = start = CPP_WRITTEN (pfile);
last -= 2; /* two extra chars for the leading escape */
for (;;)
CPP_PUTS (pfile, "\r ", 2);
for (i = replacement; i < list->tokens_used; i++)
{
/* Macro expansion is off, so we are guaranteed not to see POP
or EOF. */
here = CPP_WRITTEN (pfile);
token = _cpp_get_define_token (pfile);
tok = pfile->token_buffer + here;
token = list->tokens[i].type;
tok = list->tokens[i].val.name.offset + list->namebuf;
len = list->tokens[i].val.name.len;
switch (token)
{
case CPP_POP:
@ -329,90 +370,54 @@ collect_expansion (pfile, arglist)
case CPP_VSPACE:
goto done;
case CPP_HSPACE:
if (last_token == STRIZE || last_token == PASTE
|| last_token == START)
CPP_SET_WRITTEN (pfile, here);
break;
case CPP_HASH:
/* # is not special in object-like macros. It is special in
function-like macros with no args. (6.10.3.2 para 1.) */
if (arglist == NULL)
goto norm;
/* # is not special immediately after PASTE.
(Implied by 6.10.3.3 para 4.) */
if (last_token == PASTE)
function-like macros with no args. (6.10.3.2 para 1.)
However, it is not special after PASTE. (Implied by
6.10.3.3 para 4.) */
if (arglist == NULL || last_token == PASTE)
goto norm;
last_token = STRIZE;
CPP_SET_WRITTEN (pfile, here); /* delete from replacement text */
break;
case CPP_PASTE:
/* 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)
{
endpat->raw_after = 1;
last_token = PASTE;
CPP_SET_WRITTEN (pfile, last);
break;
}
else if (last_token == PASTE)
if (last_token == PASTE)
/* ## ## - the second ## is ordinary. */
goto norm;
else if (last_token == START)
cpp_error (pfile, "`##' at start of macro definition");
/* 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)
else if (last_token == ARG)
/* If the last token was an argument, mark it raw_after. */
endpat->raw_after = 1;
else if (last_token == STRIZE)
/* Oops - that wasn't a stringify operator. */
CPP_PUTC (pfile, '#');
last_token = PASTE;
break;
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 and it's in the middle of the line.
_cpp_lex_token won't return a COMMENT if there was trailing
space. */
CPP_SET_WRITTEN (pfile, here);
if (last_token == START)
break;
if (is_hspace (pfile->token_buffer[here-1]))
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_WTRADITIONAL (pfile))
goto maybe_trad_stringify;
else
goto norm;
if (argc && CPP_WTRADITIONAL (pfile))
warn_trad_stringify (pfile, tok, len, argc, argv);
goto norm;
case CPP_NAME:
for (i = 0; i < argc; i++)
if (!strncmp (tok, argv[i].name, argv[i].len)
&& tok + argv[i].len == CPP_PWRITTEN (pfile))
for (j = 0; j < argc; j++)
if (argv[j].len == len
&& !strncmp (tok, argv[j].name, argv[j].len))
goto addref;
/* fall through */
default:
norm:
if (last_token == STRIZE)
cpp_error (pfile, "`#' is not followed by a macro argument name");
cpp_error (pfile, "# is not followed by a macro argument name");
if (last_token != PASTE && last_token != START
&& (list->tokens[i].flags & HSPACE_BEFORE))
CPP_PUTC (pfile, ' ');
CPP_PUTS (pfile, tok, len);
last_token = NORM;
break;
}
@ -421,85 +426,27 @@ collect_expansion (pfile, arglist)
addref:
{
struct reflist *tpat;
if (last_token != PASTE && (list->tokens[i].flags & HSPACE_BEFORE))
CPP_PUTC (pfile, ' ');
/* 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;
tpat->rest_args = argv[j].rest_arg;
tpat->argno = j;
tpat->nchars = CPP_WRITTEN (pfile) - last;
if (endpat == NULL)
pat = tpat;
else
endpat->next = tpat;
endpat = tpat;
last = here;
last = CPP_WRITTEN (pfile);
}
CPP_SET_WRITTEN (pfile, here); /* discard arg name */
last_token = ARG;
continue;
maybe_trad_stringify:
last_token = NORM;
{
U_CHAR *base, *p, *limit;
struct reflist *tpat;
base = p = pfile->token_buffer + here;
limit = CPP_PWRITTEN (pfile);
while (++p < limit)
{
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 argument `%.*s' would be stringified with -traditional",
(int) argv[i].len, argv[i].name);
continue;
}
if (CPP_WTRADITIONAL (pfile))
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;
/* Don't attempt to paste this with anything. */
tpat->raw_before = 0;
tpat->raw_after = 0;
tpat->stringify = 1;
tpat->rest_args = argv[i].rest_arg;
tpat->argno = i;
tpat->nchars = (p - base) + here - last;
if (endpat == NULL)
pat = tpat;
else
endpat->next = tpat;
endpat = tpat;
last = (p - base) + here;
}
CPP_ADJUST_WRITTEN (pfile, CPP_PWRITTEN (pfile) - limit);
}
}
done:
@ -508,241 +455,224 @@ collect_expansion (pfile, arglist)
else if (last_token == PASTE)
cpp_error (pfile, "`##' at end of macro definition");
if (last_token == START)
{
/* Empty macro definition. */
exp = (U_CHAR *) xstrdup ("\r \r ");
len = 1;
}
else
{
/* Trim trailing white space from definition. */
here = CPP_WRITTEN (pfile);
while (here > last && is_hspace (pfile->token_buffer [here-1]))
here--;
CPP_SET_WRITTEN (pfile, here);
len = CPP_WRITTEN (pfile) - start + 1;
/* space for no-concat markers at either end */
exp = (U_CHAR *) xmalloc (len + 4);
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_PUTS (pfile, "\r ", 2);
len = CPP_WRITTEN (pfile) - start;
CPP_SET_WRITTEN (pfile, start);
exp = (U_CHAR *) xmalloc (len + 1);
memcpy (exp, pfile->token_buffer + start, len);
exp[len] = '\0';
defn = (DEFINITION *) xmalloc (sizeof (DEFINITION));
defn->length = len + 3;
defn->length = len;
defn->expansion = exp;
defn->pattern = pat;
defn->rest_args = 0;
defn->rest_args = argv && argv[argc - 1].rest_arg;
if (arglist)
{
defn->nargs = argc;
defn->argnames = arglist->namebuf;
if (argv)
{
defn->rest_args = argv[argc - 1].rest_arg;
free (argv);
}
free (arglist);
free ((PTR) argv);
}
else
{
defn->nargs = -1;
defn->argnames = 0;
defn->rest_args = 0;
}
return defn;
}
static struct arglist *
collect_formal_parameters (pfile)
cpp_reader *pfile;
/* Is argument NEW, which has just been added to the argument list,
a duplicate of a previous argument name? */
static int
duplicate_arg_p (args, new)
U_CHAR *args, *new;
{
struct arglist *result = 0;
struct arg *argv = 0;
U_CHAR *namebuf = (U_CHAR *) xstrdup ("");
size_t newlen = strlen (new) + 1;
size_t oldlen;
U_CHAR *name, *tok;
size_t argslen = 1;
int len;
int argc = 0;
int i;
enum cpp_ttype token;
long old_written;
old_written = CPP_WRITTEN (pfile);
token = _cpp_get_directive_token (pfile);
if (token != CPP_OPEN_PAREN)
while (args < new)
{
cpp_ice (pfile, "first token = %d not %d in collect_formal_parameters",
token, CPP_OPEN_PAREN);
goto invalid;
oldlen = strlen (args) + 1;
if (!memcmp (args, new, MIN (oldlen, newlen)))
return 1;
args += oldlen;
}
argv = (struct arg *) xmalloc (sizeof (struct arg));
argv[argc].len = 0;
argv[argc].rest_arg = 0;
for (;;)
{
CPP_SET_WRITTEN (pfile, old_written);
token = _cpp_get_directive_token (pfile);
switch (token)
{
case CPP_NAME:
tok = pfile->token_buffer + old_written;
len = CPP_PWRITTEN (pfile) - tok;
if (namebuf
&& (name = (U_CHAR *) strstr (namebuf, tok))
&& name[len] == ','
&& (name == namebuf || name[-1] == ','))
{
cpp_error (pfile, "duplicate macro argument name `%s'", tok);
continue;
}
if (CPP_PEDANTIC (pfile) && CPP_OPTION (pfile, c99)
&& len == sizeof "__VA_ARGS__" - 1
&& !strncmp (tok, "__VA_ARGS__", len))
cpp_pedwarn (pfile,
"C99 does not permit use of `__VA_ARGS__' as a macro argument name");
namebuf = (U_CHAR *) xrealloc (namebuf, argslen + len + 1);
name = &namebuf[argslen - 1];
argslen += len + 1;
memcpy (name, tok, len);
name[len] = ',';
name[len+1] = '\0';
argv[argc].len = len;
argv[argc].rest_arg = 0;
break;
case CPP_COMMA:
argc++;
argv = (struct arg *) xrealloc (argv, (argc + 1)*sizeof(struct arg));
argv[argc].len = 0;
break;
case CPP_CLOSE_PAREN:
goto done;
case CPP_ELLIPSIS:
goto rest_arg;
case CPP_VSPACE:
cpp_error (pfile, "missing right paren in macro argument list");
goto invalid;
default:
cpp_error (pfile, "syntax error in #define");
goto invalid;
}
}
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)
{
if (CPP_PEDANTIC (pfile) && ! CPP_OPTION (pfile, c99))
cpp_pedwarn (pfile, "C89 does not permit varargs macros");
len = sizeof "__VA_ARGS__" - 1;
namebuf = (U_CHAR *) xrealloc (namebuf, argslen + len + 1);
name = &namebuf[argslen - 1];
argslen += len;
memcpy (name, "__VA_ARGS__", len);
argv[argc].len = len;
}
else
if (CPP_PEDANTIC (pfile))
cpp_pedwarn (pfile, "ISO C does not permit named varargs macros");
argv[argc].rest_arg = 1;
token = _cpp_get_directive_token (pfile);
if (token != CPP_CLOSE_PAREN)
{
cpp_error (pfile, "another parameter follows `...'");
goto invalid;
}
done:
/* Go through argv and fix up the pointers. */
len = 0;
for (i = 0; i <= argc; i++)
{
argv[i].name = namebuf + len;
len += argv[i].len + 1;
namebuf[len - 1] = '\0';
}
CPP_SET_WRITTEN (pfile, old_written);
result = (struct arglist *) xmalloc (sizeof (struct arglist));
if (namebuf[0] != '\0')
{
result->namebuf = namebuf;
result->argc = argc + 1;
result->argv = argv;
}
else
{
free (namebuf);
result->namebuf = 0;
result->argc = 0;
result->argv = 0;
}
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. */
static unsigned int
collect_params (pfile, list, arglist)
cpp_reader *pfile;
cpp_toklist *list;
struct arglist *arglist;
{
struct arg *argv = 0;
U_CHAR *namebuf, *p, *tok;
unsigned int len, argslen;
unsigned int argc, a, i, j;
/* The formal parameters list starts at token 1. */
if (list->tokens[1].type != CPP_OPEN_PAREN)
{
cpp_ice (pfile, "first token = %d not %d in collect_formal_parameters",
list->tokens[1].type, CPP_OPEN_PAREN);
return 0;
}
/* Scan once and count the number of parameters; also check for
syntax errors here. */
argc = 0;
argslen = 0;
for (i = 2; i < list->tokens_used; i++)
switch (list->tokens[i].type)
{
case CPP_NAME:
argslen += list->tokens[i].val.name.len + 1;
argc++;
break;
case CPP_COMMA:
break;
case CPP_CLOSE_PAREN:
goto scanned;
case CPP_VSPACE:
cpp_error_with_line (pfile, list->line, list->tokens[i].col,
"missing right paren in macro argument list");
return 0;
default:
cpp_error_with_line (pfile, list->line, list->tokens[i].col,
"syntax error in #define");
return 0;
case CPP_ELLIPSIS:
if (list->tokens[i-1].type != CPP_NAME)
{
argslen += sizeof "__VA_ARGS__";
argc++;
}
i++;
if (list->tokens[i].type != CPP_CLOSE_PAREN)
{
cpp_error_with_line (pfile, list->line, list->tokens[i].col,
"another parameter follows \"...\"");
return 0;
}
goto scanned;
}
cpp_ice (pfile, "collect_params: unreachable - i=%d, ntokens=%d, type=%d",
i, list->tokens_used, list->tokens[i-1].type);
return 0;
scanned:
if (argc == 0) /* function-like macro, no arguments */
{
arglist->argc = 0;
arglist->argv = 0;
arglist->namebuf = 0;
return i + 1;
}
if (argslen == 0)
{
cpp_ice (pfile, "collect_params: argc=%d argslen=0", argc);
return 0;
}
/* Now allocate space and copy the suckers. */
argv = (struct arg *) xmalloc (argc * sizeof (struct arg));
namebuf = (U_CHAR *) xmalloc (argslen);
p = namebuf;
a = 0;
for (j = 2; j < i; j++)
switch (list->tokens[j].type)
{
case CPP_NAME:
tok = list->tokens[j].val.name.offset + list->namebuf;
len = list->tokens[j].val.name.len;
memcpy (p, tok, len);
p[len] = '\0';
if (duplicate_arg_p (namebuf, p))
{
cpp_error (pfile, "duplicate macro argument name \"%s\"", tok);
a++;
break;
}
if (CPP_PEDANTIC (pfile) && CPP_OPTION (pfile, c99)
&& len == sizeof "__VA_ARGS__" - 1
&& !strcmp (p, "__VA_ARGS__"))
cpp_pedwarn (pfile,
"C99 does not permit use of __VA_ARGS__ as a macro argument name");
argv[a].len = len;
argv[a].name = p;
argv[a].rest_arg = 0;
p += len;
a++;
break;
case CPP_COMMA:
break;
case CPP_ELLIPSIS:
if (list->tokens[j-1].type != CPP_NAME)
{
if (CPP_PEDANTIC (pfile) && ! CPP_OPTION (pfile, c99))
cpp_pedwarn (pfile, "C89 does not permit varargs macros");
argv[a].len = sizeof "__VA_ARGS__" - 1;
argv[a].name = p;
argv[a].rest_arg = 1;
strcpy (p, "__VA_ARGS__");
}
else
{
if (CPP_PEDANTIC (pfile))
cpp_pedwarn (pfile,
"ISO C does not permit named varargs macros");
argv[a-1].rest_arg = 1;
}
break;
default:
cpp_ice (pfile, "collect_params: impossible token type %d",
list->tokens[j].type);
}
arglist->argc = argc;
arglist->argv = argv;
arglist->namebuf = namebuf;
return i + 1;
}
/* Create a DEFINITION node for a macro. The replacement text
(including formal parameters if present) is in LIST. If FUNLIKE is
true, this is a function-like macro. */
DEFINITION *
_cpp_create_definition (pfile, funlike)
_cpp_create_definition (pfile, list, funlike)
cpp_reader *pfile;
cpp_toklist *list;
int funlike;
{
struct arglist *args = 0;
unsigned int line, col;
const char *file;
struct arglist args;
DEFINITION *defn;
line = CPP_BUF_LINE (CPP_BUFFER (pfile));
col = CPP_BUF_COL (CPP_BUFFER (pfile));
file = CPP_BUFFER (pfile)->nominal_fname;
int replacement = 1; /* replacement begins at this token */
if (funlike)
{
args = collect_formal_parameters (pfile);
if (args == 0)
replacement = collect_params (pfile, list, &args);
if (replacement == 0)
return 0;
}
defn = collect_expansion (pfile, args);
defn = collect_expansion (pfile, list, funlike ? &args : 0, replacement);
if (defn == 0)
return 0;
defn->line = line;
defn->file = file;
defn->col = col;
defn->file = CPP_BUFFER (pfile)->nominal_fname;
defn->line = list->line;
defn->col = list->tokens[0].col;
return defn;
}
@ -1098,11 +1028,8 @@ _cpp_macroexpand (pfile, hp)
}
else if (i < nargs)
{
/* traditional C allows foo() if foo wants one argument. */
if (nargs == 1 && i == 0 && CPP_TRADITIONAL (pfile))
;
/* the rest args token is allowed to absorb 0 tokens */
else if (i == nargs - 1 && defn->rest_args)
if (i == nargs - 1 && defn->rest_args)
rest_zero = 1;
else if (i == 0)
cpp_error (pfile, "macro `%s' used without args", hp->name);
@ -1158,8 +1085,7 @@ _cpp_macroexpand (pfile, hp)
int need_space = -1;
i = 0;
arg->stringified = CPP_WRITTEN (pfile);
if (!CPP_TRADITIONAL (pfile))
CPP_PUTC (pfile, '\"'); /* insert beginning quote */
CPP_PUTC (pfile, '\"'); /* insert beginning quote */
for (; i < arglen; i++)
{
c = (ARG_BASE + arg->raw)[i];
@ -1214,14 +1140,13 @@ _cpp_macroexpand (pfile, hp)
CPP_ADJUST_WRITTEN (pfile, 4);
}
}
if (!CPP_TRADITIONAL (pfile))
CPP_PUTC (pfile, '\"'); /* insert ending quote */
CPP_PUTC (pfile, '\"'); /* insert ending quote */
arg->stringified_length
= CPP_WRITTEN (pfile) - arg->stringified;
}
xbuf_len += args[ap->argno].stringified_length;
}
else if (ap->raw_before || ap->raw_after || CPP_TRADITIONAL (pfile))
else if (ap->raw_before || ap->raw_after)
/* Add 4 for two \r-space markers to prevent
token concatenation. */
xbuf_len += args[ap->argno].raw_length + 4;
@ -1288,7 +1213,7 @@ _cpp_macroexpand (pfile, hp)
arg->stringified_length);
totlen += arg->stringified_length;
}
else if (ap->raw_before || ap->raw_after || CPP_TRADITIONAL (pfile))
else if (ap->raw_before || ap->raw_after)
{
U_CHAR *p1 = ARG_BASE + arg->raw;
U_CHAR *l1 = p1 + arg->raw_length;
@ -1340,7 +1265,6 @@ _cpp_macroexpand (pfile, hp)
{
U_CHAR *expanded = ARG_BASE + arg->expanded;
if (!ap->raw_before && totlen > 0 && arg->expand_length
&& !CPP_TRADITIONAL (pfile)
&& unsafe_chars (pfile, xbuf[totlen - 1], expanded[0]))
{
xbuf[totlen++] = '\r';
@ -1351,7 +1275,6 @@ _cpp_macroexpand (pfile, hp)
totlen += arg->expand_length;
if (!ap->raw_after && totlen > 0 && offset < defn->length
&& !CPP_TRADITIONAL (pfile)
&& unsafe_chars (pfile, xbuf[totlen - 1], exp[offset]))
{
xbuf[totlen++] = '\r';
@ -1394,12 +1317,8 @@ _cpp_macroexpand (pfile, hp)
/* Pop the space we've used in the token_buffer for argument expansion. */
CPP_SET_WRITTEN (pfile, old_written);
/* Recursive macro use sometimes works traditionally.
#define foo(x,y) bar (x (y,0), y)
foo (foo, baz) */
if (!CPP_TRADITIONAL (pfile))
hp->type = T_DISABLED;
/* Per C89, a macro cannot be expanded recursively. */
hp->type = T_DISABLED;
}
/* Return 1 iff a token ending in C1 followed directly by a token C2
@ -1520,12 +1439,11 @@ _cpp_compare_defs (pfile, d1, d2)
DEFINITION *d1, *d2;
{
struct reflist *a1, *a2;
U_CHAR *p1 = d1->expansion;
U_CHAR *p2 = d2->expansion;
int first = 1;
if (d1->nargs != d2->nargs)
return 1;
if (strcmp (d1->expansion, d2->expansion))
return 1;
if (CPP_PEDANTIC (pfile)
&& d1->argnames && d2->argnames)
{
@ -1545,74 +1463,17 @@ _cpp_compare_defs (pfile, d1, d2)
for (a1 = d1->pattern, a2 = d2->pattern; a1 && a2;
a1 = a1->next, a2 = a2->next)
{
if (!((a1->nchars == a2->nchars && !strncmp (p1, p2, a1->nchars))
|| !comp_def_part (first, p1, a1->nchars, p2, a2->nchars, 0))
if (a1->nchars != a2->nchars
|| a1->argno != a2->argno
|| a1->stringify != a2->stringify
|| a1->raw_before != a2->raw_before
|| a1->raw_after != a2->raw_after)
return 1;
first = 0;
p1 += a1->nchars;
p2 += a2->nchars;
}
if (a1 != a2)
return 1;
return comp_def_part (first, p1, d1->length - (p1 - d1->expansion),
p2, d2->length - (p2 - d2->expansion), 1);
}
/* Return 1 if two parts of two macro definitions are effectively different.
One of the parts starts at BEG1 and has LEN1 chars;
the other has LEN2 chars at BEG2.
Any sequence of whitespace matches any other sequence of whitespace.
FIRST means these parts are the first of a macro definition;
so ignore leading whitespace entirely.
LAST means these parts are the last of a macro definition;
so ignore trailing whitespace entirely. */
static int
comp_def_part (first, beg1, len1, beg2, len2, last)
int first;
U_CHAR *beg1, *beg2;
int len1, len2;
int last;
{
register U_CHAR *end1 = beg1 + len1;
register U_CHAR *end2 = beg2 + len2;
if (first)
{
while (beg1 != end1 && is_space(*beg1))
beg1++;
while (beg2 != end2 && is_space(*beg2))
beg2++;
}
if (last)
{
while (beg1 != end1 && is_space(end1[-1]))
end1--;
while (beg2 != end2 && is_space(end2[-1]))
end2--;
}
while (beg1 != end1 && beg2 != end2)
{
if (is_space(*beg1) && is_space(*beg2))
{
while (beg1 != end1 && is_space(*beg1))
beg1++;
while (beg2 != end2 && is_space(*beg2))
beg2++;
}
else if (*beg1 == *beg2)
{
beg1++;
beg2++;
}
else
break;
}
return (beg1 != end1) || (beg2 != end2);
return 0;
}
/* Dump the definition of macro MACRO on stdout. The format is suitable

View file

@ -272,7 +272,8 @@ extern HASHNODE **_cpp_lookup_slot PARAMS ((cpp_reader *,
enum insert_option,
unsigned long *));
extern void _cpp_free_definition PARAMS ((DEFINITION *));
extern DEFINITION *_cpp_create_definition PARAMS ((cpp_reader *, int));
extern DEFINITION *_cpp_create_definition PARAMS ((cpp_reader *,
cpp_toklist *, int));
extern void _cpp_dump_definition PARAMS ((cpp_reader *, const U_CHAR *,
long, DEFINITION *));
extern int _cpp_compare_defs PARAMS ((cpp_reader *, DEFINITION *,

View file

@ -57,6 +57,8 @@ static void bump_column PARAMS ((cpp_printer *, unsigned int,
static void expand_name_space PARAMS ((cpp_toklist *));
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));
/* Re-allocates PFILE->token_buffer so it will hold at least N more chars. */
@ -474,7 +476,8 @@ init_token_list (pfile, list, recycle)
list->namebuf = (unsigned char *) xmalloc (list->name_cap);
}
list->line = pfile->buffer->lineno;
if (pfile->buffer)
list->line = pfile->buffer->lineno;
list->dir_handler = 0;
list->dir_flags = 0;
}
@ -490,11 +493,13 @@ _cpp_scan_line (pfile, list)
int i, col;
long written, len;
enum cpp_ttype type;
int space_before;
init_token_list (pfile, list, 1);
written = CPP_WRITTEN (pfile);
i = 0;
space_before = 0;
for (;;)
{
col = CPP_BUFFER (pfile)->cur - CPP_BUFFER (pfile)->line_base;
@ -502,17 +507,26 @@ _cpp_scan_line (pfile, list)
len = CPP_WRITTEN (pfile) - written;
CPP_SET_WRITTEN (pfile, written);
if (type == CPP_HSPACE)
continue;
{
if (CPP_PEDANTIC (pfile))
pedantic_whitespace (pfile, pfile->token_buffer + written, len);
space_before = 1;
continue;
}
if (list->tokens_used >= list->tokens_cap)
expand_token_space (list);
if (list->name_used + len >= list->name_cap)
expand_name_space (list);
if (type == CPP_MACRO)
type = CPP_NAME;
list->tokens_used++;
list->tokens[i].type = type;
list->tokens[i].col = col;
list->tokens[i].flags = space_before ? HSPACE_BEFORE : 0;
if (type == CPP_VSPACE)
break;
@ -521,8 +535,12 @@ _cpp_scan_line (pfile, list)
memcpy (list->namebuf + list->name_used, CPP_PWRITTEN (pfile), len);
list->name_used += len;
i++;
space_before = 0;
}
list->tokens[i].aux = CPP_BUFFER (pfile)->lineno + 1;
/* XXX Temporary kluge: put back the newline. */
FORWARD(-1);
}
@ -1034,14 +1052,8 @@ _cpp_lex_token (pfile)
For -traditional, a comment is equivalent to nothing. */
if (!CPP_OPTION (pfile, discard_comments))
return CPP_COMMENT;
else if (CPP_TRADITIONAL (pfile)
&& ! is_space (PEEKC ()))
{
if (pfile->parsing_define_directive)
return CPP_COMMENT;
else
goto get_next;
}
else if (CPP_TRADITIONAL (pfile))
goto get_next;
else
{
CPP_PUTC (pfile, c);
@ -1060,7 +1072,7 @@ _cpp_lex_token (pfile)
return CPP_OTHER;
}
if (pfile->parsing_define_directive && ! CPP_TRADITIONAL (pfile))
if (pfile->parsing_define_directive)
{
c2 = PEEKC ();
if (c2 == '#')
@ -1510,6 +1522,26 @@ maybe_macroexpand (pfile, written)
return 1;
}
/* Complain about \v or \f in a preprocessing directive (constraint
violation, C99 6.10 para 5). Caller has checked CPP_PEDANTIC. */
static void
pedantic_whitespace (pfile, p, len)
cpp_reader *pfile;
U_CHAR *p;
unsigned int len;
{
while (len)
{
if (*p == '\v')
cpp_pedwarn (pfile, "vertical tab in preprocessing directive");
else if (*p == '\f')
cpp_pedwarn (pfile, "form feed in preprocessing directive");
p++;
len--;
}
}
enum cpp_ttype
cpp_get_token (pfile)
cpp_reader *pfile;
@ -1591,14 +1623,10 @@ cpp_get_non_space_token (pfile)
}
/* Like cpp_get_token, except that it does not execute directives,
does not consume vertical space, and automatically pops off macro
buffers.
XXX This function will exist only till collect_expansion doesn't
need to see whitespace anymore, then it'll be merged with
_cpp_get_directive_token (below). */
does not consume vertical space, discards horizontal space, and
automatically pops off macro buffers. */
enum cpp_ttype
_cpp_get_define_token (pfile)
_cpp_get_directive_token (pfile)
cpp_reader *pfile;
{
long old_written;
@ -1620,18 +1648,10 @@ _cpp_get_define_token (pfile)
case CPP_HSPACE:
if (CPP_PEDANTIC (pfile))
{
U_CHAR *p, *limit;
p = pfile->token_buffer + old_written;
limit = CPP_PWRITTEN (pfile);
while (p < limit)
{
if (*p == '\v' || *p == '\f')
cpp_pedwarn (pfile, "%s in preprocessing directive",
*p == '\f' ? "formfeed" : "vertical tab");
p++;
}
}
pedantic_whitespace (pfile, pfile->token_buffer + old_written,
CPP_WRITTEN (pfile) - old_written);
CPP_SET_WRITTEN (pfile, old_written);
goto get_next;
return CPP_HSPACE;
case CPP_DIRECTIVE:
@ -1660,23 +1680,6 @@ _cpp_get_define_token (pfile)
}
}
/* Just like _cpp_get_define_token except that it discards horizontal
whitespace. */
enum cpp_ttype
_cpp_get_directive_token (pfile)
cpp_reader *pfile;
{
int old_written = CPP_WRITTEN (pfile);
for (;;)
{
enum cpp_ttype token = _cpp_get_define_token (pfile);
if (token != CPP_COMMENT && token != CPP_HSPACE)
return token;
CPP_SET_WRITTEN (pfile, old_written);
}
}
/* Determine the current line and column. Used only by read_and_prescan. */
static U_CHAR *
find_position (start, limit, linep)
@ -2008,6 +2011,7 @@ _cpp_init_input_buffer (pfile)
U_CHAR *tmp;
init_chartab ();
init_token_list (pfile, &pfile->directbuf, 0);
/* Determine the appropriate size for the input buffer. Normal C
source files are smaller than eight K. */

View file

@ -66,7 +66,6 @@ static int read_line_number PARAMS ((cpp_reader *, int *));
static U_CHAR *detect_if_not_defined PARAMS ((cpp_reader *));
static int consider_directive_while_skipping
PARAMS ((cpp_reader *, IF_STACK *));
static int get_macro_name PARAMS ((cpp_reader *));
/* Values for the flags field of the table below. KANDR and COND
directives come from traditional (K&R) C. The difference is, if we
@ -310,36 +309,6 @@ pass_thru_directive (buf, len, pfile, keyword)
CPP_PUTS_Q (pfile, buf, len);
}
/* Subroutine of do_define: determine the name of the macro to be
defined. */
static int
get_macro_name (pfile)
cpp_reader *pfile;
{
long here, len;
here = CPP_WRITTEN (pfile);
if (_cpp_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;
}
return len;
invalid:
_cpp_skip_rest_of_line (pfile);
return 0;
}
/* Process a #define command. */
static int
@ -348,47 +317,60 @@ do_define (pfile)
{
HASHNODE **slot;
DEFINITION *def = 0;
long here;
unsigned long hash;
int len;
int funlike = 0, empty = 0;
U_CHAR *sym;
enum cpp_ttype token;
cpp_toklist *list = &pfile->directbuf;
pfile->no_macro_expand++;
pfile->parsing_define_directive++;
CPP_OPTION (pfile, discard_comments)++;
here = CPP_WRITTEN (pfile);
len = get_macro_name (pfile);
if (len == 0)
goto out;
_cpp_scan_line (pfile, list);
/* 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';
/* First token on the line must be a NAME. There must be at least
one token (the VSPACE at the end). */
if (list->tokens[0].type != CPP_NAME)
{
cpp_error_with_line (pfile, list->line, list->tokens[0].col,
"#define must be followed by an identifier");
goto out;
}
sym = list->namebuf + list->tokens[0].val.name.offset;
len = list->tokens[0].val.name.len;
/* That NAME is not allowed to be "defined". (Not clear if the
standard requires this.) */
if (len == 7 && !strncmp (sym, "defined", 7))
{
cpp_error_with_line (pfile, list->line, list->tokens[0].col,
"\"defined\" is not a legal macro name");
goto out;
}
if (list->tokens_used == 2 && list->tokens[1].type == CPP_VSPACE)
empty = 0; /* Empty definition of object-like macro. */
/* If the next character, with no intervening whitespace, is '(',
then this is a function-like macro.
XXX Layering violation. */
CPP_SET_MARK (pfile);
token = _cpp_get_directive_token (pfile);
if (token == CPP_VSPACE)
empty = 0; /* Empty definition of object like macro. */
else if (token == CPP_OPEN_PAREN && ADJACENT_TO_MARK (pfile))
funlike = 1;
else if (ADJACENT_TO_MARK (pfile))
/* If this is an object-like macro, C99 requires white space after
the name. */
cpp_pedwarn (pfile, "missing white space after `#define %.*s'", len, sym);
CPP_GOTO_MARK (pfile);
CPP_SET_WRITTEN (pfile, here);
then this is a function-like macro. Otherwise it is an object-
like macro, and C99 requires whitespace after the name
(6.10.3 para 3). */
else if (!(list->tokens[1].flags & HSPACE_BEFORE))
{
if (list->tokens[1].type == CPP_OPEN_PAREN)
funlike = 1;
else
cpp_pedwarn (pfile,
"The C standard requires whitespace after #define %.*s",
len, sym);
}
if (! empty)
{
def = _cpp_create_definition (pfile, funlike);
def = _cpp_create_definition (pfile, list, funlike);
if (def == 0)
goto out;
}

View file

@ -135,6 +135,9 @@ struct cpp_name
unsigned int offset; /* from list->namebuf */
};
/* Per token flags. */
#define HSPACE_BEFORE (1 << 0) /* token preceded by hspace */
/* A preprocessing token.
This has been carefully packed and should occupy 16 bytes on
both 32- and 64-bit hosts. */
@ -146,7 +149,7 @@ struct cpp_token
#else
unsigned char type;
#endif
unsigned char flags; /* flags - not presently used */
unsigned char flags; /* flags - see above */
unsigned int aux; /* hash of a NAME, or something -
see uses in the code */
union
@ -435,8 +438,12 @@ struct cpp_options
struct cpp_reader
{
/* Top of buffer stack. */
cpp_buffer *buffer;
/* Token list used by get_directive_token. */
cpp_toklist directbuf;
/* A buffer used for both for cpp_get_token's output, and also internally. */
unsigned char *token_buffer;
/* Allocated size of token_buffer. CPP_RESERVE allocates space. */