Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ### Eclipse Workspace Patch 1.0
- #P make-patched
- Index: expand.c
- ===================================================================
- RCS file: /sources/make/make/expand.c,v
- retrieving revision 1.62
- diff -u -r1.62 expand.c
- --- expand.c 5 Mar 2012 14:10:43 -0000 1.62
- +++ expand.c 9 Apr 2012 13:34:41 -0000
- @@ -16,8 +16,6 @@
- #include "make.h"
- -#include <assert.h>
- -
- #include "filedef.h"
- #include "job.h"
- #include "commands.h"
- @@ -30,125 +28,121 @@
- /* The next two describe the variable output buffer.
- This buffer is used to hold the variable-expansion of a line of the
- - makefile. It is made bigger with realloc whenever it is too small.
- - variable_buffer_length is the size currently allocated.
- - variable_buffer is the address of the buffer.
- + makefile. It is made bigger with realloc whenever it is too small. */
- +
- +static struct vbuffer *expansion_vbuf;
- - For efficiency, it's guaranteed that the buffer will always have
- +/* For efficiency, it's guaranteed that the buffer will always have
- VARIABLE_BUFFER_ZONE extra bytes allocated. This allows you to add a few
- extra chars without having to call a function. Note you should never use
- these bytes unless you're _sure_ you have room (you know when the buffer
- length was last checked. */
- +#define VARIABLE_BUFFER_ZONE (2 * sizeof (char *))
- -#define VARIABLE_BUFFER_ZONE 5
- +struct vbuffer *
- +vbuffer_init (struct vbuffer *vbuf)
- +{
- + vbuf->size = 100;
- + vbuf->ptr = vbuf->buffer = xmalloc (vbuf->size);
- -static unsigned int variable_buffer_length;
- -char *variable_buffer;
- + *vbuf->ptr = '\0';
- -/* Subroutine of variable_expand and friends:
- - The text to add is LENGTH chars starting at STRING to the variable_buffer.
- - The text is added to the buffer at PTR, and the updated pointer into
- - the buffer is returned as the value. Thus, the value returned by
- - each call to variable_buffer_output should be the first argument to
- - the following call. */
- + return vbuf;
- +}
- -char *
- -variable_buffer_output (char *ptr, const char *string, unsigned int length)
- +struct vbuffer *
- +vbuffer_reset (struct vbuffer *vbuf)
- {
- - register unsigned int newlen = length + (ptr - variable_buffer);
- + vbuf->ptr = vbuf->buffer;
- - if ((newlen + VARIABLE_BUFFER_ZONE) > variable_buffer_length)
- - {
- - unsigned int offset = ptr - variable_buffer;
- - variable_buffer_length = (newlen + 100 > 2 * variable_buffer_length
- - ? newlen + 100
- - : 2 * variable_buffer_length);
- - variable_buffer = xrealloc (variable_buffer, variable_buffer_length);
- - ptr = variable_buffer + offset;
- - }
- + *vbuf->ptr = '\0';
- - memcpy (ptr, string, length);
- - return ptr + length;
- + return vbuf;
- }
- -/* Return a pointer to the beginning of the variable buffer. */
- +#ifdef __GNUC__
- +__inline
- +#endif
- +static void
- +vbuffer_grow (struct vbuffer *vbuf, size_t newlen)
- +{
- + size_t oldlen = vbuf->size;
- + size_t offset = vbuf->ptr - vbuf->buffer;
- +
- + newlen = newlen + 100 > 2 * oldlen
- + ? newlen + 100 : 2 * oldlen;
- +
- + vbuf->buffer = xrealloc (vbuf->buffer, newlen);
- + vbuf->ptr = vbuf->buffer + offset;
- + vbuf->size = newlen;
- +}
- -static char *
- -initialize_variable_output (void)
- +#ifdef __GNUC__
- +__inline
- +#endif
- +size_t
- +vbuffer_reserve (struct vbuffer *o, size_t length)
- {
- - /* If we don't have a variable output buffer yet, get one. */
- + size_t newoff = (o->ptr - o->buffer) + length;
- - if (variable_buffer == 0)
- - {
- - variable_buffer_length = 200;
- - variable_buffer = xmalloc (variable_buffer_length);
- - variable_buffer[0] = '\0';
- - }
- + if ((newoff + VARIABLE_BUFFER_ZONE) > o->size)
- + vbuffer_grow (o, newoff);
- - return variable_buffer;
- + return o->size - newoff;
- }
- -
- -/* Recursively expand V. The returned string is malloc'd. */
- -static char *allocated_variable_append (const struct variable *v);
- +/* Writes byte stream pointed by STR into VBUF.
- + The optional LEN argument can be used to limit the amount of bytes to copy.
- + Otherwise (if LEN is a negative number) STR is treated as a null-terminated
- + string and copied accordingly.
- -char *
- -recursively_expand_for_file (struct variable *v, struct file *file)
- + Returns the actual number of bytes copied,
- + that is LEN argument if it is non-negative and strlen (STR) otherwise.
- +
- + As like all the other vbuffer methods it leaves the internal buffer
- + of the VBUF null-terminated. */
- +
- +#ifdef __GNUC__
- +__inline
- +#endif
- +size_t
- +vbuffer_write (struct vbuffer *o, const char *str, ssize_t len)
- {
- - char *value;
- - const struct floc *this_var;
- - const struct floc **saved_varp;
- - struct variable_set_list *save = 0;
- - int set_reading = 0;
- + size_t length = len < 0 ? strlen (str) : (size_t) len;
- - /* Don't install a new location if this location is empty.
- - This can happen for command-line variables, builtin variables, etc. */
- - saved_varp = expanding_var;
- - if (v->fileinfo.filenm)
- - {
- - this_var = &v->fileinfo;
- - expanding_var = &this_var;
- - }
- + if (length == 0)
- + return 0;
- - /* If we have no other file-reading context, use the variable's context. */
- - if (!reading_file)
- - {
- - set_reading = 1;
- - reading_file = &v->fileinfo;
- - }
- + vbuffer_reserve (o, length);
- - if (v->expanding)
- - {
- - if (!v->exp_count)
- - /* Expanding V causes infinite recursion. Lose. */
- - fatal (*expanding_var,
- - _("Recursive variable '%s' references itself (eventually)"),
- - v->name);
- - --v->exp_count;
- - }
- + memcpy (o->ptr, str, length);
- + o->ptr += length;
- - if (file)
- - {
- - save = current_variable_set_list;
- - current_variable_set_list = file->variables;
- - }
- + *o->ptr = '\0';
- - v->expanding = 1;
- - if (v->append)
- - value = allocated_variable_append (v);
- - else
- - value = allocated_variable_expand (v->value);
- - v->expanding = 0;
- + return length;
- +}
- - if (set_reading)
- - reading_file = 0;
- +/* Moves the pointer of the VBUF back on the LEN bytes.
- + If LEN is negative, or if moving the pointer would lead to an underflow,
- + then sets the pointer to the start of the buffer.
- - if (file)
- - current_variable_set_list = save;
- + Returns the actual number of discarded bytes. */
- - expanding_var = saved_varp;
- +size_t
- +vbuffer_unwrite (struct vbuffer *o, ssize_t len)
- +{
- + size_t oldoff = o->ptr - o->buffer;
- + size_t length = len < 0 ? oldoff : (size_t) len;
- - return value;
- + if (length > oldoff)
- + length = oldoff;
- +
- + o->ptr -= length;
- +
- + *o->ptr = '\0';
- +
- + return length;
- }
- /* Expand a simple reference to variable NAME, which is LENGTH chars long. */
- @@ -156,11 +150,10 @@
- #ifdef __GNUC__
- __inline
- #endif
- -static char *
- -reference_variable (char *o, const char *name, unsigned int length)
- +static size_t
- +expand_variable_reference (struct vbuffer *o, const char *name, size_t length)
- {
- struct variable *v;
- - char *value;
- v = lookup_variable (name, length);
- @@ -169,62 +162,117 @@
- /* If there's no variable by that name or it has no value, stop now. */
- if (v == 0 || (*v->value == '\0' && !v->append))
- - return o;
- -
- - value = (v->recursive ? recursively_expand (v) : v->value);
- -
- - o = variable_buffer_output (o, value, strlen (value));
- + return 0;
- if (v->recursive)
- - free (value);
- -
- - return o;
- + return vbuffer_expand_variable (o, v);
- + else
- + return vbuffer_write (o, v->value, -1);
- }
- -
- -/* Scan STRING for variable references and expansion-function calls. Only
- - LENGTH bytes of STRING are actually scanned. If LENGTH is -1, scan until
- - a null byte is found.
- -
- - Write the results to LINE, which must point into 'variable_buffer'. If
- - LINE is NULL, start at the beginning of the buffer.
- - Return a pointer to LINE, or to the beginning of the buffer if LINE is
- - NULL.
- - */
- -char *
- -variable_expand_string (char *line, const char *string, long length)
- +
- +
- +#ifdef __GNUC__
- +__inline
- +#endif
- +static int
- +handle_subst_reference (struct vbuffer *o, char *beg, char *end)
- {
- + size_t result = 0;
- struct variable *v;
- - const char *p, *p1;
- - char *save;
- - char *o;
- - unsigned int line_offset;
- -
- - if (!line)
- - line = initialize_variable_output();
- - o = line;
- - line_offset = line - variable_buffer;
- + const char *subst_beg, *subst_end, *replace_beg, *replace_end;
- + char *colon = lindex (beg, end, ':');
- - if (length == 0)
- + if (colon == 0)
- + return -1;
- +
- + subst_beg = colon + 1;
- + subst_end = lindex (subst_beg, end, '=');
- + if (subst_end == 0)
- + /* There is no = in sight. Punt on the substitution reference and treat
- + this as a variable name containing a colon. */
- + return -1;
- +
- + /* This looks like a valid substitution reference: $(FOO:A=B). */
- + replace_beg = subst_end + 1;
- + replace_end = end;
- +
- + /* Extract the variable name before the colon and look up that variable. */
- + v = lookup_variable (beg, colon - beg);
- + if (v == 0)
- + warn_undefined (beg, colon - beg);
- +
- + /* If the variable is not empty, perform the substitution. */
- + if (v != 0 && *v->value != '\0')
- {
- - variable_buffer_output (o, "", 1);
- - return (variable_buffer);
- + char *pattern, *replace, *ppercent, *rpercent;
- + char *value = (v->recursive
- + ? recursively_expand(v)
- + : v->value);
- +
- + /* Copy the pattern and the replacement. Add in an extra % at the
- + beginning to use in case there isn't one in the pattern. */
- + pattern = alloca (subst_end - subst_beg + 2);
- + *(pattern++) = '%';
- + memcpy (pattern, subst_beg, subst_end - subst_beg);
- + pattern[subst_end - subst_beg] = '\0';
- +
- + replace = alloca (replace_end - replace_beg + 2);
- + *(replace++) = '%';
- + memcpy (replace, replace_beg, replace_end - replace_beg);
- + replace[replace_end - replace_beg] = '\0';
- +
- + /* Look for %. Set the percent pointers properly
- + based on whether we find one or not. */
- + ppercent = find_percent (pattern);
- + if (ppercent)
- + {
- + ++ppercent;
- + rpercent = find_percent (replace);
- + if (rpercent)
- + ++rpercent;
- + }
- + else
- + {
- + ppercent = pattern--;
- + rpercent = replace--;
- + }
- +
- + *o->ptr = '\0';
- +
- + result = patsubst_expand_pat (o, value,
- + pattern, replace, ppercent, rpercent);
- +
- + if (v->recursive)
- + free (value);
- }
- - /* We need a copy of STRING: due to eval, it's possible that it will get
- - freed as we process it (it might be the value of a variable that's reset
- - for example). Also having a nil-terminated string is handy. */
- - save = length < 0 ? xstrdup (string) : xstrndup (string, length);
- - p = save;
- + return result;
- +}
- +size_t
- +vbuffer_expand (struct vbuffer *o, char *str, ssize_t len)
- +{
- + size_t result = 0;
- + char *p, *p1;
- +
- + if (len == 0)
- + return 0;
- +
- + if (len > 0)
- + str[len] = '\0';
- +
- + p = str;
- while (1)
- {
- /* Copy all following uninteresting chars all at once to the
- - variable output buffer, and skip them. Uninteresting chars end
- + variable output buffer, and skip them. Uninteresting chars end
- at the next $ or the end of the input. */
- p1 = strchr (p, '$');
- - o = variable_buffer_output (o, p, p1 != 0 ? (unsigned int)(p1 - p) : strlen (p) + 1);
- + /* In case when P1 is nil,
- + 'vbuffer_write' writes the whole string pointed by P. */
- + result += vbuffer_write (o, p, p1 ? p1 - p : -1);
- if (p1 == 0)
- break;
- @@ -236,27 +284,23 @@
- {
- case '$':
- /* $$ seen means output one $ to the variable output buffer. */
- - o = variable_buffer_output (o, p, 1);
- + result += vbuffer_write (o, p, 1);
- break;
- case '(':
- case '{':
- /* $(...) or ${...} is the general case of substitution. */
- {
- + int handle_ret;
- char openparen = *p;
- char closeparen = (openparen == '(') ? ')' : '}';
- - const char *begp;
- - const char *beg = p + 1;
- - char *op;
- - char *abeg = NULL;
- - const char *end, *colon;
- -
- - op = o;
- - begp = p;
- - if (handle_function (&op, &begp))
- + char *beg = p + 1;
- + char *end;
- +
- + handle_ret = handle_function (o, &p);
- + if (handle_ret >= 0)
- {
- - o = op;
- - p = begp;
- + result += handle_ret;
- break;
- }
- @@ -265,8 +309,8 @@
- end = strchr (beg, closeparen);
- if (end == 0)
- - /* Unterminated variable reference. */
- - fatal (*expanding_var, _("unterminated variable reference"));
- + fatal (*expanding_var, _("unterminated variable reference"));
- +
- p1 = lindex (beg, end, '$');
- if (p1 != 0)
- {
- @@ -285,102 +329,41 @@
- such as '$($(a)'. */
- if (count < 0)
- {
- - abeg = expand_argument (beg, p); /* Expand the name. */
- - beg = abeg;
- - end = strchr (beg, '\0');
- + /* Expand the name.
- + As a little optimization we reuse the same vbuffer. */
- + size_t name_len = vbuffer_expand (o, beg, p - beg);
- + *p = closeparen;
- +
- + /* We don't use 'vbuffer_unwrite' here because it would
- + reset the first byte of the computed name to nil. */
- + o->ptr -= name_len;
- +
- + beg = o->ptr;
- + end = beg + name_len;
- +
- }
- }
- else
- /* Advance P to the end of this reference. After we are
- - finished expanding this one, P will be incremented to
- - continue the scan. */
- + finished expanding this one, P will be incremented to
- + continue the scan. */
- p = end;
- /* This is not a reference to a built-in function and
- any variable references inside are now expanded.
- Is the resultant text a substitution reference? */
- - colon = lindex (beg, end, ':');
- - if (colon)
- + handle_ret = handle_subst_reference (o, beg, end);
- + if (handle_ret >= 0)
- {
- - /* This looks like a substitution reference: $(FOO:A=B). */
- - const char *subst_beg, *subst_end, *replace_beg, *replace_end;
- -
- - subst_beg = colon + 1;
- - subst_end = lindex (subst_beg, end, '=');
- - if (subst_end == 0)
- - /* There is no = in sight. Punt on the substitution
- - reference and treat this as a variable name containing
- - a colon, in the code below. */
- - colon = 0;
- - else
- - {
- - replace_beg = subst_end + 1;
- - replace_end = end;
- -
- - /* Extract the variable name before the colon
- - and look up that variable. */
- - v = lookup_variable (beg, colon - beg);
- - if (v == 0)
- - warn_undefined (beg, colon - beg);
- -
- - /* If the variable is not empty, perform the
- - substitution. */
- - if (v != 0 && *v->value != '\0')
- - {
- - char *pattern, *replace, *ppercent, *rpercent;
- - char *value = (v->recursive
- - ? recursively_expand (v)
- - : v->value);
- -
- - /* Copy the pattern and the replacement. Add in an
- - extra % at the beginning to use in case there
- - isn't one in the pattern. */
- - pattern = alloca (subst_end - subst_beg + 2);
- - *(pattern++) = '%';
- - memcpy (pattern, subst_beg, subst_end - subst_beg);
- - pattern[subst_end - subst_beg] = '\0';
- -
- - replace = alloca (replace_end - replace_beg + 2);
- - *(replace++) = '%';
- - memcpy (replace, replace_beg,
- - replace_end - replace_beg);
- - replace[replace_end - replace_beg] = '\0';
- -
- - /* Look for %. Set the percent pointers properly
- - based on whether we find one or not. */
- - ppercent = find_percent (pattern);
- - if (ppercent)
- - {
- - ++ppercent;
- - rpercent = find_percent (replace);
- - if (rpercent)
- - ++rpercent;
- - }
- - else
- - {
- - ppercent = pattern;
- - rpercent = replace;
- - --pattern;
- - --replace;
- - }
- -
- - o = patsubst_expand_pat (o, value, pattern, replace,
- - ppercent, rpercent);
- -
- - if (v->recursive)
- - free (value);
- - }
- - }
- + result += handle_ret;
- + break;
- }
- - if (colon == 0)
- - /* This is an ordinary variable reference.
- - Look up the value of the variable. */
- - o = reference_variable (o, beg, end - beg);
- -
- - if (abeg)
- - free (abeg);
- + /* This is an ordinary variable reference.
- + Look up the value of the variable. */
- + result += expand_variable_reference (o, beg, end - beg);
- + *o->ptr = '\0';
- }
- break;
- @@ -393,7 +376,7 @@
- /* A $ followed by a random char is a variable reference:
- $a is equivalent to $(a). */
- - o = reference_variable (o, p, 1);
- + result += expand_variable_reference (o, p, 1);
- break;
- }
- @@ -404,69 +387,19 @@
- ++p;
- }
- - free (save);
- -
- - variable_buffer_output (o, "", 1);
- - return (variable_buffer + line_offset);
- -}
- -
- -/* Scan LINE for variable references and expansion-function calls.
- - Build in 'variable_buffer' the result of expanding the references and calls.
- - Return the address of the resulting string, which is null-terminated
- - and is valid only until the next time this function is called. */
- -
- -char *
- -variable_expand (const char *line)
- -{
- - return variable_expand_string(NULL, line, (long)-1);
- -}
- -
- -/* Expand an argument for an expansion function.
- - The text starting at STR and ending at END is variable-expanded
- - into a null-terminated string that is returned as the value.
- - This is done without clobbering 'variable_buffer' or the current
- - variable-expansion that is in progress. */
- -
- -char *
- -expand_argument (const char *str, const char *end)
- -{
- - char *tmp, *alloc = NULL;
- - char *r;
- -
- - if (str == end)
- - return xstrdup("");
- -
- - if (!end || *end == '\0')
- - return allocated_variable_expand (str);
- -
- - if (end - str + 1 > 1000)
- - tmp = alloc = xmalloc (end - str + 1);
- - else
- - tmp = alloca (end - str + 1);
- -
- - memcpy (tmp, str, end - str);
- - tmp[end - str] = '\0';
- -
- - r = allocated_variable_expand (tmp);
- -
- - if (alloc)
- - free (alloc);
- + return result;
- - return r;
- }
- -
- -/* Expand LINE for FILE. Error messages refer to the file and line where
- - FILE's commands were found. Expansion uses FILE's variable set list. */
- -char *
- -variable_expand_for_file (const char *line, struct file *file)
- -{
- - char *result;
- +size_t
- +vbuffer_expand_for_file (struct vbuffer *o, char *str, ssize_t len,
- + struct file *file) {
- + size_t result = 0;
- struct variable_set_list *savev;
- const struct floc *savef;
- if (file == 0)
- - return variable_expand (line);
- + return vbuffer_expand (o, str, len);
- savev = current_variable_set_list;
- current_variable_set_list = file->variables;
- @@ -477,124 +410,251 @@
- else
- reading_file = 0;
- - result = variable_expand (line);
- + result = vbuffer_expand (o, str, len);
- current_variable_set_list = savev;
- reading_file = savef;
- return result;
- }
- -
- +
- /* Like allocated_variable_expand, but for += target-specific variables.
- First recursively construct the variable value from its appended parts in
- any upper variable sets. Then expand the resulting value. */
- -static char *
- -variable_append (const char *name, unsigned int length,
- - const struct variable_set_list *set, int local)
- +static size_t
- +expand_variable_append (struct vbuffer *o,
- + const char *name, unsigned int length,
- + const struct variable_set_list *set_list,
- + int local)
- {
- + size_t ret = 0;
- const struct variable *v;
- - char *buf = 0;
- - /* If this set is local and the next is not a parent, then next is local. */
- - int nextlocal = local && set->next_is_parent == 0;
- + int nextlocal;
- /* If there's nothing left to check, return the empty buffer. */
- - if (!set)
- - return initialize_variable_output ();
- + if (!set_list)
- + return 0;
- +
- + /* If this set is local and the next is not a parent, then next is local. */
- + nextlocal = local && set_list->next_is_parent == 0;
- /* Try to find the variable in this variable set. */
- - v = lookup_variable_in_set (name, length, set->set);
- + v = lookup_variable_in_set (name, length, set_list->set);
- /* If there isn't one, or this one is private, try the set above us. */
- if (!v || (!local && v->private_var))
- - return variable_append (name, length, set->next, nextlocal);
- + return expand_variable_append (o, name, length,
- + set_list->next, nextlocal);
- /* If this variable type is append, first get any upper values.
- If not, initialize the buffer. */
- if (v->append)
- - buf = variable_append (name, length, set->next, nextlocal);
- - else
- - buf = initialize_variable_output ();
- + ret += expand_variable_append (o, name, length,
- + set_list->next, nextlocal);
- /* Append this value to the buffer, and return it.
- If we already have a value, first add a space. */
- - if (buf > variable_buffer)
- - buf = variable_buffer_output (buf, " ", 1);
- + if (ret != 0)
- + ret += vbuffer_write (o, " ", 1);
- /* Either expand it or copy it, depending. */
- - if (! v->recursive)
- - return variable_buffer_output (buf, v->value, strlen (v->value));
- + if (v->recursive)
- + ret += vbuffer_expand_ro (o, v->value, -1);
- + else
- + ret += vbuffer_write (o, v->value, -1);
- - buf = variable_expand_string (buf, v->value, strlen (v->value));
- - return (buf + strlen (buf));
- + return ret;
- }
- +size_t
- +vbuffer_expand_variable_for_file (struct vbuffer *o, struct variable *v,
- + struct file *file)
- +{
- + size_t ret = 0;
- + const struct floc *this_var;
- + const struct floc **saved_varp;
- + struct variable_set_list *save = 0;
- + int set_reading = 0;
- +
- + /* Don't install a new location if this location is empty.
- + This can happen for command-line variables, builtin variables, etc. */
- + saved_varp = expanding_var;
- + if (v->fileinfo.filenm)
- + {
- + this_var = &v->fileinfo;
- + expanding_var = &this_var;
- + }
- +
- + /* If we have no other file-reading context, use the variable's context. */
- + if (!reading_file)
- + {
- + set_reading = 1;
- + reading_file = &v->fileinfo;
- + }
- +
- + if (v->expanding)
- + {
- + if (!v->exp_count)
- + /* Expanding V causes infinite recursion. Lose. */
- + fatal (*expanding_var,
- + _("Recursive variable '%s' references itself (eventually)"),
- + v->name);
- + --v->exp_count;
- + }
- +
- + if (file)
- + {
- + save = current_variable_set_list;
- + current_variable_set_list = file->variables;
- + }
- +
- + v->expanding = 1;
- +
- + if (v->append)
- + ret += expand_variable_append (o, v->name, strlen (v->name),
- + current_variable_set_list, 1);
- + else
- + /* We need a copy of STRING: due to eval, it's possible that it will get
- + freed as we process it (it might be the value of a variable that's
- + reset, for example). Also having a nil-terminated string is handy. */
- + ret += vbuffer_expand_ro (o, v->value, -1);
- -static char *
- -allocated_variable_append (const struct variable *v)
- + v->expanding = 0;
- +
- + if (set_reading)
- + reading_file = 0;
- +
- + if (file)
- + current_variable_set_list = save;
- +
- + expanding_var = saved_varp;
- +
- + return ret;
- +}
- +
- +size_t
- +vbuffer_expand_ro (struct vbuffer *o, const char *str, ssize_t len)
- +{
- + size_t ret;
- + size_t length = len < 0 ? strlen (str) : (size_t) len;
- +
- + char *alloc = 0;
- + char *value = length > MAX_ALLOCA_SIZE
- + ? (alloc = xmalloc (length + 1))
- + : alloca (length + 1);
- +
- + ret = vbuffer_expand (o, memcpy (value, str, length + 1), length);
- +
- + if (alloc)
- + free (alloc);
- +
- + return ret;
- +}
- +
- +size_t
- +vbuffer_expand_ro_for_file (struct vbuffer *o, const char *str, ssize_t len,
- + struct file *file)
- {
- - char *val;
- + size_t ret;
- + char *string = len < 0 ? xstrdup (str) : xstrndup (str, len);
- + ret = vbuffer_expand_for_file (o, string, -1, file);
- + free (string);
- + return ret;
- +}
- - /* Construct the appended variable value. */
- +/* Install a new expansion vbuffer, returning the current one. */
- +
- +struct vbuffer *
- +install_new_expansion_vbuffer (void)
- +{
- + struct vbuffer *old_vbuf = expansion_vbuf;
- - char *obuf = variable_buffer;
- - unsigned int olen = variable_buffer_length;
- + expansion_vbuf = xmalloc(sizeof(struct vbuffer));
- + vbuffer_init(expansion_vbuf);
- - variable_buffer = 0;
- + return old_vbuf;
- +}
- - val = variable_append (v->name, strlen (v->name),
- - current_variable_set_list, 1);
- - variable_buffer_output (val, "", 1);
- - val = variable_buffer;
- +/* Restore a previously-saved vbuffer setting freeing the current one. */
- - variable_buffer = obuf;
- - variable_buffer_length = olen;
- +void
- +restore_expansion_vbuffer (struct vbuffer *old_vbuf)
- +{
- + vbuffer_free(expansion_vbuf);
- + free(expansion_vbuf);
- - return val;
- + expansion_vbuf = old_vbuf;
- }
- -/* Like variable_expand_for_file, but the returned string is malloc'd.
- - This function is called a lot. It wants to be efficient. */
- +/* Expand an argument for an expansion function.
- + The text starting at STR and ending at END is variable-expanded
- + into a null-terminated string that is returned as the value.
- + This is done without clobbering 'variable_buffer' or the current
- + variable-expansion that is in progress. */
- char *
- -allocated_variable_expand_for_file (const char *line, struct file *file)
- +expand_argument (const char *str, const char *end)
- {
- - char *value;
- + struct vbuffer vbuf;
- - char *obuf = variable_buffer;
- - unsigned int olen = variable_buffer_length;
- + vbuffer_expand_ro (vbuffer_init(&vbuf), str, end - str);
- - variable_buffer = 0;
- + return vbuf.buffer;
- +}
- - value = variable_expand_for_file (line, file);
- +/* Scan LINE for variable references and expansion-function calls.
- + Build in 'variable_buffer' the result of expanding the references and calls.
- + Return the address of the resulting string, which is null-terminated
- + and is valid only until the next time this function is called. */
- - variable_buffer = obuf;
- - variable_buffer_length = olen;
- +char *
- +variable_expand (const char *line)
- +{
- + vbuffer_expand_ro (vbuffer_reset(expansion_vbuf), line, -1);
- - return value;
- + return expansion_vbuf->buffer;
- }
- -/* Install a new variable_buffer context, returning the current one for
- - safe-keeping. */
- +/* Expand LINE for FILE. Error messages refer to the file and line where
- + FILE's commands were found. Expansion uses FILE's variable set list. */
- -void
- -install_variable_buffer (char **bufp, unsigned int *lenp)
- +char *
- +variable_expand_for_file (const char *line, struct file *file)
- +{
- + vbuffer_expand_ro_for_file (vbuffer_reset(expansion_vbuf), line, -1, file);
- +
- + return expansion_vbuf->buffer;
- +}
- +
- +char *
- +allocated_variable_expand (const char *line)
- {
- - *bufp = variable_buffer;
- - *lenp = variable_buffer_length;
- + struct vbuffer vbuf;
- - variable_buffer = 0;
- - initialize_variable_output ();
- + vbuffer_expand_ro (vbuffer_init(&vbuf), line, -1);
- +
- + return vbuf.buffer;
- }
- -/* Restore a previously-saved variable_buffer setting (free the current one).
- - */
- +/* Like variable_expand_for_file, but the returned string is malloc'd. */
- -void
- -restore_variable_buffer (char *buf, unsigned int len)
- +char *
- +allocated_variable_expand_for_file (const char *line, struct file *file)
- {
- - free (variable_buffer);
- + struct vbuffer vbuf;
- +
- + vbuffer_expand_ro_for_file (vbuffer_init(&vbuf), line, -1, file);
- +
- + return vbuf.buffer;
- +}
- +
- +char *
- +recursively_expand_for_file (struct variable *v, struct file *file)
- +{
- + struct vbuffer vbuf;
- +
- + vbuffer_expand_variable_for_file (vbuffer_init(&vbuf), v, file);
- - variable_buffer = buf;
- - variable_buffer_length = len;
- + return vbuf.buffer;
- }
- Index: file.c
- ===================================================================
- RCS file: /sources/make/make/file.c,v
- retrieving revision 1.105
- diff -u -r1.105 file.c
- --- file.c 5 Mar 2012 14:10:43 -0000 1.105
- +++ file.c 9 Apr 2012 13:34:41 -0000
- @@ -467,9 +467,11 @@
- if (stem)
- {
- const char *pattern = "%";
- - char *buffer = variable_expand ("");
- + struct vbuffer vbuf;
- struct dep *dp = deps, *dl = 0;
- + vbuffer_init (&vbuf);
- +
- while (dp != 0)
- {
- char *percent;
- @@ -479,22 +481,23 @@
- percent = find_percent (nm);
- if (percent)
- {
- - char *o;
- + size_t len;
- /* We have to handle empty stems specially, because that
- would be equivalent to $(patsubst %,dp->name,) which
- will always be empty. */
- - if (stem[0] == '\0')
- + if (*stem == '\0')
- {
- memmove (percent, percent+1, strlen (percent));
- - o = variable_buffer_output (buffer, nm, strlen (nm) + 1);
- + len = vbuffer_write (vbuffer_reset (&vbuf), nm, -1);
- }
- else
- - o = patsubst_expand_pat (buffer, stem, pattern, nm,
- - pattern+1, percent+1);
- + len = patsubst_expand_pat (vbuffer_reset (&vbuf), stem,
- + pattern, nm,
- + pattern+1, percent+1);
- /* If the name expanded to the empty string, ignore it. */
- - if (buffer[0] == '\0')
- + if (len == 0)
- {
- struct dep *df = dp;
- if (dp == deps)
- @@ -506,24 +509,26 @@
- }
- /* Save the name. */
- - dp->name = strcache_add_len (buffer, o - buffer);
- + dp->name = strcache_add_len (vbuf.buffer, len);
- }
- dp->stem = stem;
- dp->staticpattern = 1;
- dl = dp;
- dp = dp->next;
- }
- +
- + vbuffer_free (&vbuf);
- }
- /* Enter them as files, unless they need a 2nd expansion. */
- for (d1 = deps; d1 != 0; d1 = d1->next)
- {
- if (d1->need_2nd_expansion)
- - continue;
- + continue;
- d1->file = lookup_file (d1->name);
- if (d1->file == 0)
- - d1->file = enter_file (d1->name);
- + d1->file = enter_file (d1->name);
- d1->staticpattern = 0;
- d1->name = 0;
- }
- @@ -573,12 +578,10 @@
- "$*" so they'll expand properly. */
- if (d->staticpattern)
- {
- - char *o;
- - d->name = o = variable_expand ("");
- - o = subst_expand (o, name, "%", "$*", 1, 2, 0);
- - *o = '\0';
- + struct vbuffer vbuf;
- + subst_expand (vbuffer_init(&vbuf), name, "%", "$*", 1, 2, 0);
- free (name);
- - d->name = name = xstrdup (d->name);
- + d->name = name = xstrdup (vbuf.buffer);
- d->staticpattern = 0;
- }
- Index: function.c
- ===================================================================
- RCS file: /sources/make/make/function.c,v
- retrieving revision 1.133
- diff -u -r1.133 function.c
- --- function.c 5 Mar 2012 14:10:43 -0000 1.133
- +++ function.c 9 Apr 2012 13:34:41 -0000
- @@ -15,6 +15,9 @@
- this program. If not, see <http://www.gnu.org/licenses/>. */
- #include "make.h"
- +
- +#include <assert.h>
- +
- #include "filedef.h"
- #include "variable.h"
- #include "dep.h"
- @@ -34,7 +37,7 @@
- unsigned char minimum_args;
- unsigned char maximum_args;
- char expand_args;
- - char *(*func_ptr) (char *output, char **argv, const char *fname);
- + size_t (*func_ptr) (struct vbuffer *output, char **argv, const char *fname);
- };
- static unsigned long
- @@ -65,26 +68,29 @@
- static struct hash_table function_table;
- -/* Store into VARIABLE_BUFFER at O the result of scanning TEXT and replacing
- +/* Store into VBUFFER at O the result of scanning TEXT and replacing
- each occurrence of SUBST with REPLACE. TEXT is null-terminated. SLEN is
- the length of SUBST and RLEN is the length of REPLACE. If BY_WORD is
- nonzero, substitutions are done only on matches which are complete
- whitespace-delimited words. */
- -char *
- -subst_expand (char *o, const char *text, const char *subst, const char *replace,
- - unsigned int slen, unsigned int rlen, int by_word)
- +size_t
- +subst_expand (struct vbuffer *o, const char *text, const char *subst,
- + const char *replace, unsigned int slen, unsigned int rlen,
- + int by_word)
- {
- + size_t result = 0;
- +
- const char *t = text;
- const char *p;
- if (slen == 0 && !by_word)
- {
- /* The first occurrence of "" in any string is its end. */
- - o = variable_buffer_output (o, t, strlen (t));
- + result += vbuffer_write (o, t, -1);
- if (rlen > 0)
- - o = variable_buffer_output (o, replace, rlen);
- - return o;
- + result += vbuffer_write (o, replace, rlen);
- + return result;
- }
- do
- @@ -99,14 +105,14 @@
- if (p == 0)
- {
- /* No more matches. Output everything left on the end. */
- - o = variable_buffer_output (o, t, strlen (t));
- - return o;
- + result += vbuffer_write (o, t, -1);
- + return result;
- }
- }
- /* Output everything before this occurrence of the string to replace. */
- if (p > t)
- - o = variable_buffer_output (o, t, p - t);
- + result += vbuffer_write (o, t, p - t);
- /* If we're substituting only by fully matched words,
- or only at the ends of words, check that this case qualifies. */
- @@ -115,20 +121,21 @@
- || (p[slen] != '\0' && !isblank ((unsigned char)p[slen]))))
- /* Struck out. Output the rest of the string that is
- no longer to be replaced. */
- - o = variable_buffer_output (o, subst, slen);
- + result += vbuffer_write (o, subst, slen);
- else if (rlen > 0)
- /* Output the replacement string. */
- - o = variable_buffer_output (o, replace, rlen);
- + result += vbuffer_write (o, replace, rlen);
- /* Advance T past the string to be replaced. */
- t = p + slen;
- - } while (*t != '\0');
- + }
- + while (*t != '\0');
- - return o;
- + return result;
- }
- -/* Store into VARIABLE_BUFFER at O the result of scanning TEXT
- +/* Store into VBUFFER at O the result of scanning TEXT
- and replacing strings matching PATTERN with REPLACE.
- If PATTERN_PERCENT is not nil, PATTERN has already been
- run through find_percent, and PATTERN_PERCENT is the result.
- @@ -138,16 +145,17 @@
- character _AFTER_ the %, not to the % itself.
- */
- -char *
- -patsubst_expand_pat (char *o, const char *text,
- +size_t
- +patsubst_expand_pat (struct vbuffer *o, const char *text,
- const char *pattern, const char *replace,
- const char *pattern_percent, const char *replace_percent)
- {
- + size_t ret = 0;
- +
- unsigned int pattern_prepercent_len, pattern_postpercent_len;
- unsigned int replace_prepercent_len, replace_postpercent_len;
- const char *t;
- unsigned int len;
- - int doneany = 0;
- /* Record the length of REPLACE before and after the % so we don't have to
- compute these lengths more than once. */
- @@ -197,43 +205,37 @@
- if (fail)
- /* It didn't match. Output the string. */
- - o = variable_buffer_output (o, t, len);
- + ret += vbuffer_write (o, t, len);
- else
- {
- /* It matched. Output the replacement. */
- /* Output the part of the replacement before the %. */
- - o = variable_buffer_output (o, replace, replace_prepercent_len);
- + ret += vbuffer_write (o, replace, replace_prepercent_len);
- if (replace_percent != 0)
- {
- /* Output the part of the matched string that
- matched the % in the pattern. */
- - o = variable_buffer_output (o, t + pattern_prepercent_len,
- - len - (pattern_prepercent_len
- + ret += vbuffer_write (o, t + pattern_prepercent_len,
- + len - (pattern_prepercent_len
- + pattern_postpercent_len));
- /* Output the part of the replacement after the %. */
- - o = variable_buffer_output (o, replace_percent,
- - replace_postpercent_len);
- + ret += vbuffer_write (o, replace_percent,
- + replace_postpercent_len);
- }
- }
- /* Output a space, but not if the replacement is "". */
- if (fail || replace_prepercent_len > 0
- || (replace_percent != 0 && len + replace_postpercent_len > 0))
- - {
- - o = variable_buffer_output (o, " ", 1);
- - doneany = 1;
- - }
- + ret += vbuffer_write (o, " ", 1);
- }
- - if (doneany)
- - /* Kill the last space. */
- - --o;
- - return o;
- + return ret - vbuffer_unwrite (o, !!ret);
- }
- -/* Store into VARIABLE_BUFFER at O the result of scanning TEXT
- +/* Store into VBUFFER at O the result of scanning TEXT
- and replacing strings matching PATTERN with REPLACE.
- If PATTERN_PERCENT is not nil, PATTERN has already been
- run through find_percent, and PATTERN_PERCENT is the result.
- @@ -243,8 +245,9 @@
- character _AFTER_ the %, not to the % itself.
- */
- -char *
- -patsubst_expand (char *o, const char *text, char *pattern, char *replace)
- +size_t
- +patsubst_expand (struct vbuffer *o, const char *text, char *pattern,
- + char *replace)
- {
- const char *pattern_percent = find_percent (pattern);
- const char *replace_percent = find_percent (replace);
- @@ -256,28 +259,7 @@
- ++pattern_percent;
- return patsubst_expand_pat (o, text, pattern, replace,
- - pattern_percent, replace_percent);
- -}
- -
- -
- -/* Look up a function by name. */
- -
- -static const struct function_table_entry *
- -lookup_function (const char *s)
- -{
- - const char *e = s;
- -
- - while (*e && ( (*e >= 'a' && *e <= 'z') || *e == '-'))
- - e++;
- - if (*e == '\0' || isblank ((unsigned char) *e))
- - {
- - struct function_table_entry function_table_entry_key;
- - function_table_entry_key.name = s;
- - function_table_entry_key.len = e - s;
- -
- - return hash_find_item (&function_table, &function_table_entry_key);
- - }
- - return 0;
- + pattern_percent, replace_percent);
- }
- @@ -310,48 +292,16 @@
- }
- -/* Find the next comma or ENDPAREN (counting nested STARTPAREN and
- - ENDPARENtheses), starting at PTR before END. Return a pointer to
- - next character.
- -
- - If no next argument is found, return NULL.
- -*/
- -
- -static char *
- -find_next_argument (char startparen, char endparen,
- - const char *ptr, const char *end)
- -{
- - int count = 0;
- -
- - for (; ptr < end; ++ptr)
- - if (*ptr == startparen)
- - ++count;
- -
- - else if (*ptr == endparen)
- - {
- - --count;
- - if (count < 0)
- - return NULL;
- - }
- -
- - else if (*ptr == ',' && !count)
- - return (char *)ptr;
- -
- - /* We didn't find anything. */
- - return NULL;
- -}
- -
- -
- -/* Glob-expand LINE. The returned pointer is
- - only good until the next call to string_glob. */
- +/* Glob-expand the LINE writing the result into O. */
- -static char *
- -string_glob (char *line)
- +#ifdef __GNUC__
- +__inline
- +#endif
- +static size_t
- +string_glob (struct vbuffer *o, char *line)
- {
- - static char *result = 0;
- - static unsigned int length;
- + size_t ret = 0;
- struct nameseq *chain;
- - unsigned int idx;
- chain = PARSE_FILE_SEQ (&line, struct nameseq, '\0', NULL,
- /* We do not want parse_file_seq to strip './'s.
- @@ -359,58 +309,53 @@
- $(patsubst ./%.c,obj/%.o,$(wildcard ./?*.c)). */
- PARSEFS_NOSTRIP|PARSEFS_NOCACHE|PARSEFS_EXISTS);
- - if (result == 0)
- - {
- - length = 100;
- - result = xmalloc (100);
- - }
- -
- - idx = 0;
- while (chain != 0)
- {
- struct nameseq *next = chain->next;
- - unsigned int len = strlen (chain->name);
- - if (idx + len + 1 > length)
- - {
- - length += (len + 1) * 2;
- - result = xrealloc (result, length);
- - }
- - memcpy (&result[idx], chain->name, len);
- - idx += len;
- - result[idx++] = ' ';
- + ret += vbuffer_write (o, chain->name, -1);
- + ret += vbuffer_write (o, " ", 1);
- /* Because we used PARSEFS_NOCACHE above, we have to free() NAME. */
- free ((char *)chain->name);
- free (chain);
- +
- chain = next;
- }
- - /* Kill the last space and terminate the string. */
- - if (idx == 0)
- - result[0] = '\0';
- - else
- - result[idx - 1] = '\0';
- + return ret - vbuffer_unwrite (o, !!ret);
- +}
- - return result;
- +static size_t
- +func_wildcard (struct vbuffer *o, char **argv, const char *funcname UNUSED)
- +{
- + size_t ret = 0;
- +
- +#ifdef _AMIGA
- + o = wildcard_expansion (argv[0], o);
- +#else
- + ret += string_glob (o, argv[0]);
- +#endif
- +
- + return ret;
- }
- +
- /*
- Builtin functions
- */
- -static char *
- -func_patsubst (char *o, char **argv, const char *funcname UNUSED)
- +static size_t
- +func_patsubst (struct vbuffer *o, char **argv, const char *funcname UNUSED)
- {
- - o = patsubst_expand (o, argv[2], argv[0], argv[1]);
- - return o;
- + return patsubst_expand (o, argv[2], argv[0], argv[1]);
- }
- -static char *
- -func_join (char *o, char **argv, const char *funcname UNUSED)
- +static size_t
- +func_join (struct vbuffer *o, char **argv, const char *funcname UNUSED)
- {
- - int doneany = 0;
- + size_t ret = 0;
- /* Write each word of the first argument directly followed
- by the corresponding word of the second argument.
- @@ -420,87 +365,84 @@
- const char *pp;
- const char *list1_iterator = argv[0];
- const char *list2_iterator = argv[1];
- +
- do
- {
- unsigned int len1, len2;
- tp = find_next_token (&list1_iterator, &len1);
- if (tp != 0)
- - o = variable_buffer_output (o, tp, len1);
- + ret += vbuffer_write (o, tp, len1);
- pp = find_next_token (&list2_iterator, &len2);
- if (pp != 0)
- - o = variable_buffer_output (o, pp, len2);
- + ret += vbuffer_write (o, pp, len2);
- if (tp != 0 || pp != 0)
- - {
- - o = variable_buffer_output (o, " ", 1);
- - doneany = 1;
- - }
- + ret += vbuffer_write (o, " ", 1);
- }
- while (tp != 0 || pp != 0);
- - if (doneany)
- - /* Kill the last blank. */
- - --o;
- - return o;
- + return ret - vbuffer_unwrite (o, !!ret);
- }
- -static char *
- -func_origin (char *o, char **argv, const char *funcname UNUSED)
- +static size_t
- +func_origin (struct vbuffer *o, char **argv, const char *funcname UNUSED)
- {
- - /* Expand the argument. */
- + size_t ret = 0;
- struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
- +
- if (v == 0)
- - o = variable_buffer_output (o, "undefined", 9);
- + ret += vbuffer_write (o, STRING_SIZE_TUPLE("undefined"));
- else
- switch (v->origin)
- {
- - default:
- - case o_invalid:
- - abort ();
- - break;
- case o_default:
- - o = variable_buffer_output (o, "default", 7);
- + ret += vbuffer_write (o, STRING_SIZE_TUPLE("default"));
- break;
- case o_env:
- - o = variable_buffer_output (o, "environment", 11);
- + ret += vbuffer_write (o, STRING_SIZE_TUPLE("environment"));
- break;
- case o_file:
- - o = variable_buffer_output (o, "file", 4);
- + ret += vbuffer_write (o, STRING_SIZE_TUPLE("file"));
- break;
- case o_env_override:
- - o = variable_buffer_output (o, "environment override", 20);
- + ret += vbuffer_write (o, STRING_SIZE_TUPLE("environment override"));
- break;
- case o_command:
- - o = variable_buffer_output (o, "command line", 12);
- + ret += vbuffer_write (o, STRING_SIZE_TUPLE("command line"));
- break;
- case o_override:
- - o = variable_buffer_output (o, "override", 8);
- + ret += vbuffer_write (o, STRING_SIZE_TUPLE("override"));
- break;
- case o_automatic:
- - o = variable_buffer_output (o, "automatic", 9);
- + ret += vbuffer_write (o, STRING_SIZE_TUPLE("automatic"));
- + break;
- + case o_invalid:
- + default:
- + abort ();
- break;
- }
- - return o;
- + return ret;
- }
- -static char *
- -func_flavor (char *o, char **argv, const char *funcname UNUSED)
- +static size_t
- +func_flavor (struct vbuffer *o, char **argv, const char *funcname UNUSED)
- {
- + size_t ret = 0;
- struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
- if (v == 0)
- - o = variable_buffer_output (o, "undefined", 9);
- + ret += vbuffer_write (o, STRING_SIZE_TUPLE("undefined"));
- else
- if (v->recursive)
- - o = variable_buffer_output (o, "recursive", 9);
- + ret += vbuffer_write (o, STRING_SIZE_TUPLE("recursive"));
- else
- - o = variable_buffer_output (o, "simple", 6);
- + ret += vbuffer_write (o, STRING_SIZE_TUPLE("simple"));
- - return o;
- + return ret;
- }
- #ifdef VMS
- @@ -514,14 +456,15 @@
- #endif
- -static char *
- -func_notdir_suffix (char *o, char **argv, const char *funcname)
- +static size_t
- +func_notdir_suffix (struct vbuffer *o, char **argv, const char *funcname)
- {
- + size_t ret = 0;
- +
- /* Expand the argument. */
- const char *list_iterator = argv[0];
- const char *p2;
- - int doneany =0;
- - unsigned int len=0;
- + unsigned int len = 0;
- int is_suffix = funcname[0] == 's';
- int is_notdir = !is_suffix;
- @@ -529,7 +472,6 @@
- {
- const char *p = p2 + len;
- -
- while (p >= p2 && (!is_suffix || *p != '.'))
- {
- if (IS_PATHSEP (*p))
- @@ -543,41 +485,35 @@
- ++p;
- else if (*p != '.')
- continue;
- - o = variable_buffer_output (o, p, len - (p - p2));
- + ret += vbuffer_write (o, p, len - (p - p2));
- }
- #ifdef HAVE_DOS_PATHS
- /* Handle the case of "d:foo/bar". */
- else if (is_notdir && p2[0] && p2[1] == ':')
- {
- p = p2 + 2;
- - o = variable_buffer_output (o, p, len - (p - p2));
- + ret += vbuffer_write (o, p, len - (p - p2));
- }
- #endif
- else if (is_notdir)
- - o = variable_buffer_output (o, p2, len);
- + ret += vbuffer_write (o, p2, len);
- if (is_notdir || p >= p2)
- - {
- - o = variable_buffer_output (o, " ", 1);
- - doneany = 1;
- - }
- + ret += vbuffer_write (o, " ", 1);
- }
- - if (doneany)
- - /* Kill last space. */
- - --o;
- -
- - return o;
- + return ret - vbuffer_unwrite (o, !!ret);
- }
- -static char *
- -func_basename_dir (char *o, char **argv, const char *funcname)
- +static size_t
- +func_basename_dir (struct vbuffer *o, char **argv, const char *funcname)
- {
- + size_t ret = 0;
- +
- /* Expand the argument. */
- const char *p3 = argv[0];
- const char *p2;
- - int doneany = 0;
- unsigned int len = 0;
- int is_basename = funcname[0] == 'b';
- @@ -594,111 +530,105 @@
- }
- if (p >= p2 && (is_dir))
- - o = variable_buffer_output (o, p2, ++p - p2);
- + ret += vbuffer_write (o, p2, ++p - p2);
- else if (p >= p2 && (*p == '.'))
- - o = variable_buffer_output (o, p2, p - p2);
- + ret += vbuffer_write (o, p2, p - p2);
- #ifdef HAVE_DOS_PATHS
- /* Handle the "d:foobar" case */
- else if (p2[0] && p2[1] == ':' && is_dir)
- - o = variable_buffer_output (o, p2, 2);
- + ret += vbuffer_write (o, p2, 2);
- #endif
- else if (is_dir)
- #ifdef VMS
- - o = variable_buffer_output (o, "[]", 2);
- + ret += vbuffer_write (o, "[]", 2);
- #else
- #ifndef _AMIGA
- - o = variable_buffer_output (o, "./", 2);
- + ret += vbuffer_write (o, "./", 2);
- #else
- ; /* Just a nop... */
- #endif /* AMIGA */
- #endif /* !VMS */
- else
- /* The entire name is the basename. */
- - o = variable_buffer_output (o, p2, len);
- + ret += vbuffer_write (o, p2, len);
- - o = variable_buffer_output (o, " ", 1);
- - doneany = 1;
- + ret += vbuffer_write (o, " ", 1);
- }
- - if (doneany)
- - /* Kill last space. */
- - --o;
- -
- - return o;
- + return ret - vbuffer_unwrite (o, !!ret);
- }
- -static char *
- -func_addsuffix_addprefix (char *o, char **argv, const char *funcname)
- +static size_t
- +func_addsuffix_addprefix (struct vbuffer *o, char **argv, const char *funcname)
- {
- + size_t ret = 0;
- +
- int fixlen = strlen (argv[0]);
- const char *list_iterator = argv[1];
- - int is_addprefix = funcname[3] == 'p';
- + int is_addprefix = funcname[CSTRLEN("add")] == 'p';
- int is_addsuffix = !is_addprefix;
- - int doneany = 0;
- const char *p;
- unsigned int len;
- while ((p = find_next_token (&list_iterator, &len)) != 0)
- {
- if (is_addprefix)
- - o = variable_buffer_output (o, argv[0], fixlen);
- - o = variable_buffer_output (o, p, len);
- + ret += vbuffer_write (o, argv[0], fixlen);
- + ret += vbuffer_write (o, p, len);
- if (is_addsuffix)
- - o = variable_buffer_output (o, argv[0], fixlen);
- - o = variable_buffer_output (o, " ", 1);
- - doneany = 1;
- + ret += vbuffer_write (o, argv[0], fixlen);
- + ret += vbuffer_write (o, " ", 1);
- }
- - if (doneany)
- - /* Kill last space. */
- - --o;
- -
- - return o;
- + return ret - vbuffer_unwrite (o, !!ret);
- }
- -static char *
- -func_subst (char *o, char **argv, const char *funcname UNUSED)
- -{
- - o = subst_expand (o, argv[2], argv[0], argv[1], strlen (argv[0]),
- - strlen (argv[1]), 0);
- - return o;
- +static size_t
- +func_subst (struct vbuffer *o, char **argv, const char *funcname UNUSED)
- +{
- + return subst_expand (o, argv[2], argv[0], argv[1], strlen (argv[0]),
- + strlen (argv[1]), 0);
- }
- -static char *
- -func_firstword (char *o, char **argv, const char *funcname UNUSED)
- +static size_t
- +func_firstword (struct vbuffer *o, char **argv, const char *funcname UNUSED)
- {
- - unsigned int i;
- + size_t ret = 0;
- +
- + unsigned int len;
- const char *words = argv[0]; /* Use a temp variable for find_next_token */
- - const char *p = find_next_token (&words, &i);
- + const char *p = find_next_token (&words, &len);
- if (p != 0)
- - o = variable_buffer_output (o, p, i);
- + ret += vbuffer_write (o, p, len);
- - return o;
- + return ret;
- }
- -static char *
- -func_lastword (char *o, char **argv, const char *funcname UNUSED)
- +static size_t
- +func_lastword (struct vbuffer *o, char **argv, const char *funcname UNUSED)
- {
- - unsigned int i;
- + size_t ret = 0;
- +
- + unsigned int len;
- const char *words = argv[0]; /* Use a temp variable for find_next_token */
- const char *p = NULL;
- const char *t;
- - while ((t = find_next_token (&words, &i)))
- + while ((t = find_next_token (&words, &len)))
- p = t;
- if (p != 0)
- - o = variable_buffer_output (o, p, i);
- + ret += vbuffer_write (o, p, len);
- - return o;
- + return ret;
- }
- -static char *
- -func_words (char *o, char **argv, const char *funcname UNUSED)
- +static size_t
- +func_words (struct vbuffer *o, char **argv, const char *funcname UNUSED)
- {
- int i = 0;
- const char *word_iterator = argv[0];
- @@ -708,9 +638,8 @@
- ++i;
- sprintf (buf, "%d", i);
- - o = variable_buffer_output (o, buf, strlen (buf));
- - return o;
- + return vbuffer_write (o, buf, -1);
- }
- /* Set begpp to point to the first non-whitespace character of the string,
- @@ -744,10 +673,11 @@
- }
- -
- -static char *
- -func_word (char *o, char **argv, const char *funcname UNUSED)
- +static size_t
- +func_word (struct vbuffer *o, char **argv, const char *funcname UNUSED)
- {
- + size_t ret = 0;
- +
- const char *end_p;
- const char *p;
- int i;
- @@ -766,14 +696,17 @@
- break;
- if (i == 0)
- - o = variable_buffer_output (o, p, end_p - p);
- + ret += vbuffer_write (o, p, end_p - p);
- - return o;
- + return ret;
- }
- -static char *
- -func_wordlist (char *o, char **argv, const char *funcname UNUSED)
- +
- +static size_t
- +func_wordlist (struct vbuffer *o, char **argv, const char *funcname UNUSED)
- {
- + size_t ret = 0;
- +
- int start, count;
- /* Check the arguments. */
- @@ -805,67 +738,102 @@
- ;
- /* Return the stuff in the middle. */
- - o = variable_buffer_output (o, p, end_p - p);
- + ret += vbuffer_write (o, p, end_p - p);
- }
- }
- - return o;
- + return ret;
- }
- -static char *
- -func_findstring (char *o, char **argv, const char *funcname UNUSED)
- +static size_t
- +func_findstring (struct vbuffer *o, char **argv, const char *funcname UNUSED)
- {
- + size_t ret = 0;
- +
- /* Find the first occurrence of the first string in the second. */
- if (strstr (argv[1], argv[0]) != 0)
- - o = variable_buffer_output (o, argv[0], strlen (argv[0]));
- + ret += vbuffer_write (o, argv[0], -1);
- - return o;
- + return ret;
- }
- -static char *
- -func_foreach (char *o, char **argv, const char *funcname UNUSED)
- +static size_t
- +func_foreach (struct vbuffer *o, char **argv, const char *funcname UNUSED)
- {
- - /* expand only the first two. */
- - char *varname = expand_argument (argv[0], NULL);
- - char *list = expand_argument (argv[1], NULL);
- - const char *body = argv[2];
- + size_t ret = 0;
- - int doneany = 0;
- - const char *list_iterator = list;
- - const char *p;
- + char *p;
- unsigned int len;
- - struct variable *var;
- + char *varname;
- + char *list;
- + char *body;
- + size_t varname_len;
- + size_t list_len;
- + size_t body_len = strlen (argv[2]);
- + struct vbuffer argbuf;
- - push_new_variable_scope ();
- - var = define_variable (varname, strlen (varname), "", o_automatic, 0);
- + /* Expand the list and the variable name into a dedicated vbuffer. */
- - /* loop through LIST, put the value in VAR and expand BODY */
- - while ((p = find_next_token (&list_iterator, &len)) != 0)
- + vbuffer_init (&argbuf);
- +
- + list_len = vbuffer_expand (&argbuf, argv[1], -1);
- + *(++argbuf.ptr) = '\0';
- + /* Add an extra nil to iterate over the list more efficiently. */
- + *(++argbuf.ptr) = '\0';
- +
- + varname_len = vbuffer_expand (&argbuf, argv[0], -1);
- + *(++argbuf.ptr) = '\0';
- +
- + /* Also get a room for an unexpanded body. */
- +
- + vbuffer_reserve (&argbuf, body_len + 1);
- +
- + list = argbuf.buffer;
- + varname = list + list_len + 2;
- + body = varname + varname_len + 1;
- + body[body_len] = ' ';
- +
- + if ((p = find_next_token ((const char **) &list, &len)) != 0)
- {
- - char *result = 0;
- + struct variable var;
- + struct variable *saved_var;
- + char **argp;
- + char *saved_arg = NULL;
- - free (var->value);
- - var->value = xstrndup (p, len);
- + argp = lookup_call_argument_value (varname, varname_len);
- + if (argp && *argp)
- + {
- + /* Variable name is a numeric value and there is a call argument
- + that would hide a pushed variable.
- + Make a "hole" in the current call frame so that the new variable
- + becomes visible. */
- + saved_arg = *argp;
- + *argp = NULL;
- + }
- + saved_var = push_scoped_variable (&var, varname, varname_len);
- - result = allocated_variable_expand (body);
- + /* loop through LIST, put the value in VAR and expand BODY */
- + do
- + {
- + p[len] = '\0';
- + var.value = p;
- + ret += vbuffer_expand (o, memcpy (body, argv[2], body_len),
- + body_len + 1);
- + ++list;
- + }
- + while ((p = find_next_token ((const char **) &list, &len)) != 0);
- - o = variable_buffer_output (o, result, strlen (result));
- - o = variable_buffer_output (o, " ", 1);
- - doneany = 1;
- - free (result);
- + pop_scoped_variable (&var, saved_var);
- + if (saved_arg)
- + *argp = saved_arg;
- }
- - if (doneany)
- - /* Kill the last space. */
- - --o;
- -
- - pop_variable_scope ();
- - free (varname);
- - free (list);
- + vbuffer_free (&argbuf);
- - return o;
- + return ret - vbuffer_unwrite (o, !!ret);
- }
- +
- struct a_word
- {
- struct a_word *next;
- @@ -905,9 +873,11 @@
- int length;
- };
- -static char *
- -func_filter_filterout (char *o, char **argv, const char *funcname)
- +static size_t
- +func_filter_filterout (struct vbuffer *o, char **argv, const char *funcname)
- {
- + size_t ret = 0;
- +
- struct a_word *wordhead;
- struct a_word **wordtail;
- struct a_word *wp;
- @@ -989,8 +959,6 @@
- if (words)
- {
- - int doneany = 0;
- -
- /* Run each pattern through the words, killing words. */
- for (pp = pathead; pp != 0; pp = pp->next)
- {
- @@ -1019,58 +987,42 @@
- for (wp = wordhead; wp != 0; wp = wp->next)
- if (is_filter ? wp->matched : !wp->matched)
- {
- - o = variable_buffer_output (o, wp->str, strlen (wp->str));
- - o = variable_buffer_output (o, " ", 1);
- - doneany = 1;
- + ret += vbuffer_write (o, wp->str, -1);
- + ret += vbuffer_write (o, " ", 1);
- }
- - if (doneany)
- - /* Kill the last space. */
- - --o;
- }
- if (hashing)
- hash_free (&a_word_table, 0);
- - return o;
- + return ret - vbuffer_unwrite (o, !!ret);
- }
- -static char *
- -func_strip (char *o, char **argv, const char *funcname UNUSED)
- +static size_t
- +func_strip (struct vbuffer *o, char **argv, const char *funcname UNUSED)
- {
- - const char *p = argv[0];
- - int doneany = 0;
- + size_t result = 0;
- - while (*p != '\0')
- - {
- - int i=0;
- - const char *word_start;
- + unsigned int len;
- + const char *words = argv[0]; /* Use a temp variable for find_next_token */
- + const char *p;
- - while (isspace ((unsigned char)*p))
- - ++p;
- - word_start = p;
- - for (i=0; *p != '\0' && !isspace ((unsigned char)*p); ++p, ++i)
- - {}
- - if (!i)
- - break;
- - o = variable_buffer_output (o, word_start, i);
- - o = variable_buffer_output (o, " ", 1);
- - doneany = 1;
- + while ((p = find_next_token (&words, &len)) != 0)
- + {
- + result += vbuffer_write (o, p, len + 1);
- + o->ptr[-1] = ' ';
- }
- - if (doneany)
- - /* Kill the last space. */
- - --o;
- -
- - return o;
- + return result - vbuffer_unwrite (o, !!result);
- }
- /*
- Print a warning or fatal message.
- */
- -static char *
- -func_error (char *o, char **argv, const char *funcname)
- +size_t
- +func_error (struct vbuffer *o UNUSED, char **argv, const char *funcname)
- {
- char **argvp;
- char *msg, *p;
- @@ -1111,16 +1063,18 @@
- }
- /* The warning function expands to the empty string. */
- - return o;
- + return 0;
- }
- /*
- chop argv[0] into words, and sort them.
- */
- -static char *
- -func_sort (char *o, char **argv, const char *funcname UNUSED)
- +static size_t
- +func_sort (struct vbuffer *o, char **argv, const char *funcname UNUSED)
- {
- + size_t result = 0;
- +
- const char *t;
- char **words;
- int wordi;
- @@ -1133,7 +1087,8 @@
- wordi = 0;
- while ((p = find_next_token (&t, NULL)) != 0)
- {
- - ++t;
- + if (*t != '\0')
- + ++t;
- ++wordi;
- }
- @@ -1144,7 +1099,8 @@
- wordi = 0;
- while ((p = find_next_token (&t, &len)) != 0)
- {
- - ++t;
- + if (*t != '\0')
- + ++t;
- p[len] = '\0';
- words[wordi++] = p;
- }
- @@ -1161,18 +1117,18 @@
- if (i == wordi - 1 || strlen (words[i + 1]) != len
- || strcmp (words[i], words[i + 1]))
- {
- - o = variable_buffer_output (o, words[i], len);
- - o = variable_buffer_output (o, " ", 1);
- + result += vbuffer_write (o, words[i], len);
- + result += vbuffer_write (o, " ", 1);
- }
- }
- /* Kill the last space. */
- - --o;
- + result -= vbuffer_unwrite (o, 1);
- }
- free (words);
- - return o;
- + return result;
- }
- /*
- @@ -1187,9 +1143,11 @@
- example).
- */
- -static char *
- -func_if (char *o, char **argv, const char *funcname UNUSED)
- +static size_t
- +func_if (struct vbuffer *o, char **argv, const char *funcname UNUSED)
- {
- + size_t ret = 0;
- +
- const char *begp = argv[0];
- const char *endp = begp + strlen (argv[0]) - 1;
- int result = 0;
- @@ -1201,12 +1159,9 @@
- strip_whitespace (&begp, &endp);
- if (begp <= endp)
- - {
- - char *expansion = expand_argument (begp, endp+1);
- + result = vbuffer_expand (o, (char *) begp, endp+1 - begp);
- - result = strlen (expansion);
- - free (expansion);
- - }
- + vbuffer_unwrite (o, result);
- /* If the result is true (1) we want to eval the first argument, and if
- it's false (0) we want to eval the second. If the argument doesn't
- @@ -1215,15 +1170,9 @@
- argv += 1 + !result;
- if (*argv)
- - {
- - char *expansion = expand_argument (*argv, NULL);
- + ret += vbuffer_expand (o, *argv, -1);
- - o = variable_buffer_output (o, expansion, strlen (expansion));
- -
- - free (expansion);
- - }
- -
- - return o;
- + return ret;
- }
- /*
- @@ -1240,15 +1189,15 @@
- (short-circuiting).
- */
- -static char *
- -func_or (char *o, char **argv, const char *funcname UNUSED)
- +static size_t
- +func_or (struct vbuffer *o, char **argv, const char *funcname UNUSED)
- {
- for ( ; *argv ; ++argv)
- {
- + size_t result;
- +
- const char *begp = *argv;
- const char *endp = begp + strlen (*argv) - 1;
- - char *expansion;
- - int result = 0;
- /* Find the result of the condition: if it's false keep going. */
- @@ -1257,23 +1206,14 @@
- if (begp > endp)
- continue;
- - expansion = expand_argument (begp, endp+1);
- - result = strlen (expansion);
- + result = vbuffer_expand (o, (char *) begp, endp+1 - begp);
- /* If the result is false keep going. */
- - if (!result)
- - {
- - free (expansion);
- - continue;
- - }
- -
- - /* It's true! Keep this result and return. */
- - o = variable_buffer_output (o, expansion, result);
- - free (expansion);
- - break;
- + if (result)
- + return result;
- }
- - return o;
- + return 0;
- }
- /*
- @@ -1290,56 +1230,37 @@
- (short-circuiting).
- */
- -static char *
- -func_and (char *o, char **argv, const char *funcname UNUSED)
- +static size_t
- +func_and (struct vbuffer *o, char **argv, const char *funcname UNUSED)
- {
- - char *expansion;
- - int result;
- -
- while (1)
- {
- + size_t result;
- +
- const char *begp = *argv;
- const char *endp = begp + strlen (*argv) - 1;
- /* An empty condition is always false. */
- strip_whitespace (&begp, &endp);
- if (begp > endp)
- - return o;
- + return 0;
- - expansion = expand_argument (begp, endp+1);
- - result = strlen (expansion);
- + result = vbuffer_expand (o, (char *) begp, endp+1 - begp);
- /* If the result is false, stop here: we're done. */
- if (!result)
- - break;
- + return 0;
- /* Otherwise the result is true. If this is the last one, keep this
- result and quit. Otherwise go on to the next one! */
- if (*(++argv))
- - free (expansion);
- + vbuffer_unwrite (o, result);
- else
- - {
- - o = variable_buffer_output (o, expansion, result);
- - break;
- - }
- + return result;
- }
- - free (expansion);
- -
- - return o;
- -}
- -
- -static char *
- -func_wildcard (char *o, char **argv, const char *funcname UNUSED)
- -{
- -#ifdef _AMIGA
- - o = wildcard_expansion (argv[0], o);
- -#else
- - char *p = string_glob (argv[0]);
- - o = variable_buffer_output (o, p, strlen (p));
- -#endif
- - return o;
- + return 0;
- }
- /*
- @@ -1350,36 +1271,38 @@
- Treat the arguments as a segment of makefile, and parse them.
- */
- -static char *
- -func_eval (char *o, char **argv, const char *funcname UNUSED)
- +static size_t
- +func_eval (struct vbuffer *o UNUSED, char **argv, const char *funcname UNUSED)
- {
- - char *buf;
- - unsigned int len;
- + struct vbuffer *vbuf;
- /* Eval the buffer. Pop the current variable buffer setting so that the
- eval'd code can use its own without conflicting. */
- - install_variable_buffer (&buf, &len);
- + vbuf = install_new_expansion_vbuffer ();
- eval_buffer (argv[0]);
- - restore_variable_buffer (buf, len);
- + restore_expansion_vbuffer (vbuf);
- - return o;
- + /* Eval always expands to nothing. */
- + return 0;
- }
- -static char *
- -func_value (char *o, char **argv, const char *funcname UNUSED)
- +static size_t
- +func_value (struct vbuffer *o, char **argv, const char *funcname UNUSED)
- {
- + size_t result = 0;
- +
- /* Look up the variable. */
- struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
- /* Copy its value into the output buffer without expanding it. */
- if (v)
- - o = variable_buffer_output (o, v->value, strlen(v->value));
- + result += vbuffer_write (o, v->value, -1);
- - return o;
- + return result;
- }
- /*
- @@ -1619,9 +1542,10 @@
- #else
- #ifndef _AMIGA
- -char *
- -func_shell_base (char *o, char **argv, int trim_newlines)
- +size_t
- +func_shell_base (struct vbuffer *o, char **argv, int trim_newlines)
- {
- + size_t result = 0;
- char *batch_filename = NULL;
- #ifdef __MSDOS__
- @@ -1650,7 +1574,7 @@
- #ifdef WINDOWS32
- just_print_flag = j_p_f;
- #endif
- - return o;
- + return 0;
- }
- #endif
- @@ -1683,7 +1607,7 @@
- if (pipedes[0] < 0)
- {
- perror_with_name (error_prefix, "pipe");
- - return o;
- + return 0;
- }
- #elif defined(WINDOWS32)
- windows32_openpipe (pipedes, &pid, command_argv, envp);
- @@ -1694,14 +1618,14 @@
- {
- /* Open of the pipe failed, mark as failed execution. */
- shell_function_completed = -1;
- - return o;
- + return 0;
- }
- else
- #else
- if (pipe (pipedes) < 0)
- {
- perror_with_name (error_prefix, "pipe");
- - return o;
- + return 0;
- }
- # ifdef __EMX__
- @@ -1800,13 +1724,13 @@
- /* The child finished normally. Replace all newlines in its output
- with spaces, and put that in the variable output buffer. */
- fold_newlines (buffer, &i, trim_newlines);
- - o = variable_buffer_output (o, buffer, i);
- + result += vbuffer_write (o, buffer, i);
- }
- free (buffer);
- }
- - return o;
- + return result;
- }
- #else /* _AMIGA */
- @@ -1892,14 +1816,14 @@
- Close (child_stdout);
- fold_newlines (buffer, &i, trim_newlines);
- - o = variable_buffer_output (o, buffer, i);
- + result += vbuffer_write (o, buffer, i);
- free (buffer);
- return o;
- }
- #endif /* _AMIGA */
- -char *
- -func_shell (char *o, char **argv, const char *funcname UNUSED)
- +size_t
- +func_shell (struct vbuffer *o, char **argv, const char *funcname UNUSED)
- {
- return func_shell_base (o, argv, 1);
- }
- @@ -1914,8 +1838,7 @@
- func_eq (char *o, char **argv, char *funcname UNUSED)
- {
- int result = ! strcmp (argv[0], argv[1]);
- - o = variable_buffer_output (o, result ? "1" : "", result);
- - return o;
- + return vbuffer_write (o, result ? "1" : "", result);
- }
- @@ -1930,8 +1853,7 @@
- while (isspace ((unsigned char)*s))
- s++;
- result = ! (*s);
- - o = variable_buffer_output (o, result ? "1" : "", result);
- - return o;
- + return vbuffer_write (o, result ? "1" : "", result);
- }
- #endif
- @@ -2058,13 +1980,14 @@
- }
- -static char *
- -func_realpath (char *o, char **argv, const char *funcname UNUSED)
- +static size_t
- +func_realpath (struct vbuffer *o, char **argv, const char *funcname UNUSED)
- {
- + size_t result = 0;
- +
- /* Expand the argument. */
- const char *p = argv[0];
- const char *path = 0;
- - int doneany = 0;
- unsigned int len = 0;
- #ifndef HAVE_REALPATH
- struct stat st;
- @@ -2087,22 +2010,17 @@
- #endif
- )
- {
- - o = variable_buffer_output (o, out, strlen (out));
- - o = variable_buffer_output (o, " ", 1);
- - doneany = 1;
- + result += vbuffer_write (o, out, -1);
- + result += vbuffer_write (o, " ", 1);
- }
- }
- }
- - /* Kill last space. */
- - if (doneany)
- - --o;
- -
- - return o;
- + return result - vbuffer_unwrite (o, !!result);
- }
- -static char *
- -func_file (char *o, char **argv, const char *funcname UNUSED)
- +static size_t
- +func_file (struct vbuffer *o UNUSED, char **argv, const char *funcname UNUSED)
- {
- char *fn = argv[0];
- @@ -2137,16 +2055,17 @@
- else
- fatal (reading_file, _("Invalid file operation: %s"), fn);
- - return o;
- + return 0;
- }
- -static char *
- -func_abspath (char *o, char **argv, const char *funcname UNUSED)
- +static size_t
- +func_abspath (struct vbuffer *o, char **argv, const char *funcname UNUSED)
- {
- + size_t result = 0;
- +
- /* Expand the argument. */
- const char *p = argv[0];
- const char *path = 0;
- - int doneany = 0;
- unsigned int len = 0;
- PATH_VAR (in);
- PATH_VAR (out);
- @@ -2160,25 +2079,18 @@
- if (abspath (in, out))
- {
- - o = variable_buffer_output (o, out, strlen (out));
- - o = variable_buffer_output (o, " ", 1);
- - doneany = 1;
- + result += vbuffer_write (o, out, strlen (out));
- + result += vbuffer_write (o, " ", 1);
- }
- }
- }
- - /* Kill last space. */
- - if (doneany)
- - --o;
- -
- - return o;
- + return result - vbuffer_unwrite (o, !!result);
- }
- /* Lookup table for builtin functions.
- - This doesn't have to be sorted; we use a straight lookup. We might gain
- - some efficiency by moving most often used functions to the start of the
- - table.
- + This doesn't have to be sorted; we use hash table to perform a lookup.
- If MAXIMUM_ARGS is 0, that means there is no maximum and all
- comma-separated values are treated as arguments.
- @@ -2186,7 +2098,7 @@
- EXPAND_ARGS means that all arguments should be expanded before invocation.
- Functions that do namespace tricks (foreach) don't automatically expand. */
- -static char *func_call (char *o, char **argv, const char *funcname);
- +static size_t func_call (struct vbuffer *o, char **argv, const char *funcname);
- static struct function_table_entry function_table_init[] =
- @@ -2237,10 +2149,26 @@
- #define FUNCTION_TABLE_ENTRIES (sizeof (function_table_init) / sizeof (struct function_table_entry))
- +/* Look up a function by name. */
- +
- +#ifdef __GNUC__
- +__inline
- +#endif
- +static const struct function_table_entry *
- +lookup_function (const char *name, unsigned int length)
- +{
- + struct function_table_entry function_table_entry_key;
- + function_table_entry_key.name = name;
- + function_table_entry_key.len = length;
- +
- + return hash_find_item (&function_table, &function_table_entry_key);
- +}
- +
- +
- /* These must come after the definition of function_table. */
- -static char *
- -expand_builtin_function (char *o, int argc, char **argv,
- +static size_t
- +expand_builtin_function (struct vbuffer *o, int argc, char **argv,
- const struct function_table_entry *entry_p)
- {
- if (argc < (int)entry_p->minimum_args)
- @@ -2253,7 +2181,7 @@
- rather than in each one. We can change it later if necessary. */
- if (!argc)
- - return o;
- + return 0;
- if (!entry_p->func_ptr)
- fatal (*expanding_var,
- @@ -2264,120 +2192,134 @@
- /* Check for a function invocation in *STRINGP. *STRINGP points at the
- opening ( or { and is not null-terminated. If a function invocation
- - is found, expand it into the buffer at *OP, updating *OP, incrementing
- - *STRINGP past the reference and returning nonzero. If not, return zero. */
- + is found, expand it into the buffer O, incrementing *STRINGP past the
- + reference and returning the amount of bytes written.
- + Note, that in this case the string between the parens is destroyed.
- +
- + If no function call is recognized, return -1. */
- int
- -handle_function (char **op, const char **stringp)
- +handle_function (struct vbuffer *o, char **stringp)
- {
- + size_t ret = 0;
- +
- const struct function_table_entry *entry_p;
- char openparen = (*stringp)[0];
- char closeparen = openparen == '(' ? ')' : '}';
- - const char *beg;
- - const char *end;
- - int count = 0;
- - char *abeg = NULL;
- + char *beg;
- + char *end;
- + int count;
- char **argv, **argvp;
- - int nargs;
- + int nargs, maxargs;
- + struct vbuffer argbuf;
- + size_t reserved;
- beg = *stringp + 1;
- - entry_p = lookup_function (beg);
- + end = beg;
- + while ((*end >= 'a' && *end <= 'z') || *end == '-')
- + end++;
- + if (*end != ' ' && *end != '\t')
- + return -1;
- + entry_p = lookup_function (beg, end - beg);
- if (!entry_p)
- - return 0;
- + return -1;
- /* We found a builtin function. Find the beginning of its arguments (skip
- whitespace after the name). */
- - beg = next_token (beg + entry_p->len);
- + beg = next_token (end);
- + maxargs = entry_p->maximum_args;
- /* Find the end of the function invocation, counting nested use of
- - whichever kind of parens we use. Since we're looking, count commas
- - to get a rough estimate of how many arguments we might have. The
- - count might be high, but it'll never be low. */
- -
- - for (nargs=1, end=beg; *end != '\0'; ++end)
- - if (*end == ',')
- - ++nargs;
- - else if (*end == openparen)
- + whichever kind of parens we use and isolating arguments.
- + As soon as we hit up to MAXARGS (if it is positive) assume the rest of
- + the string is part of the last argument. For each argument, we save
- + a pointer into the ARGBUF and NULL-terminate the argument value. */
- +#define VBUFFER_WRITE_PTR(o, value) \
- + *((char **) (((o)->ptr += sizeof (char *)) - sizeof (char *))) = (value)
- +
- + vbuffer_init (&argbuf);
- + reserved = argbuf.size - sizeof (char *);
- +
- + VBUFFER_WRITE_PTR (&argbuf, beg);
- +
- + nargs=1;
- + count = 0;
- + for (end=beg; *end != '\0'; ++end)
- + if (*end == openparen)
- ++count;
- else if (*end == closeparen && --count < 0)
- break;
- + else if (count == 0 && *end == ',' && nargs != maxargs)
- + {
- + *end = '\0';
- + nargs++;
- +
- + if (reserved <= 2 * sizeof (char *))
- + reserved = vbuffer_reserve (&argbuf, 2 * sizeof (char *));
- + else
- + reserved -= sizeof (char *);
- +
- + VBUFFER_WRITE_PTR (&argbuf, end+1);
- + }
- if (count >= 0)
- fatal (*expanding_var,
- _("unterminated call to function '%s': missing '%c'"),
- entry_p->name, closeparen);
- - *stringp = end;
- + /* NULL-terminate the last argument. */
- + *end = '\0';
- - /* Get some memory to store the arg pointers. */
- - argvp = argv = alloca (sizeof (char *) * (nargs + 2));
- + /* NULL-terminate the arg vector (assume there was enough room reserved). */
- + VBUFFER_WRITE_PTR (&argbuf, NULL);
- - /* Chop the string into arguments, then a nul. As soon as we hit
- - MAXIMUM_ARGS (if it's >0) assume the rest of the string is part of the
- - last argument.
- -
- - If we're expanding, store pointers to the expansion of each one. If
- - not, make a duplicate of the string and point into that, nul-terminating
- - each argument. */
- + argv = (char **) argbuf.buffer;
- - if (entry_p->expand_args)
- - {
- - const char *p;
- - for (p=beg, nargs=0; p <= end; ++argvp)
- - {
- - const char *next;
- + /* If the function requires argument to be expanded, expand them into the
- + same buffer as we used to for the arg vector, but store pointers to the
- + expansion of each one into a new stack-allocated vector.
- - ++nargs;
- + This, in turn, is performed in two steps:
- + - First, we save position-independent offsets into a special buffer.
- + - Next, build the final arg vector from the offsets buffer.
- - if (nargs == entry_p->maximum_args
- - || (! (next = find_next_argument (openparen, closeparen, p, end))))
- - next = end;
- + Involving an intermediate buffer for the offsets is necessary because
- + ARGBUF may grow while expanding an argument thus invalidating any
- + previously stored pointers. */
- - *argvp = expand_argument (p, next);
- - p = next + 1;
- - }
- - }
- - else
- + if (entry_p->expand_args)
- {
- - int len = end - beg;
- - char *p, *aend;
- -
- - abeg = xmalloc (len+1);
- - memcpy (abeg, beg, len);
- - abeg[len] = '\0';
- - aend = abeg + len;
- -
- - for (p=abeg, nargs=0; p <= aend; ++argvp)
- - {
- - char *next;
- -
- - ++nargs;
- -
- - if (nargs == entry_p->maximum_args
- - || (! (next = find_next_argument (openparen, closeparen, p, aend))))
- - next = aend;
- -
- - *argvp = p;
- - *next = '\0';
- - p = next + 1;
- - }
- + int i;
- + size_t *offs = alloca ((nargs + 1) * sizeof (size_t));
- + argv = memcpy (alloca ((nargs + 1) * sizeof (char *)),
- + argv, (nargs + 1) * sizeof (char *));
- +
- + vbuffer_reset (&argbuf);
- + offs[0] = 0;
- + for (i=0, argvp=argv; *argvp != 0; ++argvp, ++i)
- + {
- + offs[i + 1] = offs[i] + vbuffer_expand (&argbuf, *argvp, -1) + 1;
- + *(++argbuf.ptr) = '\0';
- + }
- + for (i=0, argvp=argv; *argvp != 0; ++argvp, ++i)
- + *argvp = argbuf.buffer + offs[i];
- }
- - *argvp = NULL;
- /* Finally! Run the function... */
- - *op = expand_builtin_function (*op, nargs, argv, entry_p);
- + ret += expand_builtin_function (o, nargs, argv, entry_p);
- - /* Free memory. */
- - if (entry_p->expand_args)
- - for (argvp=argv; *argvp != 0; ++argvp)
- - free (*argvp);
- - else if (abeg)
- - free (abeg);
- + /* Restore a paren after the last argument and advance the STRINGP. */
- + *end = closeparen;
- + *stringp = end;
- +
- + vbuffer_free (&argbuf);
- +
- +#undef VBUFFER_WRITE_PTR
- - return 1;
- + return ret;
- }
- @@ -2385,37 +2327,41 @@
- function or a make variable, in the context of the rest of the arguments
- assigned to $1, $2, ... $N. $0 is the name of the function. */
- -static char *
- -func_call (char *o, char **argv, const char *funcname UNUSED)
- +static size_t
- +func_call (struct vbuffer *o, char **argv, const char *funcname UNUSED)
- {
- - static int max_args = 0;
- + size_t ret = 0;
- +
- char *fname;
- char *cp;
- - char *body;
- int flen;
- int i;
- - int saved_args;
- + int argc;
- const struct function_table_entry *entry_p;
- struct variable *v;
- /* There is no way to define a variable with a space in the name, so strip
- - leading and trailing whitespace as a favor to the user. */
- + trailing whitespace as a favor to the user. */
- fname = argv[0];
- while (*fname != '\0' && isspace ((unsigned char)*fname))
- ++fname;
- - cp = fname + strlen (fname) - 1;
- + flen = strlen (fname);
- +
- + cp = fname + flen - 1;
- while (cp > fname && isspace ((unsigned char)*cp))
- --cp;
- cp[1] = '\0';
- /* Calling nothing is a no-op */
- if (*fname == '\0')
- - return o;
- + return 0;
- - /* Are we invoking a builtin function? */
- + /* Fix up the length after stripping a trailing whitespace. */
- + flen = cp - fname + 1;
- - entry_p = lookup_function (fname);
- + /* Are we invoking a builtin function? */
- + entry_p = lookup_function (fname, flen);
- if (entry_p)
- {
- /* How many arguments do we have? */
- @@ -2426,7 +2372,6 @@
- /* Not a builtin, so the first argument is the name of a variable to be
- expanded and interpreted as a function. Find it. */
- - flen = strlen (fname);
- v = lookup_variable (fname, flen);
- @@ -2434,61 +2379,42 @@
- warn_undefined (fname, flen);
- if (v == 0 || *v->value == '\0')
- - return o;
- -
- - body = alloca (flen + 4);
- - body[0] = '$';
- - body[1] = '(';
- - memcpy (body + 2, fname, flen);
- - body[flen+2] = ')';
- - body[flen+3] = '\0';
- -
- - /* Set up arguments $(1) .. $(N). $(0) is the function name. */
- -
- - push_new_variable_scope ();
- -
- - for (i=0; *argv; ++i, ++argv)
- - {
- - char num[11];
- -
- - sprintf (num, "%d", i);
- - define_variable (num, strlen (num), *argv, o_automatic, 0);
- - }
- -
- - /* If the number of arguments we have is < max_args, it means we're inside
- - a recursive invocation of $(call ...). Fill in the remaining arguments
- - in the new scope with the empty value, to hide them from this
- - invocation. */
- -
- - for (; i < max_args; ++i)
- - {
- - char num[11];
- -
- - sprintf (num, "%d", i);
- - define_variable (num, strlen (num), "", o_automatic, 0);
- - }
- + return 0;
- - /* Expand the body in the context of the arguments, adding the result to
- - the variable buffer. */
- + if (!v->recursive)
- + return vbuffer_write(o, v->value, -1);
- - v->exp_count = EXP_COUNT_MAX;
- + /* Count the arguments. */
- + argc = 0;
- + while (argv[++argc])
- + ;
- - saved_args = max_args;
- - max_args = i;
- - o = variable_expand_string (o, body, flen+3);
- - max_args = saved_args;
- + {
- + struct call_frame new_frame;
- + struct call_frame *saved_frame = current_call_frame;
- - v->exp_count = 0;
- + /* Replace the current call frame with a new one. */
- + new_frame.argc = argc;
- + new_frame.argv = argv;
- + current_call_frame = &new_frame;
- +
- + /* Expand the variable in the context of the arguments,
- + writing the result into the variable buffer. */
- + v->exp_count = EXP_COUNT_MAX;
- + ret += vbuffer_expand_variable (o, v);
- + v->exp_count = 0;
- - pop_variable_scope ();
- + current_call_frame = saved_frame;
- + }
- - return o + strlen (o);
- + return ret;
- }
- +
- void
- define_new_function(const struct floc *flocp,
- const char *name, int min, int max, int expand,
- - char *(*func)(char *, char **, const char *))
- + size_t (*func)(struct vbuffer *, char **, const char *))
- {
- size_t len = strlen (name);
- struct function_table_entry *ent = xmalloc (sizeof (struct function_table_entry));
- Index: guile.c
- ===================================================================
- RCS file: /sources/make/make/guile.c,v
- retrieving revision 2.5
- diff -u -r2.5 guile.c
- --- guile.c 5 Mar 2012 14:10:44 -0000 2.5
- +++ guile.c 9 Apr 2012 13:34:41 -0000
- @@ -86,20 +86,22 @@
- }
- /* This is the function registered with make */
- -static char *
- -func_guile (char *o, char **argv, const char *funcname UNUSED)
- +static size_t
- +func_guile (struct vbuffer *o, char **argv, const char *funcname UNUSED)
- {
- + size_t result = 0;
- +
- if (argv[0] && argv[0][0] != '\0')
- {
- char *str = scm_with_guile (internal_guile_eval, argv[0]);
- if (str)
- {
- - o = variable_buffer_output (o, str, strlen (str));
- + result += vbuffer_write (o, str, -1);
- free (str);
- }
- }
- - return o;
- + return result;
- }
- /* ----- Public interface ----- */
- Index: main.c
- ===================================================================
- RCS file: /sources/make/make/main.c,v
- retrieving revision 1.256
- diff -u -r1.256 main.c
- --- main.c 5 Mar 2012 14:10:44 -0000 1.256
- +++ main.c 9 Apr 2012 13:34:42 -0000
- @@ -1104,6 +1104,8 @@
- initialize_global_hash_tables ();
- + install_new_expansion_vbuffer();
- +
- /* Figure out where we are. */
- #ifdef WINDOWS32
- @@ -2277,12 +2279,7 @@
- if (default_goal_var->recursive)
- p = variable_expand (default_goal_var->value);
- else
- - {
- - p = variable_buffer_output (variable_buffer, default_goal_var->value,
- - strlen (default_goal_var->value));
- - *p = '\0';
- - p = variable_buffer;
- - }
- + p = default_goal_var->value;
- if (*p != '\0')
- {
- @@ -2359,6 +2356,16 @@
- if (clock_skew_detected)
- error (NILF,
- _("warning: Clock skew detected. Your build may be incomplete."));
- +// error (NILF,
- +// "memory_usage: %10d total: %8d mallocs, %8d reallocs, %8d strdups",
- +// nr_mallocs + nr_reallocs + nr_strdups,
- +// nr_mallocs, nr_reallocs, nr_strdups);
- +// error (NILF,
- +// "hash: %10d cmps, %8d hash1, %8d hash2",
- +// nr_cmps, nr_hash1, nr_hash2);
- +// error (NILF,
- +// "max_lookup_depth: %10d, miss: %10d",
- +// max_lookup_depth, lookup_miss);
- /* Exit. */
- die (status);
- Index: make.h
- ===================================================================
- RCS file: /sources/make/make/make.h,v
- retrieving revision 1.157
- diff -u -r1.157 make.h
- --- make.h 5 Mar 2012 14:10:44 -0000 1.157
- +++ make.h 9 Apr 2012 13:34:42 -0000
- @@ -21,6 +21,9 @@
- #undef HAVE_CONFIG_H
- #define HAVE_CONFIG_H 1
- +extern int nr_mallocs, nr_reallocs, nr_strdups, nr_cmps, nr_hash1, nr_hash2;
- +extern int max_lookup_depth, lookup_miss;
- +
- /* Specify we want GNU source code. This must be defined before any
- system headers are included. */
- @@ -406,11 +409,32 @@
- void *xrealloc (void *, unsigned int);
- char *xstrdup (const char *);
- char *xstrndup (const char *, unsigned int);
- +
- char *find_next_token (const char **, unsigned int *);
- -char *next_token (const char *);
- -char *end_of_token (const char *);
- +
- +/* The following three functions are used extremely frequently,
- + so we try to inline them where possible. */
- +#ifdef __GNUC__
- +
- +static __inline char *
- +next_token (const char *s)
- + { return (char *) s + strspn (s, " \t"); }
- +
- +static __inline char *
- +end_of_token (const char *s)
- + { return (char *) s + strcspn (s, " \t"); }
- +
- +static __inline char *
- +lindex (const char *s, const char *limit, int c)
- + { return memchr (s, c, limit - s); }
- +
- +#else
- +char *next_token (const char *s);
- +char *end_of_token (const char *s);
- +char *lindex (const char *s, const char *limit, int c);
- +#endif /* __GNUC__ */
- +
- void collapse_continuations (char *);
- -char *lindex (const char *, const char *, int);
- int alpha_compare (const void *, const void *);
- void print_spaces (unsigned int);
- char *find_percent (char *);
- Index: misc.c
- ===================================================================
- RCS file: /sources/make/make/misc.c,v
- retrieving revision 1.89
- diff -u -r1.89 misc.c
- --- misc.c 5 Mar 2012 14:10:44 -0000 1.89
- +++ misc.c 9 Apr 2012 13:34:42 -0000
- @@ -360,6 +360,8 @@
- /* Like malloc but get fatal error if memory is exhausted. */
- /* Don't bother if we're using dmalloc; it provides these for us. */
- +int nr_mallocs, nr_reallocs, nr_strdups, nr_cmps, nr_hash1, nr_hash2;
- +
- #ifndef HAVE_DMALLOC_H
- #undef xmalloc
- @@ -372,6 +374,7 @@
- {
- /* Make sure we don't allocate 0, for pre-ISO implementations. */
- void *result = malloc (size ? size : 1);
- +// ++nr_mallocs;
- if (result == 0)
- fatal (NILF, _("virtual memory exhausted"));
- return result;
- @@ -383,6 +386,7 @@
- {
- /* Make sure we don't allocate 0, for pre-ISO implementations. */
- void *result = calloc (size ? size : 1, 1);
- +// ++nr_mallocs;
- if (result == 0)
- fatal (NILF, _("virtual memory exhausted"));
- return result;
- @@ -393,6 +397,7 @@
- xrealloc (void *ptr, unsigned int size)
- {
- void *result;
- +// ++nr_reallocs;
- /* Some older implementations of realloc() don't conform to ISO. */
- if (! size)
- @@ -408,6 +413,7 @@
- xstrdup (const char *ptr)
- {
- char *result;
- +// ++nr_strdups;
- #ifdef HAVE_STRDUP
- result = strdup (ptr);
- @@ -431,6 +437,7 @@
- xstrndup (const char *str, unsigned int length)
- {
- char *result;
- +// ++nr_strdups;
- #ifdef HAVE_STRNDUP
- result = strndup (str, length);
- @@ -447,6 +454,7 @@
- }
- +#ifndef __GNUC__
- /* Limited INDEX:
- Search through the string STRING, which ends at LIMIT, for the character C.
- Returns a pointer to the first occurrence, or nil if none is found.
- @@ -456,11 +464,7 @@
- char *
- lindex (const char *s, const char *limit, int c)
- {
- - while (s < limit)
- - if (*s++ == c)
- - return (char *)(s - 1);
- -
- - return 0;
- + return memchr (s, c, limit - s);
- }
- /* Return the address of the first whitespace or null in the string S. */
- @@ -468,10 +472,9 @@
- char *
- end_of_token (const char *s)
- {
- - while (*s != '\0' && !isblank ((unsigned char)*s))
- - ++s;
- - return (char *)s;
- + return (char *) s + strcspn (s, " \t");
- }
- +#endif /* !__GNUC__ */
- #ifdef WINDOWS32
- /*
- @@ -503,15 +506,15 @@
- }
- #endif
- +#ifndef __GNUC__
- /* Return the address of the first nonwhitespace or null in the string S. */
- char *
- next_token (const char *s)
- {
- - while (isblank ((unsigned char)*s))
- - ++s;
- - return (char *)s;
- + return (char *) s + strspn (s, " \t");
- }
- +#endif /* !__GNUC__ */
- /* Find the next token in PTR; return the address of it, and store the length
- of the token into *LENGTHPTR if LENGTHPTR is not nil. Set *PTR to the end
- Index: read.c
- ===================================================================
- RCS file: /sources/make/make/read.c,v
- retrieving revision 1.210
- diff -u -r1.210 read.c
- --- read.c 5 Mar 2012 14:10:44 -0000 1.210
- +++ read.c 9 Apr 2012 13:34:42 -0000
- @@ -566,6 +566,7 @@
- const char *pattern_percent;
- struct floc *fstart;
- struct floc fi;
- + struct vbuffer vbuf;
- #define record_waiting_files() \
- do \
- @@ -583,6 +584,8 @@
- pattern = 0; \
- } while (0)
- + vbuffer_init(&vbuf);
- +
- pattern_percent = 0;
- cmds_started = tgts_started = 1;
- @@ -893,6 +896,7 @@
- {
- enum make_word_type wtype;
- char *cmdleft, *semip, *lb_next;
- + unsigned int llen = 0;
- unsigned int plen = 0;
- char *colonp;
- const char *end, *beg; /* Helpers for whitespace stripping. */
- @@ -943,7 +947,8 @@
- break;
- }
- - p2 = variable_expand_string(NULL, lb_next, wlen);
- + vbuffer_expand_ro (vbuffer_reset(&vbuf), lb_next, wlen);
- + p2 = vbuf.buffer;
- while (1)
- {
- @@ -955,9 +960,8 @@
- if (cmdleft != 0)
- {
- - unsigned long p2_off = p2 - variable_buffer;
- - unsigned long cmd_off = cmdleft - variable_buffer;
- - char *pend = p2 + strlen(p2);
- + unsigned long p2_off = p2 - vbuf.buffer;
- + unsigned long cmd_off = cmdleft - vbuf.buffer;
- /* Append any remnants of lb, then cut the line short
- at the semicolon. */
- @@ -967,14 +971,16 @@
- here, but merely copy, since now you're beyond a ";"
- and into a command script. However, the old parser
- expanded the whole line, so we continue that for
- - backwards-compatiblity. Also, it wouldn't be
- + backwards-compatibility. Also, it wouldn't be
- entirely consistent, since we do an unconditional
- expand below once we know we don't have a
- target-specific variable. */
- - (void)variable_expand_string(pend, lb_next, (long)-1);
- + vbuffer_expand_ro (&vbuf, lb_next, -1);
- +
- + p2 = vbuf.buffer + p2_off;
- + cmdleft = vbuf.buffer + cmd_off + 1;
- +
- lb_next += strlen(lb_next);
- - p2 = variable_buffer + p2_off;
- - cmdleft = variable_buffer + cmd_off + 1;
- }
- }
- @@ -996,15 +1002,16 @@
- if (wtype == w_eol)
- break;
- - p2 += strlen(p2);
- - *(p2++) = ' ';
- - p2 = variable_expand_string(p2, lb_next, wlen);
- + vbuffer_write(&vbuf, " ", 1);
- + plen = vbuffer_expand_ro (&vbuf, lb_next, wlen);
- + p2 = vbuf.ptr - plen;
- +
- /* We don't need to worry about cmdleft here, because if it was
- found in the variable_buffer the entire buffer has already
- been expanded... we'll never get here. */
- }
- - p2 = next_token (variable_buffer);
- + p2 = next_token (vbuf.buffer);
- /* If the word we're looking at is EOL, see if there's _anything_
- on the line. If not, a variable expanded to nothing, so ignore
- @@ -1045,14 +1052,13 @@
- /* Test to see if it's a target-specific variable. Copy the rest
- of the buffer over, possibly temporarily (we'll expand it later
- - if it's not a target-specific variable). PLEN saves the length
- - of the unparsed section of p2, for later. */
- + if it's not a target-specific variable). LLEN saves the length
- + of the copied string, to know how many bytes to discard later. */
- if (*lb_next != '\0')
- {
- - unsigned int l = p2 - variable_buffer;
- - plen = strlen (p2);
- - variable_buffer_output (p2+plen, lb_next, strlen (lb_next)+1);
- - p2 = variable_buffer + l;
- + unsigned long p2_off = p2 - vbuf.buffer;
- + llen = vbuffer_write (&vbuf, lb_next, -1);
- + p2 = vbuf.buffer + p2_off;
- }
- p2 = parse_var_assignment (p2, &vmod);
- @@ -1062,12 +1068,11 @@
- after it. */
- if (semip)
- {
- - unsigned int l = p - variable_buffer;
- + unsigned long p2_off = p2 - vbuf.buffer;
- *(--semip) = ';';
- collapse_continuations (semip);
- - variable_buffer_output (p2 + strlen (p2),
- - semip, strlen (semip)+1);
- - p = variable_buffer + l;
- + vbuffer_write (&vbuf, semip, -1);
- + p2 = vbuf.buffer + p2_off;
- }
- record_target_var (filenames, p2,
- vmod.override_v ? o_override : o_file,
- @@ -1086,12 +1091,14 @@
- /* We have some targets, so don't ignore the following commands. */
- no_targets = 0;
- - /* Expand the dependencies, etc. */
- + /* Expand the dependencies, etc.
- + P2 still point past the colon. */
- if (*lb_next != '\0')
- {
- - unsigned int l = p2 - variable_buffer;
- - (void) variable_expand_string (p2 + plen, lb_next, (long)-1);
- - p2 = variable_buffer + l;
- + unsigned long p2_off = p2 - vbuf.buffer;
- + vbuffer_unwrite (&vbuf, llen);
- + vbuffer_expand_ro (&vbuf, lb_next, -1);
- + p2 = vbuf.buffer + p2_off;
- /* Look for a semicolon in the expanded line. */
- if (cmdleft == 0)
- @@ -1281,8 +1288,6 @@
- record_waiting_files ();
- }
- -#undef word1eq
- -
- if (conditionals->if_cmds)
- fatal (fstart, _("missing 'endif'"));
- @@ -1292,7 +1297,13 @@
- if (collapsed)
- free (collapsed);
- free (commands);
- +
- + vbuffer_free(&vbuf);
- +
- +#undef record_waiting_files
- }
- +
- +#undef word1eq
- /* Remove comments from LINE.
- @@ -1842,6 +1853,7 @@
- struct dep *deps;
- const char *implicit_percent;
- const char *name;
- + struct vbuffer patbuf;
- /* If we've already snapped deps, that means we're in an eval being
- resolved after the makefiles have been read in. We can't add more rules
- @@ -1945,6 +1957,7 @@
- return;
- }
- + vbuffer_init (&patbuf);
- /* Walk through each target and create it in the database.
- We already set up the first target, above. */
- @@ -2057,10 +2070,12 @@
- if (pattern)
- {
- static const char *percent = "%";
- - char *buffer = variable_expand ("");
- - char *o = patsubst_expand_pat (buffer, name, pattern, percent,
- - pattern_percent+1, percent+1);
- - f->stem = strcache_add_len (buffer, o - buffer);
- + size_t len;
- +
- + len = patsubst_expand_pat (vbuffer_reset(&patbuf), name,
- + pattern, percent,
- + pattern_percent+1, percent+1);
- + f->stem = strcache_add_len (patbuf.buffer, len);
- if (this)
- {
- if (! this->need_2nd_expansion)
- @@ -2112,6 +2127,8 @@
- if (find_percent_cached (&name))
- fatal (flocp, _("mixed implicit and normal rules"));
- }
- +
- + vbuffer_free (&patbuf);
- }
- /* Search STRING for an unquoted STOPCHAR or blank (if BLANK is nonzero).
- Index: remake.c
- ===================================================================
- RCS file: /sources/make/make/remake.c,v
- retrieving revision 1.153
- diff -u -r1.153 remake.c
- --- remake.c 5 Mar 2012 14:10:45 -0000 1.153
- +++ remake.c 9 Apr 2012 13:34:42 -0000
- @@ -1534,12 +1534,14 @@
- const char *p2;
- unsigned int len;
- unsigned int liblen;
- + struct vbuffer vbuf;
- /* Information about the earliest (in the vpath sequence) match. */
- unsigned int best_vpath = 0, best_path = 0;
- char **dp;
- + vbuffer_init(&vbuf);
- libpatterns = xstrdup (variable_expand ("$(.LIBPATTERNS)"));
- /* Skip the '-l'. */
- @@ -1556,28 +1558,30 @@
- static unsigned int buflen = 0;
- static int libdir_maxlen = -1;
- static unsigned int std_dirs = 0;
- - char *libbuf = variable_expand ("");
- + char *libbuf;
- /* Expand the pattern using LIB as a replacement. */
- {
- char c = p[len];
- - char *p3, *p4;
- + char *percent;
- p[len] = '\0';
- - p3 = find_percent (p);
- - if (!p3)
- + percent = find_percent (p);
- + if (!percent)
- {
- /* Give a warning if there is no pattern. */
- error (NILF, _(".LIBPATTERNS element '%s' is not a pattern"), p);
- p[len] = c;
- continue;
- }
- - p4 = variable_buffer_output (libbuf, p, p3-p);
- - p4 = variable_buffer_output (p4, lib, liblen);
- - p4 = variable_buffer_output (p4, p3+1, len - (p3-p));
- + vbuffer_write (&vbuf, p, percent-p);
- + vbuffer_write (&vbuf, lib, liblen);
- + vbuffer_write (&vbuf, percent+1, len - (percent-p));
- p[len] = c;
- }
- + libbuf = vbuf.buffer;
- +
- /* Look first for 'libNAME.a' in the current directory. */
- mtime = name_mtime (libbuf);
- if (mtime != NONEXISTENT_MTIME)
- @@ -1660,5 +1664,7 @@
- }
- free (libpatterns);
- + vbuffer_free(&vbuf);
- +
- return file;
- }
- Index: variable.c
- ===================================================================
- RCS file: /sources/make/make/variable.c,v
- retrieving revision 1.112
- diff -u -r1.112 variable.c
- --- variable.c 5 Mar 2012 14:10:45 -0000 1.112
- +++ variable.c 9 Apr 2012 13:34:42 -0000
- @@ -172,6 +172,7 @@
- static struct variable_set_list global_setlist
- = { 0, &global_variable_set, 0 };
- struct variable_set_list *current_variable_set_list = &global_setlist;
- +
- /* Implement variables. */
- @@ -182,18 +183,19 @@
- variable_hash_1, variable_hash_2, variable_hash_cmp);
- }
- -/* Define variable named NAME with value VALUE in SET. VALUE is copied.
- +/* Define variable named NAME with value VALUE in SET. VALUE is NOT copied,
- + and after a call client must check whether the VALUE is assigned or not.
- LENGTH is the length of NAME, which does not need to be null-terminated.
- ORIGIN specifies the origin of the variable (makefile, command line
- or environment).
- If RECURSIVE is nonzero a flag is set in the variable saying
- that it should be recursively re-expanded. */
- -struct variable *
- -define_variable_in_set (const char *name, unsigned int length,
- - const char *value, enum variable_origin origin,
- - int recursive, struct variable_set *set,
- - const struct floc *flocp)
- +static struct variable *
- +define_variable_in_set_allocated (const char *name, unsigned int length,
- + const char *value, enum variable_origin origin,
- + int recursive, struct variable_set *set,
- + const struct floc *flocp)
- {
- struct variable *v;
- struct variable **var_slot;
- @@ -224,7 +226,7 @@
- {
- if (v->value != 0)
- free (v->value);
- - v->value = xstrdup (value);
- + v->value = (char *) value;
- if (flocp != 0)
- v->fileinfo = *flocp;
- else
- @@ -241,7 +243,7 @@
- v->name = xstrndup (name, length);
- v->length = length;
- hash_insert_at (&set->table, v, var_slot);
- - v->value = xstrdup (value);
- + v->value = (char *) value;
- if (flocp != 0)
- v->fileinfo = *flocp;
- else
- @@ -254,6 +256,8 @@
- v->per_target = 0;
- v->append = 0;
- v->private_var = 0;
- + v->volatile_var = 0;
- + v->global = set == &global_variable_set;
- v->export = v_default;
- v->exportable = 1;
- @@ -275,6 +279,71 @@
- }
- +struct variable *
- +define_variable_in_set (const char *name, unsigned int length,
- + const char *value, enum variable_origin origin,
- + int recursive, struct variable_set *set,
- + const struct floc *flocp)
- +{
- + struct variable *v = define_variable_in_set_allocated (name, length, value,
- + origin, recursive,
- + set, flocp);
- + /* Check if the new value was really assigned. */
- + if (v->value == value)
- + v->value = xstrdup (value);
- +
- + return v;
- +}
- +
- +struct variable *
- +push_scoped_variable (struct variable *v, char *name, unsigned int length)
- +{
- + struct variable_set *set = current_variable_set_list->set;
- + struct variable *old_var;
- + struct variable **var_slot;
- +
- + v->name = name;
- + v->length = length;
- + var_slot = (struct variable **) hash_find_slot (&set->table, v);
- +
- + old_var = *var_slot;
- + if (HASH_VACANT (old_var))
- + old_var = NULL;
- +
- + hash_insert_at (&set->table, v, var_slot);
- +
- + v->fileinfo.filenm = NULL;
- + v->origin = o_automatic;
- + v->recursive = 0;
- + v->special = 0;
- + v->expanding = 0;
- + v->exp_count = 0;
- + v->per_target = 0;
- + v->append = 0;
- + v->private_var = 0;
- + v->volatile_var = 0;
- + v->exportable = 0;
- + v->export = v_default;
- +
- + v->global = old_var ? old_var->global : 0;
- +
- + return old_var;
- +}
- +
- +void
- +pop_scoped_variable (struct variable *v, struct variable *old_var)
- +{
- + struct variable_set *set = current_variable_set_list->set;
- + struct variable **var_slot;
- +
- + var_slot = (struct variable **) hash_find_slot (&set->table, v);
- +
- + if (old_var)
- + hash_insert_at (&set->table, old_var, var_slot);
- + else
- + hash_delete_at (&set->table, var_slot);
- +}
- +
- /* Undefine variable named NAME in SET. LENGTH is the length of NAME, which
- does not need to be null-terminated. ORIGIN specifies the origin of the
- variable (makefile, command line or environment). */
- @@ -361,7 +430,8 @@
- */
- if (streq (var->name, ".VARIABLES")
- - && global_variable_set.table.ht_fill != last_var_count)
- +// && global_variable_set.table.ht_fill != last_var_count
- + )
- {
- unsigned long max = EXPANSION_INCREMENT (strlen (var->value));
- unsigned long len;
- @@ -381,6 +451,9 @@
- struct variable *v = *vp;
- int l = v->length;
- + if (!v->global)
- + continue;
- +
- len += l + 1;
- if (len > max)
- {
- @@ -408,26 +481,89 @@
- }
- +static struct call_frame empty_call_frame;
- +struct call_frame *current_call_frame = &empty_call_frame;
- +
- +#ifdef __GNUC__
- +__inline
- +#endif
- +char **
- +lookup_call_argument_value (const char *name, unsigned int length)
- +{
- + int num = 0;
- + const char *p;
- +
- + /* Hot path: a single digit. */
- + if (length == 1
- + && (unsigned) *name - '0' < (unsigned) current_call_frame->argc)
- + return current_call_frame->argv + (*name - '0');
- +
- + /* Empty name or name with leading zeroes is not numeric. */
- + if (length == 0 || *name == '0')
- + return NULL;
- +
- + for (p=name; length != 0 && ISDIGIT(*p); --length, ++p)
- + {
- + num *= 10;
- + num += *p - '0';
- + }
- +
- + if (length != 0 || num >= current_call_frame->argc)
- + return NULL;
- +
- + return current_call_frame->argv + num;
- +}
- +
- +#define CALL_ARGUMENT_INIT \
- + { \
- + /* name */ "", /* value */ "", \
- + /* file */ { NULL, 0}, /* length */ 0, \
- + /* recursive */ 0, /* append */ 0, \
- + /* conditional */ 0, /* per_target */ 0, \
- + /* special */ 0, /* exportable */ 0, \
- + /* expanding */ 0, /* private */ 0, \
- + /* volatile */ 1, /* global */ 0, \
- + /* exp_count */ 0, \
- + f_simple, o_automatic, v_default, \
- + }
- +
- /* Lookup a variable whose name is a string starting at NAME
- and with LENGTH chars. NAME need not be null-terminated.
- Returns address of the 'struct variable' containing all info
- - on the variable, or nil if no such variable is defined. */
- + on the variable, or nil if no such variable is defined.
- + In case when the variable is an argument of the current call frame,
- + the 'struct variable' refers to the shared statically allocated instance,
- + and its 'volatile_var' field is set to 1. */
- struct variable *
- lookup_variable (const char *name, unsigned int length)
- {
- + static struct variable call_argument = CALL_ARGUMENT_INIT;
- const struct variable_set_list *setlist;
- + struct variable *v = NULL;
- struct variable var_key;
- int is_parent = 0;
- var_key.name = (char *) name;
- var_key.length = length;
- + if (ISDIGIT(*name))
- + {
- + char **argp = lookup_call_argument_value (name, length);
- + if (argp && *argp)
- + {
- + v = &call_argument;
- + v->value = *argp;
- + v->name = (char *) name;
- + v->length = length;
- + return v;
- + }
- + }
- +
- for (setlist = current_variable_set_list;
- setlist != 0; setlist = setlist->next)
- {
- const struct variable_set *set = setlist->set;
- - struct variable *v;
- v = (struct variable *) hash_find_item ((struct hash_table *) &set->table, &var_key);
- if (v && (!is_parent || !v->private_var))
- @@ -494,6 +630,7 @@
- return 0;
- }
- +
- /* Lookup a variable whose name is a string starting at NAME
- and with LENGTH chars in set SET. NAME need not be null-terminated.
- @@ -512,6 +649,7 @@
- return (struct variable *) hash_find_item ((struct hash_table *) &set->table, &var_key);
- }
- +
- /* Initialize FILE's variable set list. If FILE already has a variable set
- list, the topmost variable set is left intact, but the the rest of the
- chain is replaced with FILE->parent's setlist. If FILE is a double-colon
- @@ -621,8 +759,6 @@
- }
- }
- -/* Pop the top set off the current variable set list,
- - and free all its storage. */
- struct variable_set_list *
- create_new_variable_set (void)
- @@ -660,66 +796,6 @@
- free (list);
- }
- -/* Create a new variable set and push it on the current setlist.
- - If we're pushing a global scope (that is, the current scope is the global
- - scope) then we need to "push" it the other way: file variable sets point
- - directly to the global_setlist so we need to replace that with the new one.
- - */
- -
- -struct variable_set_list *
- -push_new_variable_scope (void)
- -{
- - current_variable_set_list = create_new_variable_set();
- - if (current_variable_set_list->next == &global_setlist)
- - {
- - /* It was the global, so instead of new -> &global we want to replace
- - &global with the new one and have &global -> new, with current still
- - pointing to &global */
- - struct variable_set *set = current_variable_set_list->set;
- - current_variable_set_list->set = global_setlist.set;
- - global_setlist.set = set;
- - current_variable_set_list->next = global_setlist.next;
- - global_setlist.next = current_variable_set_list;
- - current_variable_set_list = &global_setlist;
- - }
- - return (current_variable_set_list);
- -}
- -
- -void
- -pop_variable_scope (void)
- -{
- - struct variable_set_list *setlist;
- - struct variable_set *set;
- -
- - /* Can't call this if there's no scope to pop! */
- - assert(current_variable_set_list->next != NULL);
- -
- - if (current_variable_set_list != &global_setlist)
- - {
- - /* We're not pointing to the global setlist, so pop this one. */
- - setlist = current_variable_set_list;
- - set = setlist->set;
- - current_variable_set_list = setlist->next;
- - }
- - else
- - {
- - /* This set is the one in the global_setlist, but there is another global
- - set beyond that. We want to copy that set to global_setlist, then
- - delete what used to be in global_setlist. */
- - setlist = global_setlist.next;
- - set = global_setlist.set;
- - global_setlist.set = setlist->set;
- - global_setlist.next = setlist->next;
- - global_setlist.next_is_parent = setlist->next_is_parent;
- - }
- -
- - /* Free the one we no longer need. */
- - free (setlist);
- - hash_map (&set->table, free_variable_name_and_value);
- - hash_free (&set->table, 1);
- - free (set);
- -}
- -
- /* Merge FROM_SET into TO_SET, freeing unused storage in FROM_SET. */
- static void
- @@ -966,6 +1042,7 @@
- struct variable makelevel_key;
- char **result_0;
- char **result;
- + struct vbuffer vbuf;
- if (file == 0)
- set_list = current_variable_set_list;
- @@ -1053,6 +1130,8 @@
- result = result_0 = xmalloc ((table.ht_fill + 2) * sizeof (char *));
- + vbuffer_init (&vbuf);
- +
- v_slot = (struct variable **) table.ht_vec;
- v_end = v_slot + table.ht_size;
- for ( ; v_slot < v_end; v_slot++)
- @@ -1060,32 +1139,30 @@
- {
- struct variable *v = *v_slot;
- + vbuffer_reset (&vbuf);
- +
- + vbuffer_write (&vbuf, v->name, -1);
- + vbuffer_write (&vbuf, "=", 1);
- +
- /* If V is recursively expanded and didn't come from the environment,
- expand its value. If it came from the environment, it should
- go back into the environment unchanged. */
- if (v->recursive
- && v->origin != o_env && v->origin != o_env_override)
- - {
- - char *value = recursively_expand_for_file (v, file);
- -#ifdef WINDOWS32
- - if (strcmp(v->name, "Path") == 0 ||
- - strcmp(v->name, "PATH") == 0)
- - convert_Path_to_windows32(value, ';');
- -#endif
- - *result++ = xstrdup (concat (3, v->name, "=", value));
- - free (value);
- - }
- + vbuffer_expand_variable_for_file (&vbuf, v, file);
- else
- - {
- + vbuffer_write (&vbuf, v->value, -1);
- +
- #ifdef WINDOWS32
- - if (strcmp(v->name, "Path") == 0 ||
- - strcmp(v->name, "PATH") == 0)
- - convert_Path_to_windows32(v->value, ';');
- + if (strcmp(v->name, "Path") == 0 ||
- + strcmp(v->name, "PATH") == 0)
- + convert_Path_to_windows32(value, ';');
- #endif
- - *result++ = xstrdup (concat (3, v->name, "=", v->value));
- - }
- + *result++ = xstrdup (vbuf.buffer);
- }
- + vbuffer_free (&vbuf);
- +
- *result = xmalloc (100);
- sprintf (*result, "%s=%u", MAKELEVEL_NAME, makelevel + 1);
- *++result = 0;
- @@ -1116,20 +1193,14 @@
- char *
- shell_result (const char *p)
- {
- - char *buf;
- - unsigned int len;
- + struct vbuffer vbuf;
- char *args[2];
- - char *result;
- -
- - install_variable_buffer (&buf, &len);
- args[0] = (char *) p;
- args[1] = NULL;
- - variable_buffer_output (func_shell_base (variable_buffer, args, 0), "\0", 1);
- - result = strdup (variable_buffer);
- + func_shell_base (vbuffer_init(&vbuf), args, 0);
- - restore_variable_buffer (buf, len);
- - return result;
- + return vbuf.buffer;
- }
- /* Given a variable, a value, and a flavor, define the variable.
- @@ -1145,6 +1216,7 @@
- struct variable *v;
- int append = 0;
- int conditional = 0;
- + unsigned int varlen = strlen (varname);
- /* Calculate the variable's new value in VALUE. */
- @@ -1174,7 +1246,7 @@
- case f_conditional:
- /* A conditional variable definition "var ?= value".
- The value is set IFF the variable is not defined yet. */
- - v = lookup_variable (varname, strlen (varname));
- + v = lookup_variable (varname, varlen);
- if (v)
- return v->special ? set_special_var (v) : v;
- @@ -1193,7 +1265,7 @@
- if (target_var)
- {
- append = 1;
- - v = lookup_variable_in_set (varname, strlen (varname),
- + v = lookup_variable_in_set (varname, varlen,
- current_variable_set_list->set);
- /* Don't append from the global set if a previous non-appending
- @@ -1202,7 +1274,7 @@
- append = 0;
- }
- else
- - v = lookup_variable (varname, strlen (varname));
- + v = lookup_variable (varname, varlen);
- if (v == 0)
- {
- @@ -1274,7 +1346,7 @@
- if (*tp == '\\')
- *tp = '/';
- - v = define_variable_loc (varname, strlen (varname),
- + v = define_variable_loc (varname, varlen,
- shellpath, origin, flavor == f_recursive,
- flocp);
- }
- @@ -1314,12 +1386,12 @@
- if (*tp == '\\')
- *tp = '/';
- - v = define_variable_loc (varname, strlen (varname),
- + v = define_variable_loc (varname, varlen,
- shellpath, origin,
- flavor == f_recursive, flocp);
- }
- else
- - v = lookup_variable (varname, strlen (varname));
- + v = lookup_variable (varname, varlen);
- free (path_string);
- }
- @@ -1338,7 +1410,7 @@
- if (find_and_set_default_shell (p))
- {
- - v = define_variable_in_set (varname, strlen (varname), default_shell,
- + v = define_variable_in_set (varname, varlen, default_shell,
- origin, flavor == f_recursive,
- (target_var
- ? current_variable_set_list->set
- @@ -1354,7 +1426,7 @@
- if (find_and_set_default_shell (alloc_value))
- {
- - v = define_variable_in_set (varname, strlen (varname), p,
- + v = define_variable_in_set (varname, varlen, p,
- origin, flavor == f_recursive,
- (target_var
- ? current_variable_set_list->set
- @@ -1363,7 +1435,7 @@
- no_default_sh_exe = 0;
- }
- else
- - v = lookup_variable (varname, strlen (varname));
- + v = lookup_variable (varname, varlen);
- if (tp)
- free (tp);
- @@ -1372,17 +1444,29 @@
- else
- #endif
- - /* If we are defining variables inside an $(eval ...), we might have a
- - different variable context pushed, not the global context (maybe we're
- - inside a $(call ...) or something. Since this function is only ever
- - invoked in places where we want to define globally visible variables,
- - make sure we define this variable in the global set. */
- -
- - v = define_variable_in_set (varname, strlen (varname), p,
- - origin, flavor == f_recursive,
- - (target_var
- - ? current_variable_set_list->set : NULL),
- - flocp);
- + {
- + /* If we are defining variables inside an $(eval ...), we might have a
- + different variable context pushed, not the global context (maybe we're
- + inside a $(call ...) or something. Since this function is only ever
- + invoked in places where we want to define globally visible variables,
- + make sure we define this variable in the global set. */
- +
- + v = define_variable_in_set_allocated (varname, varlen, alloc_value,
- + origin, flavor == f_recursive,
- + (target_var
- + ? current_variable_set_list->set
- + : NULL),
- + flocp);
- +
- + if (v->value == alloc_value)
- + {
- + if (!alloc_value)
- + v->value = xstrdup (p);
- + else
- + alloc_value = NULL;
- + }
- + }
- +
- v->append = append;
- v->conditional = conditional;
- Index: variable.h
- ===================================================================
- RCS file: /sources/make/make/variable.h,v
- retrieving revision 1.51
- diff -u -r1.51 variable.h
- --- variable.h 5 Mar 2012 14:10:45 -0000 1.51
- +++ variable.h 9 Apr 2012 13:34:42 -0000
- @@ -44,9 +44,11 @@
- Each bucket of the hash table is a chain of these,
- chained through 'next'. */
- -#define EXP_COUNT_BITS 15 /* This gets all the bitfields into 32 bits */
- +#define EXP_COUNT_BITS 14 /* This gets all the bitfields into 32 bits */
- #define EXP_COUNT_MAX ((1<<EXP_COUNT_BITS)-1)
- +#define MAX_ALLOCA_SIZE 1024
- +
- struct variable
- {
- char *name; /* Variable name. */
- @@ -64,6 +66,10 @@
- unsigned int expanding:1; /* Nonzero if currently being expanded. */
- unsigned int private_var:1; /* Nonzero avoids inheritance of this
- target-specific variable. */
- + unsigned int volatile_var:1;/* Nonzero if the state can change across
- + certain function calls. */
- + unsigned int global:1; /* Nonzero if this should be included in
- + $(.VARIABLES) list. */
- unsigned int exp_count:EXP_COUNT_BITS;
- /* If >1, allow this many self-referential
- expansions. */
- @@ -107,44 +113,80 @@
- struct variable variable;
- };
- -extern char *variable_buffer;
- +/* Structure used to hold the result of variable expansion. */
- +
- +struct vbuffer
- + {
- + char *ptr; /* Current position pointing inside the buffer. */
- + char *buffer; /* Start of the entire buffer. */
- + size_t size; /* Size of the allocated buffer. */
- + };
- +
- +struct call_frame
- + {
- + int argc;
- + char **argv;
- + };
- +
- extern struct variable_set_list *current_variable_set_list;
- extern struct variable *default_goal_var;
- +extern struct call_frame *current_call_frame;
- +
- +struct vbuffer *vbuffer_init (struct vbuffer *vbuf);
- +struct vbuffer *vbuffer_reset (struct vbuffer *vbuf);
- +
- +#define vbuffer_free(vbuf) \
- + free ((vbuf)->buffer)
- +
- +size_t vbuffer_reserve (struct vbuffer *o, size_t len);
- +
- +size_t vbuffer_write (struct vbuffer *o, const char *str, ssize_t len);
- +size_t vbuffer_unwrite (struct vbuffer *o, ssize_t len);
- +
- +size_t vbuffer_expand (struct vbuffer *o, char *str, ssize_t len);
- +size_t vbuffer_expand_for_file (struct vbuffer *o, char *str, ssize_t len,
- + struct file *file);
- +
- +size_t vbuffer_expand_ro (struct vbuffer *o, const char *str, ssize_t len);
- +size_t vbuffer_expand_ro_for_file (struct vbuffer *o, const char *str,
- + ssize_t len, struct file *file);
- +
- +#define vbuffer_expand_variable(o, v) \
- + vbuffer_expand_variable_for_file (o, v, NULL)
- +size_t vbuffer_expand_variable_for_file (struct vbuffer *o,
- + struct variable *v,
- + struct file *file);
- +
- +struct vbuffer *install_new_expansion_vbuffer (void);
- +void restore_expansion_vbuffer (struct vbuffer *old_vbuf);
- +
- /* expand.c */
- -char *variable_buffer_output (char *ptr, const char *string, unsigned int length);
- +char *expand_argument (const char *str, const char *end);
- char *variable_expand (const char *line);
- char *variable_expand_for_file (const char *line, struct file *file);
- +char *allocated_variable_expand (const char *line);
- char *allocated_variable_expand_for_file (const char *line, struct file *file);
- -#define allocated_variable_expand(line) \
- - allocated_variable_expand_for_file (line, (struct file *) 0)
- -char *expand_argument (const char *str, const char *end);
- -char *variable_expand_string (char *line, const char *string, long length);
- -void install_variable_buffer (char **bufp, unsigned int *lenp);
- -void restore_variable_buffer (char *buf, unsigned int len);
- +#define recursively_expand(v) recursively_expand_for_file (v, NULL)
- +char *recursively_expand_for_file (struct variable *v, struct file *file);
- /* function.c */
- -int handle_function (char **op, const char **stringp);
- +int handle_function (struct vbuffer *vbuf, char **stringp);
- int pattern_matches (const char *pattern, const char *percent, const char *str);
- -char *subst_expand (char *o, const char *text, const char *subst,
- - const char *replace, unsigned int slen, unsigned int rlen,
- - int by_word);
- -char *patsubst_expand_pat (char *o, const char *text, const char *pattern,
- - const char *replace, const char *pattern_percent,
- - const char *replace_percent);
- -char *patsubst_expand (char *o, const char *text, char *pattern, char *replace);
- -char *func_shell_base (char *o, char **argv, int trim_newlines);
- -
- -
- -/* expand.c */
- -char *recursively_expand_for_file (struct variable *v, struct file *file);
- -#define recursively_expand(v) recursively_expand_for_file (v, NULL)
- +size_t subst_expand (struct vbuffer *vbuf, const char *text, const char *subst,
- + const char *replace, unsigned int slen, unsigned int rlen,
- + int by_word);
- +size_t patsubst_expand_pat (struct vbuffer *vbuf, const char *text,
- + const char *pattern, const char *replace,
- + const char *pattern_percent,
- + const char *replace_percent);
- +size_t patsubst_expand (struct vbuffer *vbuf, const char *text, char *pattern,
- + char *replace);
- +size_t func_shell_base (struct vbuffer *vbuf, char **argv, int trim_newlines);
- /* variable.c */
- struct variable_set_list *create_new_variable_set (void);
- void free_variable_set (struct variable_set_list *);
- -struct variable_set_list *push_new_variable_scope (void);
- -void pop_variable_scope (void);
- void define_automatic_variables (void);
- void initialize_file_variables (struct file *file, int reading);
- void print_file_variables (const struct file *file);
- @@ -167,10 +209,11 @@
- void hash_init_function_table (void);
- void define_new_function(const struct floc *flocp,
- const char *name, int min, int max, int expand,
- - char *(*func)(char *, char **, const char *));
- + size_t (*func)(struct vbuffer *, char **, const char *));
- struct variable *lookup_variable (const char *name, unsigned int length);
- struct variable *lookup_variable_in_set (const char *name, unsigned int length,
- const struct variable_set *set);
- +char **lookup_call_argument_value (const char *name, unsigned int length);
- struct variable *define_variable_in_set (const char *name, unsigned int length,
- const char *value,
- @@ -207,6 +250,10 @@
- #define define_variable_for_file(n,l,v,o,r,f) \
- define_variable_in_set((n),(l),(v),(o),(r),(f)->variables->set,NILF)
- +struct variable *push_scoped_variable (struct variable *v,
- + char *name, unsigned int length);
- +void pop_scoped_variable (struct variable *v, struct variable *old_var);
- +
- void undefine_variable_in_set (const char *name, unsigned int length,
- enum variable_origin origin,
- struct variable_set *set);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement