abusalimov

make-perf-vbuffer.patch

Mar 15th, 2012
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 96.53 KB | None | 0 0
  1. ### Eclipse Workspace Patch 1.0
  2. #P make-patched
  3. Index: expand.c
  4. ===================================================================
  5. RCS file: /sources/make/make/expand.c,v
  6. retrieving revision 1.62
  7. diff -u -r1.62 expand.c
  8. --- expand.c    5 Mar 2012 14:10:43 -0000   1.62
  9. +++ expand.c    15 Mar 2012 21:19:13 -0000
  10. @@ -16,13 +16,12 @@
  11.  
  12.  #include "make.h"
  13.  
  14. -#include <assert.h>
  15. -
  16.  #include "filedef.h"
  17.  #include "job.h"
  18.  #include "commands.h"
  19.  #include "variable.h"
  20.  #include "rule.h"
  21. +#include "/usr/include/assert.h"
  22.  
  23.  /* Initially, any errors reported when expanding strings will be reported
  24.     against the file where the error appears.  */
  25. @@ -31,8 +30,6 @@
  26.  /* The next two describe the variable output buffer.
  27.     This buffer is used to hold the variable-expansion of a line of the
  28.     makefile.  It is made bigger with realloc whenever it is too small.
  29. -   variable_buffer_length is the size currently allocated.
  30. -   variable_buffer is the address of the buffer.
  31.  
  32.     For efficiency, it's guaranteed that the buffer will always have
  33.     VARIABLE_BUFFER_ZONE extra bytes allocated.  This allows you to add a few
  34. @@ -40,115 +37,121 @@
  35.     these bytes unless you're _sure_ you have room (you know when the buffer
  36.     length was last checked.  */
  37.  
  38. +static struct vbuffer *expansion_vbuf;
  39. +
  40.  #define VARIABLE_BUFFER_ZONE    5
  41.  
  42. -static unsigned int variable_buffer_length;
  43. -char *variable_buffer;
  44. +struct vbuffer *
  45. +vbuffer_init (struct vbuffer *vbuf)
  46. +{
  47. +  vbuf->size = 50;
  48. +  vbuf->ptr = vbuf->buffer = xmalloc (vbuf->size);
  49.  
  50. -/* Subroutine of variable_expand and friends:
  51. -   The text to add is LENGTH chars starting at STRING to the variable_buffer.
  52. -   The text is added to the buffer at PTR, and the updated pointer into
  53. -   the buffer is returned as the value.  Thus, the value returned by
  54. -   each call to variable_buffer_output should be the first argument to
  55. -   the following call.  */
  56. +//  memset(vbuf->buffer, 0x7f, vbuf->size);
  57. +  *vbuf->ptr = '\0';
  58.  
  59. -char *
  60. -variable_buffer_output (char *ptr, const char *string, unsigned int length)
  61. +  return vbuf;
  62. +}
  63. +
  64. +struct vbuffer *
  65. +vbuffer_reset (struct vbuffer *vbuf)
  66.  {
  67. -  register unsigned int newlen = length + (ptr - variable_buffer);
  68. +  vbuf->ptr = vbuf->buffer;
  69.  
  70. -  if ((newlen + VARIABLE_BUFFER_ZONE) > variable_buffer_length)
  71. -    {
  72. -      unsigned int offset = ptr - variable_buffer;
  73. -      variable_buffer_length = (newlen + 100 > 2 * variable_buffer_length
  74. -               ? newlen + 100
  75. -               : 2 * variable_buffer_length);
  76. -      variable_buffer = xrealloc (variable_buffer, variable_buffer_length);
  77. -      ptr = variable_buffer + offset;
  78. -    }
  79. +  *vbuf->ptr = '\0';
  80.  
  81. -  memcpy (ptr, string, length);
  82. -  return ptr + length;
  83. +  return vbuf;
  84.  }
  85.  
  86. -/* Return a pointer to the beginning of the variable buffer.  */
  87. +#ifdef __GNUC__
  88. +__inline
  89. +#endif
  90. +static void
  91. +vbuffer_grow (struct vbuffer *vbuf, size_t newlen)
  92. +{
  93. +  size_t oldlen = vbuf->size;
  94. +  size_t offset = vbuf->ptr - vbuf->buffer;
  95.  
  96. -static char *
  97. -initialize_variable_output (void)
  98. +  newlen = newlen + 100 > 2 * oldlen
  99. +    ? newlen + 100 : 2 * oldlen;
  100. +
  101. +  vbuf->buffer = xrealloc (vbuf->buffer, newlen);
  102. +  vbuf->ptr = vbuf->buffer + offset;
  103. +//  memset(vbuf->ptr + 1, 0x7f, vbuf->size - offset - 1);
  104. +  vbuf->size = newlen;
  105. +}
  106. +
  107. +#ifdef __GNUC__
  108. +__inline
  109. +#endif
  110. +size_t
  111. +vbuffer_reserve (struct vbuffer *o, size_t length)
  112.  {
  113. -  /* If we don't have a variable output buffer yet, get one.  */
  114. +  size_t newoff = (o->ptr - o->buffer) + length;
  115.  
  116. -  if (variable_buffer == 0)
  117. -    {
  118. -      variable_buffer_length = 200;
  119. -      variable_buffer = xmalloc (variable_buffer_length);
  120. -      variable_buffer[0] = '\0';
  121. -    }
  122. +  if ((newoff + VARIABLE_BUFFER_ZONE) > o->size)
  123. +    vbuffer_grow (o, newoff);
  124.  
  125. -  return variable_buffer;
  126. +  return o->size - newoff;
  127.  }
  128. -
  129. -/* Recursively expand V.  The returned string is malloc'd.  */
  130.  
  131. -static char *allocated_variable_append (const struct variable *v);
  132. +/* Writes byte stream pointed by STR into VBUF.
  133. +   The optional LEN argument can be used to limit the amount of bytes to copy.
  134. +   Otherwise (if LEN is a negative number) STR is treated as a null-terminated
  135. +   string and copied accordingly.
  136.  
  137. -char *
  138. -recursively_expand_for_file (struct variable *v, struct file *file)
  139. +   Returns the actual number of bytes copied,
  140. +   that is LEN argument if it is non-negative and strlen (STR) otherwise.
  141. +
  142. +   As like all the other vbuffer methods it leaves the internal buffer
  143. +   of the VBUF null-terminated.   */
  144. +
  145. +#ifdef __GNUC__
  146. +__inline
  147. +#endif
  148. +size_t
  149. +vbuffer_write (struct vbuffer *o, const char *str, ssize_t len)
  150.  {
  151. -  char *value;
  152. -  const struct floc *this_var;
  153. -  const struct floc **saved_varp;
  154. -  struct variable_set_list *save = 0;
  155. -  int set_reading = 0;
  156. +  size_t length = len < 0 ? strlen(str) : (size_t) len;
  157.  
  158. -  /* Don't install a new location if this location is empty.
  159. -     This can happen for command-line variables, builtin variables, etc.  */
  160. -  saved_varp = expanding_var;
  161. -  if (v->fileinfo.filenm)
  162. -    {
  163. -      this_var = &v->fileinfo;
  164. -      expanding_var = &this_var;
  165. -    }
  166. +//  if ((*vbuf->ptr != '\0')
  167. +//      || (vbuf->ptr > vbuf->buffer + strlen(vbuf->buffer))
  168. +//      || strchr(vbuf->buffer, 0x7f)) {
  169. +//    error (reading_file, "buffer: %s", vbuf->buffer);
  170. +//    error (reading_file, "   ptr: %s", vbuf->ptr);
  171. +//    assert (0);
  172. +//  }
  173.  
  174. -  /* If we have no other file-reading context, use the variable's context. */
  175. -  if (!reading_file)
  176. -    {
  177. -      set_reading = 1;
  178. -      reading_file = &v->fileinfo;
  179. -    }
  180. +  vbuffer_reserve (o, length);
  181.  
  182. -  if (v->expanding)
  183. -    {
  184. -      if (!v->exp_count)
  185. -        /* Expanding V causes infinite recursion.  Lose.  */
  186. -        fatal (*expanding_var,
  187. -               _("Recursive variable '%s' references itself (eventually)"),
  188. -               v->name);
  189. -      --v->exp_count;
  190. -    }
  191. +  memcpy (o->ptr, str, length);
  192. +  o->ptr += length;
  193.  
  194. -  if (file)
  195. -    {
  196. -      save = current_variable_set_list;
  197. -      current_variable_set_list = file->variables;
  198. -    }
  199. +  *o->ptr = '\0';
  200.  
  201. -  v->expanding = 1;
  202. -  if (v->append)
  203. -    value = allocated_variable_append (v);
  204. -  else
  205. -    value = allocated_variable_expand (v->value);
  206. -  v->expanding = 0;
  207. +  return length;
  208. +}
  209.  
  210. -  if (set_reading)
  211. -    reading_file = 0;
  212. +/* Moves the pointer of the VBUF back on the LEN bytes.
  213. +   If LEN is negative, or if moving the pointer would lead to an underflow,
  214. +   then sets the pointer to the start of the buffer.
  215.  
  216. -  if (file)
  217. -    current_variable_set_list = save;
  218. +   Returns the actual number of discarded bytes.  */
  219.  
  220. -  expanding_var = saved_varp;
  221. +size_t
  222. +vbuffer_unwrite (struct vbuffer *o, ssize_t len)
  223. +{
  224. +  size_t oldoff = o->ptr - o->buffer;
  225. +  size_t length = len < 0 ? oldoff : (size_t) len;
  226. +
  227. +  if (length > oldoff)
  228. +    length = oldoff;
  229.  
  230. -  return value;
  231. +  o->ptr -= length;
  232. +
  233. +  *o->ptr = '\0';
  234. +
  235. +  return length;
  236.  }
  237.  
  238.  /* Expand a simple reference to variable NAME, which is LENGTH chars long.  */
  239. @@ -156,75 +159,130 @@
  240.  #ifdef __GNUC__
  241.  __inline
  242.  #endif
  243. -static char *
  244. -reference_variable (char *o, const char *name, unsigned int length)
  245. +static size_t
  246. +expand_variable_reference (struct vbuffer *o, const char *name, size_t length)
  247.  {
  248.    struct variable *v;
  249. -  char *value;
  250.  
  251.    v = lookup_variable (name, length);
  252. +  o->ptr[0] = 0;
  253.  
  254.    if (v == 0)
  255.      warn_undefined (name, length);
  256.  
  257.    /* If there's no variable by that name or it has no value, stop now.  */
  258.    if (v == 0 || (*v->value == '\0' && !v->append))
  259. -    return o;
  260. -
  261. -  value = (v->recursive ? recursively_expand (v) : v->value);
  262. -
  263. -  o = variable_buffer_output (o, value, strlen (value));
  264. +    return 0;
  265.  
  266.    if (v->recursive)
  267. -    free (value);
  268. -
  269. -  return o;
  270. +    return vbuffer_expand_variable (o, v);
  271. +  else
  272. +    return vbuffer_write (o, v->value, -1);
  273.  }
  274. -
  275. -/* Scan STRING for variable references and expansion-function calls.  Only
  276. -   LENGTH bytes of STRING are actually scanned.  If LENGTH is -1, scan until
  277. -   a null byte is found.
  278. -
  279. -   Write the results to LINE, which must point into 'variable_buffer'.  If
  280. -   LINE is NULL, start at the beginning of the buffer.
  281. -   Return a pointer to LINE, or to the beginning of the buffer if LINE is
  282. -   NULL.
  283. - */
  284. -char *
  285. -variable_expand_string (char *line, const char *string, long length)
  286. +
  287. +
  288. +#ifdef __GNUC__
  289. +__inline
  290. +#endif
  291. +static int
  292. +handle_subst_reference (struct vbuffer *o, char *beg, char *end)
  293.  {
  294. +  size_t result = 0;
  295.    struct variable *v;
  296. -  const char *p, *p1;
  297. -  char *save;
  298. -  char *o;
  299. -  unsigned int line_offset;
  300. -
  301. -  if (!line)
  302. -    line = initialize_variable_output();
  303. -  o = line;
  304. -  line_offset = line - variable_buffer;
  305. +  const char *subst_beg, *subst_end, *replace_beg, *replace_end;
  306. +  char *colon = lindex (beg, end, ':');
  307. +
  308. +  if (colon == 0)
  309. +    return -1;
  310. +
  311. +  subst_beg = colon + 1;
  312. +  subst_end = lindex (subst_beg, end, '=');
  313. +  if (subst_end == 0)
  314. +    /* There is no = in sight.  Punt on the substitution reference and treat
  315. +       this as a variable name containing a colon.  */
  316. +    return -1;
  317. +
  318. +  /* This looks like a valid substitution reference: $(FOO:A=B).  */
  319. +  replace_beg = subst_end + 1;
  320. +  replace_end = end;
  321. +
  322. +  /* Extract the variable name before the colon and look up that variable.  */
  323. +  v = lookup_variable (beg, colon - beg);
  324. +  if (v == 0)
  325. +    warn_undefined (beg, colon - beg);
  326.  
  327. -  if (length == 0)
  328. +  /* If the variable is not empty, perform the substitution.  */
  329. +  if (v != 0 && *v->value != '\0')
  330.      {
  331. -      variable_buffer_output (o, "", 1);
  332. -      return (variable_buffer);
  333. +      char *pattern, *replace, *ppercent, *rpercent;
  334. +      char *value = (v->recursive
  335. +            ? recursively_expand(v)
  336. +            : v->value);
  337. +
  338. +      /* Copy the pattern and the replacement.  Add in an extra % at the
  339. +         beginning to use in case there isn't one in the pattern.  */
  340. +      pattern = alloca (subst_end - subst_beg + 2);
  341. +      *(pattern++) = '%';
  342. +      memcpy (pattern, subst_beg, subst_end - subst_beg);
  343. +      pattern[subst_end - subst_beg] = '\0';
  344. +
  345. +      replace = alloca (replace_end - replace_beg + 2);
  346. +      *(replace++) = '%';
  347. +      memcpy (replace, replace_beg, replace_end - replace_beg);
  348. +      replace[replace_end - replace_beg] = '\0';
  349. +
  350. +      /* Look for %.  Set the percent pointers properly
  351. +    based on whether we find one or not.  */
  352. +      ppercent = find_percent (pattern);
  353. +      if (ppercent)
  354. +   {
  355. +     ++ppercent;
  356. +     rpercent = find_percent (replace);
  357. +     if (rpercent)
  358. +       ++rpercent;
  359. +   }
  360. +      else
  361. +   {
  362. +     ppercent = pattern--;
  363. +     rpercent = replace--;
  364. +   }
  365. +
  366. +      *o->ptr = '\0';
  367. +
  368. +      result = patsubst_expand_pat (o, value,
  369. +                   pattern, replace, ppercent, rpercent);
  370. +
  371. +      if (v->recursive)
  372. +   free (value);
  373.      }
  374.  
  375. -  /* We need a copy of STRING: due to eval, it's possible that it will get
  376. -     freed as we process it (it might be the value of a variable that's reset
  377. -     for example).  Also having a nil-terminated string is handy.  */
  378. -  save = length < 0 ? xstrdup (string) : xstrndup (string, length);
  379. -  p = save;
  380. +  return result;
  381. +}
  382. +
  383. +size_t
  384. +vbuffer_expand (struct vbuffer *o, char *str, ssize_t len)
  385. +{
  386. +  size_t result = 0;
  387. +  char *p, *p1;
  388. +
  389. +  if (len == 0)
  390. +    return 0;
  391.  
  392. +  if (len > 0)
  393. +    str[len] = '\0';
  394. +
  395. +  p = str;
  396.    while (1)
  397.      {
  398.        /* Copy all following uninteresting chars all at once to the
  399. -         variable output buffer, and skip them.  Uninteresting chars end
  400. +    variable output buffer, and skip them.  Uninteresting chars end
  401.      at the next $ or the end of the input.  */
  402.  
  403.        p1 = strchr (p, '$');
  404.  
  405. -      o = variable_buffer_output (o, p, p1 != 0 ? (unsigned int)(p1 - p) : strlen (p) + 1);
  406. +      /* In case when P1 is nil,
  407. +         'vbuffer_write' writes the whole string pointed by P.  */
  408. +      result += vbuffer_write (o, p, p1 - p);
  409.  
  410.        if (p1 == 0)
  411.     break;
  412. @@ -236,27 +294,23 @@
  413.     {
  414.     case '$':
  415.       /* $$ seen means output one $ to the variable output buffer.  */
  416. -     o = variable_buffer_output (o, p, 1);
  417. +     result += vbuffer_write (o, p, 1);
  418.       break;
  419.  
  420.     case '(':
  421.     case '{':
  422.       /* $(...) or ${...} is the general case of substitution.  */
  423.       {
  424. +       int handle_ret;
  425.         char openparen = *p;
  426.         char closeparen = (openparen == '(') ? ')' : '}';
  427. -            const char *begp;
  428. -       const char *beg = p + 1;
  429. -       char *op;
  430. -            char *abeg = NULL;
  431. -       const char *end, *colon;
  432. -
  433. -       op = o;
  434. -       begp = p;
  435. -       if (handle_function (&op, &begp))
  436. +       char *beg = p + 1;
  437. +       char *end;
  438. +
  439. +       handle_ret = handle_function (o, &p);
  440. +       if (handle_ret >= 0)
  441.           {
  442. -       o = op;
  443. -       p = begp;
  444. +       result += handle_ret;
  445.         break;
  446.           }
  447.  
  448. @@ -265,8 +319,8 @@
  449.  
  450.         end = strchr (beg, closeparen);
  451.         if (end == 0)
  452. -              /* Unterminated variable reference.  */
  453. -              fatal (*expanding_var, _("unterminated variable reference"));
  454. +         fatal (*expanding_var, _("unterminated variable reference"));
  455. +
  456.         p1 = lindex (beg, end, '$');
  457.         if (p1 != 0)
  458.           {
  459. @@ -285,102 +339,40 @@
  460.            such as '$($(a)'.  */
  461.         if (count < 0)
  462.           {
  463. -           abeg = expand_argument (beg, p); /* Expand the name.  */
  464. -           beg = abeg;
  465. -           end = strchr (beg, '\0');
  466. +           /* Expand the name.
  467. +              As a little optimization we reuse the same vbuffer.  */
  468. +           size_t name_len = vbuffer_expand (o, beg, p - beg);
  469. +           *p = closeparen;
  470. +
  471. +           /* We don't use 'vbuffer_unwrite' here because it would
  472. +              reset the first byte of the computed name to nil.  */
  473. +           o->ptr -= name_len;
  474. +
  475. +           beg = o->ptr;
  476. +           end = beg + name_len;
  477. +
  478.           }
  479.           }
  480.         else
  481.           /* Advance P to the end of this reference.  After we are
  482. -                 finished expanding this one, P will be incremented to
  483. -                 continue the scan.  */
  484. +        finished expanding this one, P will be incremented to
  485. +        continue the scan.  */
  486.           p = end;
  487.  
  488.         /* This is not a reference to a built-in function and
  489.            any variable references inside are now expanded.
  490.            Is the resultant text a substitution reference?  */
  491.  
  492. -       colon = lindex (beg, end, ':');
  493. -       if (colon)
  494. +       handle_ret = handle_subst_reference(o, beg, end);
  495. +       if (handle_ret >= 0)
  496.           {
  497. -       /* This looks like a substitution reference: $(FOO:A=B).  */
  498. -       const char *subst_beg, *subst_end, *replace_beg, *replace_end;
  499. -
  500. -       subst_beg = colon + 1;
  501. -       subst_end = lindex (subst_beg, end, '=');
  502. -       if (subst_end == 0)
  503. -         /* There is no = in sight.  Punt on the substitution
  504. -            reference and treat this as a variable name containing
  505. -            a colon, in the code below.  */
  506. -         colon = 0;
  507. -       else
  508. -         {
  509. -           replace_beg = subst_end + 1;
  510. -           replace_end = end;
  511. -
  512. -           /* Extract the variable name before the colon
  513. -              and look up that variable.  */
  514. -           v = lookup_variable (beg, colon - beg);
  515. -           if (v == 0)
  516. -             warn_undefined (beg, colon - beg);
  517. -
  518. -                    /* If the variable is not empty, perform the
  519. -                       substitution.  */
  520. -           if (v != 0 && *v->value != '\0')
  521. -             {
  522. -           char *pattern, *replace, *ppercent, *rpercent;
  523. -           char *value = (v->recursive
  524. -                                       ? recursively_expand (v)
  525. -                      : v->value);
  526. -
  527. -                        /* Copy the pattern and the replacement.  Add in an
  528. -                           extra % at the beginning to use in case there
  529. -                           isn't one in the pattern.  */
  530. -                        pattern = alloca (subst_end - subst_beg + 2);
  531. -                        *(pattern++) = '%';
  532. -                        memcpy (pattern, subst_beg, subst_end - subst_beg);
  533. -                        pattern[subst_end - subst_beg] = '\0';
  534. -
  535. -                        replace = alloca (replace_end - replace_beg + 2);
  536. -                        *(replace++) = '%';
  537. -                        memcpy (replace, replace_beg,
  538. -                               replace_end - replace_beg);
  539. -                        replace[replace_end - replace_beg] = '\0';
  540. -
  541. -                        /* Look for %.  Set the percent pointers properly
  542. -                           based on whether we find one or not.  */
  543. -           ppercent = find_percent (pattern);
  544. -           if (ppercent)
  545. -                          {
  546. -                            ++ppercent;
  547. -                            rpercent = find_percent (replace);
  548. -                            if (rpercent)
  549. -                              ++rpercent;
  550. -                          }
  551. -           else
  552. -                          {
  553. -                            ppercent = pattern;
  554. -                            rpercent = replace;
  555. -                            --pattern;
  556. -                            --replace;
  557. -                          }
  558. -
  559. -                        o = patsubst_expand_pat (o, value, pattern, replace,
  560. -                                                 ppercent, rpercent);
  561. -
  562. -           if (v->recursive)
  563. -             free (value);
  564. -             }
  565. -         }
  566. +       result += handle_ret;
  567. +       break;
  568.           }
  569.  
  570. -       if (colon == 0)
  571. -         /* This is an ordinary variable reference.
  572. -        Look up the value of the variable.  */
  573. -       o = reference_variable (o, beg, end - beg);
  574. -
  575. -     if (abeg)
  576. -       free (abeg);
  577. +       /* This is an ordinary variable reference.
  578. +          Look up the value of the variable.  */
  579. +       result += expand_variable_reference(o, beg, end - beg);
  580.       }
  581.       break;
  582.  
  583. @@ -393,7 +385,7 @@
  584.  
  585.       /* A $ followed by a random char is a variable reference:
  586.          $a is equivalent to $(a).  */
  587. -          o = reference_variable (o, p, 1);
  588. +     result += expand_variable_reference(o, p, 1);
  589.  
  590.       break;
  591.     }
  592. @@ -404,69 +396,19 @@
  593.        ++p;
  594.      }
  595.  
  596. -  free (save);
  597. -
  598. -  variable_buffer_output (o, "", 1);
  599. -  return (variable_buffer + line_offset);
  600. -}
  601. -
  602. -/* Scan LINE for variable references and expansion-function calls.
  603. -   Build in 'variable_buffer' the result of expanding the references and calls.
  604. -   Return the address of the resulting string, which is null-terminated
  605. -   and is valid only until the next time this function is called.  */
  606. -
  607. -char *
  608. -variable_expand (const char *line)
  609. -{
  610. -  return variable_expand_string(NULL, line, (long)-1);
  611. -}
  612. -
  613. -/* Expand an argument for an expansion function.
  614. -   The text starting at STR and ending at END is variable-expanded
  615. -   into a null-terminated string that is returned as the value.
  616. -   This is done without clobbering 'variable_buffer' or the current
  617. -   variable-expansion that is in progress.  */
  618. -
  619. -char *
  620. -expand_argument (const char *str, const char *end)
  621. -{
  622. -  char *tmp, *alloc = NULL;
  623. -  char *r;
  624. -
  625. -  if (str == end)
  626. -    return xstrdup("");
  627. -
  628. -  if (!end || *end == '\0')
  629. -    return allocated_variable_expand (str);
  630. -
  631. -  if (end - str + 1 > 1000)
  632. -    tmp = alloc = xmalloc (end - str + 1);
  633. -  else
  634. -    tmp = alloca (end - str + 1);
  635. -
  636. -  memcpy (tmp, str, end - str);
  637. -  tmp[end - str] = '\0';
  638. -
  639. -  r = allocated_variable_expand (tmp);
  640. -
  641. -  if (alloc)
  642. -    free (alloc);
  643. +  return result;
  644.  
  645. -  return r;
  646.  }
  647. -
  648. -/* Expand LINE for FILE.  Error messages refer to the file and line where
  649. -   FILE's commands were found.  Expansion uses FILE's variable set list.  */
  650.  
  651. -char *
  652. -variable_expand_for_file (const char *line, struct file *file)
  653. -{
  654. -  char *result;
  655. +size_t
  656. +vbuffer_expand_for_file (struct vbuffer *o, char *str, ssize_t len,
  657. +                         struct file *file) {
  658. +  size_t result = 0;
  659.    struct variable_set_list *savev;
  660.    const struct floc *savef;
  661.  
  662.    if (file == 0)
  663. -    return variable_expand (line);
  664. +    return vbuffer_expand (o, str, len);
  665.  
  666.    savev = current_variable_set_list;
  667.    current_variable_set_list = file->variables;
  668. @@ -477,124 +419,248 @@
  669.    else
  670.      reading_file = 0;
  671.  
  672. -  result = variable_expand (line);
  673. +  result = vbuffer_expand (o, str, len);
  674.  
  675.    current_variable_set_list = savev;
  676.    reading_file = savef;
  677.  
  678.    return result;
  679.  }
  680. -
  681. +
  682.  /* Like allocated_variable_expand, but for += target-specific variables.
  683.     First recursively construct the variable value from its appended parts in
  684.     any upper variable sets.  Then expand the resulting value.  */
  685.  
  686. -static char *
  687. -variable_append (const char *name, unsigned int length,
  688. -                 const struct variable_set_list *set, int local)
  689. +static size_t
  690. +expand_variable_append (struct vbuffer *o,
  691. +           const char *name, unsigned int length,
  692. +           const struct variable_set_list *set_list,
  693. +           int local)
  694.  {
  695. +  size_t ret = 0;
  696.    const struct variable *v;
  697. -  char *buf = 0;
  698. -  /* If this set is local and the next is not a parent, then next is local.  */
  699. -  int nextlocal = local && set->next_is_parent == 0;
  700. +  int nextlocal;
  701.  
  702.    /* If there's nothing left to check, return the empty buffer.  */
  703. -  if (!set)
  704. -    return initialize_variable_output ();
  705. +  if (!set_list)
  706. +    return 0;
  707. +
  708. +  /* If this set is local and the next is not a parent, then next is local.  */
  709. +  nextlocal = local && set_list->next_is_parent == 0;
  710.  
  711.    /* Try to find the variable in this variable set.  */
  712. -  v = lookup_variable_in_set (name, length, set->set);
  713. +  v = lookup_variable_in_set (name, length, set_list->set);
  714.  
  715.    /* If there isn't one, or this one is private, try the set above us.  */
  716.    if (!v || (!local && v->private_var))
  717. -    return variable_append (name, length, set->next, nextlocal);
  718. +    return expand_variable_append (o, name, length,
  719. +                  set_list->next, nextlocal);
  720.  
  721.    /* If this variable type is append, first get any upper values.
  722.       If not, initialize the buffer.  */
  723.    if (v->append)
  724. -    buf = variable_append (name, length, set->next, nextlocal);
  725. -  else
  726. -    buf = initialize_variable_output ();
  727. +    ret += expand_variable_append (o, name, length,
  728. +                  set_list->next, nextlocal);
  729.  
  730.    /* Append this value to the buffer, and return it.
  731.       If we already have a value, first add a space.  */
  732. -  if (buf > variable_buffer)
  733. -    buf = variable_buffer_output (buf, " ", 1);
  734. +  if (ret != 0)
  735. +    ret += vbuffer_write (o, " ", 1);
  736.  
  737.    /* Either expand it or copy it, depending.  */
  738. -  if (! v->recursive)
  739. -    return variable_buffer_output (buf, v->value, strlen (v->value));
  740. +  if (v->recursive)
  741. +    {
  742. +      char *value = xstrdup (v->value);
  743. +      ret += vbuffer_expand (o, value, -1);
  744. +      free (value);
  745. +    }
  746. +  else
  747. +    ret += vbuffer_write (o, v->value, -1);
  748. +
  749. +  return ret;
  750. +}
  751. +
  752. +size_t
  753. +vbuffer_expand_variable_for_file (struct vbuffer *o, struct variable *v,
  754. +                 struct file *file)
  755. +{
  756. +  size_t ret = 0;
  757. +  const struct floc *this_var;
  758. +  const struct floc **saved_varp;
  759. +  struct variable_set_list *save = 0;
  760. +  int set_reading = 0;
  761. +
  762. +  /* Don't install a new location if this location is empty.
  763. +     This can happen for command-line variables, builtin variables, etc.  */
  764. +  saved_varp = expanding_var;
  765. +  if (v->fileinfo.filenm)
  766. +    {
  767. +      this_var = &v->fileinfo;
  768. +      expanding_var = &this_var;
  769. +    }
  770. +
  771. +  /* If we have no other file-reading context, use the variable's context. */
  772. +  if (!reading_file)
  773. +    {
  774. +      set_reading = 1;
  775. +      reading_file = &v->fileinfo;
  776. +    }
  777. +
  778. +  if (v->expanding)
  779. +    {
  780. +      if (!v->exp_count)
  781. +        /* Expanding V causes infinite recursion.  Lose.  */
  782. +        fatal (*expanding_var,
  783. +               _("Recursive variable '%s' references itself (eventually)"),
  784. +               v->name);
  785. +      --v->exp_count;
  786. +    }
  787. +
  788. +  if (file)
  789. +    {
  790. +      save = current_variable_set_list;
  791. +      current_variable_set_list = file->variables;
  792. +    }
  793. +
  794. +  v->expanding = 1;
  795. +  if (v->append)
  796. +    ret += expand_variable_append (o, v->name, strlen (v->name),
  797. +                  current_variable_set_list, 1);
  798. +  else
  799. +    {
  800. +      /* We need a copy of STRING: due to eval, it's possible that it will get
  801. +         freed as we process it (it might be the value of a variable that's
  802. +         reset, for example).  Also having a nil-terminated string is handy.  */
  803. +      char *value = xstrdup (v->value);
  804. +      ret += vbuffer_expand (o, value, -1);
  805. +      free (value);
  806. +    }
  807. +  v->expanding = 0;
  808. +
  809. +  if (set_reading)
  810. +    reading_file = 0;
  811. +
  812. +  if (file)
  813. +    current_variable_set_list = save;
  814.  
  815. -  buf = variable_expand_string (buf, v->value, strlen (v->value));
  816. -  return (buf + strlen (buf));
  817. +  expanding_var = saved_varp;
  818. +
  819. +  return ret;
  820.  }
  821.  
  822. +size_t
  823. +vbuffer_expand_ro (struct vbuffer *o, const char *str, ssize_t len)
  824. +{
  825. +  size_t ret;
  826. +  char *string = len < 0 ? xstrdup (str) : xstrndup (str, len);
  827. +  ret = vbuffer_expand (o, string, -1);
  828. +  free (string);
  829. +  return ret;
  830. +}
  831.  
  832. -static char *
  833. -allocated_variable_append (const struct variable *v)
  834. +size_t
  835. +vbuffer_expand_ro_for_file (struct vbuffer *o, const char *str, ssize_t len,
  836. +               struct file *file)
  837.  {
  838. -  char *val;
  839. +  size_t ret;
  840. +  char *string = len < 0 ? xstrdup (str) : xstrndup (str, len);
  841. +  ret = vbuffer_expand_for_file (o, string, -1, file);
  842. +  free (string);
  843. +  return ret;
  844. +}
  845. +
  846. +/* Install a new expansion vbuffer, returning the current one.  */
  847.  
  848. -  /* Construct the appended variable value.  */
  849. +struct vbuffer *
  850. +install_new_expansion_vbuffer (void)
  851. +{
  852. +  struct vbuffer *old_vbuf = expansion_vbuf;
  853.  
  854. -  char *obuf = variable_buffer;
  855. -  unsigned int olen = variable_buffer_length;
  856. +  expansion_vbuf = xmalloc(sizeof(struct vbuffer));
  857. +  vbuffer_init(expansion_vbuf);
  858.  
  859. -  variable_buffer = 0;
  860. +  return old_vbuf;
  861. +}
  862.  
  863. -  val = variable_append (v->name, strlen (v->name),
  864. -                         current_variable_set_list, 1);
  865. -  variable_buffer_output (val, "", 1);
  866. -  val = variable_buffer;
  867. +/* Restore a previously-saved vbuffer setting freeing the current one.  */
  868.  
  869. -  variable_buffer = obuf;
  870. -  variable_buffer_length = olen;
  871. +void
  872. +restore_expansion_vbuffer (struct vbuffer *old_vbuf)
  873. +{
  874. +  vbuffer_free(expansion_vbuf);
  875. +  free(expansion_vbuf);
  876.  
  877. -  return val;
  878. +  expansion_vbuf = old_vbuf;
  879.  }
  880.  
  881. -/* Like variable_expand_for_file, but the returned string is malloc'd.
  882. -   This function is called a lot.  It wants to be efficient.  */
  883. +/* Expand an argument for an expansion function.
  884. +   The text starting at STR and ending at END is variable-expanded
  885. +   into a null-terminated string that is returned as the value.
  886. +   This is done without clobbering 'variable_buffer' or the current
  887. +   variable-expansion that is in progress.  */
  888.  
  889.  char *
  890. -allocated_variable_expand_for_file (const char *line, struct file *file)
  891. +expand_argument (const char *str, const char *end)
  892.  {
  893. -  char *value;
  894. +  struct vbuffer vbuf;
  895.  
  896. -  char *obuf = variable_buffer;
  897. -  unsigned int olen = variable_buffer_length;
  898. +  vbuffer_expand_ro (vbuffer_init(&vbuf), str, end - str);
  899.  
  900. -  variable_buffer = 0;
  901. +  return vbuf.buffer;
  902. +}
  903.  
  904. -  value = variable_expand_for_file (line, file);
  905. +/* Scan LINE for variable references and expansion-function calls.
  906. +   Build in 'variable_buffer' the result of expanding the references and calls.
  907. +   Return the address of the resulting string, which is null-terminated
  908. +   and is valid only until the next time this function is called.  */
  909.  
  910. -  variable_buffer = obuf;
  911. -  variable_buffer_length = olen;
  912. +char *
  913. +variable_expand (const char *line)
  914. +{
  915. +  vbuffer_expand_ro (vbuffer_reset(expansion_vbuf), line, -1);
  916.  
  917. -  return value;
  918. +  return expansion_vbuf->buffer;
  919.  }
  920.  
  921. -/* Install a new variable_buffer context, returning the current one for
  922. -   safe-keeping.  */
  923. +/* Expand LINE for FILE.  Error messages refer to the file and line where
  924. +   FILE's commands were found.  Expansion uses FILE's variable set list.  */
  925.  
  926. -void
  927. -install_variable_buffer (char **bufp, unsigned int *lenp)
  928. +char *
  929. +variable_expand_for_file (const char *line, struct file *file)
  930.  {
  931. -  *bufp = variable_buffer;
  932. -  *lenp = variable_buffer_length;
  933. +  vbuffer_expand_ro_for_file (vbuffer_reset(expansion_vbuf), line, -1, file);
  934.  
  935. -  variable_buffer = 0;
  936. -  initialize_variable_output ();
  937. +  return expansion_vbuf->buffer;
  938.  }
  939.  
  940. -/* Restore a previously-saved variable_buffer setting (free the current one).
  941. - */
  942. +char *
  943. +allocated_variable_expand (const char *line)
  944. +{
  945. +  struct vbuffer vbuf;
  946.  
  947. -void
  948. -restore_variable_buffer (char *buf, unsigned int len)
  949. +  vbuffer_expand_ro (vbuffer_init(&vbuf), line, -1);
  950. +
  951. +  return vbuf.buffer;
  952. +}
  953. +
  954. +/* Like variable_expand_for_file, but the returned string is malloc'd.  */
  955. +
  956. +char *
  957. +allocated_variable_expand_for_file (const char *line, struct file *file)
  958.  {
  959. -  free (variable_buffer);
  960. +  struct vbuffer vbuf;
  961. +
  962. +  vbuffer_expand_ro_for_file (vbuffer_init(&vbuf), line, -1, file);
  963. +
  964. +  return vbuf.buffer;
  965. +}
  966. +
  967. +char *
  968. +recursively_expand_for_file (struct variable *v, struct file *file)
  969. +{
  970. +  struct vbuffer vbuf;
  971. +
  972. +  vbuffer_expand_variable_for_file (vbuffer_init(&vbuf), v, file);
  973.  
  974. -  variable_buffer = buf;
  975. -  variable_buffer_length = len;
  976. +  return vbuf.buffer;
  977.  }
  978. Index: file.c
  979. ===================================================================
  980. RCS file: /sources/make/make/file.c,v
  981. retrieving revision 1.105
  982. diff -u -r1.105 file.c
  983. --- file.c  5 Mar 2012 14:10:43 -0000   1.105
  984. +++ file.c  15 Mar 2012 21:19:13 -0000
  985. @@ -467,63 +467,66 @@
  986.    if (stem)
  987.      {
  988.        const char *pattern = "%";
  989. -      char *buffer = variable_expand ("");
  990. +      struct vbuffer vbuf;
  991.        struct dep *dp = deps, *dl = 0;
  992.  
  993. +      vbuffer_init (&vbuf);
  994. +
  995.        while (dp != 0)
  996. -        {
  997. -          char *percent;
  998. -          int nl = strlen (dp->name) + 1;
  999. -          char *nm = alloca (nl);
  1000. -          memcpy (nm, dp->name, nl);
  1001. -          percent = find_percent (nm);
  1002. -          if (percent)
  1003. -            {
  1004. -              char *o;
  1005. -
  1006. -              /* We have to handle empty stems specially, because that
  1007. -                 would be equivalent to $(patsubst %,dp->name,) which
  1008. -                 will always be empty.  */
  1009. -              if (stem[0] == '\0')
  1010. -                {
  1011. -                  memmove (percent, percent+1, strlen (percent));
  1012. -                  o = variable_buffer_output (buffer, nm, strlen (nm) + 1);
  1013. -                }
  1014. -              else
  1015. -                o = patsubst_expand_pat (buffer, stem, pattern, nm,
  1016. -                                         pattern+1, percent+1);
  1017. -
  1018. -              /* If the name expanded to the empty string, ignore it.  */
  1019. -              if (buffer[0] == '\0')
  1020. -                {
  1021. -                  struct dep *df = dp;
  1022. -                  if (dp == deps)
  1023. -                    dp = deps = deps->next;
  1024. -                  else
  1025. -                    dp = dl->next = dp->next;
  1026. -                  free_dep (df);
  1027. -                  continue;
  1028. -                }
  1029. -
  1030. -              /* Save the name.  */
  1031. -              dp->name = strcache_add_len (buffer, o - buffer);
  1032. -            }
  1033. -          dp->stem = stem;
  1034. -          dp->staticpattern = 1;
  1035. -          dl = dp;
  1036. -          dp = dp->next;
  1037. -        }
  1038. +   {
  1039. +     char *percent;
  1040. +     int nl = strlen (dp->name) + 1;
  1041. +     char *nm = alloca (nl);
  1042. +     memcpy (nm, dp->name, nl);
  1043. +     percent = find_percent (nm);
  1044. +     if (percent)
  1045. +       {
  1046. +         size_t len;
  1047. +
  1048. +         /* We have to handle empty stems specially, because that
  1049. +        would be equivalent to $(patsubst %,dp->name,) which
  1050. +        will always be empty.  */
  1051. +         if (*stem == '\0')
  1052. +       {
  1053. +         memmove (percent, percent+1, strlen (percent));
  1054. +         len = vbuffer_write (vbuffer_reset (&vbuf), nm, -1);
  1055. +       }
  1056. +         else
  1057. +       len = patsubst_expand_pat (vbuffer_reset (&vbuf), stem,
  1058. +                      pattern, nm,
  1059. +                      pattern+1, percent+1);
  1060. +
  1061. +         /* If the name expanded to the empty string, ignore it.  */
  1062. +         if (len == 0)
  1063. +       {
  1064. +         struct dep *df = dp;
  1065. +         if (dp == deps)
  1066. +           dp = deps = deps->next;
  1067. +         else
  1068. +           dp = dl->next = dp->next;
  1069. +         free_dep (df);
  1070. +         continue;
  1071. +       }
  1072. +
  1073. +         /* Save the name.  */
  1074. +         dp->name = strcache_add_len (vbuf.buffer, len);
  1075. +       }
  1076. +     dp->stem = stem;
  1077. +     dp->staticpattern = 1;
  1078. +     dl = dp;
  1079. +     dp = dp->next;
  1080. +   }
  1081.      }
  1082.  
  1083.    /* Enter them as files, unless they need a 2nd expansion.  */
  1084.    for (d1 = deps; d1 != 0; d1 = d1->next)
  1085.      {
  1086.        if (d1->need_2nd_expansion)
  1087. -        continue;
  1088. +   continue;
  1089.  
  1090.        d1->file = lookup_file (d1->name);
  1091.        if (d1->file == 0)
  1092. -        d1->file = enter_file (d1->name);
  1093. +   d1->file = enter_file (d1->name);
  1094.        d1->staticpattern = 0;
  1095.        d1->name = 0;
  1096.      }
  1097. @@ -573,12 +576,10 @@
  1098.           "$*" so they'll expand properly.  */
  1099.        if (d->staticpattern)
  1100.          {
  1101. -          char *o;
  1102. -          d->name = o = variable_expand ("");
  1103. -          o = subst_expand (o, name, "%", "$*", 1, 2, 0);
  1104. -          *o = '\0';
  1105. +     struct vbuffer vbuf;
  1106. +          subst_expand (vbuffer_init(&vbuf), name, "%", "$*", 1, 2, 0);
  1107.            free (name);
  1108. -          d->name = name = xstrdup (d->name);
  1109. +          d->name = name = xstrdup (vbuf.buffer);
  1110.            d->staticpattern = 0;
  1111.          }
  1112.  
  1113. Index: function.c
  1114. ===================================================================
  1115. RCS file: /sources/make/make/function.c,v
  1116. retrieving revision 1.133
  1117. diff -u -r1.133 function.c
  1118. --- function.c  5 Mar 2012 14:10:43 -0000   1.133
  1119. +++ function.c  15 Mar 2012 21:19:14 -0000
  1120. @@ -34,7 +34,7 @@
  1121.      unsigned char minimum_args;
  1122.      unsigned char maximum_args;
  1123.      char expand_args;
  1124. -    char *(*func_ptr) (char *output, char **argv, const char *fname);
  1125. +   size_t (*func_ptr) (struct vbuffer *output, char **argv, const char *fname);
  1126.    };
  1127.  
  1128.  static unsigned long
  1129. @@ -71,20 +71,23 @@
  1130.     nonzero, substitutions are done only on matches which are complete
  1131.     whitespace-delimited words.  */
  1132.  
  1133. -char *
  1134. -subst_expand (char *o, const char *text, const char *subst, const char *replace,
  1135. -              unsigned int slen, unsigned int rlen, int by_word)
  1136. +size_t
  1137. +subst_expand (struct vbuffer *o, const char *text, const char *subst,
  1138. +              const char *replace, unsigned int slen, unsigned int rlen,
  1139. +              int by_word)
  1140.  {
  1141. +  size_t result = 0;
  1142. +
  1143.    const char *t = text;
  1144.    const char *p;
  1145.  
  1146.    if (slen == 0 && !by_word)
  1147.      {
  1148.        /* The first occurrence of "" in any string is its end.  */
  1149. -      o = variable_buffer_output (o, t, strlen (t));
  1150. +      result += vbuffer_write (o, t, -1);
  1151.        if (rlen > 0)
  1152. -   o = variable_buffer_output (o, replace, rlen);
  1153. -      return o;
  1154. +   result += vbuffer_write (o, replace, rlen);
  1155. +      return result;
  1156.      }
  1157.  
  1158.    do
  1159. @@ -99,14 +102,14 @@
  1160.       if (p == 0)
  1161.         {
  1162.           /* No more matches.  Output everything left on the end.  */
  1163. -         o = variable_buffer_output (o, t, strlen (t));
  1164. -         return o;
  1165. +         result += vbuffer_write (o, t, -1);
  1166. +         return result;
  1167.         }
  1168.     }
  1169.  
  1170.        /* Output everything before this occurrence of the string to replace.  */
  1171.        if (p > t)
  1172. -   o = variable_buffer_output (o, t, p - t);
  1173. +   result += vbuffer_write (o, t, p - t);
  1174.  
  1175.        /* If we're substituting only by fully matched words,
  1176.      or only at the ends of words, check that this case qualifies.  */
  1177. @@ -115,16 +118,16 @@
  1178.                || (p[slen] != '\0' && !isblank ((unsigned char)p[slen]))))
  1179.     /* Struck out.  Output the rest of the string that is
  1180.        no longer to be replaced.  */
  1181. -   o = variable_buffer_output (o, subst, slen);
  1182. +   result += vbuffer_write (o, subst, slen);
  1183.        else if (rlen > 0)
  1184.     /* Output the replacement string.  */
  1185. -   o = variable_buffer_output (o, replace, rlen);
  1186. +   result += vbuffer_write (o, replace, rlen);
  1187.  
  1188.        /* Advance T past the string to be replaced.  */
  1189.        t = p + slen;
  1190.      } while (*t != '\0');
  1191.  
  1192. -  return o;
  1193. +  return result;
  1194.  }
  1195.  
  1196.  
  1197. @@ -138,16 +141,17 @@
  1198.     character _AFTER_ the %, not to the % itself.
  1199.  */
  1200.  
  1201. -char *
  1202. -patsubst_expand_pat (char *o, const char *text,
  1203. +size_t
  1204. +patsubst_expand_pat (struct vbuffer *o, const char *text,
  1205.                       const char *pattern, const char *replace,
  1206.                       const char *pattern_percent, const char *replace_percent)
  1207.  {
  1208. +  size_t result = 0;
  1209. +
  1210.    unsigned int pattern_prepercent_len, pattern_postpercent_len;
  1211.    unsigned int replace_prepercent_len, replace_postpercent_len;
  1212.    const char *t;
  1213.    unsigned int len;
  1214. -  int doneany = 0;
  1215.  
  1216.    /* Record the length of REPLACE before and after the % so we don't have to
  1217.       compute these lengths more than once.  */
  1218. @@ -197,40 +201,34 @@
  1219.  
  1220.        if (fail)
  1221.     /* It didn't match.  Output the string.  */
  1222. -   o = variable_buffer_output (o, t, len);
  1223. +   result += vbuffer_write (o, t, len);
  1224.        else
  1225.     {
  1226.       /* It matched.  Output the replacement.  */
  1227.  
  1228.       /* Output the part of the replacement before the %.  */
  1229. -     o = variable_buffer_output (o, replace, replace_prepercent_len);
  1230. +     result += vbuffer_write (o, replace, replace_prepercent_len);
  1231.  
  1232.       if (replace_percent != 0)
  1233.         {
  1234.           /* Output the part of the matched string that
  1235.          matched the % in the pattern.  */
  1236. -         o = variable_buffer_output (o, t + pattern_prepercent_len,
  1237. -                     len - (pattern_prepercent_len
  1238. +         result += vbuffer_write (o, t + pattern_prepercent_len,
  1239. +                      len - (pattern_prepercent_len
  1240.                          + pattern_postpercent_len));
  1241.           /* Output the part of the replacement after the %.  */
  1242. -         o = variable_buffer_output (o, replace_percent,
  1243. -                     replace_postpercent_len);
  1244. +         result += vbuffer_write (o, replace_percent,
  1245. +                      replace_postpercent_len);
  1246.         }
  1247.     }
  1248.  
  1249.        /* Output a space, but not if the replacement is "".  */
  1250.        if (fail || replace_prepercent_len > 0
  1251.       || (replace_percent != 0 && len + replace_postpercent_len > 0))
  1252. -   {
  1253. -     o = variable_buffer_output (o, " ", 1);
  1254. -     doneany = 1;
  1255. -   }
  1256. +   result += vbuffer_write (o, " ", 1);
  1257.      }
  1258. -  if (doneany)
  1259. -    /* Kill the last space.  */
  1260. -    --o;
  1261.  
  1262. -  return o;
  1263. +  return result - vbuffer_unwrite (o, !!result);
  1264.  }
  1265.  
  1266.  /* Store into VARIABLE_BUFFER at O the result of scanning TEXT
  1267. @@ -243,8 +241,9 @@
  1268.     character _AFTER_ the %, not to the % itself.
  1269.  */
  1270.  
  1271. -char *
  1272. -patsubst_expand (char *o, const char *text, char *pattern, char *replace)
  1273. +size_t
  1274. +patsubst_expand (struct vbuffer *o, const char *text, char *pattern,
  1275. +                 char *replace)
  1276.  {
  1277.    const char *pattern_percent = find_percent (pattern);
  1278.    const char *replace_percent = find_percent (replace);
  1279. @@ -256,7 +255,7 @@
  1280.      ++pattern_percent;
  1281.  
  1282.    return patsubst_expand_pat (o, text, pattern, replace,
  1283. -                              pattern_percent, replace_percent);
  1284. +                 pattern_percent, replace_percent);
  1285.  }
  1286.  
  1287.  
  1288. @@ -310,38 +309,6 @@
  1289.  }
  1290.  
  1291.  
  1292. -/* Find the next comma or ENDPAREN (counting nested STARTPAREN and
  1293. -   ENDPARENtheses), starting at PTR before END.  Return a pointer to
  1294. -   next character.
  1295. -
  1296. -   If no next argument is found, return NULL.
  1297. -*/
  1298. -
  1299. -static char *
  1300. -find_next_argument (char startparen, char endparen,
  1301. -                    const char *ptr, const char *end)
  1302. -{
  1303. -  int count = 0;
  1304. -
  1305. -  for (; ptr < end; ++ptr)
  1306. -    if (*ptr == startparen)
  1307. -      ++count;
  1308. -
  1309. -    else if (*ptr == endparen)
  1310. -      {
  1311. -   --count;
  1312. -   if (count < 0)
  1313. -     return NULL;
  1314. -      }
  1315. -
  1316. -    else if (*ptr == ',' && !count)
  1317. -      return (char *)ptr;
  1318. -
  1319. -  /* We didn't find anything.  */
  1320. -  return NULL;
  1321. -}
  1322. -
  1323. -
  1324.  /* Glob-expand LINE.  The returned pointer is
  1325.     only good until the next call to string_glob.  */
  1326.  
  1327. @@ -399,18 +366,17 @@
  1328.    Builtin functions
  1329.   */
  1330.  
  1331. -static char *
  1332. -func_patsubst (char *o, char **argv, const char *funcname UNUSED)
  1333. +static size_t
  1334. +func_patsubst (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  1335.  {
  1336. -  o = patsubst_expand (o, argv[2], argv[0], argv[1]);
  1337. -  return o;
  1338. +  return patsubst_expand (o, argv[2], argv[0], argv[1]);
  1339.  }
  1340.  
  1341.  
  1342. -static char *
  1343. -func_join (char *o, char **argv, const char *funcname UNUSED)
  1344. +static size_t
  1345. +func_join (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  1346.  {
  1347. -  int doneany = 0;
  1348. +  size_t result = 0;
  1349.  
  1350.    /* Write each word of the first argument directly followed
  1351.       by the corresponding word of the second argument.
  1352. @@ -420,87 +386,87 @@
  1353.    const char *pp;
  1354.    const char *list1_iterator = argv[0];
  1355.    const char *list2_iterator = argv[1];
  1356. +
  1357.    do
  1358.      {
  1359.        unsigned int len1, len2;
  1360.  
  1361.        tp = find_next_token (&list1_iterator, &len1);
  1362.        if (tp != 0)
  1363. -   o = variable_buffer_output (o, tp, len1);
  1364. +   result += vbuffer_write (o, tp, len1);
  1365.  
  1366.        pp = find_next_token (&list2_iterator, &len2);
  1367.        if (pp != 0)
  1368. -   o = variable_buffer_output (o, pp, len2);
  1369. +   result += vbuffer_write (o, pp, len2);
  1370.  
  1371.        if (tp != 0 || pp != 0)
  1372. -   {
  1373. -     o = variable_buffer_output (o, " ", 1);
  1374. -     doneany = 1;
  1375. -   }
  1376. +   result += vbuffer_write (o, " ", 1);
  1377.      }
  1378.    while (tp != 0 || pp != 0);
  1379. -  if (doneany)
  1380. -    /* Kill the last blank.  */
  1381. -    --o;
  1382.  
  1383. -  return o;
  1384. +  return result - vbuffer_unwrite (o, !!result);
  1385.  }
  1386.  
  1387.  
  1388. -static char *
  1389. -func_origin (char *o, char **argv, const char *funcname UNUSED)
  1390. +static size_t
  1391. +func_origin (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  1392.  {
  1393. +  size_t result = 0;
  1394. +
  1395.    /* Expand the argument.  */
  1396.    struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
  1397. +
  1398.    if (v == 0)
  1399. -    o = variable_buffer_output (o, "undefined", 9);
  1400. +    result += vbuffer_write (o, STRING_SIZE_TUPLE("undefined"));
  1401.    else
  1402.      switch (v->origin)
  1403.        {
  1404. -      default:
  1405. -      case o_invalid:
  1406. -   abort ();
  1407. -   break;
  1408.        case o_default:
  1409. -   o = variable_buffer_output (o, "default", 7);
  1410. +   result += vbuffer_write (o, STRING_SIZE_TUPLE("default"));
  1411.     break;
  1412.        case o_env:
  1413. -   o = variable_buffer_output (o, "environment", 11);
  1414. +   result += vbuffer_write (o, STRING_SIZE_TUPLE("environment"));
  1415.     break;
  1416.        case o_file:
  1417. -   o = variable_buffer_output (o, "file", 4);
  1418. +   result += vbuffer_write (o, STRING_SIZE_TUPLE("file"));
  1419.     break;
  1420.        case o_env_override:
  1421. -   o = variable_buffer_output (o, "environment override", 20);
  1422. +   result += vbuffer_write (o, STRING_SIZE_TUPLE("environment override"));
  1423.     break;
  1424.        case o_command:
  1425. -   o = variable_buffer_output (o, "command line", 12);
  1426. +   result += vbuffer_write (o, STRING_SIZE_TUPLE("command line"));
  1427.     break;
  1428.        case o_override:
  1429. -   o = variable_buffer_output (o, "override", 8);
  1430. +   result += vbuffer_write (o, STRING_SIZE_TUPLE("override"));
  1431.     break;
  1432.        case o_automatic:
  1433. -   o = variable_buffer_output (o, "automatic", 9);
  1434. +   result += vbuffer_write (o, STRING_SIZE_TUPLE("automatic"));
  1435. +   break;
  1436. +      case o_invalid:
  1437. +      default:
  1438. +   abort ();
  1439.     break;
  1440.        }
  1441.  
  1442. -  return o;
  1443. +  return result;
  1444.  }
  1445.  
  1446. -static char *
  1447. -func_flavor (char *o, char **argv, const char *funcname UNUSED)
  1448. +static size_t
  1449. +func_flavor (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  1450.  {
  1451. +  size_t result = 0;
  1452. +
  1453.    struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
  1454.  
  1455.    if (v == 0)
  1456. -    o = variable_buffer_output (o, "undefined", 9);
  1457. +    result += vbuffer_write (o, STRING_SIZE_TUPLE("undefined"));
  1458.    else
  1459.      if (v->recursive)
  1460. -      o = variable_buffer_output (o, "recursive", 9);
  1461. +      result += vbuffer_write (o, STRING_SIZE_TUPLE("recursive"));
  1462.      else
  1463. -      o = variable_buffer_output (o, "simple", 6);
  1464. +      result += vbuffer_write (o, STRING_SIZE_TUPLE("simple"));
  1465.  
  1466. -  return o;
  1467. +  return result;
  1468.  }
  1469.  
  1470.  #ifdef VMS
  1471. @@ -514,14 +480,15 @@
  1472.  #endif
  1473.  
  1474.  
  1475. -static char *
  1476. -func_notdir_suffix (char *o, char **argv, const char *funcname)
  1477. +static size_t
  1478. +func_notdir_suffix (struct vbuffer *o, char **argv, const char *funcname)
  1479.  {
  1480. +  size_t result = 0;
  1481. +
  1482.    /* Expand the argument.  */
  1483.    const char *list_iterator = argv[0];
  1484.    const char *p2;
  1485. -  int doneany =0;
  1486. -  unsigned int len=0;
  1487. +  unsigned int len = 0;
  1488.  
  1489.    int is_suffix = funcname[0] == 's';
  1490.    int is_notdir = !is_suffix;
  1491. @@ -529,7 +496,6 @@
  1492.      {
  1493.        const char *p = p2 + len;
  1494.  
  1495. -
  1496.        while (p >= p2 && (!is_suffix || *p != '.'))
  1497.     {
  1498.       if (IS_PATHSEP (*p))
  1499. @@ -543,41 +509,35 @@
  1500.         ++p;
  1501.       else if (*p != '.')
  1502.         continue;
  1503. -     o = variable_buffer_output (o, p, len - (p - p2));
  1504. +     result += vbuffer_write (o, p, len - (p - p2));
  1505.     }
  1506.  #ifdef HAVE_DOS_PATHS
  1507.        /* Handle the case of "d:foo/bar".  */
  1508.        else if (is_notdir && p2[0] && p2[1] == ':')
  1509.     {
  1510.       p = p2 + 2;
  1511. -     o = variable_buffer_output (o, p, len - (p - p2));
  1512. +     result += vbuffer_write (o, p, len - (p - p2));
  1513.     }
  1514.  #endif
  1515.        else if (is_notdir)
  1516. -   o = variable_buffer_output (o, p2, len);
  1517. +   result += vbuffer_write (o, p2, len);
  1518.  
  1519.        if (is_notdir || p >= p2)
  1520. -   {
  1521. -     o = variable_buffer_output (o, " ", 1);
  1522. -     doneany = 1;
  1523. -   }
  1524. +   result += vbuffer_write (o, " ", 1);
  1525.      }
  1526.  
  1527. -  if (doneany)
  1528. -    /* Kill last space.  */
  1529. -    --o;
  1530. -
  1531. -  return o;
  1532. +  return result - vbuffer_unwrite (o, !!result);
  1533.  }
  1534.  
  1535.  
  1536. -static char *
  1537. -func_basename_dir (char *o, char **argv, const char *funcname)
  1538. +static size_t
  1539. +func_basename_dir (struct vbuffer *o, char **argv, const char *funcname)
  1540.  {
  1541. +  size_t result = 0;
  1542. +
  1543.    /* Expand the argument.  */
  1544.    const char *p3 = argv[0];
  1545.    const char *p2;
  1546. -  int doneany = 0;
  1547.    unsigned int len = 0;
  1548.  
  1549.    int is_basename = funcname[0] == 'b';
  1550. @@ -594,111 +554,105 @@
  1551.          }
  1552.  
  1553.        if (p >= p2 && (is_dir))
  1554. -        o = variable_buffer_output (o, p2, ++p - p2);
  1555. +        result += vbuffer_write (o, p2, ++p - p2);
  1556.        else if (p >= p2 && (*p == '.'))
  1557. -        o = variable_buffer_output (o, p2, p - p2);
  1558. +        result += vbuffer_write (o, p2, p - p2);
  1559.  #ifdef HAVE_DOS_PATHS
  1560.        /* Handle the "d:foobar" case */
  1561.        else if (p2[0] && p2[1] == ':' && is_dir)
  1562. -        o = variable_buffer_output (o, p2, 2);
  1563. +        result += vbuffer_write (o, p2, 2);
  1564.  #endif
  1565.        else if (is_dir)
  1566.  #ifdef VMS
  1567. -        o = variable_buffer_output (o, "[]", 2);
  1568. +        result += vbuffer_write (o, "[]", 2);
  1569.  #else
  1570.  #ifndef _AMIGA
  1571. -      o = variable_buffer_output (o, "./", 2);
  1572. +      result += vbuffer_write (o, "./", 2);
  1573.  #else
  1574.        ; /* Just a nop...  */
  1575.  #endif /* AMIGA */
  1576.  #endif /* !VMS */
  1577.        else
  1578.          /* The entire name is the basename.  */
  1579. -        o = variable_buffer_output (o, p2, len);
  1580. +        result += vbuffer_write (o, p2, len);
  1581.  
  1582. -      o = variable_buffer_output (o, " ", 1);
  1583. -      doneany = 1;
  1584. +      result += vbuffer_write (o, " ", 1);
  1585.      }
  1586.  
  1587. -  if (doneany)
  1588. -    /* Kill last space.  */
  1589. -    --o;
  1590. -
  1591. -  return o;
  1592. +  return result - vbuffer_unwrite (o, !!result);
  1593.  }
  1594.  
  1595. -static char *
  1596. -func_addsuffix_addprefix (char *o, char **argv, const char *funcname)
  1597. +static size_t
  1598. +func_addsuffix_addprefix (struct vbuffer *o, char **argv, const char *funcname)
  1599.  {
  1600. +  size_t result = 0;
  1601. +
  1602.    int fixlen = strlen (argv[0]);
  1603.    const char *list_iterator = argv[1];
  1604. -  int is_addprefix = funcname[3] == 'p';
  1605. +  int is_addprefix = funcname[CSTRLEN("add")] == 'p';
  1606.    int is_addsuffix = !is_addprefix;
  1607.  
  1608. -  int doneany = 0;
  1609.    const char *p;
  1610.    unsigned int len;
  1611.  
  1612.    while ((p = find_next_token (&list_iterator, &len)) != 0)
  1613.      {
  1614.        if (is_addprefix)
  1615. -   o = variable_buffer_output (o, argv[0], fixlen);
  1616. -      o = variable_buffer_output (o, p, len);
  1617. +   result += vbuffer_write (o, argv[0], fixlen);
  1618. +      result += vbuffer_write (o, p, len);
  1619.        if (is_addsuffix)
  1620. -   o = variable_buffer_output (o, argv[0], fixlen);
  1621. -      o = variable_buffer_output (o, " ", 1);
  1622. -      doneany = 1;
  1623. +   result += vbuffer_write (o, argv[0], fixlen);
  1624. +      result += vbuffer_write (o, " ", 1);
  1625.      }
  1626.  
  1627. -  if (doneany)
  1628. -    /* Kill last space.  */
  1629. -    --o;
  1630. -
  1631. -  return o;
  1632. +  return result - vbuffer_unwrite (o, !!result);
  1633.  }
  1634.  
  1635. -static char *
  1636. -func_subst (char *o, char **argv, const char *funcname UNUSED)
  1637. -{
  1638. -  o = subst_expand (o, argv[2], argv[0], argv[1], strlen (argv[0]),
  1639. -           strlen (argv[1]), 0);
  1640.  
  1641. -  return o;
  1642. +static size_t
  1643. +func_subst (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  1644. +{
  1645. +  return subst_expand (o, argv[2], argv[0], argv[1], strlen (argv[0]),
  1646. +              strlen (argv[1]), 0);
  1647.  }
  1648.  
  1649.  
  1650. -static char *
  1651. -func_firstword (char *o, char **argv, const char *funcname UNUSED)
  1652. +static size_t
  1653. +func_firstword (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  1654.  {
  1655. -  unsigned int i;
  1656. +  size_t result = 0;
  1657. +
  1658. +  unsigned int len;
  1659.    const char *words = argv[0];    /* Use a temp variable for find_next_token */
  1660. -  const char *p = find_next_token (&words, &i);
  1661. +  const char *p = find_next_token (&words, &len);
  1662.  
  1663.    if (p != 0)
  1664. -    o = variable_buffer_output (o, p, i);
  1665. +    result += vbuffer_write (o, p, len);
  1666.  
  1667. -  return o;
  1668. +  return result;
  1669.  }
  1670.  
  1671. -static char *
  1672. -func_lastword (char *o, char **argv, const char *funcname UNUSED)
  1673. +static size_t
  1674. +func_lastword (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  1675.  {
  1676. -  unsigned int i;
  1677. +  size_t result = 0;
  1678. +
  1679. +  unsigned int len;
  1680.    const char *words = argv[0];    /* Use a temp variable for find_next_token */
  1681.    const char *p = NULL;
  1682.    const char *t;
  1683.  
  1684. -  while ((t = find_next_token (&words, &i)))
  1685. +  while ((t = find_next_token (&words, &len)))
  1686.      p = t;
  1687.  
  1688.    if (p != 0)
  1689. -    o = variable_buffer_output (o, p, i);
  1690. +    result += vbuffer_write (o, p, len);
  1691.  
  1692. -  return o;
  1693. +  return result;
  1694.  }
  1695.  
  1696. -static char *
  1697. -func_words (char *o, char **argv, const char *funcname UNUSED)
  1698. +static size_t
  1699. +func_words (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  1700.  {
  1701.    int i = 0;
  1702.    const char *word_iterator = argv[0];
  1703. @@ -708,9 +662,8 @@
  1704.      ++i;
  1705.  
  1706.    sprintf (buf, "%d", i);
  1707. -  o = variable_buffer_output (o, buf, strlen (buf));
  1708.  
  1709. -  return o;
  1710. +  return vbuffer_write (o, buf, -1);
  1711.  }
  1712.  
  1713.  /* Set begpp to point to the first non-whitespace character of the string,
  1714. @@ -744,10 +697,11 @@
  1715.  }
  1716.  
  1717.  
  1718. -
  1719. -static char *
  1720. -func_word (char *o, char **argv, const char *funcname UNUSED)
  1721. +static size_t
  1722. +func_word (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  1723.  {
  1724. +  size_t result = 0;
  1725. +
  1726.    const char *end_p;
  1727.    const char *p;
  1728.    int i;
  1729. @@ -766,14 +720,17 @@
  1730.        break;
  1731.  
  1732.    if (i == 0)
  1733. -    o = variable_buffer_output (o, p, end_p - p);
  1734. +    result += vbuffer_write (o, p, end_p - p);
  1735.  
  1736. -  return o;
  1737. +  return result;
  1738.  }
  1739.  
  1740. -static char *
  1741. -func_wordlist (char *o, char **argv, const char *funcname UNUSED)
  1742. +
  1743. +static size_t
  1744. +func_wordlist (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  1745.  {
  1746. +  size_t result = 0;
  1747. +
  1748.    int start, count;
  1749.  
  1750.    /* Check the arguments.  */
  1751. @@ -805,32 +762,35 @@
  1752.              ;
  1753.  
  1754.            /* Return the stuff in the middle.  */
  1755. -          o = variable_buffer_output (o, p, end_p - p);
  1756. +          result += vbuffer_write (o, p, end_p - p);
  1757.          }
  1758.      }
  1759.  
  1760. -  return o;
  1761. +  return result;
  1762.  }
  1763.  
  1764. -static char *
  1765. -func_findstring (char *o, char **argv, const char *funcname UNUSED)
  1766. +static size_t
  1767. +func_findstring (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  1768.  {
  1769. +  size_t result = 0;
  1770. +
  1771.    /* Find the first occurrence of the first string in the second.  */
  1772.    if (strstr (argv[1], argv[0]) != 0)
  1773. -    o = variable_buffer_output (o, argv[0], strlen (argv[0]));
  1774. +    result += vbuffer_write (o, argv[0], strlen (argv[0]));
  1775.  
  1776. -  return o;
  1777. +  return result;
  1778.  }
  1779.  
  1780. -static char *
  1781. -func_foreach (char *o, char **argv, const char *funcname UNUSED)
  1782. +static size_t
  1783. +func_foreach (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  1784.  {
  1785. +  size_t result = 0;
  1786. +
  1787.    /* expand only the first two.  */
  1788.    char *varname = expand_argument (argv[0], NULL);
  1789.    char *list = expand_argument (argv[1], NULL);
  1790.    const char *body = argv[2];
  1791.  
  1792. -  int doneany = 0;
  1793.    const char *list_iterator = list;
  1794.    const char *p;
  1795.    unsigned int len;
  1796. @@ -842,28 +802,24 @@
  1797.    /* loop through LIST,  put the value in VAR and expand BODY */
  1798.    while ((p = find_next_token (&list_iterator, &len)) != 0)
  1799.      {
  1800. -      char *result = 0;
  1801. +      char *expansion = 0;
  1802.  
  1803.        free (var->value);
  1804.        var->value = xstrndup (p, len);
  1805.  
  1806. -      result = allocated_variable_expand (body);
  1807. +      expansion = allocated_variable_expand (body);
  1808.  
  1809. -      o = variable_buffer_output (o, result, strlen (result));
  1810. -      o = variable_buffer_output (o, " ", 1);
  1811. -      doneany = 1;
  1812. -      free (result);
  1813. -    }
  1814. +      result += vbuffer_write (o, expansion, strlen (expansion));
  1815. +      result += vbuffer_write (o, " ", 1);
  1816.  
  1817. -  if (doneany)
  1818. -    /* Kill the last space.  */
  1819. -    --o;
  1820. +      free (expansion);
  1821. +    }
  1822.  
  1823.    pop_variable_scope ();
  1824.    free (varname);
  1825.    free (list);
  1826.  
  1827. -  return o;
  1828. +  return result - vbuffer_unwrite (o, !!result);
  1829.  }
  1830.  
  1831.  struct a_word
  1832. @@ -905,9 +861,11 @@
  1833.    int length;
  1834.  };
  1835.  
  1836. -static char *
  1837. -func_filter_filterout (char *o, char **argv, const char *funcname)
  1838. +static size_t
  1839. +func_filter_filterout (struct vbuffer *o, char **argv, const char *funcname)
  1840.  {
  1841. +  size_t result = 0;
  1842. +
  1843.    struct a_word *wordhead;
  1844.    struct a_word **wordtail;
  1845.    struct a_word *wp;
  1846. @@ -989,8 +947,6 @@
  1847.  
  1848.    if (words)
  1849.      {
  1850. -      int doneany = 0;
  1851. -
  1852.        /* Run each pattern through the words, killing words.  */
  1853.        for (pp = pathead; pp != 0; pp = pp->next)
  1854.     {
  1855. @@ -1019,28 +975,25 @@
  1856.        for (wp = wordhead; wp != 0; wp = wp->next)
  1857.     if (is_filter ? wp->matched : !wp->matched)
  1858.       {
  1859. -       o = variable_buffer_output (o, wp->str, strlen (wp->str));
  1860. -       o = variable_buffer_output (o, " ", 1);
  1861. -       doneany = 1;
  1862. +       result += vbuffer_write (o, wp->str, -1);
  1863. +       result += vbuffer_write (o, " ", 1);
  1864.       }
  1865.  
  1866. -      if (doneany)
  1867. -   /* Kill the last space.  */
  1868. -   --o;
  1869.      }
  1870.  
  1871.    if (hashing)
  1872.      hash_free (&a_word_table, 0);
  1873.  
  1874. -  return o;
  1875. +  return result - vbuffer_unwrite (o, !!result);
  1876.  }
  1877.  
  1878.  
  1879. -static char *
  1880. -func_strip (char *o, char **argv, const char *funcname UNUSED)
  1881. +static size_t
  1882. +func_strip (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  1883.  {
  1884. +  size_t result = 0;
  1885. +
  1886.    const char *p = argv[0];
  1887. -  int doneany = 0;
  1888.  
  1889.    while (*p != '\0')
  1890.      {
  1891. @@ -1051,26 +1004,21 @@
  1892.     ++p;
  1893.        word_start = p;
  1894.        for (i=0; *p != '\0' && !isspace ((unsigned char)*p); ++p, ++i)
  1895. -   {}
  1896. +   ;
  1897.        if (!i)
  1898.     break;
  1899. -      o = variable_buffer_output (o, word_start, i);
  1900. -      o = variable_buffer_output (o, " ", 1);
  1901. -      doneany = 1;
  1902. +      result += vbuffer_write (o, word_start, i);
  1903. +      result += vbuffer_write (o, " ", 1);
  1904.      }
  1905.  
  1906. -  if (doneany)
  1907. -    /* Kill the last space.  */
  1908. -    --o;
  1909. -
  1910. -  return o;
  1911. +  return result - vbuffer_unwrite (o, !!result);
  1912.  }
  1913.  
  1914.  /*
  1915.    Print a warning or fatal message.
  1916.  */
  1917. -static char *
  1918. -func_error (char *o, char **argv, const char *funcname)
  1919. +size_t
  1920. +func_error (struct vbuffer *o UNUSED, char **argv, const char *funcname)
  1921.  {
  1922.    char **argvp;
  1923.    char *msg, *p;
  1924. @@ -1111,16 +1059,18 @@
  1925.    }
  1926.  
  1927.    /* The warning function expands to the empty string.  */
  1928. -  return o;
  1929. +  return 0;
  1930.  }
  1931.  
  1932.  
  1933.  /*
  1934.    chop argv[0] into words, and sort them.
  1935.   */
  1936. -static char *
  1937. -func_sort (char *o, char **argv, const char *funcname UNUSED)
  1938. +static size_t
  1939. +func_sort (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  1940.  {
  1941. +  size_t result = 0;
  1942. +
  1943.    const char *t;
  1944.    char **words;
  1945.    int wordi;
  1946. @@ -1133,7 +1083,8 @@
  1947.    wordi = 0;
  1948.    while ((p = find_next_token (&t, NULL)) != 0)
  1949.      {
  1950. -      ++t;
  1951. +      if (*t != '\0')
  1952. +   ++t;
  1953.        ++wordi;
  1954.      }
  1955.  
  1956. @@ -1144,7 +1095,8 @@
  1957.    wordi = 0;
  1958.    while ((p = find_next_token (&t, &len)) != 0)
  1959.      {
  1960. -      ++t;
  1961. +      if (*t != '\0')
  1962. +   ++t;
  1963.        p[len] = '\0';
  1964.        words[wordi++] = p;
  1965.      }
  1966. @@ -1161,18 +1113,18 @@
  1967.            if (i == wordi - 1 || strlen (words[i + 1]) != len
  1968.                || strcmp (words[i], words[i + 1]))
  1969.              {
  1970. -              o = variable_buffer_output (o, words[i], len);
  1971. -              o = variable_buffer_output (o, " ", 1);
  1972. +              result += vbuffer_write (o, words[i], len);
  1973. +              result += vbuffer_write (o, " ", 1);
  1974.              }
  1975.          }
  1976.  
  1977.        /* Kill the last space.  */
  1978. -      --o;
  1979. +      result -= vbuffer_unwrite (o, 1);
  1980.      }
  1981.  
  1982.    free (words);
  1983.  
  1984. -  return o;
  1985. +  return result;
  1986.  }
  1987.  
  1988.  /*
  1989. @@ -1187,9 +1139,11 @@
  1990.    example).
  1991.  */
  1992.  
  1993. -static char *
  1994. -func_if (char *o, char **argv, const char *funcname UNUSED)
  1995. +static size_t
  1996. +func_if (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  1997.  {
  1998. +  size_t ret = 0;
  1999. +
  2000.    const char *begp = argv[0];
  2001.    const char *endp = begp + strlen (argv[0]) - 1;
  2002.    int result = 0;
  2003. @@ -1218,12 +1172,12 @@
  2004.      {
  2005.        char *expansion = expand_argument (*argv, NULL);
  2006.  
  2007. -      o = variable_buffer_output (o, expansion, strlen (expansion));
  2008. +      ret += vbuffer_write (o, expansion, strlen (expansion));
  2009.  
  2010.        free (expansion);
  2011.      }
  2012.  
  2013. -  return o;
  2014. +  return ret;
  2015.  }
  2016.  
  2017.  /*
  2018. @@ -1240,15 +1194,17 @@
  2019.    (short-circuiting).
  2020.  */
  2021.  
  2022. -static char *
  2023. -func_or (char *o, char **argv, const char *funcname UNUSED)
  2024. +static size_t
  2025. +func_or (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  2026.  {
  2027. +  size_t ret = 0;
  2028. +
  2029.    for ( ; *argv ; ++argv)
  2030.      {
  2031.        const char *begp = *argv;
  2032.        const char *endp = begp + strlen (*argv) - 1;
  2033.        char *expansion;
  2034. -      int result = 0;
  2035. +      int result;
  2036.  
  2037.        /* Find the result of the condition: if it's false keep going.  */
  2038.  
  2039. @@ -1268,12 +1224,12 @@
  2040.          }
  2041.  
  2042.        /* It's true!  Keep this result and return.  */
  2043. -      o = variable_buffer_output (o, expansion, result);
  2044. +      ret += vbuffer_write (o, expansion, result);
  2045.        free (expansion);
  2046.        break;
  2047.      }
  2048.  
  2049. -  return o;
  2050. +  return ret;
  2051.  }
  2052.  
  2053.  /*
  2054. @@ -1290,21 +1246,23 @@
  2055.    (short-circuiting).
  2056.  */
  2057.  
  2058. -static char *
  2059. -func_and (char *o, char **argv, const char *funcname UNUSED)
  2060. +static size_t
  2061. +func_and (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  2062.  {
  2063. +  size_t ret = 0;
  2064. +
  2065.    char *expansion;
  2066. -  int result;
  2067.  
  2068.    while (1)
  2069.      {
  2070.        const char *begp = *argv;
  2071.        const char *endp = begp + strlen (*argv) - 1;
  2072. +      int result;
  2073.  
  2074.        /* An empty condition is always false.  */
  2075.        strip_whitespace (&begp, &endp);
  2076.        if (begp > endp)
  2077. -        return o;
  2078. +        return 0;
  2079.  
  2080.        expansion = expand_argument (begp, endp+1);
  2081.        result = strlen (expansion);
  2082. @@ -1320,26 +1278,29 @@
  2083.          free (expansion);
  2084.        else
  2085.          {
  2086. -          o = variable_buffer_output (o, expansion, result);
  2087. +          ret += vbuffer_write (o, expansion, result);
  2088.            break;
  2089.          }
  2090.      }
  2091.  
  2092.    free (expansion);
  2093.  
  2094. -  return o;
  2095. +  return ret;
  2096.  }
  2097.  
  2098. -static char *
  2099. -func_wildcard (char *o, char **argv, const char *funcname UNUSED)
  2100. +static size_t
  2101. +func_wildcard (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  2102.  {
  2103. +  size_t result = 0;
  2104. +
  2105.  #ifdef _AMIGA
  2106.     o = wildcard_expansion (argv[0], o);
  2107.  #else
  2108.     char *p = string_glob (argv[0]);
  2109. -   o = variable_buffer_output (o, p, strlen (p));
  2110. +   result += vbuffer_write (o, p, strlen (p));
  2111.  #endif
  2112. -   return o;
  2113. +
  2114. +   return result;
  2115.  }
  2116.  
  2117.  /*
  2118. @@ -1350,36 +1311,38 @@
  2119.    Treat the arguments as a segment of makefile, and parse them.
  2120.  */
  2121.  
  2122. -static char *
  2123. -func_eval (char *o, char **argv, const char *funcname UNUSED)
  2124. +static size_t
  2125. +func_eval (struct vbuffer *o UNUSED, char **argv, const char *funcname UNUSED)
  2126.  {
  2127. -  char *buf;
  2128. -  unsigned int len;
  2129. +  struct vbuffer *vbuf;
  2130.  
  2131.    /* Eval the buffer.  Pop the current variable buffer setting so that the
  2132.       eval'd code can use its own without conflicting.  */
  2133.  
  2134. -  install_variable_buffer (&buf, &len);
  2135. +  vbuf = install_new_expansion_vbuffer ();
  2136.  
  2137.    eval_buffer (argv[0]);
  2138.  
  2139. -  restore_variable_buffer (buf, len);
  2140. +  restore_expansion_vbuffer (vbuf);
  2141.  
  2142. -  return o;
  2143. +  /* Eval always expands to nothing. */
  2144. +  return 0;
  2145.  }
  2146.  
  2147.  
  2148. -static char *
  2149. -func_value (char *o, char **argv, const char *funcname UNUSED)
  2150. +static size_t
  2151. +func_value (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  2152.  {
  2153. +  size_t result = 0;
  2154. +
  2155.    /* Look up the variable.  */
  2156.    struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
  2157.  
  2158.    /* Copy its value into the output buffer without expanding it.  */
  2159.    if (v)
  2160. -    o = variable_buffer_output (o, v->value, strlen(v->value));
  2161. +    result += vbuffer_write (o, v->value, -1);
  2162.  
  2163. -  return o;
  2164. +  return result;
  2165.  }
  2166.  
  2167.  /*
  2168. @@ -1619,9 +1582,10 @@
  2169.  
  2170.  #else
  2171.  #ifndef _AMIGA
  2172. -char *
  2173. -func_shell_base (char *o, char **argv, int trim_newlines)
  2174. +size_t
  2175. +func_shell_base (struct vbuffer *o, char **argv, int trim_newlines)
  2176.  {
  2177. +  size_t result = 0;
  2178.    char *batch_filename = NULL;
  2179.  
  2180.  #ifdef __MSDOS__
  2181. @@ -1650,7 +1614,7 @@
  2182.  #ifdef WINDOWS32
  2183.        just_print_flag = j_p_f;
  2184.  #endif
  2185. -      return o;
  2186. +      return 0;
  2187.      }
  2188.  #endif
  2189.  
  2190. @@ -1683,7 +1647,7 @@
  2191.    if (pipedes[0] < 0)
  2192.      {
  2193.        perror_with_name (error_prefix, "pipe");
  2194. -      return o;
  2195. +      return 0;
  2196.      }
  2197.  #elif defined(WINDOWS32)
  2198.    windows32_openpipe (pipedes, &pid, command_argv, envp);
  2199. @@ -1694,14 +1658,14 @@
  2200.      {
  2201.        /* Open of the pipe failed, mark as failed execution.  */
  2202.        shell_function_completed = -1;
  2203. -      return o;
  2204. +      return 0;
  2205.      }
  2206.    else
  2207.  #else
  2208.    if (pipe (pipedes) < 0)
  2209.      {
  2210.        perror_with_name (error_prefix, "pipe");
  2211. -      return o;
  2212. +      return 0;
  2213.      }
  2214.  
  2215.  # ifdef __EMX__
  2216. @@ -1800,13 +1764,13 @@
  2217.       /* The child finished normally.  Replace all newlines in its output
  2218.          with spaces, and put that in the variable output buffer.  */
  2219.       fold_newlines (buffer, &i, trim_newlines);
  2220. -     o = variable_buffer_output (o, buffer, i);
  2221. +     result += vbuffer_write (o, buffer, i);
  2222.     }
  2223.  
  2224.        free (buffer);
  2225.      }
  2226.  
  2227. -  return o;
  2228. +  return result;
  2229.  }
  2230.  
  2231.  #else  /* _AMIGA */
  2232. @@ -1892,14 +1856,14 @@
  2233.    Close (child_stdout);
  2234.  
  2235.    fold_newlines (buffer, &i, trim_newlines);
  2236. -  o = variable_buffer_output (o, buffer, i);
  2237. +  result += vbuffer_write (o, buffer, i);
  2238.    free (buffer);
  2239.    return o;
  2240.  }
  2241.  #endif  /* _AMIGA */
  2242.  
  2243. -char *
  2244. -func_shell (char *o, char **argv, const char *funcname UNUSED)
  2245. +size_t
  2246. +func_shell (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  2247.  {
  2248.    return func_shell_base (o, argv, 1);
  2249.  }
  2250. @@ -1914,8 +1878,7 @@
  2251.  func_eq (char *o, char **argv, char *funcname UNUSED)
  2252.  {
  2253.    int result = ! strcmp (argv[0], argv[1]);
  2254. -  o = variable_buffer_output (o,  result ? "1" : "", result);
  2255. -  return o;
  2256. +  return vbuffer_write (o,  result ? "1" : "", result);
  2257.  }
  2258.  
  2259.  
  2260. @@ -1930,8 +1893,7 @@
  2261.    while (isspace ((unsigned char)*s))
  2262.      s++;
  2263.    result = ! (*s);
  2264. -  o = variable_buffer_output (o,  result ? "1" : "", result);
  2265. -  return o;
  2266. +  return vbuffer_write (o,  result ? "1" : "", result);
  2267.  }
  2268.  #endif
  2269.  
  2270. @@ -2058,13 +2020,14 @@
  2271.  }
  2272.  
  2273.  
  2274. -static char *
  2275. -func_realpath (char *o, char **argv, const char *funcname UNUSED)
  2276. +static size_t
  2277. +func_realpath (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  2278.  {
  2279. +  size_t result = 0;
  2280. +
  2281.    /* Expand the argument.  */
  2282.    const char *p = argv[0];
  2283.    const char *path = 0;
  2284. -  int doneany = 0;
  2285.    unsigned int len = 0;
  2286.  #ifndef HAVE_REALPATH
  2287.    struct stat st;
  2288. @@ -2087,22 +2050,17 @@
  2289.  #endif
  2290.               )
  2291.              {
  2292. -              o = variable_buffer_output (o, out, strlen (out));
  2293. -              o = variable_buffer_output (o, " ", 1);
  2294. -              doneany = 1;
  2295. +              result += vbuffer_write (o, out, -1);
  2296. +              result += vbuffer_write (o, " ", 1);
  2297.              }
  2298.          }
  2299.      }
  2300.  
  2301. -  /* Kill last space.  */
  2302. -  if (doneany)
  2303. -    --o;
  2304. -
  2305. -  return o;
  2306. +  return result - vbuffer_unwrite (o, !!result);
  2307.  }
  2308.  
  2309. -static char *
  2310. -func_file (char *o, char **argv, const char *funcname UNUSED)
  2311. +static size_t
  2312. +func_file (struct vbuffer *o UNUSED, char **argv, const char *funcname UNUSED)
  2313.  {
  2314.    char *fn = argv[0];
  2315.  
  2316. @@ -2137,16 +2095,17 @@
  2317.    else
  2318.      fatal (reading_file, _("Invalid file operation: %s"), fn);
  2319.  
  2320. -  return o;
  2321. +  return 0;
  2322.  }
  2323.  
  2324. -static char *
  2325. -func_abspath (char *o, char **argv, const char *funcname UNUSED)
  2326. +static size_t
  2327. +func_abspath (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  2328.  {
  2329. +  size_t result = 0;
  2330. +
  2331.    /* Expand the argument.  */
  2332.    const char *p = argv[0];
  2333.    const char *path = 0;
  2334. -  int doneany = 0;
  2335.    unsigned int len = 0;
  2336.    PATH_VAR (in);
  2337.    PATH_VAR (out);
  2338. @@ -2160,18 +2119,13 @@
  2339.  
  2340.            if (abspath (in, out))
  2341.              {
  2342. -              o = variable_buffer_output (o, out, strlen (out));
  2343. -              o = variable_buffer_output (o, " ", 1);
  2344. -              doneany = 1;
  2345. +              result += vbuffer_write (o, out, strlen (out));
  2346. +              result += vbuffer_write (o, " ", 1);
  2347.              }
  2348.          }
  2349.      }
  2350.  
  2351. -  /* Kill last space.  */
  2352. -  if (doneany)
  2353. -    --o;
  2354. -
  2355. -  return o;
  2356. +  return result - vbuffer_unwrite (o, !!result);
  2357.  }
  2358.  
  2359.  /* Lookup table for builtin functions.
  2360. @@ -2186,7 +2140,7 @@
  2361.     EXPAND_ARGS means that all arguments should be expanded before invocation.
  2362.     Functions that do namespace tricks (foreach) don't automatically expand.  */
  2363.  
  2364. -static char *func_call (char *o, char **argv, const char *funcname);
  2365. +static size_t func_call (struct vbuffer *o, char **argv, const char *funcname);
  2366.  
  2367.  
  2368.  static struct function_table_entry function_table_init[] =
  2369. @@ -2239,8 +2193,8 @@
  2370.  
  2371.  /* These must come after the definition of function_table.  */
  2372.  
  2373. -static char *
  2374. -expand_builtin_function (char *o, int argc, char **argv,
  2375. +static size_t
  2376. +expand_builtin_function (struct vbuffer *o, int argc, char **argv,
  2377.                           const struct function_table_entry *entry_p)
  2378.  {
  2379.    if (argc < (int)entry_p->minimum_args)
  2380. @@ -2253,7 +2207,7 @@
  2381.       rather than in each one.  We can change it later if necessary.  */
  2382.  
  2383.    if (!argc)
  2384. -    return o;
  2385. +    return 0;
  2386.  
  2387.    if (!entry_p->func_ptr)
  2388.      fatal (*expanding_var,
  2389. @@ -2265,45 +2219,64 @@
  2390.  /* Check for a function invocation in *STRINGP.  *STRINGP points at the
  2391.     opening ( or { and is not null-terminated.  If a function invocation
  2392.     is found, expand it into the buffer at *OP, updating *OP, incrementing
  2393. -   *STRINGP past the reference and returning nonzero.  If not, return zero.  */
  2394. +   *STRINGP past the reference and returning the amount of bytes written.
  2395. +   If not, return -1.  */
  2396.  
  2397.  int
  2398. -handle_function (char **op, const char **stringp)
  2399. +handle_function (struct vbuffer *o, char **stringp)
  2400.  {
  2401. +  size_t result = 0;
  2402. +
  2403.    const struct function_table_entry *entry_p;
  2404.    char openparen = (*stringp)[0];
  2405.    char closeparen = openparen == '(' ? ')' : '}';
  2406. -  const char *beg;
  2407. -  const char *end;
  2408. -  int count = 0;
  2409. -  char *abeg = NULL;
  2410. +  char *beg;
  2411. +  char *end;
  2412. +  int count;
  2413.    char **argv, **argvp;
  2414. -  int nargs;
  2415. +  int nargs, maxargs;
  2416. +  struct vbuffer argbuf;
  2417.  
  2418.    beg = *stringp + 1;
  2419.  
  2420.    entry_p = lookup_function (beg);
  2421.  
  2422.    if (!entry_p)
  2423. -    return 0;
  2424. +    return -1;
  2425. +
  2426. +  vbuffer_init(&argbuf);
  2427.  
  2428.    /* We found a builtin function.  Find the beginning of its arguments (skip
  2429.       whitespace after the name).  */
  2430.  
  2431.    beg = next_token (beg + entry_p->len);
  2432. +  maxargs = entry_p->maximum_args;
  2433.  
  2434.    /* Find the end of the function invocation, counting nested use of
  2435.       whichever kind of parens we use.  Since we're looking, count commas
  2436.       to get a rough estimate of how many arguments we might have.  The
  2437.       count might be high, but it'll never be low.  */
  2438.  
  2439. -  for (nargs=1, end=beg; *end != '\0'; ++end)
  2440. -    if (*end == ',')
  2441. -      ++nargs;
  2442. -    else if (*end == openparen)
  2443. +
  2444. +  nargs=1;
  2445. +  *((char **) argbuf.ptr) = beg;
  2446. +  argbuf.ptr += sizeof (char *);
  2447. +
  2448. +  count = 0;
  2449. +  for (end=beg; *end != '\0'; ++end)
  2450. +    if (*end == openparen)
  2451.        ++count;
  2452.      else if (*end == closeparen && --count < 0)
  2453.        break;
  2454. +    else if (count == 0 && *end == ',' && nargs != maxargs)
  2455. +      {
  2456. +   *end = '\0';
  2457. +   nargs++;
  2458. +
  2459. +   vbuffer_reserve(&argbuf, sizeof (char *));
  2460. +   *((char **) argbuf.ptr) = end + 1;
  2461. +   argbuf.ptr += sizeof (char *);
  2462. +      }
  2463.  
  2464.    if (count >= 0)
  2465.      fatal (*expanding_var,
  2466. @@ -2312,8 +2285,14 @@
  2467.  
  2468.    *stringp = end;
  2469.  
  2470. -  /* Get some memory to store the arg pointers.  */
  2471. -  argvp = argv = alloca (sizeof (char *) * (nargs + 2));
  2472. +  *end = '\0';
  2473. +
  2474. +  /* NULL-terminate the arg vector. */
  2475. +  vbuffer_reserve(&argbuf, sizeof (char *));
  2476. +  *((char **) argbuf.ptr) = NULL;
  2477. +  argbuf.ptr += sizeof (char *);
  2478. +
  2479. +  argv = (char **) argbuf.buffer;
  2480.  
  2481.    /* Chop the string into arguments, then a nul.  As soon as we hit
  2482.       MAXIMUM_ARGS (if it's >0) assume the rest of the string is part of the
  2483. @@ -2325,59 +2304,30 @@
  2484.  
  2485.    if (entry_p->expand_args)
  2486.      {
  2487. -      const char *p;
  2488. -      for (p=beg, nargs=0; p <= end; ++argvp)
  2489. -        {
  2490. -          const char *next;
  2491. -
  2492. -          ++nargs;
  2493. -
  2494. -          if (nargs == entry_p->maximum_args
  2495. -              || (! (next = find_next_argument (openparen, closeparen, p, end))))
  2496. -            next = end;
  2497. -
  2498. -          *argvp = expand_argument (p, next);
  2499. -          p = next + 1;
  2500. -        }
  2501. -    }
  2502. -  else
  2503. -    {
  2504. -      int len = end - beg;
  2505. -      char *p, *aend;
  2506. -
  2507. -      abeg = xmalloc (len+1);
  2508. -      memcpy (abeg, beg, len);
  2509. -      abeg[len] = '\0';
  2510. -      aend = abeg + len;
  2511. -
  2512. -      for (p=abeg, nargs=0; p <= aend; ++argvp)
  2513. -        {
  2514. -          char *next;
  2515. -
  2516. -          ++nargs;
  2517. -
  2518. -          if (nargs == entry_p->maximum_args
  2519. -              || (! (next = find_next_argument (openparen, closeparen, p, aend))))
  2520. -            next = aend;
  2521. -
  2522. -          *argvp = p;
  2523. -          *next = '\0';
  2524. -          p = next + 1;
  2525. -        }
  2526. +      int i;
  2527. +      size_t *offs = alloca ((nargs + 1) * sizeof (size_t));
  2528. +      argv = memcpy (alloca ((nargs + 1) * sizeof (char *)),
  2529. +              argv, (nargs + 1) * sizeof (char *));
  2530. +
  2531. +      vbuffer_reset(&argbuf);
  2532. +      offs[0] = 0;
  2533. +      for (i=0, argvp=argv; *argvp != 0; ++argvp, ++i)
  2534. +   {
  2535. +     offs[i + 1] = offs[i] + vbuffer_expand (&argbuf, *argvp, -1) + 1;
  2536. +     *argbuf.ptr++ = '\0';
  2537. +   }
  2538. +      for (i=0, argvp=argv; *argvp != 0; ++argvp, ++i)
  2539. +   *argvp = argbuf.buffer + offs[i];
  2540.      }
  2541. -  *argvp = NULL;
  2542.  
  2543.    /* Finally!  Run the function...  */
  2544. -  *op = expand_builtin_function (*op, nargs, argv, entry_p);
  2545. +  result += expand_builtin_function (o, nargs, argv, entry_p);
  2546.  
  2547. -  /* Free memory.  */
  2548. -  if (entry_p->expand_args)
  2549. -    for (argvp=argv; *argvp != 0; ++argvp)
  2550. -      free (*argvp);
  2551. -  else if (abeg)
  2552. -    free (abeg);
  2553. +  *end = closeparen;
  2554.  
  2555. -  return 1;
  2556. +  vbuffer_free(&argbuf);
  2557. +
  2558. +  return result;
  2559.  }
  2560.  
  2561.  
  2562. @@ -2385,9 +2335,11 @@
  2563.     function or a make variable, in the context of the rest of the arguments
  2564.     assigned to $1, $2, ... $N.  $0 is the name of the function.  */
  2565.  
  2566. -static char *
  2567. -func_call (char *o, char **argv, const char *funcname UNUSED)
  2568. +static size_t
  2569. +func_call (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  2570.  {
  2571. +  size_t result = 0;
  2572. +
  2573.    static int max_args = 0;
  2574.    char *fname;
  2575.    char *cp;
  2576. @@ -2411,7 +2363,7 @@
  2577.  
  2578.    /* Calling nothing is a no-op */
  2579.    if (*fname == '\0')
  2580. -    return o;
  2581. +    return 0;
  2582.  
  2583.    /* Are we invoking a builtin function?  */
  2584.  
  2585. @@ -2434,7 +2386,7 @@
  2586.      warn_undefined (fname, flen);
  2587.  
  2588.    if (v == 0 || *v->value == '\0')
  2589. -    return o;
  2590. +    return 0;
  2591.  
  2592.    body = alloca (flen + 4);
  2593.    body[0] = '$';
  2594. @@ -2475,20 +2427,20 @@
  2595.  
  2596.    saved_args = max_args;
  2597.    max_args = i;
  2598. -  o = variable_expand_string (o, body, flen+3);
  2599. +  result += vbuffer_expand (o, body, flen+3);
  2600.    max_args = saved_args;
  2601.  
  2602.    v->exp_count = 0;
  2603.  
  2604.    pop_variable_scope ();
  2605.  
  2606. -  return o + strlen (o);
  2607. +  return result;
  2608.  }
  2609.  
  2610.  void
  2611.  define_new_function(const struct floc *flocp,
  2612.                      const char *name, int min, int max, int expand,
  2613. -                    char *(*func)(char *, char **, const char *))
  2614. +                    size_t (*func)(struct vbuffer *, char **, const char *))
  2615.  {
  2616.    size_t len = strlen (name);
  2617.    struct function_table_entry *ent = xmalloc (sizeof (struct function_table_entry));
  2618. Index: guile.c
  2619. ===================================================================
  2620. RCS file: /sources/make/make/guile.c,v
  2621. retrieving revision 2.5
  2622. diff -u -r2.5 guile.c
  2623. --- guile.c 5 Mar 2012 14:10:44 -0000   2.5
  2624. +++ guile.c 15 Mar 2012 21:19:14 -0000
  2625. @@ -86,20 +86,22 @@
  2626.  }
  2627.  
  2628.  /* This is the function registered with make  */
  2629. -static char *
  2630. -func_guile (char *o, char **argv, const char *funcname UNUSED)
  2631. +static size_t
  2632. +func_guile (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  2633.  {
  2634. +  size_t result = 0;
  2635. +
  2636.    if (argv[0] && argv[0][0] != '\0')
  2637.      {
  2638.        char *str = scm_with_guile (internal_guile_eval, argv[0]);
  2639.        if (str)
  2640.          {
  2641. -          o = variable_buffer_output (o, str, strlen (str));
  2642. +          result += vbuffer_write (o, str, -1);
  2643.            free (str);
  2644.          }
  2645.      }
  2646.  
  2647. -  return o;
  2648. +  return result;
  2649.  }
  2650.  
  2651.  /* ----- Public interface ----- */
  2652. Index: main.c
  2653. ===================================================================
  2654. RCS file: /sources/make/make/main.c,v
  2655. retrieving revision 1.256
  2656. diff -u -r1.256 main.c
  2657. --- main.c  5 Mar 2012 14:10:44 -0000   1.256
  2658. +++ main.c  15 Mar 2012 21:19:15 -0000
  2659. @@ -1104,6 +1104,8 @@
  2660.  
  2661.    initialize_global_hash_tables ();
  2662.  
  2663. +  install_new_expansion_vbuffer();
  2664. +
  2665.    /* Figure out where we are.  */
  2666.  
  2667.  #ifdef WINDOWS32
  2668. @@ -2277,12 +2279,7 @@
  2669.        if (default_goal_var->recursive)
  2670.          p = variable_expand (default_goal_var->value);
  2671.        else
  2672. -        {
  2673. -          p = variable_buffer_output (variable_buffer, default_goal_var->value,
  2674. -                                      strlen (default_goal_var->value));
  2675. -          *p = '\0';
  2676. -          p = variable_buffer;
  2677. -        }
  2678. +   p = default_goal_var->value;
  2679.  
  2680.        if (*p != '\0')
  2681.          {
  2682. Index: read.c
  2683. ===================================================================
  2684. RCS file: /sources/make/make/read.c,v
  2685. retrieving revision 1.210
  2686. diff -u -r1.210 read.c
  2687. --- read.c  5 Mar 2012 14:10:44 -0000   1.210
  2688. +++ read.c  15 Mar 2012 21:19:15 -0000
  2689. @@ -566,6 +566,7 @@
  2690.    const char *pattern_percent;
  2691.    struct floc *fstart;
  2692.    struct floc fi;
  2693. +  struct vbuffer vbuf;
  2694.  
  2695.  #define record_waiting_files()                           \
  2696.    do                                         \
  2697. @@ -583,6 +584,8 @@
  2698.        pattern = 0;                                                            \
  2699.      } while (0)
  2700.  
  2701. +  vbuffer_init(&vbuf);
  2702. +
  2703.    pattern_percent = 0;
  2704.    cmds_started = tgts_started = 1;
  2705.  
  2706. @@ -893,6 +896,7 @@
  2707.        {
  2708.          enum make_word_type wtype;
  2709.          char *cmdleft, *semip, *lb_next;
  2710. +        unsigned int llen = 0;
  2711.          unsigned int plen = 0;
  2712.          char *colonp;
  2713.          const char *end, *beg; /* Helpers for whitespace stripping. */
  2714. @@ -943,42 +947,44 @@
  2715.              break;
  2716.            }
  2717.  
  2718. -        p2 = variable_expand_string(NULL, lb_next, wlen);
  2719. -
  2720. -        while (1)
  2721. -          {
  2722. -            lb_next += wlen;
  2723. -            if (cmdleft == 0)
  2724. -              {
  2725. -                /* Look for a semicolon in the expanded line.  */
  2726. -                cmdleft = find_char_unquote (p2, ';', 0, 0, 0);
  2727. +        vbuffer_expand_ro (vbuffer_reset(&vbuf), lb_next, wlen);
  2728. +   p2 = vbuf.buffer;
  2729.  
  2730. -                if (cmdleft != 0)
  2731. -                  {
  2732. -                    unsigned long p2_off = p2 - variable_buffer;
  2733. -                    unsigned long cmd_off = cmdleft - variable_buffer;
  2734. -                    char *pend = p2 + strlen(p2);
  2735. -
  2736. -                    /* Append any remnants of lb, then cut the line short
  2737. -                       at the semicolon.  */
  2738. -                    *cmdleft = '\0';
  2739. -
  2740. -                    /* One school of thought says that you shouldn't expand
  2741. -                       here, but merely copy, since now you're beyond a ";"
  2742. -                       and into a command script.  However, the old parser
  2743. -                       expanded the whole line, so we continue that for
  2744. -                       backwards-compatiblity.  Also, it wouldn't be
  2745. -                       entirely consistent, since we do an unconditional
  2746. -                       expand below once we know we don't have a
  2747. -                       target-specific variable. */
  2748. -                    (void)variable_expand_string(pend, lb_next, (long)-1);
  2749. -                    lb_next += strlen(lb_next);
  2750. -                    p2 = variable_buffer + p2_off;
  2751. -                    cmdleft = variable_buffer + cmd_off + 1;
  2752. -                  }
  2753. -              }
  2754. +   while (1)
  2755. +     {
  2756. +       lb_next += wlen;
  2757. +       if (cmdleft == 0)
  2758. +         {
  2759. +       /* Look for a semicolon in the expanded line.  */
  2760. +       cmdleft = find_char_unquote (p2, ';', 0, 0, 0);
  2761. +
  2762. +       if (cmdleft != 0)
  2763. +         {
  2764. +           unsigned long p2_off = p2 - vbuf.buffer;
  2765. +           unsigned long cmd_off = cmdleft - vbuf.buffer;
  2766. +
  2767. +           /* Append any remnants of lb, then cut the line short
  2768. +              at the semicolon.  */
  2769. +           *cmdleft = '\0';
  2770. +
  2771. +           /* One school of thought says that you shouldn't expand
  2772. +              here, but merely copy, since now you're beyond a ";"
  2773. +              and into a command script.  However, the old parser
  2774. +              expanded the whole line, so we continue that for
  2775. +              backwards-compatibility.  Also, it wouldn't be
  2776. +              entirely consistent, since we do an unconditional
  2777. +              expand below once we know we don't have a
  2778. +              target-specific variable. */
  2779. +           vbuffer_expand_ro (&vbuf, lb_next, -1);
  2780. +
  2781. +           p2 = vbuf.buffer + p2_off;
  2782. +           cmdleft = vbuf.buffer + cmd_off + 1;
  2783. +
  2784. +           lb_next += strlen(lb_next);
  2785. +         }
  2786. +         }
  2787.  
  2788. -            colonp = find_char_unquote(p2, ':', 0, 0, 0);
  2789. +       colonp = find_char_unquote(p2, ':', 0, 0, 0);
  2790.  #ifdef HAVE_DOS_PATHS
  2791.              /* The drive spec brain-damage strikes again...  */
  2792.              /* Note that the only separators of targets in this context
  2793. @@ -989,118 +995,119 @@
  2794.                     (colonp == p2 + 1 || strchr (" \t(", colonp[-2]) != 0))
  2795.                colonp = find_char_unquote(colonp + 1, ':', 0, 0, 0);
  2796.  #endif
  2797. -            if (colonp != 0)
  2798. -              break;
  2799. -
  2800. -            wtype = get_next_mword(lb_next, NULL, &lb_next, &wlen);
  2801. -            if (wtype == w_eol)
  2802. -              break;
  2803. -
  2804. -            p2 += strlen(p2);
  2805. -            *(p2++) = ' ';
  2806. -            p2 = variable_expand_string(p2, lb_next, wlen);
  2807. -            /* We don't need to worry about cmdleft here, because if it was
  2808. -               found in the variable_buffer the entire buffer has already
  2809. -               been expanded... we'll never get here.  */
  2810. -          }
  2811. -
  2812. -        p2 = next_token (variable_buffer);
  2813. +       if (colonp != 0)
  2814. +         break;
  2815.  
  2816. -        /* If the word we're looking at is EOL, see if there's _anything_
  2817. -           on the line.  If not, a variable expanded to nothing, so ignore
  2818. -           it.  If so, we can't parse this line so punt.  */
  2819. -        if (wtype == w_eol)
  2820. -          {
  2821. -            if (*p2 != '\0')
  2822. -              /* There's no need to be ivory-tower about this: check for
  2823. -                 one of the most common bugs found in makefiles...  */
  2824. -              fatal (fstart, _("missing separator%s"),
  2825. -                     (cmd_prefix == '\t' && !strneq (line, "        ", 8))
  2826. -                     ? "" : _(" (did you mean TAB instead of 8 spaces?)"));
  2827. -            continue;
  2828. -          }
  2829. +       wtype = get_next_mword(lb_next, NULL, &lb_next, &wlen);
  2830. +       if (wtype == w_eol)
  2831. +         break;
  2832.  
  2833. -        /* Make the colon the end-of-string so we know where to stop
  2834. -           looking for targets.  Start there again once we're done.  */
  2835. -        *colonp = '\0';
  2836. -        filenames = PARSE_FILE_SEQ (&p2, struct nameseq, '\0', NULL, 0);
  2837. -        *colonp = ':';
  2838. -        p2 = colonp;
  2839. +       vbuffer_write(&vbuf, " ", 1);
  2840. +       plen = vbuffer_expand_ro (&vbuf, lb_next, wlen);
  2841. +       p2 = vbuf.ptr - plen;
  2842. +
  2843. +       /* We don't need to worry about cmdleft here, because if it was
  2844. +          found in the variable_buffer the entire buffer has already
  2845. +          been expanded... we'll never get here.  */
  2846. +     }
  2847.  
  2848. -        if (!filenames)
  2849. -          {
  2850. -            /* We accept and ignore rules without targets for
  2851. -               compatibility with SunOS 4 make.  */
  2852. -            no_targets = 1;
  2853. -            continue;
  2854. -          }
  2855. -        /* This should never be possible; we handled it above.  */
  2856. -        assert (*p2 != '\0');
  2857. -        ++p2;
  2858. -
  2859. -        /* Is this a one-colon or two-colon entry?  */
  2860. -        two_colon = *p2 == ':';
  2861. -        if (two_colon)
  2862. -          p2++;
  2863. -
  2864. -        /* Test to see if it's a target-specific variable.  Copy the rest
  2865. -           of the buffer over, possibly temporarily (we'll expand it later
  2866. -           if it's not a target-specific variable).  PLEN saves the length
  2867. -           of the unparsed section of p2, for later.  */
  2868. -        if (*lb_next != '\0')
  2869. -          {
  2870. -            unsigned int l = p2 - variable_buffer;
  2871. -            plen = strlen (p2);
  2872. -            variable_buffer_output (p2+plen, lb_next, strlen (lb_next)+1);
  2873. -            p2 = variable_buffer + l;
  2874. -          }
  2875. +   p2 = next_token (vbuf.buffer);
  2876.  
  2877. -        p2 = parse_var_assignment (p2, &vmod);
  2878. -        if (vmod.assign_v)
  2879. -          {
  2880. -            /* If there was a semicolon found, add it back, plus anything
  2881. -               after it.  */
  2882. -            if (semip)
  2883. -              {
  2884. -                unsigned int l = p - variable_buffer;
  2885. -                *(--semip) = ';';
  2886. -                collapse_continuations (semip);
  2887. -                variable_buffer_output (p2 + strlen (p2),
  2888. -                                        semip, strlen (semip)+1);
  2889. -                p = variable_buffer + l;
  2890. -              }
  2891. -            record_target_var (filenames, p2,
  2892. -                               vmod.override_v ? o_override : o_file,
  2893. -                               &vmod, fstart);
  2894. -            filenames = 0;
  2895. -            continue;
  2896. -          }
  2897. -
  2898. -        /* This is a normal target, _not_ a target-specific variable.
  2899. -           Unquote any = in the dependency list.  */
  2900. -        find_char_unquote (lb_next, '=', 0, 0, 0);
  2901. +   /* If the word we're looking at is EOL, see if there's _anything_
  2902. +      on the line.  If not, a variable expanded to nothing, so ignore
  2903. +      it.  If so, we can't parse this line so punt.  */
  2904. +   if (wtype == w_eol)
  2905. +     {
  2906. +       if (*p2 != '\0')
  2907. +         /* There's no need to be ivory-tower about this: check for
  2908. +        one of the most common bugs found in makefiles...  */
  2909. +         fatal (fstart, _("missing separator%s"),
  2910. +            (cmd_prefix == '\t' && !strneq (line, "        ", 8))
  2911. +            ? "" : _(" (did you mean TAB instead of 8 spaces?)"));
  2912. +       continue;
  2913. +     }
  2914.  
  2915. -        /* Remember the command prefix for this target.  */
  2916. -        prefix = cmd_prefix;
  2917. +   /* Make the colon the end-of-string so we know where to stop
  2918. +      looking for targets.  Start there again once we're done.  */
  2919. +   *colonp = '\0';
  2920. +   filenames = PARSE_FILE_SEQ (&p2, struct nameseq, '\0', NULL, 0);
  2921. +   *colonp = ':';
  2922. +   p2 = colonp;
  2923.  
  2924. -        /* We have some targets, so don't ignore the following commands.  */
  2925. -        no_targets = 0;
  2926. +   if (!filenames)
  2927. +     {
  2928. +       /* We accept and ignore rules without targets for
  2929. +          compatibility with SunOS 4 make.  */
  2930. +       no_targets = 1;
  2931. +       continue;
  2932. +     }
  2933. +   /* This should never be possible; we handled it above.  */
  2934. +   assert (*p2 != '\0');
  2935. +   ++p2;
  2936. +
  2937. +   /* Is this a one-colon or two-colon entry?  */
  2938. +   two_colon = *p2 == ':';
  2939. +   if (two_colon)
  2940. +     p2++;
  2941. +
  2942. +   /* Test to see if it's a target-specific variable.  Copy the rest
  2943. +      of the buffer over, possibly temporarily (we'll expand it later
  2944. +      if it's not a target-specific variable).  LLEN saves the length
  2945. +      of the copied string, to know how many bytes to discard later.  */
  2946. +   if (*lb_next != '\0')
  2947. +     {
  2948. +       unsigned long p2_off = p2 - vbuf.buffer;
  2949. +       llen = vbuffer_write (&vbuf, lb_next, -1);
  2950. +       p2 = vbuf.buffer + p2_off;
  2951. +     }
  2952.  
  2953. -        /* Expand the dependencies, etc.  */
  2954. -        if (*lb_next != '\0')
  2955. -          {
  2956. -            unsigned int l = p2 - variable_buffer;
  2957. -            (void) variable_expand_string (p2 + plen, lb_next, (long)-1);
  2958. -            p2 = variable_buffer + l;
  2959. +   p2 = parse_var_assignment (p2, &vmod);
  2960. +   if (vmod.assign_v)
  2961. +     {
  2962. +       /* If there was a semicolon found, add it back, plus anything
  2963. +          after it.  */
  2964. +       if (semip)
  2965. +         {
  2966. +       unsigned long p2_off = p2 - vbuf.buffer;
  2967. +       *(--semip) = ';';
  2968. +       collapse_continuations (semip);
  2969. +       vbuffer_write (&vbuf, semip, -1);
  2970. +       p2 = vbuf.buffer + p2_off;
  2971. +         }
  2972. +       record_target_var (filenames, p2,
  2973. +                  vmod.override_v ? o_override : o_file,
  2974. +                  &vmod, fstart);
  2975. +       filenames = 0;
  2976. +       continue;
  2977. +     }
  2978.  
  2979. -            /* Look for a semicolon in the expanded line.  */
  2980. -            if (cmdleft == 0)
  2981. -              {
  2982. -                cmdleft = find_char_unquote (p2, ';', 0, 0, 0);
  2983. -                if (cmdleft != 0)
  2984. -                  *(cmdleft++) = '\0';
  2985. -              }
  2986. -          }
  2987. +   /* This is a normal target, _not_ a target-specific variable.
  2988. +      Unquote any = in the dependency list.  */
  2989. +   find_char_unquote (lb_next, '=', 0, 0, 0);
  2990. +
  2991. +   /* Remember the command prefix for this target.  */
  2992. +   prefix = cmd_prefix;
  2993. +
  2994. +   /* We have some targets, so don't ignore the following commands.  */
  2995. +   no_targets = 0;
  2996. +
  2997. +   /* Expand the dependencies, etc.
  2998. +      P2 still point past the colon.  */
  2999. +   if (*lb_next != '\0')
  3000. +     {
  3001. +       unsigned long p2_off = p2 - vbuf.buffer;
  3002. +       vbuffer_unwrite (&vbuf, llen);
  3003. +       vbuffer_expand_ro (&vbuf, lb_next, -1);
  3004. +       p2 = vbuf.buffer + p2_off;
  3005. +
  3006. +       /* Look for a semicolon in the expanded line.  */
  3007. +       if (cmdleft == 0)
  3008. +         {
  3009. +       cmdleft = find_char_unquote (p2, ';', 0, 0, 0);
  3010. +       if (cmdleft != 0)
  3011. +         *(cmdleft++) = '\0';
  3012. +         }
  3013. +     }
  3014.  
  3015.          /* Is this a static pattern rule: 'target: %targ: %dep; ...'?  */
  3016.          p = strchr (p2, ':');
  3017. @@ -1281,8 +1288,6 @@
  3018.        record_waiting_files ();
  3019.      }
  3020.  
  3021. -#undef word1eq
  3022. -
  3023.    if (conditionals->if_cmds)
  3024.      fatal (fstart, _("missing 'endif'"));
  3025.  
  3026. @@ -1292,7 +1297,13 @@
  3027.    if (collapsed)
  3028.      free (collapsed);
  3029.    free (commands);
  3030. +
  3031. +  vbuffer_free(&vbuf);
  3032. +
  3033. +#undef record_waiting_files
  3034.  }
  3035. +
  3036. +#undef word1eq
  3037.  
  3038.  
  3039.  /* Remove comments from LINE.
  3040. @@ -1842,6 +1853,7 @@
  3041.    struct dep *deps;
  3042.    const char *implicit_percent;
  3043.    const char *name;
  3044. +  struct vbuffer patbuf;
  3045.  
  3046.    /* If we've already snapped deps, that means we're in an eval being
  3047.       resolved after the makefiles have been read in.  We can't add more rules
  3048. @@ -1945,6 +1957,7 @@
  3049.        return;
  3050.      }
  3051.  
  3052. +  vbuffer_init (&patbuf);
  3053.  
  3054.    /* Walk through each target and create it in the database.
  3055.       We already set up the first target, above.  */
  3056. @@ -2057,10 +2070,12 @@
  3057.        if (pattern)
  3058.          {
  3059.            static const char *percent = "%";
  3060. -          char *buffer = variable_expand ("");
  3061. -          char *o = patsubst_expand_pat (buffer, name, pattern, percent,
  3062. -                                         pattern_percent+1, percent+1);
  3063. -          f->stem = strcache_add_len (buffer, o - buffer);
  3064. +          size_t len;
  3065. +
  3066. +          len = patsubst_expand_pat (vbuffer_reset(&patbuf), name,
  3067. +                    pattern, percent,
  3068. +                    pattern_percent+1, percent+1);
  3069. +          f->stem = strcache_add_len (patbuf.buffer, len);
  3070.            if (this)
  3071.              {
  3072.                if (! this->need_2nd_expansion)
  3073. @@ -2112,6 +2127,8 @@
  3074.        if (find_percent_cached (&name))
  3075.          fatal (flocp, _("mixed implicit and normal rules"));
  3076.      }
  3077. +
  3078. +  vbuffer_free (&patbuf);
  3079.  }
  3080.  
  3081.  /* Search STRING for an unquoted STOPCHAR or blank (if BLANK is nonzero).
  3082. Index: remake.c
  3083. ===================================================================
  3084. RCS file: /sources/make/make/remake.c,v
  3085. retrieving revision 1.153
  3086. diff -u -r1.153 remake.c
  3087. --- remake.c    5 Mar 2012 14:10:45 -0000   1.153
  3088. +++ remake.c    15 Mar 2012 21:19:16 -0000
  3089. @@ -1534,12 +1534,14 @@
  3090.    const char *p2;
  3091.    unsigned int len;
  3092.    unsigned int liblen;
  3093. +  struct vbuffer vbuf;
  3094.  
  3095.    /* Information about the earliest (in the vpath sequence) match.  */
  3096.    unsigned int best_vpath = 0, best_path = 0;
  3097.  
  3098.    char **dp;
  3099.  
  3100. +  vbuffer_init(&vbuf);
  3101.    libpatterns = xstrdup (variable_expand ("$(.LIBPATTERNS)"));
  3102.  
  3103.    /* Skip the '-l'.  */
  3104. @@ -1556,28 +1558,30 @@
  3105.        static unsigned int buflen = 0;
  3106.        static int libdir_maxlen = -1;
  3107.        static unsigned int std_dirs = 0;
  3108. -      char *libbuf = variable_expand ("");
  3109. +      char *libbuf;
  3110.  
  3111.        /* Expand the pattern using LIB as a replacement.  */
  3112.        {
  3113.     char c = p[len];
  3114. -   char *p3, *p4;
  3115. +   char *percent;
  3116.  
  3117.     p[len] = '\0';
  3118. -   p3 = find_percent (p);
  3119. -   if (!p3)
  3120. +   percent = find_percent (p);
  3121. +   if (!percent)
  3122.       {
  3123.         /* Give a warning if there is no pattern.  */
  3124.         error (NILF, _(".LIBPATTERNS element '%s' is not a pattern"), p);
  3125.              p[len] = c;
  3126.         continue;
  3127.       }
  3128. -   p4 = variable_buffer_output (libbuf, p, p3-p);
  3129. -   p4 = variable_buffer_output (p4, lib, liblen);
  3130. -   p4 = variable_buffer_output (p4, p3+1, len - (p3-p));
  3131. +   vbuffer_write (&vbuf, p, percent-p);
  3132. +   vbuffer_write (&vbuf, lib, liblen);
  3133. +   vbuffer_write (&vbuf, percent+1, len - (percent-p));
  3134.     p[len] = c;
  3135.        }
  3136.  
  3137. +      libbuf = vbuf.buffer;
  3138. +
  3139.        /* Look first for 'libNAME.a' in the current directory.  */
  3140.        mtime = name_mtime (libbuf);
  3141.        if (mtime != NONEXISTENT_MTIME)
  3142. @@ -1660,5 +1664,7 @@
  3143.      }
  3144.  
  3145.    free (libpatterns);
  3146. +  vbuffer_free(&vbuf);
  3147. +
  3148.    return file;
  3149.  }
  3150. Index: variable.c
  3151. ===================================================================
  3152. RCS file: /sources/make/make/variable.c,v
  3153. retrieving revision 1.112
  3154. diff -u -r1.112 variable.c
  3155. --- variable.c  5 Mar 2012 14:10:45 -0000   1.112
  3156. +++ variable.c  15 Mar 2012 21:19:16 -0000
  3157. @@ -966,6 +966,7 @@
  3158.    struct variable makelevel_key;
  3159.    char **result_0;
  3160.    char **result;
  3161. +  struct vbuffer vbuf;
  3162.  
  3163.    if (file == 0)
  3164.      set_list = current_variable_set_list;
  3165. @@ -1053,6 +1054,8 @@
  3166.  
  3167.    result = result_0 = xmalloc ((table.ht_fill + 2) * sizeof (char *));
  3168.  
  3169. +  vbuffer_init (&vbuf);
  3170. +
  3171.    v_slot = (struct variable **) table.ht_vec;
  3172.    v_end = v_slot + table.ht_size;
  3173.    for ( ; v_slot < v_end; v_slot++)
  3174. @@ -1060,32 +1063,30 @@
  3175.        {
  3176.     struct variable *v = *v_slot;
  3177.  
  3178. +   vbuffer_reset (&vbuf);
  3179. +
  3180. +   vbuffer_write (&vbuf, v->name, -1);
  3181. +   vbuffer_write (&vbuf, "=", 1);
  3182. +
  3183.     /* If V is recursively expanded and didn't come from the environment,
  3184.        expand its value.  If it came from the environment, it should
  3185.        go back into the environment unchanged.  */
  3186.     if (v->recursive
  3187.         && v->origin != o_env && v->origin != o_env_override)
  3188. -     {
  3189. -       char *value = recursively_expand_for_file (v, file);
  3190. -#ifdef WINDOWS32
  3191. -       if (strcmp(v->name, "Path") == 0 ||
  3192. -       strcmp(v->name, "PATH") == 0)
  3193. -         convert_Path_to_windows32(value, ';');
  3194. -#endif
  3195. -       *result++ = xstrdup (concat (3, v->name, "=", value));
  3196. -       free (value);
  3197. -     }
  3198. +     vbuffer_expand_variable_for_file (&vbuf, v, file);
  3199.     else
  3200. -     {
  3201. +     vbuffer_write (&vbuf, v->value, -1);
  3202. +
  3203.  #ifdef WINDOWS32
  3204. -            if (strcmp(v->name, "Path") == 0 ||
  3205. -                strcmp(v->name, "PATH") == 0)
  3206. -              convert_Path_to_windows32(v->value, ';');
  3207. +   if (strcmp(v->name, "Path") == 0 ||
  3208. +       strcmp(v->name, "PATH") == 0)
  3209. +     convert_Path_to_windows32(value, ';');
  3210.  #endif
  3211. -       *result++ = xstrdup (concat (3, v->name, "=", v->value));
  3212. -     }
  3213. +   *result++ = xstrdup (vbuf.buffer);
  3214.        }
  3215.  
  3216. +  vbuffer_free (&vbuf);
  3217. +
  3218.    *result = xmalloc (100);
  3219.    sprintf (*result, "%s=%u", MAKELEVEL_NAME, makelevel + 1);
  3220.    *++result = 0;
  3221. @@ -1116,20 +1117,14 @@
  3222.  char *
  3223.  shell_result (const char *p)
  3224.  {
  3225. -  char *buf;
  3226. -  unsigned int len;
  3227. +  struct vbuffer vbuf;
  3228.    char *args[2];
  3229. -  char *result;
  3230. -
  3231. -  install_variable_buffer (&buf, &len);
  3232.  
  3233.    args[0] = (char *) p;
  3234.    args[1] = NULL;
  3235. -  variable_buffer_output (func_shell_base (variable_buffer, args, 0), "\0", 1);
  3236. -  result = strdup (variable_buffer);
  3237. +  func_shell_base (vbuffer_init(&vbuf), args, 0);
  3238.  
  3239. -  restore_variable_buffer (buf, len);
  3240. -  return result;
  3241. +  return vbuf.buffer;
  3242.  }
  3243.  
  3244.  /* Given a variable, a value, and a flavor, define the variable.
  3245. Index: variable.h
  3246. ===================================================================
  3247. RCS file: /sources/make/make/variable.h,v
  3248. retrieving revision 1.51
  3249. diff -u -r1.51 variable.h
  3250. --- variable.h  5 Mar 2012 14:10:45 -0000   1.51
  3251. +++ variable.h  15 Mar 2012 21:19:16 -0000
  3252. @@ -107,38 +107,68 @@
  3253.      struct variable variable;
  3254.    };
  3255.  
  3256. -extern char *variable_buffer;
  3257. +/* Structure used for pattern-specific variables.  */
  3258. +
  3259. +struct vbuffer
  3260. +  {
  3261. +    char *ptr;    /* Current position pointing inside the buffer.  */
  3262. +    char *buffer; /* Start of the entire buffer.  */
  3263. +    size_t size;  /* Size of the allocated buffer.  */
  3264. +  };
  3265. +
  3266.  extern struct variable_set_list *current_variable_set_list;
  3267.  extern struct variable *default_goal_var;
  3268.  
  3269. +struct vbuffer *vbuffer_init  (struct vbuffer *vbuf);
  3270. +struct vbuffer *vbuffer_reset (struct vbuffer *vbuf);
  3271. +
  3272. +#define vbuffer_free(vbuf) \
  3273. +  free ((vbuf)->buffer)
  3274. +
  3275. +size_t vbuffer_reserve (struct vbuffer *o, size_t len);
  3276. +
  3277. +size_t vbuffer_write (struct vbuffer *o, const char *str, ssize_t len);
  3278. +size_t vbuffer_unwrite (struct vbuffer *o, ssize_t len);
  3279. +
  3280. +size_t vbuffer_expand (struct vbuffer *o, char *str, ssize_t len);
  3281. +size_t vbuffer_expand_for_file (struct vbuffer *o, char *str, ssize_t len,
  3282. +               struct file *file);
  3283. +
  3284. +size_t vbuffer_expand_ro (struct vbuffer *o, const char *str, ssize_t len);
  3285. +size_t vbuffer_expand_ro_for_file (struct vbuffer *o, const char *str,
  3286. +                  ssize_t len, struct file *file);
  3287. +
  3288. +#define vbuffer_expand_variable(o, v) \
  3289. +  vbuffer_expand_variable_for_file (o, v, NULL)
  3290. +size_t vbuffer_expand_variable_for_file (struct vbuffer *o,
  3291. +                                         struct variable *v,
  3292. +                                         struct file *file);
  3293. +
  3294. +struct vbuffer *install_new_expansion_vbuffer (void);
  3295. +void restore_expansion_vbuffer (struct vbuffer *old_vbuf);
  3296. +
  3297.  /* expand.c */
  3298. -char *variable_buffer_output (char *ptr, const char *string, unsigned int length);
  3299. +char *expand_argument (const char *str, const char *end);
  3300.  char *variable_expand (const char *line);
  3301.  char *variable_expand_for_file (const char *line, struct file *file);
  3302. +char *allocated_variable_expand (const char *line);
  3303.  char *allocated_variable_expand_for_file (const char *line, struct file *file);
  3304. -#define    allocated_variable_expand(line) \
  3305. -  allocated_variable_expand_for_file (line, (struct file *) 0)
  3306. -char *expand_argument (const char *str, const char *end);
  3307. -char *variable_expand_string (char *line, const char *string, long length);
  3308. -void install_variable_buffer (char **bufp, unsigned int *lenp);
  3309. -void restore_variable_buffer (char *buf, unsigned int len);
  3310. +#define recursively_expand(v)   recursively_expand_for_file (v, NULL)
  3311. +char *recursively_expand_for_file (struct variable *v, struct file *file);
  3312.  
  3313.  /* function.c */
  3314. -int handle_function (char **op, const char **stringp);
  3315. +int handle_function (struct vbuffer *vbuf, char **stringp);
  3316.  int pattern_matches (const char *pattern, const char *percent, const char *str);
  3317. -char *subst_expand (char *o, const char *text, const char *subst,
  3318. -                    const char *replace, unsigned int slen, unsigned int rlen,
  3319. -                    int by_word);
  3320. -char *patsubst_expand_pat (char *o, const char *text, const char *pattern,
  3321. -                           const char *replace, const char *pattern_percent,
  3322. -                           const char *replace_percent);
  3323. -char *patsubst_expand (char *o, const char *text, char *pattern, char *replace);
  3324. -char *func_shell_base (char *o, char **argv, int trim_newlines);
  3325. -
  3326. -
  3327. -/* expand.c */
  3328. -char *recursively_expand_for_file (struct variable *v, struct file *file);
  3329. -#define recursively_expand(v)   recursively_expand_for_file (v, NULL)
  3330. +size_t subst_expand (struct vbuffer *vbuf, const char *text, const char *subst,
  3331. +                     const char *replace, unsigned int slen, unsigned int rlen,
  3332. +                     int by_word);
  3333. +size_t patsubst_expand_pat (struct vbuffer *vbuf, const char *text,
  3334. +                            const char *pattern, const char *replace,
  3335. +                            const char *pattern_percent,
  3336. +                            const char *replace_percent);
  3337. +size_t patsubst_expand (struct vbuffer *vbuf, const char *text, char *pattern,
  3338. +                        char *replace);
  3339. +size_t func_shell_base (struct vbuffer *vbuf, char **argv, int trim_newlines);
  3340.  
  3341.  /* variable.c */
  3342.  struct variable_set_list *create_new_variable_set (void);
  3343. @@ -167,7 +197,7 @@
  3344.  void hash_init_function_table (void);
  3345.  void define_new_function(const struct floc *flocp,
  3346.                           const char *name, int min, int max, int expand,
  3347. -                         char *(*func)(char *, char **, const char *));
  3348. +                         size_t (*func)(struct vbuffer *, char **, const char *));
  3349.  struct variable *lookup_variable (const char *name, unsigned int length);
  3350.  struct variable *lookup_variable_in_set (const char *name, unsigned int length,
  3351.                                           const struct variable_set *set);
Advertisement
Add Comment
Please, Sign In to add comment