Commit 9e62c811 by Zack Weinberg Committed by Zack Weinberg

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
parent 152897b1
2000-04-21 Zack Weinberg <zack@wolery.cumb.org> 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 * predict.c (estimate_probability): New heuristic: if a jump
branches around a block with no successors, predict it taken. branches around a block with no successors, predict it taken.
Disentangle control flow. Disentangle control flow.
......
...@@ -36,8 +36,6 @@ static int eq_HASHNODE PARAMS ((const void *, const void *)); ...@@ -36,8 +36,6 @@ static int eq_HASHNODE PARAMS ((const void *, const void *));
static void del_HASHNODE PARAMS ((void *)); static void del_HASHNODE PARAMS ((void *));
static int dump_hash_helper PARAMS ((void **, 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 *, static void push_macro_expansion PARAMS ((cpp_reader *,
U_CHAR *, int, HASHNODE *)); U_CHAR *, int, HASHNODE *));
static int unsafe_chars PARAMS ((cpp_reader *, int, int)); static int unsafe_chars PARAMS ((cpp_reader *, int, int));
...@@ -61,21 +59,27 @@ static void special_symbol PARAMS ((HASHNODE *, cpp_reader *)); ...@@ -61,21 +59,27 @@ static void special_symbol PARAMS ((HASHNODE *, cpp_reader *));
struct arg struct arg
{ {
U_CHAR *name; const U_CHAR *name;
int len; unsigned int len;
char rest_arg; char rest_arg;
}; };
struct arglist struct arglist
{ {
U_CHAR *namebuf; U_CHAR *namebuf;
struct arg *argv; const struct arg *argv;
int argc; int argc;
}; };
static DEFINITION *collect_expansion PARAMS ((cpp_reader *, struct arglist *)); static DEFINITION *collect_expansion PARAMS ((cpp_reader *, cpp_toklist *,
static struct arglist *collect_formal_parameters PARAMS ((cpp_reader *)); 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. /* This structure represents one parsed argument in a macro call.
`raw' points to the argument text as written (`raw_length' is its length). `raw' points to the argument text as written (`raw_length' is its length).
...@@ -275,28 +279,64 @@ macro_cleanup (pbuf, pfile) ...@@ -275,28 +279,64 @@ macro_cleanup (pbuf, pfile)
return 0; return 0;
} }
/* 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;
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 /* Read a replacement list for a macro, and build the DEFINITION
structure. ARGLIST specifies the formal parameters to look for in structure. LIST contains the replacement list, beginning at
the text of the definition. If ARGLIST is null, this is an 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 object-like macro; if it points to an empty arglist, this is a
function-like macro with no arguments. function-like macro with no arguments. */
A good half of this is devoted to supporting -traditional.
Kill me now. */
static DEFINITION * static DEFINITION *
collect_expansion (pfile, arglist) collect_expansion (pfile, list, arglist, replacement)
cpp_reader *pfile; cpp_reader *pfile;
cpp_toklist *list;
struct arglist *arglist; struct arglist *arglist;
unsigned int replacement;
{ {
DEFINITION *defn; DEFINITION *defn;
struct reflist *pat = 0, *endpat = 0; struct reflist *pat = 0, *endpat = 0;
enum cpp_ttype token; enum cpp_ttype token;
long start, here, last; long start, last;
int i; unsigned int i;
int argc; int j, argc;
size_t len; size_t len;
struct arg *argv; const struct arg *argv;
U_CHAR *tok, *exp; U_CHAR *tok, *exp;
enum { START = 0, NORM, ARG, STRIZE, PASTE } last_token = START; enum { START = 0, NORM, ARG, STRIZE, PASTE } last_token = START;
...@@ -311,15 +351,16 @@ collect_expansion (pfile, arglist) ...@@ -311,15 +351,16 @@ collect_expansion (pfile, arglist)
argc = 0; argc = 0;
} }
/* We copy the expansion text into the token_buffer, then out to
its proper home. */
last = start = CPP_WRITTEN (pfile); last = start = CPP_WRITTEN (pfile);
last -= 2; /* two extra chars for the leading escape */ CPP_PUTS (pfile, "\r ", 2);
for (;;)
for (i = replacement; i < list->tokens_used; i++)
{ {
/* Macro expansion is off, so we are guaranteed not to see POP token = list->tokens[i].type;
or EOF. */ tok = list->tokens[i].val.name.offset + list->namebuf;
here = CPP_WRITTEN (pfile); len = list->tokens[i].val.name.len;
token = _cpp_get_define_token (pfile);
tok = pfile->token_buffer + here;
switch (token) switch (token)
{ {
case CPP_POP: case CPP_POP:
...@@ -329,90 +370,54 @@ collect_expansion (pfile, arglist) ...@@ -329,90 +370,54 @@ collect_expansion (pfile, arglist)
case CPP_VSPACE: case CPP_VSPACE:
goto done; goto done;
case CPP_HSPACE:
if (last_token == STRIZE || last_token == PASTE
|| last_token == START)
CPP_SET_WRITTEN (pfile, here);
break;
case CPP_HASH: case CPP_HASH:
/* # is not special in object-like macros. It is special in /* # is not special in object-like macros. It is special in
function-like macros with no args. (6.10.3.2 para 1.) */ function-like macros with no args. (6.10.3.2 para 1.)
if (arglist == NULL) However, it is not special after PASTE. (Implied by
goto norm; 6.10.3.3 para 4.) */
/* # is not special immediately after PASTE. if (arglist == NULL || last_token == PASTE)
(Implied by 6.10.3.3 para 4.) */
if (last_token == PASTE)
goto norm; goto norm;
last_token = STRIZE; last_token = STRIZE;
CPP_SET_WRITTEN (pfile, here); /* delete from replacement text */
break; break;
case CPP_PASTE: case CPP_PASTE:
/* If the last token was an argument, discard this token and if (last_token == PASTE)
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)
/* ## ## - the second ## is ordinary. */ /* ## ## - the second ## is ordinary. */
goto norm; goto norm;
else if (last_token == START) else if (last_token == START)
cpp_error (pfile, "`##' at start of macro definition"); cpp_error (pfile, "`##' at start of macro definition");
/* Discard the token and any hspace before it. */ else if (last_token == ARG)
while (is_hspace (pfile->token_buffer[here-1])) /* If the last token was an argument, mark it raw_after. */
here--; endpat->raw_after = 1;
CPP_SET_WRITTEN (pfile, here); else if (last_token == STRIZE)
if (last_token == STRIZE)
/* Oops - that wasn't a stringify operator. */ /* Oops - that wasn't a stringify operator. */
CPP_PUTC (pfile, '#'); 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; last_token = PASTE;
break; break;
case CPP_STRING: case CPP_STRING:
case CPP_CHAR: case CPP_CHAR:
if (last_token == STRIZE) if (argc && CPP_WTRADITIONAL (pfile))
cpp_error (pfile, "`#' is not followed by a macro argument name"); warn_trad_stringify (pfile, tok, len, argc, argv);
goto norm;
if (CPP_TRADITIONAL (pfile) || CPP_WTRADITIONAL (pfile))
goto maybe_trad_stringify;
else
goto norm;
case CPP_NAME: case CPP_NAME:
for (i = 0; i < argc; i++) for (j = 0; j < argc; j++)
if (!strncmp (tok, argv[i].name, argv[i].len) if (argv[j].len == len
&& tok + argv[i].len == CPP_PWRITTEN (pfile)) && !strncmp (tok, argv[j].name, argv[j].len))
goto addref; goto addref;
/* fall through */ /* fall through */
default: default:
norm: norm:
if (last_token == STRIZE) 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; last_token = NORM;
break; break;
} }
...@@ -421,85 +426,27 @@ collect_expansion (pfile, arglist) ...@@ -421,85 +426,27 @@ collect_expansion (pfile, arglist)
addref: addref:
{ {
struct reflist *tpat; 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 */ /* Make a pat node for this arg and add it to the pat list */
tpat = (struct reflist *) xmalloc (sizeof (struct reflist)); tpat = (struct reflist *) xmalloc (sizeof (struct reflist));
tpat->next = NULL; tpat->next = NULL;
tpat->raw_before = (last_token == PASTE); tpat->raw_before = (last_token == PASTE);
tpat->raw_after = 0; tpat->raw_after = 0;
tpat->stringify = (last_token == STRIZE); tpat->stringify = (last_token == STRIZE);
tpat->rest_args = argv[i].rest_arg; tpat->rest_args = argv[j].rest_arg;
tpat->argno = i; tpat->argno = j;
tpat->nchars = here - last; tpat->nchars = CPP_WRITTEN (pfile) - last;
if (endpat == NULL) if (endpat == NULL)
pat = tpat; pat = tpat;
else else
endpat->next = tpat; endpat->next = tpat;
endpat = tpat; endpat = tpat;
last = here; last = CPP_WRITTEN (pfile);
} }
CPP_SET_WRITTEN (pfile, here); /* discard arg name */
last_token = ARG; 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: done:
...@@ -508,241 +455,224 @@ collect_expansion (pfile, arglist) ...@@ -508,241 +455,224 @@ collect_expansion (pfile, arglist)
else if (last_token == PASTE) else if (last_token == PASTE)
cpp_error (pfile, "`##' at end of macro definition"); cpp_error (pfile, "`##' at end of macro definition");
if (last_token == START) CPP_PUTS (pfile, "\r ", 2);
{ len = CPP_WRITTEN (pfile) - 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_SET_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 = (DEFINITION *) xmalloc (sizeof (DEFINITION));
defn->length = len + 3; defn->length = len;
defn->expansion = exp; defn->expansion = exp;
defn->pattern = pat; defn->pattern = pat;
defn->rest_args = 0; defn->rest_args = argv && argv[argc - 1].rest_arg;
if (arglist) if (arglist)
{ {
defn->nargs = argc; defn->nargs = argc;
defn->argnames = arglist->namebuf; defn->argnames = arglist->namebuf;
if (argv) if (argv)
{ free ((PTR) argv);
defn->rest_args = argv[argc - 1].rest_arg;
free (argv);
}
free (arglist);
} }
else else
{ {
defn->nargs = -1; defn->nargs = -1;
defn->argnames = 0; defn->argnames = 0;
defn->rest_args = 0;
} }
return defn; return defn;
} }
static struct arglist * /* Is argument NEW, which has just been added to the argument list,
collect_formal_parameters (pfile) a duplicate of a previous argument name? */
static int
duplicate_arg_p (args, new)
U_CHAR *args, *new;
{
size_t newlen = strlen (new) + 1;
size_t oldlen;
while (args < new)
{
oldlen = strlen (args) + 1;
if (!memcmp (args, new, MIN (oldlen, newlen)))
return 1;
args += oldlen;
}
return 0;
}
static unsigned int
collect_params (pfile, list, arglist)
cpp_reader *pfile; cpp_reader *pfile;
cpp_toklist *list;
struct arglist *arglist;
{ {
struct arglist *result = 0;
struct arg *argv = 0; struct arg *argv = 0;
U_CHAR *namebuf = (U_CHAR *) xstrdup (""); U_CHAR *namebuf, *p, *tok;
unsigned int len, argslen;
unsigned int argc, a, i, j;
U_CHAR *name, *tok; /* The formal parameters list starts at token 1. */
size_t argslen = 1; if (list->tokens[1].type != CPP_OPEN_PAREN)
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)
{ {
cpp_ice (pfile, "first token = %d not %d in collect_formal_parameters", cpp_ice (pfile, "first token = %d not %d in collect_formal_parameters",
token, CPP_OPEN_PAREN); list->tokens[1].type, CPP_OPEN_PAREN);
goto invalid; return 0;
} }
argv = (struct arg *) xmalloc (sizeof (struct arg)); /* Scan once and count the number of parameters; also check for
argv[argc].len = 0; syntax errors here. */
argv[argc].rest_arg = 0; argc = 0;
for (;;) argslen = 0;
{ for (i = 2; i < list->tokens_used; i++)
CPP_SET_WRITTEN (pfile, old_written); switch (list->tokens[i].type)
token = _cpp_get_directive_token (pfile); {
switch (token) case CPP_NAME:
{ argslen += list->tokens[i].val.name.len + 1;
case CPP_NAME: argc++;
tok = pfile->token_buffer + old_written; break;
len = CPP_PWRITTEN (pfile) - tok; case CPP_COMMA:
if (namebuf break;
&& (name = (U_CHAR *) strstr (namebuf, tok)) case CPP_CLOSE_PAREN:
&& name[len] == ',' goto scanned;
&& (name == namebuf || name[-1] == ',')) case CPP_VSPACE:
{ cpp_error_with_line (pfile, list->line, list->tokens[i].col,
cpp_error (pfile, "duplicate macro argument name `%s'", tok); "missing right paren in macro argument list");
continue; return 0;
}
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: default:
goto rest_arg; cpp_error_with_line (pfile, list->line, list->tokens[i].col,
"syntax error in #define");
return 0;
case CPP_VSPACE: case CPP_ELLIPSIS:
cpp_error (pfile, "missing right paren in macro argument list"); if (list->tokens[i-1].type != CPP_NAME)
goto invalid; {
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;
}
default: cpp_ice (pfile, "collect_params: unreachable - i=%d, ntokens=%d, type=%d",
cpp_error (pfile, "syntax error in #define"); i, list->tokens_used, list->tokens[i-1].type);
goto invalid; return 0;
}
}
rest_arg: scanned:
/* There are two possible styles for a vararg macro: if (argc == 0) /* function-like macro, no arguments */
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)) arglist->argc = 0;
cpp_pedwarn (pfile, "C89 does not permit varargs macros"); arglist->argv = 0;
arglist->namebuf = 0;
len = sizeof "__VA_ARGS__" - 1; return i + 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 (argslen == 0)
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 `...'"); cpp_ice (pfile, "collect_params: argc=%d argslen=0", argc);
goto invalid; return 0;
} }
done: /* Now allocate space and copy the suckers. */
/* Go through argv and fix up the pointers. */ argv = (struct arg *) xmalloc (argc * sizeof (struct arg));
len = 0; namebuf = (U_CHAR *) xmalloc (argslen);
for (i = 0; i <= argc; i++) p = namebuf;
{ a = 0;
argv[i].name = namebuf + len; for (j = 2; j < i; j++)
len += argv[i].len + 1; switch (list->tokens[j].type)
namebuf[len - 1] = '\0'; {
} 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;
CPP_SET_WRITTEN (pfile, old_written); case CPP_COMMA:
break;
result = (struct arglist *) xmalloc (sizeof (struct arglist)); case CPP_ELLIPSIS:
if (namebuf[0] != '\0') if (list->tokens[j-1].type != CPP_NAME)
{ {
result->namebuf = namebuf; if (CPP_PEDANTIC (pfile) && ! CPP_OPTION (pfile, c99))
result->argc = argc + 1; cpp_pedwarn (pfile, "C89 does not permit varargs macros");
result->argv = argv;
}
else
{
free (namebuf);
result->namebuf = 0;
result->argc = 0;
result->argv = 0;
}
return result; 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;
invalid: default:
if (argv) cpp_ice (pfile, "collect_params: impossible token type %d",
free (argv); list->tokens[j].type);
if (namebuf) }
free (namebuf);
return 0; arglist->argc = argc;
arglist->argv = argv;
arglist->namebuf = namebuf;
return i + 1;
} }
/* Create a DEFINITION node for a macro. The reader's point is just /* Create a DEFINITION node for a macro. The replacement text
after the macro name. If FUNLIKE is true, this is a function-like (including formal parameters if present) is in LIST. If FUNLIKE is
macro. */ true, this is a function-like macro. */
DEFINITION * DEFINITION *
_cpp_create_definition (pfile, funlike) _cpp_create_definition (pfile, list, funlike)
cpp_reader *pfile; cpp_reader *pfile;
cpp_toklist *list;
int funlike; int funlike;
{ {
struct arglist *args = 0; struct arglist args;
unsigned int line, col;
const char *file;
DEFINITION *defn; DEFINITION *defn;
int replacement = 1; /* replacement begins at this token */
line = CPP_BUF_LINE (CPP_BUFFER (pfile));
col = CPP_BUF_COL (CPP_BUFFER (pfile));
file = CPP_BUFFER (pfile)->nominal_fname;
if (funlike) if (funlike)
{ {
args = collect_formal_parameters (pfile); replacement = collect_params (pfile, list, &args);
if (args == 0) if (replacement == 0)
return 0; return 0;
} }
defn = collect_expansion (pfile, args); defn = collect_expansion (pfile, list, funlike ? &args : 0, replacement);
if (defn == 0) if (defn == 0)
return 0; return 0;
defn->line = line; defn->file = CPP_BUFFER (pfile)->nominal_fname;
defn->file = file; defn->line = list->line;
defn->col = col; defn->col = list->tokens[0].col;
return defn; return defn;
} }
...@@ -1098,11 +1028,8 @@ _cpp_macroexpand (pfile, hp) ...@@ -1098,11 +1028,8 @@ _cpp_macroexpand (pfile, hp)
} }
else if (i < nargs) 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 */ /* 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; rest_zero = 1;
else if (i == 0) else if (i == 0)
cpp_error (pfile, "macro `%s' used without args", hp->name); cpp_error (pfile, "macro `%s' used without args", hp->name);
...@@ -1158,8 +1085,7 @@ _cpp_macroexpand (pfile, hp) ...@@ -1158,8 +1085,7 @@ _cpp_macroexpand (pfile, hp)
int need_space = -1; int need_space = -1;
i = 0; i = 0;
arg->stringified = CPP_WRITTEN (pfile); 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++) for (; i < arglen; i++)
{ {
c = (ARG_BASE + arg->raw)[i]; c = (ARG_BASE + arg->raw)[i];
...@@ -1214,14 +1140,13 @@ _cpp_macroexpand (pfile, hp) ...@@ -1214,14 +1140,13 @@ _cpp_macroexpand (pfile, hp)
CPP_ADJUST_WRITTEN (pfile, 4); CPP_ADJUST_WRITTEN (pfile, 4);
} }
} }
if (!CPP_TRADITIONAL (pfile)) CPP_PUTC (pfile, '\"'); /* insert ending quote */
CPP_PUTC (pfile, '\"'); /* insert ending quote */
arg->stringified_length arg->stringified_length
= CPP_WRITTEN (pfile) - arg->stringified; = CPP_WRITTEN (pfile) - arg->stringified;
} }
xbuf_len += args[ap->argno].stringified_length; 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 /* Add 4 for two \r-space markers to prevent
token concatenation. */ token concatenation. */
xbuf_len += args[ap->argno].raw_length + 4; xbuf_len += args[ap->argno].raw_length + 4;
...@@ -1288,7 +1213,7 @@ _cpp_macroexpand (pfile, hp) ...@@ -1288,7 +1213,7 @@ _cpp_macroexpand (pfile, hp)
arg->stringified_length); arg->stringified_length);
totlen += 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 *p1 = ARG_BASE + arg->raw;
U_CHAR *l1 = p1 + arg->raw_length; U_CHAR *l1 = p1 + arg->raw_length;
...@@ -1340,7 +1265,6 @@ _cpp_macroexpand (pfile, hp) ...@@ -1340,7 +1265,6 @@ _cpp_macroexpand (pfile, hp)
{ {
U_CHAR *expanded = ARG_BASE + arg->expanded; U_CHAR *expanded = ARG_BASE + arg->expanded;
if (!ap->raw_before && totlen > 0 && arg->expand_length if (!ap->raw_before && totlen > 0 && arg->expand_length
&& !CPP_TRADITIONAL (pfile)
&& unsafe_chars (pfile, xbuf[totlen - 1], expanded[0])) && unsafe_chars (pfile, xbuf[totlen - 1], expanded[0]))
{ {
xbuf[totlen++] = '\r'; xbuf[totlen++] = '\r';
...@@ -1351,7 +1275,6 @@ _cpp_macroexpand (pfile, hp) ...@@ -1351,7 +1275,6 @@ _cpp_macroexpand (pfile, hp)
totlen += arg->expand_length; totlen += arg->expand_length;
if (!ap->raw_after && totlen > 0 && offset < defn->length if (!ap->raw_after && totlen > 0 && offset < defn->length
&& !CPP_TRADITIONAL (pfile)
&& unsafe_chars (pfile, xbuf[totlen - 1], exp[offset])) && unsafe_chars (pfile, xbuf[totlen - 1], exp[offset]))
{ {
xbuf[totlen++] = '\r'; xbuf[totlen++] = '\r';
...@@ -1394,12 +1317,8 @@ _cpp_macroexpand (pfile, hp) ...@@ -1394,12 +1317,8 @@ _cpp_macroexpand (pfile, hp)
/* Pop the space we've used in the token_buffer for argument expansion. */ /* Pop the space we've used in the token_buffer for argument expansion. */
CPP_SET_WRITTEN (pfile, old_written); CPP_SET_WRITTEN (pfile, old_written);
/* Recursive macro use sometimes works traditionally. /* Per C89, a macro cannot be expanded recursively. */
#define foo(x,y) bar (x (y,0), y) hp->type = T_DISABLED;
foo (foo, baz) */
if (!CPP_TRADITIONAL (pfile))
hp->type = T_DISABLED;
} }
/* Return 1 iff a token ending in C1 followed directly by a token C2 /* Return 1 iff a token ending in C1 followed directly by a token C2
...@@ -1520,12 +1439,11 @@ _cpp_compare_defs (pfile, d1, d2) ...@@ -1520,12 +1439,11 @@ _cpp_compare_defs (pfile, d1, d2)
DEFINITION *d1, *d2; DEFINITION *d1, *d2;
{ {
struct reflist *a1, *a2; struct reflist *a1, *a2;
U_CHAR *p1 = d1->expansion;
U_CHAR *p2 = d2->expansion;
int first = 1;
if (d1->nargs != d2->nargs) if (d1->nargs != d2->nargs)
return 1; return 1;
if (strcmp (d1->expansion, d2->expansion))
return 1;
if (CPP_PEDANTIC (pfile) if (CPP_PEDANTIC (pfile)
&& d1->argnames && d2->argnames) && d1->argnames && d2->argnames)
{ {
...@@ -1545,74 +1463,17 @@ _cpp_compare_defs (pfile, d1, d2) ...@@ -1545,74 +1463,17 @@ _cpp_compare_defs (pfile, d1, d2)
for (a1 = d1->pattern, a2 = d2->pattern; a1 && a2; for (a1 = d1->pattern, a2 = d2->pattern; a1 && a2;
a1 = a1->next, a2 = a2->next) a1 = a1->next, a2 = a2->next)
{ {
if (!((a1->nchars == a2->nchars && !strncmp (p1, p2, a1->nchars)) if (a1->nchars != a2->nchars
|| !comp_def_part (first, p1, a1->nchars, p2, a2->nchars, 0))
|| a1->argno != a2->argno || a1->argno != a2->argno
|| a1->stringify != a2->stringify || a1->stringify != a2->stringify
|| a1->raw_before != a2->raw_before || a1->raw_before != a2->raw_before
|| a1->raw_after != a2->raw_after) || a1->raw_after != a2->raw_after)
return 1; return 1;
first = 0;
p1 += a1->nchars;
p2 += a2->nchars;
} }
if (a1 != a2) if (a1 != a2)
return 1; return 1;
return comp_def_part (first, p1, d1->length - (p1 - d1->expansion), return 0;
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);
} }
/* Dump the definition of macro MACRO on stdout. The format is suitable /* Dump the definition of macro MACRO on stdout. The format is suitable
......
...@@ -272,7 +272,8 @@ extern HASHNODE **_cpp_lookup_slot PARAMS ((cpp_reader *, ...@@ -272,7 +272,8 @@ extern HASHNODE **_cpp_lookup_slot PARAMS ((cpp_reader *,
enum insert_option, enum insert_option,
unsigned long *)); unsigned long *));
extern void _cpp_free_definition PARAMS ((DEFINITION *)); 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 *, extern void _cpp_dump_definition PARAMS ((cpp_reader *, const U_CHAR *,
long, DEFINITION *)); long, DEFINITION *));
extern int _cpp_compare_defs PARAMS ((cpp_reader *, DEFINITION *, extern int _cpp_compare_defs PARAMS ((cpp_reader *, DEFINITION *,
......
...@@ -57,6 +57,8 @@ static void bump_column PARAMS ((cpp_printer *, unsigned int, ...@@ -57,6 +57,8 @@ static void bump_column PARAMS ((cpp_printer *, unsigned int,
static void expand_name_space PARAMS ((cpp_toklist *)); static void expand_name_space PARAMS ((cpp_toklist *));
static void expand_token_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 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. */ /* Re-allocates PFILE->token_buffer so it will hold at least N more chars. */
...@@ -474,7 +476,8 @@ init_token_list (pfile, list, recycle) ...@@ -474,7 +476,8 @@ init_token_list (pfile, list, recycle)
list->namebuf = (unsigned char *) xmalloc (list->name_cap); 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_handler = 0;
list->dir_flags = 0; list->dir_flags = 0;
} }
...@@ -490,11 +493,13 @@ _cpp_scan_line (pfile, list) ...@@ -490,11 +493,13 @@ _cpp_scan_line (pfile, list)
int i, col; int i, col;
long written, len; long written, len;
enum cpp_ttype type; enum cpp_ttype type;
int space_before;
init_token_list (pfile, list, 1); init_token_list (pfile, list, 1);
written = CPP_WRITTEN (pfile); written = CPP_WRITTEN (pfile);
i = 0; i = 0;
space_before = 0;
for (;;) for (;;)
{ {
col = CPP_BUFFER (pfile)->cur - CPP_BUFFER (pfile)->line_base; col = CPP_BUFFER (pfile)->cur - CPP_BUFFER (pfile)->line_base;
...@@ -502,17 +507,26 @@ _cpp_scan_line (pfile, list) ...@@ -502,17 +507,26 @@ _cpp_scan_line (pfile, list)
len = CPP_WRITTEN (pfile) - written; len = CPP_WRITTEN (pfile) - written;
CPP_SET_WRITTEN (pfile, written); CPP_SET_WRITTEN (pfile, written);
if (type == CPP_HSPACE) 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) if (list->tokens_used >= list->tokens_cap)
expand_token_space (list); expand_token_space (list);
if (list->name_used + len >= list->name_cap) if (list->name_used + len >= list->name_cap)
expand_name_space (list); expand_name_space (list);
if (type == CPP_MACRO)
type = CPP_NAME;
list->tokens_used++; list->tokens_used++;
list->tokens[i].type = type; list->tokens[i].type = type;
list->tokens[i].col = col; list->tokens[i].col = col;
list->tokens[i].flags = space_before ? HSPACE_BEFORE : 0;
if (type == CPP_VSPACE) if (type == CPP_VSPACE)
break; break;
...@@ -521,8 +535,12 @@ _cpp_scan_line (pfile, list) ...@@ -521,8 +535,12 @@ _cpp_scan_line (pfile, list)
memcpy (list->namebuf + list->name_used, CPP_PWRITTEN (pfile), len); memcpy (list->namebuf + list->name_used, CPP_PWRITTEN (pfile), len);
list->name_used += len; list->name_used += len;
i++; i++;
space_before = 0;
} }
list->tokens[i].aux = CPP_BUFFER (pfile)->lineno + 1; 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) ...@@ -1034,14 +1052,8 @@ _cpp_lex_token (pfile)
For -traditional, a comment is equivalent to nothing. */ For -traditional, a comment is equivalent to nothing. */
if (!CPP_OPTION (pfile, discard_comments)) if (!CPP_OPTION (pfile, discard_comments))
return CPP_COMMENT; return CPP_COMMENT;
else if (CPP_TRADITIONAL (pfile) else if (CPP_TRADITIONAL (pfile))
&& ! is_space (PEEKC ())) goto get_next;
{
if (pfile->parsing_define_directive)
return CPP_COMMENT;
else
goto get_next;
}
else else
{ {
CPP_PUTC (pfile, c); CPP_PUTC (pfile, c);
...@@ -1060,7 +1072,7 @@ _cpp_lex_token (pfile) ...@@ -1060,7 +1072,7 @@ _cpp_lex_token (pfile)
return CPP_OTHER; return CPP_OTHER;
} }
if (pfile->parsing_define_directive && ! CPP_TRADITIONAL (pfile)) if (pfile->parsing_define_directive)
{ {
c2 = PEEKC (); c2 = PEEKC ();
if (c2 == '#') if (c2 == '#')
...@@ -1510,6 +1522,26 @@ maybe_macroexpand (pfile, written) ...@@ -1510,6 +1522,26 @@ maybe_macroexpand (pfile, written)
return 1; 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 enum cpp_ttype
cpp_get_token (pfile) cpp_get_token (pfile)
cpp_reader *pfile; cpp_reader *pfile;
...@@ -1591,14 +1623,10 @@ cpp_get_non_space_token (pfile) ...@@ -1591,14 +1623,10 @@ cpp_get_non_space_token (pfile)
} }
/* Like cpp_get_token, except that it does not execute directives, /* Like cpp_get_token, except that it does not execute directives,
does not consume vertical space, and automatically pops off macro does not consume vertical space, discards horizontal space, and
buffers. 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). */
enum cpp_ttype enum cpp_ttype
_cpp_get_define_token (pfile) _cpp_get_directive_token (pfile)
cpp_reader *pfile; cpp_reader *pfile;
{ {
long old_written; long old_written;
...@@ -1620,18 +1648,10 @@ _cpp_get_define_token (pfile) ...@@ -1620,18 +1648,10 @@ _cpp_get_define_token (pfile)
case CPP_HSPACE: case CPP_HSPACE:
if (CPP_PEDANTIC (pfile)) if (CPP_PEDANTIC (pfile))
{ pedantic_whitespace (pfile, pfile->token_buffer + old_written,
U_CHAR *p, *limit; CPP_WRITTEN (pfile) - old_written);
p = pfile->token_buffer + old_written; CPP_SET_WRITTEN (pfile, old_written);
limit = CPP_PWRITTEN (pfile); goto get_next;
while (p < limit)
{
if (*p == '\v' || *p == '\f')
cpp_pedwarn (pfile, "%s in preprocessing directive",
*p == '\f' ? "formfeed" : "vertical tab");
p++;
}
}
return CPP_HSPACE; return CPP_HSPACE;
case CPP_DIRECTIVE: case CPP_DIRECTIVE:
...@@ -1660,23 +1680,6 @@ _cpp_get_define_token (pfile) ...@@ -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. */ /* Determine the current line and column. Used only by read_and_prescan. */
static U_CHAR * static U_CHAR *
find_position (start, limit, linep) find_position (start, limit, linep)
...@@ -2008,6 +2011,7 @@ _cpp_init_input_buffer (pfile) ...@@ -2008,6 +2011,7 @@ _cpp_init_input_buffer (pfile)
U_CHAR *tmp; U_CHAR *tmp;
init_chartab (); init_chartab ();
init_token_list (pfile, &pfile->directbuf, 0);
/* Determine the appropriate size for the input buffer. Normal C /* Determine the appropriate size for the input buffer. Normal C
source files are smaller than eight K. */ source files are smaller than eight K. */
......
...@@ -66,7 +66,6 @@ static int read_line_number PARAMS ((cpp_reader *, int *)); ...@@ -66,7 +66,6 @@ static int read_line_number PARAMS ((cpp_reader *, int *));
static U_CHAR *detect_if_not_defined PARAMS ((cpp_reader *)); static U_CHAR *detect_if_not_defined PARAMS ((cpp_reader *));
static int consider_directive_while_skipping static int consider_directive_while_skipping
PARAMS ((cpp_reader *, IF_STACK *)); 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 /* Values for the flags field of the table below. KANDR and COND
directives come from traditional (K&R) C. The difference is, if we directives come from traditional (K&R) C. The difference is, if we
...@@ -310,36 +309,6 @@ pass_thru_directive (buf, len, pfile, keyword) ...@@ -310,36 +309,6 @@ pass_thru_directive (buf, len, pfile, keyword)
CPP_PUTS_Q (pfile, buf, len); 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. */ /* Process a #define command. */
static int static int
...@@ -348,47 +317,60 @@ do_define (pfile) ...@@ -348,47 +317,60 @@ do_define (pfile)
{ {
HASHNODE **slot; HASHNODE **slot;
DEFINITION *def = 0; DEFINITION *def = 0;
long here;
unsigned long hash; unsigned long hash;
int len; int len;
int funlike = 0, empty = 0; int funlike = 0, empty = 0;
U_CHAR *sym; U_CHAR *sym;
enum cpp_ttype token; cpp_toklist *list = &pfile->directbuf;
pfile->no_macro_expand++; pfile->no_macro_expand++;
pfile->parsing_define_directive++; pfile->parsing_define_directive++;
CPP_OPTION (pfile, discard_comments)++; CPP_OPTION (pfile, discard_comments)++;
here = CPP_WRITTEN (pfile); _cpp_scan_line (pfile, list);
len = get_macro_name (pfile);
if (len == 0)
goto out;
/* Copy out the name so we can pop the token buffer. */ /* First token on the line must be a NAME. There must be at least
len = CPP_WRITTEN (pfile) - here; one token (the VSPACE at the end). */
sym = (U_CHAR *) alloca (len + 1); if (list->tokens[0].type != CPP_NAME)
memcpy (sym, pfile->token_buffer + here, len); {
sym[len] = '\0'; 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 '(', /* If the next character, with no intervening whitespace, is '(',
then this is a function-like macro. then this is a function-like macro. Otherwise it is an object-
XXX Layering violation. */ like macro, and C99 requires whitespace after the name
CPP_SET_MARK (pfile); (6.10.3 para 3). */
token = _cpp_get_directive_token (pfile); else if (!(list->tokens[1].flags & HSPACE_BEFORE))
if (token == CPP_VSPACE) {
empty = 0; /* Empty definition of object like macro. */ if (list->tokens[1].type == CPP_OPEN_PAREN)
else if (token == CPP_OPEN_PAREN && ADJACENT_TO_MARK (pfile)) funlike = 1;
funlike = 1; else
else if (ADJACENT_TO_MARK (pfile)) cpp_pedwarn (pfile,
/* If this is an object-like macro, C99 requires white space after "The C standard requires whitespace after #define %.*s",
the name. */ len, sym);
cpp_pedwarn (pfile, "missing white space after `#define %.*s'", len, sym); }
CPP_GOTO_MARK (pfile);
CPP_SET_WRITTEN (pfile, here);
if (! empty) if (! empty)
{ {
def = _cpp_create_definition (pfile, funlike); def = _cpp_create_definition (pfile, list, funlike);
if (def == 0) if (def == 0)
goto out; goto out;
} }
......
...@@ -135,6 +135,9 @@ struct cpp_name ...@@ -135,6 +135,9 @@ struct cpp_name
unsigned int offset; /* from list->namebuf */ unsigned int offset; /* from list->namebuf */
}; };
/* Per token flags. */
#define HSPACE_BEFORE (1 << 0) /* token preceded by hspace */
/* A preprocessing token. /* A preprocessing token.
This has been carefully packed and should occupy 16 bytes on This has been carefully packed and should occupy 16 bytes on
both 32- and 64-bit hosts. */ both 32- and 64-bit hosts. */
...@@ -146,7 +149,7 @@ struct cpp_token ...@@ -146,7 +149,7 @@ struct cpp_token
#else #else
unsigned char type; unsigned char type;
#endif #endif
unsigned char flags; /* flags - not presently used */ unsigned char flags; /* flags - see above */
unsigned int aux; /* hash of a NAME, or something - unsigned int aux; /* hash of a NAME, or something -
see uses in the code */ see uses in the code */
union union
...@@ -435,8 +438,12 @@ struct cpp_options ...@@ -435,8 +438,12 @@ struct cpp_options
struct cpp_reader struct cpp_reader
{ {
/* Top of buffer stack. */
cpp_buffer *buffer; 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. */ /* A buffer used for both for cpp_get_token's output, and also internally. */
unsigned char *token_buffer; unsigned char *token_buffer;
/* Allocated size of token_buffer. CPP_RESERVE allocates space. */ /* Allocated size of token_buffer. CPP_RESERVE allocates space. */
......
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