summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorneil <neil@138bc75d-0d04-0410-961f-82ee72b054a4>2001-09-26 17:52:50 +0000
committerneil <neil@138bc75d-0d04-0410-961f-82ee72b054a4>2001-09-26 17:52:50 +0000
commit06c92cbc412348d781face036e144c36d0f73fc5 (patch)
treec6066a336fb26cdd94d5e883ad2dbefc8c99c02d
parent8f3e702b4f5e481efd9da3287688988be46262de (diff)
downloadgcc-06c92cbc412348d781face036e144c36d0f73fc5.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@45827 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/cpphash.h18
-rw-r--r--gcc/cppinit.c1
-rw-r--r--gcc/cpplex.c92
-rw-r--r--gcc/cpplib.h3
-rw-r--r--gcc/cppmacro.c237
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 <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.
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;