summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Blake <ebb9@byu.net>2008-11-10 06:38:53 -0700
committerEric Blake <ebb9@byu.net>2009-04-17 07:05:18 -0600
commitf19ae58cb67ebb06d7d92c74cfc6b8996217f7fb (patch)
tree681fd5b9423dbd6340cf836442e495fc73a615ab
parent85448d76dfe50262934f676fec7229027e5bf626 (diff)
downloadm4-argv_ref.tar.gz
initial stage34: cache ref-counting in back-refsargv_ref
-rw-r--r--src/macro.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/src/macro.c b/src/macro.c
index 6fd12f98..ed93dd2e 100644
--- a/src/macro.c
+++ b/src/macro.c
@@ -61,6 +61,8 @@ struct macro_arguments
back-reference. */
call_info *info;
int level; /* Which obstack owns this argv. */
+ /* How many times arg_adjust_refcount has been called. */
+ unsigned int refcount;
unsigned int arraylen; /* True length of allocated elements in array. */
/* Used as a variable-length array, storing information about each
argument. */
@@ -498,6 +500,7 @@ collect_arguments (symbol *sym, call_info *info, struct obstack *arguments,
args.quote_age = quote_age ();
args.info = info;
args.level = expansion_level - 1;
+ args.refcount = 0;
args.arraylen = 0;
obstack_grow (argv_stack, &args, offsetof (macro_arguments, array));
@@ -705,6 +708,7 @@ expand_macro (symbol *sym)
}
else
{
+ assert (!argv->refcount);
obstack_free (stacks[level].args, args_base);
obstack_free (stacks[level].argv, argv_base);
stacks[level].argcount--;
@@ -749,8 +753,13 @@ arg_adjust_refcount (macro_arguments *argv, bool increase)
unsigned int i;
token_chain *chain;
bool result = !argv->inuse;
+ bool recurse = !argv->refcount;
- if (argv->has_ref)
+ if (increase)
+ argv->refcount++;
+ else if (argv->refcount)
+ recurse = !--argv->refcount;
+ if (argv->has_ref && recurse)
for (i = 0; i < argv->arraylen; i++)
if (TOKEN_DATA_TYPE (argv->array[i]) == TOKEN_COMP)
{
@@ -1506,6 +1515,7 @@ make_argv_ref (macro_arguments *argv, const char *argv0, size_t argv0_len,
info->name = argv0;
info->name_len = argv0_len;
new_argv->level = argv->level;
+ new_argv->refcount = 0;
return new_argv;
}