initial stage34: cache ref-counting in back-refs
diff --git a/src/macro.c b/src/macro.c
index 6fd12f9..ed93dd2 100644
--- a/src/macro.c
+++ b/src/macro.c
@@ -61,6 +61,8 @@
      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 @@
   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 @@
 	}
       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 @@
   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 @@
   info->name = argv0;
   info->name_len = argv0_len;
   new_argv->level = argv->level;
+  new_argv->refcount = 0;
   return new_argv;
 }