From 78c8c44326f644da612088fa05c8a77c5ca17a5e Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Sat, 25 Mar 2023 19:15:20 -0400 Subject: 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. --- src/expand.c | 97 ++++++++++++++++++++++++++++++++++++++-------- src/function.c | 12 +----- src/job.c | 6 +-- src/main.c | 9 +---- src/read.c | 4 +- src/remake.c | 2 +- src/variable.h | 6 +++ src/vpath.c | 6 ++- src/w32/subproc/sub_proc.c | 7 ++-- 9 files changed, 103 insertions(+), 46 deletions(-) diff --git a/src/expand.c b/src/expand.c index 25c71153..a72dfff7 100644 --- a/src/expand.c +++ b/src/expand.c @@ -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; } diff --git a/src/function.c b/src/function.c index 8f46ec60..5ca28f85 100644 --- a/src/function.c +++ b/src/function.c @@ -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; diff --git a/src/job.c b/src/job.c index c7313fdb..d7b584f5 100644 --- a/src/job.c +++ b/src/job.c @@ -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; } diff --git a/src/main.c b/src/main.c index 86497e70..16bbb83a 100644 --- a/src/main.c +++ b/src/main.c @@ -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); diff --git a/src/read.c b/src/read.c index 14f9dcee..bae836f2 100644 --- a/src/read.c +++ b/src/read.c @@ -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; } diff --git a/src/remake.c b/src/remake.c index 7c841f5d..d5cd3b38 100644 --- a/src/remake.c +++ b/src/remake.c @@ -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; diff --git a/src/variable.h b/src/variable.h index 195cc360..bfba63f5 100644 --- a/src/variable.h +++ b/src/variable.h @@ -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); diff --git a/src/vpath.c b/src/vpath.c index 873a9c94..25c41e30 100644 --- a/src/vpath.c +++ b/src/vpath.c @@ -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') { diff --git a/src/w32/subproc/sub_proc.c b/src/w32/subproc/sub_proc.c index be32d9ef..4c1611d3 100644 --- a/src/w32/subproc/sub_proc.c +++ b/src/w32/subproc/sub_proc.c @@ -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]. */ -- cgit v1.2.1