From b8af0ca5c72a8663b3ea7b0d706cb7055d827aed Mon Sep 17 00:00:00 2001 From: Neil Booth Date: Wed, 26 Sep 2001 17:52:50 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 13 +++ gcc/cpphash.h | 18 ++++ gcc/cppinit.c | 1 + gcc/cpplex.c | 92 ++++++++++++++++++- gcc/cpplib.h | 3 - gcc/cppmacro.c | 237 ++++++++++++++++++++++++++----------------------- 6 files changed, 247 insertions(+), 117 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c24acee9592..891bfef195b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2001-09-26 Neil Booth + + * 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 * final.c (final_scan_insn): Use delete_insn instead of delete_note. diff --git a/gcc/cpphash.h b/gcc/cpphash.h index 001ac60c53e..ee5b03e624a 100644 --- a/gcc/cpphash.h +++ b/gcc/cpphash.h @@ -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; diff --git a/gcc/cppinit.c b/gcc/cppinit.c index 11c86aa3377..53e1c68b8a6 100644 --- a/gcc/cppinit.c +++ b/gcc/cppinit.c @@ -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) { diff --git a/gcc/cpplex.c b/gcc/cpplex.c index e822ba57719..1ad608de5b2 100644 --- a/gcc/cpplex.c +++ b/gcc/cpplex.c @@ -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) diff --git a/gcc/cpplib.h b/gcc/cpplib.h index b8db3663794..5dc6828bf6a 100644 --- a/gcc/cpplib.h +++ b/gcc/cpplib.h @@ -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; diff --git a/gcc/cppmacro.c b/gcc/cppmacro.c index 6cc45022288..fd38c08c9ae 100644 --- a/gcc/cppmacro.c +++ b/gcc/cppmacro.c @@ -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) +/* 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; - struct macro_arg *arg; - int variadic; + const cpp_hashnode *node; { - enum cpp_ttype result; - unsigned int paren = 0; - - arg->first = (const cpp_token **) POOL_FRONT (&pfile->argument_pool); - for (;; arg->count++) + _cpp_buff *buff, *base_buff; + cpp_macro *macro; + macro_arg *args, *arg; + const cpp_token *token; + 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; - 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]; - } + unsigned int paren_depth = 0; + unsigned int ntokens = 0; - /* Drop leading padding. */ - do - token = cpp_get_token (pfile); - while (arg->count == 0 && token->type == CPP_PADDING); - *ptoken++ = token; - result = token->type; + argc++; + arg->first = (const cpp_token **) buff->cur; - 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) + for (;;) { - /* 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--; + /* 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; + } - /* 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; -} + token = cpp_get_token (pfile); -/* Parse the arguments making up a macro invocation. */ -static macro_arg * -parse_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; + 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; - /* Allocate room for at least one argument, and zero it out. */ - argc = macro->paramc ? macro->paramc: 1; - args = xcnewvec (macro_arg, argc); + arg->first[ntokens++] = token; + } - for (cur = args, argc = 0; ;) - { - argc++; + /* Drop trailing padding. */ + while (ntokens > 0 && arg->first[ntokens - 1]->type == CPP_PADDING) + ntokens--; - type = parse_arg (pfile, cur, argc == macro->paramc && macro->variadic); - if (type == CPP_CLOSE_PAREN || type == CPP_EOF) - break; + arg->count = ntokens; + arg->first[ntokens] = &pfile->eof; - /* Re-use the last argument for excess arguments. */ - if (argc < macro->paramc) - cur++; + /* 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; -- 2.30.2