cpphash.h (struct _cpp_buff, [...]): New.

* cpphash.h (struct _cpp_buff, _cpp_get_buff, _cpp_release_buff,
	_cpp_extend_buff, _cpp_free_buff): New.
	(struct cpp_reader): New member free_buffs.
	* cppinit.c (cpp_destroy): Free buffers.
	* cpplex.c (new_buff, _cpp_release_buff, _cpp_get_buff,
	_cpp_extend_buff, _cpp_free_buff): New.
	* cpplib.h (struct cpp_options): Remove unused member.
	* cppmacro.c (collect_args): New.  Combines the old parse_arg
	and parse_args.  Use _cpp_buff for memory allocation.
	(funlike_invocation_p, replace_args): Update.

From-SVN: r45827
This commit is contained in:
Neil Booth 2001-09-26 17:52:50 +00:00 committed by Neil Booth
parent 9c383523a3
commit b8af0ca5c7
6 changed files with 250 additions and 120 deletions

View File

@ -1,3 +1,16 @@
2001-09-26 Neil Booth <neil@daikokuya.demon.co.uk>
* cpphash.h (struct _cpp_buff, _cpp_get_buff, _cpp_release_buff,
_cpp_extend_buff, _cpp_free_buff): New.
(struct cpp_reader): New member free_buffs.
* cppinit.c (cpp_destroy): Free buffers.
* cpplex.c (new_buff, _cpp_release_buff, _cpp_get_buff,
_cpp_extend_buff, _cpp_free_buff): New.
* cpplib.h (struct cpp_options): Remove unused member.
* cppmacro.c (collect_args): New. Combines the old parse_arg
and parse_args. Use _cpp_buff for memory allocation.
(funlike_invocation_p, replace_args): Update.
Wed Sep 26 13:20:51 CEST 2001 Jan Hubicka <jh@suse.cz>
* final.c (final_scan_insn): Use delete_insn instead of delete_note.

View File

@ -72,6 +72,21 @@ struct cpp_pool
unsigned int locks;
};
/* A generic memory buffer. */
typedef struct _cpp_buff _cpp_buff;
struct _cpp_buff
{
struct _cpp_buff *next;
char *base, *cur, *limit;
};
extern _cpp_buff *_cpp_get_buff PARAMS ((cpp_reader *, unsigned int));
extern void _cpp_release_buff PARAMS ((cpp_reader *, _cpp_buff *));
extern _cpp_buff *_cpp_extend_buff PARAMS ((cpp_reader *, _cpp_buff *,
unsigned int));
extern void _cpp_free_buff PARAMS ((_cpp_buff *));
/* List of directories to look for include files in. */
struct search_path
{
@ -254,6 +269,9 @@ struct cpp_reader
cpp_pool macro_pool; /* For macro definitions. Permanent. */
cpp_pool argument_pool; /* For macro arguments. Temporary. */
/* Memory buffers. */
_cpp_buff *free_buffs;
/* Context stack. */
struct cpp_context base_context;
struct cpp_context *context;

View File

@ -591,6 +591,7 @@ cpp_destroy (pfile)
_cpp_free_pool (&pfile->ident_pool);
_cpp_free_pool (&pfile->macro_pool);
_cpp_free_pool (&pfile->argument_pool);
_cpp_free_buff (pfile->free_buffs);
for (run = &pfile->base_run; run; run = runn)
{

View File

@ -107,6 +107,7 @@ static tokenrun *next_tokenrun PARAMS ((tokenrun *));
static cpp_chunk *new_chunk PARAMS ((unsigned int));
static int chunk_suitable PARAMS ((cpp_pool *, cpp_chunk *, unsigned int));
static unsigned int hex_digit_value PARAMS ((unsigned int));
static _cpp_buff *new_buff PARAMS ((unsigned int));
/* Utility routine:
@ -2114,7 +2115,7 @@ cpp_interpret_charconst (pfile, token, warn_multi, traditional, pchars_seen)
return result;
}
/* Memory pools. */
/* Memory buffers. */
struct dummy
{
@ -2127,6 +2128,95 @@ struct dummy
};
#define DEFAULT_ALIGNMENT (offsetof (struct dummy, u))
#define CPP_ALIGN(size, align) (((size) + ((align) - 1)) & ~((align) - 1))
/* Create a new allocation buffer. */
static _cpp_buff *
new_buff (len)
unsigned int len;
{
_cpp_buff *result;
char *base;
if (len < 4000)
len = 4000;
len = CPP_ALIGN (len, DEFAULT_ALIGNMENT);
base = xmalloc (len + sizeof (_cpp_buff));
result = (_cpp_buff *) (base + len);
result->base = base;
result->cur = base;
result->limit = base + len;
result->next = NULL;
return result;
}
/* Place a chain of unwanted allocation buffers on the free list. */
void
_cpp_release_buff (pfile, buff)
cpp_reader *pfile;
_cpp_buff *buff;
{
_cpp_buff *end = buff;
while (end->next)
end = end->next;
end->next = pfile->free_buffs;
pfile->free_buffs = buff;
}
/* Return a free buffer of size at least MIN_SIZE. */
_cpp_buff *
_cpp_get_buff (pfile, min_size)
cpp_reader *pfile;
unsigned int min_size;
{
_cpp_buff *result, **p;
for (p = &pfile->free_buffs;; p = &(*p)->next)
{
if (*p == NULL || (*p)->next == NULL)
return new_buff (min_size);
result = (*p)->next;
if ((unsigned int) (result->limit - result->base) > min_size)
break;
}
*p = result->next;
result->next = NULL;
result->cur = result->base;
return result;
}
/* Return a buffer chained on the end of BUFF. Copy to it the
uncommitted remaining bytes of BUFF, with at least MIN_EXTRA more
bytes. */
_cpp_buff *
_cpp_extend_buff (pfile, buff, min_extra)
cpp_reader *pfile;
_cpp_buff *buff;
unsigned int min_extra;
{
unsigned int size = min_extra + (buff->limit - buff->cur) * 2;
buff->next = _cpp_get_buff (pfile, size);
memcpy (buff->next->base, buff->cur, buff->limit - buff->cur);
return buff->next;
}
/* Free a chain of buffers starting at BUFF. */
void
_cpp_free_buff (buff)
_cpp_buff *buff;
{
_cpp_buff *next;
for (; buff; buff = next)
{
next = buff->next;
free (buff->base);
}
}
static int
chunk_suitable (pool, chunk, size)

View File

@ -236,9 +236,6 @@ struct cpp_options
/* The language we're preprocessing. */
enum c_lang lang;
/* Nonzero means to return spacing characters for stand-alone CPP. */
unsigned char spacing;
/* Non-0 means -v, so print the full set of include dirs. */
unsigned char verbose;

View File

@ -62,8 +62,7 @@ static void push_token_context
PARAMS ((cpp_reader *, cpp_macro *, const cpp_token *, unsigned int));
static void push_ptoken_context
PARAMS ((cpp_reader *, cpp_macro *, const cpp_token **, unsigned int));
static enum cpp_ttype parse_arg PARAMS ((cpp_reader *, macro_arg *, int));
static macro_arg *parse_args PARAMS ((cpp_reader *, const cpp_hashnode *));
static _cpp_buff *collect_args PARAMS ((cpp_reader *, const cpp_hashnode *));
static cpp_context *next_context PARAMS ((cpp_reader *));
static const cpp_token *padding_token
PARAMS ((cpp_reader *, const cpp_token *));
@ -461,116 +460,131 @@ paste_all_tokens (pfile, lhs)
push_token_context (pfile, NULL, pasted, 1);
}
/* Reads the unexpanded tokens of a macro argument into ARG. VAR_ARGS
is non-zero if this is a variadic macro. Returns the type of the
token that caused reading to finish. */
static enum cpp_ttype
parse_arg (pfile, arg, variadic)
cpp_reader *pfile;
struct macro_arg *arg;
int variadic;
{
enum cpp_ttype result;
unsigned int paren = 0;
arg->first = (const cpp_token **) POOL_FRONT (&pfile->argument_pool);
for (;; arg->count++)
{
const cpp_token *token;
const cpp_token **ptoken = &arg->first[arg->count];
if ((unsigned char *) (ptoken + 2) >= POOL_LIMIT (&pfile->argument_pool))
{
_cpp_next_chunk (&pfile->argument_pool, 2 * sizeof (cpp_token *),
(unsigned char **) &arg->first);
ptoken = &arg->first[arg->count];
}
/* Drop leading padding. */
do
token = cpp_get_token (pfile);
while (arg->count == 0 && token->type == CPP_PADDING);
*ptoken++ = token;
result = token->type;
if (result == CPP_OPEN_PAREN)
paren++;
else if (result == CPP_CLOSE_PAREN && paren-- == 0)
break;
/* Commas are not terminators within parantheses or variadic. */
else if (result == CPP_COMMA && paren == 0 && !variadic)
break;
else if (result == CPP_EOF)
{
/* We still need the EOF (added below) to end pre-expansion
and directives. */
if (pfile->context->prev || pfile->state.in_directive)
_cpp_backup_tokens (pfile, 1);
/* Error reported by caller. */
break;
}
else if (result == CPP_HASH && token->flags & BOL)
{
/* 6.10.3 paragraph 11: If there are sequences of
preprocessing tokens within the list of arguments that
would otherwise act as preprocessing directives, the
behavior is undefined.
This implementation will report a hard error, terminate
the macro invocation, and proceed to process the
directive. */
cpp_error (pfile,
"directives may not be used inside a macro argument");
_cpp_backup_tokens (pfile, 1);
result = CPP_EOF;
break;
}
}
/* Drop trailing padding. */
while (arg->count > 0 && arg->first[arg->count - 1]->type == CPP_PADDING)
arg->count--;
/* Commit the memory used to store the arguments. We make the last
argument a CPP_EOF, so that it terminates macro pre-expansion,
but it is not included in arg->count. */
arg->first[arg->count] = &pfile->eof;
POOL_COMMIT (&pfile->argument_pool, (arg->count + 1) * sizeof (cpp_token *));
return result;
}
/* Parse the arguments making up a macro invocation. */
static macro_arg *
parse_args (pfile, node)
/* Reads and returns the arguments to a function-like macro invocation.
Assumes the opening parenthesis has been processed. If there is an
error, emits an appropriate diagnostic and returns NULL. */
static _cpp_buff *
collect_args (pfile, node)
cpp_reader *pfile;
const cpp_hashnode *node;
{
cpp_macro *macro = node->value.macro;
macro_arg *args, *cur;
enum cpp_ttype type;
int argc, error = 0;
_cpp_buff *buff, *base_buff;
cpp_macro *macro;
macro_arg *args, *arg;
const cpp_token *token;
unsigned int argc;
bool error = false;
/* Allocate room for at least one argument, and zero it out. */
argc = macro->paramc ? macro->paramc: 1;
args = xcnewvec (macro_arg, argc);
macro = node->value.macro;
if (macro->paramc)
argc = macro->paramc;
else
argc = 1;
buff = _cpp_get_buff (pfile, argc * (50 * sizeof (cpp_token *)
+ sizeof (macro_arg)));
base_buff = buff;
args = (macro_arg *) buff->base;
memset (args, 0, argc * sizeof (macro_arg));
buff->cur = (char *) &args[argc];
arg = args, argc = 0;
for (cur = args, argc = 0; ;)
/* Collect the tokens making up each argument. We don't yet know
how many arguments have been supplied, whether too many or too
few. Hence the slightly bizarre usage of "argc" and "arg". */
do
{
unsigned int paren_depth = 0;
unsigned int ntokens = 0;
argc++;
arg->first = (const cpp_token **) buff->cur;
type = parse_arg (pfile, cur, argc == macro->paramc && macro->variadic);
if (type == CPP_CLOSE_PAREN || type == CPP_EOF)
break;
for (;;)
{
/* Require space for 2 new tokens (including a CPP_EOF). */
if ((char *) &arg->first[ntokens + 2] > buff->limit)
{
buff = _cpp_extend_buff (pfile, buff,
1000 * sizeof (cpp_token *));
arg->first = (const cpp_token **) buff->cur;
}
/* Re-use the last argument for excess arguments. */
if (argc < macro->paramc)
cur++;
token = cpp_get_token (pfile);
if (token->type == CPP_PADDING)
{
/* Drop leading padding. */
if (ntokens == 0)
continue;
}
else if (token->type == CPP_OPEN_PAREN)
paren_depth++;
else if (token->type == CPP_CLOSE_PAREN)
{
if (paren_depth-- == 0)
break;
}
else if (token->type == CPP_COMMA)
{
/* A comma does not terminate an argument within
parentheses or as part of a variable argument. */
if (paren_depth == 0
&& ! (macro->variadic && argc == macro->paramc))
break;
}
else if (token->type == CPP_EOF
|| (token->type == CPP_HASH && token->flags & BOL))
break;
arg->first[ntokens++] = token;
}
/* Drop trailing padding. */
while (ntokens > 0 && arg->first[ntokens - 1]->type == CPP_PADDING)
ntokens--;
arg->count = ntokens;
arg->first[ntokens] = &pfile->eof;
/* Terminate the argument. Excess arguments loop back and
overwrite the final legitimate argument, before failing. */
if (argc <= macro->paramc)
{
buff->cur = (char *) &arg->first[ntokens + 1];
if (argc != macro->paramc)
arg++;
}
}
while (token->type != CPP_CLOSE_PAREN
&& token->type != CPP_EOF
&& token->type != CPP_HASH);
if (type == CPP_EOF)
if (token->type == CPP_EOF || token->type == CPP_HASH)
{
bool step_back = false;
/* 6.10.3 paragraph 11: If there are sequences of preprocessing
tokens within the list of arguments that would otherwise act
as preprocessing directives, the behavior is undefined.
This implementation will report a hard error, terminate the
macro invocation, and proceed to process the directive. */
if (token->type == CPP_HASH)
{
cpp_error (pfile,
"directives may not be used inside a macro argument");
step_back = true;
}
else
/* We still need the CPP_EOF to end directives, and to end
pre-expansion of a macro argument. */
step_back = (pfile->context->prev || pfile->state.in_directive);
if (step_back)
_cpp_backup_tokens (pfile, 1);
cpp_error (pfile, "unterminated argument list invoking macro \"%s\"",
NODE_NAME (node));
error = 1;
error = true;
}
else if (argc < macro->paramc)
{
@ -592,28 +606,26 @@ parse_args (pfile, node)
cpp_error (pfile,
"macro \"%s\" requires %u arguments, but only %u given",
NODE_NAME (node), macro->paramc, argc);
error = 1;
error = true;
}
}
else if (argc > macro->paramc)
{
/* Empty argument to a macro taking no arguments is OK. */
if (argc != 1 || cur->count)
if (argc != 1 || arg->count)
{
cpp_error (pfile,
"macro \"%s\" passed %u arguments, but takes just %u",
NODE_NAME (node), argc, macro->paramc);
error = 1;
error = true;
}
}
if (error)
{
free (args);
args = 0;
}
if (!error)
return base_buff;
return args;
_cpp_release_buff (pfile, base_buff);
return NULL;
}
static int
@ -622,7 +634,7 @@ funlike_invocation_p (pfile, node)
const cpp_hashnode *node;
{
const cpp_token *maybe_paren;
macro_arg *args = 0;
_cpp_buff *buff = NULL;
pfile->state.prevent_expansion++;
pfile->keep_tokens++;
@ -634,7 +646,7 @@ funlike_invocation_p (pfile, node)
pfile->state.parsing_args = 2;
if (maybe_paren->type == CPP_OPEN_PAREN)
args = parse_args (pfile, node);
buff = collect_args (pfile, node);
else
{
_cpp_backup_tokens (pfile, 1);
@ -648,14 +660,14 @@ funlike_invocation_p (pfile, node)
pfile->keep_tokens--;
pfile->state.prevent_expansion--;
if (args)
if (buff)
{
if (node->value.macro->paramc > 0)
replace_args (pfile, node->value.macro, args);
free (args);
replace_args (pfile, node->value.macro, (macro_arg *) buff->base);
_cpp_release_buff (pfile, buff);
}
return args != 0;
return buff != 0;
}
/* Push the context of a macro onto the context stack. TOKEN is the
@ -694,8 +706,8 @@ enter_macro_context (pfile, node)
}
/* Take the expansion of a function-like MACRO, replacing parameters
with the actual arguments. Each instance is first macro-expanded,
unless that paramter is operated upon by the # or ## operators. */
with the actual arguments. Each argument is macro-expanded before
replacement, unless operated upon by the # or ## operators. */
static void
replace_args (pfile, macro, args)
cpp_reader *pfile;
@ -904,7 +916,6 @@ expand_arg (pfile, arg)
{
unsigned int capacity;
arg->expanded_count = 0;
if (arg->count == 0)
return;