Advertisement
abusalimov

make-perf-r2.patch

Apr 9th, 2012
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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    9 Apr 2012 13:34:41 -0000
  10. @@ -16,8 +16,6 @@
  11.  
  12.  #include "make.h"
  13.  
  14. -#include <assert.h>
  15. -
  16.  #include "filedef.h"
  17.  #include "job.h"
  18.  #include "commands.h"
  19. @@ -30,125 +28,121 @@
  20.  
  21.  /* The next two describe the variable output buffer.
  22.     This buffer is used to hold the variable-expansion of a line of the
  23. -   makefile.  It is made bigger with realloc whenever it is too small.
  24. -   variable_buffer_length is the size currently allocated.
  25. -   variable_buffer is the address of the buffer.
  26. +   makefile.  It is made bigger with realloc whenever it is too small.  */
  27. +
  28. +static struct vbuffer *expansion_vbuf;
  29.  
  30. -   For efficiency, it's guaranteed that the buffer will always have
  31. +/* For efficiency, it's guaranteed that the buffer will always have
  32.     VARIABLE_BUFFER_ZONE extra bytes allocated.  This allows you to add a few
  33.     extra chars without having to call a function.  Note you should never use
  34.     these bytes unless you're _sure_ you have room (you know when the buffer
  35.     length was last checked.  */
  36. +#define VARIABLE_BUFFER_ZONE    (2 * sizeof (char *))
  37.  
  38. -#define VARIABLE_BUFFER_ZONE    5
  39. +struct vbuffer *
  40. +vbuffer_init (struct vbuffer *vbuf)
  41. +{
  42. +  vbuf->size = 100;
  43. +  vbuf->ptr = vbuf->buffer = xmalloc (vbuf->size);
  44.  
  45. -static unsigned int variable_buffer_length;
  46. -char *variable_buffer;
  47. +  *vbuf->ptr = '\0';
  48.  
  49. -/* Subroutine of variable_expand and friends:
  50. -   The text to add is LENGTH chars starting at STRING to the variable_buffer.
  51. -   The text is added to the buffer at PTR, and the updated pointer into
  52. -   the buffer is returned as the value.  Thus, the value returned by
  53. -   each call to variable_buffer_output should be the first argument to
  54. -   the following call.  */
  55. +  return vbuf;
  56. +}
  57.  
  58. -char *
  59. -variable_buffer_output (char *ptr, const char *string, unsigned int length)
  60. +struct vbuffer *
  61. +vbuffer_reset (struct vbuffer *vbuf)
  62.  {
  63. -  register unsigned int newlen = length + (ptr - variable_buffer);
  64. +  vbuf->ptr = vbuf->buffer;
  65.  
  66. -  if ((newlen + VARIABLE_BUFFER_ZONE) > variable_buffer_length)
  67. -    {
  68. -      unsigned int offset = ptr - variable_buffer;
  69. -      variable_buffer_length = (newlen + 100 > 2 * variable_buffer_length
  70. -               ? newlen + 100
  71. -               : 2 * variable_buffer_length);
  72. -      variable_buffer = xrealloc (variable_buffer, variable_buffer_length);
  73. -      ptr = variable_buffer + offset;
  74. -    }
  75. +  *vbuf->ptr = '\0';
  76.  
  77. -  memcpy (ptr, string, length);
  78. -  return ptr + length;
  79. +  return vbuf;
  80.  }
  81.  
  82. -/* Return a pointer to the beginning of the variable buffer.  */
  83. +#ifdef __GNUC__
  84. +__inline
  85. +#endif
  86. +static void
  87. +vbuffer_grow (struct vbuffer *vbuf, size_t newlen)
  88. +{
  89. +  size_t oldlen = vbuf->size;
  90. +  size_t offset = vbuf->ptr - vbuf->buffer;
  91. +
  92. +  newlen = newlen + 100 > 2 * oldlen
  93. +    ? newlen + 100 : 2 * oldlen;
  94. +
  95. +  vbuf->buffer = xrealloc (vbuf->buffer, newlen);
  96. +  vbuf->ptr = vbuf->buffer + offset;
  97. +  vbuf->size = newlen;
  98. +}
  99.  
  100. -static char *
  101. -initialize_variable_output (void)
  102. +#ifdef __GNUC__
  103. +__inline
  104. +#endif
  105. +size_t
  106. +vbuffer_reserve (struct vbuffer *o, size_t length)
  107.  {
  108. -  /* If we don't have a variable output buffer yet, get one.  */
  109. +  size_t newoff = (o->ptr - o->buffer) + length;
  110.  
  111. -  if (variable_buffer == 0)
  112. -    {
  113. -      variable_buffer_length = 200;
  114. -      variable_buffer = xmalloc (variable_buffer_length);
  115. -      variable_buffer[0] = '\0';
  116. -    }
  117. +  if ((newoff + VARIABLE_BUFFER_ZONE) > o->size)
  118. +    vbuffer_grow (o, newoff);
  119.  
  120. -  return variable_buffer;
  121. +  return o->size - newoff;
  122.  }
  123. -
  124. -/* Recursively expand V.  The returned string is malloc'd.  */
  125.  
  126. -static char *allocated_variable_append (const struct variable *v);
  127. +/* Writes byte stream pointed by STR into VBUF.
  128. +   The optional LEN argument can be used to limit the amount of bytes to copy.
  129. +   Otherwise (if LEN is a negative number) STR is treated as a null-terminated
  130. +   string and copied accordingly.
  131.  
  132. -char *
  133. -recursively_expand_for_file (struct variable *v, struct file *file)
  134. +   Returns the actual number of bytes copied,
  135. +   that is LEN argument if it is non-negative and strlen (STR) otherwise.
  136. +
  137. +   As like all the other vbuffer methods it leaves the internal buffer
  138. +   of the VBUF null-terminated.   */
  139. +
  140. +#ifdef __GNUC__
  141. +__inline
  142. +#endif
  143. +size_t
  144. +vbuffer_write (struct vbuffer *o, const char *str, ssize_t len)
  145.  {
  146. -  char *value;
  147. -  const struct floc *this_var;
  148. -  const struct floc **saved_varp;
  149. -  struct variable_set_list *save = 0;
  150. -  int set_reading = 0;
  151. +  size_t length = len < 0 ? strlen (str) : (size_t) len;
  152.  
  153. -  /* Don't install a new location if this location is empty.
  154. -     This can happen for command-line variables, builtin variables, etc.  */
  155. -  saved_varp = expanding_var;
  156. -  if (v->fileinfo.filenm)
  157. -    {
  158. -      this_var = &v->fileinfo;
  159. -      expanding_var = &this_var;
  160. -    }
  161. +  if (length == 0)
  162. +    return 0;
  163.  
  164. -  /* If we have no other file-reading context, use the variable's context. */
  165. -  if (!reading_file)
  166. -    {
  167. -      set_reading = 1;
  168. -      reading_file = &v->fileinfo;
  169. -    }
  170. +  vbuffer_reserve (o, length);
  171.  
  172. -  if (v->expanding)
  173. -    {
  174. -      if (!v->exp_count)
  175. -        /* Expanding V causes infinite recursion.  Lose.  */
  176. -        fatal (*expanding_var,
  177. -               _("Recursive variable '%s' references itself (eventually)"),
  178. -               v->name);
  179. -      --v->exp_count;
  180. -    }
  181. +  memcpy (o->ptr, str, length);
  182. +  o->ptr += length;
  183.  
  184. -  if (file)
  185. -    {
  186. -      save = current_variable_set_list;
  187. -      current_variable_set_list = file->variables;
  188. -    }
  189. +  *o->ptr = '\0';
  190.  
  191. -  v->expanding = 1;
  192. -  if (v->append)
  193. -    value = allocated_variable_append (v);
  194. -  else
  195. -    value = allocated_variable_expand (v->value);
  196. -  v->expanding = 0;
  197. +  return length;
  198. +}
  199.  
  200. -  if (set_reading)
  201. -    reading_file = 0;
  202. +/* Moves the pointer of the VBUF back on the LEN bytes.
  203. +   If LEN is negative, or if moving the pointer would lead to an underflow,
  204. +   then sets the pointer to the start of the buffer.
  205.  
  206. -  if (file)
  207. -    current_variable_set_list = save;
  208. +   Returns the actual number of discarded bytes.  */
  209.  
  210. -  expanding_var = saved_varp;
  211. +size_t
  212. +vbuffer_unwrite (struct vbuffer *o, ssize_t len)
  213. +{
  214. +  size_t oldoff = o->ptr - o->buffer;
  215. +  size_t length = len < 0 ? oldoff : (size_t) len;
  216.  
  217. -  return value;
  218. +  if (length > oldoff)
  219. +    length = oldoff;
  220. +
  221. +  o->ptr -= length;
  222. +
  223. +  *o->ptr = '\0';
  224. +
  225. +  return length;
  226.  }
  227.  
  228.  /* Expand a simple reference to variable NAME, which is LENGTH chars long.  */
  229. @@ -156,11 +150,10 @@
  230.  #ifdef __GNUC__
  231.  __inline
  232.  #endif
  233. -static char *
  234. -reference_variable (char *o, const char *name, unsigned int length)
  235. +static size_t
  236. +expand_variable_reference (struct vbuffer *o, const char *name, size_t length)
  237.  {
  238.    struct variable *v;
  239. -  char *value;
  240.  
  241.    v = lookup_variable (name, length);
  242.  
  243. @@ -169,62 +162,117 @@
  244.  
  245.    /* If there's no variable by that name or it has no value, stop now.  */
  246.    if (v == 0 || (*v->value == '\0' && !v->append))
  247. -    return o;
  248. -
  249. -  value = (v->recursive ? recursively_expand (v) : v->value);
  250. -
  251. -  o = variable_buffer_output (o, value, strlen (value));
  252. +    return 0;
  253.  
  254.    if (v->recursive)
  255. -    free (value);
  256. -
  257. -  return o;
  258. +    return vbuffer_expand_variable (o, v);
  259. +  else
  260. +    return vbuffer_write (o, v->value, -1);
  261.  }
  262. -
  263. -/* Scan STRING for variable references and expansion-function calls.  Only
  264. -   LENGTH bytes of STRING are actually scanned.  If LENGTH is -1, scan until
  265. -   a null byte is found.
  266. -
  267. -   Write the results to LINE, which must point into 'variable_buffer'.  If
  268. -   LINE is NULL, start at the beginning of the buffer.
  269. -   Return a pointer to LINE, or to the beginning of the buffer if LINE is
  270. -   NULL.
  271. - */
  272. -char *
  273. -variable_expand_string (char *line, const char *string, long length)
  274. +
  275. +
  276. +#ifdef __GNUC__
  277. +__inline
  278. +#endif
  279. +static int
  280. +handle_subst_reference (struct vbuffer *o, char *beg, char *end)
  281.  {
  282. +  size_t result = 0;
  283.    struct variable *v;
  284. -  const char *p, *p1;
  285. -  char *save;
  286. -  char *o;
  287. -  unsigned int line_offset;
  288. -
  289. -  if (!line)
  290. -    line = initialize_variable_output();
  291. -  o = line;
  292. -  line_offset = line - variable_buffer;
  293. +  const char *subst_beg, *subst_end, *replace_beg, *replace_end;
  294. +  char *colon = lindex (beg, end, ':');
  295.  
  296. -  if (length == 0)
  297. +  if (colon == 0)
  298. +    return -1;
  299. +
  300. +  subst_beg = colon + 1;
  301. +  subst_end = lindex (subst_beg, end, '=');
  302. +  if (subst_end == 0)
  303. +    /* There is no = in sight.  Punt on the substitution reference and treat
  304. +       this as a variable name containing a colon.  */
  305. +    return -1;
  306. +
  307. +  /* This looks like a valid substitution reference: $(FOO:A=B).  */
  308. +  replace_beg = subst_end + 1;
  309. +  replace_end = end;
  310. +
  311. +  /* Extract the variable name before the colon and look up that variable.  */
  312. +  v = lookup_variable (beg, colon - beg);
  313. +  if (v == 0)
  314. +    warn_undefined (beg, colon - beg);
  315. +
  316. +  /* If the variable is not empty, perform the substitution.  */
  317. +  if (v != 0 && *v->value != '\0')
  318.      {
  319. -      variable_buffer_output (o, "", 1);
  320. -      return (variable_buffer);
  321. +      char *pattern, *replace, *ppercent, *rpercent;
  322. +      char *value = (v->recursive
  323. +            ? recursively_expand(v)
  324. +            : v->value);
  325. +
  326. +      /* Copy the pattern and the replacement.  Add in an extra % at the
  327. +         beginning to use in case there isn't one in the pattern.  */
  328. +      pattern = alloca (subst_end - subst_beg + 2);
  329. +      *(pattern++) = '%';
  330. +      memcpy (pattern, subst_beg, subst_end - subst_beg);
  331. +      pattern[subst_end - subst_beg] = '\0';
  332. +
  333. +      replace = alloca (replace_end - replace_beg + 2);
  334. +      *(replace++) = '%';
  335. +      memcpy (replace, replace_beg, replace_end - replace_beg);
  336. +      replace[replace_end - replace_beg] = '\0';
  337. +
  338. +      /* Look for %.  Set the percent pointers properly
  339. +    based on whether we find one or not.  */
  340. +      ppercent = find_percent (pattern);
  341. +      if (ppercent)
  342. +   {
  343. +     ++ppercent;
  344. +     rpercent = find_percent (replace);
  345. +     if (rpercent)
  346. +       ++rpercent;
  347. +   }
  348. +      else
  349. +   {
  350. +     ppercent = pattern--;
  351. +     rpercent = replace--;
  352. +   }
  353. +
  354. +      *o->ptr = '\0';
  355. +
  356. +      result = patsubst_expand_pat (o, value,
  357. +                   pattern, replace, ppercent, rpercent);
  358. +
  359. +      if (v->recursive)
  360. +   free (value);
  361.      }
  362.  
  363. -  /* We need a copy of STRING: due to eval, it's possible that it will get
  364. -     freed as we process it (it might be the value of a variable that's reset
  365. -     for example).  Also having a nil-terminated string is handy.  */
  366. -  save = length < 0 ? xstrdup (string) : xstrndup (string, length);
  367. -  p = save;
  368. +  return result;
  369. +}
  370.  
  371. +size_t
  372. +vbuffer_expand (struct vbuffer *o, char *str, ssize_t len)
  373. +{
  374. +  size_t result = 0;
  375. +  char *p, *p1;
  376. +
  377. +  if (len == 0)
  378. +    return 0;
  379. +
  380. +  if (len > 0)
  381. +    str[len] = '\0';
  382. +
  383. +  p = str;
  384.    while (1)
  385.      {
  386.        /* Copy all following uninteresting chars all at once to the
  387. -         variable output buffer, and skip them.  Uninteresting chars end
  388. +    variable output buffer, and skip them.  Uninteresting chars end
  389.      at the next $ or the end of the input.  */
  390.  
  391.        p1 = strchr (p, '$');
  392.  
  393. -      o = variable_buffer_output (o, p, p1 != 0 ? (unsigned int)(p1 - p) : strlen (p) + 1);
  394. +      /* In case when P1 is nil,
  395. +         'vbuffer_write' writes the whole string pointed by P.  */
  396. +      result += vbuffer_write (o, p, p1 ? p1 - p : -1);
  397.  
  398.        if (p1 == 0)
  399.     break;
  400. @@ -236,27 +284,23 @@
  401.     {
  402.     case '$':
  403.       /* $$ seen means output one $ to the variable output buffer.  */
  404. -     o = variable_buffer_output (o, p, 1);
  405. +     result += vbuffer_write (o, p, 1);
  406.       break;
  407.  
  408.     case '(':
  409.     case '{':
  410.       /* $(...) or ${...} is the general case of substitution.  */
  411.       {
  412. +       int handle_ret;
  413.         char openparen = *p;
  414.         char closeparen = (openparen == '(') ? ')' : '}';
  415. -            const char *begp;
  416. -       const char *beg = p + 1;
  417. -       char *op;
  418. -            char *abeg = NULL;
  419. -       const char *end, *colon;
  420. -
  421. -       op = o;
  422. -       begp = p;
  423. -       if (handle_function (&op, &begp))
  424. +       char *beg = p + 1;
  425. +       char *end;
  426. +
  427. +       handle_ret = handle_function (o, &p);
  428. +       if (handle_ret >= 0)
  429.           {
  430. -       o = op;
  431. -       p = begp;
  432. +       result += handle_ret;
  433.         break;
  434.           }
  435.  
  436. @@ -265,8 +309,8 @@
  437.  
  438.         end = strchr (beg, closeparen);
  439.         if (end == 0)
  440. -              /* Unterminated variable reference.  */
  441. -              fatal (*expanding_var, _("unterminated variable reference"));
  442. +         fatal (*expanding_var, _("unterminated variable reference"));
  443. +
  444.         p1 = lindex (beg, end, '$');
  445.         if (p1 != 0)
  446.           {
  447. @@ -285,102 +329,41 @@
  448.            such as '$($(a)'.  */
  449.         if (count < 0)
  450.           {
  451. -           abeg = expand_argument (beg, p); /* Expand the name.  */
  452. -           beg = abeg;
  453. -           end = strchr (beg, '\0');
  454. +           /* Expand the name.
  455. +              As a little optimization we reuse the same vbuffer.  */
  456. +           size_t name_len = vbuffer_expand (o, beg, p - beg);
  457. +           *p = closeparen;
  458. +
  459. +           /* We don't use 'vbuffer_unwrite' here because it would
  460. +              reset the first byte of the computed name to nil.  */
  461. +           o->ptr -= name_len;
  462. +
  463. +           beg = o->ptr;
  464. +           end = beg + name_len;
  465. +
  466.           }
  467.           }
  468.         else
  469.           /* Advance P to the end of this reference.  After we are
  470. -                 finished expanding this one, P will be incremented to
  471. -                 continue the scan.  */
  472. +        finished expanding this one, P will be incremented to
  473. +        continue the scan.  */
  474.           p = end;
  475.  
  476.         /* This is not a reference to a built-in function and
  477.            any variable references inside are now expanded.
  478.            Is the resultant text a substitution reference?  */
  479.  
  480. -       colon = lindex (beg, end, ':');
  481. -       if (colon)
  482. +       handle_ret = handle_subst_reference (o, beg, end);
  483. +       if (handle_ret >= 0)
  484.           {
  485. -       /* This looks like a substitution reference: $(FOO:A=B).  */
  486. -       const char *subst_beg, *subst_end, *replace_beg, *replace_end;
  487. -
  488. -       subst_beg = colon + 1;
  489. -       subst_end = lindex (subst_beg, end, '=');
  490. -       if (subst_end == 0)
  491. -         /* There is no = in sight.  Punt on the substitution
  492. -            reference and treat this as a variable name containing
  493. -            a colon, in the code below.  */
  494. -         colon = 0;
  495. -       else
  496. -         {
  497. -           replace_beg = subst_end + 1;
  498. -           replace_end = end;
  499. -
  500. -           /* Extract the variable name before the colon
  501. -              and look up that variable.  */
  502. -           v = lookup_variable (beg, colon - beg);
  503. -           if (v == 0)
  504. -             warn_undefined (beg, colon - beg);
  505. -
  506. -                    /* If the variable is not empty, perform the
  507. -                       substitution.  */
  508. -           if (v != 0 && *v->value != '\0')
  509. -             {
  510. -           char *pattern, *replace, *ppercent, *rpercent;
  511. -           char *value = (v->recursive
  512. -                                       ? recursively_expand (v)
  513. -                      : v->value);
  514. -
  515. -                        /* Copy the pattern and the replacement.  Add in an
  516. -                           extra % at the beginning to use in case there
  517. -                           isn't one in the pattern.  */
  518. -                        pattern = alloca (subst_end - subst_beg + 2);
  519. -                        *(pattern++) = '%';
  520. -                        memcpy (pattern, subst_beg, subst_end - subst_beg);
  521. -                        pattern[subst_end - subst_beg] = '\0';
  522. -
  523. -                        replace = alloca (replace_end - replace_beg + 2);
  524. -                        *(replace++) = '%';
  525. -                        memcpy (replace, replace_beg,
  526. -                               replace_end - replace_beg);
  527. -                        replace[replace_end - replace_beg] = '\0';
  528. -
  529. -                        /* Look for %.  Set the percent pointers properly
  530. -                           based on whether we find one or not.  */
  531. -           ppercent = find_percent (pattern);
  532. -           if (ppercent)
  533. -                          {
  534. -                            ++ppercent;
  535. -                            rpercent = find_percent (replace);
  536. -                            if (rpercent)
  537. -                              ++rpercent;
  538. -                          }
  539. -           else
  540. -                          {
  541. -                            ppercent = pattern;
  542. -                            rpercent = replace;
  543. -                            --pattern;
  544. -                            --replace;
  545. -                          }
  546. -
  547. -                        o = patsubst_expand_pat (o, value, pattern, replace,
  548. -                                                 ppercent, rpercent);
  549. -
  550. -           if (v->recursive)
  551. -             free (value);
  552. -             }
  553. -         }
  554. +       result += handle_ret;
  555. +       break;
  556.           }
  557.  
  558. -       if (colon == 0)
  559. -         /* This is an ordinary variable reference.
  560. -        Look up the value of the variable.  */
  561. -       o = reference_variable (o, beg, end - beg);
  562. -
  563. -     if (abeg)
  564. -       free (abeg);
  565. +       /* This is an ordinary variable reference.
  566. +          Look up the value of the variable.  */
  567. +       result += expand_variable_reference (o, beg, end - beg);
  568. +       *o->ptr = '\0';
  569.       }
  570.       break;
  571.  
  572. @@ -393,7 +376,7 @@
  573.  
  574.       /* A $ followed by a random char is a variable reference:
  575.          $a is equivalent to $(a).  */
  576. -          o = reference_variable (o, p, 1);
  577. +     result += expand_variable_reference (o, p, 1);
  578.  
  579.       break;
  580.     }
  581. @@ -404,69 +387,19 @@
  582.        ++p;
  583.      }
  584.  
  585. -  free (save);
  586. -
  587. -  variable_buffer_output (o, "", 1);
  588. -  return (variable_buffer + line_offset);
  589. -}
  590. -
  591. -/* Scan LINE for variable references and expansion-function calls.
  592. -   Build in 'variable_buffer' the result of expanding the references and calls.
  593. -   Return the address of the resulting string, which is null-terminated
  594. -   and is valid only until the next time this function is called.  */
  595. -
  596. -char *
  597. -variable_expand (const char *line)
  598. -{
  599. -  return variable_expand_string(NULL, line, (long)-1);
  600. -}
  601. -
  602. -/* Expand an argument for an expansion function.
  603. -   The text starting at STR and ending at END is variable-expanded
  604. -   into a null-terminated string that is returned as the value.
  605. -   This is done without clobbering 'variable_buffer' or the current
  606. -   variable-expansion that is in progress.  */
  607. -
  608. -char *
  609. -expand_argument (const char *str, const char *end)
  610. -{
  611. -  char *tmp, *alloc = NULL;
  612. -  char *r;
  613. -
  614. -  if (str == end)
  615. -    return xstrdup("");
  616. -
  617. -  if (!end || *end == '\0')
  618. -    return allocated_variable_expand (str);
  619. -
  620. -  if (end - str + 1 > 1000)
  621. -    tmp = alloc = xmalloc (end - str + 1);
  622. -  else
  623. -    tmp = alloca (end - str + 1);
  624. -
  625. -  memcpy (tmp, str, end - str);
  626. -  tmp[end - str] = '\0';
  627. -
  628. -  r = allocated_variable_expand (tmp);
  629. -
  630. -  if (alloc)
  631. -    free (alloc);
  632. +  return result;
  633.  
  634. -  return r;
  635.  }
  636. -
  637. -/* Expand LINE for FILE.  Error messages refer to the file and line where
  638. -   FILE's commands were found.  Expansion uses FILE's variable set list.  */
  639.  
  640. -char *
  641. -variable_expand_for_file (const char *line, struct file *file)
  642. -{
  643. -  char *result;
  644. +size_t
  645. +vbuffer_expand_for_file (struct vbuffer *o, char *str, ssize_t len,
  646. +                         struct file *file) {
  647. +  size_t result = 0;
  648.    struct variable_set_list *savev;
  649.    const struct floc *savef;
  650.  
  651.    if (file == 0)
  652. -    return variable_expand (line);
  653. +    return vbuffer_expand (o, str, len);
  654.  
  655.    savev = current_variable_set_list;
  656.    current_variable_set_list = file->variables;
  657. @@ -477,124 +410,251 @@
  658.    else
  659.      reading_file = 0;
  660.  
  661. -  result = variable_expand (line);
  662. +  result = vbuffer_expand (o, str, len);
  663.  
  664.    current_variable_set_list = savev;
  665.    reading_file = savef;
  666.  
  667.    return result;
  668.  }
  669. -
  670. +
  671.  /* Like allocated_variable_expand, but for += target-specific variables.
  672.     First recursively construct the variable value from its appended parts in
  673.     any upper variable sets.  Then expand the resulting value.  */
  674.  
  675. -static char *
  676. -variable_append (const char *name, unsigned int length,
  677. -                 const struct variable_set_list *set, int local)
  678. +static size_t
  679. +expand_variable_append (struct vbuffer *o,
  680. +           const char *name, unsigned int length,
  681. +           const struct variable_set_list *set_list,
  682. +           int local)
  683.  {
  684. +  size_t ret = 0;
  685.    const struct variable *v;
  686. -  char *buf = 0;
  687. -  /* If this set is local and the next is not a parent, then next is local.  */
  688. -  int nextlocal = local && set->next_is_parent == 0;
  689. +  int nextlocal;
  690.  
  691.    /* If there's nothing left to check, return the empty buffer.  */
  692. -  if (!set)
  693. -    return initialize_variable_output ();
  694. +  if (!set_list)
  695. +    return 0;
  696. +
  697. +  /* If this set is local and the next is not a parent, then next is local.  */
  698. +  nextlocal = local && set_list->next_is_parent == 0;
  699.  
  700.    /* Try to find the variable in this variable set.  */
  701. -  v = lookup_variable_in_set (name, length, set->set);
  702. +  v = lookup_variable_in_set (name, length, set_list->set);
  703.  
  704.    /* If there isn't one, or this one is private, try the set above us.  */
  705.    if (!v || (!local && v->private_var))
  706. -    return variable_append (name, length, set->next, nextlocal);
  707. +    return expand_variable_append (o, name, length,
  708. +                  set_list->next, nextlocal);
  709.  
  710.    /* If this variable type is append, first get any upper values.
  711.       If not, initialize the buffer.  */
  712.    if (v->append)
  713. -    buf = variable_append (name, length, set->next, nextlocal);
  714. -  else
  715. -    buf = initialize_variable_output ();
  716. +    ret += expand_variable_append (o, name, length,
  717. +                  set_list->next, nextlocal);
  718.  
  719.    /* Append this value to the buffer, and return it.
  720.       If we already have a value, first add a space.  */
  721. -  if (buf > variable_buffer)
  722. -    buf = variable_buffer_output (buf, " ", 1);
  723. +  if (ret != 0)
  724. +    ret += vbuffer_write (o, " ", 1);
  725.  
  726.    /* Either expand it or copy it, depending.  */
  727. -  if (! v->recursive)
  728. -    return variable_buffer_output (buf, v->value, strlen (v->value));
  729. +  if (v->recursive)
  730. +    ret += vbuffer_expand_ro (o, v->value, -1);
  731. +  else
  732. +    ret += vbuffer_write (o, v->value, -1);
  733.  
  734. -  buf = variable_expand_string (buf, v->value, strlen (v->value));
  735. -  return (buf + strlen (buf));
  736. +  return ret;
  737.  }
  738.  
  739. +size_t
  740. +vbuffer_expand_variable_for_file (struct vbuffer *o, struct variable *v,
  741. +                 struct file *file)
  742. +{
  743. +  size_t ret = 0;
  744. +  const struct floc *this_var;
  745. +  const struct floc **saved_varp;
  746. +  struct variable_set_list *save = 0;
  747. +  int set_reading = 0;
  748. +
  749. +  /* Don't install a new location if this location is empty.
  750. +     This can happen for command-line variables, builtin variables, etc.  */
  751. +  saved_varp = expanding_var;
  752. +  if (v->fileinfo.filenm)
  753. +    {
  754. +      this_var = &v->fileinfo;
  755. +      expanding_var = &this_var;
  756. +    }
  757. +
  758. +  /* If we have no other file-reading context, use the variable's context. */
  759. +  if (!reading_file)
  760. +    {
  761. +      set_reading = 1;
  762. +      reading_file = &v->fileinfo;
  763. +    }
  764. +
  765. +  if (v->expanding)
  766. +    {
  767. +      if (!v->exp_count)
  768. +        /* Expanding V causes infinite recursion.  Lose.  */
  769. +        fatal (*expanding_var,
  770. +               _("Recursive variable '%s' references itself (eventually)"),
  771. +               v->name);
  772. +      --v->exp_count;
  773. +    }
  774. +
  775. +  if (file)
  776. +    {
  777. +      save = current_variable_set_list;
  778. +      current_variable_set_list = file->variables;
  779. +    }
  780. +
  781. +  v->expanding = 1;
  782. +
  783. +  if (v->append)
  784. +    ret += expand_variable_append (o, v->name, strlen (v->name),
  785. +                  current_variable_set_list, 1);
  786. +  else
  787. +    /* We need a copy of STRING: due to eval, it's possible that it will get
  788. +       freed as we process it (it might be the value of a variable that's
  789. +       reset, for example).  Also having a nil-terminated string is handy.  */
  790. +    ret += vbuffer_expand_ro (o, v->value, -1);
  791.  
  792. -static char *
  793. -allocated_variable_append (const struct variable *v)
  794. +  v->expanding = 0;
  795. +
  796. +  if (set_reading)
  797. +    reading_file = 0;
  798. +
  799. +  if (file)
  800. +    current_variable_set_list = save;
  801. +
  802. +  expanding_var = saved_varp;
  803. +
  804. +  return ret;
  805. +}
  806. +
  807. +size_t
  808. +vbuffer_expand_ro (struct vbuffer *o, const char *str, ssize_t len)
  809. +{
  810. +  size_t ret;
  811. +  size_t length = len < 0 ? strlen (str) : (size_t) len;
  812. +
  813. +  char *alloc = 0;
  814. +  char *value = length > MAX_ALLOCA_SIZE
  815. +       ? (alloc = xmalloc (length + 1))
  816. +       : alloca (length + 1);
  817. +
  818. +  ret = vbuffer_expand (o, memcpy (value, str, length + 1), length);
  819. +
  820. +  if (alloc)
  821. +    free (alloc);
  822. +
  823. +  return ret;
  824. +}
  825. +
  826. +size_t
  827. +vbuffer_expand_ro_for_file (struct vbuffer *o, const char *str, ssize_t len,
  828. +               struct file *file)
  829.  {
  830. -  char *val;
  831. +  size_t ret;
  832. +  char *string = len < 0 ? xstrdup (str) : xstrndup (str, len);
  833. +  ret = vbuffer_expand_for_file (o, string, -1, file);
  834. +  free (string);
  835. +  return ret;
  836. +}
  837.  
  838. -  /* Construct the appended variable value.  */
  839. +/* Install a new expansion vbuffer, returning the current one.  */
  840. +
  841. +struct vbuffer *
  842. +install_new_expansion_vbuffer (void)
  843. +{
  844. +  struct vbuffer *old_vbuf = expansion_vbuf;
  845.  
  846. -  char *obuf = variable_buffer;
  847. -  unsigned int olen = variable_buffer_length;
  848. +  expansion_vbuf = xmalloc(sizeof(struct vbuffer));
  849. +  vbuffer_init(expansion_vbuf);
  850.  
  851. -  variable_buffer = 0;
  852. +  return old_vbuf;
  853. +}
  854.  
  855. -  val = variable_append (v->name, strlen (v->name),
  856. -                         current_variable_set_list, 1);
  857. -  variable_buffer_output (val, "", 1);
  858. -  val = variable_buffer;
  859. +/* Restore a previously-saved vbuffer setting freeing the current one.  */
  860.  
  861. -  variable_buffer = obuf;
  862. -  variable_buffer_length = olen;
  863. +void
  864. +restore_expansion_vbuffer (struct vbuffer *old_vbuf)
  865. +{
  866. +  vbuffer_free(expansion_vbuf);
  867. +  free(expansion_vbuf);
  868.  
  869. -  return val;
  870. +  expansion_vbuf = old_vbuf;
  871.  }
  872.  
  873. -/* Like variable_expand_for_file, but the returned string is malloc'd.
  874. -   This function is called a lot.  It wants to be efficient.  */
  875. +/* Expand an argument for an expansion function.
  876. +   The text starting at STR and ending at END is variable-expanded
  877. +   into a null-terminated string that is returned as the value.
  878. +   This is done without clobbering 'variable_buffer' or the current
  879. +   variable-expansion that is in progress.  */
  880.  
  881.  char *
  882. -allocated_variable_expand_for_file (const char *line, struct file *file)
  883. +expand_argument (const char *str, const char *end)
  884.  {
  885. -  char *value;
  886. +  struct vbuffer vbuf;
  887.  
  888. -  char *obuf = variable_buffer;
  889. -  unsigned int olen = variable_buffer_length;
  890. +  vbuffer_expand_ro (vbuffer_init(&vbuf), str, end - str);
  891.  
  892. -  variable_buffer = 0;
  893. +  return vbuf.buffer;
  894. +}
  895.  
  896. -  value = variable_expand_for_file (line, file);
  897. +/* Scan LINE for variable references and expansion-function calls.
  898. +   Build in 'variable_buffer' the result of expanding the references and calls.
  899. +   Return the address of the resulting string, which is null-terminated
  900. +   and is valid only until the next time this function is called.  */
  901.  
  902. -  variable_buffer = obuf;
  903. -  variable_buffer_length = olen;
  904. +char *
  905. +variable_expand (const char *line)
  906. +{
  907. +  vbuffer_expand_ro (vbuffer_reset(expansion_vbuf), line, -1);
  908.  
  909. -  return value;
  910. +  return expansion_vbuf->buffer;
  911.  }
  912.  
  913. -/* Install a new variable_buffer context, returning the current one for
  914. -   safe-keeping.  */
  915. +/* Expand LINE for FILE.  Error messages refer to the file and line where
  916. +   FILE's commands were found.  Expansion uses FILE's variable set list.  */
  917.  
  918. -void
  919. -install_variable_buffer (char **bufp, unsigned int *lenp)
  920. +char *
  921. +variable_expand_for_file (const char *line, struct file *file)
  922. +{
  923. +  vbuffer_expand_ro_for_file (vbuffer_reset(expansion_vbuf), line, -1, file);
  924. +
  925. +  return expansion_vbuf->buffer;
  926. +}
  927. +
  928. +char *
  929. +allocated_variable_expand (const char *line)
  930.  {
  931. -  *bufp = variable_buffer;
  932. -  *lenp = variable_buffer_length;
  933. +  struct vbuffer vbuf;
  934.  
  935. -  variable_buffer = 0;
  936. -  initialize_variable_output ();
  937. +  vbuffer_expand_ro (vbuffer_init(&vbuf), line, -1);
  938. +
  939. +  return vbuf.buffer;
  940.  }
  941.  
  942. -/* Restore a previously-saved variable_buffer setting (free the current one).
  943. - */
  944. +/* Like variable_expand_for_file, but the returned string is malloc'd.  */
  945.  
  946. -void
  947. -restore_variable_buffer (char *buf, unsigned int len)
  948. +char *
  949. +allocated_variable_expand_for_file (const char *line, struct file *file)
  950.  {
  951. -  free (variable_buffer);
  952. +  struct vbuffer vbuf;
  953. +
  954. +  vbuffer_expand_ro_for_file (vbuffer_init(&vbuf), line, -1, file);
  955. +
  956. +  return vbuf.buffer;
  957. +}
  958. +
  959. +char *
  960. +recursively_expand_for_file (struct variable *v, struct file *file)
  961. +{
  962. +  struct vbuffer vbuf;
  963. +
  964. +  vbuffer_expand_variable_for_file (vbuffer_init(&vbuf), v, file);
  965.  
  966. -  variable_buffer = buf;
  967. -  variable_buffer_length = len;
  968. +  return vbuf.buffer;
  969.  }
  970. Index: file.c
  971. ===================================================================
  972. RCS file: /sources/make/make/file.c,v
  973. retrieving revision 1.105
  974. diff -u -r1.105 file.c
  975. --- file.c  5 Mar 2012 14:10:43 -0000   1.105
  976. +++ file.c  9 Apr 2012 13:34:41 -0000
  977. @@ -467,9 +467,11 @@
  978.    if (stem)
  979.      {
  980.        const char *pattern = "%";
  981. -      char *buffer = variable_expand ("");
  982. +      struct vbuffer vbuf;
  983.        struct dep *dp = deps, *dl = 0;
  984.  
  985. +      vbuffer_init (&vbuf);
  986. +
  987.        while (dp != 0)
  988.          {
  989.            char *percent;
  990. @@ -479,22 +481,23 @@
  991.            percent = find_percent (nm);
  992.            if (percent)
  993.              {
  994. -              char *o;
  995. +              size_t len;
  996.  
  997.                /* We have to handle empty stems specially, because that
  998.                   would be equivalent to $(patsubst %,dp->name,) which
  999.                   will always be empty.  */
  1000. -              if (stem[0] == '\0')
  1001. +              if (*stem == '\0')
  1002.                  {
  1003.                    memmove (percent, percent+1, strlen (percent));
  1004. -                  o = variable_buffer_output (buffer, nm, strlen (nm) + 1);
  1005. +                  len = vbuffer_write (vbuffer_reset (&vbuf), nm, -1);
  1006.                  }
  1007.                else
  1008. -                o = patsubst_expand_pat (buffer, stem, pattern, nm,
  1009. -                                         pattern+1, percent+1);
  1010. +                len = patsubst_expand_pat (vbuffer_reset (&vbuf), stem,
  1011. +                                           pattern, nm,
  1012. +                                           pattern+1, percent+1);
  1013.  
  1014.                /* If the name expanded to the empty string, ignore it.  */
  1015. -              if (buffer[0] == '\0')
  1016. +              if (len == 0)
  1017.                  {
  1018.                    struct dep *df = dp;
  1019.                    if (dp == deps)
  1020. @@ -506,24 +509,26 @@
  1021.                  }
  1022.  
  1023.                /* Save the name.  */
  1024. -              dp->name = strcache_add_len (buffer, o - buffer);
  1025. +              dp->name = strcache_add_len (vbuf.buffer, len);
  1026.              }
  1027.            dp->stem = stem;
  1028.            dp->staticpattern = 1;
  1029.            dl = dp;
  1030.            dp = dp->next;
  1031.          }
  1032. +
  1033. +        vbuffer_free (&vbuf);
  1034.      }
  1035.  
  1036.    /* Enter them as files, unless they need a 2nd expansion.  */
  1037.    for (d1 = deps; d1 != 0; d1 = d1->next)
  1038.      {
  1039.        if (d1->need_2nd_expansion)
  1040. -        continue;
  1041. +   continue;
  1042.  
  1043.        d1->file = lookup_file (d1->name);
  1044.        if (d1->file == 0)
  1045. -        d1->file = enter_file (d1->name);
  1046. +   d1->file = enter_file (d1->name);
  1047.        d1->staticpattern = 0;
  1048.        d1->name = 0;
  1049.      }
  1050. @@ -573,12 +578,10 @@
  1051.           "$*" so they'll expand properly.  */
  1052.        if (d->staticpattern)
  1053.          {
  1054. -          char *o;
  1055. -          d->name = o = variable_expand ("");
  1056. -          o = subst_expand (o, name, "%", "$*", 1, 2, 0);
  1057. -          *o = '\0';
  1058. +     struct vbuffer vbuf;
  1059. +          subst_expand (vbuffer_init(&vbuf), name, "%", "$*", 1, 2, 0);
  1060.            free (name);
  1061. -          d->name = name = xstrdup (d->name);
  1062. +          d->name = name = xstrdup (vbuf.buffer);
  1063.            d->staticpattern = 0;
  1064.          }
  1065.  
  1066. Index: function.c
  1067. ===================================================================
  1068. RCS file: /sources/make/make/function.c,v
  1069. retrieving revision 1.133
  1070. diff -u -r1.133 function.c
  1071. --- function.c  5 Mar 2012 14:10:43 -0000   1.133
  1072. +++ function.c  9 Apr 2012 13:34:41 -0000
  1073. @@ -15,6 +15,9 @@
  1074.  this program.  If not, see <http://www.gnu.org/licenses/>.  */
  1075.  
  1076.  #include "make.h"
  1077. +
  1078. +#include <assert.h>
  1079. +
  1080.  #include "filedef.h"
  1081.  #include "variable.h"
  1082.  #include "dep.h"
  1083. @@ -34,7 +37,7 @@
  1084.      unsigned char minimum_args;
  1085.      unsigned char maximum_args;
  1086.      char expand_args;
  1087. -    char *(*func_ptr) (char *output, char **argv, const char *fname);
  1088. +   size_t (*func_ptr) (struct vbuffer *output, char **argv, const char *fname);
  1089.    };
  1090.  
  1091.  static unsigned long
  1092. @@ -65,26 +68,29 @@
  1093.  static struct hash_table function_table;
  1094.  
  1095.  
  1096. -/* Store into VARIABLE_BUFFER at O the result of scanning TEXT and replacing
  1097. +/* Store into VBUFFER at O the result of scanning TEXT and replacing
  1098.     each occurrence of SUBST with REPLACE. TEXT is null-terminated.  SLEN is
  1099.     the length of SUBST and RLEN is the length of REPLACE.  If BY_WORD is
  1100.     nonzero, substitutions are done only on matches which are complete
  1101.     whitespace-delimited words.  */
  1102.  
  1103. -char *
  1104. -subst_expand (char *o, const char *text, const char *subst, const char *replace,
  1105. -              unsigned int slen, unsigned int rlen, int by_word)
  1106. +size_t
  1107. +subst_expand (struct vbuffer *o, const char *text, const char *subst,
  1108. +              const char *replace, unsigned int slen, unsigned int rlen,
  1109. +              int by_word)
  1110.  {
  1111. +  size_t result = 0;
  1112. +
  1113.    const char *t = text;
  1114.    const char *p;
  1115.  
  1116.    if (slen == 0 && !by_word)
  1117.      {
  1118.        /* The first occurrence of "" in any string is its end.  */
  1119. -      o = variable_buffer_output (o, t, strlen (t));
  1120. +      result += vbuffer_write (o, t, -1);
  1121.        if (rlen > 0)
  1122. -   o = variable_buffer_output (o, replace, rlen);
  1123. -      return o;
  1124. +   result += vbuffer_write (o, replace, rlen);
  1125. +      return result;
  1126.      }
  1127.  
  1128.    do
  1129. @@ -99,14 +105,14 @@
  1130.       if (p == 0)
  1131.         {
  1132.           /* No more matches.  Output everything left on the end.  */
  1133. -         o = variable_buffer_output (o, t, strlen (t));
  1134. -         return o;
  1135. +         result += vbuffer_write (o, t, -1);
  1136. +         return result;
  1137.         }
  1138.     }
  1139.  
  1140.        /* Output everything before this occurrence of the string to replace.  */
  1141.        if (p > t)
  1142. -   o = variable_buffer_output (o, t, p - t);
  1143. +   result += vbuffer_write (o, t, p - t);
  1144.  
  1145.        /* If we're substituting only by fully matched words,
  1146.      or only at the ends of words, check that this case qualifies.  */
  1147. @@ -115,20 +121,21 @@
  1148.                || (p[slen] != '\0' && !isblank ((unsigned char)p[slen]))))
  1149.     /* Struck out.  Output the rest of the string that is
  1150.        no longer to be replaced.  */
  1151. -   o = variable_buffer_output (o, subst, slen);
  1152. +   result += vbuffer_write (o, subst, slen);
  1153.        else if (rlen > 0)
  1154.     /* Output the replacement string.  */
  1155. -   o = variable_buffer_output (o, replace, rlen);
  1156. +   result += vbuffer_write (o, replace, rlen);
  1157.  
  1158.        /* Advance T past the string to be replaced.  */
  1159.        t = p + slen;
  1160. -    } while (*t != '\0');
  1161. +    }
  1162. +  while (*t != '\0');
  1163.  
  1164. -  return o;
  1165. +  return result;
  1166.  }
  1167.  
  1168.  
  1169. -/* Store into VARIABLE_BUFFER at O the result of scanning TEXT
  1170. +/* Store into VBUFFER at O the result of scanning TEXT
  1171.     and replacing strings matching PATTERN with REPLACE.
  1172.     If PATTERN_PERCENT is not nil, PATTERN has already been
  1173.     run through find_percent, and PATTERN_PERCENT is the result.
  1174. @@ -138,16 +145,17 @@
  1175.     character _AFTER_ the %, not to the % itself.
  1176.  */
  1177.  
  1178. -char *
  1179. -patsubst_expand_pat (char *o, const char *text,
  1180. +size_t
  1181. +patsubst_expand_pat (struct vbuffer *o, const char *text,
  1182.                       const char *pattern, const char *replace,
  1183.                       const char *pattern_percent, const char *replace_percent)
  1184.  {
  1185. +  size_t ret = 0;
  1186. +
  1187.    unsigned int pattern_prepercent_len, pattern_postpercent_len;
  1188.    unsigned int replace_prepercent_len, replace_postpercent_len;
  1189.    const char *t;
  1190.    unsigned int len;
  1191. -  int doneany = 0;
  1192.  
  1193.    /* Record the length of REPLACE before and after the % so we don't have to
  1194.       compute these lengths more than once.  */
  1195. @@ -197,43 +205,37 @@
  1196.  
  1197.        if (fail)
  1198.     /* It didn't match.  Output the string.  */
  1199. -   o = variable_buffer_output (o, t, len);
  1200. +   ret += vbuffer_write (o, t, len);
  1201.        else
  1202.     {
  1203.       /* It matched.  Output the replacement.  */
  1204.  
  1205.       /* Output the part of the replacement before the %.  */
  1206. -     o = variable_buffer_output (o, replace, replace_prepercent_len);
  1207. +     ret += vbuffer_write (o, replace, replace_prepercent_len);
  1208.  
  1209.       if (replace_percent != 0)
  1210.         {
  1211.           /* Output the part of the matched string that
  1212.          matched the % in the pattern.  */
  1213. -         o = variable_buffer_output (o, t + pattern_prepercent_len,
  1214. -                     len - (pattern_prepercent_len
  1215. +         ret += vbuffer_write (o, t + pattern_prepercent_len,
  1216. +                      len - (pattern_prepercent_len
  1217.                          + pattern_postpercent_len));
  1218.           /* Output the part of the replacement after the %.  */
  1219. -         o = variable_buffer_output (o, replace_percent,
  1220. -                     replace_postpercent_len);
  1221. +         ret += vbuffer_write (o, replace_percent,
  1222. +                      replace_postpercent_len);
  1223.         }
  1224.     }
  1225.  
  1226.        /* Output a space, but not if the replacement is "".  */
  1227.        if (fail || replace_prepercent_len > 0
  1228.       || (replace_percent != 0 && len + replace_postpercent_len > 0))
  1229. -   {
  1230. -     o = variable_buffer_output (o, " ", 1);
  1231. -     doneany = 1;
  1232. -   }
  1233. +   ret += vbuffer_write (o, " ", 1);
  1234.      }
  1235. -  if (doneany)
  1236. -    /* Kill the last space.  */
  1237. -    --o;
  1238.  
  1239. -  return o;
  1240. +  return ret - vbuffer_unwrite (o, !!ret);
  1241.  }
  1242.  
  1243. -/* Store into VARIABLE_BUFFER at O the result of scanning TEXT
  1244. +/* Store into VBUFFER at O the result of scanning TEXT
  1245.     and replacing strings matching PATTERN with REPLACE.
  1246.     If PATTERN_PERCENT is not nil, PATTERN has already been
  1247.     run through find_percent, and PATTERN_PERCENT is the result.
  1248. @@ -243,8 +245,9 @@
  1249.     character _AFTER_ the %, not to the % itself.
  1250.  */
  1251.  
  1252. -char *
  1253. -patsubst_expand (char *o, const char *text, char *pattern, char *replace)
  1254. +size_t
  1255. +patsubst_expand (struct vbuffer *o, const char *text, char *pattern,
  1256. +                 char *replace)
  1257.  {
  1258.    const char *pattern_percent = find_percent (pattern);
  1259.    const char *replace_percent = find_percent (replace);
  1260. @@ -256,28 +259,7 @@
  1261.      ++pattern_percent;
  1262.  
  1263.    return patsubst_expand_pat (o, text, pattern, replace,
  1264. -                              pattern_percent, replace_percent);
  1265. -}
  1266. -
  1267. -
  1268. -/* Look up a function by name.  */
  1269. -
  1270. -static const struct function_table_entry *
  1271. -lookup_function (const char *s)
  1272. -{
  1273. -  const char *e = s;
  1274. -
  1275. -  while (*e && ( (*e >= 'a' && *e <= 'z') || *e == '-'))
  1276. -    e++;
  1277. -  if (*e == '\0' || isblank ((unsigned char) *e))
  1278. -    {
  1279. -      struct function_table_entry function_table_entry_key;
  1280. -      function_table_entry_key.name = s;
  1281. -      function_table_entry_key.len = e - s;
  1282. -
  1283. -      return hash_find_item (&function_table, &function_table_entry_key);
  1284. -    }
  1285. -  return 0;
  1286. +                 pattern_percent, replace_percent);
  1287.  }
  1288.  
  1289.  
  1290. @@ -310,48 +292,16 @@
  1291.  }
  1292.  
  1293.  
  1294. -/* Find the next comma or ENDPAREN (counting nested STARTPAREN and
  1295. -   ENDPARENtheses), starting at PTR before END.  Return a pointer to
  1296. -   next character.
  1297. -
  1298. -   If no next argument is found, return NULL.
  1299. -*/
  1300. -
  1301. -static char *
  1302. -find_next_argument (char startparen, char endparen,
  1303. -                    const char *ptr, const char *end)
  1304. -{
  1305. -  int count = 0;
  1306. -
  1307. -  for (; ptr < end; ++ptr)
  1308. -    if (*ptr == startparen)
  1309. -      ++count;
  1310. -
  1311. -    else if (*ptr == endparen)
  1312. -      {
  1313. -   --count;
  1314. -   if (count < 0)
  1315. -     return NULL;
  1316. -      }
  1317. -
  1318. -    else if (*ptr == ',' && !count)
  1319. -      return (char *)ptr;
  1320. -
  1321. -  /* We didn't find anything.  */
  1322. -  return NULL;
  1323. -}
  1324. -
  1325. -
  1326. -/* Glob-expand LINE.  The returned pointer is
  1327. -   only good until the next call to string_glob.  */
  1328. +/* Glob-expand the LINE writing the result into O.  */
  1329.  
  1330. -static char *
  1331. -string_glob (char *line)
  1332. +#ifdef __GNUC__
  1333. +__inline
  1334. +#endif
  1335. +static size_t
  1336. +string_glob (struct vbuffer *o, char *line)
  1337.  {
  1338. -  static char *result = 0;
  1339. -  static unsigned int length;
  1340. +  size_t ret = 0;
  1341.    struct nameseq *chain;
  1342. -  unsigned int idx;
  1343.  
  1344.    chain = PARSE_FILE_SEQ (&line, struct nameseq, '\0', NULL,
  1345.                            /* We do not want parse_file_seq to strip './'s.
  1346. @@ -359,58 +309,53 @@
  1347.                               $(patsubst ./%.c,obj/%.o,$(wildcard ./?*.c)).  */
  1348.                            PARSEFS_NOSTRIP|PARSEFS_NOCACHE|PARSEFS_EXISTS);
  1349.  
  1350. -  if (result == 0)
  1351. -    {
  1352. -      length = 100;
  1353. -      result = xmalloc (100);
  1354. -    }
  1355. -
  1356. -  idx = 0;
  1357.    while (chain != 0)
  1358.      {
  1359.        struct nameseq *next = chain->next;
  1360. -      unsigned int len = strlen (chain->name);
  1361.  
  1362. -      if (idx + len + 1 > length)
  1363. -        {
  1364. -          length += (len + 1) * 2;
  1365. -          result = xrealloc (result, length);
  1366. -        }
  1367. -      memcpy (&result[idx], chain->name, len);
  1368. -      idx += len;
  1369. -      result[idx++] = ' ';
  1370. +      ret += vbuffer_write (o, chain->name, -1);
  1371. +      ret += vbuffer_write (o, " ", 1);
  1372.  
  1373.        /* Because we used PARSEFS_NOCACHE above, we have to free() NAME.  */
  1374.        free ((char *)chain->name);
  1375.        free (chain);
  1376. +
  1377.        chain = next;
  1378.      }
  1379.  
  1380. -  /* Kill the last space and terminate the string.  */
  1381. -  if (idx == 0)
  1382. -    result[0] = '\0';
  1383. -  else
  1384. -    result[idx - 1] = '\0';
  1385. +  return ret - vbuffer_unwrite (o, !!ret);
  1386. +}
  1387.  
  1388. -  return result;
  1389. +static size_t
  1390. +func_wildcard (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  1391. +{
  1392. +  size_t ret = 0;
  1393. +
  1394. +#ifdef _AMIGA
  1395. +   o = wildcard_expansion (argv[0], o);
  1396. +#else
  1397. +   ret += string_glob (o, argv[0]);
  1398. +#endif
  1399. +
  1400. +   return ret;
  1401.  }
  1402. +
  1403.  
  1404.  /*
  1405.    Builtin functions
  1406.   */
  1407.  
  1408. -static char *
  1409. -func_patsubst (char *o, char **argv, const char *funcname UNUSED)
  1410. +static size_t
  1411. +func_patsubst (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  1412.  {
  1413. -  o = patsubst_expand (o, argv[2], argv[0], argv[1]);
  1414. -  return o;
  1415. +  return patsubst_expand (o, argv[2], argv[0], argv[1]);
  1416.  }
  1417.  
  1418.  
  1419. -static char *
  1420. -func_join (char *o, char **argv, const char *funcname UNUSED)
  1421. +static size_t
  1422. +func_join (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  1423.  {
  1424. -  int doneany = 0;
  1425. +  size_t ret = 0;
  1426.  
  1427.    /* Write each word of the first argument directly followed
  1428.       by the corresponding word of the second argument.
  1429. @@ -420,87 +365,84 @@
  1430.    const char *pp;
  1431.    const char *list1_iterator = argv[0];
  1432.    const char *list2_iterator = argv[1];
  1433. +
  1434.    do
  1435.      {
  1436.        unsigned int len1, len2;
  1437.  
  1438.        tp = find_next_token (&list1_iterator, &len1);
  1439.        if (tp != 0)
  1440. -   o = variable_buffer_output (o, tp, len1);
  1441. +   ret += vbuffer_write (o, tp, len1);
  1442.  
  1443.        pp = find_next_token (&list2_iterator, &len2);
  1444.        if (pp != 0)
  1445. -   o = variable_buffer_output (o, pp, len2);
  1446. +   ret += vbuffer_write (o, pp, len2);
  1447.  
  1448.        if (tp != 0 || pp != 0)
  1449. -   {
  1450. -     o = variable_buffer_output (o, " ", 1);
  1451. -     doneany = 1;
  1452. -   }
  1453. +   ret += vbuffer_write (o, " ", 1);
  1454.      }
  1455.    while (tp != 0 || pp != 0);
  1456. -  if (doneany)
  1457. -    /* Kill the last blank.  */
  1458. -    --o;
  1459.  
  1460. -  return o;
  1461. +  return ret - vbuffer_unwrite (o, !!ret);
  1462.  }
  1463.  
  1464.  
  1465. -static char *
  1466. -func_origin (char *o, char **argv, const char *funcname UNUSED)
  1467. +static size_t
  1468. +func_origin (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  1469.  {
  1470. -  /* Expand the argument.  */
  1471. +  size_t ret = 0;
  1472.    struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
  1473. +
  1474.    if (v == 0)
  1475. -    o = variable_buffer_output (o, "undefined", 9);
  1476. +    ret += vbuffer_write (o, STRING_SIZE_TUPLE("undefined"));
  1477.    else
  1478.      switch (v->origin)
  1479.        {
  1480. -      default:
  1481. -      case o_invalid:
  1482. -   abort ();
  1483. -   break;
  1484.        case o_default:
  1485. -   o = variable_buffer_output (o, "default", 7);
  1486. +   ret += vbuffer_write (o, STRING_SIZE_TUPLE("default"));
  1487.     break;
  1488.        case o_env:
  1489. -   o = variable_buffer_output (o, "environment", 11);
  1490. +   ret += vbuffer_write (o, STRING_SIZE_TUPLE("environment"));
  1491.     break;
  1492.        case o_file:
  1493. -   o = variable_buffer_output (o, "file", 4);
  1494. +   ret += vbuffer_write (o, STRING_SIZE_TUPLE("file"));
  1495.     break;
  1496.        case o_env_override:
  1497. -   o = variable_buffer_output (o, "environment override", 20);
  1498. +   ret += vbuffer_write (o, STRING_SIZE_TUPLE("environment override"));
  1499.     break;
  1500.        case o_command:
  1501. -   o = variable_buffer_output (o, "command line", 12);
  1502. +   ret += vbuffer_write (o, STRING_SIZE_TUPLE("command line"));
  1503.     break;
  1504.        case o_override:
  1505. -   o = variable_buffer_output (o, "override", 8);
  1506. +   ret += vbuffer_write (o, STRING_SIZE_TUPLE("override"));
  1507.     break;
  1508.        case o_automatic:
  1509. -   o = variable_buffer_output (o, "automatic", 9);
  1510. +   ret += vbuffer_write (o, STRING_SIZE_TUPLE("automatic"));
  1511. +   break;
  1512. +      case o_invalid:
  1513. +      default:
  1514. +   abort ();
  1515.     break;
  1516.        }
  1517.  
  1518. -  return o;
  1519. +  return ret;
  1520.  }
  1521.  
  1522. -static char *
  1523. -func_flavor (char *o, char **argv, const char *funcname UNUSED)
  1524. +static size_t
  1525. +func_flavor (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  1526.  {
  1527. +  size_t ret = 0;
  1528.    struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
  1529.  
  1530.    if (v == 0)
  1531. -    o = variable_buffer_output (o, "undefined", 9);
  1532. +    ret += vbuffer_write (o, STRING_SIZE_TUPLE("undefined"));
  1533.    else
  1534.      if (v->recursive)
  1535. -      o = variable_buffer_output (o, "recursive", 9);
  1536. +      ret += vbuffer_write (o, STRING_SIZE_TUPLE("recursive"));
  1537.      else
  1538. -      o = variable_buffer_output (o, "simple", 6);
  1539. +      ret += vbuffer_write (o, STRING_SIZE_TUPLE("simple"));
  1540.  
  1541. -  return o;
  1542. +  return ret;
  1543.  }
  1544.  
  1545.  #ifdef VMS
  1546. @@ -514,14 +456,15 @@
  1547.  #endif
  1548.  
  1549.  
  1550. -static char *
  1551. -func_notdir_suffix (char *o, char **argv, const char *funcname)
  1552. +static size_t
  1553. +func_notdir_suffix (struct vbuffer *o, char **argv, const char *funcname)
  1554.  {
  1555. +  size_t ret = 0;
  1556. +
  1557.    /* Expand the argument.  */
  1558.    const char *list_iterator = argv[0];
  1559.    const char *p2;
  1560. -  int doneany =0;
  1561. -  unsigned int len=0;
  1562. +  unsigned int len = 0;
  1563.  
  1564.    int is_suffix = funcname[0] == 's';
  1565.    int is_notdir = !is_suffix;
  1566. @@ -529,7 +472,6 @@
  1567.      {
  1568.        const char *p = p2 + len;
  1569.  
  1570. -
  1571.        while (p >= p2 && (!is_suffix || *p != '.'))
  1572.     {
  1573.       if (IS_PATHSEP (*p))
  1574. @@ -543,41 +485,35 @@
  1575.         ++p;
  1576.       else if (*p != '.')
  1577.         continue;
  1578. -     o = variable_buffer_output (o, p, len - (p - p2));
  1579. +     ret += vbuffer_write (o, p, len - (p - p2));
  1580.     }
  1581.  #ifdef HAVE_DOS_PATHS
  1582.        /* Handle the case of "d:foo/bar".  */
  1583.        else if (is_notdir && p2[0] && p2[1] == ':')
  1584.     {
  1585.       p = p2 + 2;
  1586. -     o = variable_buffer_output (o, p, len - (p - p2));
  1587. +     ret += vbuffer_write (o, p, len - (p - p2));
  1588.     }
  1589.  #endif
  1590.        else if (is_notdir)
  1591. -   o = variable_buffer_output (o, p2, len);
  1592. +   ret += vbuffer_write (o, p2, len);
  1593.  
  1594.        if (is_notdir || p >= p2)
  1595. -   {
  1596. -     o = variable_buffer_output (o, " ", 1);
  1597. -     doneany = 1;
  1598. -   }
  1599. +   ret += vbuffer_write (o, " ", 1);
  1600.      }
  1601.  
  1602. -  if (doneany)
  1603. -    /* Kill last space.  */
  1604. -    --o;
  1605. -
  1606. -  return o;
  1607. +  return ret - vbuffer_unwrite (o, !!ret);
  1608.  }
  1609.  
  1610.  
  1611. -static char *
  1612. -func_basename_dir (char *o, char **argv, const char *funcname)
  1613. +static size_t
  1614. +func_basename_dir (struct vbuffer *o, char **argv, const char *funcname)
  1615.  {
  1616. +  size_t ret = 0;
  1617. +
  1618.    /* Expand the argument.  */
  1619.    const char *p3 = argv[0];
  1620.    const char *p2;
  1621. -  int doneany = 0;
  1622.    unsigned int len = 0;
  1623.  
  1624.    int is_basename = funcname[0] == 'b';
  1625. @@ -594,111 +530,105 @@
  1626.          }
  1627.  
  1628.        if (p >= p2 && (is_dir))
  1629. -        o = variable_buffer_output (o, p2, ++p - p2);
  1630. +        ret += vbuffer_write (o, p2, ++p - p2);
  1631.        else if (p >= p2 && (*p == '.'))
  1632. -        o = variable_buffer_output (o, p2, p - p2);
  1633. +        ret += vbuffer_write (o, p2, p - p2);
  1634.  #ifdef HAVE_DOS_PATHS
  1635.        /* Handle the "d:foobar" case */
  1636.        else if (p2[0] && p2[1] == ':' && is_dir)
  1637. -        o = variable_buffer_output (o, p2, 2);
  1638. +   ret += vbuffer_write (o, p2, 2);
  1639.  #endif
  1640.        else if (is_dir)
  1641.  #ifdef VMS
  1642. -        o = variable_buffer_output (o, "[]", 2);
  1643. +   ret += vbuffer_write (o, "[]", 2);
  1644.  #else
  1645.  #ifndef _AMIGA
  1646. -      o = variable_buffer_output (o, "./", 2);
  1647. +      ret += vbuffer_write (o, "./", 2);
  1648.  #else
  1649.        ; /* Just a nop...  */
  1650.  #endif /* AMIGA */
  1651.  #endif /* !VMS */
  1652.        else
  1653.          /* The entire name is the basename.  */
  1654. -        o = variable_buffer_output (o, p2, len);
  1655. +        ret += vbuffer_write (o, p2, len);
  1656.  
  1657. -      o = variable_buffer_output (o, " ", 1);
  1658. -      doneany = 1;
  1659. +      ret += vbuffer_write (o, " ", 1);
  1660.      }
  1661.  
  1662. -  if (doneany)
  1663. -    /* Kill last space.  */
  1664. -    --o;
  1665. -
  1666. -  return o;
  1667. +  return ret - vbuffer_unwrite (o, !!ret);
  1668.  }
  1669.  
  1670. -static char *
  1671. -func_addsuffix_addprefix (char *o, char **argv, const char *funcname)
  1672. +static size_t
  1673. +func_addsuffix_addprefix (struct vbuffer *o, char **argv, const char *funcname)
  1674.  {
  1675. +  size_t ret = 0;
  1676. +
  1677.    int fixlen = strlen (argv[0]);
  1678.    const char *list_iterator = argv[1];
  1679. -  int is_addprefix = funcname[3] == 'p';
  1680. +  int is_addprefix = funcname[CSTRLEN("add")] == 'p';
  1681.    int is_addsuffix = !is_addprefix;
  1682.  
  1683. -  int doneany = 0;
  1684.    const char *p;
  1685.    unsigned int len;
  1686.  
  1687.    while ((p = find_next_token (&list_iterator, &len)) != 0)
  1688.      {
  1689.        if (is_addprefix)
  1690. -   o = variable_buffer_output (o, argv[0], fixlen);
  1691. -      o = variable_buffer_output (o, p, len);
  1692. +   ret += vbuffer_write (o, argv[0], fixlen);
  1693. +      ret += vbuffer_write (o, p, len);
  1694.        if (is_addsuffix)
  1695. -   o = variable_buffer_output (o, argv[0], fixlen);
  1696. -      o = variable_buffer_output (o, " ", 1);
  1697. -      doneany = 1;
  1698. +   ret += vbuffer_write (o, argv[0], fixlen);
  1699. +      ret += vbuffer_write (o, " ", 1);
  1700.      }
  1701.  
  1702. -  if (doneany)
  1703. -    /* Kill last space.  */
  1704. -    --o;
  1705. -
  1706. -  return o;
  1707. +  return ret - vbuffer_unwrite (o, !!ret);
  1708.  }
  1709.  
  1710. -static char *
  1711. -func_subst (char *o, char **argv, const char *funcname UNUSED)
  1712. -{
  1713. -  o = subst_expand (o, argv[2], argv[0], argv[1], strlen (argv[0]),
  1714. -           strlen (argv[1]), 0);
  1715.  
  1716. -  return o;
  1717. +static size_t
  1718. +func_subst (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  1719. +{
  1720. +  return subst_expand (o, argv[2], argv[0], argv[1], strlen (argv[0]),
  1721. +              strlen (argv[1]), 0);
  1722.  }
  1723.  
  1724.  
  1725. -static char *
  1726. -func_firstword (char *o, char **argv, const char *funcname UNUSED)
  1727. +static size_t
  1728. +func_firstword (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  1729.  {
  1730. -  unsigned int i;
  1731. +  size_t ret = 0;
  1732. +
  1733. +  unsigned int len;
  1734.    const char *words = argv[0];    /* Use a temp variable for find_next_token */
  1735. -  const char *p = find_next_token (&words, &i);
  1736. +  const char *p = find_next_token (&words, &len);
  1737.  
  1738.    if (p != 0)
  1739. -    o = variable_buffer_output (o, p, i);
  1740. +    ret += vbuffer_write (o, p, len);
  1741.  
  1742. -  return o;
  1743. +  return ret;
  1744.  }
  1745.  
  1746. -static char *
  1747. -func_lastword (char *o, char **argv, const char *funcname UNUSED)
  1748. +static size_t
  1749. +func_lastword (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  1750.  {
  1751. -  unsigned int i;
  1752. +  size_t ret = 0;
  1753. +
  1754. +  unsigned int len;
  1755.    const char *words = argv[0];    /* Use a temp variable for find_next_token */
  1756.    const char *p = NULL;
  1757.    const char *t;
  1758.  
  1759. -  while ((t = find_next_token (&words, &i)))
  1760. +  while ((t = find_next_token (&words, &len)))
  1761.      p = t;
  1762.  
  1763.    if (p != 0)
  1764. -    o = variable_buffer_output (o, p, i);
  1765. +    ret += vbuffer_write (o, p, len);
  1766.  
  1767. -  return o;
  1768. +  return ret;
  1769.  }
  1770.  
  1771. -static char *
  1772. -func_words (char *o, char **argv, const char *funcname UNUSED)
  1773. +static size_t
  1774. +func_words (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  1775.  {
  1776.    int i = 0;
  1777.    const char *word_iterator = argv[0];
  1778. @@ -708,9 +638,8 @@
  1779.      ++i;
  1780.  
  1781.    sprintf (buf, "%d", i);
  1782. -  o = variable_buffer_output (o, buf, strlen (buf));
  1783.  
  1784. -  return o;
  1785. +  return vbuffer_write (o, buf, -1);
  1786.  }
  1787.  
  1788.  /* Set begpp to point to the first non-whitespace character of the string,
  1789. @@ -744,10 +673,11 @@
  1790.  }
  1791.  
  1792.  
  1793. -
  1794. -static char *
  1795. -func_word (char *o, char **argv, const char *funcname UNUSED)
  1796. +static size_t
  1797. +func_word (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  1798.  {
  1799. +  size_t ret = 0;
  1800. +
  1801.    const char *end_p;
  1802.    const char *p;
  1803.    int i;
  1804. @@ -766,14 +696,17 @@
  1805.        break;
  1806.  
  1807.    if (i == 0)
  1808. -    o = variable_buffer_output (o, p, end_p - p);
  1809. +    ret += vbuffer_write (o, p, end_p - p);
  1810.  
  1811. -  return o;
  1812. +  return ret;
  1813.  }
  1814.  
  1815. -static char *
  1816. -func_wordlist (char *o, char **argv, const char *funcname UNUSED)
  1817. +
  1818. +static size_t
  1819. +func_wordlist (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  1820.  {
  1821. +  size_t ret = 0;
  1822. +
  1823.    int start, count;
  1824.  
  1825.    /* Check the arguments.  */
  1826. @@ -805,67 +738,102 @@
  1827.              ;
  1828.  
  1829.            /* Return the stuff in the middle.  */
  1830. -          o = variable_buffer_output (o, p, end_p - p);
  1831. +          ret += vbuffer_write (o, p, end_p - p);
  1832.          }
  1833.      }
  1834.  
  1835. -  return o;
  1836. +  return ret;
  1837.  }
  1838.  
  1839. -static char *
  1840. -func_findstring (char *o, char **argv, const char *funcname UNUSED)
  1841. +static size_t
  1842. +func_findstring (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  1843.  {
  1844. +  size_t ret = 0;
  1845. +
  1846.    /* Find the first occurrence of the first string in the second.  */
  1847.    if (strstr (argv[1], argv[0]) != 0)
  1848. -    o = variable_buffer_output (o, argv[0], strlen (argv[0]));
  1849. +    ret += vbuffer_write (o, argv[0], -1);
  1850.  
  1851. -  return o;
  1852. +  return ret;
  1853.  }
  1854.  
  1855. -static char *
  1856. -func_foreach (char *o, char **argv, const char *funcname UNUSED)
  1857. +static size_t
  1858. +func_foreach (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  1859.  {
  1860. -  /* expand only the first two.  */
  1861. -  char *varname = expand_argument (argv[0], NULL);
  1862. -  char *list = expand_argument (argv[1], NULL);
  1863. -  const char *body = argv[2];
  1864. +  size_t ret = 0;
  1865.  
  1866. -  int doneany = 0;
  1867. -  const char *list_iterator = list;
  1868. -  const char *p;
  1869. +  char *p;
  1870.    unsigned int len;
  1871. -  struct variable *var;
  1872. +  char *varname;
  1873. +  char *list;
  1874. +  char *body;
  1875. +  size_t varname_len;
  1876. +  size_t list_len;
  1877. +  size_t body_len = strlen (argv[2]);
  1878. +  struct vbuffer argbuf;
  1879.  
  1880. -  push_new_variable_scope ();
  1881. -  var = define_variable (varname, strlen (varname), "", o_automatic, 0);
  1882. +  /* Expand the list and the variable name into a dedicated vbuffer.  */
  1883.  
  1884. -  /* loop through LIST,  put the value in VAR and expand BODY */
  1885. -  while ((p = find_next_token (&list_iterator, &len)) != 0)
  1886. +  vbuffer_init (&argbuf);
  1887. +
  1888. +  list_len = vbuffer_expand (&argbuf, argv[1], -1);
  1889. +  *(++argbuf.ptr) = '\0';
  1890. +  /* Add an extra nil to iterate over the list more efficiently.  */
  1891. +  *(++argbuf.ptr) = '\0';
  1892. +
  1893. +  varname_len = vbuffer_expand (&argbuf, argv[0], -1);
  1894. +  *(++argbuf.ptr) = '\0';
  1895. +
  1896. +  /* Also get a room for an unexpanded body.  */
  1897. +
  1898. +  vbuffer_reserve (&argbuf, body_len + 1);
  1899. +
  1900. +  list = argbuf.buffer;
  1901. +  varname = list + list_len + 2;
  1902. +  body = varname + varname_len + 1;
  1903. +  body[body_len] = ' ';
  1904. +
  1905. +  if ((p = find_next_token ((const char **) &list, &len)) != 0)
  1906.      {
  1907. -      char *result = 0;
  1908. +      struct variable var;
  1909. +      struct variable *saved_var;
  1910. +      char **argp;
  1911. +      char *saved_arg = NULL;
  1912.  
  1913. -      free (var->value);
  1914. -      var->value = xstrndup (p, len);
  1915. +      argp = lookup_call_argument_value (varname, varname_len);
  1916. +      if (argp && *argp)
  1917. +   {
  1918. +     /* Variable name is a numeric value and there is a call argument
  1919. +        that would hide a pushed variable.
  1920. +        Make a "hole" in the current call frame so that the new variable
  1921. +        becomes visible.  */
  1922. +     saved_arg = *argp;
  1923. +     *argp = NULL;
  1924. +   }
  1925. +      saved_var = push_scoped_variable (&var, varname, varname_len);
  1926.  
  1927. -      result = allocated_variable_expand (body);
  1928. +      /* loop through LIST,  put the value in VAR and expand BODY */
  1929. +      do
  1930. +   {
  1931. +     p[len] = '\0';
  1932. +     var.value = p;
  1933. +     ret += vbuffer_expand (o, memcpy (body, argv[2], body_len),
  1934. +                body_len + 1);
  1935. +     ++list;
  1936. +   }
  1937. +      while ((p = find_next_token ((const char **) &list, &len)) != 0);
  1938.  
  1939. -      o = variable_buffer_output (o, result, strlen (result));
  1940. -      o = variable_buffer_output (o, " ", 1);
  1941. -      doneany = 1;
  1942. -      free (result);
  1943. +      pop_scoped_variable (&var, saved_var);
  1944. +      if (saved_arg)
  1945. +   *argp = saved_arg;
  1946.      }
  1947.  
  1948. -  if (doneany)
  1949. -    /* Kill the last space.  */
  1950. -    --o;
  1951. -
  1952. -  pop_variable_scope ();
  1953. -  free (varname);
  1954. -  free (list);
  1955. +  vbuffer_free (&argbuf);
  1956.  
  1957. -  return o;
  1958. +  return ret - vbuffer_unwrite (o, !!ret);
  1959.  }
  1960.  
  1961. +
  1962.  struct a_word
  1963.  {
  1964.    struct a_word *next;
  1965. @@ -905,9 +873,11 @@
  1966.    int length;
  1967.  };
  1968.  
  1969. -static char *
  1970. -func_filter_filterout (char *o, char **argv, const char *funcname)
  1971. +static size_t
  1972. +func_filter_filterout (struct vbuffer *o, char **argv, const char *funcname)
  1973.  {
  1974. +  size_t ret = 0;
  1975. +
  1976.    struct a_word *wordhead;
  1977.    struct a_word **wordtail;
  1978.    struct a_word *wp;
  1979. @@ -989,8 +959,6 @@
  1980.  
  1981.    if (words)
  1982.      {
  1983. -      int doneany = 0;
  1984. -
  1985.        /* Run each pattern through the words, killing words.  */
  1986.        for (pp = pathead; pp != 0; pp = pp->next)
  1987.     {
  1988. @@ -1019,58 +987,42 @@
  1989.        for (wp = wordhead; wp != 0; wp = wp->next)
  1990.     if (is_filter ? wp->matched : !wp->matched)
  1991.       {
  1992. -       o = variable_buffer_output (o, wp->str, strlen (wp->str));
  1993. -       o = variable_buffer_output (o, " ", 1);
  1994. -       doneany = 1;
  1995. +       ret += vbuffer_write (o, wp->str, -1);
  1996. +       ret += vbuffer_write (o, " ", 1);
  1997.       }
  1998.  
  1999. -      if (doneany)
  2000. -   /* Kill the last space.  */
  2001. -   --o;
  2002.      }
  2003.  
  2004.    if (hashing)
  2005.      hash_free (&a_word_table, 0);
  2006.  
  2007. -  return o;
  2008. +  return ret - vbuffer_unwrite (o, !!ret);
  2009.  }
  2010.  
  2011.  
  2012. -static char *
  2013. -func_strip (char *o, char **argv, const char *funcname UNUSED)
  2014. +static size_t
  2015. +func_strip (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  2016.  {
  2017. -  const char *p = argv[0];
  2018. -  int doneany = 0;
  2019. +  size_t result = 0;
  2020.  
  2021. -  while (*p != '\0')
  2022. -    {
  2023. -      int i=0;
  2024. -      const char *word_start;
  2025. +  unsigned int len;
  2026. +  const char *words = argv[0];    /* Use a temp variable for find_next_token */
  2027. +  const char *p;
  2028.  
  2029. -      while (isspace ((unsigned char)*p))
  2030. -   ++p;
  2031. -      word_start = p;
  2032. -      for (i=0; *p != '\0' && !isspace ((unsigned char)*p); ++p, ++i)
  2033. -   {}
  2034. -      if (!i)
  2035. -   break;
  2036. -      o = variable_buffer_output (o, word_start, i);
  2037. -      o = variable_buffer_output (o, " ", 1);
  2038. -      doneany = 1;
  2039. +  while ((p = find_next_token (&words, &len)) != 0)
  2040. +    {
  2041. +      result += vbuffer_write (o, p, len + 1);
  2042. +      o->ptr[-1] = ' ';
  2043.      }
  2044.  
  2045. -  if (doneany)
  2046. -    /* Kill the last space.  */
  2047. -    --o;
  2048. -
  2049. -  return o;
  2050. +  return result - vbuffer_unwrite (o, !!result);
  2051.  }
  2052.  
  2053.  /*
  2054.    Print a warning or fatal message.
  2055.  */
  2056. -static char *
  2057. -func_error (char *o, char **argv, const char *funcname)
  2058. +size_t
  2059. +func_error (struct vbuffer *o UNUSED, char **argv, const char *funcname)
  2060.  {
  2061.    char **argvp;
  2062.    char *msg, *p;
  2063. @@ -1111,16 +1063,18 @@
  2064.    }
  2065.  
  2066.    /* The warning function expands to the empty string.  */
  2067. -  return o;
  2068. +  return 0;
  2069.  }
  2070.  
  2071.  
  2072.  /*
  2073.    chop argv[0] into words, and sort them.
  2074.   */
  2075. -static char *
  2076. -func_sort (char *o, char **argv, const char *funcname UNUSED)
  2077. +static size_t
  2078. +func_sort (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  2079.  {
  2080. +  size_t result = 0;
  2081. +
  2082.    const char *t;
  2083.    char **words;
  2084.    int wordi;
  2085. @@ -1133,7 +1087,8 @@
  2086.    wordi = 0;
  2087.    while ((p = find_next_token (&t, NULL)) != 0)
  2088.      {
  2089. -      ++t;
  2090. +      if (*t != '\0')
  2091. +   ++t;
  2092.        ++wordi;
  2093.      }
  2094.  
  2095. @@ -1144,7 +1099,8 @@
  2096.    wordi = 0;
  2097.    while ((p = find_next_token (&t, &len)) != 0)
  2098.      {
  2099. -      ++t;
  2100. +      if (*t != '\0')
  2101. +   ++t;
  2102.        p[len] = '\0';
  2103.        words[wordi++] = p;
  2104.      }
  2105. @@ -1161,18 +1117,18 @@
  2106.            if (i == wordi - 1 || strlen (words[i + 1]) != len
  2107.                || strcmp (words[i], words[i + 1]))
  2108.              {
  2109. -              o = variable_buffer_output (o, words[i], len);
  2110. -              o = variable_buffer_output (o, " ", 1);
  2111. +              result += vbuffer_write (o, words[i], len);
  2112. +              result += vbuffer_write (o, " ", 1);
  2113.              }
  2114.          }
  2115.  
  2116.        /* Kill the last space.  */
  2117. -      --o;
  2118. +      result -= vbuffer_unwrite (o, 1);
  2119.      }
  2120.  
  2121.    free (words);
  2122.  
  2123. -  return o;
  2124. +  return result;
  2125.  }
  2126.  
  2127.  /*
  2128. @@ -1187,9 +1143,11 @@
  2129.    example).
  2130.  */
  2131.  
  2132. -static char *
  2133. -func_if (char *o, char **argv, const char *funcname UNUSED)
  2134. +static size_t
  2135. +func_if (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  2136.  {
  2137. +  size_t ret = 0;
  2138. +
  2139.    const char *begp = argv[0];
  2140.    const char *endp = begp + strlen (argv[0]) - 1;
  2141.    int result = 0;
  2142. @@ -1201,12 +1159,9 @@
  2143.    strip_whitespace (&begp, &endp);
  2144.  
  2145.    if (begp <= endp)
  2146. -    {
  2147. -      char *expansion = expand_argument (begp, endp+1);
  2148. +    result = vbuffer_expand (o, (char *) begp, endp+1 - begp);
  2149.  
  2150. -      result = strlen (expansion);
  2151. -      free (expansion);
  2152. -    }
  2153. +  vbuffer_unwrite (o, result);
  2154.  
  2155.    /* If the result is true (1) we want to eval the first argument, and if
  2156.       it's false (0) we want to eval the second.  If the argument doesn't
  2157. @@ -1215,15 +1170,9 @@
  2158.    argv += 1 + !result;
  2159.  
  2160.    if (*argv)
  2161. -    {
  2162. -      char *expansion = expand_argument (*argv, NULL);
  2163. +    ret += vbuffer_expand (o, *argv, -1);
  2164.  
  2165. -      o = variable_buffer_output (o, expansion, strlen (expansion));
  2166. -
  2167. -      free (expansion);
  2168. -    }
  2169. -
  2170. -  return o;
  2171. +  return ret;
  2172.  }
  2173.  
  2174.  /*
  2175. @@ -1240,15 +1189,15 @@
  2176.    (short-circuiting).
  2177.  */
  2178.  
  2179. -static char *
  2180. -func_or (char *o, char **argv, const char *funcname UNUSED)
  2181. +static size_t
  2182. +func_or (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  2183.  {
  2184.    for ( ; *argv ; ++argv)
  2185.      {
  2186. +      size_t result;
  2187. +
  2188.        const char *begp = *argv;
  2189.        const char *endp = begp + strlen (*argv) - 1;
  2190. -      char *expansion;
  2191. -      int result = 0;
  2192.  
  2193.        /* Find the result of the condition: if it's false keep going.  */
  2194.  
  2195. @@ -1257,23 +1206,14 @@
  2196.        if (begp > endp)
  2197.          continue;
  2198.  
  2199. -      expansion = expand_argument (begp, endp+1);
  2200. -      result = strlen (expansion);
  2201. +      result = vbuffer_expand (o, (char *) begp, endp+1 - begp);
  2202.  
  2203.        /* If the result is false keep going.  */
  2204. -      if (!result)
  2205. -        {
  2206. -          free (expansion);
  2207. -          continue;
  2208. -        }
  2209. -
  2210. -      /* It's true!  Keep this result and return.  */
  2211. -      o = variable_buffer_output (o, expansion, result);
  2212. -      free (expansion);
  2213. -      break;
  2214. +      if (result)
  2215. +   return result;
  2216.      }
  2217.  
  2218. -  return o;
  2219. +    return 0;
  2220.  }
  2221.  
  2222.  /*
  2223. @@ -1290,56 +1230,37 @@
  2224.    (short-circuiting).
  2225.  */
  2226.  
  2227. -static char *
  2228. -func_and (char *o, char **argv, const char *funcname UNUSED)
  2229. +static size_t
  2230. +func_and (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  2231.  {
  2232. -  char *expansion;
  2233. -  int result;
  2234. -
  2235.    while (1)
  2236.      {
  2237. +      size_t result;
  2238. +
  2239.        const char *begp = *argv;
  2240.        const char *endp = begp + strlen (*argv) - 1;
  2241.  
  2242.        /* An empty condition is always false.  */
  2243.        strip_whitespace (&begp, &endp);
  2244.        if (begp > endp)
  2245. -        return o;
  2246. +        return 0;
  2247.  
  2248. -      expansion = expand_argument (begp, endp+1);
  2249. -      result = strlen (expansion);
  2250. +      result = vbuffer_expand (o, (char *) begp, endp+1 - begp);
  2251.  
  2252.        /* If the result is false, stop here: we're done.  */
  2253.        if (!result)
  2254. -        break;
  2255. +        return 0;
  2256.  
  2257.        /* Otherwise the result is true.  If this is the last one, keep this
  2258.           result and quit.  Otherwise go on to the next one!  */
  2259.  
  2260.        if (*(++argv))
  2261. -        free (expansion);
  2262. +   vbuffer_unwrite (o, result);
  2263.        else
  2264. -        {
  2265. -          o = variable_buffer_output (o, expansion, result);
  2266. -          break;
  2267. -        }
  2268. +   return result;
  2269.      }
  2270.  
  2271. -  free (expansion);
  2272. -
  2273. -  return o;
  2274. -}
  2275. -
  2276. -static char *
  2277. -func_wildcard (char *o, char **argv, const char *funcname UNUSED)
  2278. -{
  2279. -#ifdef _AMIGA
  2280. -   o = wildcard_expansion (argv[0], o);
  2281. -#else
  2282. -   char *p = string_glob (argv[0]);
  2283. -   o = variable_buffer_output (o, p, strlen (p));
  2284. -#endif
  2285. -   return o;
  2286. +    return 0;
  2287.  }
  2288.  
  2289.  /*
  2290. @@ -1350,36 +1271,38 @@
  2291.    Treat the arguments as a segment of makefile, and parse them.
  2292.  */
  2293.  
  2294. -static char *
  2295. -func_eval (char *o, char **argv, const char *funcname UNUSED)
  2296. +static size_t
  2297. +func_eval (struct vbuffer *o UNUSED, char **argv, const char *funcname UNUSED)
  2298.  {
  2299. -  char *buf;
  2300. -  unsigned int len;
  2301. +  struct vbuffer *vbuf;
  2302.  
  2303.    /* Eval the buffer.  Pop the current variable buffer setting so that the
  2304.       eval'd code can use its own without conflicting.  */
  2305.  
  2306. -  install_variable_buffer (&buf, &len);
  2307. +  vbuf = install_new_expansion_vbuffer ();
  2308.  
  2309.    eval_buffer (argv[0]);
  2310.  
  2311. -  restore_variable_buffer (buf, len);
  2312. +  restore_expansion_vbuffer (vbuf);
  2313.  
  2314. -  return o;
  2315. +  /* Eval always expands to nothing. */
  2316. +  return 0;
  2317.  }
  2318.  
  2319.  
  2320. -static char *
  2321. -func_value (char *o, char **argv, const char *funcname UNUSED)
  2322. +static size_t
  2323. +func_value (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  2324.  {
  2325. +  size_t result = 0;
  2326. +
  2327.    /* Look up the variable.  */
  2328.    struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
  2329.  
  2330.    /* Copy its value into the output buffer without expanding it.  */
  2331.    if (v)
  2332. -    o = variable_buffer_output (o, v->value, strlen(v->value));
  2333. +    result += vbuffer_write (o, v->value, -1);
  2334.  
  2335. -  return o;
  2336. +  return result;
  2337.  }
  2338.  
  2339.  /*
  2340. @@ -1619,9 +1542,10 @@
  2341.  
  2342.  #else
  2343.  #ifndef _AMIGA
  2344. -char *
  2345. -func_shell_base (char *o, char **argv, int trim_newlines)
  2346. +size_t
  2347. +func_shell_base (struct vbuffer *o, char **argv, int trim_newlines)
  2348.  {
  2349. +  size_t result = 0;
  2350.    char *batch_filename = NULL;
  2351.  
  2352.  #ifdef __MSDOS__
  2353. @@ -1650,7 +1574,7 @@
  2354.  #ifdef WINDOWS32
  2355.        just_print_flag = j_p_f;
  2356.  #endif
  2357. -      return o;
  2358. +      return 0;
  2359.      }
  2360.  #endif
  2361.  
  2362. @@ -1683,7 +1607,7 @@
  2363.    if (pipedes[0] < 0)
  2364.      {
  2365.        perror_with_name (error_prefix, "pipe");
  2366. -      return o;
  2367. +      return 0;
  2368.      }
  2369.  #elif defined(WINDOWS32)
  2370.    windows32_openpipe (pipedes, &pid, command_argv, envp);
  2371. @@ -1694,14 +1618,14 @@
  2372.      {
  2373.        /* Open of the pipe failed, mark as failed execution.  */
  2374.        shell_function_completed = -1;
  2375. -      return o;
  2376. +      return 0;
  2377.      }
  2378.    else
  2379.  #else
  2380.    if (pipe (pipedes) < 0)
  2381.      {
  2382.        perror_with_name (error_prefix, "pipe");
  2383. -      return o;
  2384. +      return 0;
  2385.      }
  2386.  
  2387.  # ifdef __EMX__
  2388. @@ -1800,13 +1724,13 @@
  2389.       /* The child finished normally.  Replace all newlines in its output
  2390.          with spaces, and put that in the variable output buffer.  */
  2391.       fold_newlines (buffer, &i, trim_newlines);
  2392. -     o = variable_buffer_output (o, buffer, i);
  2393. +     result += vbuffer_write (o, buffer, i);
  2394.     }
  2395.  
  2396.        free (buffer);
  2397.      }
  2398.  
  2399. -  return o;
  2400. +  return result;
  2401.  }
  2402.  
  2403.  #else  /* _AMIGA */
  2404. @@ -1892,14 +1816,14 @@
  2405.    Close (child_stdout);
  2406.  
  2407.    fold_newlines (buffer, &i, trim_newlines);
  2408. -  o = variable_buffer_output (o, buffer, i);
  2409. +  result += vbuffer_write (o, buffer, i);
  2410.    free (buffer);
  2411.    return o;
  2412.  }
  2413.  #endif  /* _AMIGA */
  2414.  
  2415. -char *
  2416. -func_shell (char *o, char **argv, const char *funcname UNUSED)
  2417. +size_t
  2418. +func_shell (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  2419.  {
  2420.    return func_shell_base (o, argv, 1);
  2421.  }
  2422. @@ -1914,8 +1838,7 @@
  2423.  func_eq (char *o, char **argv, char *funcname UNUSED)
  2424.  {
  2425.    int result = ! strcmp (argv[0], argv[1]);
  2426. -  o = variable_buffer_output (o,  result ? "1" : "", result);
  2427. -  return o;
  2428. +  return vbuffer_write (o,  result ? "1" : "", result);
  2429.  }
  2430.  
  2431.  
  2432. @@ -1930,8 +1853,7 @@
  2433.    while (isspace ((unsigned char)*s))
  2434.      s++;
  2435.    result = ! (*s);
  2436. -  o = variable_buffer_output (o,  result ? "1" : "", result);
  2437. -  return o;
  2438. +  return vbuffer_write (o,  result ? "1" : "", result);
  2439.  }
  2440.  #endif
  2441.  
  2442. @@ -2058,13 +1980,14 @@
  2443.  }
  2444.  
  2445.  
  2446. -static char *
  2447. -func_realpath (char *o, char **argv, const char *funcname UNUSED)
  2448. +static size_t
  2449. +func_realpath (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  2450.  {
  2451. +  size_t result = 0;
  2452. +
  2453.    /* Expand the argument.  */
  2454.    const char *p = argv[0];
  2455.    const char *path = 0;
  2456. -  int doneany = 0;
  2457.    unsigned int len = 0;
  2458.  #ifndef HAVE_REALPATH
  2459.    struct stat st;
  2460. @@ -2087,22 +2010,17 @@
  2461.  #endif
  2462.               )
  2463.              {
  2464. -              o = variable_buffer_output (o, out, strlen (out));
  2465. -              o = variable_buffer_output (o, " ", 1);
  2466. -              doneany = 1;
  2467. +              result += vbuffer_write (o, out, -1);
  2468. +              result += vbuffer_write (o, " ", 1);
  2469.              }
  2470.          }
  2471.      }
  2472.  
  2473. -  /* Kill last space.  */
  2474. -  if (doneany)
  2475. -    --o;
  2476. -
  2477. -  return o;
  2478. +  return result - vbuffer_unwrite (o, !!result);
  2479.  }
  2480.  
  2481. -static char *
  2482. -func_file (char *o, char **argv, const char *funcname UNUSED)
  2483. +static size_t
  2484. +func_file (struct vbuffer *o UNUSED, char **argv, const char *funcname UNUSED)
  2485.  {
  2486.    char *fn = argv[0];
  2487.  
  2488. @@ -2137,16 +2055,17 @@
  2489.    else
  2490.      fatal (reading_file, _("Invalid file operation: %s"), fn);
  2491.  
  2492. -  return o;
  2493. +  return 0;
  2494.  }
  2495.  
  2496. -static char *
  2497. -func_abspath (char *o, char **argv, const char *funcname UNUSED)
  2498. +static size_t
  2499. +func_abspath (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  2500.  {
  2501. +  size_t result = 0;
  2502. +
  2503.    /* Expand the argument.  */
  2504.    const char *p = argv[0];
  2505.    const char *path = 0;
  2506. -  int doneany = 0;
  2507.    unsigned int len = 0;
  2508.    PATH_VAR (in);
  2509.    PATH_VAR (out);
  2510. @@ -2160,25 +2079,18 @@
  2511.  
  2512.            if (abspath (in, out))
  2513.              {
  2514. -              o = variable_buffer_output (o, out, strlen (out));
  2515. -              o = variable_buffer_output (o, " ", 1);
  2516. -              doneany = 1;
  2517. +              result += vbuffer_write (o, out, strlen (out));
  2518. +              result += vbuffer_write (o, " ", 1);
  2519.              }
  2520.          }
  2521.      }
  2522.  
  2523. -  /* Kill last space.  */
  2524. -  if (doneany)
  2525. -    --o;
  2526. -
  2527. -  return o;
  2528. +  return result - vbuffer_unwrite (o, !!result);
  2529.  }
  2530.  
  2531.  /* Lookup table for builtin functions.
  2532.  
  2533. -   This doesn't have to be sorted; we use a straight lookup.  We might gain
  2534. -   some efficiency by moving most often used functions to the start of the
  2535. -   table.
  2536. +   This doesn't have to be sorted; we use hash table to perform a lookup.
  2537.  
  2538.     If MAXIMUM_ARGS is 0, that means there is no maximum and all
  2539.     comma-separated values are treated as arguments.
  2540. @@ -2186,7 +2098,7 @@
  2541.     EXPAND_ARGS means that all arguments should be expanded before invocation.
  2542.     Functions that do namespace tricks (foreach) don't automatically expand.  */
  2543.  
  2544. -static char *func_call (char *o, char **argv, const char *funcname);
  2545. +static size_t func_call (struct vbuffer *o, char **argv, const char *funcname);
  2546.  
  2547.  
  2548.  static struct function_table_entry function_table_init[] =
  2549. @@ -2237,10 +2149,26 @@
  2550.  #define FUNCTION_TABLE_ENTRIES (sizeof (function_table_init) / sizeof (struct function_table_entry))
  2551.  
  2552.  
  2553. +/* Look up a function by name.  */
  2554. +
  2555. +#ifdef __GNUC__
  2556. +__inline
  2557. +#endif
  2558. +static const struct function_table_entry *
  2559. +lookup_function (const char *name, unsigned int length)
  2560. +{
  2561. +  struct function_table_entry function_table_entry_key;
  2562. +  function_table_entry_key.name = name;
  2563. +  function_table_entry_key.len = length;
  2564. +
  2565. +  return hash_find_item (&function_table, &function_table_entry_key);
  2566. +}
  2567. +
  2568. +
  2569.  /* These must come after the definition of function_table.  */
  2570.  
  2571. -static char *
  2572. -expand_builtin_function (char *o, int argc, char **argv,
  2573. +static size_t
  2574. +expand_builtin_function (struct vbuffer *o, int argc, char **argv,
  2575.                           const struct function_table_entry *entry_p)
  2576.  {
  2577.    if (argc < (int)entry_p->minimum_args)
  2578. @@ -2253,7 +2181,7 @@
  2579.       rather than in each one.  We can change it later if necessary.  */
  2580.  
  2581.    if (!argc)
  2582. -    return o;
  2583. +    return 0;
  2584.  
  2585.    if (!entry_p->func_ptr)
  2586.      fatal (*expanding_var,
  2587. @@ -2264,120 +2192,134 @@
  2588.  
  2589.  /* Check for a function invocation in *STRINGP.  *STRINGP points at the
  2590.     opening ( or { and is not null-terminated.  If a function invocation
  2591. -   is found, expand it into the buffer at *OP, updating *OP, incrementing
  2592. -   *STRINGP past the reference and returning nonzero.  If not, return zero.  */
  2593. +   is found, expand it into the buffer O, incrementing *STRINGP past the
  2594. +   reference and returning the amount of bytes written.
  2595. +   Note, that in this case the string between the parens is destroyed.
  2596. +
  2597. +   If no function call is recognized, return -1.  */
  2598.  
  2599.  int
  2600. -handle_function (char **op, const char **stringp)
  2601. +handle_function (struct vbuffer *o, char **stringp)
  2602.  {
  2603. +  size_t ret = 0;
  2604. +
  2605.    const struct function_table_entry *entry_p;
  2606.    char openparen = (*stringp)[0];
  2607.    char closeparen = openparen == '(' ? ')' : '}';
  2608. -  const char *beg;
  2609. -  const char *end;
  2610. -  int count = 0;
  2611. -  char *abeg = NULL;
  2612. +  char *beg;
  2613. +  char *end;
  2614. +  int count;
  2615.    char **argv, **argvp;
  2616. -  int nargs;
  2617. +  int nargs, maxargs;
  2618. +  struct vbuffer argbuf;
  2619. +  size_t reserved;
  2620.  
  2621.    beg = *stringp + 1;
  2622.  
  2623. -  entry_p = lookup_function (beg);
  2624. +  end = beg;
  2625. +  while ((*end >= 'a' && *end <= 'z') || *end == '-')
  2626. +    end++;
  2627. +  if (*end != ' ' && *end != '\t')
  2628. +    return -1;
  2629.  
  2630. +  entry_p = lookup_function (beg, end - beg);
  2631.    if (!entry_p)
  2632. -    return 0;
  2633. +    return -1;
  2634.  
  2635.    /* We found a builtin function.  Find the beginning of its arguments (skip
  2636.       whitespace after the name).  */
  2637.  
  2638. -  beg = next_token (beg + entry_p->len);
  2639. +  beg = next_token (end);
  2640. +  maxargs = entry_p->maximum_args;
  2641.  
  2642.    /* Find the end of the function invocation, counting nested use of
  2643. -     whichever kind of parens we use.  Since we're looking, count commas
  2644. -     to get a rough estimate of how many arguments we might have.  The
  2645. -     count might be high, but it'll never be low.  */
  2646. -
  2647. -  for (nargs=1, end=beg; *end != '\0'; ++end)
  2648. -    if (*end == ',')
  2649. -      ++nargs;
  2650. -    else if (*end == openparen)
  2651. +     whichever kind of parens we use and isolating arguments.
  2652. +     As soon as we hit up to MAXARGS (if it is positive) assume the rest of
  2653. +     the string is part of the last argument. For each argument, we save
  2654. +     a pointer into the ARGBUF and NULL-terminate the argument value.  */
  2655. +#define VBUFFER_WRITE_PTR(o, value) \
  2656. +  *((char **) (((o)->ptr += sizeof (char *)) - sizeof (char *))) = (value)
  2657. +
  2658. +  vbuffer_init (&argbuf);
  2659. +  reserved = argbuf.size - sizeof (char *);
  2660. +
  2661. +  VBUFFER_WRITE_PTR (&argbuf, beg);
  2662. +
  2663. +  nargs=1;
  2664. +  count = 0;
  2665. +  for (end=beg; *end != '\0'; ++end)
  2666. +    if (*end == openparen)
  2667.        ++count;
  2668.      else if (*end == closeparen && --count < 0)
  2669.        break;
  2670. +    else if (count == 0 && *end == ',' && nargs != maxargs)
  2671. +      {
  2672. +   *end = '\0';
  2673. +   nargs++;
  2674. +
  2675. +   if (reserved <= 2 * sizeof (char *))
  2676. +     reserved = vbuffer_reserve (&argbuf, 2 * sizeof (char *));
  2677. +   else
  2678. +     reserved -= sizeof (char *);
  2679. +
  2680. +   VBUFFER_WRITE_PTR (&argbuf, end+1);
  2681. +      }
  2682.  
  2683.    if (count >= 0)
  2684.      fatal (*expanding_var,
  2685.        _("unterminated call to function '%s': missing '%c'"),
  2686.        entry_p->name, closeparen);
  2687.  
  2688. -  *stringp = end;
  2689. +  /* NULL-terminate the last argument.  */
  2690. +  *end = '\0';
  2691.  
  2692. -  /* Get some memory to store the arg pointers.  */
  2693. -  argvp = argv = alloca (sizeof (char *) * (nargs + 2));
  2694. +  /* NULL-terminate the arg vector (assume there was enough room reserved).  */
  2695. +  VBUFFER_WRITE_PTR (&argbuf, NULL);
  2696.  
  2697. -  /* Chop the string into arguments, then a nul.  As soon as we hit
  2698. -     MAXIMUM_ARGS (if it's >0) assume the rest of the string is part of the
  2699. -     last argument.
  2700. -
  2701. -     If we're expanding, store pointers to the expansion of each one.  If
  2702. -     not, make a duplicate of the string and point into that, nul-terminating
  2703. -     each argument.  */
  2704. +  argv = (char **) argbuf.buffer;
  2705.  
  2706. -  if (entry_p->expand_args)
  2707. -    {
  2708. -      const char *p;
  2709. -      for (p=beg, nargs=0; p <= end; ++argvp)
  2710. -        {
  2711. -          const char *next;
  2712. +  /* If the function requires argument to be expanded, expand them into the
  2713. +     same buffer as we used to for the arg vector, but store pointers to the
  2714. +     expansion of each one into a new stack-allocated vector.
  2715.  
  2716. -          ++nargs;
  2717. +     This, in turn, is performed in two steps:
  2718. +       - First, we save position-independent offsets into a special buffer.
  2719. +       - Next, build the final arg vector from the offsets buffer.
  2720.  
  2721. -          if (nargs == entry_p->maximum_args
  2722. -              || (! (next = find_next_argument (openparen, closeparen, p, end))))
  2723. -            next = end;
  2724. +     Involving an intermediate buffer for the offsets is necessary because
  2725. +     ARGBUF may grow while expanding an argument thus invalidating any
  2726. +     previously stored pointers.  */
  2727.  
  2728. -          *argvp = expand_argument (p, next);
  2729. -          p = next + 1;
  2730. -        }
  2731. -    }
  2732. -  else
  2733. +  if (entry_p->expand_args)
  2734.      {
  2735. -      int len = end - beg;
  2736. -      char *p, *aend;
  2737. -
  2738. -      abeg = xmalloc (len+1);
  2739. -      memcpy (abeg, beg, len);
  2740. -      abeg[len] = '\0';
  2741. -      aend = abeg + len;
  2742. -
  2743. -      for (p=abeg, nargs=0; p <= aend; ++argvp)
  2744. -        {
  2745. -          char *next;
  2746. -
  2747. -          ++nargs;
  2748. -
  2749. -          if (nargs == entry_p->maximum_args
  2750. -              || (! (next = find_next_argument (openparen, closeparen, p, aend))))
  2751. -            next = aend;
  2752. -
  2753. -          *argvp = p;
  2754. -          *next = '\0';
  2755. -          p = next + 1;
  2756. -        }
  2757. +      int i;
  2758. +      size_t *offs = alloca ((nargs + 1) * sizeof (size_t));
  2759. +      argv = memcpy (alloca ((nargs + 1) * sizeof (char *)),
  2760. +              argv, (nargs + 1) * sizeof (char *));
  2761. +
  2762. +      vbuffer_reset (&argbuf);
  2763. +      offs[0] = 0;
  2764. +      for (i=0, argvp=argv; *argvp != 0; ++argvp, ++i)
  2765. +   {
  2766. +     offs[i + 1] = offs[i] + vbuffer_expand (&argbuf, *argvp, -1) + 1;
  2767. +     *(++argbuf.ptr) = '\0';
  2768. +   }
  2769. +      for (i=0, argvp=argv; *argvp != 0; ++argvp, ++i)
  2770. +   *argvp = argbuf.buffer + offs[i];
  2771.      }
  2772. -  *argvp = NULL;
  2773.  
  2774.    /* Finally!  Run the function...  */
  2775. -  *op = expand_builtin_function (*op, nargs, argv, entry_p);
  2776. +  ret += expand_builtin_function (o, nargs, argv, entry_p);
  2777.  
  2778. -  /* Free memory.  */
  2779. -  if (entry_p->expand_args)
  2780. -    for (argvp=argv; *argvp != 0; ++argvp)
  2781. -      free (*argvp);
  2782. -  else if (abeg)
  2783. -    free (abeg);
  2784. +  /* Restore a paren after the last argument and advance the STRINGP.  */
  2785. +  *end = closeparen;
  2786. +  *stringp = end;
  2787. +
  2788. +  vbuffer_free (&argbuf);
  2789. +
  2790. +#undef VBUFFER_WRITE_PTR
  2791.  
  2792. -  return 1;
  2793. +  return ret;
  2794.  }
  2795.  
  2796.  
  2797. @@ -2385,37 +2327,41 @@
  2798.     function or a make variable, in the context of the rest of the arguments
  2799.     assigned to $1, $2, ... $N.  $0 is the name of the function.  */
  2800.  
  2801. -static char *
  2802. -func_call (char *o, char **argv, const char *funcname UNUSED)
  2803. +static size_t
  2804. +func_call (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  2805.  {
  2806. -  static int max_args = 0;
  2807. +  size_t ret = 0;
  2808. +
  2809.    char *fname;
  2810.    char *cp;
  2811. -  char *body;
  2812.    int flen;
  2813.    int i;
  2814. -  int saved_args;
  2815. +  int argc;
  2816.    const struct function_table_entry *entry_p;
  2817.    struct variable *v;
  2818.  
  2819.    /* There is no way to define a variable with a space in the name, so strip
  2820. -     leading and trailing whitespace as a favor to the user.  */
  2821. +     trailing whitespace as a favor to the user.  */
  2822.    fname = argv[0];
  2823.    while (*fname != '\0' && isspace ((unsigned char)*fname))
  2824.      ++fname;
  2825.  
  2826. -  cp = fname + strlen (fname) - 1;
  2827. +  flen = strlen (fname);
  2828. +
  2829. +  cp = fname + flen - 1;
  2830.    while (cp > fname && isspace ((unsigned char)*cp))
  2831.      --cp;
  2832.    cp[1] = '\0';
  2833.  
  2834.    /* Calling nothing is a no-op */
  2835.    if (*fname == '\0')
  2836. -    return o;
  2837. +    return 0;
  2838.  
  2839. -  /* Are we invoking a builtin function?  */
  2840. +  /* Fix up the length after stripping a trailing whitespace. */
  2841. +  flen = cp - fname + 1;
  2842.  
  2843. -  entry_p = lookup_function (fname);
  2844. +  /* Are we invoking a builtin function?  */
  2845. +  entry_p = lookup_function (fname, flen);
  2846.    if (entry_p)
  2847.      {
  2848.        /* How many arguments do we have?  */
  2849. @@ -2426,7 +2372,6 @@
  2850.  
  2851.    /* Not a builtin, so the first argument is the name of a variable to be
  2852.       expanded and interpreted as a function.  Find it.  */
  2853. -  flen = strlen (fname);
  2854.  
  2855.    v = lookup_variable (fname, flen);
  2856.  
  2857. @@ -2434,61 +2379,42 @@
  2858.      warn_undefined (fname, flen);
  2859.  
  2860.    if (v == 0 || *v->value == '\0')
  2861. -    return o;
  2862. -
  2863. -  body = alloca (flen + 4);
  2864. -  body[0] = '$';
  2865. -  body[1] = '(';
  2866. -  memcpy (body + 2, fname, flen);
  2867. -  body[flen+2] = ')';
  2868. -  body[flen+3] = '\0';
  2869. -
  2870. -  /* Set up arguments $(1) .. $(N).  $(0) is the function name.  */
  2871. -
  2872. -  push_new_variable_scope ();
  2873. -
  2874. -  for (i=0; *argv; ++i, ++argv)
  2875. -    {
  2876. -      char num[11];
  2877. -
  2878. -      sprintf (num, "%d", i);
  2879. -      define_variable (num, strlen (num), *argv, o_automatic, 0);
  2880. -    }
  2881. -
  2882. -  /* If the number of arguments we have is < max_args, it means we're inside
  2883. -     a recursive invocation of $(call ...).  Fill in the remaining arguments
  2884. -     in the new scope with the empty value, to hide them from this
  2885. -     invocation.  */
  2886. -
  2887. -  for (; i < max_args; ++i)
  2888. -    {
  2889. -      char num[11];
  2890. -
  2891. -      sprintf (num, "%d", i);
  2892. -      define_variable (num, strlen (num), "", o_automatic, 0);
  2893. -    }
  2894. +    return 0;
  2895.  
  2896. -  /* Expand the body in the context of the arguments, adding the result to
  2897. -     the variable buffer.  */
  2898. +  if (!v->recursive)
  2899. +    return vbuffer_write(o, v->value, -1);
  2900.  
  2901. -  v->exp_count = EXP_COUNT_MAX;
  2902. +  /* Count the arguments.  */
  2903. +  argc = 0;
  2904. +  while (argv[++argc])
  2905. +    ;
  2906.  
  2907. -  saved_args = max_args;
  2908. -  max_args = i;
  2909. -  o = variable_expand_string (o, body, flen+3);
  2910. -  max_args = saved_args;
  2911. +  {
  2912. +    struct call_frame new_frame;
  2913. +    struct call_frame *saved_frame = current_call_frame;
  2914.  
  2915. -  v->exp_count = 0;
  2916. +    /* Replace the current call frame with a new one.  */
  2917. +    new_frame.argc = argc;
  2918. +    new_frame.argv = argv;
  2919. +    current_call_frame = &new_frame;
  2920. +
  2921. +    /* Expand the variable in the context of the arguments,
  2922. +       writing the result into the variable buffer.  */
  2923. +    v->exp_count = EXP_COUNT_MAX;
  2924. +    ret += vbuffer_expand_variable (o, v);
  2925. +    v->exp_count = 0;
  2926.  
  2927. -  pop_variable_scope ();
  2928. +    current_call_frame = saved_frame;
  2929. +  }
  2930.  
  2931. -  return o + strlen (o);
  2932. +  return ret;
  2933.  }
  2934.  
  2935. +
  2936.  void
  2937.  define_new_function(const struct floc *flocp,
  2938.                      const char *name, int min, int max, int expand,
  2939. -                    char *(*func)(char *, char **, const char *))
  2940. +                    size_t (*func)(struct vbuffer *, char **, const char *))
  2941.  {
  2942.    size_t len = strlen (name);
  2943.    struct function_table_entry *ent = xmalloc (sizeof (struct function_table_entry));
  2944. Index: guile.c
  2945. ===================================================================
  2946. RCS file: /sources/make/make/guile.c,v
  2947. retrieving revision 2.5
  2948. diff -u -r2.5 guile.c
  2949. --- guile.c 5 Mar 2012 14:10:44 -0000   2.5
  2950. +++ guile.c 9 Apr 2012 13:34:41 -0000
  2951. @@ -86,20 +86,22 @@
  2952.  }
  2953.  
  2954.  /* This is the function registered with make  */
  2955. -static char *
  2956. -func_guile (char *o, char **argv, const char *funcname UNUSED)
  2957. +static size_t
  2958. +func_guile (struct vbuffer *o, char **argv, const char *funcname UNUSED)
  2959.  {
  2960. +  size_t result = 0;
  2961. +
  2962.    if (argv[0] && argv[0][0] != '\0')
  2963.      {
  2964.        char *str = scm_with_guile (internal_guile_eval, argv[0]);
  2965.        if (str)
  2966.          {
  2967. -          o = variable_buffer_output (o, str, strlen (str));
  2968. +          result += vbuffer_write (o, str, -1);
  2969.            free (str);
  2970.          }
  2971.      }
  2972.  
  2973. -  return o;
  2974. +  return result;
  2975.  }
  2976.  
  2977.  /* ----- Public interface ----- */
  2978. Index: main.c
  2979. ===================================================================
  2980. RCS file: /sources/make/make/main.c,v
  2981. retrieving revision 1.256
  2982. diff -u -r1.256 main.c
  2983. --- main.c  5 Mar 2012 14:10:44 -0000   1.256
  2984. +++ main.c  9 Apr 2012 13:34:42 -0000
  2985. @@ -1104,6 +1104,8 @@
  2986.  
  2987.    initialize_global_hash_tables ();
  2988.  
  2989. +  install_new_expansion_vbuffer();
  2990. +
  2991.    /* Figure out where we are.  */
  2992.  
  2993.  #ifdef WINDOWS32
  2994. @@ -2277,12 +2279,7 @@
  2995.        if (default_goal_var->recursive)
  2996.          p = variable_expand (default_goal_var->value);
  2997.        else
  2998. -        {
  2999. -          p = variable_buffer_output (variable_buffer, default_goal_var->value,
  3000. -                                      strlen (default_goal_var->value));
  3001. -          *p = '\0';
  3002. -          p = variable_buffer;
  3003. -        }
  3004. +   p = default_goal_var->value;
  3005.  
  3006.        if (*p != '\0')
  3007.          {
  3008. @@ -2359,6 +2356,16 @@
  3009.      if (clock_skew_detected)
  3010.        error (NILF,
  3011.               _("warning:  Clock skew detected.  Your build may be incomplete."));
  3012. +//    error (NILF,
  3013. +//    "memory_usage: %10d total: %8d mallocs, %8d reallocs, %8d strdups",
  3014. +//    nr_mallocs + nr_reallocs + nr_strdups,
  3015. +//    nr_mallocs, nr_reallocs, nr_strdups);
  3016. +//    error (NILF,
  3017. +//    "hash: %10d cmps, %8d hash1, %8d hash2",
  3018. +//    nr_cmps, nr_hash1, nr_hash2);
  3019. +//    error (NILF,
  3020. +//    "max_lookup_depth: %10d, miss: %10d",
  3021. +//    max_lookup_depth, lookup_miss);
  3022.  
  3023.      /* Exit.  */
  3024.      die (status);
  3025. Index: make.h
  3026. ===================================================================
  3027. RCS file: /sources/make/make/make.h,v
  3028. retrieving revision 1.157
  3029. diff -u -r1.157 make.h
  3030. --- make.h  5 Mar 2012 14:10:44 -0000   1.157
  3031. +++ make.h  9 Apr 2012 13:34:42 -0000
  3032. @@ -21,6 +21,9 @@
  3033.  #undef  HAVE_CONFIG_H
  3034.  #define HAVE_CONFIG_H 1
  3035.  
  3036. +extern int nr_mallocs, nr_reallocs, nr_strdups, nr_cmps, nr_hash1, nr_hash2;
  3037. +extern int max_lookup_depth, lookup_miss;
  3038. +
  3039.  /* Specify we want GNU source code.  This must be defined before any
  3040.     system headers are included.  */
  3041.  
  3042. @@ -406,11 +409,32 @@
  3043.  void *xrealloc (void *, unsigned int);
  3044.  char *xstrdup (const char *);
  3045.  char *xstrndup (const char *, unsigned int);
  3046. +
  3047.  char *find_next_token (const char **, unsigned int *);
  3048. -char *next_token (const char *);
  3049. -char *end_of_token (const char *);
  3050. +
  3051. +/* The following three functions are used extremely frequently,
  3052. +   so we try to inline them where possible.  */
  3053. +#ifdef __GNUC__
  3054. +
  3055. +static __inline char *
  3056. +next_token (const char *s)
  3057. +  { return (char *) s + strspn (s, " \t"); }
  3058. +
  3059. +static __inline char *
  3060. +end_of_token (const char *s)
  3061. +  { return (char *) s + strcspn (s, " \t"); }
  3062. +
  3063. +static __inline char *
  3064. +lindex (const char *s, const char *limit, int c)
  3065. +  { return memchr (s, c, limit - s); }
  3066. +
  3067. +#else
  3068. +char *next_token (const char *s);
  3069. +char *end_of_token (const char *s);
  3070. +char *lindex (const char *s, const char *limit, int c);
  3071. +#endif /* __GNUC__ */
  3072. +
  3073.  void collapse_continuations (char *);
  3074. -char *lindex (const char *, const char *, int);
  3075.  int alpha_compare (const void *, const void *);
  3076.  void print_spaces (unsigned int);
  3077.  char *find_percent (char *);
  3078. Index: misc.c
  3079. ===================================================================
  3080. RCS file: /sources/make/make/misc.c,v
  3081. retrieving revision 1.89
  3082. diff -u -r1.89 misc.c
  3083. --- misc.c  5 Mar 2012 14:10:44 -0000   1.89
  3084. +++ misc.c  9 Apr 2012 13:34:42 -0000
  3085. @@ -360,6 +360,8 @@
  3086.  /* Like malloc but get fatal error if memory is exhausted.  */
  3087.  /* Don't bother if we're using dmalloc; it provides these for us.  */
  3088.  
  3089. +int nr_mallocs, nr_reallocs, nr_strdups, nr_cmps, nr_hash1, nr_hash2;
  3090. +
  3091.  #ifndef HAVE_DMALLOC_H
  3092.  
  3093.  #undef xmalloc
  3094. @@ -372,6 +374,7 @@
  3095.  {
  3096.    /* Make sure we don't allocate 0, for pre-ISO implementations.  */
  3097.    void *result = malloc (size ? size : 1);
  3098. +//  ++nr_mallocs;
  3099.    if (result == 0)
  3100.      fatal (NILF, _("virtual memory exhausted"));
  3101.    return result;
  3102. @@ -383,6 +386,7 @@
  3103.  {
  3104.    /* Make sure we don't allocate 0, for pre-ISO implementations.  */
  3105.    void *result = calloc (size ? size : 1, 1);
  3106. +//  ++nr_mallocs;
  3107.    if (result == 0)
  3108.      fatal (NILF, _("virtual memory exhausted"));
  3109.    return result;
  3110. @@ -393,6 +397,7 @@
  3111.  xrealloc (void *ptr, unsigned int size)
  3112.  {
  3113.    void *result;
  3114. +//  ++nr_reallocs;
  3115.  
  3116.    /* Some older implementations of realloc() don't conform to ISO.  */
  3117.    if (! size)
  3118. @@ -408,6 +413,7 @@
  3119.  xstrdup (const char *ptr)
  3120.  {
  3121.    char *result;
  3122. +//  ++nr_strdups;
  3123.  
  3124.  #ifdef HAVE_STRDUP
  3125.    result = strdup (ptr);
  3126. @@ -431,6 +437,7 @@
  3127.  xstrndup (const char *str, unsigned int length)
  3128.  {
  3129.    char *result;
  3130. +//  ++nr_strdups;
  3131.  
  3132.  #ifdef HAVE_STRNDUP
  3133.    result = strndup (str, length);
  3134. @@ -447,6 +454,7 @@
  3135.  }
  3136.  
  3137.  
  3138. +#ifndef __GNUC__
  3139.  /* Limited INDEX:
  3140.     Search through the string STRING, which ends at LIMIT, for the character C.
  3141.     Returns a pointer to the first occurrence, or nil if none is found.
  3142. @@ -456,11 +464,7 @@
  3143.  char *
  3144.  lindex (const char *s, const char *limit, int c)
  3145.  {
  3146. -  while (s < limit)
  3147. -    if (*s++ == c)
  3148. -      return (char *)(s - 1);
  3149. -
  3150. -  return 0;
  3151. +  return memchr (s, c, limit - s);
  3152.  }
  3153.  
  3154.  /* Return the address of the first whitespace or null in the string S.  */
  3155. @@ -468,10 +472,9 @@
  3156.  char *
  3157.  end_of_token (const char *s)
  3158.  {
  3159. -  while (*s != '\0' && !isblank ((unsigned char)*s))
  3160. -    ++s;
  3161. -  return (char *)s;
  3162. +  return (char *) s + strcspn (s, " \t");
  3163.  }
  3164. +#endif /* !__GNUC__ */
  3165.  
  3166.  #ifdef WINDOWS32
  3167.  /*
  3168. @@ -503,15 +506,15 @@
  3169.  }
  3170.  #endif
  3171.  
  3172. +#ifndef __GNUC__
  3173.  /* Return the address of the first nonwhitespace or null in the string S.  */
  3174.  
  3175.  char *
  3176.  next_token (const char *s)
  3177.  {
  3178. -  while (isblank ((unsigned char)*s))
  3179. -    ++s;
  3180. -  return (char *)s;
  3181. +  return (char *) s + strspn (s, " \t");
  3182.  }
  3183. +#endif /* !__GNUC__ */
  3184.  
  3185.  /* Find the next token in PTR; return the address of it, and store the length
  3186.     of the token into *LENGTHPTR if LENGTHPTR is not nil.  Set *PTR to the end
  3187. Index: read.c
  3188. ===================================================================
  3189. RCS file: /sources/make/make/read.c,v
  3190. retrieving revision 1.210
  3191. diff -u -r1.210 read.c
  3192. --- read.c  5 Mar 2012 14:10:44 -0000   1.210
  3193. +++ read.c  9 Apr 2012 13:34:42 -0000
  3194. @@ -566,6 +566,7 @@
  3195.    const char *pattern_percent;
  3196.    struct floc *fstart;
  3197.    struct floc fi;
  3198. +  struct vbuffer vbuf;
  3199.  
  3200.  #define record_waiting_files()                           \
  3201.    do                                         \
  3202. @@ -583,6 +584,8 @@
  3203.        pattern = 0;                                                            \
  3204.      } while (0)
  3205.  
  3206. +  vbuffer_init(&vbuf);
  3207. +
  3208.    pattern_percent = 0;
  3209.    cmds_started = tgts_started = 1;
  3210.  
  3211. @@ -893,6 +896,7 @@
  3212.        {
  3213.          enum make_word_type wtype;
  3214.          char *cmdleft, *semip, *lb_next;
  3215. +        unsigned int llen = 0;
  3216.          unsigned int plen = 0;
  3217.          char *colonp;
  3218.          const char *end, *beg; /* Helpers for whitespace stripping. */
  3219. @@ -943,7 +947,8 @@
  3220.              break;
  3221.            }
  3222.  
  3223. -        p2 = variable_expand_string(NULL, lb_next, wlen);
  3224. +        vbuffer_expand_ro (vbuffer_reset(&vbuf), lb_next, wlen);
  3225. +        p2 = vbuf.buffer;
  3226.  
  3227.          while (1)
  3228.            {
  3229. @@ -955,9 +960,8 @@
  3230.  
  3231.                  if (cmdleft != 0)
  3232.                    {
  3233. -                    unsigned long p2_off = p2 - variable_buffer;
  3234. -                    unsigned long cmd_off = cmdleft - variable_buffer;
  3235. -                    char *pend = p2 + strlen(p2);
  3236. +                    unsigned long p2_off = p2 - vbuf.buffer;
  3237. +                    unsigned long cmd_off = cmdleft - vbuf.buffer;
  3238.  
  3239.                      /* Append any remnants of lb, then cut the line short
  3240.                         at the semicolon.  */
  3241. @@ -967,14 +971,16 @@
  3242.                         here, but merely copy, since now you're beyond a ";"
  3243.                         and into a command script.  However, the old parser
  3244.                         expanded the whole line, so we continue that for
  3245. -                       backwards-compatiblity.  Also, it wouldn't be
  3246. +                       backwards-compatibility.  Also, it wouldn't be
  3247.                         entirely consistent, since we do an unconditional
  3248.                         expand below once we know we don't have a
  3249.                         target-specific variable. */
  3250. -                    (void)variable_expand_string(pend, lb_next, (long)-1);
  3251. +                    vbuffer_expand_ro (&vbuf, lb_next, -1);
  3252. +
  3253. +                    p2 = vbuf.buffer + p2_off;
  3254. +                    cmdleft = vbuf.buffer + cmd_off + 1;
  3255. +
  3256.                      lb_next += strlen(lb_next);
  3257. -                    p2 = variable_buffer + p2_off;
  3258. -                    cmdleft = variable_buffer + cmd_off + 1;
  3259.                    }
  3260.                }
  3261.  
  3262. @@ -996,15 +1002,16 @@
  3263.              if (wtype == w_eol)
  3264.                break;
  3265.  
  3266. -            p2 += strlen(p2);
  3267. -            *(p2++) = ' ';
  3268. -            p2 = variable_expand_string(p2, lb_next, wlen);
  3269. +            vbuffer_write(&vbuf, " ", 1);
  3270. +            plen = vbuffer_expand_ro (&vbuf, lb_next, wlen);
  3271. +            p2 = vbuf.ptr - plen;
  3272. +
  3273.              /* We don't need to worry about cmdleft here, because if it was
  3274.                 found in the variable_buffer the entire buffer has already
  3275.                 been expanded... we'll never get here.  */
  3276.            }
  3277.  
  3278. -        p2 = next_token (variable_buffer);
  3279. +        p2 = next_token (vbuf.buffer);
  3280.  
  3281.          /* If the word we're looking at is EOL, see if there's _anything_
  3282.             on the line.  If not, a variable expanded to nothing, so ignore
  3283. @@ -1045,14 +1052,13 @@
  3284.  
  3285.          /* Test to see if it's a target-specific variable.  Copy the rest
  3286.             of the buffer over, possibly temporarily (we'll expand it later
  3287. -           if it's not a target-specific variable).  PLEN saves the length
  3288. -           of the unparsed section of p2, for later.  */
  3289. +           if it's not a target-specific variable).  LLEN saves the length
  3290. +           of the copied string, to know how many bytes to discard later.  */
  3291.          if (*lb_next != '\0')
  3292.            {
  3293. -            unsigned int l = p2 - variable_buffer;
  3294. -            plen = strlen (p2);
  3295. -            variable_buffer_output (p2+plen, lb_next, strlen (lb_next)+1);
  3296. -            p2 = variable_buffer + l;
  3297. +            unsigned long p2_off = p2 - vbuf.buffer;
  3298. +            llen = vbuffer_write (&vbuf, lb_next, -1);
  3299. +            p2 = vbuf.buffer + p2_off;
  3300.            }
  3301.  
  3302.          p2 = parse_var_assignment (p2, &vmod);
  3303. @@ -1062,12 +1068,11 @@
  3304.                 after it.  */
  3305.              if (semip)
  3306.                {
  3307. -                unsigned int l = p - variable_buffer;
  3308. +                unsigned long p2_off = p2 - vbuf.buffer;
  3309.                  *(--semip) = ';';
  3310.                  collapse_continuations (semip);
  3311. -                variable_buffer_output (p2 + strlen (p2),
  3312. -                                        semip, strlen (semip)+1);
  3313. -                p = variable_buffer + l;
  3314. +                vbuffer_write (&vbuf, semip, -1);
  3315. +                p2 = vbuf.buffer + p2_off;
  3316.                }
  3317.              record_target_var (filenames, p2,
  3318.                                 vmod.override_v ? o_override : o_file,
  3319. @@ -1086,12 +1091,14 @@
  3320.          /* We have some targets, so don't ignore the following commands.  */
  3321.          no_targets = 0;
  3322.  
  3323. -        /* Expand the dependencies, etc.  */
  3324. +        /* Expand the dependencies, etc.
  3325. +           P2 still point past the colon.  */
  3326.          if (*lb_next != '\0')
  3327.            {
  3328. -            unsigned int l = p2 - variable_buffer;
  3329. -            (void) variable_expand_string (p2 + plen, lb_next, (long)-1);
  3330. -            p2 = variable_buffer + l;
  3331. +            unsigned long p2_off = p2 - vbuf.buffer;
  3332. +            vbuffer_unwrite (&vbuf, llen);
  3333. +            vbuffer_expand_ro (&vbuf, lb_next, -1);
  3334. +            p2 = vbuf.buffer + p2_off;
  3335.  
  3336.              /* Look for a semicolon in the expanded line.  */
  3337.              if (cmdleft == 0)
  3338. @@ -1281,8 +1288,6 @@
  3339.        record_waiting_files ();
  3340.      }
  3341.  
  3342. -#undef word1eq
  3343. -
  3344.    if (conditionals->if_cmds)
  3345.      fatal (fstart, _("missing 'endif'"));
  3346.  
  3347. @@ -1292,7 +1297,13 @@
  3348.    if (collapsed)
  3349.      free (collapsed);
  3350.    free (commands);
  3351. +
  3352. +  vbuffer_free(&vbuf);
  3353. +
  3354. +#undef record_waiting_files
  3355.  }
  3356. +
  3357. +#undef word1eq
  3358.  
  3359.  
  3360.  /* Remove comments from LINE.
  3361. @@ -1842,6 +1853,7 @@
  3362.    struct dep *deps;
  3363.    const char *implicit_percent;
  3364.    const char *name;
  3365. +  struct vbuffer patbuf;
  3366.  
  3367.    /* If we've already snapped deps, that means we're in an eval being
  3368.       resolved after the makefiles have been read in.  We can't add more rules
  3369. @@ -1945,6 +1957,7 @@
  3370.        return;
  3371.      }
  3372.  
  3373. +  vbuffer_init (&patbuf);
  3374.  
  3375.    /* Walk through each target and create it in the database.
  3376.       We already set up the first target, above.  */
  3377. @@ -2057,10 +2070,12 @@
  3378.        if (pattern)
  3379.          {
  3380.            static const char *percent = "%";
  3381. -          char *buffer = variable_expand ("");
  3382. -          char *o = patsubst_expand_pat (buffer, name, pattern, percent,
  3383. -                                         pattern_percent+1, percent+1);
  3384. -          f->stem = strcache_add_len (buffer, o - buffer);
  3385. +          size_t len;
  3386. +
  3387. +          len = patsubst_expand_pat (vbuffer_reset(&patbuf), name,
  3388. +                    pattern, percent,
  3389. +                    pattern_percent+1, percent+1);
  3390. +          f->stem = strcache_add_len (patbuf.buffer, len);
  3391.            if (this)
  3392.              {
  3393.                if (! this->need_2nd_expansion)
  3394. @@ -2112,6 +2127,8 @@
  3395.        if (find_percent_cached (&name))
  3396.          fatal (flocp, _("mixed implicit and normal rules"));
  3397.      }
  3398. +
  3399. +  vbuffer_free (&patbuf);
  3400.  }
  3401.  
  3402.  /* Search STRING for an unquoted STOPCHAR or blank (if BLANK is nonzero).
  3403. Index: remake.c
  3404. ===================================================================
  3405. RCS file: /sources/make/make/remake.c,v
  3406. retrieving revision 1.153
  3407. diff -u -r1.153 remake.c
  3408. --- remake.c    5 Mar 2012 14:10:45 -0000   1.153
  3409. +++ remake.c    9 Apr 2012 13:34:42 -0000
  3410. @@ -1534,12 +1534,14 @@
  3411.    const char *p2;
  3412.    unsigned int len;
  3413.    unsigned int liblen;
  3414. +  struct vbuffer vbuf;
  3415.  
  3416.    /* Information about the earliest (in the vpath sequence) match.  */
  3417.    unsigned int best_vpath = 0, best_path = 0;
  3418.  
  3419.    char **dp;
  3420.  
  3421. +  vbuffer_init(&vbuf);
  3422.    libpatterns = xstrdup (variable_expand ("$(.LIBPATTERNS)"));
  3423.  
  3424.    /* Skip the '-l'.  */
  3425. @@ -1556,28 +1558,30 @@
  3426.        static unsigned int buflen = 0;
  3427.        static int libdir_maxlen = -1;
  3428.        static unsigned int std_dirs = 0;
  3429. -      char *libbuf = variable_expand ("");
  3430. +      char *libbuf;
  3431.  
  3432.        /* Expand the pattern using LIB as a replacement.  */
  3433.        {
  3434.     char c = p[len];
  3435. -   char *p3, *p4;
  3436. +   char *percent;
  3437.  
  3438.     p[len] = '\0';
  3439. -   p3 = find_percent (p);
  3440. -   if (!p3)
  3441. +   percent = find_percent (p);
  3442. +   if (!percent)
  3443.       {
  3444.         /* Give a warning if there is no pattern.  */
  3445.         error (NILF, _(".LIBPATTERNS element '%s' is not a pattern"), p);
  3446.              p[len] = c;
  3447.         continue;
  3448.       }
  3449. -   p4 = variable_buffer_output (libbuf, p, p3-p);
  3450. -   p4 = variable_buffer_output (p4, lib, liblen);
  3451. -   p4 = variable_buffer_output (p4, p3+1, len - (p3-p));
  3452. +   vbuffer_write (&vbuf, p, percent-p);
  3453. +   vbuffer_write (&vbuf, lib, liblen);
  3454. +   vbuffer_write (&vbuf, percent+1, len - (percent-p));
  3455.     p[len] = c;
  3456.        }
  3457.  
  3458. +      libbuf = vbuf.buffer;
  3459. +
  3460.        /* Look first for 'libNAME.a' in the current directory.  */
  3461.        mtime = name_mtime (libbuf);
  3462.        if (mtime != NONEXISTENT_MTIME)
  3463. @@ -1660,5 +1664,7 @@
  3464.      }
  3465.  
  3466.    free (libpatterns);
  3467. +  vbuffer_free(&vbuf);
  3468. +
  3469.    return file;
  3470.  }
  3471. Index: variable.c
  3472. ===================================================================
  3473. RCS file: /sources/make/make/variable.c,v
  3474. retrieving revision 1.112
  3475. diff -u -r1.112 variable.c
  3476. --- variable.c  5 Mar 2012 14:10:45 -0000   1.112
  3477. +++ variable.c  9 Apr 2012 13:34:42 -0000
  3478. @@ -172,6 +172,7 @@
  3479.  static struct variable_set_list global_setlist
  3480.    = { 0, &global_variable_set, 0 };
  3481.  struct variable_set_list *current_variable_set_list = &global_setlist;
  3482. +
  3483.  
  3484.  /* Implement variables.  */
  3485.  
  3486. @@ -182,18 +183,19 @@
  3487.          variable_hash_1, variable_hash_2, variable_hash_cmp);
  3488.  }
  3489.  
  3490. -/* Define variable named NAME with value VALUE in SET.  VALUE is copied.
  3491. +/* Define variable named NAME with value VALUE in SET.  VALUE is NOT copied,
  3492. +   and after a call client must check whether the VALUE is assigned or not.
  3493.     LENGTH is the length of NAME, which does not need to be null-terminated.
  3494.     ORIGIN specifies the origin of the variable (makefile, command line
  3495.     or environment).
  3496.     If RECURSIVE is nonzero a flag is set in the variable saying
  3497.     that it should be recursively re-expanded.  */
  3498.  
  3499. -struct variable *
  3500. -define_variable_in_set (const char *name, unsigned int length,
  3501. -                        const char *value, enum variable_origin origin,
  3502. -                        int recursive, struct variable_set *set,
  3503. -                        const struct floc *flocp)
  3504. +static struct variable *
  3505. +define_variable_in_set_allocated (const char *name, unsigned int length,
  3506. +                 const char *value, enum variable_origin origin,
  3507. +                 int recursive, struct variable_set *set,
  3508. +                 const struct floc *flocp)
  3509.  {
  3510.    struct variable *v;
  3511.    struct variable **var_slot;
  3512. @@ -224,7 +226,7 @@
  3513.     {
  3514.       if (v->value != 0)
  3515.         free (v->value);
  3516. -     v->value = xstrdup (value);
  3517. +     v->value = (char *) value;
  3518.            if (flocp != 0)
  3519.              v->fileinfo = *flocp;
  3520.            else
  3521. @@ -241,7 +243,7 @@
  3522.    v->name = xstrndup (name, length);
  3523.    v->length = length;
  3524.    hash_insert_at (&set->table, v, var_slot);
  3525. -  v->value = xstrdup (value);
  3526. +  v->value = (char *) value;
  3527.    if (flocp != 0)
  3528.      v->fileinfo = *flocp;
  3529.    else
  3530. @@ -254,6 +256,8 @@
  3531.    v->per_target = 0;
  3532.    v->append = 0;
  3533.    v->private_var = 0;
  3534. +  v->volatile_var = 0;
  3535. +  v->global = set == &global_variable_set;
  3536.    v->export = v_default;
  3537.  
  3538.    v->exportable = 1;
  3539. @@ -275,6 +279,71 @@
  3540.  }
  3541.  
  3542.  
  3543. +struct variable *
  3544. +define_variable_in_set (const char *name, unsigned int length,
  3545. +                        const char *value, enum variable_origin origin,
  3546. +                        int recursive, struct variable_set *set,
  3547. +                        const struct floc *flocp)
  3548. +{
  3549. +  struct variable *v = define_variable_in_set_allocated (name, length, value,
  3550. +                            origin, recursive,
  3551. +                            set, flocp);
  3552. +  /* Check if the new value was really assigned.  */
  3553. +  if (v->value == value)
  3554. +    v->value = xstrdup (value);
  3555. +
  3556. +  return v;
  3557. +}
  3558. +
  3559. +struct variable *
  3560. +push_scoped_variable (struct variable *v, char *name, unsigned int length)
  3561. +{
  3562. +  struct variable_set *set = current_variable_set_list->set;
  3563. +  struct variable *old_var;
  3564. +  struct variable **var_slot;
  3565. +
  3566. +  v->name   = name;
  3567. +  v->length = length;
  3568. +  var_slot = (struct variable **) hash_find_slot (&set->table, v);
  3569. +
  3570. +  old_var = *var_slot;
  3571. +  if (HASH_VACANT (old_var))
  3572. +    old_var = NULL;
  3573. +
  3574. +  hash_insert_at (&set->table, v, var_slot);
  3575. +
  3576. +  v->fileinfo.filenm = NULL;
  3577. +  v->origin = o_automatic;
  3578. +  v->recursive = 0;
  3579. +  v->special = 0;
  3580. +  v->expanding = 0;
  3581. +  v->exp_count = 0;
  3582. +  v->per_target = 0;
  3583. +  v->append = 0;
  3584. +  v->private_var = 0;
  3585. +  v->volatile_var = 0;
  3586. +  v->exportable = 0;
  3587. +  v->export = v_default;
  3588. +
  3589. +  v->global = old_var ? old_var->global : 0;
  3590. +
  3591. +  return old_var;
  3592. +}
  3593. +
  3594. +void
  3595. +pop_scoped_variable (struct variable *v, struct variable *old_var)
  3596. +{
  3597. +  struct variable_set *set = current_variable_set_list->set;
  3598. +  struct variable **var_slot;
  3599. +
  3600. +  var_slot = (struct variable **) hash_find_slot (&set->table, v);
  3601. +
  3602. +  if (old_var)
  3603. +    hash_insert_at (&set->table, old_var, var_slot);
  3604. +  else
  3605. +    hash_delete_at (&set->table, var_slot);
  3606. +}
  3607. +
  3608.  /* Undefine variable named NAME in SET. LENGTH is the length of NAME, which
  3609.     does not need to be null-terminated. ORIGIN specifies the origin of the
  3610.     variable (makefile, command line or environment). */
  3611. @@ -361,7 +430,8 @@
  3612.    */
  3613.  
  3614.    if (streq (var->name, ".VARIABLES")
  3615. -      && global_variable_set.table.ht_fill != last_var_count)
  3616. +//      && global_variable_set.table.ht_fill != last_var_count
  3617. +      )
  3618.      {
  3619.        unsigned long max = EXPANSION_INCREMENT (strlen (var->value));
  3620.        unsigned long len;
  3621. @@ -381,6 +451,9 @@
  3622.              struct variable *v = *vp;
  3623.              int l = v->length;
  3624.  
  3625. +            if (!v->global)
  3626. +              continue;
  3627. +
  3628.              len += l + 1;
  3629.              if (len > max)
  3630.                {
  3631. @@ -408,26 +481,89 @@
  3632.  }
  3633.  
  3634.  
  3635. +static struct call_frame empty_call_frame;
  3636. +struct call_frame *current_call_frame = &empty_call_frame;
  3637. +
  3638. +#ifdef __GNUC__
  3639. +__inline
  3640. +#endif
  3641. +char **
  3642. +lookup_call_argument_value (const char *name, unsigned int length)
  3643. +{
  3644. +  int num = 0;
  3645. +  const char *p;
  3646. +
  3647. +  /* Hot path: a single digit.  */
  3648. +  if (length == 1
  3649. +      && (unsigned) *name - '0' < (unsigned) current_call_frame->argc)
  3650. +    return current_call_frame->argv + (*name - '0');
  3651. +
  3652. +  /* Empty name or name with leading zeroes is not numeric.  */
  3653. +  if (length == 0 || *name == '0')
  3654. +    return NULL;
  3655. +
  3656. +  for (p=name; length != 0 && ISDIGIT(*p); --length, ++p)
  3657. +    {
  3658. +      num *= 10;
  3659. +      num += *p - '0';
  3660. +    }
  3661. +
  3662. +  if (length != 0 || num >= current_call_frame->argc)
  3663. +    return NULL;
  3664. +
  3665. +  return current_call_frame->argv + num;
  3666. +}
  3667. +
  3668. +#define CALL_ARGUMENT_INIT \
  3669. +  { \
  3670. +    /* name */ "",          /* value */ "",   \
  3671. +    /* file */ { NULL, 0},  /* length */ 0,   \
  3672. +    /* recursive   */ 0, /* append      */ 0, \
  3673. +    /* conditional */ 0, /* per_target  */ 0, \
  3674. +    /* special     */ 0, /* exportable  */ 0, \
  3675. +    /* expanding   */ 0, /* private     */ 0, \
  3676. +    /* volatile    */ 1, /* global      */ 0, \
  3677. +    /* exp_count   */ 0,                      \
  3678. +    f_simple, o_automatic, v_default,         \
  3679. +  }
  3680. +
  3681.  /* Lookup a variable whose name is a string starting at NAME
  3682.     and with LENGTH chars.  NAME need not be null-terminated.
  3683.     Returns address of the 'struct variable' containing all info
  3684. -   on the variable, or nil if no such variable is defined.  */
  3685. +   on the variable, or nil if no such variable is defined.
  3686. +   In case when the variable is an argument of the current call frame,
  3687. +   the 'struct variable' refers to the shared statically allocated instance,
  3688. +   and its 'volatile_var' field is set to 1.  */
  3689.  
  3690.  struct variable *
  3691.  lookup_variable (const char *name, unsigned int length)
  3692.  {
  3693. +  static struct variable call_argument = CALL_ARGUMENT_INIT;
  3694.    const struct variable_set_list *setlist;
  3695. +  struct variable *v = NULL;
  3696.    struct variable var_key;
  3697.    int is_parent = 0;
  3698.  
  3699.    var_key.name = (char *) name;
  3700.    var_key.length = length;
  3701.  
  3702. +  if (ISDIGIT(*name))
  3703. +    {
  3704. +      char **argp = lookup_call_argument_value (name, length);
  3705. +      if (argp && *argp)
  3706. +   {
  3707. +     v = &call_argument;
  3708. +     v->value = *argp;
  3709. +     v->name = (char *) name;
  3710. +     v->length = length;
  3711. +     return v;
  3712. +   }
  3713. +    }
  3714. +
  3715.    for (setlist = current_variable_set_list;
  3716.         setlist != 0; setlist = setlist->next)
  3717.      {
  3718.        const struct variable_set *set = setlist->set;
  3719. -      struct variable *v;
  3720.  
  3721.        v = (struct variable *) hash_find_item ((struct hash_table *) &set->table, &var_key);
  3722.        if (v && (!is_parent || !v->private_var))
  3723. @@ -494,6 +630,7 @@
  3724.  
  3725.    return 0;
  3726.  }
  3727. +
  3728.  
  3729.  /* Lookup a variable whose name is a string starting at NAME
  3730.     and with LENGTH chars in set SET.  NAME need not be null-terminated.
  3731. @@ -512,6 +649,7 @@
  3732.    return (struct variable *) hash_find_item ((struct hash_table *) &set->table, &var_key);
  3733.  }
  3734.  
  3735. +
  3736.  /* Initialize FILE's variable set list.  If FILE already has a variable set
  3737.     list, the topmost variable set is left intact, but the the rest of the
  3738.     chain is replaced with FILE->parent's setlist.  If FILE is a double-colon
  3739. @@ -621,8 +759,6 @@
  3740.      }
  3741.  }
  3742.  
  3743. -/* Pop the top set off the current variable set list,
  3744. -   and free all its storage.  */
  3745.  
  3746.  struct variable_set_list *
  3747.  create_new_variable_set (void)
  3748. @@ -660,66 +796,6 @@
  3749.    free (list);
  3750.  }
  3751.  
  3752. -/* Create a new variable set and push it on the current setlist.
  3753. -   If we're pushing a global scope (that is, the current scope is the global
  3754. -   scope) then we need to "push" it the other way: file variable sets point
  3755. -   directly to the global_setlist so we need to replace that with the new one.
  3756. - */
  3757. -
  3758. -struct variable_set_list *
  3759. -push_new_variable_scope (void)
  3760. -{
  3761. -  current_variable_set_list = create_new_variable_set();
  3762. -  if (current_variable_set_list->next == &global_setlist)
  3763. -    {
  3764. -      /* It was the global, so instead of new -> &global we want to replace
  3765. -         &global with the new one and have &global -> new, with current still
  3766. -         pointing to &global  */
  3767. -      struct variable_set *set = current_variable_set_list->set;
  3768. -      current_variable_set_list->set = global_setlist.set;
  3769. -      global_setlist.set = set;
  3770. -      current_variable_set_list->next = global_setlist.next;
  3771. -      global_setlist.next = current_variable_set_list;
  3772. -      current_variable_set_list = &global_setlist;
  3773. -    }
  3774. -  return (current_variable_set_list);
  3775. -}
  3776. -
  3777. -void
  3778. -pop_variable_scope (void)
  3779. -{
  3780. -  struct variable_set_list *setlist;
  3781. -  struct variable_set *set;
  3782. -
  3783. -  /* Can't call this if there's no scope to pop!  */
  3784. -  assert(current_variable_set_list->next != NULL);
  3785. -
  3786. -  if (current_variable_set_list != &global_setlist)
  3787. -    {
  3788. -      /* We're not pointing to the global setlist, so pop this one.  */
  3789. -      setlist = current_variable_set_list;
  3790. -      set = setlist->set;
  3791. -      current_variable_set_list = setlist->next;
  3792. -    }
  3793. -  else
  3794. -    {
  3795. -      /* This set is the one in the global_setlist, but there is another global
  3796. -         set beyond that.  We want to copy that set to global_setlist, then
  3797. -         delete what used to be in global_setlist.  */
  3798. -      setlist = global_setlist.next;
  3799. -      set = global_setlist.set;
  3800. -      global_setlist.set = setlist->set;
  3801. -      global_setlist.next = setlist->next;
  3802. -      global_setlist.next_is_parent = setlist->next_is_parent;
  3803. -    }
  3804. -
  3805. -  /* Free the one we no longer need.  */
  3806. -  free (setlist);
  3807. -  hash_map (&set->table, free_variable_name_and_value);
  3808. -  hash_free (&set->table, 1);
  3809. -  free (set);
  3810. -}
  3811. -
  3812.  /* Merge FROM_SET into TO_SET, freeing unused storage in FROM_SET.  */
  3813.  
  3814.  static void
  3815. @@ -966,6 +1042,7 @@
  3816.    struct variable makelevel_key;
  3817.    char **result_0;
  3818.    char **result;
  3819. +  struct vbuffer vbuf;
  3820.  
  3821.    if (file == 0)
  3822.      set_list = current_variable_set_list;
  3823. @@ -1053,6 +1130,8 @@
  3824.  
  3825.    result = result_0 = xmalloc ((table.ht_fill + 2) * sizeof (char *));
  3826.  
  3827. +  vbuffer_init (&vbuf);
  3828. +
  3829.    v_slot = (struct variable **) table.ht_vec;
  3830.    v_end = v_slot + table.ht_size;
  3831.    for ( ; v_slot < v_end; v_slot++)
  3832. @@ -1060,32 +1139,30 @@
  3833.        {
  3834.     struct variable *v = *v_slot;
  3835.  
  3836. +   vbuffer_reset (&vbuf);
  3837. +
  3838. +   vbuffer_write (&vbuf, v->name, -1);
  3839. +   vbuffer_write (&vbuf, "=", 1);
  3840. +
  3841.     /* If V is recursively expanded and didn't come from the environment,
  3842.        expand its value.  If it came from the environment, it should
  3843.        go back into the environment unchanged.  */
  3844.     if (v->recursive
  3845.         && v->origin != o_env && v->origin != o_env_override)
  3846. -     {
  3847. -       char *value = recursively_expand_for_file (v, file);
  3848. -#ifdef WINDOWS32
  3849. -       if (strcmp(v->name, "Path") == 0 ||
  3850. -       strcmp(v->name, "PATH") == 0)
  3851. -         convert_Path_to_windows32(value, ';');
  3852. -#endif
  3853. -       *result++ = xstrdup (concat (3, v->name, "=", value));
  3854. -       free (value);
  3855. -     }
  3856. +     vbuffer_expand_variable_for_file (&vbuf, v, file);
  3857.     else
  3858. -     {
  3859. +     vbuffer_write (&vbuf, v->value, -1);
  3860. +
  3861.  #ifdef WINDOWS32
  3862. -            if (strcmp(v->name, "Path") == 0 ||
  3863. -                strcmp(v->name, "PATH") == 0)
  3864. -              convert_Path_to_windows32(v->value, ';');
  3865. +   if (strcmp(v->name, "Path") == 0 ||
  3866. +       strcmp(v->name, "PATH") == 0)
  3867. +     convert_Path_to_windows32(value, ';');
  3868.  #endif
  3869. -       *result++ = xstrdup (concat (3, v->name, "=", v->value));
  3870. -     }
  3871. +   *result++ = xstrdup (vbuf.buffer);
  3872.        }
  3873.  
  3874. +  vbuffer_free (&vbuf);
  3875. +
  3876.    *result = xmalloc (100);
  3877.    sprintf (*result, "%s=%u", MAKELEVEL_NAME, makelevel + 1);
  3878.    *++result = 0;
  3879. @@ -1116,20 +1193,14 @@
  3880.  char *
  3881.  shell_result (const char *p)
  3882.  {
  3883. -  char *buf;
  3884. -  unsigned int len;
  3885. +  struct vbuffer vbuf;
  3886.    char *args[2];
  3887. -  char *result;
  3888. -
  3889. -  install_variable_buffer (&buf, &len);
  3890.  
  3891.    args[0] = (char *) p;
  3892.    args[1] = NULL;
  3893. -  variable_buffer_output (func_shell_base (variable_buffer, args, 0), "\0", 1);
  3894. -  result = strdup (variable_buffer);
  3895. +  func_shell_base (vbuffer_init(&vbuf), args, 0);
  3896.  
  3897. -  restore_variable_buffer (buf, len);
  3898. -  return result;
  3899. +  return vbuf.buffer;
  3900.  }
  3901.  
  3902.  /* Given a variable, a value, and a flavor, define the variable.
  3903. @@ -1145,6 +1216,7 @@
  3904.    struct variable *v;
  3905.    int append = 0;
  3906.    int conditional = 0;
  3907. +  unsigned int varlen = strlen (varname);
  3908.  
  3909.    /* Calculate the variable's new value in VALUE.  */
  3910.  
  3911. @@ -1174,7 +1246,7 @@
  3912.      case f_conditional:
  3913.        /* A conditional variable definition "var ?= value".
  3914.           The value is set IFF the variable is not defined yet. */
  3915. -      v = lookup_variable (varname, strlen (varname));
  3916. +      v = lookup_variable (varname, varlen);
  3917.        if (v)
  3918.          return v->special ? set_special_var (v) : v;
  3919.  
  3920. @@ -1193,7 +1265,7 @@
  3921.          if (target_var)
  3922.            {
  3923.              append = 1;
  3924. -            v = lookup_variable_in_set (varname, strlen (varname),
  3925. +            v = lookup_variable_in_set (varname, varlen,
  3926.                                          current_variable_set_list->set);
  3927.  
  3928.              /* Don't append from the global set if a previous non-appending
  3929. @@ -1202,7 +1274,7 @@
  3930.                append = 0;
  3931.            }
  3932.          else
  3933. -          v = lookup_variable (varname, strlen (varname));
  3934. +          v = lookup_variable (varname, varlen);
  3935.  
  3936.          if (v == 0)
  3937.            {
  3938. @@ -1274,7 +1346,7 @@
  3939.              if (*tp == '\\')
  3940.                *tp = '/';
  3941.  
  3942. -     v = define_variable_loc (varname, strlen (varname),
  3943. +     v = define_variable_loc (varname, varlen,
  3944.                                     shellpath, origin, flavor == f_recursive,
  3945.                                     flocp);
  3946.     }
  3947. @@ -1314,12 +1386,12 @@
  3948.                  if (*tp == '\\')
  3949.                    *tp = '/';
  3950.  
  3951. -         v = define_variable_loc (varname, strlen (varname),
  3952. +         v = define_variable_loc (varname, varlen,
  3953.                                         shellpath, origin,
  3954.                                         flavor == f_recursive, flocp);
  3955.         }
  3956.       else
  3957. -       v = lookup_variable (varname, strlen (varname));
  3958. +       v = lookup_variable (varname, varlen);
  3959.  
  3960.       free (path_string);
  3961.     }
  3962. @@ -1338,7 +1410,7 @@
  3963.  
  3964.        if (find_and_set_default_shell (p))
  3965.          {
  3966. -          v = define_variable_in_set (varname, strlen (varname), default_shell,
  3967. +          v = define_variable_in_set (varname, varlen, default_shell,
  3968.                                        origin, flavor == f_recursive,
  3969.                                        (target_var
  3970.                                         ? current_variable_set_list->set
  3971. @@ -1354,7 +1426,7 @@
  3972.  
  3973.            if (find_and_set_default_shell (alloc_value))
  3974.              {
  3975. -              v = define_variable_in_set (varname, strlen (varname), p,
  3976. +              v = define_variable_in_set (varname, varlen, p,
  3977.                                            origin, flavor == f_recursive,
  3978.                                            (target_var
  3979.                                             ? current_variable_set_list->set
  3980. @@ -1363,7 +1435,7 @@
  3981.                no_default_sh_exe = 0;
  3982.              }
  3983.            else
  3984. -            v = lookup_variable (varname, strlen (varname));
  3985. +            v = lookup_variable (varname, varlen);
  3986.  
  3987.            if (tp)
  3988.              free (tp);
  3989. @@ -1372,17 +1444,29 @@
  3990.    else
  3991.  #endif
  3992.  
  3993. -  /* If we are defining variables inside an $(eval ...), we might have a
  3994. -     different variable context pushed, not the global context (maybe we're
  3995. -     inside a $(call ...) or something.  Since this function is only ever
  3996. -     invoked in places where we want to define globally visible variables,
  3997. -     make sure we define this variable in the global set.  */
  3998. -
  3999. -  v = define_variable_in_set (varname, strlen (varname), p,
  4000. -                              origin, flavor == f_recursive,
  4001. -                              (target_var
  4002. -                               ? current_variable_set_list->set : NULL),
  4003. -                              flocp);
  4004. +    {
  4005. +      /* If we are defining variables inside an $(eval ...), we might have a
  4006. +    different variable context pushed, not the global context (maybe we're
  4007. +    inside a $(call ...) or something.  Since this function is only ever
  4008. +    invoked in places where we want to define globally visible variables,
  4009. +    make sure we define this variable in the global set.  */
  4010. +
  4011. +      v = define_variable_in_set_allocated (varname, varlen, alloc_value,
  4012. +                       origin, flavor == f_recursive,
  4013. +                       (target_var
  4014. +                        ? current_variable_set_list->set
  4015. +                        : NULL),
  4016. +                       flocp);
  4017. +
  4018. +      if (v->value == alloc_value)
  4019. +   {
  4020. +     if (!alloc_value)
  4021. +       v->value = xstrdup (p);
  4022. +     else
  4023. +       alloc_value = NULL;
  4024. +   }
  4025. +    }
  4026. +
  4027.    v->append = append;
  4028.    v->conditional = conditional;
  4029.  
  4030. Index: variable.h
  4031. ===================================================================
  4032. RCS file: /sources/make/make/variable.h,v
  4033. retrieving revision 1.51
  4034. diff -u -r1.51 variable.h
  4035. --- variable.h  5 Mar 2012 14:10:45 -0000   1.51
  4036. +++ variable.h  9 Apr 2012 13:34:42 -0000
  4037. @@ -44,9 +44,11 @@
  4038.     Each bucket of the hash table is a chain of these,
  4039.     chained through 'next'.  */
  4040.  
  4041. -#define EXP_COUNT_BITS  15      /* This gets all the bitfields into 32 bits */
  4042. +#define EXP_COUNT_BITS  14      /* This gets all the bitfields into 32 bits */
  4043.  #define EXP_COUNT_MAX   ((1<<EXP_COUNT_BITS)-1)
  4044.  
  4045. +#define MAX_ALLOCA_SIZE 1024
  4046. +
  4047.  struct variable
  4048.    {
  4049.      char *name;            /* Variable name.  */
  4050. @@ -64,6 +66,10 @@
  4051.      unsigned int expanding:1;  /* Nonzero if currently being expanded.  */
  4052.      unsigned int private_var:1; /* Nonzero avoids inheritance of this
  4053.                                     target-specific variable.  */
  4054. +    unsigned int volatile_var:1;/* Nonzero if the state can change across
  4055. +                  certain function calls.  */
  4056. +    unsigned int global:1;      /* Nonzero if this should be included in
  4057. +                  $(.VARIABLES) list.  */
  4058.      unsigned int exp_count:EXP_COUNT_BITS;
  4059.                                  /* If >1, allow this many self-referential
  4060.                                     expansions.  */
  4061. @@ -107,44 +113,80 @@
  4062.      struct variable variable;
  4063.    };
  4064.  
  4065. -extern char *variable_buffer;
  4066. +/* Structure used to hold the result of variable expansion.  */
  4067. +
  4068. +struct vbuffer
  4069. +  {
  4070. +    char *ptr;    /* Current position pointing inside the buffer.  */
  4071. +    char *buffer; /* Start of the entire buffer.  */
  4072. +    size_t size;  /* Size of the allocated buffer.  */
  4073. +  };
  4074. +
  4075. +struct call_frame
  4076. +  {
  4077. +    int argc;
  4078. +    char **argv;
  4079. +  };
  4080. +
  4081.  extern struct variable_set_list *current_variable_set_list;
  4082.  extern struct variable *default_goal_var;
  4083.  
  4084. +extern struct call_frame *current_call_frame;
  4085. +
  4086. +struct vbuffer *vbuffer_init  (struct vbuffer *vbuf);
  4087. +struct vbuffer *vbuffer_reset (struct vbuffer *vbuf);
  4088. +
  4089. +#define vbuffer_free(vbuf) \
  4090. +  free ((vbuf)->buffer)
  4091. +
  4092. +size_t vbuffer_reserve (struct vbuffer *o, size_t len);
  4093. +
  4094. +size_t vbuffer_write (struct vbuffer *o, const char *str, ssize_t len);
  4095. +size_t vbuffer_unwrite (struct vbuffer *o, ssize_t len);
  4096. +
  4097. +size_t vbuffer_expand (struct vbuffer *o, char *str, ssize_t len);
  4098. +size_t vbuffer_expand_for_file (struct vbuffer *o, char *str, ssize_t len,
  4099. +               struct file *file);
  4100. +
  4101. +size_t vbuffer_expand_ro (struct vbuffer *o, const char *str, ssize_t len);
  4102. +size_t vbuffer_expand_ro_for_file (struct vbuffer *o, const char *str,
  4103. +                  ssize_t len, struct file *file);
  4104. +
  4105. +#define vbuffer_expand_variable(o, v) \
  4106. +  vbuffer_expand_variable_for_file (o, v, NULL)
  4107. +size_t vbuffer_expand_variable_for_file (struct vbuffer *o,
  4108. +                                         struct variable *v,
  4109. +                                         struct file *file);
  4110. +
  4111. +struct vbuffer *install_new_expansion_vbuffer (void);
  4112. +void restore_expansion_vbuffer (struct vbuffer *old_vbuf);
  4113. +
  4114.  /* expand.c */
  4115. -char *variable_buffer_output (char *ptr, const char *string, unsigned int length);
  4116. +char *expand_argument (const char *str, const char *end);
  4117.  char *variable_expand (const char *line);
  4118.  char *variable_expand_for_file (const char *line, struct file *file);
  4119. +char *allocated_variable_expand (const char *line);
  4120.  char *allocated_variable_expand_for_file (const char *line, struct file *file);
  4121. -#define    allocated_variable_expand(line) \
  4122. -  allocated_variable_expand_for_file (line, (struct file *) 0)
  4123. -char *expand_argument (const char *str, const char *end);
  4124. -char *variable_expand_string (char *line, const char *string, long length);
  4125. -void install_variable_buffer (char **bufp, unsigned int *lenp);
  4126. -void restore_variable_buffer (char *buf, unsigned int len);
  4127. +#define recursively_expand(v)   recursively_expand_for_file (v, NULL)
  4128. +char *recursively_expand_for_file (struct variable *v, struct file *file);
  4129.  
  4130.  /* function.c */
  4131. -int handle_function (char **op, const char **stringp);
  4132. +int handle_function (struct vbuffer *vbuf, char **stringp);
  4133.  int pattern_matches (const char *pattern, const char *percent, const char *str);
  4134. -char *subst_expand (char *o, const char *text, const char *subst,
  4135. -                    const char *replace, unsigned int slen, unsigned int rlen,
  4136. -                    int by_word);
  4137. -char *patsubst_expand_pat (char *o, const char *text, const char *pattern,
  4138. -                           const char *replace, const char *pattern_percent,
  4139. -                           const char *replace_percent);
  4140. -char *patsubst_expand (char *o, const char *text, char *pattern, char *replace);
  4141. -char *func_shell_base (char *o, char **argv, int trim_newlines);
  4142. -
  4143. -
  4144. -/* expand.c */
  4145. -char *recursively_expand_for_file (struct variable *v, struct file *file);
  4146. -#define recursively_expand(v)   recursively_expand_for_file (v, NULL)
  4147. +size_t subst_expand (struct vbuffer *vbuf, const char *text, const char *subst,
  4148. +                     const char *replace, unsigned int slen, unsigned int rlen,
  4149. +                     int by_word);
  4150. +size_t patsubst_expand_pat (struct vbuffer *vbuf, const char *text,
  4151. +                            const char *pattern, const char *replace,
  4152. +                            const char *pattern_percent,
  4153. +                            const char *replace_percent);
  4154. +size_t patsubst_expand (struct vbuffer *vbuf, const char *text, char *pattern,
  4155. +                        char *replace);
  4156. +size_t func_shell_base (struct vbuffer *vbuf, char **argv, int trim_newlines);
  4157.  
  4158.  /* variable.c */
  4159.  struct variable_set_list *create_new_variable_set (void);
  4160.  void free_variable_set (struct variable_set_list *);
  4161. -struct variable_set_list *push_new_variable_scope (void);
  4162. -void pop_variable_scope (void);
  4163.  void define_automatic_variables (void);
  4164.  void initialize_file_variables (struct file *file, int reading);
  4165.  void print_file_variables (const struct file *file);
  4166. @@ -167,10 +209,11 @@
  4167.  void hash_init_function_table (void);
  4168.  void define_new_function(const struct floc *flocp,
  4169.                           const char *name, int min, int max, int expand,
  4170. -                         char *(*func)(char *, char **, const char *));
  4171. +                         size_t (*func)(struct vbuffer *, char **, const char *));
  4172.  struct variable *lookup_variable (const char *name, unsigned int length);
  4173.  struct variable *lookup_variable_in_set (const char *name, unsigned int length,
  4174.                                           const struct variable_set *set);
  4175. +char **lookup_call_argument_value (const char *name, unsigned int length);
  4176.  
  4177.  struct variable *define_variable_in_set (const char *name, unsigned int length,
  4178.                                           const char *value,
  4179. @@ -207,6 +250,10 @@
  4180.  #define define_variable_for_file(n,l,v,o,r,f) \
  4181.            define_variable_in_set((n),(l),(v),(o),(r),(f)->variables->set,NILF)
  4182.  
  4183. +struct variable *push_scoped_variable (struct variable *v,
  4184. +                      char *name, unsigned int length);
  4185. +void pop_scoped_variable (struct variable *v, struct variable *old_var);
  4186. +
  4187.  void undefine_variable_in_set (const char *name, unsigned int length,
  4188.                                 enum variable_origin origin,
  4189.                                 struct variable_set *set);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement