Imported Upstream version 4.0
[platform/upstream/make.git] / variable.c
index 915be20..2ff14b6 100644 (file)
@@ -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)
 \f
 /* 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)
 \f
 /* 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;
     }
 }
 \f
@@ -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;
 }
 \f
+/* 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;
+}
+\f
 /* 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,
 \f
 /* 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;
 }
 \f
 /* 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