abusalimov

make-perf-func-logic.patch

Mar 15th, 2012
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 107.90 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    16 Mar 2012 03:20:30 -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  16 Mar 2012 03:20:30 -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  16 Mar 2012 03:20:31 -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,65 +762,71 @@
  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 ret = 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. +  char *p;
  1796.    unsigned int len;
  1797. -  struct variable *var;
  1798. +  struct variable var;
  1799. +  struct variable *old_var;
  1800. +  size_t body_len = strlen (argv[2]);
  1801. +  char *body;
  1802. +  char *alloc = 0;
  1803.  
  1804. -  push_new_variable_scope ();
  1805. -  var = define_variable (varname, strlen (varname), "", o_automatic, 0);
  1806. +  body = (body_len > 1000)
  1807. +     ? (alloc = xmalloc (body_len + 1))
  1808. +     : (alloca (body_len + 1));
  1809. +
  1810. +  old_var = push_scoped_variable (&var, varname, strlen (varname));
  1811.  
  1812.    /* loop through LIST,  put the value in VAR and expand BODY */
  1813.    while ((p = find_next_token (&list_iterator, &len)) != 0)
  1814.      {
  1815. -      char *result = 0;
  1816. -
  1817. -      free (var->value);
  1818. -      var->value = xstrndup (p, len);
  1819. +      char end_ch = p[len];
  1820. +      p[len] = '\0';
  1821.  
  1822. -      result = allocated_variable_expand (body);
  1823. +      var.value = p;
  1824. +      body[body_len] = ' ';
  1825. +      ret += vbuffer_expand (o, memcpy (body, argv[2], body_len), body_len + 1);
  1826.  
  1827. -      o = variable_buffer_output (o, result, strlen (result));
  1828. -      o = variable_buffer_output (o, " ", 1);
  1829. -      doneany = 1;
  1830. -      free (result);
  1831. +      p[len] = end_ch;
  1832.      }
  1833.  
  1834. -  if (doneany)
  1835. -    /* Kill the last space.  */
  1836. -    --o;
  1837. +  pop_scoped_variable (&var, old_var);
  1838. +
  1839. +  if (alloc)
  1840. +    free (alloc);
  1841.  
  1842. -  pop_variable_scope ();
  1843.    free (varname);
  1844.    free (list);
  1845.  
  1846. -  return o;
  1847. +  return ret - vbuffer_unwrite (o, !!ret);
  1848.  }
  1849.  
  1850.  struct a_word
  1851. @@ -905,9 +868,11 @@
  1852.    int length;
  1853.  };
  1854.  
  1855. -static char *
  1856. -func_filter_filterout (char *o, char **argv, const char *funcname)
  1857. +static size_t
  1858. +func_filter_filterout (struct vbuffer *o, char **argv, const char *funcname)
  1859.  {
  1860. +  size_t result = 0;
  1861. +
  1862.    struct a_word *wordhead;
  1863.    struct a_word **wordtail;
  1864.    struct a_word *wp;
  1865. @@ -989,8 +954,6 @@
  1866.  
  1867.    if (words)
  1868.      {
  1869. -      int doneany = 0;
  1870. -
  1871.        /* Run each pattern through the words, killing words.  */
  1872.        for (pp = pathead; pp != 0; pp = pp->next)
  1873.     {
  1874. @@ -1019,58 +982,42 @@
  1875.        for (wp = wordhead; wp != 0; wp = wp->next)
  1876.     if (is_filter ? wp->matched : !wp->matched)
  1877.       {
  1878. -       o = variable_buffer_output (o, wp->str, strlen (wp->str));
  1879. -       o = variable_buffer_output (o, " ", 1);
  1880. -       doneany = 1;
  1881. +       result += vbuffer_write (o, wp->str, -1);
  1882. +       result += vbuffer_write (o, " ", 1);
  1883.       }
  1884.  
  1885. -      if (doneany)
  1886. -   /* Kill the last space.  */
  1887. -   --o;
  1888.      }
  1889.  
  1890.    if (hashing)
  1891.      hash_free (&a_word_table, 0);
  1892.  
  1893. -  return o;
  1894. +  return result - vbuffer_unwrite (o, !!result);
  1895.  }
  1896.  
  1897.  
  1898. -static char *
  1899. -func_strip (char *o, char **argv, const char *funcname UNUSED)
  1900. +static size_t
  1901. +func_strip (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  1902.  {
  1903. -  const char *p = argv[0];
  1904. -  int doneany = 0;
  1905. +  size_t result = 0;
  1906.  
  1907. -  while (*p != '\0')
  1908. -    {
  1909. -      int i=0;
  1910. -      const char *word_start;
  1911. +  unsigned int len;
  1912. +  const char *words = argv[0];    /* Use a temp variable for find_next_token */
  1913. +  const char *p;
  1914.  
  1915. -      while (isspace ((unsigned char)*p))
  1916. -   ++p;
  1917. -      word_start = p;
  1918. -      for (i=0; *p != '\0' && !isspace ((unsigned char)*p); ++p, ++i)
  1919. -   {}
  1920. -      if (!i)
  1921. -   break;
  1922. -      o = variable_buffer_output (o, word_start, i);
  1923. -      o = variable_buffer_output (o, " ", 1);
  1924. -      doneany = 1;
  1925. +  while ((p = find_next_token (&words, &len)) != 0)
  1926. +    {
  1927. +      result += vbuffer_write (o, p, len + 1);
  1928. +      o->ptr[-1] = ' ';
  1929.      }
  1930.  
  1931. -  if (doneany)
  1932. -    /* Kill the last space.  */
  1933. -    --o;
  1934. -
  1935. -  return o;
  1936. +  return result - vbuffer_unwrite (o, !!result);
  1937.  }
  1938.  
  1939.  /*
  1940.    Print a warning or fatal message.
  1941.  */
  1942. -static char *
  1943. -func_error (char *o, char **argv, const char *funcname)
  1944. +size_t
  1945. +func_error (struct vbuffer *o UNUSED, char **argv, const char *funcname)
  1946.  {
  1947.    char **argvp;
  1948.    char *msg, *p;
  1949. @@ -1111,16 +1058,18 @@
  1950.    }
  1951.  
  1952.    /* The warning function expands to the empty string.  */
  1953. -  return o;
  1954. +  return 0;
  1955.  }
  1956.  
  1957.  
  1958.  /*
  1959.    chop argv[0] into words, and sort them.
  1960.   */
  1961. -static char *
  1962. -func_sort (char *o, char **argv, const char *funcname UNUSED)
  1963. +static size_t
  1964. +func_sort (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  1965.  {
  1966. +  size_t result = 0;
  1967. +
  1968.    const char *t;
  1969.    char **words;
  1970.    int wordi;
  1971. @@ -1133,7 +1082,8 @@
  1972.    wordi = 0;
  1973.    while ((p = find_next_token (&t, NULL)) != 0)
  1974.      {
  1975. -      ++t;
  1976. +      if (*t != '\0')
  1977. +   ++t;
  1978.        ++wordi;
  1979.      }
  1980.  
  1981. @@ -1144,7 +1094,8 @@
  1982.    wordi = 0;
  1983.    while ((p = find_next_token (&t, &len)) != 0)
  1984.      {
  1985. -      ++t;
  1986. +      if (*t != '\0')
  1987. +   ++t;
  1988.        p[len] = '\0';
  1989.        words[wordi++] = p;
  1990.      }
  1991. @@ -1161,18 +1112,18 @@
  1992.            if (i == wordi - 1 || strlen (words[i + 1]) != len
  1993.                || strcmp (words[i], words[i + 1]))
  1994.              {
  1995. -              o = variable_buffer_output (o, words[i], len);
  1996. -              o = variable_buffer_output (o, " ", 1);
  1997. +              result += vbuffer_write (o, words[i], len);
  1998. +              result += vbuffer_write (o, " ", 1);
  1999.              }
  2000.          }
  2001.  
  2002.        /* Kill the last space.  */
  2003. -      --o;
  2004. +      result -= vbuffer_unwrite (o, 1);
  2005.      }
  2006.  
  2007.    free (words);
  2008.  
  2009. -  return o;
  2010. +  return result;
  2011.  }
  2012.  
  2013.  /*
  2014. @@ -1187,9 +1138,11 @@
  2015.    example).
  2016.  */
  2017.  
  2018. -static char *
  2019. -func_if (char *o, char **argv, const char *funcname UNUSED)
  2020. +static size_t
  2021. +func_if (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  2022.  {
  2023. +  size_t ret = 0;
  2024. +
  2025.    const char *begp = argv[0];
  2026.    const char *endp = begp + strlen (argv[0]) - 1;
  2027.    int result = 0;
  2028. @@ -1201,12 +1154,9 @@
  2029.    strip_whitespace (&begp, &endp);
  2030.  
  2031.    if (begp <= endp)
  2032. -    {
  2033. -      char *expansion = expand_argument (begp, endp+1);
  2034. +    result = vbuffer_expand (o, (char *) begp, endp+1 - begp);
  2035.  
  2036. -      result = strlen (expansion);
  2037. -      free (expansion);
  2038. -    }
  2039. +  vbuffer_unwrite (o, result);
  2040.  
  2041.    /* If the result is true (1) we want to eval the first argument, and if
  2042.       it's false (0) we want to eval the second.  If the argument doesn't
  2043. @@ -1215,15 +1165,9 @@
  2044.    argv += 1 + !result;
  2045.  
  2046.    if (*argv)
  2047. -    {
  2048. -      char *expansion = expand_argument (*argv, NULL);
  2049. -
  2050. -      o = variable_buffer_output (o, expansion, strlen (expansion));
  2051. -
  2052. -      free (expansion);
  2053. -    }
  2054. +    ret += vbuffer_expand (o, *argv, -1);
  2055.  
  2056. -  return o;
  2057. +  return ret;
  2058.  }
  2059.  
  2060.  /*
  2061. @@ -1240,15 +1184,15 @@
  2062.    (short-circuiting).
  2063.  */
  2064.  
  2065. -static char *
  2066. -func_or (char *o, char **argv, const char *funcname UNUSED)
  2067. +static size_t
  2068. +func_or (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  2069.  {
  2070.    for ( ; *argv ; ++argv)
  2071.      {
  2072. +      size_t result;
  2073. +
  2074.        const char *begp = *argv;
  2075.        const char *endp = begp + strlen (*argv) - 1;
  2076. -      char *expansion;
  2077. -      int result = 0;
  2078.  
  2079.        /* Find the result of the condition: if it's false keep going.  */
  2080.  
  2081. @@ -1257,23 +1201,14 @@
  2082.        if (begp > endp)
  2083.          continue;
  2084.  
  2085. -      expansion = expand_argument (begp, endp+1);
  2086. -      result = strlen (expansion);
  2087. +      result = vbuffer_expand (o, (char *) begp, endp+1 - begp);
  2088.  
  2089.        /* If the result is false keep going.  */
  2090. -      if (!result)
  2091. -        {
  2092. -          free (expansion);
  2093. -          continue;
  2094. -        }
  2095. -
  2096. -      /* It's true!  Keep this result and return.  */
  2097. -      o = variable_buffer_output (o, expansion, result);
  2098. -      free (expansion);
  2099. -      break;
  2100. +      if (result)
  2101. +   return result;
  2102.      }
  2103.  
  2104. -  return o;
  2105. +    return 0;
  2106.  }
  2107.  
  2108.  /*
  2109. @@ -1290,56 +1225,52 @@
  2110.    (short-circuiting).
  2111.  */
  2112.  
  2113. -static char *
  2114. -func_and (char *o, char **argv, const char *funcname UNUSED)
  2115. +static size_t
  2116. +func_and (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  2117.  {
  2118. -  char *expansion;
  2119. -  int result;
  2120. -
  2121.    while (1)
  2122.      {
  2123. +      size_t result;
  2124. +
  2125.        const char *begp = *argv;
  2126.        const char *endp = begp + strlen (*argv) - 1;
  2127.  
  2128.        /* An empty condition is always false.  */
  2129.        strip_whitespace (&begp, &endp);
  2130.        if (begp > endp)
  2131. -        return o;
  2132. +        return 0;
  2133.  
  2134. -      expansion = expand_argument (begp, endp+1);
  2135. -      result = strlen (expansion);
  2136. +      result = vbuffer_expand (o, (char *) begp, endp+1 - begp);
  2137.  
  2138.        /* If the result is false, stop here: we're done.  */
  2139.        if (!result)
  2140. -        break;
  2141. +        return 0;
  2142.  
  2143.        /* Otherwise the result is true.  If this is the last one, keep this
  2144.           result and quit.  Otherwise go on to the next one!  */
  2145.  
  2146.        if (*(++argv))
  2147. -        free (expansion);
  2148. +   vbuffer_unwrite (o, result);
  2149.        else
  2150. -        {
  2151. -          o = variable_buffer_output (o, expansion, result);
  2152. -          break;
  2153. -        }
  2154. +   return result;
  2155.      }
  2156.  
  2157. -  free (expansion);
  2158. -
  2159. -  return o;
  2160. +    return 0;
  2161.  }
  2162.  
  2163. -static char *
  2164. -func_wildcard (char *o, char **argv, const char *funcname UNUSED)
  2165. +static size_t
  2166. +func_wildcard (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  2167.  {
  2168. +  size_t result = 0;
  2169. +
  2170.  #ifdef _AMIGA
  2171.     o = wildcard_expansion (argv[0], o);
  2172.  #else
  2173.     char *p = string_glob (argv[0]);
  2174. -   o = variable_buffer_output (o, p, strlen (p));
  2175. +   result += vbuffer_write (o, p, strlen (p));
  2176.  #endif
  2177. -   return o;
  2178. +
  2179. +   return result;
  2180.  }
  2181.  
  2182.  /*
  2183. @@ -1350,36 +1281,38 @@
  2184.    Treat the arguments as a segment of makefile, and parse them.
  2185.  */
  2186.  
  2187. -static char *
  2188. -func_eval (char *o, char **argv, const char *funcname UNUSED)
  2189. +static size_t
  2190. +func_eval (struct vbuffer *o UNUSED, char **argv, const char *funcname UNUSED)
  2191.  {
  2192. -  char *buf;
  2193. -  unsigned int len;
  2194. +  struct vbuffer *vbuf;
  2195.  
  2196.    /* Eval the buffer.  Pop the current variable buffer setting so that the
  2197.       eval'd code can use its own without conflicting.  */
  2198.  
  2199. -  install_variable_buffer (&buf, &len);
  2200. +  vbuf = install_new_expansion_vbuffer ();
  2201.  
  2202.    eval_buffer (argv[0]);
  2203.  
  2204. -  restore_variable_buffer (buf, len);
  2205. +  restore_expansion_vbuffer (vbuf);
  2206.  
  2207. -  return o;
  2208. +  /* Eval always expands to nothing. */
  2209. +  return 0;
  2210.  }
  2211.  
  2212.  
  2213. -static char *
  2214. -func_value (char *o, char **argv, const char *funcname UNUSED)
  2215. +static size_t
  2216. +func_value (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  2217.  {
  2218. +  size_t result = 0;
  2219. +
  2220.    /* Look up the variable.  */
  2221.    struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
  2222.  
  2223.    /* Copy its value into the output buffer without expanding it.  */
  2224.    if (v)
  2225. -    o = variable_buffer_output (o, v->value, strlen(v->value));
  2226. +    result += vbuffer_write (o, v->value, -1);
  2227.  
  2228. -  return o;
  2229. +  return result;
  2230.  }
  2231.  
  2232.  /*
  2233. @@ -1619,9 +1552,10 @@
  2234.  
  2235.  #else
  2236.  #ifndef _AMIGA
  2237. -char *
  2238. -func_shell_base (char *o, char **argv, int trim_newlines)
  2239. +size_t
  2240. +func_shell_base (struct vbuffer *o, char **argv, int trim_newlines)
  2241.  {
  2242. +  size_t result = 0;
  2243.    char *batch_filename = NULL;
  2244.  
  2245.  #ifdef __MSDOS__
  2246. @@ -1650,7 +1584,7 @@
  2247.  #ifdef WINDOWS32
  2248.        just_print_flag = j_p_f;
  2249.  #endif
  2250. -      return o;
  2251. +      return 0;
  2252.      }
  2253.  #endif
  2254.  
  2255. @@ -1683,7 +1617,7 @@
  2256.    if (pipedes[0] < 0)
  2257.      {
  2258.        perror_with_name (error_prefix, "pipe");
  2259. -      return o;
  2260. +      return 0;
  2261.      }
  2262.  #elif defined(WINDOWS32)
  2263.    windows32_openpipe (pipedes, &pid, command_argv, envp);
  2264. @@ -1694,14 +1628,14 @@
  2265.      {
  2266.        /* Open of the pipe failed, mark as failed execution.  */
  2267.        shell_function_completed = -1;
  2268. -      return o;
  2269. +      return 0;
  2270.      }
  2271.    else
  2272.  #else
  2273.    if (pipe (pipedes) < 0)
  2274.      {
  2275.        perror_with_name (error_prefix, "pipe");
  2276. -      return o;
  2277. +      return 0;
  2278.      }
  2279.  
  2280.  # ifdef __EMX__
  2281. @@ -1800,13 +1734,13 @@
  2282.       /* The child finished normally.  Replace all newlines in its output
  2283.          with spaces, and put that in the variable output buffer.  */
  2284.       fold_newlines (buffer, &i, trim_newlines);
  2285. -     o = variable_buffer_output (o, buffer, i);
  2286. +     result += vbuffer_write (o, buffer, i);
  2287.     }
  2288.  
  2289.        free (buffer);
  2290.      }
  2291.  
  2292. -  return o;
  2293. +  return result;
  2294.  }
  2295.  
  2296.  #else  /* _AMIGA */
  2297. @@ -1892,14 +1826,14 @@
  2298.    Close (child_stdout);
  2299.  
  2300.    fold_newlines (buffer, &i, trim_newlines);
  2301. -  o = variable_buffer_output (o, buffer, i);
  2302. +  result += vbuffer_write (o, buffer, i);
  2303.    free (buffer);
  2304.    return o;
  2305.  }
  2306.  #endif  /* _AMIGA */
  2307.  
  2308. -char *
  2309. -func_shell (char *o, char **argv, const char *funcname UNUSED)
  2310. +size_t
  2311. +func_shell (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  2312.  {
  2313.    return func_shell_base (o, argv, 1);
  2314.  }
  2315. @@ -1914,8 +1848,7 @@
  2316.  func_eq (char *o, char **argv, char *funcname UNUSED)
  2317.  {
  2318.    int result = ! strcmp (argv[0], argv[1]);
  2319. -  o = variable_buffer_output (o,  result ? "1" : "", result);
  2320. -  return o;
  2321. +  return vbuffer_write (o,  result ? "1" : "", result);
  2322.  }
  2323.  
  2324.  
  2325. @@ -1930,8 +1863,7 @@
  2326.    while (isspace ((unsigned char)*s))
  2327.      s++;
  2328.    result = ! (*s);
  2329. -  o = variable_buffer_output (o,  result ? "1" : "", result);
  2330. -  return o;
  2331. +  return vbuffer_write (o,  result ? "1" : "", result);
  2332.  }
  2333.  #endif
  2334.  
  2335. @@ -2058,13 +1990,14 @@
  2336.  }
  2337.  
  2338.  
  2339. -static char *
  2340. -func_realpath (char *o, char **argv, const char *funcname UNUSED)
  2341. +static size_t
  2342. +func_realpath (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  2343.  {
  2344. +  size_t result = 0;
  2345. +
  2346.    /* Expand the argument.  */
  2347.    const char *p = argv[0];
  2348.    const char *path = 0;
  2349. -  int doneany = 0;
  2350.    unsigned int len = 0;
  2351.  #ifndef HAVE_REALPATH
  2352.    struct stat st;
  2353. @@ -2087,22 +2020,17 @@
  2354.  #endif
  2355.               )
  2356.              {
  2357. -              o = variable_buffer_output (o, out, strlen (out));
  2358. -              o = variable_buffer_output (o, " ", 1);
  2359. -              doneany = 1;
  2360. +              result += vbuffer_write (o, out, -1);
  2361. +              result += vbuffer_write (o, " ", 1);
  2362.              }
  2363.          }
  2364.      }
  2365.  
  2366. -  /* Kill last space.  */
  2367. -  if (doneany)
  2368. -    --o;
  2369. -
  2370. -  return o;
  2371. +  return result - vbuffer_unwrite (o, !!result);
  2372.  }
  2373.  
  2374. -static char *
  2375. -func_file (char *o, char **argv, const char *funcname UNUSED)
  2376. +static size_t
  2377. +func_file (struct vbuffer *o UNUSED, char **argv, const char *funcname UNUSED)
  2378.  {
  2379.    char *fn = argv[0];
  2380.  
  2381. @@ -2137,16 +2065,17 @@
  2382.    else
  2383.      fatal (reading_file, _("Invalid file operation: %s"), fn);
  2384.  
  2385. -  return o;
  2386. +  return 0;
  2387.  }
  2388.  
  2389. -static char *
  2390. -func_abspath (char *o, char **argv, const char *funcname UNUSED)
  2391. +static size_t
  2392. +func_abspath (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  2393.  {
  2394. +  size_t result = 0;
  2395. +
  2396.    /* Expand the argument.  */
  2397.    const char *p = argv[0];
  2398.    const char *path = 0;
  2399. -  int doneany = 0;
  2400.    unsigned int len = 0;
  2401.    PATH_VAR (in);
  2402.    PATH_VAR (out);
  2403. @@ -2160,18 +2089,13 @@
  2404.  
  2405.            if (abspath (in, out))
  2406.              {
  2407. -              o = variable_buffer_output (o, out, strlen (out));
  2408. -              o = variable_buffer_output (o, " ", 1);
  2409. -              doneany = 1;
  2410. +              result += vbuffer_write (o, out, strlen (out));
  2411. +              result += vbuffer_write (o, " ", 1);
  2412.              }
  2413.          }
  2414.      }
  2415.  
  2416. -  /* Kill last space.  */
  2417. -  if (doneany)
  2418. -    --o;
  2419. -
  2420. -  return o;
  2421. +  return result - vbuffer_unwrite (o, !!result);
  2422.  }
  2423.  
  2424.  /* Lookup table for builtin functions.
  2425. @@ -2186,7 +2110,7 @@
  2426.     EXPAND_ARGS means that all arguments should be expanded before invocation.
  2427.     Functions that do namespace tricks (foreach) don't automatically expand.  */
  2428.  
  2429. -static char *func_call (char *o, char **argv, const char *funcname);
  2430. +static size_t func_call (struct vbuffer *o, char **argv, const char *funcname);
  2431.  
  2432.  
  2433.  static struct function_table_entry function_table_init[] =
  2434. @@ -2239,8 +2163,8 @@
  2435.  
  2436.  /* These must come after the definition of function_table.  */
  2437.  
  2438. -static char *
  2439. -expand_builtin_function (char *o, int argc, char **argv,
  2440. +static size_t
  2441. +expand_builtin_function (struct vbuffer *o, int argc, char **argv,
  2442.                           const struct function_table_entry *entry_p)
  2443.  {
  2444.    if (argc < (int)entry_p->minimum_args)
  2445. @@ -2253,7 +2177,7 @@
  2446.       rather than in each one.  We can change it later if necessary.  */
  2447.  
  2448.    if (!argc)
  2449. -    return o;
  2450. +    return 0;
  2451.  
  2452.    if (!entry_p->func_ptr)
  2453.      fatal (*expanding_var,
  2454. @@ -2265,45 +2189,64 @@
  2455.  /* Check for a function invocation in *STRINGP.  *STRINGP points at the
  2456.     opening ( or { and is not null-terminated.  If a function invocation
  2457.     is found, expand it into the buffer at *OP, updating *OP, incrementing
  2458. -   *STRINGP past the reference and returning nonzero.  If not, return zero.  */
  2459. +   *STRINGP past the reference and returning the amount of bytes written.
  2460. +   If not, return -1.  */
  2461.  
  2462.  int
  2463. -handle_function (char **op, const char **stringp)
  2464. +handle_function (struct vbuffer *o, char **stringp)
  2465.  {
  2466. +  size_t result = 0;
  2467. +
  2468.    const struct function_table_entry *entry_p;
  2469.    char openparen = (*stringp)[0];
  2470.    char closeparen = openparen == '(' ? ')' : '}';
  2471. -  const char *beg;
  2472. -  const char *end;
  2473. -  int count = 0;
  2474. -  char *abeg = NULL;
  2475. +  char *beg;
  2476. +  char *end;
  2477. +  int count;
  2478.    char **argv, **argvp;
  2479. -  int nargs;
  2480. +  int nargs, maxargs;
  2481. +  struct vbuffer argbuf;
  2482.  
  2483.    beg = *stringp + 1;
  2484.  
  2485.    entry_p = lookup_function (beg);
  2486.  
  2487.    if (!entry_p)
  2488. -    return 0;
  2489. +    return -1;
  2490. +
  2491. +  vbuffer_init(&argbuf);
  2492.  
  2493.    /* We found a builtin function.  Find the beginning of its arguments (skip
  2494.       whitespace after the name).  */
  2495.  
  2496.    beg = next_token (beg + entry_p->len);
  2497. +  maxargs = entry_p->maximum_args;
  2498.  
  2499.    /* Find the end of the function invocation, counting nested use of
  2500.       whichever kind of parens we use.  Since we're looking, count commas
  2501.       to get a rough estimate of how many arguments we might have.  The
  2502.       count might be high, but it'll never be low.  */
  2503.  
  2504. -  for (nargs=1, end=beg; *end != '\0'; ++end)
  2505. -    if (*end == ',')
  2506. -      ++nargs;
  2507. -    else if (*end == openparen)
  2508. +
  2509. +  nargs=1;
  2510. +  *((char **) argbuf.ptr) = beg;
  2511. +  argbuf.ptr += sizeof (char *);
  2512. +
  2513. +  count = 0;
  2514. +  for (end=beg; *end != '\0'; ++end)
  2515. +    if (*end == openparen)
  2516.        ++count;
  2517.      else if (*end == closeparen && --count < 0)
  2518.        break;
  2519. +    else if (count == 0 && *end == ',' && nargs != maxargs)
  2520. +      {
  2521. +   *end = '\0';
  2522. +   nargs++;
  2523. +
  2524. +   vbuffer_reserve(&argbuf, sizeof (char *));
  2525. +   *((char **) argbuf.ptr) = end + 1;
  2526. +   argbuf.ptr += sizeof (char *);
  2527. +      }
  2528.  
  2529.    if (count >= 0)
  2530.      fatal (*expanding_var,
  2531. @@ -2312,8 +2255,14 @@
  2532.  
  2533.    *stringp = end;
  2534.  
  2535. -  /* Get some memory to store the arg pointers.  */
  2536. -  argvp = argv = alloca (sizeof (char *) * (nargs + 2));
  2537. +  *end = '\0';
  2538. +
  2539. +  /* NULL-terminate the arg vector. */
  2540. +  vbuffer_reserve(&argbuf, sizeof (char *));
  2541. +  *((char **) argbuf.ptr) = NULL;
  2542. +  argbuf.ptr += sizeof (char *);
  2543. +
  2544. +  argv = (char **) argbuf.buffer;
  2545.  
  2546.    /* Chop the string into arguments, then a nul.  As soon as we hit
  2547.       MAXIMUM_ARGS (if it's >0) assume the rest of the string is part of the
  2548. @@ -2325,59 +2274,30 @@
  2549.  
  2550.    if (entry_p->expand_args)
  2551.      {
  2552. -      const char *p;
  2553. -      for (p=beg, nargs=0; p <= end; ++argvp)
  2554. -        {
  2555. -          const char *next;
  2556. -
  2557. -          ++nargs;
  2558. -
  2559. -          if (nargs == entry_p->maximum_args
  2560. -              || (! (next = find_next_argument (openparen, closeparen, p, end))))
  2561. -            next = end;
  2562. -
  2563. -          *argvp = expand_argument (p, next);
  2564. -          p = next + 1;
  2565. -        }
  2566. -    }
  2567. -  else
  2568. -    {
  2569. -      int len = end - beg;
  2570. -      char *p, *aend;
  2571. -
  2572. -      abeg = xmalloc (len+1);
  2573. -      memcpy (abeg, beg, len);
  2574. -      abeg[len] = '\0';
  2575. -      aend = abeg + len;
  2576. -
  2577. -      for (p=abeg, nargs=0; p <= aend; ++argvp)
  2578. -        {
  2579. -          char *next;
  2580. -
  2581. -          ++nargs;
  2582. -
  2583. -          if (nargs == entry_p->maximum_args
  2584. -              || (! (next = find_next_argument (openparen, closeparen, p, aend))))
  2585. -            next = aend;
  2586. -
  2587. -          *argvp = p;
  2588. -          *next = '\0';
  2589. -          p = next + 1;
  2590. -        }
  2591. +      int i;
  2592. +      size_t *offs = alloca ((nargs + 1) * sizeof (size_t));
  2593. +      argv = memcpy (alloca ((nargs + 1) * sizeof (char *)),
  2594. +              argv, (nargs + 1) * sizeof (char *));
  2595. +
  2596. +      vbuffer_reset(&argbuf);
  2597. +      offs[0] = 0;
  2598. +      for (i=0, argvp=argv; *argvp != 0; ++argvp, ++i)
  2599. +   {
  2600. +     offs[i + 1] = offs[i] + vbuffer_expand (&argbuf, *argvp, -1) + 1;
  2601. +     *argbuf.ptr++ = '\0';
  2602. +   }
  2603. +      for (i=0, argvp=argv; *argvp != 0; ++argvp, ++i)
  2604. +   *argvp = argbuf.buffer + offs[i];
  2605.      }
  2606. -  *argvp = NULL;
  2607.  
  2608.    /* Finally!  Run the function...  */
  2609. -  *op = expand_builtin_function (*op, nargs, argv, entry_p);
  2610. +  result += expand_builtin_function (o, nargs, argv, entry_p);
  2611.  
  2612. -  /* Free memory.  */
  2613. -  if (entry_p->expand_args)
  2614. -    for (argvp=argv; *argvp != 0; ++argvp)
  2615. -      free (*argvp);
  2616. -  else if (abeg)
  2617. -    free (abeg);
  2618. +  *end = closeparen;
  2619.  
  2620. -  return 1;
  2621. +  vbuffer_free(&argbuf);
  2622. +
  2623. +  return result;
  2624.  }
  2625.  
  2626.  
  2627. @@ -2385,36 +2305,61 @@
  2628.     function or a make variable, in the context of the rest of the arguments
  2629.     assigned to $1, $2, ... $N.  $0 is the name of the function.  */
  2630.  
  2631. -static char *
  2632. -func_call (char *o, char **argv, const char *funcname UNUSED)
  2633. +struct call_arg
  2634. +{
  2635. +  struct variable var;
  2636. +  struct variable *upper;
  2637. +  char *masked_value;
  2638. +};
  2639. +
  2640. +struct call_frame
  2641. +{
  2642. +  struct call_arg *args;
  2643. +};
  2644. +
  2645. +static size_t
  2646. +func_call (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  2647.  {
  2648. -  static int max_args = 0;
  2649. +  size_t ret = 0;
  2650. +
  2651. +  static char *digits[10] =
  2652. +      { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", };
  2653. +
  2654. +  static struct call_frame nullframe = { NULL };
  2655. +  static struct call_frame *upframe = &nullframe;
  2656. +
  2657. +  struct call_frame *saved_upframe;
  2658.    char *fname;
  2659.    char *cp;
  2660. -  char *body;
  2661.    int flen;
  2662.    int i;
  2663. -  int saved_args;
  2664. +  char **argvp;
  2665. +  struct call_arg **upframe_argp;
  2666. +  struct call_arg **masked_argp;
  2667.    const struct function_table_entry *entry_p;
  2668.    struct variable *v;
  2669.  
  2670.    /* There is no way to define a variable with a space in the name, so strip
  2671. -     leading and trailing whitespace as a favor to the user.  */
  2672. +     trailing whitespace as a favor to the user.  */
  2673.    fname = argv[0];
  2674.    while (*fname != '\0' && isspace ((unsigned char)*fname))
  2675.      ++fname;
  2676.  
  2677. -  cp = fname + strlen (fname) - 1;
  2678. +  flen = strlen (fname);
  2679. +
  2680. +  cp = fname + flen - 1;
  2681.    while (cp > fname && isspace ((unsigned char)*cp))
  2682.      --cp;
  2683.    cp[1] = '\0';
  2684.  
  2685.    /* Calling nothing is a no-op */
  2686.    if (*fname == '\0')
  2687. -    return o;
  2688. +    return 0;
  2689.  
  2690. -  /* Are we invoking a builtin function?  */
  2691. +  /* Fix up the length after stripping a trailing whitespace. */
  2692. +  flen = cp - fname + 1;
  2693.  
  2694. +  /* Are we invoking a builtin function?  */
  2695.    entry_p = lookup_function (fname);
  2696.    if (entry_p)
  2697.      {
  2698. @@ -2426,7 +2371,6 @@
  2699.  
  2700.    /* Not a builtin, so the first argument is the name of a variable to be
  2701.       expanded and interpreted as a function.  Find it.  */
  2702. -  flen = strlen (fname);
  2703.  
  2704.    v = lookup_variable (fname, flen);
  2705.  
  2706. @@ -2434,61 +2378,86 @@
  2707.      warn_undefined (fname, flen);
  2708.  
  2709.    if (v == 0 || *v->value == '\0')
  2710. -    return o;
  2711. -
  2712. -  body = alloca (flen + 4);
  2713. -  body[0] = '$';
  2714. -  body[1] = '(';
  2715. -  memcpy (body + 2, fname, flen);
  2716. -  body[flen+2] = ')';
  2717. -  body[flen+3] = '\0';
  2718. +    return 0;
  2719.  
  2720.    /* Set up arguments $(1) .. $(N).  $(0) is the function name.  */
  2721.  
  2722. -  push_new_variable_scope ();
  2723. +  upframe_argp = &upframe->args;
  2724.  
  2725. -  for (i=0; *argv; ++i, ++argv)
  2726. -    {
  2727. -      char num[11];
  2728. +  /* The first ten argument names are always taken from digits cache.  */
  2729.  
  2730. -      sprintf (num, "%d", i);
  2731. -      define_variable (num, strlen (num), *argv, o_automatic, 0);
  2732. +  for (i=0, argvp=argv; *argvp; ++i, ++argvp)
  2733. +    {
  2734. +      struct call_arg *arg = alloca (sizeof (struct call_arg));
  2735. +      char *num = alloca (12);
  2736. +      arg->upper = i < 10
  2737. +          ? push_scoped_variable (&arg->var, digits[i], 1)
  2738. +          : push_scoped_variable (&arg->var, num,
  2739. +                      sprintf (num, "%d", i));
  2740. +      arg->var.value = *argvp;
  2741. +      arg->masked_value = 0;
  2742. +      *argvp = (void *) arg;
  2743. +      if (*upframe_argp)
  2744. +   ++upframe_argp;
  2745.      }
  2746.  
  2747.    /* If the number of arguments we have is < max_args, it means we're inside
  2748.       a recursive invocation of $(call ...).  Fill in the remaining arguments
  2749.       in the new scope with the empty value, to hide them from this
  2750.       invocation.  */
  2751. +  masked_argp = upframe_argp;
  2752.  
  2753. -  for (; i < max_args; ++i)
  2754. +  for (; *upframe_argp; ++i, ++upframe_argp)
  2755.      {
  2756. -      char num[11];
  2757. -
  2758. -      sprintf (num, "%d", i);
  2759. -      define_variable (num, strlen (num), "", o_automatic, 0);
  2760. +      char num[12];
  2761. +      struct variable *arg_var = i < 10
  2762. +                ? lookup_variable (digits[i], 1)
  2763. +                : lookup_variable (num,
  2764. +                           sprintf (num, "%d", i));
  2765. +      if (arg_var == &(*upframe_argp)->var)
  2766. +   {
  2767. +     (*upframe_argp)->masked_value = arg_var->value;
  2768. +     arg_var->value = "";
  2769. +   }
  2770.      }
  2771.  
  2772. -  /* Expand the body in the context of the arguments, adding the result to
  2773. +  /* Expand the variable in the context of the arguments, adding the result to
  2774.       the variable buffer.  */
  2775.  
  2776. +  saved_upframe = upframe;
  2777. +  upframe = (struct call_frame *) argv;
  2778. +
  2779.    v->exp_count = EXP_COUNT_MAX;
  2780. +  ret += v->recursive
  2781. +    ? vbuffer_expand_variable (o, v)
  2782. +    : vbuffer_write(o, v->value, -1);
  2783. +  v->exp_count = 0;
  2784.  
  2785. -  saved_args = max_args;
  2786. -  max_args = i;
  2787. -  o = variable_expand_string (o, body, flen+3);
  2788. -  max_args = saved_args;
  2789. +  upframe = saved_upframe;
  2790.  
  2791. -  v->exp_count = 0;
  2792. +  for (argvp=argv; *argvp; ++argvp)
  2793. +    {
  2794. +      struct call_arg *arg = (struct call_arg *) *argvp;
  2795. +      pop_scoped_variable (&arg->var, arg->upper);
  2796. +    }
  2797.  
  2798. -  pop_variable_scope ();
  2799. +  for (upframe_argp=masked_argp; *upframe_argp; ++upframe_argp)
  2800. +    {
  2801. +      struct call_arg *arg = (*upframe_argp);
  2802. +      if (arg->masked_value)
  2803. +   {
  2804. +     arg->var.value = arg->masked_value;
  2805. +     arg->masked_value = NULL;
  2806. +   }
  2807. +    }
  2808.  
  2809. -  return o + strlen (o);
  2810. +  return ret;
  2811.  }
  2812.  
  2813.  void
  2814.  define_new_function(const struct floc *flocp,
  2815.                      const char *name, int min, int max, int expand,
  2816. -                    char *(*func)(char *, char **, const char *))
  2817. +                    size_t (*func)(struct vbuffer *, char **, const char *))
  2818.  {
  2819.    size_t len = strlen (name);
  2820.    struct function_table_entry *ent = xmalloc (sizeof (struct function_table_entry));
  2821. Index: guile.c
  2822. ===================================================================
  2823. RCS file: /sources/make/make/guile.c,v
  2824. retrieving revision 2.5
  2825. diff -u -r2.5 guile.c
  2826. --- guile.c 5 Mar 2012 14:10:44 -0000   2.5
  2827. +++ guile.c 16 Mar 2012 03:20:31 -0000
  2828. @@ -86,20 +86,22 @@
  2829.  }
  2830.  
  2831.  /* This is the function registered with make  */
  2832. -static char *
  2833. -func_guile (char *o, char **argv, const char *funcname UNUSED)
  2834. +static size_t
  2835. +func_guile (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  2836.  {
  2837. +  size_t result = 0;
  2838. +
  2839.    if (argv[0] && argv[0][0] != '\0')
  2840.      {
  2841.        char *str = scm_with_guile (internal_guile_eval, argv[0]);
  2842.        if (str)
  2843.          {
  2844. -          o = variable_buffer_output (o, str, strlen (str));
  2845. +          result += vbuffer_write (o, str, -1);
  2846.            free (str);
  2847.          }
  2848.      }
  2849.  
  2850. -  return o;
  2851. +  return result;
  2852.  }
  2853.  
  2854.  /* ----- Public interface ----- */
  2855. Index: main.c
  2856. ===================================================================
  2857. RCS file: /sources/make/make/main.c,v
  2858. retrieving revision 1.256
  2859. diff -u -r1.256 main.c
  2860. --- main.c  5 Mar 2012 14:10:44 -0000   1.256
  2861. +++ main.c  16 Mar 2012 03:20:31 -0000
  2862. @@ -1104,6 +1104,8 @@
  2863.  
  2864.    initialize_global_hash_tables ();
  2865.  
  2866. +  install_new_expansion_vbuffer();
  2867. +
  2868.    /* Figure out where we are.  */
  2869.  
  2870.  #ifdef WINDOWS32
  2871. @@ -2277,12 +2279,7 @@
  2872.        if (default_goal_var->recursive)
  2873.          p = variable_expand (default_goal_var->value);
  2874.        else
  2875. -        {
  2876. -          p = variable_buffer_output (variable_buffer, default_goal_var->value,
  2877. -                                      strlen (default_goal_var->value));
  2878. -          *p = '\0';
  2879. -          p = variable_buffer;
  2880. -        }
  2881. +   p = default_goal_var->value;
  2882.  
  2883.        if (*p != '\0')
  2884.          {
  2885. Index: make.h
  2886. ===================================================================
  2887. RCS file: /sources/make/make/make.h,v
  2888. retrieving revision 1.157
  2889. diff -u -r1.157 make.h
  2890. --- make.h  5 Mar 2012 14:10:44 -0000   1.157
  2891. +++ make.h  16 Mar 2012 03:20:31 -0000
  2892. @@ -406,11 +406,22 @@
  2893.  void *xrealloc (void *, unsigned int);
  2894.  char *xstrdup (const char *);
  2895.  char *xstrndup (const char *, unsigned int);
  2896. +
  2897.  char *find_next_token (const char **, unsigned int *);
  2898. -char *next_token (const char *);
  2899. -char *end_of_token (const char *);
  2900. +
  2901. +static __inline char *
  2902. +next_token (const char *s)
  2903. +  { return (char *) s + strspn(s, " \t"); }
  2904. +
  2905. +static __inline char *
  2906. +end_of_token (const char *s)
  2907. +  { return (char *) s + strcspn(s, " \t"); }
  2908. +
  2909. +static __inline char *
  2910. +lindex (const char *s, const char *limit, int c)
  2911. +  { return memchr (s, c, limit - s); }
  2912. +
  2913.  void collapse_continuations (char *);
  2914. -char *lindex (const char *, const char *, int);
  2915.  int alpha_compare (const void *, const void *);
  2916.  void print_spaces (unsigned int);
  2917.  char *find_percent (char *);
  2918. Index: misc.c
  2919. ===================================================================
  2920. RCS file: /sources/make/make/misc.c,v
  2921. retrieving revision 1.89
  2922. diff -u -r1.89 misc.c
  2923. --- misc.c  5 Mar 2012 14:10:44 -0000   1.89
  2924. +++ misc.c  16 Mar 2012 03:20:31 -0000
  2925. @@ -447,6 +447,7 @@
  2926.  }
  2927.  
  2928.  
  2929. +#if 0
  2930.  /* Limited INDEX:
  2931.     Search through the string STRING, which ends at LIMIT, for the character C.
  2932.     Returns a pointer to the first occurrence, or nil if none is found.
  2933. @@ -472,6 +473,7 @@
  2934.      ++s;
  2935.    return (char *)s;
  2936.  }
  2937. +#endif
  2938.  
  2939.  #ifdef WINDOWS32
  2940.  /*
  2941. @@ -503,6 +505,7 @@
  2942.  }
  2943.  #endif
  2944.  
  2945. +#if 0
  2946.  /* Return the address of the first nonwhitespace or null in the string S.  */
  2947.  
  2948.  char *
  2949. @@ -512,6 +515,7 @@
  2950.      ++s;
  2951.    return (char *)s;
  2952.  }
  2953. +#endif
  2954.  
  2955.  /* Find the next token in PTR; return the address of it, and store the length
  2956.     of the token into *LENGTHPTR if LENGTHPTR is not nil.  Set *PTR to the end
  2957. Index: read.c
  2958. ===================================================================
  2959. RCS file: /sources/make/make/read.c,v
  2960. retrieving revision 1.210
  2961. diff -u -r1.210 read.c
  2962. --- read.c  5 Mar 2012 14:10:44 -0000   1.210
  2963. +++ read.c  16 Mar 2012 03:20:31 -0000
  2964. @@ -566,6 +566,7 @@
  2965.    const char *pattern_percent;
  2966.    struct floc *fstart;
  2967.    struct floc fi;
  2968. +  struct vbuffer vbuf;
  2969.  
  2970.  #define record_waiting_files()                           \
  2971.    do                                         \
  2972. @@ -583,6 +584,8 @@
  2973.        pattern = 0;                                                            \
  2974.      } while (0)
  2975.  
  2976. +  vbuffer_init(&vbuf);
  2977. +
  2978.    pattern_percent = 0;
  2979.    cmds_started = tgts_started = 1;
  2980.  
  2981. @@ -893,6 +896,7 @@
  2982.        {
  2983.          enum make_word_type wtype;
  2984.          char *cmdleft, *semip, *lb_next;
  2985. +        unsigned int llen = 0;
  2986.          unsigned int plen = 0;
  2987.          char *colonp;
  2988.          const char *end, *beg; /* Helpers for whitespace stripping. */
  2989. @@ -943,42 +947,44 @@
  2990.              break;
  2991.            }
  2992.  
  2993. -        p2 = variable_expand_string(NULL, lb_next, wlen);
  2994. -
  2995. -        while (1)
  2996. -          {
  2997. -            lb_next += wlen;
  2998. -            if (cmdleft == 0)
  2999. -              {
  3000. -                /* Look for a semicolon in the expanded line.  */
  3001. -                cmdleft = find_char_unquote (p2, ';', 0, 0, 0);
  3002. +        vbuffer_expand_ro (vbuffer_reset(&vbuf), lb_next, wlen);
  3003. +   p2 = vbuf.buffer;
  3004.  
  3005. -                if (cmdleft != 0)
  3006. -                  {
  3007. -                    unsigned long p2_off = p2 - variable_buffer;
  3008. -                    unsigned long cmd_off = cmdleft - variable_buffer;
  3009. -                    char *pend = p2 + strlen(p2);
  3010. -
  3011. -                    /* Append any remnants of lb, then cut the line short
  3012. -                       at the semicolon.  */
  3013. -                    *cmdleft = '\0';
  3014. -
  3015. -                    /* One school of thought says that you shouldn't expand
  3016. -                       here, but merely copy, since now you're beyond a ";"
  3017. -                       and into a command script.  However, the old parser
  3018. -                       expanded the whole line, so we continue that for
  3019. -                       backwards-compatiblity.  Also, it wouldn't be
  3020. -                       entirely consistent, since we do an unconditional
  3021. -                       expand below once we know we don't have a
  3022. -                       target-specific variable. */
  3023. -                    (void)variable_expand_string(pend, lb_next, (long)-1);
  3024. -                    lb_next += strlen(lb_next);
  3025. -                    p2 = variable_buffer + p2_off;
  3026. -                    cmdleft = variable_buffer + cmd_off + 1;
  3027. -                  }
  3028. -              }
  3029. +   while (1)
  3030. +     {
  3031. +       lb_next += wlen;
  3032. +       if (cmdleft == 0)
  3033. +         {
  3034. +       /* Look for a semicolon in the expanded line.  */
  3035. +       cmdleft = find_char_unquote (p2, ';', 0, 0, 0);
  3036. +
  3037. +       if (cmdleft != 0)
  3038. +         {
  3039. +           unsigned long p2_off = p2 - vbuf.buffer;
  3040. +           unsigned long cmd_off = cmdleft - vbuf.buffer;
  3041. +
  3042. +           /* Append any remnants of lb, then cut the line short
  3043. +              at the semicolon.  */
  3044. +           *cmdleft = '\0';
  3045. +
  3046. +           /* One school of thought says that you shouldn't expand
  3047. +              here, but merely copy, since now you're beyond a ";"
  3048. +              and into a command script.  However, the old parser
  3049. +              expanded the whole line, so we continue that for
  3050. +              backwards-compatibility.  Also, it wouldn't be
  3051. +              entirely consistent, since we do an unconditional
  3052. +              expand below once we know we don't have a
  3053. +              target-specific variable. */
  3054. +           vbuffer_expand_ro (&vbuf, lb_next, -1);
  3055. +
  3056. +           p2 = vbuf.buffer + p2_off;
  3057. +           cmdleft = vbuf.buffer + cmd_off + 1;
  3058. +
  3059. +           lb_next += strlen(lb_next);
  3060. +         }
  3061. +         }
  3062.  
  3063. -            colonp = find_char_unquote(p2, ':', 0, 0, 0);
  3064. +       colonp = find_char_unquote(p2, ':', 0, 0, 0);
  3065.  #ifdef HAVE_DOS_PATHS
  3066.              /* The drive spec brain-damage strikes again...  */
  3067.              /* Note that the only separators of targets in this context
  3068. @@ -989,118 +995,119 @@
  3069.                     (colonp == p2 + 1 || strchr (" \t(", colonp[-2]) != 0))
  3070.                colonp = find_char_unquote(colonp + 1, ':', 0, 0, 0);
  3071.  #endif
  3072. -            if (colonp != 0)
  3073. -              break;
  3074. -
  3075. -            wtype = get_next_mword(lb_next, NULL, &lb_next, &wlen);
  3076. -            if (wtype == w_eol)
  3077. -              break;
  3078. -
  3079. -            p2 += strlen(p2);
  3080. -            *(p2++) = ' ';
  3081. -            p2 = variable_expand_string(p2, lb_next, wlen);
  3082. -            /* We don't need to worry about cmdleft here, because if it was
  3083. -               found in the variable_buffer the entire buffer has already
  3084. -               been expanded... we'll never get here.  */
  3085. -          }
  3086. -
  3087. -        p2 = next_token (variable_buffer);
  3088. +       if (colonp != 0)
  3089. +         break;
  3090.  
  3091. -        /* If the word we're looking at is EOL, see if there's _anything_
  3092. -           on the line.  If not, a variable expanded to nothing, so ignore
  3093. -           it.  If so, we can't parse this line so punt.  */
  3094. -        if (wtype == w_eol)
  3095. -          {
  3096. -            if (*p2 != '\0')
  3097. -              /* There's no need to be ivory-tower about this: check for
  3098. -                 one of the most common bugs found in makefiles...  */
  3099. -              fatal (fstart, _("missing separator%s"),
  3100. -                     (cmd_prefix == '\t' && !strneq (line, "        ", 8))
  3101. -                     ? "" : _(" (did you mean TAB instead of 8 spaces?)"));
  3102. -            continue;
  3103. -          }
  3104. +       wtype = get_next_mword(lb_next, NULL, &lb_next, &wlen);
  3105. +       if (wtype == w_eol)
  3106. +         break;
  3107.  
  3108. -        /* Make the colon the end-of-string so we know where to stop
  3109. -           looking for targets.  Start there again once we're done.  */
  3110. -        *colonp = '\0';
  3111. -        filenames = PARSE_FILE_SEQ (&p2, struct nameseq, '\0', NULL, 0);
  3112. -        *colonp = ':';
  3113. -        p2 = colonp;
  3114. +       vbuffer_write(&vbuf, " ", 1);
  3115. +       plen = vbuffer_expand_ro (&vbuf, lb_next, wlen);
  3116. +       p2 = vbuf.ptr - plen;
  3117. +
  3118. +       /* We don't need to worry about cmdleft here, because if it was
  3119. +          found in the variable_buffer the entire buffer has already
  3120. +          been expanded... we'll never get here.  */
  3121. +     }
  3122.  
  3123. -        if (!filenames)
  3124. -          {
  3125. -            /* We accept and ignore rules without targets for
  3126. -               compatibility with SunOS 4 make.  */
  3127. -            no_targets = 1;
  3128. -            continue;
  3129. -          }
  3130. -        /* This should never be possible; we handled it above.  */
  3131. -        assert (*p2 != '\0');
  3132. -        ++p2;
  3133. -
  3134. -        /* Is this a one-colon or two-colon entry?  */
  3135. -        two_colon = *p2 == ':';
  3136. -        if (two_colon)
  3137. -          p2++;
  3138. -
  3139. -        /* Test to see if it's a target-specific variable.  Copy the rest
  3140. -           of the buffer over, possibly temporarily (we'll expand it later
  3141. -           if it's not a target-specific variable).  PLEN saves the length
  3142. -           of the unparsed section of p2, for later.  */
  3143. -        if (*lb_next != '\0')
  3144. -          {
  3145. -            unsigned int l = p2 - variable_buffer;
  3146. -            plen = strlen (p2);
  3147. -            variable_buffer_output (p2+plen, lb_next, strlen (lb_next)+1);
  3148. -            p2 = variable_buffer + l;
  3149. -          }
  3150. +   p2 = next_token (vbuf.buffer);
  3151.  
  3152. -        p2 = parse_var_assignment (p2, &vmod);
  3153. -        if (vmod.assign_v)
  3154. -          {
  3155. -            /* If there was a semicolon found, add it back, plus anything
  3156. -               after it.  */
  3157. -            if (semip)
  3158. -              {
  3159. -                unsigned int l = p - variable_buffer;
  3160. -                *(--semip) = ';';
  3161. -                collapse_continuations (semip);
  3162. -                variable_buffer_output (p2 + strlen (p2),
  3163. -                                        semip, strlen (semip)+1);
  3164. -                p = variable_buffer + l;
  3165. -              }
  3166. -            record_target_var (filenames, p2,
  3167. -                               vmod.override_v ? o_override : o_file,
  3168. -                               &vmod, fstart);
  3169. -            filenames = 0;
  3170. -            continue;
  3171. -          }
  3172. -
  3173. -        /* This is a normal target, _not_ a target-specific variable.
  3174. -           Unquote any = in the dependency list.  */
  3175. -        find_char_unquote (lb_next, '=', 0, 0, 0);
  3176. +   /* If the word we're looking at is EOL, see if there's _anything_
  3177. +      on the line.  If not, a variable expanded to nothing, so ignore
  3178. +      it.  If so, we can't parse this line so punt.  */
  3179. +   if (wtype == w_eol)
  3180. +     {
  3181. +       if (*p2 != '\0')
  3182. +         /* There's no need to be ivory-tower about this: check for
  3183. +        one of the most common bugs found in makefiles...  */
  3184. +         fatal (fstart, _("missing separator%s"),
  3185. +            (cmd_prefix == '\t' && !strneq (line, "        ", 8))
  3186. +            ? "" : _(" (did you mean TAB instead of 8 spaces?)"));
  3187. +       continue;
  3188. +     }
  3189.  
  3190. -        /* Remember the command prefix for this target.  */
  3191. -        prefix = cmd_prefix;
  3192. +   /* Make the colon the end-of-string so we know where to stop
  3193. +      looking for targets.  Start there again once we're done.  */
  3194. +   *colonp = '\0';
  3195. +   filenames = PARSE_FILE_SEQ (&p2, struct nameseq, '\0', NULL, 0);
  3196. +   *colonp = ':';
  3197. +   p2 = colonp;
  3198.  
  3199. -        /* We have some targets, so don't ignore the following commands.  */
  3200. -        no_targets = 0;
  3201. +   if (!filenames)
  3202. +     {
  3203. +       /* We accept and ignore rules without targets for
  3204. +          compatibility with SunOS 4 make.  */
  3205. +       no_targets = 1;
  3206. +       continue;
  3207. +     }
  3208. +   /* This should never be possible; we handled it above.  */
  3209. +   assert (*p2 != '\0');
  3210. +   ++p2;
  3211. +
  3212. +   /* Is this a one-colon or two-colon entry?  */
  3213. +   two_colon = *p2 == ':';
  3214. +   if (two_colon)
  3215. +     p2++;
  3216. +
  3217. +   /* Test to see if it's a target-specific variable.  Copy the rest
  3218. +      of the buffer over, possibly temporarily (we'll expand it later
  3219. +      if it's not a target-specific variable).  LLEN saves the length
  3220. +      of the copied string, to know how many bytes to discard later.  */
  3221. +   if (*lb_next != '\0')
  3222. +     {
  3223. +       unsigned long p2_off = p2 - vbuf.buffer;
  3224. +       llen = vbuffer_write (&vbuf, lb_next, -1);
  3225. +       p2 = vbuf.buffer + p2_off;
  3226. +     }
  3227.  
  3228. -        /* Expand the dependencies, etc.  */
  3229. -        if (*lb_next != '\0')
  3230. -          {
  3231. -            unsigned int l = p2 - variable_buffer;
  3232. -            (void) variable_expand_string (p2 + plen, lb_next, (long)-1);
  3233. -            p2 = variable_buffer + l;
  3234. +   p2 = parse_var_assignment (p2, &vmod);
  3235. +   if (vmod.assign_v)
  3236. +     {
  3237. +       /* If there was a semicolon found, add it back, plus anything
  3238. +          after it.  */
  3239. +       if (semip)
  3240. +         {
  3241. +       unsigned long p2_off = p2 - vbuf.buffer;
  3242. +       *(--semip) = ';';
  3243. +       collapse_continuations (semip);
  3244. +       vbuffer_write (&vbuf, semip, -1);
  3245. +       p2 = vbuf.buffer + p2_off;
  3246. +         }
  3247. +       record_target_var (filenames, p2,
  3248. +                  vmod.override_v ? o_override : o_file,
  3249. +                  &vmod, fstart);
  3250. +       filenames = 0;
  3251. +       continue;
  3252. +     }
  3253.  
  3254. -            /* Look for a semicolon in the expanded line.  */
  3255. -            if (cmdleft == 0)
  3256. -              {
  3257. -                cmdleft = find_char_unquote (p2, ';', 0, 0, 0);
  3258. -                if (cmdleft != 0)
  3259. -                  *(cmdleft++) = '\0';
  3260. -              }
  3261. -          }
  3262. +   /* This is a normal target, _not_ a target-specific variable.
  3263. +      Unquote any = in the dependency list.  */
  3264. +   find_char_unquote (lb_next, '=', 0, 0, 0);
  3265. +
  3266. +   /* Remember the command prefix for this target.  */
  3267. +   prefix = cmd_prefix;
  3268. +
  3269. +   /* We have some targets, so don't ignore the following commands.  */
  3270. +   no_targets = 0;
  3271. +
  3272. +   /* Expand the dependencies, etc.
  3273. +      P2 still point past the colon.  */
  3274. +   if (*lb_next != '\0')
  3275. +     {
  3276. +       unsigned long p2_off = p2 - vbuf.buffer;
  3277. +       vbuffer_unwrite (&vbuf, llen);
  3278. +       vbuffer_expand_ro (&vbuf, lb_next, -1);
  3279. +       p2 = vbuf.buffer + p2_off;
  3280. +
  3281. +       /* Look for a semicolon in the expanded line.  */
  3282. +       if (cmdleft == 0)
  3283. +         {
  3284. +       cmdleft = find_char_unquote (p2, ';', 0, 0, 0);
  3285. +       if (cmdleft != 0)
  3286. +         *(cmdleft++) = '\0';
  3287. +         }
  3288. +     }
  3289.  
  3290.          /* Is this a static pattern rule: 'target: %targ: %dep; ...'?  */
  3291.          p = strchr (p2, ':');
  3292. @@ -1281,8 +1288,6 @@
  3293.        record_waiting_files ();
  3294.      }
  3295.  
  3296. -#undef word1eq
  3297. -
  3298.    if (conditionals->if_cmds)
  3299.      fatal (fstart, _("missing 'endif'"));
  3300.  
  3301. @@ -1292,7 +1297,13 @@
  3302.    if (collapsed)
  3303.      free (collapsed);
  3304.    free (commands);
  3305. +
  3306. +  vbuffer_free(&vbuf);
  3307. +
  3308. +#undef record_waiting_files
  3309.  }
  3310. +
  3311. +#undef word1eq
  3312.  
  3313.  
  3314.  /* Remove comments from LINE.
  3315. @@ -1842,6 +1853,7 @@
  3316.    struct dep *deps;
  3317.    const char *implicit_percent;
  3318.    const char *name;
  3319. +  struct vbuffer patbuf;
  3320.  
  3321.    /* If we've already snapped deps, that means we're in an eval being
  3322.       resolved after the makefiles have been read in.  We can't add more rules
  3323. @@ -1945,6 +1957,7 @@
  3324.        return;
  3325.      }
  3326.  
  3327. +  vbuffer_init (&patbuf);
  3328.  
  3329.    /* Walk through each target and create it in the database.
  3330.       We already set up the first target, above.  */
  3331. @@ -2057,10 +2070,12 @@
  3332.        if (pattern)
  3333.          {
  3334.            static const char *percent = "%";
  3335. -          char *buffer = variable_expand ("");
  3336. -          char *o = patsubst_expand_pat (buffer, name, pattern, percent,
  3337. -                                         pattern_percent+1, percent+1);
  3338. -          f->stem = strcache_add_len (buffer, o - buffer);
  3339. +          size_t len;
  3340. +
  3341. +          len = patsubst_expand_pat (vbuffer_reset(&patbuf), name,
  3342. +                    pattern, percent,
  3343. +                    pattern_percent+1, percent+1);
  3344. +          f->stem = strcache_add_len (patbuf.buffer, len);
  3345.            if (this)
  3346.              {
  3347.                if (! this->need_2nd_expansion)
  3348. @@ -2112,6 +2127,8 @@
  3349.        if (find_percent_cached (&name))
  3350.          fatal (flocp, _("mixed implicit and normal rules"));
  3351.      }
  3352. +
  3353. +  vbuffer_free (&patbuf);
  3354.  }
  3355.  
  3356.  /* Search STRING for an unquoted STOPCHAR or blank (if BLANK is nonzero).
  3357. Index: remake.c
  3358. ===================================================================
  3359. RCS file: /sources/make/make/remake.c,v
  3360. retrieving revision 1.153
  3361. diff -u -r1.153 remake.c
  3362. --- remake.c    5 Mar 2012 14:10:45 -0000   1.153
  3363. +++ remake.c    16 Mar 2012 03:20:31 -0000
  3364. @@ -1534,12 +1534,14 @@
  3365.    const char *p2;
  3366.    unsigned int len;
  3367.    unsigned int liblen;
  3368. +  struct vbuffer vbuf;
  3369.  
  3370.    /* Information about the earliest (in the vpath sequence) match.  */
  3371.    unsigned int best_vpath = 0, best_path = 0;
  3372.  
  3373.    char **dp;
  3374.  
  3375. +  vbuffer_init(&vbuf);
  3376.    libpatterns = xstrdup (variable_expand ("$(.LIBPATTERNS)"));
  3377.  
  3378.    /* Skip the '-l'.  */
  3379. @@ -1556,28 +1558,30 @@
  3380.        static unsigned int buflen = 0;
  3381.        static int libdir_maxlen = -1;
  3382.        static unsigned int std_dirs = 0;
  3383. -      char *libbuf = variable_expand ("");
  3384. +      char *libbuf;
  3385.  
  3386.        /* Expand the pattern using LIB as a replacement.  */
  3387.        {
  3388.     char c = p[len];
  3389. -   char *p3, *p4;
  3390. +   char *percent;
  3391.  
  3392.     p[len] = '\0';
  3393. -   p3 = find_percent (p);
  3394. -   if (!p3)
  3395. +   percent = find_percent (p);
  3396. +   if (!percent)
  3397.       {
  3398.         /* Give a warning if there is no pattern.  */
  3399.         error (NILF, _(".LIBPATTERNS element '%s' is not a pattern"), p);
  3400.              p[len] = c;
  3401.         continue;
  3402.       }
  3403. -   p4 = variable_buffer_output (libbuf, p, p3-p);
  3404. -   p4 = variable_buffer_output (p4, lib, liblen);
  3405. -   p4 = variable_buffer_output (p4, p3+1, len - (p3-p));
  3406. +   vbuffer_write (&vbuf, p, percent-p);
  3407. +   vbuffer_write (&vbuf, lib, liblen);
  3408. +   vbuffer_write (&vbuf, percent+1, len - (percent-p));
  3409.     p[len] = c;
  3410.        }
  3411.  
  3412. +      libbuf = vbuf.buffer;
  3413. +
  3414.        /* Look first for 'libNAME.a' in the current directory.  */
  3415.        mtime = name_mtime (libbuf);
  3416.        if (mtime != NONEXISTENT_MTIME)
  3417. @@ -1660,5 +1664,7 @@
  3418.      }
  3419.  
  3420.    free (libpatterns);
  3421. +  vbuffer_free(&vbuf);
  3422. +
  3423.    return file;
  3424.  }
  3425. Index: variable.c
  3426. ===================================================================
  3427. RCS file: /sources/make/make/variable.c,v
  3428. retrieving revision 1.112
  3429. diff -u -r1.112 variable.c
  3430. --- variable.c  5 Mar 2012 14:10:45 -0000   1.112
  3431. +++ variable.c  16 Mar 2012 03:20:31 -0000
  3432. @@ -254,6 +254,7 @@
  3433.    v->per_target = 0;
  3434.    v->append = 0;
  3435.    v->private_var = 0;
  3436. +  v->scoped = 0;
  3437.    v->export = v_default;
  3438.  
  3439.    v->exportable = 1;
  3440. @@ -275,6 +276,70 @@
  3441.  }
  3442.  
  3443.  
  3444. +struct variable *
  3445. +push_scoped_variable_in_set (struct variable *v,
  3446. +                char *name, unsigned int length,
  3447. +                struct variable_set *set)
  3448. +{
  3449. +  struct variable *old_var;
  3450. +  struct variable **var_slot;
  3451. +  struct variable var_key;
  3452. +
  3453. +  if (set == NULL)
  3454. +    set = &global_variable_set;
  3455. +
  3456. +  var_key.name   = name;
  3457. +  var_key.length = length;
  3458. +  var_slot = (struct variable **) hash_find_slot (&set->table, &var_key);
  3459. +
  3460. +  old_var = *var_slot;
  3461. +  if (HASH_VACANT (old_var))
  3462. +    old_var = NULL;
  3463. +
  3464. +  /* Create a new variable definition and add it to the hash table.  */
  3465. +
  3466. +  v->name = name;
  3467. +  v->length = length;
  3468. +  hash_insert_at (&set->table, v, var_slot);
  3469. +
  3470. +  v->fileinfo.filenm = NULL;
  3471. +  v->origin = o_automatic;
  3472. +  v->recursive = 0;
  3473. +  v->special = 0;
  3474. +  v->expanding = 0;
  3475. +  v->exp_count = 0;
  3476. +  v->per_target = 0;
  3477. +  v->append = 0;
  3478. +  v->private_var = 0;
  3479. +  v->exportable = 0;
  3480. +  v->export = v_default;
  3481. +
  3482. +  v->scoped = 1;
  3483. +
  3484. +  return old_var;
  3485. +}
  3486. +
  3487. +void
  3488. +pop_scoped_variable_in_set (struct variable *v,
  3489. +               struct variable *old_var,
  3490. +               struct variable_set *set)
  3491. +{
  3492. +  struct variable **var_slot;
  3493. +  struct variable var_key;
  3494. +
  3495. +  if (set == NULL)
  3496. +    set = &global_variable_set;
  3497. +
  3498. +  var_key.name   = v->name;
  3499. +  var_key.length = v->length;
  3500. +  var_slot = (struct variable **) hash_find_slot (&set->table, &var_key);
  3501. +
  3502. +  if (old_var)
  3503. +    hash_insert_at (&set->table, old_var, var_slot);
  3504. +  else
  3505. +    hash_delete_at (&set->table, var_slot);
  3506. +}
  3507. +
  3508.  /* Undefine variable named NAME in SET. LENGTH is the length of NAME, which
  3509.     does not need to be null-terminated. ORIGIN specifies the origin of the
  3510.     variable (makefile, command line or environment). */
  3511. @@ -381,6 +446,9 @@
  3512.              struct variable *v = *vp;
  3513.              int l = v->length;
  3514.  
  3515. +            if (v->scoped)
  3516. +              continue;
  3517. +
  3518.              len += l + 1;
  3519.              if (len > max)
  3520.                {
  3521. @@ -966,6 +1034,7 @@
  3522.    struct variable makelevel_key;
  3523.    char **result_0;
  3524.    char **result;
  3525. +  struct vbuffer vbuf;
  3526.  
  3527.    if (file == 0)
  3528.      set_list = current_variable_set_list;
  3529. @@ -1053,6 +1122,8 @@
  3530.  
  3531.    result = result_0 = xmalloc ((table.ht_fill + 2) * sizeof (char *));
  3532.  
  3533. +  vbuffer_init (&vbuf);
  3534. +
  3535.    v_slot = (struct variable **) table.ht_vec;
  3536.    v_end = v_slot + table.ht_size;
  3537.    for ( ; v_slot < v_end; v_slot++)
  3538. @@ -1060,32 +1131,30 @@
  3539.        {
  3540.     struct variable *v = *v_slot;
  3541.  
  3542. +   vbuffer_reset (&vbuf);
  3543. +
  3544. +   vbuffer_write (&vbuf, v->name, -1);
  3545. +   vbuffer_write (&vbuf, "=", 1);
  3546. +
  3547.     /* If V is recursively expanded and didn't come from the environment,
  3548.        expand its value.  If it came from the environment, it should
  3549.        go back into the environment unchanged.  */
  3550.     if (v->recursive
  3551.         && v->origin != o_env && v->origin != o_env_override)
  3552. -     {
  3553. -       char *value = recursively_expand_for_file (v, file);
  3554. -#ifdef WINDOWS32
  3555. -       if (strcmp(v->name, "Path") == 0 ||
  3556. -       strcmp(v->name, "PATH") == 0)
  3557. -         convert_Path_to_windows32(value, ';');
  3558. -#endif
  3559. -       *result++ = xstrdup (concat (3, v->name, "=", value));
  3560. -       free (value);
  3561. -     }
  3562. +     vbuffer_expand_variable_for_file (&vbuf, v, file);
  3563.     else
  3564. -     {
  3565. +     vbuffer_write (&vbuf, v->value, -1);
  3566. +
  3567.  #ifdef WINDOWS32
  3568. -            if (strcmp(v->name, "Path") == 0 ||
  3569. -                strcmp(v->name, "PATH") == 0)
  3570. -              convert_Path_to_windows32(v->value, ';');
  3571. +   if (strcmp(v->name, "Path") == 0 ||
  3572. +       strcmp(v->name, "PATH") == 0)
  3573. +     convert_Path_to_windows32(value, ';');
  3574.  #endif
  3575. -       *result++ = xstrdup (concat (3, v->name, "=", v->value));
  3576. -     }
  3577. +   *result++ = xstrdup (vbuf.buffer);
  3578.        }
  3579.  
  3580. +  vbuffer_free (&vbuf);
  3581. +
  3582.    *result = xmalloc (100);
  3583.    sprintf (*result, "%s=%u", MAKELEVEL_NAME, makelevel + 1);
  3584.    *++result = 0;
  3585. @@ -1116,20 +1185,14 @@
  3586.  char *
  3587.  shell_result (const char *p)
  3588.  {
  3589. -  char *buf;
  3590. -  unsigned int len;
  3591. +  struct vbuffer vbuf;
  3592.    char *args[2];
  3593. -  char *result;
  3594. -
  3595. -  install_variable_buffer (&buf, &len);
  3596.  
  3597.    args[0] = (char *) p;
  3598.    args[1] = NULL;
  3599. -  variable_buffer_output (func_shell_base (variable_buffer, args, 0), "\0", 1);
  3600. -  result = strdup (variable_buffer);
  3601. +  func_shell_base (vbuffer_init(&vbuf), args, 0);
  3602.  
  3603. -  restore_variable_buffer (buf, len);
  3604. -  return result;
  3605. +  return vbuf.buffer;
  3606.  }
  3607.  
  3608.  /* Given a variable, a value, and a flavor, define the variable.
  3609. Index: variable.h
  3610. ===================================================================
  3611. RCS file: /sources/make/make/variable.h,v
  3612. retrieving revision 1.51
  3613. diff -u -r1.51 variable.h
  3614. --- variable.h  5 Mar 2012 14:10:45 -0000   1.51
  3615. +++ variable.h  16 Mar 2012 03:20:31 -0000
  3616. @@ -64,6 +64,8 @@
  3617.      unsigned int expanding:1;  /* Nonzero if currently being expanded.  */
  3618.      unsigned int private_var:1; /* Nonzero avoids inheritance of this
  3619.                                     target-specific variable.  */
  3620. +    unsigned int scoped:1;      /* Nonzero if it is allocated on the stack
  3621. +                  of 'call' or 'foreach' functions.  */
  3622.      unsigned int exp_count:EXP_COUNT_BITS;
  3623.                                  /* If >1, allow this many self-referential
  3624.                                     expansions.  */
  3625. @@ -107,38 +109,68 @@
  3626.      struct variable variable;
  3627.    };
  3628.  
  3629. -extern char *variable_buffer;
  3630. +/* Structure used for pattern-specific variables.  */
  3631. +
  3632. +struct vbuffer
  3633. +  {
  3634. +    char *ptr;    /* Current position pointing inside the buffer.  */
  3635. +    char *buffer; /* Start of the entire buffer.  */
  3636. +    size_t size;  /* Size of the allocated buffer.  */
  3637. +  };
  3638. +
  3639.  extern struct variable_set_list *current_variable_set_list;
  3640.  extern struct variable *default_goal_var;
  3641.  
  3642. +struct vbuffer *vbuffer_init  (struct vbuffer *vbuf);
  3643. +struct vbuffer *vbuffer_reset (struct vbuffer *vbuf);
  3644. +
  3645. +#define vbuffer_free(vbuf) \
  3646. +  free ((vbuf)->buffer)
  3647. +
  3648. +size_t vbuffer_reserve (struct vbuffer *o, size_t len);
  3649. +
  3650. +size_t vbuffer_write (struct vbuffer *o, const char *str, ssize_t len);
  3651. +size_t vbuffer_unwrite (struct vbuffer *o, ssize_t len);
  3652. +
  3653. +size_t vbuffer_expand (struct vbuffer *o, char *str, ssize_t len);
  3654. +size_t vbuffer_expand_for_file (struct vbuffer *o, char *str, ssize_t len,
  3655. +               struct file *file);
  3656. +
  3657. +size_t vbuffer_expand_ro (struct vbuffer *o, const char *str, ssize_t len);
  3658. +size_t vbuffer_expand_ro_for_file (struct vbuffer *o, const char *str,
  3659. +                  ssize_t len, struct file *file);
  3660. +
  3661. +#define vbuffer_expand_variable(o, v) \
  3662. +  vbuffer_expand_variable_for_file (o, v, NULL)
  3663. +size_t vbuffer_expand_variable_for_file (struct vbuffer *o,
  3664. +                                         struct variable *v,
  3665. +                                         struct file *file);
  3666. +
  3667. +struct vbuffer *install_new_expansion_vbuffer (void);
  3668. +void restore_expansion_vbuffer (struct vbuffer *old_vbuf);
  3669. +
  3670.  /* expand.c */
  3671. -char *variable_buffer_output (char *ptr, const char *string, unsigned int length);
  3672. +char *expand_argument (const char *str, const char *end);
  3673.  char *variable_expand (const char *line);
  3674.  char *variable_expand_for_file (const char *line, struct file *file);
  3675. +char *allocated_variable_expand (const char *line);
  3676.  char *allocated_variable_expand_for_file (const char *line, struct file *file);
  3677. -#define    allocated_variable_expand(line) \
  3678. -  allocated_variable_expand_for_file (line, (struct file *) 0)
  3679. -char *expand_argument (const char *str, const char *end);
  3680. -char *variable_expand_string (char *line, const char *string, long length);
  3681. -void install_variable_buffer (char **bufp, unsigned int *lenp);
  3682. -void restore_variable_buffer (char *buf, unsigned int len);
  3683. +#define recursively_expand(v)   recursively_expand_for_file (v, NULL)
  3684. +char *recursively_expand_for_file (struct variable *v, struct file *file);
  3685.  
  3686.  /* function.c */
  3687. -int handle_function (char **op, const char **stringp);
  3688. +int handle_function (struct vbuffer *vbuf, char **stringp);
  3689.  int pattern_matches (const char *pattern, const char *percent, const char *str);
  3690. -char *subst_expand (char *o, const char *text, const char *subst,
  3691. -                    const char *replace, unsigned int slen, unsigned int rlen,
  3692. -                    int by_word);
  3693. -char *patsubst_expand_pat (char *o, const char *text, const char *pattern,
  3694. -                           const char *replace, const char *pattern_percent,
  3695. -                           const char *replace_percent);
  3696. -char *patsubst_expand (char *o, const char *text, char *pattern, char *replace);
  3697. -char *func_shell_base (char *o, char **argv, int trim_newlines);
  3698. -
  3699. -
  3700. -/* expand.c */
  3701. -char *recursively_expand_for_file (struct variable *v, struct file *file);
  3702. -#define recursively_expand(v)   recursively_expand_for_file (v, NULL)
  3703. +size_t subst_expand (struct vbuffer *vbuf, const char *text, const char *subst,
  3704. +                     const char *replace, unsigned int slen, unsigned int rlen,
  3705. +                     int by_word);
  3706. +size_t patsubst_expand_pat (struct vbuffer *vbuf, const char *text,
  3707. +                            const char *pattern, const char *replace,
  3708. +                            const char *pattern_percent,
  3709. +                            const char *replace_percent);
  3710. +size_t patsubst_expand (struct vbuffer *vbuf, const char *text, char *pattern,
  3711. +                        char *replace);
  3712. +size_t func_shell_base (struct vbuffer *vbuf, char **argv, int trim_newlines);
  3713.  
  3714.  /* variable.c */
  3715.  struct variable_set_list *create_new_variable_set (void);
  3716. @@ -167,7 +199,7 @@
  3717.  void hash_init_function_table (void);
  3718.  void define_new_function(const struct floc *flocp,
  3719.                           const char *name, int min, int max, int expand,
  3720. -                         char *(*func)(char *, char **, const char *));
  3721. +                         size_t (*func)(struct vbuffer *, char **, const char *));
  3722.  struct variable *lookup_variable (const char *name, unsigned int length);
  3723.  struct variable *lookup_variable_in_set (const char *name, unsigned int length,
  3724.                                           const struct variable_set *set);
  3725. @@ -207,6 +239,23 @@
  3726.  #define define_variable_for_file(n,l,v,o,r,f) \
  3727.            define_variable_in_set((n),(l),(v),(o),(r),(f)->variables->set,NILF)
  3728.  
  3729. +struct variable *push_scoped_variable_in_set (struct variable *v,
  3730. +                          char *name, unsigned int length,
  3731. +                          struct variable_set *set);
  3732. +void pop_scoped_variable_in_set (struct variable *v,
  3733. +                struct variable *old_var,
  3734. +                struct variable_set *set);
  3735. +
  3736. +/* Pushes a scoped variable in the current variable set.  */
  3737. +
  3738. +#define push_scoped_variable(v, name, length) \
  3739. +  push_scoped_variable_in_set(v, name, length, current_variable_set_list->set)
  3740. +
  3741. +/* Restores an old variable in the current variable set.  */
  3742. +
  3743. +#define pop_scoped_variable(v, old) \
  3744. +  pop_scoped_variable_in_set(v, old, current_variable_set_list->set)
  3745. +
  3746.  void undefine_variable_in_set (const char *name, unsigned int length,
  3747.                                 enum variable_origin origin,
  3748.                                 struct variable_set *set);
Advertisement
Add Comment
Please, Sign In to add comment