summaryrefslogtreecommitdiff
path: root/variable.c
diff options
context:
space:
mode:
Diffstat (limited to 'variable.c')
-rw-r--r--variable.c316
1 files changed, 176 insertions, 140 deletions
diff --git a/variable.c b/variable.c
index 148e081..ca9265c 100644
--- a/variable.c
+++ b/variable.c
@@ -57,7 +57,7 @@ struct variable_set_list *current_variable_set_list = &global_setlist;
struct variable *
define_variable_in_set (name, length, value, origin, recursive, set, flocp)
- char *name;
+ const char *name;
unsigned int length;
char *value;
enum variable_origin origin;
@@ -69,6 +69,9 @@ define_variable_in_set (name, length, value, origin, recursive, set, flocp)
register unsigned int hashval;
register struct variable *v;
+ if (set == NULL)
+ set = &global_variable_set;
+
hashval = 0;
for (i = 0; i < length; ++i)
HASH (hashval, name[i]);
@@ -741,117 +744,27 @@ target_environment (file)
return result;
}
-/* Try to interpret LINE (a null-terminated string) as a variable definition.
-
- ORIGIN may be o_file, o_override, o_env, o_env_override,
- or o_command specifying that the variable definition comes
- from a makefile, an override directive, the environment with
- or without the -e switch, or the command line.
-
- See the comments for parse_variable_definition().
-
- If LINE was recognized as a variable definition, a pointer to its `struct
- variable' is returned. If LINE is not a variable definition, NULL is
- returned. */
+/* Given a variable, a value, and a flavor, define the variable.
+ See the try_variable_definition() function for details on the parameters. */
struct variable *
-try_variable_definition (flocp, line, origin, target_var)
+do_variable_definition (flocp, varname, value, origin, flavor, target_var)
const struct floc *flocp;
- char *line;
+ const char *varname;
+ char *value;
enum variable_origin origin;
+ enum variable_flavor flavor;
int target_var;
{
- register int c;
- register char *p = line;
- register char *beg;
- register char *end;
- enum { f_bogus,
- f_simple, f_recursive, f_append, f_conditional } flavor = f_bogus;
- char *name, *expanded_name, *value=0, *alloc_value=NULL;
+ char *p, *alloc_value = NULL;
struct variable *v;
int append = 0;
- while (1)
- {
- c = *p++;
- if (c == '\0' || c == '#')
- return 0;
- if (c == '=')
- {
- end = p - 1;
- flavor = f_recursive;
- break;
- }
- else if (c == ':')
- if (*p == '=')
- {
- end = p++ - 1;
- flavor = f_simple;
- break;
- }
- else
- /* A colon other than := is a rule line, not a variable defn. */
- return 0;
- else if (c == '+' && *p == '=')
- {
- end = p++ - 1;
- flavor = f_append;
- break;
- }
- else if (c == '?' && *p == '=')
- {
- end = p++ - 1;
- flavor = f_conditional;
- break;
- }
- else if (c == '$')
- {
- /* This might begin a variable expansion reference. Make sure we
- don't misrecognize chars inside the reference as =, := or +=. */
- char closeparen;
- int count;
- c = *p++;
- if (c == '(')
- closeparen = ')';
- else if (c == '{')
- closeparen = '}';
- else
- continue; /* Nope. */
-
- /* P now points past the opening paren or brace.
- Count parens or braces until it is matched. */
- count = 0;
- for (; *p != '\0'; ++p)
- {
- if (*p == c)
- ++count;
- else if (*p == closeparen && --count < 0)
- {
- ++p;
- break;
- }
- }
- }
- }
-
- beg = next_token (line);
- while (end > beg && isblank ((unsigned char)end[-1]))
- --end;
- p = next_token (p);
-
- /* Expand the name, so "$(foo)bar = baz" works. */
- name = (char *) alloca (end - beg + 1);
- bcopy (beg, name, end - beg);
- name[end - beg] = '\0';
- expanded_name = allocated_variable_expand (name);
-
- if (expanded_name[0] == '\0')
- fatal (flocp, _("empty variable name"));
-
/* Calculate the variable's new value in VALUE. */
switch (flavor)
{
+ default:
case f_bogus:
/* Should not be possible. */
abort ();
@@ -860,23 +773,21 @@ try_variable_definition (flocp, line, origin, target_var)
We have to allocate memory since otherwise it'll clobber the
variable buffer, and we may still need that if we're looking at a
target-specific variable. */
- value = alloc_value = allocated_variable_expand (p);
+ p = alloc_value = allocated_variable_expand (value);
break;
case f_conditional:
/* A conditional variable definition "var ?= value".
The value is set IFF the variable is not defined yet. */
- v = lookup_variable(expanded_name, strlen(expanded_name));
+ v = lookup_variable (varname, strlen (varname));
if (v)
- {
- free(expanded_name);
- return v;
- }
+ return v;
+
flavor = f_recursive;
/* FALLTHROUGH */
case f_recursive:
/* A recursive variable definition "var = value".
The value is used verbatim. */
- value = p;
+ p = value;
break;
case f_append:
{
@@ -885,17 +796,17 @@ try_variable_definition (flocp, line, origin, target_var)
if (target_var)
{
append = 1;
- v = lookup_variable_in_set (expanded_name, strlen (expanded_name),
+ v = lookup_variable_in_set (varname, strlen (varname),
current_variable_set_list->set);
}
else
- v = lookup_variable (expanded_name, strlen (expanded_name));
+ v = lookup_variable (varname, strlen (varname));
if (v == 0)
{
/* There was no old value.
This becomes a normal recursive definition. */
- value = p;
+ p = value;
flavor = f_recursive;
}
else
@@ -904,6 +815,7 @@ try_variable_definition (flocp, line, origin, target_var)
unsigned int oldlen, newlen;
+ p = value;
if (v->recursive)
/* The previous definition of the variable was recursive.
The new value is the unexpanded old and new values. */
@@ -918,10 +830,10 @@ try_variable_definition (flocp, line, origin, target_var)
oldlen = strlen (v->value);
newlen = strlen (p);
- value = (char *) alloca (oldlen + 1 + newlen + 1);
- bcopy (v->value, value, oldlen);
- value[oldlen] = ' ';
- bcopy (p, &value[oldlen + 1], newlen + 1);
+ p = (char *) alloca (oldlen + 1 + newlen + 1);
+ bcopy (v->value, p, oldlen);
+ p[oldlen] = ' ';
+ bcopy (value, &p[oldlen + 1], newlen + 1);
}
}
}
@@ -941,13 +853,13 @@ try_variable_definition (flocp, line, origin, target_var)
your $PATH, then SHELL=/usr/local/bin/bash will have the effect of
defining SHELL to be "d:/unix/bash.exe". */
if ((origin == o_file || origin == o_override)
- && strcmp (expanded_name, "SHELL") == 0)
+ && strcmp (varname, "SHELL") == 0)
{
char shellpath[PATH_MAX];
extern char * __dosexec_find_on_path (const char *, char *[], char *);
/* See if we can find "/bin/sh.exe", "/bin/sh.com", etc. */
- if (__dosexec_find_on_path (value, (char **)0, shellpath))
+ if (__dosexec_find_on_path (p, (char **)0, shellpath))
{
char *p;
@@ -956,7 +868,7 @@ try_variable_definition (flocp, line, origin, target_var)
if (*p == '\\')
*p = '/';
}
- v = define_variable_loc (expanded_name, strlen (expanded_name),
+ v = define_variable_loc (varname, strlen (varname),
shellpath, origin, flavor == f_recursive,
flocp);
}
@@ -968,16 +880,16 @@ try_variable_definition (flocp, line, origin, target_var)
char *fake_env[2];
size_t pathlen = 0;
- shellbase = strrchr (value, '/');
- bslash = strrchr (value, '\\');
+ shellbase = strrchr (p, '/');
+ bslash = strrchr (p, '\\');
if (!shellbase || bslash > shellbase)
shellbase = bslash;
- if (!shellbase && value[1] == ':')
- shellbase = value + 1;
+ if (!shellbase && p[1] == ':')
+ shellbase = p + 1;
if (shellbase)
shellbase++;
else
- shellbase = value;
+ shellbase = p;
/* Search for the basename of the shell (with standard
executable extensions) along the $PATH. */
@@ -997,12 +909,12 @@ try_variable_definition (flocp, line, origin, target_var)
if (*p == '\\')
*p = '/';
}
- v = define_variable_loc (expanded_name, strlen (expanded_name),
+ v = define_variable_loc (varname, strlen (varname),
shellpath, origin,
flavor == f_recursive, flocp);
}
else
- v = lookup_variable (expanded_name, strlen (expanded_name));
+ v = lookup_variable (varname, strlen (varname));
free (path_string);
}
@@ -1010,33 +922,157 @@ try_variable_definition (flocp, line, origin, target_var)
else
#endif /* __MSDOS__ */
#ifdef WINDOWS32
- if ((origin == o_file || origin == o_override)
- && strcmp (expanded_name, "SHELL") == 0)
+ if ((origin == o_file || origin == o_override) && streq (varname, "SHELL"))
{
- extern char* default_shell;
+ extern char *default_shell;
- /*
- * Call shell locator function. If it returns TRUE, then
- * set no_default_sh_exe to indicate sh was found and
- * set new value for SHELL variable.
- */
- if (find_and_set_default_shell(value)) {
- v = define_variable_loc (expanded_name, strlen (expanded_name),
- default_shell, origin, flavor == f_recursive,
- flocp);
- no_default_sh_exe = 0;
- }
+ /* Call shell locator function. If it returns TRUE, then
+ set no_default_sh_exe to indicate sh was found and
+ set new value for SHELL variable. */
+
+ if (find_and_set_default_shell (p))
+ {
+ v = define_variable_in_set (varname, strlen (varname), default_shell,
+ origin, flavor == f_recursive,
+ (target_var
+ ? current_variable_set_list->set
+ : NULL),
+ flocp);
+ no_default_sh_exe = 0;
+ }
+ else
+ v = lookup_variable (varname, strlen (varname));
}
else
#endif
- v = define_variable_loc (expanded_name, strlen (expanded_name), value,
- origin, flavor == f_recursive, 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 (varname, strlen (varname), p,
+ origin, flavor == f_recursive,
+ (target_var
+ ? current_variable_set_list->set : NULL),
+ flocp);
v->append = append;
if (alloc_value)
free (alloc_value);
+
+ return v;
+}
+
+/* Try to interpret LINE (a null-terminated string) as a variable definition.
+
+ ORIGIN may be o_file, o_override, o_env, o_env_override,
+ or o_command specifying that the variable definition comes
+ from a makefile, an override directive, the environment with
+ or without the -e switch, or the command line.
+
+ See the comments for parse_variable_definition().
+
+ If LINE was recognized as a variable definition, a pointer to its `struct
+ variable' is returned. If LINE is not a variable definition, NULL is
+ returned. */
+
+struct variable *
+try_variable_definition (flocp, line, origin, target_var)
+ const struct floc *flocp;
+ char *line;
+ enum variable_origin origin;
+ int target_var;
+{
+ register int c;
+ register char *p = line;
+ register char *beg;
+ register char *end;
+ enum variable_flavor flavor = f_bogus;
+ char *name, *expanded_name;
+ struct variable *v;
+
+ while (1)
+ {
+ c = *p++;
+ if (c == '\0' || c == '#')
+ return 0;
+ if (c == '=')
+ {
+ end = p - 1;
+ flavor = f_recursive;
+ break;
+ }
+ else if (c == ':')
+ if (*p == '=')
+ {
+ end = p++ - 1;
+ flavor = f_simple;
+ break;
+ }
+ else
+ /* A colon other than := is a rule line, not a variable defn. */
+ return 0;
+ else if (c == '+' && *p == '=')
+ {
+ end = p++ - 1;
+ flavor = f_append;
+ break;
+ }
+ else if (c == '?' && *p == '=')
+ {
+ end = p++ - 1;
+ flavor = f_conditional;
+ break;
+ }
+ else if (c == '$')
+ {
+ /* This might begin a variable expansion reference. Make sure we
+ don't misrecognize chars inside the reference as =, := or +=. */
+ char closeparen;
+ int count;
+ c = *p++;
+ if (c == '(')
+ closeparen = ')';
+ else if (c == '{')
+ closeparen = '}';
+ else
+ continue; /* Nope. */
+
+ /* P now points past the opening paren or brace.
+ Count parens or braces until it is matched. */
+ count = 0;
+ for (; *p != '\0'; ++p)
+ {
+ if (*p == c)
+ ++count;
+ else if (*p == closeparen && --count < 0)
+ {
+ ++p;
+ break;
+ }
+ }
+ }
+ }
+
+ beg = next_token (line);
+ while (end > beg && isblank ((unsigned char)end[-1]))
+ --end;
+ p = next_token (p);
+
+ /* Expand the name, so "$(foo)bar = baz" works. */
+ name = (char *) alloca (end - beg + 1);
+ bcopy (beg, name, end - beg);
+ name[end - beg] = '\0';
+ expanded_name = allocated_variable_expand (name);
+
+ if (expanded_name[0] == '\0')
+ fatal (flocp, _("empty variable name"));
+
+ v = do_variable_definition (flocp, expanded_name, p,
+ origin, flavor, target_var);
+
free (expanded_name);
return v;