Add functions to directly expand variables by name

Replace all locally-created "$("+varname+")" and similar constructs
with calls to these new functions.

* src/expand.c (expand_variable_output): Call expand_string_output()
on the expansion of a variable value.  Replaces reference_variable().
(expand_variable_buf): Like expand_variable_output() but return the
starting location of the result.
(allocated_expand_variable): Like expand_variable_buf() but return
an allocated string.
(expand_string_buf): Call expand_variable_output().
* src/variable.h: Declare the new functions.
* src/function.c (func_call): Call expand_variable_output() instead
of expand_string_buf().
* src/main.c (decode_env_switches): Call expand_variable() instead
of expand_string().
* src/remake.c (library_search): Call allocated_expand_variable()
instead of expand_string() plus xstrdup().
* src/vpath.c (build_vpath_lists): Expand VPATH and GPATH using
expand_variable() instead of expand_string().
* src/w32/subproc/sub_proc.c (process_begin): Use expand_variable()
to expand SHELL.  Also use alloc() in case the result is larger than
PATH_MAX.
This commit is contained in:
Paul Smith 2023-03-25 19:15:20 -04:00
parent caf1d4c28f
commit 78c8c44326
9 changed files with 103 additions and 46 deletions

View File

@ -83,7 +83,7 @@ initialize_variable_output ()
{
/* If we don't have a variable output buffer yet, get one. */
if (variable_buffer == NULL)
if (!variable_buffer)
{
variable_buffer_length = 200;
variable_buffer = xmalloc (variable_buffer_length);
@ -221,42 +221,105 @@ recursively_expand_for_file (struct variable *v, struct file *file)
return value;
}
/* Expand a simple reference to variable NAME, which is LENGTH chars long. */
/* Expand a simple reference to variable NAME, which is LENGTH chars long.
The result is written to PTR which must point into the variable_buffer.
Returns a pointer to the new end of the variable_buffer. */
#ifdef __GNUC__
__inline
#endif
static char *
reference_variable (char *o, const char *name, size_t length)
char *
expand_variable_output (char *ptr, const char *name, size_t length)
{
struct variable *v;
char *value;
v = lookup_variable (name, length);
if (v == 0)
if (!v)
warn_undefined (name, length);
/* 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;
if (!v || (v->value[0] == '\0' && !v->append))
return ptr;
value = (v->recursive ? recursively_expand (v) : v->value);
value = v->recursive ? recursively_expand (v) : v->value;
o = variable_buffer_output (o, value, strlen (value));
ptr = variable_buffer_output (ptr, value, strlen (value));
if (v->recursive)
free (value);
return o;
return ptr;
}
/* Expand a simple reference to variable NAME, which is LENGTH chars long.
The result is written to BUF which must point into the variable_buffer.
If BUF is NULL, start at the beginning of the current variable_buffer.
Returns BUF, or the beginning of the buffer if BUF is NULL. */
char *
expand_variable_buf (char *buf, const char *name, size_t length)
{
if (!buf)
buf = initialize_variable_output ();
expand_variable_output (buf, name, length);
return buf;
}
/* Expand a simple reference to variable NAME, which is LENGTH chars long.
Returns an allocated buffer containing the value. */
char *
allocated_expand_variable (const char *name, size_t length)
{
char *obuf;
size_t olen;
install_variable_buffer (&obuf, &olen);
expand_variable_output (variable_buffer, name, length);
return swap_variable_buffer (obuf, olen);
}
/* Expand a simple reference to variable NAME, which is LENGTH chars long.
Error messages refer to the file and line where FILE's commands were found.
Expansion uses FILE's variable set list.
Returns an allocated buffer containing the value. */
char *
allocated_expand_variable_for_file (const char *name, size_t length, struct file *file)
{
char *result;
struct variable_set_list *savev;
const floc *savef;
if (!file)
return allocated_expand_variable (name, length);
savev = current_variable_set_list;
current_variable_set_list = file->variables;
savef = reading_file;
if (file->cmds && file->cmds->fileinfo.filenm)
reading_file = &file->cmds->fileinfo;
else
reading_file = NULL;
result = allocated_expand_variable (name, length);
current_variable_set_list = savev;
reading_file = savef;
return result;
}
/* Scan STRING for variable references and expansion-function calls. Only
LENGTH bytes of STRING are actually scanned.
If LENGTH is SIZE_MAX, scan until a null byte is found.
Write the results to BUF, which must point into 'variable_buffer'. If
BUF is NULL, start at the beginning of the current 'variable_buffer'.
Write the results to BUF, which must point into variable_buffer. If
BUF is NULL, start at the beginning of the current variable_buffer.
Return a pointer to BUF, or to the beginning of the new buffer if BUF is
NULL.
@ -445,7 +508,7 @@ expand_string_buf (char *buf, const char *string, size_t length)
if (colon == 0)
/* This is an ordinary variable reference.
Look up the value of the variable. */
o = reference_variable (o, beg, end - beg);
o = expand_variable_output (o, beg, end - beg);
free (abeg);
}
@ -457,7 +520,7 @@ expand_string_buf (char *buf, const char *string, size_t length)
/* A $ followed by a random char is a variable reference:
$a is equivalent to $(a). */
o = reference_variable (o, p, 1);
o = expand_variable_output (o, p, 1);
break;
}

View File

@ -2613,7 +2613,6 @@ func_call (char *o, char **argv, const char *funcname UNUSED)
{
static unsigned int max_args = 0;
char *fname;
char *body;
size_t flen;
unsigned int i;
int saved_args;
@ -2651,13 +2650,6 @@ func_call (char *o, char **argv, const char *funcname UNUSED)
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 ();
@ -2683,14 +2675,14 @@ func_call (char *o, char **argv, const char *funcname UNUSED)
define_variable (num, strlen (num), "", o_automatic, 0);
}
/* Expand the body in the context of the arguments, adding the result to
/* Expand the function in the context of the arguments, adding the result to
the variable buffer. */
v->exp_count = EXP_COUNT_MAX;
saved_args = max_args;
max_args = i;
o = expand_string_buf (o, body, flen+3);
o = expand_variable_output (o, fname, flen);
max_args = saved_args;
v->exp_count = 0;

View File

@ -1882,7 +1882,7 @@ new_job (struct file *file)
nm, c->file->name);
else
{
char *newer = allocated_expand_string_for_file ("$?", c->file);
char *newer = allocated_expand_variable_for_file (STRING_SIZE_TUPLE ("?"), c->file);
if (newer[0] != '\0')
{
OSSS (message, 0, _("%s: update target '%s' due to: %s"),
@ -3637,7 +3637,7 @@ construct_command_argv (char *line, char **restp, struct file *file,
int save = warn_undefined_variables_flag;
warn_undefined_variables_flag = 0;
shell = allocated_expand_string_for_file ("$(SHELL)", file);
shell = allocated_expand_variable_for_file (STRING_SIZE_TUPLE ("SHELL"), file);
#if MK_OS_W32
/*
* Convert to forward slashes so that construct_command_argv_internal()
@ -3702,7 +3702,7 @@ construct_command_argv (char *line, char **restp, struct file *file,
else
shellflags = allocated_expand_string_for_file (var->value, file);
ifs = allocated_expand_string_for_file ("$(IFS)", file);
ifs = allocated_expand_variable_for_file (STRING_SIZE_TUPLE ("IFS"), file);
warn_undefined_variables_flag = save;
}

View File

@ -3328,19 +3328,12 @@ decode_switches (int argc, const char **argv, enum variable_origin origin)
static void
decode_env_switches (const char *envar, size_t len, enum variable_origin origin)
{
char *varref = alloca (2 + len + 2);
char *value, *p, *buf;
int argc;
const char **argv;
/* Get the variable's value. */
p = varref;
*(p++) = '$';
*(p++) = '(';
p = mempcpy (p, envar, len);
*(p++) = ')';
*p = '\0';
value = expand_string (varref);
value = expand_variable (envar, len);
/* Skip whitespace, and check for an empty value. */
NEXT_TOKEN (value);

View File

@ -186,7 +186,7 @@ read_all_makefiles (const char **makefiles)
char *name, *p;
size_t length;
value = allocated_expand_string ("$(MAKEFILES)");
value = allocated_expand_variable (STRING_SIZE_TUPLE ("MAKEFILES"));
/* Set NAME to the start of next token and LENGTH to its length.
MAKEFILES is updated for finding remaining tokens. */
@ -3071,7 +3071,7 @@ tilde_expand (const char *name)
int save = warn_undefined_variables_flag;
warn_undefined_variables_flag = 0;
home_dir = allocated_expand_string ("$(HOME)");
home_dir = allocated_expand_variable (STRING_SIZE_TUPLE ("HOME"));
warn_undefined_variables_flag = save;
}

View File

@ -1717,7 +1717,7 @@ library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr)
const char **dp;
libpatterns = xstrdup (expand_string ("$(.LIBPATTERNS)"));
libpatterns = allocated_expand_variable (STRING_SIZE_TUPLE (".LIBPATTERNS"));
/* Skip the '-l'. */
lib += 2;

View File

@ -136,6 +136,12 @@ char *expand_argument (const char *str, const char *end);
char *recursively_expand_for_file (struct variable *v, struct file *file);
#define recursively_expand(v) recursively_expand_for_file ((v), NULL)
char *expand_variable_output (char *ptr, const char *name, size_t length);
char *expand_variable_buf (char *buf, const char *name, size_t length);
#define expand_variable(n,l) expand_variable_buf (NULL, (n), (l));
char *allocated_expand_variable (const char *name, size_t length);
char *allocated_expand_variable_for_file (const char *name, size_t length, struct file *file);
/* function.c */
int handle_function (char **op, const char **stringp);
int pattern_matches (const char *pattern, const char *percent, const char *str);

View File

@ -71,7 +71,8 @@ build_vpath_lists (void)
/* If there is a VPATH variable with a nonnull expanded value, construct the
general VPATH list from it. */
p = expand_string ("$(strip $(VPATH))");
p = expand_variable ("VPATH", 5);
NEXT_TOKEN (p);
if (*p != '\0')
{
@ -95,7 +96,8 @@ build_vpath_lists (void)
/* If there is a GPATH variable with a nonnull expanded value, construct the
GPATH list from it. */
p = expand_string ("$(strip $(GPATH))");
p = expand_variable ("GPATH", 5);
NEXT_TOKEN (p);
if (*p != '\0')
{

View File

@ -566,10 +566,10 @@ process_begin(
char *shell_name = 0;
int file_not_found=0;
HANDLE exec_handle;
char exec_fname[MAX_PATH];
char exec_fname[MAX_PATH+1];
const char *path_var = NULL;
char **ep;
char buf[MAX_PATH];
char buf[MAX_PATH+1];
DWORD bytes_returned;
DWORD flags;
char *command_line;
@ -614,8 +614,9 @@ process_begin(
char *new_argv0;
char **argvi = argv;
size_t arglen = 0;
char *exp = expand_variable ("SHELL", 5);
strcpy(buf, expand_string ("$(SHELL)"));
memcpy (buf, exp, strlen(exp) + 1);
shell_name = &buf[0];
strcpy(exec_fname, "-c");
/* Construct a single command string in argv[0]. */