summaryrefslogtreecommitdiff
path: root/variable.c
diff options
context:
space:
mode:
Diffstat (limited to 'variable.c')
-rw-r--r--variable.c702
1 files changed, 403 insertions, 299 deletions
diff --git a/variable.c b/variable.c
index 915be20..2ff14b6 100644
--- a/variable.c
+++ b/variable.c
@@ -1,7 +1,5 @@
/* Internals of variables for GNU Make.
-Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
-1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
-2010 Free Software Foundation, Inc.
+Copyright (C) 1988-2013 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@@ -16,12 +14,12 @@ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program. If not, see <http://www.gnu.org/licenses/>. */
-#include "make.h"
+#include "makeint.h"
#include <assert.h>
-#include "dep.h"
#include "filedef.h"
+#include "dep.h"
#include "job.h"
#include "commands.h"
#include "variable.h"
@@ -100,7 +98,7 @@ static struct pattern_var *
lookup_pattern_var (struct pattern_var *start, const char *target)
{
struct pattern_var *p;
- unsigned int targlen = strlen(target);
+ unsigned int targlen = strlen (target);
for (p = start ? start->next : pattern_vars; p != 0; p = p->next)
{
@@ -160,14 +158,14 @@ variable_hash_cmp (const void *xv, const void *yv)
return_STRING_N_COMPARE (x->name, y->name, x->length);
}
-#ifndef VARIABLE_BUCKETS
-#define VARIABLE_BUCKETS 523
+#ifndef VARIABLE_BUCKETS
+#define VARIABLE_BUCKETS 523
#endif
-#ifndef PERFILE_VARIABLE_BUCKETS
-#define PERFILE_VARIABLE_BUCKETS 23
+#ifndef PERFILE_VARIABLE_BUCKETS
+#define PERFILE_VARIABLE_BUCKETS 23
#endif
-#ifndef SMALL_SCOPE_VARIABLE_BUCKETS
-#define SMALL_SCOPE_VARIABLE_BUCKETS 13
+#ifndef SMALL_SCOPE_VARIABLE_BUCKETS
+#define SMALL_SCOPE_VARIABLE_BUCKETS 13
#endif
static struct variable_set global_variable_set;
@@ -181,7 +179,7 @@ void
init_hash_global_variable_set (void)
{
hash_init (&global_variable_set.table, VARIABLE_BUCKETS,
- variable_hash_1, variable_hash_2, variable_hash_cmp);
+ variable_hash_1, variable_hash_2, variable_hash_cmp);
}
/* Define variable named NAME with value VALUE in SET. VALUE is copied.
@@ -195,7 +193,7 @@ 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)
+ const gmk_floc *flocp)
{
struct variable *v;
struct variable **var_slot;
@@ -215,25 +213,25 @@ define_variable_in_set (const char *name, unsigned int length,
if (! HASH_VACANT (v))
{
if (env_overrides && v->origin == o_env)
- /* V came from in the environment. Since it was defined
- before the switches were parsed, it wasn't affected by -e. */
- v->origin = o_env_override;
+ /* V came from in the environment. Since it was defined
+ before the switches were parsed, it wasn't affected by -e. */
+ v->origin = o_env_override;
/* A variable of this name is already defined.
- If the old definition is from a stronger source
- than this one, don't redefine it. */
+ If the old definition is from a stronger source
+ than this one, don't redefine it. */
if ((int) origin >= (int) v->origin)
- {
- if (v->value != 0)
- free (v->value);
- v->value = xstrdup (value);
+ {
+ if (v->value != 0)
+ free (v->value);
+ v->value = xstrdup (value);
if (flocp != 0)
v->fileinfo = *flocp;
else
v->fileinfo.filenm = 0;
- v->origin = origin;
- v->recursive = recursive;
- }
+ v->origin = origin;
+ v->recursive = recursive;
+ }
return v;
}
@@ -282,7 +280,21 @@ define_variable_in_set (const char *name, unsigned int length,
variable (makefile, command line or environment). */
static void
-free_variable_name_and_value (const void *item);
+free_variable_name_and_value (const void *item)
+{
+ struct variable *v = (struct variable *) item;
+ free (v->name);
+ free (v->value);
+}
+
+void
+free_variable_set (struct variable_set_list *list)
+{
+ hash_map (&list->set->table, free_variable_name_and_value);
+ hash_free (&list->set->table, 1);
+ free (list->set);
+ free (list);
+}
void
undefine_variable_in_set (const char *name, unsigned int length,
@@ -307,17 +319,17 @@ undefine_variable_in_set (const char *name, unsigned int length,
if (! HASH_VACANT (v))
{
if (env_overrides && v->origin == o_env)
- /* V came from in the environment. Since it was defined
- before the switches were parsed, it wasn't affected by -e. */
- v->origin = o_env_override;
+ /* V came from in the environment. Since it was defined
+ before the switches were parsed, it wasn't affected by -e. */
+ v->origin = o_env_override;
/* If the definition is from a stronger source than this one, don't
undefine it. */
if ((int) origin >= (int) v->origin)
- {
+ {
hash_delete_at (&set->table, var_slot);
free_variable_name_and_value (v);
- }
+ }
}
}
@@ -412,7 +424,7 @@ lookup_special_var (struct variable *var)
/* 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
+ Returns address of the 'struct variable' containing all info
on the variable, or nil if no such variable is defined. */
struct variable *
@@ -433,7 +445,7 @@ lookup_variable (const char *name, unsigned int length)
v = (struct variable *) hash_find_item ((struct hash_table *) &set->table, &var_key);
if (v && (!is_parent || !v->private_var))
- return v->special ? lookup_special_var (v) : v;
+ return v->special ? lookup_special_var (v) : v;
is_parent |= setlist->next_is_parent;
}
@@ -499,7 +511,7 @@ lookup_variable (const char *name, unsigned int length)
/* Lookup a variable whose name is a string starting at NAME
and with LENGTH chars in set SET. NAME need not be null-terminated.
- Returns address of the `struct variable' containing all info
+ Returns address of the 'struct variable' containing all info
on the variable, or nil if no such variable is defined. */
struct variable *
@@ -531,7 +543,7 @@ initialize_file_variables (struct file *file, int reading)
if (l == 0)
{
l = (struct variable_set_list *)
- xmalloc (sizeof (struct variable_set_list));
+ xmalloc (sizeof (struct variable_set_list));
l->set = xmalloc (sizeof (struct variable_set));
hash_init (&l->set->table, PERFILE_VARIABLE_BUCKETS,
variable_hash_1, variable_hash_2, variable_hash_cmp);
@@ -634,7 +646,7 @@ create_new_variable_set (void)
set = xmalloc (sizeof (struct variable_set));
hash_init (&set->table, SMALL_SCOPE_VARIABLE_BUCKETS,
- variable_hash_1, variable_hash_2, variable_hash_cmp);
+ variable_hash_1, variable_hash_2, variable_hash_cmp);
setlist = (struct variable_set_list *)
xmalloc (sizeof (struct variable_set_list));
@@ -645,23 +657,6 @@ create_new_variable_set (void)
return setlist;
}
-static void
-free_variable_name_and_value (const void *item)
-{
- struct variable *v = (struct variable *) item;
- free (v->name);
- free (v->value);
-}
-
-void
-free_variable_set (struct variable_set_list *list)
-{
- hash_map (&list->set->table, free_variable_name_and_value);
- hash_free (&list->set->table, 1);
- free (list->set);
- 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
@@ -671,7 +666,7 @@ free_variable_set (struct variable_set_list *list)
struct variable_set_list *
push_new_variable_scope (void)
{
- current_variable_set_list = create_new_variable_set();
+ 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
@@ -694,7 +689,7 @@ pop_variable_scope (void)
struct variable_set *set;
/* Can't call this if there's no scope to pop! */
- assert(current_variable_set_list->next != NULL);
+ assert (current_variable_set_list->next != NULL);
if (current_variable_set_list != &global_setlist)
{
@@ -734,17 +729,17 @@ merge_variable_sets (struct variable_set *to_set,
for ( ; from_var_slot < from_var_end; from_var_slot++)
if (! HASH_VACANT (*from_var_slot))
{
- struct variable *from_var = *from_var_slot;
- struct variable **to_var_slot
- = (struct variable **) hash_find_slot (&to_set->table, *from_var_slot);
- if (HASH_VACANT (*to_var_slot))
- hash_insert_at (&to_set->table, from_var, to_var_slot);
- else
- {
- /* GKM FIXME: delete in from_set->table */
- free (from_var->value);
- free (from_var);
- }
+ struct variable *from_var = *from_var_slot;
+ struct variable **to_var_slot
+ = (struct variable **) hash_find_slot (&to_set->table, *from_var_slot);
+ if (HASH_VACANT (*to_var_slot))
+ hash_insert_at (&to_set->table, from_var, to_var_slot);
+ else
+ {
+ /* GKM FIXME: delete in from_set->table */
+ free (from_var->value);
+ free (from_var);
+ }
}
}
@@ -778,9 +773,9 @@ merge_variable_set_lists (struct variable_set_list **setlist0,
if (setlist1 != &global_setlist)
{
if (last0 == 0)
- *setlist0 = setlist1;
+ *setlist0 = setlist1;
else
- last0->next = setlist1;
+ last0->next = setlist1;
}
}
@@ -802,12 +797,13 @@ define_automatic_variables (void)
define_variable_cname (MAKELEVEL_NAME, buf, o_env, 0);
sprintf (buf, "%s%s%s",
- version_string,
- (remote_description == 0 || remote_description[0] == '\0')
- ? "" : "-",
- (remote_description == 0 || remote_description[0] == '\0')
- ? "" : remote_description);
+ version_string,
+ (remote_description == 0 || remote_description[0] == '\0')
+ ? "" : "-",
+ (remote_description == 0 || remote_description[0] == '\0')
+ ? "" : remote_description);
define_variable_cname ("MAKE_VERSION", buf, o_default, 0);
+ define_variable_cname ("MAKE_HOST", make_host, o_default, 0);
#ifdef __MSDOS__
/* Allow to specify a special shell just for Make,
@@ -821,14 +817,14 @@ define_automatic_variables (void)
/* $(MAKESHELL) overrides $(SHELL) even if -e is in effect. */
if (mshp)
(void) define_variable (shell_str, shlen,
- mshp->value, o_env_override, 0);
+ mshp->value, o_env_override, 0);
else if (comp)
{
- /* $(COMSPEC) shouldn't override $(SHELL). */
- struct variable *shp = lookup_variable (shell_str, shlen);
+ /* $(COMSPEC) shouldn't override $(SHELL). */
+ struct variable *shp = lookup_variable (shell_str, shlen);
- if (!shp)
- (void) define_variable (shell_str, shlen, comp->value, o_env, 0);
+ if (!shp)
+ (void) define_variable (shell_str, shlen, comp->value, o_env, 0);
}
}
#elif defined(__EMX__)
@@ -846,13 +842,13 @@ define_automatic_variables (void)
did not come from the environment */
if (!replace || !*replace->value)
if (shell && *shell->value && (shell->origin == o_env
- || shell->origin == o_env_override))
- {
- /* overwrite whatever we got from the environment */
- free(shell->value);
- shell->value = xstrdup (default_shell);
- shell->origin = o_default;
- }
+ || shell->origin == o_env_override))
+ {
+ /* overwrite whatever we got from the environment */
+ free (shell->value);
+ shell->value = xstrdup (default_shell);
+ shell->origin = o_default;
+ }
/* Some people do not like cmd to be used as the default
if $SHELL is not defined in the Makefile.
@@ -872,11 +868,11 @@ define_automatic_variables (void)
if (replace && *replace->value)
/* overwrite $SHELL */
(void) define_variable (shell_str, shlen, replace->value,
- replace->origin, 0);
+ replace->origin, 0);
else
/* provide a definition if there is none */
(void) define_variable (shell_str, shlen, default_shell,
- o_default, 0);
+ o_default, 0);
}
#endif
@@ -917,7 +913,23 @@ define_automatic_variables (void)
define_variable_cname ("?D", "$(dir $?)", o_automatic, 1);
define_variable_cname ("^D", "$(dir $^)", o_automatic, 1);
define_variable_cname ("+D", "$(dir $+)", o_automatic, 1);
-#else
+#elif defined(__MSDOS__) || defined(WINDOWS32)
+ /* For consistency, remove the trailing backslash as well as slash. */
+ define_variable_cname ("@D", "$(patsubst %/,%,$(patsubst %\\,%,$(dir $@)))",
+ o_automatic, 1);
+ define_variable_cname ("%D", "$(patsubst %/,%,$(patsubst %\\,%,$(dir $%)))",
+ o_automatic, 1);
+ define_variable_cname ("*D", "$(patsubst %/,%,$(patsubst %\\,%,$(dir $*)))",
+ o_automatic, 1);
+ define_variable_cname ("<D", "$(patsubst %/,%,$(patsubst %\\,%,$(dir $<)))",
+ o_automatic, 1);
+ define_variable_cname ("?D", "$(patsubst %/,%,$(patsubst %\\,%,$(dir $?)))",
+ o_automatic, 1);
+ define_variable_cname ("^D", "$(patsubst %/,%,$(patsubst %\\,%,$(dir $^)))",
+ o_automatic, 1);
+ define_variable_cname ("+D", "$(patsubst %/,%,$(patsubst %\\,%,$(dir $+)))",
+ o_automatic, 1);
+#else /* not __MSDOS__, not WINDOWS32 */
define_variable_cname ("@D", "$(patsubst %/,%,$(dir $@))", o_automatic, 1);
define_variable_cname ("%D", "$(patsubst %/,%,$(dir $%))", o_automatic, 1);
define_variable_cname ("*D", "$(patsubst %/,%,$(dir $*))", o_automatic, 1);
@@ -938,7 +950,7 @@ define_automatic_variables (void)
int export_all_variables;
/* Create a new environment for FILE's commands.
- If FILE is nil, this is for the `shell' function.
+ If FILE is nil, this is for the 'shell' function.
The child's MAKELEVEL variable is incremented. */
char **
@@ -959,7 +971,7 @@ target_environment (struct file *file)
set_list = file->variables;
hash_init (&table, VARIABLE_BUCKETS,
- variable_hash_1, variable_hash_2, variable_hash_cmp);
+ variable_hash_1, variable_hash_2, variable_hash_cmp);
/* Run through all the variable sets in the list,
accumulating variables in TABLE. */
@@ -969,68 +981,68 @@ target_environment (struct file *file)
v_slot = (struct variable **) set->table.ht_vec;
v_end = v_slot + set->table.ht_size;
for ( ; v_slot < v_end; v_slot++)
- if (! HASH_VACANT (*v_slot))
- {
- struct variable **new_slot;
- struct variable *v = *v_slot;
-
- /* If this is a per-target variable and it hasn't been touched
- already then look up the global version and take its export
- value. */
- if (v->per_target && v->export == v_default)
- {
- struct variable *gv;
-
- gv = lookup_variable_in_set (v->name, strlen(v->name),
+ if (! HASH_VACANT (*v_slot))
+ {
+ struct variable **new_slot;
+ struct variable *v = *v_slot;
+
+ /* If this is a per-target variable and it hasn't been touched
+ already then look up the global version and take its export
+ value. */
+ if (v->per_target && v->export == v_default)
+ {
+ struct variable *gv;
+
+ gv = lookup_variable_in_set (v->name, strlen (v->name),
&global_variable_set);
- if (gv)
- v->export = gv->export;
- }
+ if (gv)
+ v->export = gv->export;
+ }
- switch (v->export)
- {
- case v_default:
- if (v->origin == o_default || v->origin == o_automatic)
- /* Only export default variables by explicit request. */
- continue;
+ switch (v->export)
+ {
+ case v_default:
+ if (v->origin == o_default || v->origin == o_automatic)
+ /* Only export default variables by explicit request. */
+ continue;
/* The variable doesn't have a name that can be exported. */
if (! v->exportable)
continue;
- if (! export_all_variables
- && v->origin != o_command
- && v->origin != o_env && v->origin != o_env_override)
- continue;
- break;
-
- case v_export:
- break;
-
- case v_noexport:
- {
- /* If this is the SHELL variable and it's not exported,
- then add the value from our original environment, if
- the original environment defined a value for SHELL. */
- extern struct variable shell_var;
- if (streq (v->name, "SHELL") && shell_var.value)
- {
- v = &shell_var;
- break;
- }
- continue;
- }
-
- case v_ifset:
- if (v->origin == o_default)
- continue;
- break;
- }
-
- new_slot = (struct variable **) hash_find_slot (&table, v);
- if (HASH_VACANT (*new_slot))
- hash_insert_at (&table, v, new_slot);
- }
+ if (! export_all_variables
+ && v->origin != o_command
+ && v->origin != o_env && v->origin != o_env_override)
+ continue;
+ break;
+
+ case v_export:
+ break;
+
+ case v_noexport:
+ {
+ /* If this is the SHELL variable and it's not exported,
+ then add the value from our original environment, if
+ the original environment defined a value for SHELL. */
+ extern struct variable shell_var;
+ if (streq (v->name, "SHELL") && shell_var.value)
+ {
+ v = &shell_var;
+ break;
+ }
+ continue;
+ }
+
+ case v_ifset:
+ if (v->origin == o_default)
+ continue;
+ break;
+ }
+
+ new_slot = (struct variable **) hash_find_slot (&table, v);
+ if (HASH_VACANT (*new_slot))
+ hash_insert_at (&table, v, new_slot);
+ }
}
makelevel_key.name = MAKELEVEL_NAME;
@@ -1044,32 +1056,32 @@ target_environment (struct file *file)
for ( ; v_slot < v_end; v_slot++)
if (! HASH_VACANT (*v_slot))
{
- struct variable *v = *v_slot;
-
- /* 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);
+ struct variable *v = *v_slot;
+
+ /* 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, ';');
+ 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);
- }
- else
- {
+ *result++ = xstrdup (concat (3, v->name, "=", value));
+ free (value);
+ }
+ else
+ {
#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 (v->value, ';');
#endif
- *result++ = xstrdup (concat (3, v->name, "=", v->value));
- }
+ *result++ = xstrdup (concat (3, v->name, "=", v->value));
+ }
}
*result = xmalloc (100);
@@ -1095,11 +1107,34 @@ set_special_var (struct variable *var)
return var;
}
+/* Given a string, shell-execute it and return a malloc'ed string of the
+ * result. This removes only ONE newline (if any) at the end, for maximum
+ * compatibility with the *BSD makes. If it fails, returns NULL. */
+
+char *
+shell_result (const char *p)
+{
+ char *buf;
+ unsigned int len;
+ 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);
+
+ restore_variable_buffer (buf, len);
+ return result;
+}
+
/* Given a variable, a value, and a flavor, define the variable.
See the try_variable_definition() function for details on the parameters. */
struct variable *
-do_variable_definition (const struct floc *flocp, const char *varname,
+do_variable_definition (const gmk_floc *flocp, const char *varname,
const char *value, enum variable_origin origin,
enum variable_flavor flavor, int target_var)
{
@@ -1120,10 +1155,20 @@ do_variable_definition (const struct floc *flocp, const char *varname,
case f_simple:
/* A simple variable definition "var := value". Expand the value.
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
+ variable buffer, and we may still need that if we're looking at a
target-specific variable. */
p = alloc_value = allocated_variable_expand (value);
break;
+ case f_shell:
+ {
+ /* A shell definition "var != value". Expand value, pass it to
+ the shell, and store the result in recursively-expanded var. */
+ char *q = allocated_variable_expand (value);
+ p = alloc_value = shell_result (q);
+ free (q);
+ flavor = f_recursive;
+ break;
+ }
case f_conditional:
/* A conditional variable definition "var ?= value".
The value is set IFF the variable is not defined yet. */
@@ -1136,7 +1181,7 @@ do_variable_definition (const struct floc *flocp, const char *varname,
/* FALLTHROUGH */
case f_recursive:
/* A recursive variable definition "var = value".
- The value is used verbatim. */
+ The value is used verbatim. */
p = value;
break;
case f_append:
@@ -1201,7 +1246,7 @@ do_variable_definition (const struct floc *flocp, const char *varname,
#ifdef __MSDOS__
/* Many Unix Makefiles include a line saying "SHELL=/bin/sh", but
non-Unix systems don't conform to this default configuration (in
- fact, most of them don't even have `/bin'). On the other hand,
+ fact, most of them don't even have '/bin'). On the other hand,
$SHELL in the environment, if set, points to the real pathname of
the shell.
Therefore, we generally won't let lines like "SHELL=/bin/sh" from
@@ -1220,62 +1265,62 @@ do_variable_definition (const struct floc *flocp, const char *varname,
/* See if we can find "/bin/sh.exe", "/bin/sh.com", etc. */
if (__dosexec_find_on_path (p, NULL, shellpath))
- {
- char *tp;
+ {
+ char *tp;
- for (tp = shellpath; *tp; tp++)
+ for (tp = shellpath; *tp; tp++)
if (*tp == '\\')
*tp = '/';
- v = define_variable_loc (varname, strlen (varname),
+ v = define_variable_loc (varname, strlen (varname),
shellpath, origin, flavor == f_recursive,
flocp);
- }
+ }
else
- {
- const char *shellbase, *bslash;
- struct variable *pathv = lookup_variable ("PATH", 4);
- char *path_string;
- char *fake_env[2];
- size_t pathlen = 0;
-
- shellbase = strrchr (p, '/');
- bslash = strrchr (p, '\\');
- if (!shellbase || bslash > shellbase)
- shellbase = bslash;
- if (!shellbase && p[1] == ':')
- shellbase = p + 1;
- if (shellbase)
- shellbase++;
- else
- shellbase = p;
-
- /* Search for the basename of the shell (with standard
- executable extensions) along the $PATH. */
- if (pathv)
- pathlen = strlen (pathv->value);
- path_string = xmalloc (5 + pathlen + 2 + 1);
- /* On MSDOS, current directory is considered as part of $PATH. */
- sprintf (path_string, "PATH=.;%s", pathv ? pathv->value : "");
- fake_env[0] = path_string;
- fake_env[1] = 0;
- if (__dosexec_find_on_path (shellbase, fake_env, shellpath))
- {
- char *tp;
-
- for (tp = shellpath; *tp; tp++)
+ {
+ const char *shellbase, *bslash;
+ struct variable *pathv = lookup_variable ("PATH", 4);
+ char *path_string;
+ char *fake_env[2];
+ size_t pathlen = 0;
+
+ shellbase = strrchr (p, '/');
+ bslash = strrchr (p, '\\');
+ if (!shellbase || bslash > shellbase)
+ shellbase = bslash;
+ if (!shellbase && p[1] == ':')
+ shellbase = p + 1;
+ if (shellbase)
+ shellbase++;
+ else
+ shellbase = p;
+
+ /* Search for the basename of the shell (with standard
+ executable extensions) along the $PATH. */
+ if (pathv)
+ pathlen = strlen (pathv->value);
+ path_string = xmalloc (5 + pathlen + 2 + 1);
+ /* On MSDOS, current directory is considered as part of $PATH. */
+ sprintf (path_string, "PATH=.;%s", pathv ? pathv->value : "");
+ fake_env[0] = path_string;
+ fake_env[1] = 0;
+ if (__dosexec_find_on_path (shellbase, fake_env, shellpath))
+ {
+ char *tp;
+
+ for (tp = shellpath; *tp; tp++)
if (*tp == '\\')
*tp = '/';
- v = define_variable_loc (varname, strlen (varname),
+ v = define_variable_loc (varname, strlen (varname),
shellpath, origin,
flavor == f_recursive, flocp);
- }
- else
- v = lookup_variable (varname, strlen (varname));
+ }
+ else
+ v = lookup_variable (varname, strlen (varname));
- free (path_string);
- }
+ free (path_string);
+ }
}
else
#endif /* __MSDOS__ */
@@ -1286,7 +1331,7 @@ do_variable_definition (const struct floc *flocp, const char *varname,
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 no_default_sh_exe to indicate sh was found and
set new value for SHELL variable. */
if (find_and_set_default_shell (p))
@@ -1347,61 +1392,72 @@ do_variable_definition (const struct floc *flocp, const char *varname,
/* Parse P (a null-terminated string) as a variable definition.
- If it is not a variable definition, return NULL.
+ If it is not a variable definition, return NULL and the contents of *VAR
+ are undefined, except NAME is set to the first non-space character or NIL.
If it is a variable definition, return a pointer to the char after the
- assignment token and set *FLAVOR to the type of variable assignment. */
+ assignment token and set the following fields (only) of *VAR:
+ name : name of the variable (ALWAYS SET) (NOT NUL-TERMINATED!)
+ length : length of the variable name
+ value : value of the variable (nul-terminated)
+ flavor : flavor of the variable
+ Other values in *VAR are unchanged.
+ */
char *
-parse_variable_definition (const char *p, enum variable_flavor *flavor)
+parse_variable_definition (const char *p, struct variable *var)
{
int wspace = 0;
+ const char *e = NULL;
p = next_token (p);
+ var->name = (char *)p;
+ var->length = 0;
while (1)
{
int c = *p++;
/* If we find a comment or EOS, it's not a variable definition. */
- if (c == '\0' || c == '#')
- return NULL;
+ if (STOP_SET (c, MAP_COMMENT|MAP_NUL))
+ return NULL;
if (c == '$')
- {
- /* This begins a variable expansion reference. Make sure we don't
- treat chars inside the reference as assignment tokens. */
- char closeparen;
- int count;
- c = *p++;
- if (c == '(')
- closeparen = ')';
- else if (c == '{')
- closeparen = '}';
- else
+ {
+ /* This begins a variable expansion reference. Make sure we don't
+ treat chars inside the reference as assignment tokens. */
+ char closeparen;
+ int count;
+ c = *p++;
+ if (c == '(')
+ closeparen = ')';
+ else if (c == '{')
+ closeparen = '}';
+ else
/* '$$' or '$X'. Either way, nothing special to do here. */
- continue;
-
- /* 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;
- }
- }
+ continue;
+
+ /* 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;
+ }
+ }
continue;
- }
+ }
/* If we find whitespace skip it, and remember we found it. */
if (isblank ((unsigned char)c))
{
wspace = 1;
+ e = p - 1;
p = next_token (p);
c = *p;
if (c == '\0')
@@ -1411,24 +1467,29 @@ parse_variable_definition (const char *p, enum variable_flavor *flavor)
if (c == '=')
- {
- *flavor = f_recursive;
- return (char *)p;
- }
+ {
+ var->flavor = f_recursive;
+ if (! e)
+ e = p - 1;
+ break;
+ }
- /* Match assignment variants (:=, +=, ?=) */
+ /* Match assignment variants (:=, +=, ?=, !=) */
if (*p == '=')
{
switch (c)
{
case ':':
- *flavor = f_simple;
+ var->flavor = f_simple;
break;
case '+':
- *flavor = f_append;
+ var->flavor = f_append;
break;
case '?':
- *flavor = f_conditional;
+ var->flavor = f_conditional;
+ break;
+ case '!':
+ var->flavor = f_shell;
break;
default:
/* If we skipped whitespace, non-assignments means no var. */
@@ -1438,50 +1499,55 @@ parse_variable_definition (const char *p, enum variable_flavor *flavor)
/* Might be assignment, or might be $= or #=. Check. */
continue;
}
- return (char *)++p;
+ if (! e)
+ e = p - 1;
+ ++p;
+ break;
+ }
+
+ /* Check for POSIX ::= syntax */
+ if (c == ':')
+ {
+ /* A colon other than :=/::= is not a variable defn. */
+ if (*p != ':' || p[1] != '=')
+ return NULL;
+
+ /* POSIX allows ::= to be the same as GNU make's := */
+ var->flavor = f_simple;
+ if (! e)
+ e = p - 1;
+ p += 2;
+ break;
}
- else if (c == ':')
- /* A colon other than := is a rule line, not a variable defn. */
- return NULL;
/* If we skipped whitespace, non-assignments means no var. */
if (wspace)
return NULL;
}
+ var->length = e - var->name;
+ var->value = next_token (p);
return (char *)p;
}
/* Try to interpret LINE (a null-terminated string) as a variable definition.
- If LINE was recognized as a variable definition, a pointer to its `struct
+ 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 *
assign_variable_definition (struct variable *v, char *line)
{
- char *beg;
- char *end;
- enum variable_flavor flavor;
char *name;
- beg = next_token (line);
- line = parse_variable_definition (beg, &flavor);
- if (!line)
+ if (!parse_variable_definition (line, v))
return NULL;
- end = line - (flavor == f_recursive ? 1 : 2);
- while (end > beg && isblank ((unsigned char)end[-1]))
- --end;
- line = next_token (line);
- v->value = line;
- v->flavor = flavor;
-
/* Expand the name, so "$(foo)bar = baz" works. */
- name = alloca (end - beg + 1);
- memcpy (name, beg, end - beg);
- name[end - beg] = '\0';
+ name = alloca (v->length + 1);
+ memcpy (name, v->name, v->length);
+ name[v->length] = '\0';
v->name = allocated_variable_expand (name);
if (v->name[0] == '\0')
@@ -1499,12 +1565,12 @@ assign_variable_definition (struct variable *v, char *line)
See the comments for assign_variable_definition().
- If LINE was recognized as a variable definition, a pointer to its `struct
+ 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 (const struct floc *flocp, char *line,
+try_variable_definition (const gmk_floc *flocp, char *line,
enum variable_origin origin, int target_var)
{
struct variable v;
@@ -1537,6 +1603,9 @@ print_variable (const void *item, void *arg)
switch (v->origin)
{
+ case o_automatic:
+ origin = _("automatic");
+ break;
case o_default:
origin = _("default");
break;
@@ -1553,10 +1622,7 @@ print_variable (const void *item, void *arg)
origin = _("command line");
break;
case o_override:
- origin = _("`override' directive");
- break;
- case o_automatic:
- origin = _("automatic");
+ origin = _("'override' directive");
break;
case o_invalid:
default:
@@ -1567,12 +1633,12 @@ print_variable (const void *item, void *arg)
if (v->private_var)
fputs (" private", stdout);
if (v->fileinfo.filenm)
- printf (_(" (from `%s', line %lu)"),
+ printf (_(" (from '%s', line %lu)"),
v->fileinfo.filenm, v->fileinfo.lineno);
putchar ('\n');
fputs (prefix, stdout);
- /* Is this a `define'? */
+ /* Is this a 'define'? */
if (v->recursive && strchr (v->value, '\n') != 0)
printf ("define %s\n%s\nendef\n", v->name, v->value);
else
@@ -1584,30 +1650,51 @@ print_variable (const void *item, void *arg)
/* Check if the value is just whitespace. */
p = next_token (v->value);
if (p != v->value && *p == '\0')
- /* All whitespace. */
- printf ("$(subst ,,%s)", v->value);
+ /* All whitespace. */
+ printf ("$(subst ,,%s)", v->value);
else if (v->recursive)
- fputs (v->value, stdout);
+ fputs (v->value, stdout);
else
- /* Double up dollar signs. */
- for (p = v->value; *p != '\0'; ++p)
- {
- if (*p == '$')
- putchar ('$');
- putchar (*p);
- }
+ /* Double up dollar signs. */
+ for (p = v->value; *p != '\0'; ++p)
+ {
+ if (*p == '$')
+ putchar ('$');
+ putchar (*p);
+ }
putchar ('\n');
}
}
+static void
+print_auto_variable (const void *item, void *arg)
+{
+ const struct variable *v = item;
+
+ if (v->origin == o_automatic)
+ print_variable (item, arg);
+}
+
+
+static void
+print_noauto_variable (const void *item, void *arg)
+{
+ const struct variable *v = item;
+
+ if (v->origin != o_automatic)
+ print_variable (item, arg);
+}
+
+
/* Print all the variables in SET. PREFIX is printed before
the actual variable definitions (everything else is comments). */
void
-print_variable_set (struct variable_set *set, char *prefix)
+print_variable_set (struct variable_set *set, char *prefix, int pauto)
{
- hash_map_arg (&set->table, print_variable, prefix);
+ hash_map_arg (&set->table, (pauto ? print_auto_variable : print_variable),
+ prefix);
fputs (_("# variable set hash-table stats:\n"), stdout);
fputs ("# ", stdout);
@@ -1622,7 +1709,7 @@ print_variable_data_base (void)
{
puts (_("\n# Variables\n"));
- print_variable_set (&global_variable_set, "");
+ print_variable_set (&global_variable_set, "", 0);
puts (_("\n# Pattern-specific Variable Values"));
@@ -1651,7 +1738,24 @@ void
print_file_variables (const struct file *file)
{
if (file->variables != 0)
- print_variable_set (file->variables->set, "# ");
+ print_variable_set (file->variables->set, "# ", 1);
+}
+
+void
+print_target_variables (const struct file *file)
+{
+ if (file->variables != 0)
+ {
+ int l = strlen (file->name);
+ char *t = alloca (l + 3);
+
+ strcpy (t, file->name);
+ t[l] = ':';
+ t[l+1] = ' ';
+ t[l+2] = '\0';
+
+ hash_map_arg (&file->variables->set->table, print_noauto_variable, t);
+ }
}
#ifdef WINDOWS32