Commit b8af0ca5 by Neil Booth Committed by Neil Booth

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
parent 9c383523
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> 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. * final.c (final_scan_insn): Use delete_insn instead of delete_note.
......
...@@ -72,6 +72,21 @@ struct cpp_pool ...@@ -72,6 +72,21 @@ struct cpp_pool
unsigned int locks; 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. */ /* List of directories to look for include files in. */
struct search_path struct search_path
{ {
...@@ -254,6 +269,9 @@ struct cpp_reader ...@@ -254,6 +269,9 @@ struct cpp_reader
cpp_pool macro_pool; /* For macro definitions. Permanent. */ cpp_pool macro_pool; /* For macro definitions. Permanent. */
cpp_pool argument_pool; /* For macro arguments. Temporary. */ cpp_pool argument_pool; /* For macro arguments. Temporary. */
/* Memory buffers. */
_cpp_buff *free_buffs;
/* Context stack. */ /* Context stack. */
struct cpp_context base_context; struct cpp_context base_context;
struct cpp_context *context; struct cpp_context *context;
......
...@@ -591,6 +591,7 @@ cpp_destroy (pfile) ...@@ -591,6 +591,7 @@ cpp_destroy (pfile)
_cpp_free_pool (&pfile->ident_pool); _cpp_free_pool (&pfile->ident_pool);
_cpp_free_pool (&pfile->macro_pool); _cpp_free_pool (&pfile->macro_pool);
_cpp_free_pool (&pfile->argument_pool); _cpp_free_pool (&pfile->argument_pool);
_cpp_free_buff (pfile->free_buffs);
for (run = &pfile->base_run; run; run = runn) for (run = &pfile->base_run; run; run = runn)
{ {
......
...@@ -107,6 +107,7 @@ static tokenrun *next_tokenrun PARAMS ((tokenrun *)); ...@@ -107,6 +107,7 @@ static tokenrun *next_tokenrun PARAMS ((tokenrun *));
static cpp_chunk *new_chunk PARAMS ((unsigned int)); static cpp_chunk *new_chunk PARAMS ((unsigned int));
static int chunk_suitable PARAMS ((cpp_pool *, cpp_chunk *, unsigned int)); static int chunk_suitable PARAMS ((cpp_pool *, cpp_chunk *, unsigned int));
static unsigned int hex_digit_value PARAMS ((unsigned int)); static unsigned int hex_digit_value PARAMS ((unsigned int));
static _cpp_buff *new_buff PARAMS ((unsigned int));
/* Utility routine: /* Utility routine:
...@@ -2114,7 +2115,7 @@ cpp_interpret_charconst (pfile, token, warn_multi, traditional, pchars_seen) ...@@ -2114,7 +2115,7 @@ cpp_interpret_charconst (pfile, token, warn_multi, traditional, pchars_seen)
return result; return result;
} }
/* Memory pools. */ /* Memory buffers. */
struct dummy struct dummy
{ {
...@@ -2127,6 +2128,95 @@ struct dummy ...@@ -2127,6 +2128,95 @@ struct dummy
}; };
#define DEFAULT_ALIGNMENT (offsetof (struct dummy, u)) #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 static int
chunk_suitable (pool, chunk, size) chunk_suitable (pool, chunk, size)
......
...@@ -236,9 +236,6 @@ struct cpp_options ...@@ -236,9 +236,6 @@ struct cpp_options
/* The language we're preprocessing. */ /* The language we're preprocessing. */
enum c_lang lang; 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. */ /* Non-0 means -v, so print the full set of include dirs. */
unsigned char verbose; unsigned char verbose;
......
...@@ -62,8 +62,7 @@ static void push_token_context ...@@ -62,8 +62,7 @@ static void push_token_context
PARAMS ((cpp_reader *, cpp_macro *, const cpp_token *, unsigned int)); PARAMS ((cpp_reader *, cpp_macro *, const cpp_token *, unsigned int));
static void push_ptoken_context static void push_ptoken_context
PARAMS ((cpp_reader *, cpp_macro *, const cpp_token **, unsigned int)); PARAMS ((cpp_reader *, cpp_macro *, const cpp_token **, unsigned int));
static enum cpp_ttype parse_arg PARAMS ((cpp_reader *, macro_arg *, int)); static _cpp_buff *collect_args PARAMS ((cpp_reader *, const cpp_hashnode *));
static macro_arg *parse_args PARAMS ((cpp_reader *, const cpp_hashnode *));
static cpp_context *next_context PARAMS ((cpp_reader *)); static cpp_context *next_context PARAMS ((cpp_reader *));
static const cpp_token *padding_token static const cpp_token *padding_token
PARAMS ((cpp_reader *, const cpp_token *)); PARAMS ((cpp_reader *, const cpp_token *));
...@@ -461,116 +460,131 @@ paste_all_tokens (pfile, lhs) ...@@ -461,116 +460,131 @@ paste_all_tokens (pfile, lhs)
push_token_context (pfile, NULL, pasted, 1); push_token_context (pfile, NULL, pasted, 1);
} }
/* Reads the unexpanded tokens of a macro argument into ARG. VAR_ARGS /* Reads and returns the arguments to a function-like macro invocation.
is non-zero if this is a variadic macro. Returns the type of the Assumes the opening parenthesis has been processed. If there is an
token that caused reading to finish. */ error, emits an appropriate diagnostic and returns NULL. */
static enum cpp_ttype static _cpp_buff *
parse_arg (pfile, arg, variadic) collect_args (pfile, node)
cpp_reader *pfile; cpp_reader *pfile;
struct macro_arg *arg; const cpp_hashnode *node;
int variadic;
{ {
enum cpp_ttype result; _cpp_buff *buff, *base_buff;
unsigned int paren = 0; cpp_macro *macro;
macro_arg *args, *arg;
arg->first = (const cpp_token **) POOL_FRONT (&pfile->argument_pool); const cpp_token *token;
for (;; arg->count++) unsigned int argc;
bool error = false;
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;
/* 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
{ {
const cpp_token *token; unsigned int paren_depth = 0;
const cpp_token **ptoken = &arg->first[arg->count]; unsigned int ntokens = 0;
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. */ argc++;
do arg->first = (const cpp_token **) buff->cur;
token = cpp_get_token (pfile);
while (arg->count == 0 && token->type == CPP_PADDING);
*ptoken++ = token;
result = token->type;
if (result == CPP_OPEN_PAREN) for (;;)
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 /* Require space for 2 new tokens (including a CPP_EOF). */
preprocessing tokens within the list of arguments that if ((char *) &arg->first[ntokens + 2] > buff->limit)
would otherwise act as preprocessing directives, the {
behavior is undefined. buff = _cpp_extend_buff (pfile, buff,
1000 * sizeof (cpp_token *));
This implementation will report a hard error, terminate arg->first = (const cpp_token **) buff->cur;
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 token = cpp_get_token (pfile);
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. */ if (token->type == CPP_PADDING)
static macro_arg * {
parse_args (pfile, node) /* Drop leading padding. */
cpp_reader *pfile; if (ntokens == 0)
const cpp_hashnode *node; continue;
{ }
cpp_macro *macro = node->value.macro; else if (token->type == CPP_OPEN_PAREN)
macro_arg *args, *cur; paren_depth++;
enum cpp_ttype type; else if (token->type == CPP_CLOSE_PAREN)
int argc, error = 0; {
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;
/* Allocate room for at least one argument, and zero it out. */ arg->first[ntokens++] = token;
argc = macro->paramc ? macro->paramc: 1; }
args = xcnewvec (macro_arg, argc);
for (cur = args, argc = 0; ;) /* Drop trailing padding. */
{ while (ntokens > 0 && arg->first[ntokens - 1]->type == CPP_PADDING)
argc++; ntokens--;
type = parse_arg (pfile, cur, argc == macro->paramc && macro->variadic); arg->count = ntokens;
if (type == CPP_CLOSE_PAREN || type == CPP_EOF) arg->first[ntokens] = &pfile->eof;
break;
/* Re-use the last argument for excess arguments. */ /* Terminate the argument. Excess arguments loop back and
if (argc < macro->paramc) overwrite the final legitimate argument, before failing. */
cur++; 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\"", cpp_error (pfile, "unterminated argument list invoking macro \"%s\"",
NODE_NAME (node)); NODE_NAME (node));
error = 1; error = true;
} }
else if (argc < macro->paramc) else if (argc < macro->paramc)
{ {
...@@ -592,28 +606,26 @@ parse_args (pfile, node) ...@@ -592,28 +606,26 @@ parse_args (pfile, node)
cpp_error (pfile, cpp_error (pfile,
"macro \"%s\" requires %u arguments, but only %u given", "macro \"%s\" requires %u arguments, but only %u given",
NODE_NAME (node), macro->paramc, argc); NODE_NAME (node), macro->paramc, argc);
error = 1; error = true;
} }
} }
else if (argc > macro->paramc) else if (argc > macro->paramc)
{ {
/* Empty argument to a macro taking no arguments is OK. */ /* Empty argument to a macro taking no arguments is OK. */
if (argc != 1 || cur->count) if (argc != 1 || arg->count)
{ {
cpp_error (pfile, cpp_error (pfile,
"macro \"%s\" passed %u arguments, but takes just %u", "macro \"%s\" passed %u arguments, but takes just %u",
NODE_NAME (node), argc, macro->paramc); NODE_NAME (node), argc, macro->paramc);
error = 1; error = true;
} }
} }
if (error) if (!error)
{ return base_buff;
free (args);
args = 0;
}
return args; _cpp_release_buff (pfile, base_buff);
return NULL;
} }
static int static int
...@@ -622,7 +634,7 @@ funlike_invocation_p (pfile, node) ...@@ -622,7 +634,7 @@ funlike_invocation_p (pfile, node)
const cpp_hashnode *node; const cpp_hashnode *node;
{ {
const cpp_token *maybe_paren; const cpp_token *maybe_paren;
macro_arg *args = 0; _cpp_buff *buff = NULL;
pfile->state.prevent_expansion++; pfile->state.prevent_expansion++;
pfile->keep_tokens++; pfile->keep_tokens++;
...@@ -634,7 +646,7 @@ funlike_invocation_p (pfile, node) ...@@ -634,7 +646,7 @@ funlike_invocation_p (pfile, node)
pfile->state.parsing_args = 2; pfile->state.parsing_args = 2;
if (maybe_paren->type == CPP_OPEN_PAREN) if (maybe_paren->type == CPP_OPEN_PAREN)
args = parse_args (pfile, node); buff = collect_args (pfile, node);
else else
{ {
_cpp_backup_tokens (pfile, 1); _cpp_backup_tokens (pfile, 1);
...@@ -648,14 +660,14 @@ funlike_invocation_p (pfile, node) ...@@ -648,14 +660,14 @@ funlike_invocation_p (pfile, node)
pfile->keep_tokens--; pfile->keep_tokens--;
pfile->state.prevent_expansion--; pfile->state.prevent_expansion--;
if (args) if (buff)
{ {
if (node->value.macro->paramc > 0) if (node->value.macro->paramc > 0)
replace_args (pfile, node->value.macro, args); replace_args (pfile, node->value.macro, (macro_arg *) buff->base);
free (args); _cpp_release_buff (pfile, buff);
} }
return args != 0; return buff != 0;
} }
/* Push the context of a macro onto the context stack. TOKEN is the /* Push the context of a macro onto the context stack. TOKEN is the
...@@ -694,8 +706,8 @@ enter_macro_context (pfile, node) ...@@ -694,8 +706,8 @@ enter_macro_context (pfile, node)
} }
/* Take the expansion of a function-like MACRO, replacing parameters /* Take the expansion of a function-like MACRO, replacing parameters
with the actual arguments. Each instance is first macro-expanded, with the actual arguments. Each argument is macro-expanded before
unless that paramter is operated upon by the # or ## operators. */ replacement, unless operated upon by the # or ## operators. */
static void static void
replace_args (pfile, macro, args) replace_args (pfile, macro, args)
cpp_reader *pfile; cpp_reader *pfile;
...@@ -904,7 +916,6 @@ expand_arg (pfile, arg) ...@@ -904,7 +916,6 @@ expand_arg (pfile, arg)
{ {
unsigned int capacity; unsigned int capacity;
arg->expanded_count = 0;
if (arg->count == 0) if (arg->count == 0)
return; return;
......
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