* Fix PR/1407.
* Keep filename/lineno information for variables, for debugging.
diff --git a/ChangeLog b/ChangeLog
index 7ed88a7..8fdd6d7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+2000-02-04  Paul D. Smith  <psmith@gnu.org>
+
+	* variable.c (print_variable): Write out filename/linenumber
+	information for the variable definition if present.
+	(define_variable_in_set): Store filename information if provided.
+	(define_variable, define_variable_for_file): Removed.
+	(try_variable_definition): Use define_variable_loc() to keep
+	variable definition location information.
+	* read.c (read_makefile): Keep variable definition location info.
+	(do_define): Ditto.
+	(record_target_var): Ditto.
+	* variable.h (define_variable_in_set): New fileinfo argument.
+	(define_variable, define_variable_loc, define_variable_for_file):
+	Declare new macros.
+
+	Fix PR/1407:
+
+	* filedef.h (struct file): Rename patvar to pat_variables and make
+	it just a variable_set_list; we need our own copy of the pattern
+	variable's variable set list here to avoid overwriting the global
+	one.
+	* variable.c (initialize_file_variables): Move the instantiation
+	of the pat_variables pointer here.  Only do the search after we're
+	done reading the makefiles so we don't search too early.  If
+	there's a pat_variables value, set up the variables next ptr.
+	* expand.c (variable_expand_for_file): Remove the setup of the
+	pat_variables info; it's done earlier now to ensure the parent's
+	pattern variables are set up correctly as well.
+
 2000-01-25  Paul D. Smith  <psmith@gnu.org>
 
 	Change gettext support to use the simplified version in libit 0.7.
diff --git a/NEWS b/NEWS
index 0dfc96d..9fe1e02 100644
--- a/NEWS
+++ b/NEWS
@@ -23,8 +23,8 @@
   be used within make build scripts.  However, using them there is not
   proper behavior: they are meant to be passed to subshells via the
   environment.  Unfortunately the values were not quoted properly to be
-  passed through the environment.  This meant that some invocations of
-  make didn't properly pass values to submakes.
+  passed through the environment.  This meant that make didn't properly
+  pass some types of command line values to submakes.
 
   With this version we change that behavior: now these variables are
   quoted properly for passing through the environment, which is the
@@ -32,9 +32,9 @@
   explicitly within a make rule you may need to re-examine your use for
   correctness given this change.
 
-* A new psuedo-target, .NOTPARALLEL, is defined.  If set the current
-  makefile is always run serially regardless of the value of -j.  Any
-  submakes will still be run in parallel if -j was specified.
+* A new psuedo-target .NOTPARALLEL is available.  If defined, the
+  current makefile is run serially regardless of the value of -j.
+  However, submakes are still eligible for parallel execution.
 
 * The $(call ...) function doesn't expand its arguments automatically
   anymore.  This allows you to put builtin functions like "if" and
@@ -48,8 +48,11 @@
   "normal" targets (not makefiles) were deemed out of date and in need
   of being rebuilt.
 
-  Note that the -d option behaves as before: all debugging information
-  is generated.
+  Note that the -d option behaves as before: it takes no arguments and
+  all debugging information is generated.
+
+* The `-p' (print database) output now includes filename and linenumber
+  information for variable definitions, to help debugging.
 
 * Hartmut Becker provided many updates for the VMS port of GNU make.
   See the readme.vms file for more details.
diff --git a/commands.c b/commands.c
index 8a8d227..75b3399 100644
--- a/commands.c
+++ b/commands.c
@@ -108,7 +108,7 @@
     less = at;
 
 #define	DEFINE_VARIABLE(name, len, value) \
-  (void) define_variable_for_file (name, len, value, o_automatic, 0, file)
+  (void) define_variable_for_file (name,len,value,o_automatic,0,file)
 
   /* Define the variables.  */
 
@@ -354,7 +354,7 @@
 
   /* First set the automatic variables according to this file.  */
 
-  initialize_file_variables (file);
+  initialize_file_variables (file, 0);
 
   set_file_variables (file);
 
diff --git a/expand.c b/expand.c
index a7cfcdb..f15da02 100644
--- a/expand.c
+++ b/expand.c
@@ -445,7 +445,7 @@
      register struct file *file;
 {
   char *result;
-  struct variable_set_list *save, *fnext;
+  struct variable_set_list *save;
 
   if (file == 0)
     return variable_expand (line);
@@ -456,22 +456,9 @@
     reading_file = &file->cmds->fileinfo;
   else
     reading_file = 0;
-  fnext = file->variables->next;
-  /* See if there's a pattern-specific variable struct for this target.  */
-  if (!file->pat_searched)
-    {
-      file->patvar = lookup_pattern_var(file->name);
-      file->pat_searched = 1;
-    }
-  if (file->patvar != 0)
-    {
-      file->patvar->vars->next = fnext;
-      file->variables->next = file->patvar->vars;
-    }
   result = variable_expand (line);
   current_variable_set_list = save;
   reading_file = 0;
-  file->variables->next = fnext;
 
   return result;
 }
diff --git a/filedef.h b/filedef.h
index f39b82a..8712e98 100644
--- a/filedef.h
+++ b/filedef.h
@@ -48,6 +48,10 @@
     /* List of variable sets used for this file.  */
     struct variable_set_list *variables;
 
+    /* Pattern-specific variable reference for this target, or null if there
+       isn't one.  Also see the pat_searched flag, below.  */
+    struct variable_set_list *pat_variables;
+
     /* Immediate dependent that caused this target to be remade,
        or nil if there isn't one.  */
     struct file *parent;
@@ -56,10 +60,6 @@
        the same file.  Otherwise this is null.  */
     struct file *double_colon;
 
-    /* Pattern-specific variable reference for this target, or null if there
-       isn't one.  Also see the pat_searched flag, below.  */
-    struct pattern_var *patvar;
-
     short int update_status;	/* Status of the last attempt to update,
 				   or -1 if none has been made.  */
 
diff --git a/read.c b/read.c
index 67d78d0..67b2a2d 100644
--- a/read.c
+++ b/read.c
@@ -609,7 +609,7 @@
 		{
 		  v = lookup_variable (p, len);
 		  if (v == 0)
-		    v = define_variable (p, len, "", o_file, 0);
+		    v = define_variable_loc (p, len, "", o_file, 0, &fileinfo);
 		  v->export = v_export;
 		}
 	    }
@@ -626,7 +626,7 @@
 	    {
 	      v = lookup_variable (p, len);
 	      if (v == 0)
-		v = define_variable (p, len, "", o_file, 0);
+		v = define_variable_loc (p, len, "", o_file, 0, &fileinfo);
 	      v->export = v_noexport;
 	    }
 	}
@@ -1116,7 +1116,8 @@
 	    definition[0] = '\0';
 	  else
 	    definition[idx - 1] = '\0';
-	  (void) define_variable (var, strlen (var), definition, origin, 1);
+	  (void) define_variable_loc (var, strlen (var), definition, origin,
+                                      1, flocp);
 	  free (definition);
 	  freebuffer (&lb);
 	  return;
@@ -1454,7 +1455,7 @@
 
           /* Get a file reference for this file, and initialize it.  */
           f = enter_file (name);
-          initialize_file_variables (f);
+          initialize_file_variables (f, 1);
           vlist = f->variables;
           fname = f->name;
         }
@@ -1477,7 +1478,7 @@
           gv = lookup_variable (v->name, len);
           if (gv && (gv->origin == o_env_override || gv->origin == o_command))
             define_variable_in_set (v->name, len, gv->value, gv->origin,
-                                    gv->recursive, vlist->set);
+                                    gv->recursive, vlist->set, flocp);
         }
 
       /* Free name if not needed further.  */
diff --git a/rule.c b/rule.c
index 5933777..2b4456e 100644
--- a/rule.c
+++ b/rule.c
@@ -607,12 +607,12 @@
         continue;
 
       /* Compare the text in the pattern after the stem, if any.
-         We could test simply use streq, but this way we compare the
+         We could test simply using streq, but this way we compare the
          first two characters immediately.  This saves time in the very
          common case where the first character matches because it is a
          period.  */
       if (*p->suffix == stem[stemlen]
-          && (*p->suffix == '\0'|| streq (&p->suffix[1], &stem[stemlen+1])))
+          && (*p->suffix == '\0' || streq (&p->suffix[1], &stem[stemlen+1])))
         break;
     }
 
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 68825fa..368a30c 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,7 @@
+2000-02-04  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/features/patspecific_vars: Add a test for PR/1407.
+
 2000-01-23  Paul D. Smith  <psmith@gnu.org>
 
 	* scripts/features/include: Remove a check; the fix caused more
diff --git a/tests/scripts/features/patspecific_vars b/tests/scripts/features/patspecific_vars
index 0684a80..7feb687 100644
--- a/tests/scripts/features/patspecific_vars
+++ b/tests/scripts/features/patspecific_vars
@@ -19,6 +19,8 @@
 %.x: override BAZ = three
 one.x: override FOO = one
 one.x two.x three.x: ; @echo $(FOO) $(BAR) $(BAZ)
+four.x: baz ; @echo $(FOO) $(BAR) $(BAZ)
+baz: ; @echo $(FOO) $(BAR) $(BAZ)
 EOF
 
 close(MAKEFILE);
@@ -37,4 +39,11 @@
 $answer = "one two three\nfoo four five\nfoo bar three\n";
 &compare_output($answer,&get_logfile(1));
 
+
+# TEST #3 -- make sure patterns are inherited properly
+
+&run_make_with_options($makefile, "four.x", &get_logfile);
+$answer = "foo two three\nfoo two three\n";
+&compare_output($answer,&get_logfile(1));
+
 1;
diff --git a/variable.c b/variable.c
index 6d105b2..58af121 100644
--- a/variable.c
+++ b/variable.c
@@ -23,6 +23,7 @@
 #include "job.h"
 #include "commands.h"
 #include "variable.h"
+#include "rule.h"
 #ifdef WINDOWS32
 #include "pathstuff.h"
 #endif
@@ -58,13 +59,14 @@
    that it should be recursively re-expanded.  */
 
 struct variable *
-define_variable_in_set (name, length, value, origin, recursive, set)
+define_variable_in_set (name, length, value, origin, recursive, set, flocp)
      char *name;
      unsigned int length;
      char *value;
      enum variable_origin origin;
      int recursive;
      struct variable_set *set;
+     const struct floc *flocp;
 {
   register unsigned int i;
   register unsigned int hashval;
@@ -99,6 +101,10 @@
 	  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;
 	}
@@ -110,6 +116,10 @@
   v = (struct variable *) xmalloc (sizeof (struct variable));
   v->name = savestring (name, length);
   v->value = xstrdup (value);
+  if (flocp != 0)
+    v->fileinfo = *flocp;
+  else
+    v->fileinfo.filenm = 0;
   v->origin = origin;
   v->recursive = recursive;
   v->expanding = 0;
@@ -120,35 +130,6 @@
   set->table[hashval] = v;
   return v;
 }
-
-/* Define a variable in the current variable set.  */
-
-struct variable *
-define_variable (name, length, value, origin, recursive)
-     char *name;
-     unsigned int length;
-     char *value;
-     enum variable_origin origin;
-     int recursive;
-{
-  return define_variable_in_set (name, length, value, origin, recursive,
-				 current_variable_set_list->set);
-}
-
-/* Define a variable in FILE's variable set.  */
-
-struct variable *
-define_variable_for_file (name, length, value, origin, recursive, file)
-     char *name;
-     unsigned int length;
-     char *value;
-     enum variable_origin origin;
-     int recursive;
-     struct file *file;
-{
-  return define_variable_in_set (name, length, value, origin, recursive,
-				 file->variables->set);
-}
 
 /* Lookup a variable whose name is a string starting at NAME
    and with LENGTH chars.  NAME need not be null-terminated.
@@ -272,13 +253,17 @@
 
 /* Initialize FILE's variable set list.  If FILE already has a variable set
    list, the topmost variable set is left intact, but the the rest of the
-   chain is replaced with FILE->parent's setlist.  */
+   chain is replaced with FILE->parent's setlist.  If we're READing a
+   makefile, don't do the pattern variable search now, since the pattern
+   variable might not have been defined yet.  */
 
 void
-initialize_file_variables (file)
+initialize_file_variables (file, reading)
      struct file *file;
+     int reading;
 {
   register struct variable_set_list *l = file->variables;
+
   if (l == 0)
     {
       l = (struct variable_set_list *)
@@ -296,9 +281,35 @@
     l->next = &global_setlist;
   else
     {
-      initialize_file_variables (file->parent);
+      initialize_file_variables (file->parent, reading);
       l->next = file->parent->variables;
     }
+
+  /* If we're not reading makefiles and we haven't looked yet, see if
+     we can find a pattern variable.  */
+
+  if (!reading && !file->pat_searched)
+    {
+      struct pattern_var *p = lookup_pattern_var (file->name);
+
+      file->pat_searched = 1;
+      if (p != 0)
+        {
+          /* If we found one, insert it between the current target's
+             variables and the next set, whatever it is.  */
+          file->pat_variables = (struct variable_set_list *)
+            xmalloc (sizeof (struct variable_set_list));
+          file->pat_variables->set = p->vars->set;
+        }
+    }
+
+  /* If we have a pattern variable match, set it up.  */
+
+  if (file->pat_variables != 0)
+    {
+      file->pat_variables->next = l->next;
+      l->next = file->pat_variables;
+    }
 }
 
 /* Pop the top set off the current variable set list,
@@ -947,8 +958,9 @@
 	      if (*p == '\\')
 		*p = '/';
 	    }
-	  v = define_variable (expanded_name, strlen (expanded_name),
-			       shellpath, origin, flavor == f_recursive);
+	  v = define_variable_loc (expanded_name, strlen (expanded_name),
+                                   shellpath, origin, flavor == f_recursive,
+                                   flocp);
 	}
       else
 	{
@@ -987,8 +999,9 @@
 		  if (*p == '\\')
 		    *p = '/';
 		}
-	      v = define_variable (expanded_name, strlen (expanded_name),
-				   shellpath, origin, flavor == f_recursive);
+	      v = define_variable_loc (expanded_name, strlen (expanded_name),
+                                       shellpath, origin,
+                                       flavor == f_recursive, flocp);
 	    }
 	  else
 	    v = lookup_variable (expanded_name, strlen (expanded_name));
@@ -1009,15 +1022,16 @@
      * set new value for SHELL variable.
 	 */
     if (find_and_set_default_shell(value)) {
-       v = define_variable (expanded_name, strlen (expanded_name),
-                            default_shell, origin, flavor == f_recursive);
+       v = define_variable_loc (expanded_name, strlen (expanded_name),
+                                default_shell, origin, flavor == f_recursive,
+                                flocp);
        no_default_sh_exe = 0;
     }
   } else
 #endif
 
-  v = define_variable (expanded_name, strlen (expanded_name),
-		       value, origin, flavor == f_recursive);
+  v = define_variable_loc (expanded_name, strlen (expanded_name), value,
+                           origin, flavor == f_recursive, flocp);
 
   v->append = append;
 
@@ -1040,32 +1054,35 @@
   switch (v->origin)
     {
     case o_default:
-      origin = "default";
+      origin = _("default");
       break;
     case o_env:
-      origin = "environment";
+      origin = _("environment");
       break;
     case o_file:
-      origin = "makefile";
+      origin = _("makefile");
       break;
     case o_env_override:
-      origin = "environment under -e";
+      origin = _("environment under -e");
       break;
     case o_command:
-      origin = "command line";
+      origin = _("command line");
       break;
     case o_override:
-      origin = "`override' directive";
+      origin = _("`override' directive");
       break;
     case o_automatic:
-      origin = "automatic";
+      origin = _("automatic");
       break;
     case o_invalid:
     default:
       abort ();
     }
-  printf ("# %s\n", origin);
-
+  fputs ("# ", stdout);
+  fputs (origin, stdout);
+  if (v->fileinfo.filenm)
+    printf (" (from `%s', line %lu)", v->fileinfo.filenm, v->fileinfo.lineno);
+  putchar ('\n');
   fputs (prefix, stdout);
 
   /* Is this a `define'?  */
diff --git a/variable.h b/variable.h
index 19ec31e..d449ef8 100644
--- a/variable.h
+++ b/variable.h
@@ -40,6 +40,7 @@
     struct variable *next;	/* Link in the chain.  */
     char *name;			/* Variable name.  */
     char *value;		/* Variable value.  */
+    struct floc fileinfo;       /* Where the variable was defined.  */
     enum variable_origin
       origin ENUM_BITFIELD (3);	/* Variable origin.  */
     unsigned int recursive:1;	/* Gets recursively re-evaluated.  */
@@ -101,19 +102,36 @@
 extern struct variable_set_list *push_new_variable_scope PARAMS ((void));
 extern void pop_variable_scope PARAMS ((void));
 extern void define_automatic_variables PARAMS ((void));
-extern void initialize_file_variables PARAMS ((struct file *file));
+extern void initialize_file_variables PARAMS ((struct file *file, int read));
 extern void print_file_variables PARAMS ((struct file *file));
 extern void print_variable_set PARAMS ((struct variable_set *set, char *prefix));
 extern void merge_variable_set_lists PARAMS ((struct variable_set_list **setlist0, struct variable_set_list *setlist1));
 extern struct variable *try_variable_definition PARAMS ((const struct floc *flocp, char *line, enum variable_origin origin, int target_var));
 
 extern struct variable *lookup_variable PARAMS ((char *name, unsigned int length));
-extern struct variable *define_variable PARAMS ((char *name, unsigned int length, char *value,
-		enum variable_origin origin, int recursive));
-extern struct variable *define_variable_in_set PARAMS ((char *name, unsigned int length,
-		char *value, enum variable_origin origin, int recursive, struct variable_set *set));
-extern struct variable *define_variable_for_file PARAMS ((char *name, unsigned int length,
-		char *value, enum variable_origin origin, int recursive, struct file *file));
+
+extern struct variable *define_variable_in_set
+    PARAMS ((char *name, unsigned int length, char *value,
+             enum variable_origin origin, int recursive,
+             struct variable_set *set, const struct floc *flocp));
+
+/* Define a variable in the current variable set.  */
+
+#define define_variable(n,l,v,o,r) \
+          define_variable_in_set((n),(l),(v),(o),(r),\
+                                 current_variable_set_list->set,NILF)
+
+/* Define a variable with a location in the current variable set.  */
+
+#define define_variable_loc(n,l,v,o,r,f) \
+          define_variable_in_set((n),(l),(v),(o),(r),\
+                                 current_variable_set_list->set,(f))
+
+/* Define a variable in FILE's variable set.  */
+
+#define define_variable_for_file(n,l,v,o,r,f) \
+          define_variable_in_set((n),(l),(v),(o),(r),(f)->variables->set,NILF)
+
 extern char **target_environment PARAMS ((struct file *file));
 
 extern int export_all_variables;