Commit 2964d54f by Neil Booth Committed by Neil Booth

cpphash.h: (TOKEN_SPELL) Pulled from cpplex.c.

	* cpphash.h: (TOKEN_SPELL) Pulled from cpplex.c.
	* cpplex.c (TOKEN_SPELL) Move to cpphash.h.

	* cpphash.c: (struct macro_info, alloc_macro, free_macro,
	struct toklist_dummy): New.
	(cpp_free_definition): Free macros with free_macro.
	(count_params): Don't save paramter spellings.  Save macro
	information in a struct macro_info.
	(parse_define): Don't allocate a token list.
	(save_expansion): Allocate the macro's token list, and
	save parameter spellings if necessary.  Use TOKEN_SPELL.
	(cpp_create_definition): Make list const.

From-SVN: r34985
parent b9161f44
2000-07-12 Neil Booth <NeilB@earthling.net>
* cpphash.h: (TOKEN_SPELL) Pulled from cpplex.c.
* cpplex.c (TOKEN_SPELL) Move to cpphash.h.
* cpphash.c: (struct macro_info, alloc_macro, free_macro,
struct toklist_dummy): New.
(cpp_free_definition): Free macros with free_macro.
(count_params): Don't save paramter spellings. Save macro
information in a struct macro_info.
(parse_define): Don't allocate a token list.
(save_expansion): Allocate the macro's token list, and
save parameter spellings if necessary. Use TOKEN_SPELL.
(cpp_create_definition): Make list const.
2000-07-12 Gabriel Dos Reis <gdr@codesourcery.com> 2000-07-12 Gabriel Dos Reis <gdr@codesourcery.com>
* c-typeck.c (pedwarn_c99): Move to * c-typeck.c (pedwarn_c99): Move to
......
...@@ -40,6 +40,14 @@ struct hashdummy ...@@ -40,6 +40,14 @@ struct hashdummy
unsigned short length; unsigned short length;
}; };
/* Stores basic information about a macro, before it is allocated. */
struct macro_info
{
unsigned int paramlen;
signed short paramc;
unsigned char flags;
};
/* Initial hash table size. (It can grow if necessary - see hashtab.c.) */ /* Initial hash table size. (It can grow if necessary - see hashtab.c.) */
#define HASHSIZE 500 #define HASHSIZE 500
...@@ -51,15 +59,21 @@ static void dump_funlike_macro PARAMS ((cpp_reader *, cpp_hashnode *)); ...@@ -51,15 +59,21 @@ static void dump_funlike_macro PARAMS ((cpp_reader *, cpp_hashnode *));
static const cpp_token *count_params PARAMS ((cpp_reader *, static const cpp_token *count_params PARAMS ((cpp_reader *,
const cpp_token *, const cpp_token *,
cpp_toklist *)); 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 cpp_toklist *parse_define PARAMS((cpp_reader *)); static const cpp_toklist * parse_define PARAMS((cpp_reader *));
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 int save_expansion PARAMS((cpp_reader *, cpp_toklist *, static const cpp_toklist * save_expansion PARAMS((cpp_reader *,
const cpp_token *, const cpp_token *)); const cpp_token *,
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 *,
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
...@@ -170,7 +184,7 @@ _cpp_free_definition (h) ...@@ -170,7 +184,7 @@ _cpp_free_definition (h)
cpp_hashnode *h; cpp_hashnode *h;
{ {
if (h->type == T_MACRO) if (h->type == T_MACRO)
_cpp_free_toklist (h->value.expansion); free_macro (h->value.expansion);
h->value.expansion = NULL; h->value.expansion = NULL;
} }
...@@ -212,20 +226,23 @@ is__va_args__ (pfile, token) ...@@ -212,20 +226,23 @@ is__va_args__ (pfile, token)
return 1; return 1;
} }
/* Counts the parameters to a function like macro, and saves their /* Counts the parameters to a function-like macro, the length of their
spellings if necessary. Returns the token that we stopped scanning null-terminated names, and whether the macro is a variable-argument
at; if it's type isn't CPP_CLOSE_PAREN there was an error, which one. FIRST is the token immediately after the open parenthesis,
has been reported. */ INFO stores the data, and should have paramlen and flags zero.
Returns the token that we stopped scanning at; if it's type isn't
CPP_CLOSE_PAREN there was an error, which has been reported. */
static const cpp_token * static const cpp_token *
count_params (pfile, first, list) count_params (pfile, first, info)
cpp_reader *pfile; cpp_reader *pfile;
const cpp_token *first; const cpp_token *first;
cpp_toklist *list; struct macro_info *info;
{ {
unsigned int params_len = 0, prev_ident = 0; unsigned int prev_ident = 0;
const cpp_token *token, *temp; const cpp_token *token;
list->paramc = 0; info->paramc = 0;
for (token = first;; token++) for (token = first;; token++)
{ {
switch (token->type) switch (token->type)
...@@ -251,10 +268,6 @@ count_params (pfile, first, list) ...@@ -251,10 +268,6 @@ count_params (pfile, first, list)
if (is__va_args__ (pfile, token)) if (is__va_args__ (pfile, token))
goto out; goto out;
params_len += token->val.node->length + 1;
prev_ident = 1;
list->paramc++;
/* Constraint 6.10.3.6 - duplicate parameter names. */ /* Constraint 6.10.3.6 - duplicate parameter names. */
if (find_param (first, token)) if (find_param (first, token))
{ {
...@@ -263,6 +276,11 @@ count_params (pfile, first, list) ...@@ -263,6 +276,11 @@ count_params (pfile, first, list)
token->val.node->name); token->val.node->name);
goto out; goto out;
} }
prev_ident = 1;
info->paramc++;
if (pfile->save_parameter_spellings)
info->paramlen += token->val.node->length + 1;
break; break;
default: default:
...@@ -271,8 +289,8 @@ count_params (pfile, first, list) ...@@ -271,8 +289,8 @@ count_params (pfile, first, list)
goto out; goto out;
case CPP_CLOSE_PAREN: case CPP_CLOSE_PAREN:
if (prev_ident || list->paramc == 0) if (prev_ident || info->paramc == 0)
goto scanned; goto out;
/* Fall through to pick up the error. */ /* Fall through to pick up the error. */
case CPP_COMMA: case CPP_COMMA:
...@@ -297,8 +315,10 @@ count_params (pfile, first, list) ...@@ -297,8 +315,10 @@ count_params (pfile, first, list)
tok->type = CPP_NAME; tok->type = CPP_NAME;
tok->val.node = pfile->spec_nodes->n__VA_ARGS__; tok->val.node = pfile->spec_nodes->n__VA_ARGS__;
list->paramc++;
params_len += tok->val.node->length + 1; info->paramc++;
if (pfile->save_parameter_spellings)
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,
...@@ -306,51 +326,31 @@ count_params (pfile, first, list) ...@@ -306,51 +326,31 @@ count_params (pfile, first, list)
} }
else else
{ {
list->flags |= GNU_REST_ARGS; info->flags |= GNU_REST_ARGS;
if (CPP_PEDANTIC (pfile)) if (CPP_PEDANTIC (pfile))
cpp_pedwarn (pfile, cpp_pedwarn (pfile,
"ISO C does not permit named varargs parameters"); "ISO C does not permit named varargs parameters");
} }
list->flags |= VAR_ARGS; info->flags |= VAR_ARGS;
token++; token++;
if (token->type == CPP_CLOSE_PAREN) if (token->type == CPP_CLOSE_PAREN)
goto scanned; goto out;
goto missing_paren; goto missing_paren;
} }
} }
scanned:
/* Store the null-terminated parameter spellings of a function, to
provide pedantic warnings to satisfy 6.10.3.2, or for use when
dumping macro definitions. */
if (list->paramc > 0 && pfile->save_parameter_spellings)
{
U_CHAR *buf;
_cpp_reserve_name_space (list, params_len);
list->params_len = list->name_used = params_len;
buf = list->namebuf;
for (temp = first; temp <= token; temp++)
if (temp->type == CPP_NAME)
{
/* copy null too */
memcpy (buf, temp->val.node->name, temp->val.node->length + 1);
buf += temp->val.node->length + 1;
}
}
out: out:
return token; return token;
} }
/* Parses a #define directive. Returns null pointer on error. */ /* Parses a #define directive. Returns null pointer on error. */
static cpp_toklist * static const cpp_toklist *
parse_define (pfile) parse_define (pfile)
cpp_reader *pfile; cpp_reader *pfile;
{ {
const cpp_token *token, *first_param; const cpp_token *token, *first_param;
cpp_toklist *list; 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. */
...@@ -362,20 +362,20 @@ parse_define (pfile) ...@@ -362,20 +362,20 @@ parse_define (pfile)
while (token->type == CPP_COMMENT) while (token->type == CPP_COMMENT)
token++, prev_white = 1; token++, prev_white = 1;
/* Allocate the expansion's list. It will go in the hash table. */
list = (cpp_toklist *) xmalloc (sizeof (cpp_toklist));
_cpp_init_toklist (list, 0);
first_param = token + 1; first_param = token + 1;
list->paramc = -1; /* Object-like macro. */
/* Assume object-like macro. */
info.paramc = -1;
info.paramlen = 0;
info.flags = 0;
if (!prev_white && !(token->flags & PREV_WHITE)) if (!prev_white && !(token->flags & PREV_WHITE))
{ {
if (token->type == CPP_OPEN_PAREN) if (token->type == CPP_OPEN_PAREN)
{ {
token = count_params (pfile, first_param, list); token = count_params (pfile, first_param, &info);
if (token->type != CPP_CLOSE_PAREN) if (token->type != CPP_CLOSE_PAREN)
goto error; return 0;
token++; token++;
} }
else if (token->type != CPP_EOF) else if (token->type != CPP_EOF)
...@@ -383,14 +383,7 @@ parse_define (pfile) ...@@ -383,14 +383,7 @@ parse_define (pfile)
"ISO C requires whitespace after the macro name"); "ISO C requires whitespace after the macro name");
} }
if (save_expansion (pfile, list, token, first_param)) return save_expansion (pfile, token, first_param, &info);
{
error:
_cpp_free_toklist (list);
list = 0;
}
return list;
} }
static int static int
...@@ -422,19 +415,82 @@ check_macro_redefinition (pfile, hp, list2) ...@@ -422,19 +415,82 @@ check_macro_redefinition (pfile, hp, list2)
return 1; return 1;
} }
/* Copy the tokens of the expansion. Change the type of macro /* This is a dummy structure whose only purpose is getting alignment
arguments from CPP_NAME to CPP_MACRO_ARG. Remove #'s that correct. */
represent stringification, flagging the CPP_MACRO_ARG it operates struct toklist_dummy
on STRINGIFY. Remove ##'s, flagging the token on its immediate {
left PASTE_LEFT. Returns non-zero on error. */ cpp_toklist list;
static int cpp_token first_token;
save_expansion (pfile, list, first, first_param) };
/* Allocate space to hold the token list, its tokens, their text, and
the parameter names if needed. Empty expansions are stored as a
single placemarker token.
These are all allocated in a block together for performance
reasons. Therefore, this token list cannot be expanded like a
normal token list. Try to do so, and you lose. */
static cpp_toklist *
alloc_macro (pfile, info, ntokens, len)
cpp_reader *pfile;
struct macro_info *info;
unsigned int ntokens, len;
{
unsigned int size;
struct toklist_dummy *dummy;
cpp_toklist *list;
size = sizeof (struct toklist_dummy);
size += (ntokens - 1) * sizeof(cpp_token);
size += len + info->paramlen;
dummy = (struct toklist_dummy *) xmalloc (size);
list = (cpp_toklist *) dummy;
/* Initialize the monster. */
list->tokens = &dummy->first_token;
list->tokens_used = list->tokens_cap = ntokens;
list->namebuf = (unsigned char *) &list->tokens[ntokens];
list->name_used = list->name_cap = len + info->paramlen;
list->directive = 0;
list->line = pfile->token_list.line;
list->file = pfile->token_list.file;
list->params_len = info->paramlen;
list->paramc = info->paramc;
list->flags = info->flags;
return list;
}
/* Free a macro allocated by allocate_macro. */
static void
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
to CPP_MACRO_ARG. Remove #'s that represent stringification,
flagging the CPP_MACRO_ARG it operates on STRINGIFY. Remove ##'s,
flagging the token on its immediate left PASTE_LEFT. Returns the
token list for the macro expansion, or 0 on error. */
static const cpp_toklist *
save_expansion (pfile, first, first_param, info)
cpp_reader *pfile; cpp_reader *pfile;
cpp_toklist *list;
const cpp_token *first; const cpp_token *first;
const cpp_token *first_param; const cpp_token *first_param;
struct macro_info *info;
{ {
const cpp_token *token; const cpp_token *token;
cpp_toklist *list;
cpp_token *dest; cpp_token *dest;
unsigned int len, ntokens; unsigned int len, ntokens;
unsigned char *buf; unsigned char *buf;
...@@ -462,7 +518,7 @@ save_expansion (pfile, list, first, first_param) ...@@ -462,7 +518,7 @@ save_expansion (pfile, list, first, first_param)
{ {
/* Stringifying #, but is a normal character if traditional, /* Stringifying #, but is a normal character if traditional,
or in object-like macros. Constraint 6.10.3.2.1. */ or in object-like macros. Constraint 6.10.3.2.1. */
if (list->paramc >= 0 && ! CPP_TRADITIONAL (pfile)) if (info->paramc >= 0 && ! CPP_TRADITIONAL (pfile))
{ {
if (token[1].type == CPP_NAME if (token[1].type == CPP_NAME
&& find_param (first_param, token + 1)) && find_param (first_param, token + 1))
...@@ -472,31 +528,42 @@ save_expansion (pfile, list, first, first_param) ...@@ -472,31 +528,42 @@ save_expansion (pfile, list, first, first_param)
msg = "'#' is not followed by a macro parameter"; msg = "'#' is not followed by a macro parameter";
error: error:
cpp_error_with_line (pfile, token->line, token->col, msg); cpp_error_with_line (pfile, token->line, token->col, msg);
return 1; return 0;
} }
} }
} }
else if (token->type == CPP_NAME) else if (token->type == CPP_NAME)
{ {
/* Constraint 6.10.3.5 */ /* Constraint 6.10.3.5 */
if (!(list->flags & VAR_ARGS) && is__va_args__ (pfile, token)) if (!(info->flags & VAR_ARGS) && is__va_args__ (pfile, token))
return 1; 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++; ntokens++;
if (token_spellings[token->type].type == SPELL_STRING) if (TOKEN_SPELL (token) == SPELL_STRING)
len += token->val.str.len; len += token->val.str.len;
} }
/* Allocate space to hold the tokens. Empty expansions are stored
as a single placemarker token. */
if (ntokens == 0) if (ntokens == 0)
ntokens++; ntokens++;
_cpp_expand_token_space (list, ntokens); list = alloc_macro (pfile, info, ntokens, len);
if (len > 0) buf = list->namebuf;
_cpp_expand_name_space (list, len);
/* Store the null-terminated parameter spellings of a macro, to
provide pedantic warnings to satisfy 6.10.3.2, or for use when
dumping macro definitions. They must go first. */
if (list->params_len)
for (token = first_param; token < first; token++)
if (token->type == CPP_NAME)
{
/* Copy null too. */
memcpy (buf, token->val.node->name, token->val.node->length + 1);
buf += token->val.node->length + 1;
}
dest = list->tokens; dest = list->tokens;
buf = list->namebuf + list->name_used;
for (token = first; token->type != CPP_EOF; token++) for (token = first; token->type != CPP_EOF; token++)
{ {
unsigned int param_no; unsigned int param_no;
...@@ -543,7 +610,7 @@ save_expansion (pfile, list, first, first_param) ...@@ -543,7 +610,7 @@ save_expansion (pfile, list, first, first_param)
/* Copy the token. */ /* Copy the token. */
*dest = *token; *dest = *token;
if (token_spellings[token->type].type == SPELL_STRING) if (TOKEN_SPELL (token) == SPELL_STRING)
{ {
memcpy (buf, token->val.str.text, token->val.str.len); memcpy (buf, token->val.str.text, token->val.str.len);
dest->val.str.text = buf; dest->val.str.text = buf;
...@@ -558,12 +625,7 @@ save_expansion (pfile, list, first, first_param) ...@@ -558,12 +625,7 @@ save_expansion (pfile, list, first, first_param)
dest->flags = 0; dest->flags = 0;
} }
list->tokens_used = ntokens; return list;
list->line = pfile->token_list.line;
list->file = pfile->token_list.file;
list->name_used = len;
return 0;
} }
int int
...@@ -571,7 +633,7 @@ _cpp_create_definition (pfile, hp) ...@@ -571,7 +633,7 @@ _cpp_create_definition (pfile, hp)
cpp_reader *pfile; cpp_reader *pfile;
cpp_hashnode *hp; cpp_hashnode *hp;
{ {
cpp_toklist *list; const cpp_toklist *list;
list = parse_define (pfile); list = parse_define (pfile);
if (!list) if (!list)
......
...@@ -43,6 +43,7 @@ struct token_spelling ...@@ -43,6 +43,7 @@ struct token_spelling
}; };
extern const struct token_spelling token_spellings[]; extern const struct token_spelling token_spellings[];
#define TOKEN_SPELL(token) (token_spellings[(token)->type].type)
/* Chained list of answers to an assertion. */ /* Chained list of answers to an assertion. */
struct answer struct answer
......
...@@ -139,7 +139,6 @@ static void process_directive PARAMS ((cpp_reader *, const cpp_token *)); ...@@ -139,7 +139,6 @@ static void process_directive PARAMS ((cpp_reader *, const cpp_token *));
/* An upper bound on the number of bytes needed to spell a token, /* An upper bound on the number of bytes needed to spell a token,
including preceding whitespace. */ including preceding whitespace. */
#define TOKEN_SPELL(token) token_spellings[(token)->type].type
#define TOKEN_LEN(token) (5 + (TOKEN_SPELL(token) == SPELL_STRING \ #define TOKEN_LEN(token) (5 + (TOKEN_SPELL(token) == SPELL_STRING \
? (token)->val.str.len \ ? (token)->val.str.len \
: (TOKEN_SPELL(token) == SPELL_IDENT \ : (TOKEN_SPELL(token) == SPELL_IDENT \
......
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