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
This commit is contained in:
parent
b9161f44f0
commit
2964d54fa6
@ -1,3 +1,18 @@
|
||||
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>
|
||||
|
||||
* c-typeck.c (pedwarn_c99): Move to
|
||||
|
240
gcc/cpphash.c
240
gcc/cpphash.c
@ -40,6 +40,14 @@ struct hashdummy
|
||||
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.) */
|
||||
#define HASHSIZE 500
|
||||
|
||||
@ -51,15 +59,21 @@ static void dump_funlike_macro PARAMS ((cpp_reader *, cpp_hashnode *));
|
||||
|
||||
static const cpp_token *count_params PARAMS ((cpp_reader *,
|
||||
const cpp_token *,
|
||||
cpp_toklist *));
|
||||
struct macro_info *));
|
||||
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,
|
||||
const cpp_toklist *));
|
||||
static int save_expansion PARAMS((cpp_reader *, cpp_toklist *,
|
||||
const cpp_token *, const cpp_token *));
|
||||
static const cpp_toklist * save_expansion PARAMS((cpp_reader *,
|
||||
const cpp_token *,
|
||||
const cpp_token *,
|
||||
struct macro_info *));
|
||||
static unsigned int find_param PARAMS ((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. */
|
||||
unsigned int
|
||||
@ -170,7 +184,7 @@ _cpp_free_definition (h)
|
||||
cpp_hashnode *h;
|
||||
{
|
||||
if (h->type == T_MACRO)
|
||||
_cpp_free_toklist (h->value.expansion);
|
||||
free_macro (h->value.expansion);
|
||||
h->value.expansion = NULL;
|
||||
}
|
||||
|
||||
@ -212,20 +226,23 @@ is__va_args__ (pfile, token)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Counts the parameters to a function like macro, and saves their
|
||||
spellings if necessary. 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. */
|
||||
/* Counts the parameters to a function-like macro, the length of their
|
||||
null-terminated names, and whether the macro is a variable-argument
|
||||
one. FIRST is the token immediately after the open parenthesis,
|
||||
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 *
|
||||
count_params (pfile, first, list)
|
||||
count_params (pfile, first, info)
|
||||
cpp_reader *pfile;
|
||||
const cpp_token *first;
|
||||
cpp_toklist *list;
|
||||
struct macro_info *info;
|
||||
{
|
||||
unsigned int params_len = 0, prev_ident = 0;
|
||||
const cpp_token *token, *temp;
|
||||
unsigned int prev_ident = 0;
|
||||
const cpp_token *token;
|
||||
|
||||
list->paramc = 0;
|
||||
info->paramc = 0;
|
||||
for (token = first;; token++)
|
||||
{
|
||||
switch (token->type)
|
||||
@ -251,10 +268,6 @@ count_params (pfile, first, list)
|
||||
if (is__va_args__ (pfile, token))
|
||||
goto out;
|
||||
|
||||
params_len += token->val.node->length + 1;
|
||||
prev_ident = 1;
|
||||
list->paramc++;
|
||||
|
||||
/* Constraint 6.10.3.6 - duplicate parameter names. */
|
||||
if (find_param (first, token))
|
||||
{
|
||||
@ -263,6 +276,11 @@ count_params (pfile, first, list)
|
||||
token->val.node->name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
prev_ident = 1;
|
||||
info->paramc++;
|
||||
if (pfile->save_parameter_spellings)
|
||||
info->paramlen += token->val.node->length + 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -271,8 +289,8 @@ count_params (pfile, first, list)
|
||||
goto out;
|
||||
|
||||
case CPP_CLOSE_PAREN:
|
||||
if (prev_ident || list->paramc == 0)
|
||||
goto scanned;
|
||||
if (prev_ident || info->paramc == 0)
|
||||
goto out;
|
||||
|
||||
/* Fall through to pick up the error. */
|
||||
case CPP_COMMA:
|
||||
@ -297,8 +315,10 @@ count_params (pfile, first, list)
|
||||
|
||||
tok->type = CPP_NAME;
|
||||
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))
|
||||
cpp_pedwarn (pfile,
|
||||
@ -306,51 +326,31 @@ count_params (pfile, first, list)
|
||||
}
|
||||
else
|
||||
{
|
||||
list->flags |= GNU_REST_ARGS;
|
||||
info->flags |= GNU_REST_ARGS;
|
||||
if (CPP_PEDANTIC (pfile))
|
||||
cpp_pedwarn (pfile,
|
||||
"ISO C does not permit named varargs parameters");
|
||||
}
|
||||
|
||||
list->flags |= VAR_ARGS;
|
||||
info->flags |= VAR_ARGS;
|
||||
token++;
|
||||
if (token->type == CPP_CLOSE_PAREN)
|
||||
goto scanned;
|
||||
goto out;
|
||||
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:
|
||||
return token;
|
||||
}
|
||||
|
||||
/* Parses a #define directive. Returns null pointer on error. */
|
||||
static cpp_toklist *
|
||||
static const cpp_toklist *
|
||||
parse_define (pfile)
|
||||
cpp_reader *pfile;
|
||||
{
|
||||
const cpp_token *token, *first_param;
|
||||
cpp_toklist *list;
|
||||
struct macro_info info;
|
||||
int prev_white = 0;
|
||||
|
||||
/* The first token after the macro's name. */
|
||||
@ -362,20 +362,20 @@ parse_define (pfile)
|
||||
|
||||
while (token->type == CPP_COMMENT)
|
||||
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;
|
||||
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 (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)
|
||||
goto error;
|
||||
return 0;
|
||||
token++;
|
||||
}
|
||||
else if (token->type != CPP_EOF)
|
||||
@ -383,14 +383,7 @@ parse_define (pfile)
|
||||
"ISO C requires whitespace after the macro name");
|
||||
}
|
||||
|
||||
if (save_expansion (pfile, list, token, first_param))
|
||||
{
|
||||
error:
|
||||
_cpp_free_toklist (list);
|
||||
list = 0;
|
||||
}
|
||||
|
||||
return list;
|
||||
return save_expansion (pfile, token, first_param, &info);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -422,19 +415,82 @@ check_macro_redefinition (pfile, hp, list2)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Copy the tokens of the expansion. Change the type of macro
|
||||
arguments 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 non-zero on error. */
|
||||
static int
|
||||
save_expansion (pfile, list, first, first_param)
|
||||
/* This is a dummy structure whose only purpose is getting alignment
|
||||
correct. */
|
||||
struct toklist_dummy
|
||||
{
|
||||
cpp_toklist list;
|
||||
cpp_token first_token;
|
||||
};
|
||||
|
||||
|
||||
/* 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_toklist *list;
|
||||
const cpp_token *first;
|
||||
const cpp_token *first_param;
|
||||
struct macro_info *info;
|
||||
{
|
||||
const cpp_token *token;
|
||||
cpp_toklist *list;
|
||||
cpp_token *dest;
|
||||
unsigned int len, ntokens;
|
||||
unsigned char *buf;
|
||||
@ -462,7 +518,7 @@ save_expansion (pfile, list, first, first_param)
|
||||
{
|
||||
/* Stringifying #, but is a normal character if traditional,
|
||||
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
|
||||
&& find_param (first_param, token + 1))
|
||||
@ -472,31 +528,42 @@ save_expansion (pfile, list, first, first_param)
|
||||
msg = "'#' is not followed by a macro parameter";
|
||||
error:
|
||||
cpp_error_with_line (pfile, token->line, token->col, msg);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (token->type == CPP_NAME)
|
||||
{
|
||||
/* Constraint 6.10.3.5 */
|
||||
if (!(list->flags & VAR_ARGS) && is__va_args__ (pfile, token))
|
||||
return 1;
|
||||
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_spellings[token->type].type == SPELL_STRING)
|
||||
if (TOKEN_SPELL (token) == SPELL_STRING)
|
||||
len += token->val.str.len;
|
||||
}
|
||||
|
||||
/* Allocate space to hold the tokens. Empty expansions are stored
|
||||
as a single placemarker token. */
|
||||
if (ntokens == 0)
|
||||
ntokens++;
|
||||
_cpp_expand_token_space (list, ntokens);
|
||||
if (len > 0)
|
||||
_cpp_expand_name_space (list, len);
|
||||
list = alloc_macro (pfile, info, ntokens, len);
|
||||
buf = list->namebuf;
|
||||
|
||||
/* 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;
|
||||
buf = list->namebuf + list->name_used;
|
||||
for (token = first; token->type != CPP_EOF; token++)
|
||||
{
|
||||
unsigned int param_no;
|
||||
@ -543,7 +610,7 @@ save_expansion (pfile, list, first, first_param)
|
||||
|
||||
/* Copy the 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);
|
||||
dest->val.str.text = buf;
|
||||
@ -558,12 +625,7 @@ save_expansion (pfile, list, first, first_param)
|
||||
dest->flags = 0;
|
||||
}
|
||||
|
||||
list->tokens_used = ntokens;
|
||||
list->line = pfile->token_list.line;
|
||||
list->file = pfile->token_list.file;
|
||||
list->name_used = len;
|
||||
|
||||
return 0;
|
||||
return list;
|
||||
}
|
||||
|
||||
int
|
||||
@ -571,7 +633,7 @@ _cpp_create_definition (pfile, hp)
|
||||
cpp_reader *pfile;
|
||||
cpp_hashnode *hp;
|
||||
{
|
||||
cpp_toklist *list;
|
||||
const cpp_toklist *list;
|
||||
|
||||
list = parse_define (pfile);
|
||||
if (!list)
|
||||
|
@ -43,6 +43,7 @@ struct token_spelling
|
||||
};
|
||||
|
||||
extern const struct token_spelling token_spellings[];
|
||||
#define TOKEN_SPELL(token) (token_spellings[(token)->type].type)
|
||||
|
||||
/* Chained list of answers to an assertion. */
|
||||
struct answer
|
||||
|
@ -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,
|
||||
including preceding whitespace. */
|
||||
#define TOKEN_SPELL(token) token_spellings[(token)->type].type
|
||||
#define TOKEN_LEN(token) (5 + (TOKEN_SPELL(token) == SPELL_STRING \
|
||||
? (token)->val.str.len \
|
||||
: (TOKEN_SPELL(token) == SPELL_IDENT \
|
||||
|
Loading…
Reference in New Issue
Block a user