From e309bb2f768d9d630ada34f7240b8d6a130ec540 Mon Sep 17 00:00:00 2001
From: Roland McGrath <roland@redhat.com>
Date: Thu, 11 Jun 1992 02:27:09 +0000
Subject: [PATCH] Formerly expand.c.~2~

---
 expand.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 66 insertions(+), 14 deletions(-)

diff --git a/expand.c b/expand.c
index 81796d57..e9e29b35 100644
--- a/expand.c
+++ b/expand.c
@@ -1,5 +1,5 @@
 /* Variable expansion functions for GNU Make.
-Copyright (C) 1988, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1988, 1989, 1991, 1992 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
 GNU Make is free software; you can redistribute it and/or modify
@@ -21,7 +21,59 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "file.h"
 #include "variable.h"
 
+/* The next two describe the variable output buffer.
+   This buffer is used to hold the variable-expansion of a line of the
+   makefile.  It is made bigger with realloc whenever it is too small.
+   variable_buffer_length is the size currently allocated.
+   variable_buffer is the address of the buffer.  */
 
+static unsigned int variable_buffer_length;
+static char *variable_buffer;
+
+/* Subroutine of variable_expand and friends:
+   The text to add is LENGTH chars starting at STRING to the variable_buffer.
+   The text is added to the buffer at PTR, and the updated pointer into
+   the buffer is returned as the value.  Thus, the value returned by
+   each call to variable_buffer_output should be the first argument to
+   the following call.  */
+
+static char *
+variable_buffer_output (ptr, string, length)
+     char *ptr, *string;
+     unsigned int length;
+{
+  register unsigned int newlen = length + (ptr - variable_buffer);
+
+  if (newlen > variable_buffer_length)
+    {
+      unsigned int offset = ptr - variable_buffer;
+      variable_buffer_length = max (2 * variable_buffer_length, newlen + 100);
+      variable_buffer = (char *) xrealloc (variable_buffer,
+					   variable_buffer_length);
+      ptr = variable_buffer + offset;
+    }
+
+  bcopy (string, ptr, length);
+  return ptr + length;
+}
+
+/* Return a pointer to the beginning of the variable buffer.  */
+
+static char *
+initialize_variable_output ()
+{
+  /* If we don't have a variable output buffer yet, get one.  */
+
+  if (variable_buffer == 0)
+    {
+      variable_buffer_length = 200;
+      variable_buffer = (char *) xmalloc (variable_buffer_length);
+      variable_buffer[0] = '\0';
+    }
+
+  return variable_buffer;
+}
+
 /* Recursively expand V.  The returned string is malloc'd.  */
 
 static char *
@@ -313,30 +365,30 @@ variable_expand_for_file (line, file)
   return result;
 }
 
-/* Like variable_expand, but the returned string is malloc'd.  */
-char *
-allocated_variable_expand (line)
-     char *line;
-{
-  return allocated_variable_expand_for_file (line, (struct file *) 0);
-}
-
-/* Like variable_expand_for_file, but the returned string is malloc'd.  */
+/* Like variable_expand_for_file, but the returned string is malloc'd.
+   This function is called a lot.  It wants to be efficient.  */
 
 char *
 allocated_variable_expand_for_file (line, file)
      char *line;
      struct file *file;
 {
-  char *save;
   char *value;
 
-  save = save_variable_output ();
+  char *obuf = variable_buffer;
+  unsigned int olen = variable_buffer_length;
+
+  variable_buffer = 0;
 
   value = variable_expand_for_file (line, file);
-  value = savestring (value, strlen (value));
 
-  restore_variable_output (save);
+#if 0
+  /* Waste a little memory and save time.  */
+  value = xrealloc (value, strlen (value))
+#endif
+
+  variable_buffer = obuf;
+  variable_buffer_length = olen;
 
   return value;
 }