Commit b30892f9 by Neil Booth Committed by Neil Booth

cpphash.c (struct macro_info): Add new members.

	* cpphash.c (struct macro_info): Add new members.
	(_cpp_free_definition): Delete the macro directly.
	(count_params): Return void, with first token of
	expansion in struct macro_info on success.
	(parse_define): Return int.  Hoist syntax checking from
	save_macro_expansion.  Leave call to save_expansion to
	_cpp_create_definition.
	(alloc_macro): Needs just 2 arguments.
	(free_macro): Delete.
	(save_expansion): Don't perform syntax check.
	(_cpp_create_definition): Call save_expansion.

From-SVN: r35025
parent 3f6790bf
2000-07-14 Neil Booth <NeilB@earthling.net>
* cpphash.c (struct macro_info): Add new members.
(_cpp_free_definition): Delete the macro directly.
(count_params): Return void, with first token of
expansion in struct macro_info on success.
(parse_define): Return int. Hoist syntax checking from
save_macro_expansion. Leave call to save_expansion to
_cpp_create_definition.
(alloc_macro): Needs just 2 arguments.
(free_macro): Delete.
(save_expansion): Don't perform syntax check.
(_cpp_create_definition): Call save_expansion.
2000-07-13 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> 2000-07-13 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* genrecog.c (write_header): Split long string. * genrecog.c (write_header): Split long string.
......
...@@ -44,8 +44,12 @@ struct hashdummy ...@@ -44,8 +44,12 @@ struct hashdummy
/* Stores basic information about a macro, before it is allocated. */ /* Stores basic information about a macro, before it is allocated. */
struct macro_info struct macro_info
{ {
unsigned int paramlen; const cpp_token *first_param; /* First parameter token. */
short paramc; const cpp_token *first; /* First expansion token. */
unsigned int paramlen; /* Length of parameter names. */
unsigned int len; /* Length of token strings. */
unsigned int ntokens; /* Number of tokens in expansion. */
short paramc; /* Number of parameters. */
unsigned char flags; unsigned char flags;
}; };
...@@ -55,26 +59,18 @@ struct macro_info ...@@ -55,26 +59,18 @@ struct macro_info
static unsigned int hash_HASHNODE PARAMS ((const void *)); static unsigned int hash_HASHNODE PARAMS ((const void *));
static int eq_HASHNODE PARAMS ((const void *, const void *)); static int eq_HASHNODE PARAMS ((const void *, const void *));
static int dump_hash_helper PARAMS ((void **, void *)); static int dump_hash_helper PARAMS ((void **, void *));
static void dump_funlike_macro PARAMS ((cpp_reader *, cpp_hashnode *)); static void dump_funlike_macro PARAMS ((cpp_reader *, cpp_hashnode *));
static void count_params PARAMS ((cpp_reader *, struct macro_info *));
static const cpp_token *count_params PARAMS ((cpp_reader *,
const cpp_token *,
struct macro_info *));
static int is__va_args__ PARAMS ((cpp_reader *, const cpp_token *)); static int is__va_args__ PARAMS ((cpp_reader *, const cpp_token *));
static const cpp_toklist * parse_define PARAMS((cpp_reader *));
static int parse_define PARAMS((cpp_reader *, struct macro_info *));
static int check_macro_redefinition PARAMS((cpp_reader *, cpp_hashnode *hp, static int check_macro_redefinition PARAMS((cpp_reader *, cpp_hashnode *hp,
const cpp_toklist *)); const cpp_toklist *));
static const cpp_toklist * save_expansion PARAMS((cpp_reader *, static const cpp_toklist * save_expansion PARAMS((cpp_reader *,
const cpp_token *, struct macro_info *));
const cpp_token *,
struct macro_info *));
static unsigned int find_param PARAMS ((const cpp_token *, static unsigned int find_param PARAMS ((const cpp_token *,
const cpp_token *)); const cpp_token *));
static cpp_toklist * alloc_macro PARAMS ((cpp_reader *, static cpp_toklist * alloc_macro PARAMS ((cpp_reader *, struct macro_info *));
struct macro_info *,
unsigned int, unsigned int));
static void free_macro PARAMS((const cpp_toklist *));
/* Calculate hash of a string of length LEN. */ /* Calculate hash of a string of length LEN. */
unsigned int unsigned int
...@@ -186,7 +182,7 @@ _cpp_free_definition (h) ...@@ -186,7 +182,7 @@ _cpp_free_definition (h)
cpp_hashnode *h; cpp_hashnode *h;
{ {
if (h->type == T_MACRO) if (h->type == T_MACRO)
free_macro (h->value.expansion); free ((PTR) h->value.expansion);
h->value.expansion = NULL; h->value.expansion = NULL;
} }
...@@ -231,29 +227,38 @@ is__va_args__ (pfile, token) ...@@ -231,29 +227,38 @@ is__va_args__ (pfile, token)
/* Counts the parameters to a function-like macro, the length of their /* Counts the parameters to a function-like macro, the length of their
null-terminated names, and whether the macro is a variable-argument null-terminated names, and whether the macro is a variable-argument
one. FIRST is the token immediately after the open parenthesis, one. FIRST is the token immediately after the open parenthesis,
INFO stores the data, and should have paramlen and flags zero. INFO stores the data.
Returns the token that we stopped scanning at; if it's type isn't On success, info->first is updated to the token after the closing
CPP_CLOSE_PAREN there was an error, which has been reported. */ parenthesis, i.e. the first token of the expansion. Otherwise
static const cpp_token * there was an error, which has been reported. */
count_params (pfile, first, info) static void
count_params (pfile, info)
cpp_reader *pfile; cpp_reader *pfile;
const cpp_token *first;
struct macro_info *info; struct macro_info *info;
{ {
unsigned int prev_ident = 0; unsigned int prev_ident = 0;
const cpp_token *token; const cpp_token *token;
info->paramc = 0; info->paramc = 0;
for (token = first;; token++) info->paramlen = 0;
info->flags = 0;
info->first = info->first_param; /* Not a ')' indicating success. */
for (token = info->first_param;; token++)
{ {
switch (token->type) switch (token->type)
{ {
default:
cpp_error_with_line (pfile, token->line, token->col,
"illegal token in macro parameter list");
return;
case CPP_EOF: case CPP_EOF:
missing_paren: missing_paren:
cpp_error_with_line (pfile, token->line, token->col, cpp_error_with_line (pfile, token->line, token->col,
"missing ')' in macro parameter list"); "missing ')' in macro parameter list");
goto out; return;
case CPP_COMMENT: case CPP_COMMENT:
continue; /* Ignore -C comments. */ continue; /* Ignore -C comments. */
...@@ -263,36 +268,30 @@ count_params (pfile, first, info) ...@@ -263,36 +268,30 @@ count_params (pfile, first, info)
{ {
cpp_error_with_line (pfile, token->line, token->col, cpp_error_with_line (pfile, token->line, token->col,
"macro parameters must be comma-separated"); "macro parameters must be comma-separated");
goto out; return;
} }
/* Constraint 6.10.3.5 */ /* Constraint 6.10.3.5 */
if (is__va_args__ (pfile, token)) if (is__va_args__ (pfile, token))
goto out; return;
/* Constraint 6.10.3.6 - duplicate parameter names. */ /* Constraint 6.10.3.6 - duplicate parameter names. */
if (find_param (first, token)) if (find_param (info->first, token))
{ {
cpp_error_with_line (pfile, token->line, token->col, cpp_error_with_line (pfile, token->line, token->col,
"duplicate macro parameter \"%s\"", "duplicate macro parameter \"%s\"",
token->val.node->name); token->val.node->name);
goto out; return;
} }
prev_ident = 1; prev_ident = 1;
info->paramc++; info->paramc++;
if (pfile->save_parameter_spellings) info->paramlen += token->val.node->length + 1;
info->paramlen += token->val.node->length + 1; continue;
break;
default:
cpp_error_with_line (pfile, token->line, token->col,
"illegal token in macro parameter list");
goto out;
case CPP_CLOSE_PAREN: case CPP_CLOSE_PAREN:
if (prev_ident || info->paramc == 0) if (prev_ident || info->paramc == 0)
goto out; break;
/* Fall through to pick up the error. */ /* Fall through to pick up the error. */
case CPP_COMMA: case CPP_COMMA:
...@@ -300,12 +299,10 @@ count_params (pfile, first, info) ...@@ -300,12 +299,10 @@ count_params (pfile, first, info)
{ {
cpp_error_with_line (pfile, token->line, token->col, cpp_error_with_line (pfile, token->line, token->col,
"parameter name expected"); "parameter name expected");
if (token->type == CPP_CLOSE_PAREN) return;
token--; /* Return the ',' not ')'. */
goto out;
} }
prev_ident = 0; prev_ident = 0;
break; continue;
case CPP_ELLIPSIS: case CPP_ELLIPSIS:
/* Convert ISO-style var_args to named varargs by changing /* Convert ISO-style var_args to named varargs by changing
...@@ -319,8 +316,7 @@ count_params (pfile, first, info) ...@@ -319,8 +316,7 @@ count_params (pfile, first, info)
tok->val.node = pfile->spec_nodes->n__VA_ARGS__; tok->val.node = pfile->spec_nodes->n__VA_ARGS__;
info->paramc++; info->paramc++;
if (pfile->save_parameter_spellings) info->paramlen += tok->val.node->length + 1;
info->paramlen += tok->val.node->length + 1;
if (CPP_PEDANTIC (pfile) && ! CPP_OPTION (pfile, c99)) if (CPP_PEDANTIC (pfile) && ! CPP_OPTION (pfile, c99))
cpp_pedwarn (pfile, cpp_pedwarn (pfile,
...@@ -337,22 +333,26 @@ count_params (pfile, first, info) ...@@ -337,22 +333,26 @@ count_params (pfile, first, info)
info->flags |= VAR_ARGS; info->flags |= VAR_ARGS;
token++; token++;
if (token->type == CPP_CLOSE_PAREN) if (token->type == CPP_CLOSE_PAREN)
goto out; break;
goto missing_paren; goto missing_paren;
} }
}
out: /* Success. */
return token; info->first = token + 1;
if (!pfile->save_parameter_spellings)
info->paramlen = 0;
return;
}
} }
/* Parses a #define directive. Returns null pointer on error. */ /* Parses a #define directive. On success, returns zero, and INFO is
static const cpp_toklist * filled in appropriately. */
parse_define (pfile) static int
parse_define (pfile, info)
cpp_reader *pfile; cpp_reader *pfile;
struct macro_info *info;
{ {
const cpp_token *token, *first_param; const cpp_token *token;
struct macro_info info;
int prev_white = 0; int prev_white = 0;
/* The first token after the macro's name. */ /* The first token after the macro's name. */
...@@ -360,34 +360,85 @@ parse_define (pfile) ...@@ -360,34 +360,85 @@ parse_define (pfile)
/* Constraint 6.10.3.5 */ /* Constraint 6.10.3.5 */
if (is__va_args__ (pfile, token - 1)) if (is__va_args__ (pfile, token - 1))
return 0; return 1;
while (token->type == CPP_COMMENT) while (token->type == CPP_COMMENT)
token++, prev_white = 1; token++, prev_white = 1;
first_param = token + 1; prev_white |= token->flags & PREV_WHITE;
/* Assume object-like macro. */ if (token->type == CPP_OPEN_PAREN && !prev_white)
info.paramc = -1; {
info.paramlen = 0; /* A function-like macro. */
info.flags = 0; info->first_param = token + 1;
count_params (pfile, info);
if (info->first[-1].type != CPP_CLOSE_PAREN)
return 1;
}
else
{
/* An object-like macro. */
info->paramc = -1;
info->paramlen = 0;
info->flags = 0;
info->first = token;
if (!prev_white && token->type != CPP_EOF)
cpp_pedwarn (pfile, "ISO C requires whitespace after the macro name");
}
if (!prev_white && !(token->flags & PREV_WHITE)) /* Count tokens in expansion. We drop paste tokens, and stringize
tokens, so don't count them. */
info->ntokens = info->len = 0;
for (token = info->first; token->type != CPP_EOF; token++)
{ {
if (token->type == CPP_OPEN_PAREN) if (token->type == CPP_PASTE)
{ {
token = count_params (pfile, first_param, &info); /* Token-paste ##, can appear in both object-like and
if (token->type != CPP_CLOSE_PAREN) function-like macros, but not at the ends. Constraint
return 0; 6.10.3.3.1 */
token++; if (token == info->first || token[1].type == CPP_EOF)
{
cpp_error_with_line (pfile, token->line, token->col,
"'##' cannot appear at either end of a macro expansion");
return 1;
}
continue;
}
else if (token->type == CPP_HASH)
{
/* Stringifying #, but a normal character in object-like
macros. Must come before a parameter name. Constraint
6.10.3.2.1. */
if (info->paramc >= 0)
{
if (token[1].type == CPP_NAME
&& find_param (info->first_param, token + 1))
continue;
if (! CPP_OPTION (pfile, lang_asm))
{
cpp_error_with_line (pfile, token->line, token->col,
"'#' is not followed by a macro parameter");
return 1;
}
}
} }
else if (token->type != CPP_EOF) else if (token->type == CPP_NAME)
cpp_pedwarn (pfile, {
"ISO C requires whitespace after the macro name"); /* Constraint 6.10.3.5 */
if (!(info->flags & VAR_ARGS) && is__va_args__ (pfile, token))
return 1;
/* It might be worth doing a check here that we aren't a
macro argument, since we don't store the text of macro
arguments. This would reduce "len" and save space. */
}
info->ntokens++;
if (TOKEN_SPELL (token) == SPELL_STRING)
info->len += token->val.str.len;
} }
return save_expansion (pfile, token, first_param, &info); return 0;
} }
/* Returns non-zero if a macro redefinition is trivial. */
static int static int
check_macro_redefinition (pfile, hp, list2) check_macro_redefinition (pfile, hp, list2)
cpp_reader *pfile; cpp_reader *pfile;
...@@ -434,28 +485,31 @@ struct toklist_dummy ...@@ -434,28 +485,31 @@ struct toklist_dummy
reasons. Therefore, this token list cannot be expanded like a reasons. Therefore, this token list cannot be expanded like a
normal token list. Try to do so, and you lose. */ normal token list. Try to do so, and you lose. */
static cpp_toklist * static cpp_toklist *
alloc_macro (pfile, info, ntokens, len) alloc_macro (pfile, info)
cpp_reader *pfile; cpp_reader *pfile;
struct macro_info *info; struct macro_info *info;
unsigned int ntokens, len;
{ {
unsigned int size; unsigned int size;
struct toklist_dummy *dummy; struct toklist_dummy *dummy;
cpp_toklist *list; cpp_toklist *list;
/* Empty macros become a single placemarker token. */
if (info->ntokens == 0)
info->ntokens = 1;
size = sizeof (struct toklist_dummy); size = sizeof (struct toklist_dummy);
size += (ntokens - 1) * sizeof(cpp_token); size += (info->ntokens - 1) * sizeof(cpp_token);
size += len + info->paramlen; size += info->len + info->paramlen;
dummy = (struct toklist_dummy *) xmalloc (size); dummy = (struct toklist_dummy *) xmalloc (size);
list = (cpp_toklist *) dummy; list = (cpp_toklist *) dummy;
/* Initialize the monster. */ /* Initialize the monster. */
list->tokens = &dummy->first_token; list->tokens = &dummy->first_token;
list->tokens_used = list->tokens_cap = ntokens; list->tokens_used = list->tokens_cap = info->ntokens;
list->namebuf = (unsigned char *) &list->tokens[ntokens]; list->namebuf = (unsigned char *) &list->tokens[info->ntokens];
list->name_used = list->name_cap = len + info->paramlen; list->name_used = list->name_cap = info->len + info->paramlen;
list->directive = 0; list->directive = 0;
list->line = pfile->token_list.line; list->line = pfile->token_list.line;
...@@ -467,96 +521,32 @@ alloc_macro (pfile, info, ntokens, len) ...@@ -467,96 +521,32 @@ alloc_macro (pfile, info, ntokens, len)
return list; return list;
} }
/* Free a macro allocated by allocate_macro. */ /* Copy the tokens of the expansion, beginning with info->first until
static void CPP_EOF. INFO contains information about the macro.
free_macro (list)
const cpp_toklist *list;
{
free ((PTR) list);
}
/* Copy the tokens of the expansion, beginning with FIRST until
CPP_EOF. For a function-like macro, FIRST_PARAM points to the
first parameter. INFO contains information about the macro.
Change the type of macro arguments in the expansion from CPP_NAME Change the type of macro arguments in the expansion from CPP_NAME
to CPP_MACRO_ARG. Remove #'s that represent stringification, to CPP_MACRO_ARG. Remove #'s that represent stringification,
flagging the CPP_MACRO_ARG it operates on STRINGIFY. Remove ##'s, flagging the CPP_MACRO_ARG it operates on STRINGIFY. Remove ##'s,
flagging the token on its immediate left PASTE_LEFT. Returns the flagging the token on its immediate left PASTE_LEFT. Returns the
token list for the macro expansion, or 0 on error. */ token list for the macro expansion. */
static const cpp_toklist * static const cpp_toklist *
save_expansion (pfile, first, first_param, info) save_expansion (pfile, info)
cpp_reader *pfile; cpp_reader *pfile;
const cpp_token *first;
const cpp_token *first_param;
struct macro_info *info; struct macro_info *info;
{ {
const cpp_token *token; const cpp_token *token;
cpp_toklist *list; cpp_toklist *list;
cpp_token *dest; cpp_token *dest;
unsigned int len, ntokens;
unsigned char *buf; unsigned char *buf;
/* Count tokens in expansion. We drop paste tokens, and stringize list = alloc_macro (pfile, info);
tokens, so don't count them. */
ntokens = len = 0;
for (token = first; token->type != CPP_EOF; token++)
{
if (token->type == CPP_PASTE)
{
/* Token-paste ##, can appear in both object-like and
function-like macros, but not at the ends. Constraint
6.10.3.3.1 */
if (token == first || token[1].type == CPP_EOF)
{
cpp_error_with_line (pfile, token->line, token->col,
"'##' cannot appear at either end of a macro expansion");
return 0;
}
continue;
}
else if (token->type == CPP_HASH)
{
/* Stringifying #, but a normal character in object-like
macros. Must come before a parameter name. Constraint
6.10.3.2.1. */
if (info->paramc >= 0)
{
if (token[1].type == CPP_NAME
&& find_param (first_param, token + 1))
continue;
if (! CPP_OPTION (pfile, lang_asm))
{
cpp_error_with_line (pfile, token->line, token->col,
"'#' is not followed by a macro parameter");
return 0;
}
}
}
else if (token->type == CPP_NAME)
{
/* Constraint 6.10.3.5 */
if (!(info->flags & VAR_ARGS) && is__va_args__ (pfile, token))
return 0;
/* It might be worth doing a check here that we aren't a
macro argument, since we don't store the text of macro
arguments. This would reduce "len" and save space. */
}
ntokens++;
if (TOKEN_SPELL (token) == SPELL_STRING)
len += token->val.str.len;
}
if (ntokens == 0)
ntokens++;
list = alloc_macro (pfile, info, ntokens, len);
buf = list->namebuf; buf = list->namebuf;
/* Store the null-terminated parameter spellings of a macro, to /* Store the null-terminated parameter spellings of a macro, to
provide pedantic warnings to satisfy 6.10.3.2, or for use when provide pedantic warnings to satisfy 6.10.3.2, or for use when
dumping macro definitions. They must go first. */ dumping macro definitions. They must go first. */
if (list->params_len) if (list->params_len)
for (token = first_param; token < first; token++) for (token = info->first_param; token < info->first; token++)
if (token->type == CPP_NAME) if (token->type == CPP_NAME)
{ {
/* Copy null too. */ /* Copy null too. */
...@@ -565,7 +555,7 @@ save_expansion (pfile, first, first_param, info) ...@@ -565,7 +555,7 @@ save_expansion (pfile, first, first_param, info)
} }
dest = list->tokens; dest = list->tokens;
for (token = first; token->type != CPP_EOF; token++) for (token = info->first; token->type != CPP_EOF; token++)
{ {
unsigned int param_no; unsigned int param_no;
...@@ -576,7 +566,7 @@ save_expansion (pfile, first, first_param, info) ...@@ -576,7 +566,7 @@ save_expansion (pfile, first, first_param, info)
break; break;
/* Check if the name is a macro parameter. */ /* Check if the name is a macro parameter. */
param_no = find_param (first_param, token); param_no = find_param (info->first_param, token);
if (param_no == 0) if (param_no == 0)
break; break;
dest->val.aux = param_no - 1; dest->val.aux = param_no - 1;
...@@ -596,7 +586,7 @@ save_expansion (pfile, first, first_param, info) ...@@ -596,7 +586,7 @@ save_expansion (pfile, first, first_param, info)
case CPP_HASH: case CPP_HASH:
/* Stringifying #. Constraint 6.10.3.2.1 */ /* Stringifying #. Constraint 6.10.3.2.1 */
if (list->paramc >= 0 && token[1].type == CPP_NAME if (list->paramc >= 0 && token[1].type == CPP_NAME
&& find_param (first_param, token + 1)) && find_param (info->first_param, token + 1))
continue; continue;
break; break;
...@@ -615,6 +605,7 @@ save_expansion (pfile, first, first_param, info) ...@@ -615,6 +605,7 @@ save_expansion (pfile, first, first_param, info)
dest++; dest++;
} }
/* Empty macros become a single placemarker token. */
if (dest == list->tokens) if (dest == list->tokens)
{ {
dest->type = CPP_PLACEMARKER; dest->type = CPP_PLACEMARKER;
...@@ -624,16 +615,18 @@ save_expansion (pfile, first, first_param, info) ...@@ -624,16 +615,18 @@ save_expansion (pfile, first, first_param, info)
return list; return list;
} }
/* Parse a macro and save its expansion. Returns non-zero on success. */
int int
_cpp_create_definition (pfile, hp) _cpp_create_definition (pfile, hp)
cpp_reader *pfile; cpp_reader *pfile;
cpp_hashnode *hp; cpp_hashnode *hp;
{ {
struct macro_info info;
const cpp_toklist *list; const cpp_toklist *list;
list = parse_define (pfile); if (parse_define (pfile, &info))
if (!list)
return 0; return 0;
list = save_expansion (pfile, &info);
/* Check for a redefinition. Redefinition of a macro is allowed if /* Check for a redefinition. Redefinition of a macro is allowed if
and only if the old and new definitions are the same. and only if the old and new definitions are the same.
......
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