Index: /trunk/src/kmk/AUTHORS
===================================================================
--- /trunk/src/kmk/AUTHORS	(revision 2590)
+++ /trunk/src/kmk/AUTHORS	(revision 2591)
@@ -67,6 +67,6 @@
 
 -------------------------------------------------------------------------------
-Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
-Free Software Foundation, Inc.
+Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
+2008, 2009, 2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
Index: /trunk/src/kmk/ChangeLog
===================================================================
--- /trunk/src/kmk/ChangeLog	(revision 2590)
+++ /trunk/src/kmk/ChangeLog	(revision 2591)
@@ -1,2 +1,841 @@
+2010-07-28  Paul Smith  <psmith@gnu.org>
+
+	Version 3.82 released.
+
+	* configure.in: Change release version.
+	* NEWS: Change the date.
+
+	* read.c (parse_file_seq): Remove GLOB_NOSORT for
+	backward-compatibility.  We'll add it back in next release.
+	* NEWS: Note it.
+
+2010-07-24  Eli Zaretskii  <eliz@gnu.org>
+
+	* job.c (pid2str) [WINDOWS32]: Fix CPP conditionals for using %Id
+	format.
+
+2010-07-18  Paul Smith  <psmith@gnu.org>
+
+	* configure.in: Switch bsd_signal to AC_CHECK_DECLS() to make sure
+	we have a declaration.  Fixes Savannah bug #25713 (maybe?)
+	* doc/make.texi (Complex Makefile): Cleanup variable assignments.
+	(One Shell): New subsection for the .ONESHELL special target.
+
+	Patches by Ozkan Sezer <sezeroz@gmail.com>:
+
+	* misc.c (strncasecmp): Local implementation for systems without.
+	* config.h.W32.template (HAVE_STRNICMP): Define on Windows.
+	* configure.in: Check for strncasecmp/strncmpi/strnicmp.
+	* job.c [WINDOWS32]: Don't define dup2 on Windows.
+	(pid2str): Use "%Id" even with MSVC
+	(exec_command): Cast to pid_t when calling pid2str().
+	* w32/subproc/sub_proc.c [WINDOWS32]: Include config.h first.
+	Use stddef.h on MSVC to get intptr_t.
+	* w32/subproc/misc.c [WINDOWS32]: Include config.h first.
+	* w32/compat/dirent.c [WINDOWS32]: Include config.h first.
+	(readdir): Cast -1 to correct type for d_ino.
+	* w32/pathstuff.c [WINDOWS32]: Ensure make.h is included first.
+	* make.h [WINDOWS32]: Don't prototype alloca() on Windows.
+	Add configuration for strncasecmp().
+	* main.c (ADD_SIG) [WINDOWS32]: Avoid warnings in MSVC.
+	* config.h.W32.template [WINDOWS32]: Don't warn on unsafe
+	functions or variables.
+	* NMakefile.template [WINDOWS32]: Remove /MACHINE:I386.
+	* main.c (clean_jobserver): Cast due to MSVC brokenness.
+	(decode_switches): Ditto.
+	* vpath.c (construct_vpath_list): Ditto.
+	* rule.c (freerule): Ditto.
+	* ar.c (ar_glob): Ditto.
+
+2010-07-16  Boris Kolpackov  <boris@codesynthesis.com>
+
+	* misc.c (concat): Fix buffer overrun.
+
+2010-07-12  Paul Smith  <psmith@gnu.org>
+
+	Update copyrights to add 2010.
+
+	* build_w32.bat: Support for MSVC Windows x86_64 builds.
+	* job.c: Don't define execve() on MSVC/64bit.
+	Patch by Viktor Szakats.  Fixes Savannah bug #27590.
+
+2010-07-12  Eli Zaretskii  <eliz@gnu.org>
+
+	* make.h (alloca) [!__GNUC__]: Don't define prototype.
+	(int w32_kill): Use pid_t for process ID argument.
+	Fixes Savannah bug #27809.
+
+2010-07-12  Paul Smith  <psmith@gnu.org>
+
+	Integrated new .ONESHELL feature.
+	Patch by David Boyce <dsb@boyski.com>.  Modified by me.
+
+	* NEWS: Add a note about the new feature.
+	* job.c (is_bourne_compatible_shell): Determine whether we're
+	using a standard POSIX shell or not.
+	(start_job_command): Accept '-ec' as POSIX shell flags.
+	(construct_command_argv_internal): If one_shell is set and we are
+	using a POSIX shell, remove "interior" prefix characters such as
+	"@", "+", "-".  Also treat "\n" as a special character when
+	choosing the slow path, if ONESHELL is set.
+	* job.h (is_bourne_compatible_argv): Define the new function.
+
+	* make.h (one_shell): New global variable to remember setting.
+	* main.c: Declare it.
+	* read.c (record_files): Set it.
+	* commands.c (chop_commands): If one_shell is set, don't chop
+	commands into multiple lines; just keep one line.
+
+2010-07-09  Eli Zaretskii  <eliz@gnu.org>
+
+	* w32/subproc/sub_proc.c: Include stdint.h.
+	(sub_process_t): Use intptr_t for file handles and pid_t for
+	process ID.
+	(process_pipes, process_init_fd, process_begin): Use intptr_t for
+	file handles and pid_t for process ID.  Fixes Savannah bug #27809.
+	Patch by Ozkan Sezer <sezeroz@gmail.com>
+
+	* function.c (abspath): Support absolute file names in UNC format.
+	Fixes Savannah bug #30312.
+
+	* job.c (pid2str) [WINDOWS32]: Don't use %Id with GCC < 4.x.
+	(exec_command) [WINDOWS32]: Use pid2str instead of non-portable
+	%Id.
+
+	* main.c (handle_runtime_exceptions): Use %p to print addresses,
+	to DTRT on both 32-bit and 64-bit hosts.  Savannah bug #27809.
+
+	* job.c (w32_kill, start_job_command, create_batch_file): Use
+	pid_t for process IDs and intptr_t for the 1st arg of
+	_open_osfhandle.
+	* function.c (windows32_openpipe): Use pid_t for process IDs and
+	intptr_t for the 1st arg of _open_osfhandle.
+	(func_shell): Use pid_t for process IDs.
+	* main.c (main) [WINDOWS32]: Pacify the compiler.
+	* config.h.W32.template (pid_t): Add a definition for 64-bit
+	Windows builds that don't use GCC.  Fixes Savannah bug #27809.
+	Patch by Ozkan Sezer <sezeroz@gmail.com>
+
+2010-07-07  Paul Smith  <psmith@gnu.org>
+
+	* configure.in: Bump to a new prerelease version 3.81.91.
+
+2010-07-06  Paul Smith  <psmith@gnu.org>
+
+	* main.c (main): Set a default value of "-c" for .SHELLFLAGS.
+	* NEWS: Mention the new behavior of .POSIX and the new .SHELLFLAGS
+	variable.
+	* job.c (construct_command_argv): Retrieve the .SHELLFLAGS value
+	and pass it to construct_command_argv_internal().
+	(construct_command_argv_internal): If .SHELLFLAGS is non-standard
+	use the slow path.  Use that value instead of hard-coded "-c".
+
+2010-07-05  Paul Smith  <psmith@gnu.org>
+
+	* implicit.c (pattern_search): lastslash can be const.
+	* dir.c (downcase): Remove unused variable.
+	* hash.c (hash_init): Cast sizeof for error message.
+	* arscan.c (ar_scan): Cast to char* for WINDOWS32.
+	(ar_member_touch): Ditto.
+	* ar.c (glob_pattern_p): Avoid symbol collision: open -> opened
+	* signame.c (strsignal): Ditto: signal -> sig
+	* job.c (create_batch_file): Ditto: error -> error_string
+	(pid2str): Portably convert a pid_t into a string
+	(reap_children): Use it.
+	(start_waiting_job): Use it.
+	Savannah bug #27809.  Patch by Ozkan Sezer <sezeroz@gmail.com>
+
+2010-07-03  Paul Smith  <psmith@gnu.org>
+
+	* read.c (parse_file_seq): All archive groups must end with ')' as
+	the LAST character in a word.  If there is no word ending in ')'
+	then it's not an archive group.  Fixes Savannah bug #28525.
+
+2010-07-01  Paul Smith  <psmith@gnu.org>
+
+	* main.c (main): Append optional features using separate calls.
+	Not as efficient but not all compilers allow conditionals inside
+	macro calls.  Fixes Savannah bug #29244.
+
+2010-01-10  Paul Smith  <psmith@gnu.org>
+
+	* make.h (patheq): Rename strieq() to patheq() for clarity.
+	* dir.c (dir_contents_file_exists_p): Use it.
+
+	* dir.c (file_impossible): Convert xmalloc/memset to xcalloc.
+	* file.c (enter_file): Ditto.
+	* job.c (new_job): Ditto.
+
+2009-12-11  Eli Zaretskii  <eliz@gnu.org>
+
+	* job.c (construct_command_argv_internal) <sh_cmds_dos>
+	[WINDOWS32]: Add "echo." and a few more commands that are built
+	into cmd.exe.  Fixes Savannah bug #28126.
+
+	* file.c (lookup_file) [HAVE_DOS_PATHS]: Treat '\\' like we do
+	with '/'.
+
+2009-11-15  Paul Smith  <psmith@gnu.org>
+
+	Patches for VMS provided by Hartmut Becker <Hartmut.Becker@hp.com>
+
+	* vmsjobs.c (ctrlYPressed) [VMS]: Deal with CTRL-Y.
+	(vmsHandleChildTerm) [VMS]: Ditto.
+	(astYHandler) [VMS]: Ditto.
+	(tryToSetupYAst) [VMS]: Ditto.
+	(child_execute_job) [VMS]: Ditto.
+
+	* vmsify.c (trnlog) [VMS]: Fix const errors.
+	(vmsify) [VMS]: Ditto.
+
+	* readme.vms [VMS]: Update with notes for 3.82.
+
+	* job.h (comname) [VMS]: Remember the temporary command filename
+
+	* dir.c (vmsify) [VMS]: Fix const errors.
+	(vms_hash) [VMS]: Ditto.
+	(vmsstat_dir) [VMS]: Ditto.
+	(find_directory) [VMS]: Fix case-insensitive option for VMS
+	(dir_contents_file_exists_p) [VMS]: Ditto.
+	(file_impossible) [VMS]: Ditto.
+
+	* config.h-vms.template (HAVE_FDOPEN) [VMS]: Have it.
+	(HAVE_STRCASECMP) [VMS]: Ditto.
+
+	* arscan.c (VMS_get_member_info) [VMS]: Fix timezone computation.
+	(ar_scan) [VMS]: Fix const error.
+
+2009-11-12  Boris Kolpackov  <boris@codesynthesis.com>
+
+	* vpath.c (vpath_search, selective_vpath_search): Add index arguments
+	which allows the caller to get the index of the matching directory.
+
+	* make.h (vpath_search): Update prototype.
+
+	* remake.c (library_search): Implement linker-compatible library
+	search. Use the new VPATH_SEARCH index functionality to keep track
+	of the directory index for each match. Select the match with the
+	lowest directory index.
+
+	* implicit.c (pattern_search): Pass NULL for the index arguments in
+	the VPATH_SEARCH call.
+
+	* doc/make.texi (Directory Search for Link Libraries): Describe the
+	new search behavior.
+
+	* NEWS: Add a note about the new behavior.
+
+2009-10-25  Paul Smith  <psmith@gnu.org>
+
+	* AUTHORS, et.al.: Update copyright years.
+
+	* implicit.c (stemlen_compare): Fix qsort() compare bug that
+	caused implicit rules with equal stem lengths to be sorted
+	indeterminately.
+
+2009-10-24  Paul Smith  <psmith@gnu.org>
+
+	* main.c (usage): Add --eval to the usage string.
+	(switches): Add the --eval switch.
+	(main): If --eval is given, add them to the simply-expanded variable
+	-*-eval-flags-*- (necessary to allow recursion to work properly).
+	(define_makeflags): Add -*-eval-flags-*- to MAKEFLAGS.
+
+	* NEWS: Describe the new --eval command line argument.
+	* doc/make.texi (Options Summary): Document --eval.
+
+	* dep.h: eval_buffer() returns void.
+	* read.c (eval_buffer): Ditto.
+	(eval): Ditto.
+
+	* variable.h (define_variable_cname): New macro for constant
+	variable names.
+	* default.c (set_default_suffixes): Use it.
+	* main.c (main): Ditto.
+	(handle_non_switch_argument): Ditto.
+	(define_makeflags): Ditto.
+	* read.c (read_all_makefiles): Ditto.
+	* variable.c (define_automatic_variables): Ditto.
+
+	* commands.c (dep_hash_cmp): Avoid casts.
+	(dep_hash_1): Ditto.
+	(dep_hash_2): Ditto.
+
+2009-10-22  Boris Kolpackov  <boris@codesynthesis.com>
+
+	* read.c (read_all_makefiles): Mark the default makefile dependency
+	dontcare.
+
+2009-10-07  Boris Kolpackov  <boris@codesynthesis.com>
+
+	* read.c (do_undefine): Free the expanded variable name.
+
+	* commands.c (dep_hash_cmp, set_file_variables): Move the order-only
+	to normal upgrade logic from  dep_hash_cmp to set_file_variables.
+
+2009-10-06  Boris Kolpackov  <boris@codesynthesis.com>
+
+	* dep.h (uniquize_deps): Remove.
+
+	* read.c (uniquize_deps): Merge into set_file_variables in
+	commands.c.
+	(dep_hash_1, dep_hash_2, dep_hash_cmp): Move to commands.c.
+
+	* commands.c (set_file_variables): Avoid modifying the dep
+	chain to achieve uniqueness. Fixes savannah bug 25780.
+
+	* implicit.c (pattern_search): Instead of re-setting all automatic
+	variables for each rule we try, just update $*.
+
+2009-10-06  Boris Kolpackov  <boris@codesynthesis.com>
+
+	* variable.h (undefine_variable_in_set): New function declaration.
+	(undefine_variable_global): New macro.
+
+	* variable.c (undefine_variable_in_set): New function implementation.
+
+	* read.c (vmodifiers): Add undefine_v modifier.
+	(parse_var_assignment): Parse undefine.
+	(do_undefine): Handle the undefine directive.
+	(eval): Call do_undefine if undefine_v is set.
+
+	* main.c (.FEATURES): Add a keyword to indicate the new feature.
+
+	* doc/make.texi (Undefine Directive): Describe the new directive.
+
+	* NEWS: Add a note about the new directive.
+
+2009-10-05  Boris Kolpackov  <boris@codesynthesis.com>
+
+	* implicit.c (pattern_search): Initialize file variables only
+	if we need to parse a rule that requires the second expansion.
+
+2009-10-03  Paul Smith  <psmith@gnu.org>
+
+	* make.h: Include <alloca.h> even on systems where __GNUC__ is
+	defined.  Not sure why it was done the other way.
+	Requested by David Boyce <dsb@boyski.com>.
+
+2009-09-30  Boris Kolpackov  <boris@codesynthesis.com>
+
+	* dep.h (dep): Add the DONTCARE bitfield.
+
+	* filedef.h (file):Add the NO_DIAG bitfield.
+
+        * read.c (eval_makefile): Set the DONTCARE flag in struct dep,
+	not struct file (a file can be a dependency of many targets,
+	some don't care, some do).
+
+	* remake.c (update_goal_chain): Propagate DONTCARE from struct
+	dep to struct file before updating the goal and restore it
+	afterwards.
+	(update_file): Don't prune the dependency graph if this target
+	has failed but the diagnostics hasn't been issued.
+	(complain): Scan the file's dependency graph to find the file
+	that caused the failure.
+	(update_file_1): Use NO_DIAG instead of DONTCARE to decide
+	whether to print diagnostics.
+
+	Fixes Savannah bugs #15110, #25493, #12686, and #17740.
+
+2009-09-28  Paul Smith  <psmith@gnu.org>
+
+	* doc/make.texi (Pattern Intro): Move the match algorithm
+	discussion into the "Pattern Match" node.
+	(Pattern Match): Expand on the pattern rule matching algorithm.
+
+2009-09-28  Andreas Buening  <andreas.buening@nexgo.de>
+
+	* job.c (construct_command_argv_internal) [OS2]: Don't eat too
+	much of the command line on a single pass.
+
+2009-09-28  Boris Kolpackov  <boris@codesynthesis.com>
+
+	* varible.c (create_pattern_var): Insert variables into the
+	PATTERN_VARS list in the shortest patterns first order.
+
+	* implicit.c (tryrule): Add STEMLEN and ORDER members. These are
+	used to sort the rules.
+	(stemlen_compare): Compare two tryrule elements.
+	(pattern_search): Sort the rules so that they are in the shortest
+	stem first order.
+
+	* main.c (.FEATURES): Add a keyword to indicate the new behavior.
+
+	* doc/make.texi (Pattern-specific Variable Values): Describe the
+	new pattern-specific variables application order.
+	(Introduction to Pattern Rules): Describe the new pattern rules
+	search order.
+
+	* NEWS: Add a note about the new behavior.
+
+2009-09-27  Paul Smith  <psmith@gnu.org>
+
+	* doc/make.texi (Double-Colon): Mention that pattern rules with
+	double-colons have a different meaning.  Savannah bug #27497.
+
+2009-09-27  Juan Manuel Guerrero  <juan.guerrero@gmx.de>
+
+	* configh.dos.template: Remove unconditional definition of
+	SYS_SIGLIST_DECLARED.
+	Include <sys/version.h> because ports of GCC 4.3.0 and later no
+	longer include it, so macros like __DJGPP_MINOR__ are no longer
+	defined automatically.
+
+	* Makefile.DOS.template (INCLUDES): Use $(prefix) and the
+	corresponding variables to define LIBDIR, INCLUDEDIR and LOCALEDIR
+	instead of using the hardcoded ones.
+	(SUBDIRS): doc subdir added.
+	(INFO_DEPS, DVIS): Values changed to 'make.info' and 'make.dvi'.
+	(TEXI2HTML, TEXI2HTML_FLAGS): Removed.  Use makeinfo --html to
+	create html formated docs.  texi2html may not be ported to DOS.
+	(make.info, make.dvi, make.ps, make.html): Make targets depend on
+	'make.texi'.
+	(.texi.info, .texi, .texi.dvi): Now invoked recursively.  Change
+	-I switch to look in ./ instead of ./doc.
+	(html): Target depend on html-recursive instead of make_1.html.
+	(make_1.html): Removed.
+	(mostlyclean-aminfo): Use $(srcdir)/doc instead of ./ as prefix.
+	(all-recursive): Allow for more than one subdir in the build
+	process.
+	(mostlyclean-recursive, clean-recursive, distclean-recursive)
+	(maintainer-clean-recursive, check-recursive): Enter in doc/ too.
+	(tags-recursive): Allow for more than one subdir in the build
+	process.
+	(info-recursive, dvi-recursive, ps-recursive, html-recursive): New
+	targets.  Enter into doc/ to produce the targets.
+	(all-am): $(INFO_DEPS) replaced by info.
+
+2009-09-26  Paul Smith  <psmith@gnu.org>
+
+	* read.c (record_files): Use free_ns() to free struct nameseq.
+	(eval): Ditto.
+
+	* rule.c (freerule): Use free_dep_chain().
+
+	* read.c (record_files): Free FILENAMES chain for implicit rules.
+	(eval): Static pattern targets go into the string cache.
+
+	* function.c (string_glob): Free NAME in the nameseq chain.
+
+2009-09-25  Boris Kolpackov  <boris@codesynthesis.com>
+
+	* implicit.c (pattern_search): Terminate early if we haven't
+	found any rules to try (performance improvement).
+
+2009-09-25  Boris Kolpackov  <boris@codesynthesis.com>
+
+	* implicit.c (pattern_search): Merge three parallel arrays,
+	TRYRULES, MATCHES, and CHECKED_LASTSLASH, into one array
+	of struct TRYRULE. In the old version the latter two arrays
+	had insufficient length.
+
+2009-09-24  Paul Smith  <psmith@gnu.org>
+
+	* implicit.c (pattern_search): Add back support for order-only
+	prerequisites for secondary expansion implicit rules, that were
+	accidentally dropped.  If we find a "|", enable order-only mode
+	and set IGNORE_MTIME on all deps that are seen afterward.
+	(pattern_search): Fix memory leaks: for intermediate files where
+	we've already set the file variable and pattern variable sets, be
+	sure to either save or free them as appropriate.
+
+2009-09-23  Paul Smith  <psmith@gnu.org>
+
+	Rework the way secondary expansion is stored, for efficiency.
+	This changes secondary expansion so that ONLY WHEN we know we have
+	a possibility of needing secondary expansion, do we defer the
+	secondary expansion.  This means more parsing the deps but we use
+	a lot less memory (due to the strcache).  Also, this fixes
+	Savannah bug #18622.
+
+	* read.c (eval): Don't parse the dep string here anymore.
+	(record_files): Take the dep argument as an unparsed string.  If
+	secondary expansion is enabled AND the prereq string has a '$' in
+	it, then set NEED_2ND_EXPANSION and keep the entire string.
+	Otherwise, parse the dep string here to construct the dep list
+	with the names in the strcache.
+
+	* misc.c (copy_dep_chain): For NEED_2ND_EXPANSION, we need to
+	duplicate the name string (others are in the strcache).
+
+	* implicit.c: Remove struct idep and free_idep_chain(): unused.
+	(struct patdeps): New structure to store prereq information.
+	(pattern_search): Use the NEED_2ND_EXPANSION flag to determine
+	which prerequisites need expansion, and expand only those.
+
+	* file.c (split_prereqs): Break parse_prereqs() into two parts: this
+	and enter_prereqs().  split_prereqs() takes a fully-expanded string
+	and splits it into a DEP list, handling order-only prereqs.
+	(enter_prereqs): This function enters a list of DEPs into the file
+	database.  If there's a stem defined, expand any pattern chars.
+	(expand_deps): Only try to expand DEPs which have NEED_2ND_EXPANSION
+	set.  Use the above functions.
+	(snap_deps): Only perform second expansion on prereqs that need it,
+	as defined by the NEED_2ND_EXPANSION flag.
+	(print_prereqs): New function to print the prereqs
+	(print_file): Call print_prereqs() rather than print inline.
+
+	* hash.h (STRING_COMPARE): Take advantage of strcache() by
+	comparing pointers.
+	(STRING_N_COMPARE): Ditto.
+	(ISTRING_COMPARE): Ditto.
+
+	* dep.h (PARSE_FILE_SEQ): New macro to reduce casts.
+	(parse_file_seq): Return void*
+	* read.c (parse_file_seq): Return void*.
+	(eval): Invoke macroized version of parse_file_seq()
+	* default.c (set_default_suffixes): Ditto.
+	* file.c (split_prereqs): Ditto.
+	* function.c (string_glob): Ditto.
+	* main.c (main): Ditto.
+	* rule.c (install_pattern_rule): Ditto.
+
+	* filedef.h: Add split_prereqs(), enter_prereqs(), etc.
+
+2009-09-16  Paul Smith  <psmith@gnu.org>
+
+	* misc.c (alloc_dep, free_dep): Now that we have xcalloc(),
+	convert to macros.
+	* dep.h: Create alloc_dep() / free_dep() macros.
+
+	* implicit.c (pattern_search): Take advantage of the new
+	parse_file_seq() to add the directory prefix to each prereq.
+
+	* dep.h: Remove multi_glob() and enhance parse_file_seq() to do it
+	all.  Avoid reversing chains.  Support adding prefixes.
+	* read.c (parse_file_seq): Rewrite to support globbing.  Allow for
+	cached/non-cached results.
+	(eval): Remove multi_glob() & invoke new parse_file_seq().
+	* rule.c (install_pattern_rule): Ditto.
+	* main.c (main): Ditto.
+	* implicit.c (pattern_search): Ditto.
+	* function.c (string_glob): Ditto.
+	* file.c (parse_prereqs): Ditto.
+	* default.c (set_default_suffixes): Ditto.
+
+	* variable.c (parse_variable_definition): Don't run off the end of
+	the string if it ends in whitespace (found with valgrind).
+
+	* commands.c (set_file_variables): Keep space for all targets in
+	$? if -B is given (found with valgrind).
+
+2009-09-15  Paul Smith  <psmith@gnu.org>
+
+	* misc.c (concat): Make concat() variadic so it takes >3 arguments.
+	(xcalloc): Add new function.
+	* make.h: New declarations.
+
+	* ar.c (ar_glob_match): New calling method for concat().
+	* main.c (main): Ditto.
+	(decode_env_switches): Ditto.
+	* read.c (eval_makefile): Ditto.
+	(tilde_expand): Ditto.
+	(parse_file_seq): Ditto.
+	* variable.c (target_environment): Ditto.
+	(sync_Path_environment): Ditto.
+
+	* ar.c (ar_glob_match): Use xcalloc().
+	* dir.c (file_impossible): Ditto.
+	* file.c (enter_file): Ditto.
+	* job.c (new_job): Ditto.
+	* read.c (parse_file_seq): Ditto.
+	* vmsfunctions.c (opendir): Ditto.
+
+2009-09-14  Rafi Einstein  <rafi.einstein@gmail.com>  (tiny patch)
+
+	* w32/subproc/sub_proc.c (process_begin): Check *ep non-NULL
+	inside the loop that looks up environment for PATH.
+
+2009-08-31  Eli Zaretskii  <eliz@gnu.org>
+
+	* function.c (windows32_openpipe): Update envp after calling
+	sync_Path_environment.
+
+2009-08-02  Paul Smith  <psmith@gnu.org>
+
+	* remake.c (notice_finished_file): Ensure file->cmds is not null
+	before looping through them.  Fixes Savannah bug #21824.
+
+	* doc/make.texi (Wildcard Examples): Clarify when objects is
+	wildcard-expanded.  Fixes Savannah bug #24509.  Patch by Martin Dorey.
+	(Include): Clarify the behavior of -include.
+	Fixes Savannah bug #18963.
+
+2009-08-01  Paul Smith  <psmith@gnu.org>
+
+	* doc/make.texi (Catalogue of Rules): Clarify where -c, -F,
+	etc. come on the command line.  Fixes Savannah bug #27093.
+
+	* expand.c (expand_argument): If the argument is large enough use
+	xmalloc() instead of alloca().  Fixes Savannah bug #27143.
+
+	* variable.c (do_variable_definition): Avoid using alloca() to
+	hold values, which can be large.  Fixes Savannah bug #23960.
+
+	* job.c (new_job): Use memmove() instead of strcpy() since both
+	pointers are in the same memory block.  Fixes Savannah bug #27148.
+	Patch by Petr Machata.
+
+2009-07-29  Ralf Wildenhues  <Ralf.Wildenhues@gmx.de>
+
+        * job.c (construct_command_argv_internal): Add "ulimit" and
+        "unset" to the sh_cmds for Unixy shells.
+
+2009-07-29  Ralf Wildenhues  <Ralf.Wildenhues@gmx.de>
+
+        * configure.in: Move side-effects outside AC_CACHE_VAL arguments
+        that set make_cv_sys_gnu_glob, so they are also correctly set
+        when the cache has been populated before.
+
+2009-07-04  Eli Zaretskii  <eliz@gnu.org>
+
+	* function.c (func_realpath) [!HAVE_REALPATH]: Require the file to
+	exist, as realpath(3) does where it's supported.
+
+2006-07-04  Eli Zaretskii  <eliz@gnu.org>
+
+	* function.c (IS_ABSOLUTE, ROOT_LEN): New macros.
+	(abspath): Support systems that define HAVE_DOS_PATHS (have
+	drive letters in their file names).  Use IS_PATHSEP instead of a
+	literal '/' comparison.  Fixes Savannah bug #26886.
+
+2009-06-14  Paul Smith  <psmith@gnu.org>
+
+	* remake.c (update_file_1): Remember the original file we marked
+	as updating, so we can clear that flag again.  If we find a target
+	via vpath, FILE might change.
+	(check_dep): Ditto.  Fixes Savannah bug #13529.
+	Patch by Reid Madsen <reid.madsen@tek.com>.
+
+2009-06-13  Paul Smith  <psmith@gnu.org>
+
+	* doc/make.texi (MAKEFILES Variable): Be explicit that files
+	included by MAKEFILES cannot give default goals.
+	* read.c (eval): If set_default is not set, pass the no-default-goal
+	value when we read included makefiles.  Fixes Savannah bug #13401.
+
+	* ar.c (ar_name): Ensure that targets with empty parens aren't
+	considered archive member references: archive members must have a
+	non-empty "member" string.  Fixes Savannah bug #18435.
+
+	* function.c (string_glob): Rely on multi_glob() to determine
+	whether files exist or not.  Remove call to file_exists_p() which
+	is not always correct.  Fixes Savannah bug #21231.
+	* read.c (multi_glob): Add a new argument EXISTS_ONLY; if true
+	then only files that really exist will be returned.
+	* dep.h: Add new argument to multi_glob().
+	* rule.c (install_pattern_rule): Ditto.
+	* read.c (eval): Ditto.
+	* main.c (main): Ditto.
+	* implicit.c (pattern_search): Ditto.
+	* file.c (parse_prereqs): Ditto.
+	* default.c (set_default_suffixes): Ditto.
+
+2009-06-09  Paul Smith  <psmith@gnu.org>
+
+	* commands.c (set_file_variables): If always_make_flag is set,
+	always add the prereq to $?.  Fixes Savannah bug #17825.
+
+	* remake.c (update_file_1): When rebuilding deps of FILE, also try
+	to rebuild the deps of all the also_make targets for that file.
+	Fixes Savannah bug #19108.
+
+	* implicit.c (pattern_search): Undo test for is_target, added by
+	BorisK on 21 Sep 2004.  This goes against step 5c in the "Implicit
+	Rule Search Algorithm".  Fixes Savannah bug #17752.
+
+	* main.c (clean_jobserver): Clear the jobserver_fds options and
+	set job_slots to the default when we clean up.
+	(define_makeflags): Return the new MAKEFLAGS value.
+	(main): Reset MAKEFLAGS in the environment when we re-exec.
+	Fixes Savannah bug #18124.
+
+2009-06-08  Paul Smith  <psmith@gnu.org>
+
+	* read.c (eval): Collapse continuations post-semicolon on target-
+	specific variables.  Fixes Savannah bug #17521.
+
+2009-06-07  Paul Smith  <psmith@gnu.org>
+
+	* job.c (reap_children): For older systems without waitpid() (are
+	there any of these left?) run wait(2) inside EINTRLOOP to handle
+	EINTR errors.  Fixes Savannah bug #16401.
+
+	* (various): Debug message cleanup.  Fixes Savannah bug #16469.
+
+	* main.c: Fix bsd_signal() typedef.  Fixes Savannah bug #16473.
+
+	* file.c (snap_deps): Set SNAPPED_DEPS at the start of snapping,
+	not the end, to catch second expansion $(eval ...) defining new
+	target/prereq relationships during snap_deps.
+	Fixes Savannah bug #24622.
+
+	* read.c (record_files): The second-expansion "f->updating" hack
+	was not completely correct: if assumed that the target with
+	commands always had prerequisites; if one didn't then the ordering
+	was messed up.  Fixed for now to use f->updating to decide whether
+	to preserve the last element in the deps list... but this whole
+	area of constructing and reversing the deps list is too confusing
+	and needs to be reworked.  Fixes Savannah bug #21198.
+
+2009-06-06  Paul Smith  <psmith@gnu.org>
+
+	* hash.c (hash_insert): Remove useless test for NULL.
+	Fixes Savannah bug #21823.
+
+	* make.h: Move SET_STACK_SIZE determination to make.h.
+	* main.c (main): New global variable, STACK_LIMIT, holds the
+	original stack limit when make was started.
+	* job.c (start_job_command): Reset the stack limit, if we changed it.
+	Fixes Savannah bug #22010.
+
+	* remake.c (check_dep): Only set the target's state to not-started
+	if it's not already running.  Found this while testing -j10 builds
+	of glibc: various targets were being rebuilt multiple times.
+	Fix from Knut St. Osmundsen; fixes a problem reported in Savannah
+	bug #15919.
+
+	* read.c (multi_glob): Don't pass GLOB_NOCHECK to glob(3); instead
+	handle the GLOB_NOMATCH error.  This is to work around Sourceware.org
+	Bugzilla bug 10246.
+
+2009-06-04  Paul Smith  <psmith@gnu.org>
+
+	* read.c (eval): Skip initial whitespace (ffeed, vtab, etc.)
+
+	* maintMakefile: Modify access of config and gnulib Savannah
+	modules to use GIT instead of CVS.
+
+	* main.c (main): Initialize the LENGTH field in SHELL_VAR.
+	Fixes Savannah bug #24655.
+
+	* read.c (eval_buffer): Don't dereference reading_file if it's NULL;
+	this can happen during some invocations of $(eval ...) for example.
+	Fixes Savannah bug #24588.  Patch by Lars Jessen <ljessen@ljessen.dk>
+
+2009-06-02  Paul Smith  <psmith@gnu.org>
+
+	* configure.in: Check for fileno()
+	* read.c (eval_makefile): If fileno() is available, set CLOSE_ON_EXEC
+	for the makefile file so invocations of $(shell ...) don't inherit it.
+	Fixes Savannah bug #24277.
+
+2009-06-01  Paul Smith  <psmith@gnu.org>
+
+	* main.c (main): The previous fix for .DEFAULT_GOAL had issues;
+	expansion was handled incorrectly.  Rework the default goal
+	handling to save the variable only.  Remove default_goal_file and
+	default_goal_name.
+	* read.c (eval): Check default_goal_var, not default_goal_name.
+	* read.c (record_target_var): Don't check default_goal_file here.
+
+2009-05-31  Paul Smith  <psmith@gnu.org>
+
+	* main.c (main): Expand the .DEFAULT_GOAL variable before using
+	it, and if the multi_glob() returns nothing (say it expanded to
+	nothing but spaces) then don't crash.  Fixes Savannah bug #25697.
+
+	* doc/make.texi (Quick Reference): Add $(if ..), $(or ..), and
+	$(and ..) to the reference.  Fixes Savannah bug #25694.
+
+	* make.1: Be clear that some recipes will be executed even with -n.
+	* doc/make.texi: Ditto.  Fixes Savannah bug #25460.
+
+	* doc/make.texi (Override Directive): Make more clear how
+	overrides and appends interact.
+	Elucidates part of Savannah bug #26207.
+
+	* read.c (record_target_var): Don't reset the origin on
+	target-specific variables; try_variable_definition() will handle
+	this correctly.  Fixes Savannah bug #26207.
+
+	* maintMakefile (do-po-update): Copy PO files into $(top_srcdir).
+	Fixes Savannah bug #25712.
+
+	* implicit.c (pattern_search): Keep a pointer to the beginning of
+	the filename and save that instead of the constructed pointer.
+	Fixes Savannah bug #26593.
+	Patch by Mark Seaborn <mrs@mythic-beasts.com>
+
+2009-05-30  Paul Smith  <psmith@gnu.org>
+
+	* doc/make.texi (Multi-Line): Add a description of the new abilities
+	of define/endef.  Rename "Sequences" to "Multi-Line" and fix some
+	"command sequence" vs. "recipe" syntax.
+	* read.c (do_define): Modify to allow assignment tokens (=, :=, etc.)
+	after a define, to create variables with those flavors.
+
+2009-05-25  Paul Smith  <psmith@gnu.org>
+
+	Reworked the parser for variable assignments to allow multiple
+	modifiers, and in any order.  Also allows variable and
+	prerequisites to be modifier names ('export', 'private', etc.)
+
+	* NEWS: Add notes about user-visible changes.
+
+	* read.c (struct vmodifiers): Remember what modifiers were seen.
+	(parse_var_assignment): New function to parse variable assignments.
+	(eval): Call the new function.  Handle variable assignments earlier.
+
+	* variable.c (parse_variable_definition): Only parse; don't create var.
+	(assign_variable_definition): Call parse, then create the var.
+
+2009-05-24  Paul Smith  <psmith@gnu.org>
+
+	* doc/make.texi: Fix the ISBN for the GNU make manual.  Incorrect
+	value noticed by Hans Stol <hans.stol@nc3a.nato.int>.
+
+2009-03-14  Eli Zaretskii  <eliz@gnu.org>
+
+	* w32/pathstuff.c (convert_Path_to_windows32): Fix last change.
+	Fixes Savannah bug #25412.
+
+	* w32/subproc/sub_proc.c <top level>: Update Copyright years.  Add
+	prototype for xmalloc.
+	(find_file): Accept 3 arguments PATH_VAR, FULL_FNAME, and FULL_LEN
+	instead of an LPOFSTRUCT pointer.  Use xmalloc instead of malloc.
+	Loop over an array of extensions, instead of duplicating the same
+	code inline.  Use SearchPath followed by CreateFile, instead of
+	the obsolete OpenFile.  Fixes Savannah bug #17277.
+	(process_begin): Find $(PATH) in `envp', and pass a pointer to it
+	to `find_file'.  Fixes Savannah bug #25662.
+
+2009-03-07  Eli Zaretskii  <eliz@gnu.org>
+
+	* function.c (func_shell): Don't close pipedes[1] if it is -1.
+	Fixes Savannah bug #20495.
+
+2009-02-28  Ralf Wildenhues  <address@hidden>
+
+        * doc/make.texi (Instead of Execution): Document interaction of
+        -t with phony targets.
+
+2009-02-23  Ramon Garcia  <ramon.garcia.f@gmail.com>
+
+	Introduce a new keyword "private" which applies to target-specific
+	variables and prevents their values from being inherited.
+
+	* variable.h (struct variable): Add private_var flag to each variable.
+	Add a flag to specify which list entry switches to the parent target.
+	* variable.c (define_variable_in_set): Initialize private_var flag.
+	(lookup_variable): Skip private variables in parent contexts.
+	(initialize_file_variables): Set next_is_parent appropriately.
+	(print_variable): Show the private_var flag.
+	* read.c (eval): Recognize the private keyword.
+	(record_target_var): Set private_var.
+	* doc/make.texi (Suppressing Inheritance): Add documentation.
+
+2008-10-26  Paul Smith  <psmith@gnu.org>
+
+	* configure.in: Check for strndup().
+	* misc.c (xstrndup): Rename savestring to xstrndup.  Use strndup
+	if it's available.
+	* make.h: Rename savestring to xstrndup.
+	* commands.c (chop_commands): Ditto.
+	* function.c (func_foreach): Ditto.
+	* read.c (eval, record_files): Ditto.
+	* variable.c (define_variable_in_set): Ditto.
+
 2008-09-30  Eli Zaretskii  <eliz@gnu.org>
 
@@ -816,5 +1655,5 @@
 
 	* make.1: Fix some display errors and document all existing options.
-	Patch provided by Mike Frysinger <vapier@gentoo.org>.
+	Patch by Mike Frysinger <vapier@gentoo.org>.
 
 2005-12-11  Paul D. Smith  <psmith@gnu.org>
@@ -3164,6 +4003,6 @@
 
 
-Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software
-Foundation, Inc.
+Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free
+Software Foundation, Inc.
 This file is part of GNU Make.
 
Index: /trunk/src/kmk/ChangeLog.1
===================================================================
--- /trunk/src/kmk/ChangeLog.1	(revision 2590)
+++ /trunk/src/kmk/ChangeLog.1	(revision 2591)
@@ -4984,6 +4984,6 @@
 
 Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
-1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2007 Free Software Foundation,
-Inc.
+1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009 Free
+Software Foundation, Inc.
 This file is part of GNU Make.
 
Index: /trunk/src/kmk/Makefile.DOS.template
===================================================================
--- /trunk/src/kmk/Makefile.DOS.template	(revision 2590)
+++ /trunk/src/kmk/Makefile.DOS.template	(revision 2591)
@@ -3,5 +3,5 @@
 #
 # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
-# 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+# 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 # This file is part of GNU Make.
 #
@@ -86,5 +86,5 @@
 man_MANS =	make.1
 
-INCLUDES =	-I$(srcdir)/glob -DLIBDIR=\"c:/djgpp/lib\" -DINCLUDEDIR=\"c:/djgpp/include\" -DLOCALEDIR=\"$(localedir)\"
+INCLUDES =	-I$(srcdir)/glob -DLIBDIR=\"$(prefix)$(libdir)\" -DINCLUDEDIR=\"$(prefix)$(includedir)\" -DLOCALEDIR=\"$(prefix)$(localedir)\"
 
 BUILT_SOURCES =	README build.sh-in
@@ -92,5 +92,5 @@
 EXTRA_DIST = 	$(BUILT_SOURCES) $(man_MANS) README.customs remote-cstms.c  make-stds.texi texinfo.tex SCOPTIONS SMakefile  Makefile.ami README.Amiga config.ami amiga.c amiga.h  NMakefile README.DOS configh.dos configure.bat makefile.com  README.W32 build_w32.bat config.h-W32 subproc.bat make.lnk  config.h-vms makefile.vms readme.vms vmsdir.h vmsfunctions.c  vmsify.c
 
-SUBDIRS =	glob
+SUBDIRS =	glob doc
 mkinstalldirs = ${exec_prefix}/bin/gmkdir -p
 CONFIG_HEADER = config.h
@@ -116,13 +116,10 @@
 TEXI2DVI = texi2dvi
 TEXINFO_TEX = $(srcdir)/config/texinfo.tex
-INFO_DEPS = make.info
-DVIS = make.dvi
+INFO_DEPS = doc/make.info
+DVIS = doc/make.dvi
 TEXINFOS = doc/make.texi
 noinst_TEXINFOS = doc/fdl.texi doc/make-stds.texi
 man1dir = $(mandir)/man1
 MANS = $(man_MANS)
-
-TEXI2HTML = texi2html
-TEXI2HTML_FLAGS = -split_chapter
 
 NROFF = nroff
@@ -192,6 +189,8 @@
 # Documentation
 
-make.info: doc/make.texi
-make.dvi: doc/make.texi
+make.info: make.texi
+make.dvi: make.texi
+make.ps: make.dvi make.texi
+make.html: make.texi
 
 
@@ -201,13 +200,13 @@
 	@command.com /c if exist make.info* del make.info*
 	@command.com /c if exist make.i* del make.i*
-	$(MAKEINFO) -I$(srcdir)/doc --no-split $< -o ./$@
+	$(MAKEINFO) -I$(srcdir) --no-split $< -o ./$@
 
 .texi:
 	@command.com /c if exist make.info* del make.info*
 	@command.com /c if exist make.i* del make.i*
-	$(MAKEINFO) -I$(srcdir)/doc --no-split $< -o ./$@
+	$(MAKEINFO) -I$(srcdir) --no-split $< -o ./$@
 
 .texi.dvi:
-	TEXINPUTS="$(srcdir)/doc;$$TEXINPUTS"    MAKEINFO='$(MAKEINFO) -I $(srcdir)/doc' $(TEXI2DVI) $<
+	TEXINPUTS="$(srcdir);$$TEXINPUTS"    MAKEINFO='$(MAKEINFO) -I $(srcdir)' $(TEXI2DVI) $<
 
 .dvi.ps:
@@ -216,15 +215,16 @@
 # Other documentation formats
 
-html: make_1.html
-
-make_1.html: $(TEXINFOS) $(noinst_TEXINFOS)
-	$(TEXI2HTML) $(TEXI2HTML_FLAGS) $(srcdir)/doc/make.texi
+html: html-recursive
+
+.texi.html:
+	@command.com /c if exist make.html* del make.html*
+	$(MAKEINFO) --html -I$(srcdir) --no-split $< -o ./$@
 
 install-info-am: $(INFO_DEPS)
 	@$(NORMAL_INSTALL)
 	$(mkinstalldirs) $(DESTDIR)$(infodir)
-	@for file in $(INFO_DEPS); do    d=$(srcdir);    for ifile in `cd $$d && echo $$file`; do      if test -f $$d/$$ifile; then        echo " $(INSTALL_DATA) $$d/$$ifile $(DESTDIR)$(infodir)/$$ifile"; $(INSTALL_DATA) $$d/$$ifile $(DESTDIR)$(infodir)/$$ifile; else : ; fi;    done;  done
+	@for file in $(INFO_DEPS); do    iifile=`echo $$file | sed "s|doc/||"`;    d=$(srcdir);    for ifile in `cd $$d && echo $$file`; do      if test -f $$d/$$ifile; then        echo " $(INSTALL_DATA) $$d/$$ifile $(DESTDIR)$(infodir)/$$iifile"; $(INSTALL_DATA) $$d/$$ifile $(DESTDIR)$(infodir)/$$iifile; else : ; fi;    done;  done
 	@$(POST_INSTALL)
-	@if $(SHELL) -c 'install-info --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then    for file in $(INFO_DEPS); do      echo " install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$file";     install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$file || :;   done;  else : ; fi
+	@if $(SHELL) -c 'install-info --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then    for file in $(INFO_DEPS); do    iifile=`echo $$file | sed "s|doc/||"`;      echo " install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$iifile";     install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$iifile || :;   done;  else : ; fi
 
 uninstall-info:
@@ -238,7 +238,10 @@
 
 mostlyclean-aminfo:
-	-rm -f make.aux make.cp make.cps make.dvi make.fn make.fns make.ky \
-	  make.kys make.ps make.log make.pg make.toc make.tp make.tps \
-	  make.vr make.vrs make.op make.tr make.cv make.cn
+	-rm -f $(srcdir)/doc/make.aux $(srcdir)/doc/make.cp $(srcdir)/doc/make.cps $(srcdir)/doc/make.dvi \
+	  $(srcdir)/doc/make.fn $(srcdir)/doc/make.fns $(srcdir)/doc/make.ky $(srcdir)/doc/make.kys \
+	  $(srcdir)/doc/make.ps $(srcdir)/doc/make.log $(srcdir)/doc/make.pg $(srcdir)/doc/make.toc \
+	  $(srcdir)/doc/make.tp $(srcdir)/doc/make.tps $(srcdir)/doc/make.vr $(srcdir)/doc/make.vrs \
+	  $(srcdir)/doc/make.op $(srcdir)/doc/make.tr $(srcdir)/doc/make.cv $(srcdir)/doc/make.cn \
+	  $(srcdir)/doc/make.html
 
 clean-aminfo:
@@ -292,11 +295,8 @@
 # a single directory, yell bloody murder.
 all-recursive:
-ifeq ($(words $(SUBDIRS)), 1)
+ifeq ($(findstring glob, $(SUBDIRS)), glob)
 	@command.com /c if not exist glob\\nul md glob
-	@echo Making all in $(SUBDIRS)
-	$(MAKE) -C $(SUBDIRS) -f ../Makefile INCLUDES='-I$(srcdir) -I$(srcdir)/glob' DEFS='-I.. -I$(srcdir)' VPATH=$(srcdir)/glob libglob.a
-else
-	@echo FATAL: There is more than one directory in "($(SUBDIRS))"
-	@$(EXIT_FAIL)
+	@echo Making all in glob
+	$(MAKE) -C glob -f ../Makefile INCLUDES='-I$(srcdir) -I$(srcdir)/glob' DEFS='-I.. -I$(srcdir)' VPATH=$(srcdir)/glob libglob.a
 endif
 
@@ -311,9 +311,11 @@
 mostlyclean-recursive clean-recursive distclean-recursive \
 maintainer-clean-recursive check-recursive:
-ifeq ($(words $(SUBDIRS)), 1)
-	@echo Making $(shell echo $@ | sed s/-recursive//) in $(SUBDIRS)
-	$(MAKE) -C $(SUBDIRS) -f ../Makefile $(shell echo $@ | sed s/-recursive//)-am
+ifeq ($(words $(SUBDIRS)), 2)
+	@echo Making $(shell echo $@ | sed s/-recursive//) in glob
+	$(MAKE) -C glob -f ../Makefile $(shell echo $@ | sed s/-recursive//)-am
+	@echo Making $(shell echo $@ | sed s/-recursive//) in doc
+	$(MAKE) -C doc -f ../Makefile $(shell echo $@ | sed s/-recursive//)-am
 else
-	@echo FATAL: There is more than one directory in "($(SUBDIRS))"
+	@echo FATAL: There is more than two directory in "($(SUBDIRS))"
 	@$(EXIT_FAIL)
 endif
@@ -323,8 +325,8 @@
 
 tags-recursive:
-ifeq ($(words $(SUBDIRS)), 1)
+ifeq ($(words $(SUBDIRS)), 2)
 	$(MAKE) tags-in-glob
 else
-	@echo FATAL: There is more than one directory in "($(SUBDIRS))"
+	@echo FATAL: There is more than two directory in "($(SUBDIRS))"
 	@$(EXIT_FAIL)
 endif
@@ -377,6 +379,35 @@
 	$(MAKE) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-hook
 
-info: $(INFO_DEPS) info-recursive
-dvi: $(DVIS) dvi-recursive
+info: info-recursive
+info-recursive:
+ifeq ($(findstring doc, $(SUBDIRS)), doc)
+	@command.com /c if not exist doc\\nul md doc
+	@echo Making all in doc
+	$(MAKE) -C doc -f ../Makefile VPATH=$(srcdir)/doc make.info
+endif
+
+dvi: dvi-recursive
+dvi-recursive:
+ifeq ($(findstring doc, $(SUBDIRS)), doc)
+	@command.com /c if not exist doc\\nul md doc
+	@echo Making all in doc
+	$(MAKE) -C doc -f ../Makefile VPATH=$(srcdir)/doc make.dvi
+endif
+
+ps: ps-recursive
+ps-recursive:
+ifeq ($(findstring doc, $(SUBDIRS)), doc)
+	@command.com /c if not exist doc\\nul md doc
+	@echo Making all in doc
+	$(MAKE) -C doc -f ../Makefile VPATH=$(srcdir)/doc make.ps
+endif
+
+html-recursive:
+ifeq ($(findstring doc, $(SUBDIRS)), doc)
+	@command.com /c if not exist doc\\nul md doc
+	@echo Making all in doc
+	$(MAKE) -C doc -f ../Makefile VPATH=$(srcdir)/doc make.html
+endif
+
 check: all-am check-recursive check-local
 	@:
@@ -385,5 +416,5 @@
 	$(MAKE) all-recursive
 
-all-am: Makefile $(INFO_DEPS) $(PROGRAMS) config.h
+all-am: Makefile $(PROGRAMS) config.h info
 
 install-exec-am: install-binPROGRAMS
Index: /trunk/src/kmk/Makefile.am
===================================================================
--- /trunk/src/kmk/Makefile.am	(revision 2590)
+++ /trunk/src/kmk/Makefile.am	(revision 2591)
@@ -2,5 +2,5 @@
 #
 # Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
-# 2007 Free Software Foundation, Inc.
+# 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 # This file is part of GNU Make.
 #
Index: /trunk/src/kmk/Makefile.ami
===================================================================
--- /trunk/src/kmk/Makefile.ami	(revision 2590)
+++ /trunk/src/kmk/Makefile.ami	(revision 2591)
@@ -5,5 +5,5 @@
 #
 # Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-# 2005, 2006, 2007 Free Software Foundation, Inc.
+# 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 # This file is part of GNU Make.
 #
Index: /trunk/src/kmk/NEWS
===================================================================
--- /trunk/src/kmk/NEWS	(revision 2590)
+++ /trunk/src/kmk/NEWS	(revision 2591)
@@ -1,5 +1,5 @@
 GNU make NEWS                                               -*-indented-text-*-
   History of user-visible changes.
-  1 April 2006
+  28 July 2010
 
 See the end of this file for copyrights and conditions.
@@ -11,15 +11,108 @@
 
 
-Version 3.81.90
+Version 3.82
+
+A complete list of bugs fixed in this version is available here:
+
+http://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=104&set=custom
 
 * Compiling GNU make now requires a conforming ISO C 1989 compiler and
   standard runtime library.
+
+* WARNING: Future backward-incompatibility!
+  Wildcards are not documented as returning sorted values, but up to and
+  including this release the results have been sorted and some makefiles are
+  apparently depending on that.  In the next release of GNU make, for
+  performance reasons, we may remove that sorting.  If your makefiles
+  require sorted results from wildcard expansions, use the $(sort ...)
+  function to request it explicitly.
+
+* WARNING: Backward-incompatibility!
+  The POSIX standard for make was changed in the 2008 version in a
+  fundamentally incompatible way: make is required to invoke the shell as if
+  the '-e' flag were provided.  Because this would break many makefiles that
+  have been written to conform to the original text of the standard, the
+  default behavior of GNU make remains to invoke the shell with simply '-c'.
+  However, any makefile specifying the .POSIX special target will follow the
+  new POSIX standard and pass '-e' to the shell.  See also .SHELLFLAGS
+  below.
+
+* WARNING: Backward-incompatibility!
+  The '$?' variable now contains all prerequisites that caused the target to
+  be considered out of date, even if they do not exist (previously only
+  existing targets were provided in $?).
+
+* WARNING: Backward-incompatibility!
+  As a result of parser enhancements, three backward-compatibility issues
+  exist: first, a prerequisite containing an "=" cannot be escaped with a
+  backslash any longer.  You must create a variable containing an "=" and
+  use that variable in the prerequisite.  Second, variable names can no
+  longer contain whitespace, unless you put the whitespace in a variable and
+  use the variable.  Third, in previous versions of make it was sometimes
+  not flagged as an error for explicit and pattern targets to appear in the
+  same rule.  Now this is always reported as an error.
+
+* WARNING: Backward-incompatibility!
+  The pattern-specific variables and pattern rules are now applied in the
+  shortest stem first order instead of the definition order (variables
+  and rules with the same stem length are still applied in the definition
+  order). This produces the usually-desired behavior where more specific
+  patterns are preferred. To detect this feature search for 'shortest-stem'
+  in the .FEATURES special variable.
+
+* WARNING: Backward-incompatibility!
+  The library search behavior has changed to be compatible with the standard
+  linker behavior. Prior to this version for prerequisites specified using
+  the -lfoo syntax make first searched for libfoo.so in the current
+  directory, vpath directories, and system directories. If that didn't yield
+  a match, make then searched for libfoo.a in these directories. Starting
+  with this version make searches first for libfoo.so and then for libfoo.a
+  in each of these directories in order.
+
+* New command line option: --eval=STRING causes STRING to be evaluated as
+  makefile syntax (akin to using the $(eval ...) function).  The evaluation
+  is performed after all default rules and variables are defined, but before
+  any makefiles are read.
 
 * New special variable: .RECIPEPREFIX allows you to reset the recipe
   introduction character from the default (TAB) to something else.  The
   first character of this variable value is the new recipe introduction
-  character.  If the variable is set to the empty string, TAB is used
-  again.  It can be set and reset at will; rules will be parsed
-  according to the current value.
+  character.  If the variable is set to the empty string, TAB is used again.
+  It can be set and reset at will; recipes will use the value active when
+  they were first parsed.  To detect this feature check the value of
+  $(.RECIPEPREFIX).
+
+* New special variable: .SHELLFLAGS allows you to change the options passed
+  to the shell when it invokes recipes.  By default the value will be "-c"
+  (or "-ec" if .POSIX is set).
+
+* New special target: .ONESHELL instructs make to invoke a single instance
+  of the shell and provide it with the entire recipe, regardless of how many
+  lines it contains.  As a special feature to allow more straightforward
+  conversion of makefiles to use .ONESHELL, any recipe line control
+  characters ('@', '+', or '-') will be removed from the second and
+  subsequent recipe lines.  This happens _only_ if the SHELL value is deemed
+  to be a standard POSIX-style shell.  If not, then no interior line control
+  characters are removed (as they may be part of the scripting language used
+  with the alternate SHELL).
+
+* New variable modifier 'private': prefixing a variable assignment with the
+  modifier 'private' suppresses inheritance of that variable by
+  prerequisites.  This is most useful for target- and pattern-specific
+  variables.
+
+* New make directive: 'undefine' allows you to undefine a variable so that
+  it appears as if it was never set. Both $(flavor) and $(origin) functions
+  will return 'undefined' for such a variable. To detect this feature search
+  for 'undefine' in the .FEATURES special variable.
+
+* The parser for variable assignments has been enhanced to allow multiple
+  modifiers ('export', 'override', 'private') on the same line as variables,
+  including define/endef variables, and in any order.  Also, it is possible
+  to create variables and targets named as these modifiers.
+
+* The 'define' make directive now allows a variable assignment operator
+  after the variable name, to allow for simple, conditional, or appending
+  multi-line variable assignment.
 
 
@@ -60,5 +153,4 @@
 
 * WARNING: Backward-incompatibility!
-
   In order to comply with POSIX, the way in which GNU make processes
   backslash-newline sequences in recipes has changed.  If your makefiles
@@ -1059,7 +1151,6 @@
 -------------------------------------------------------------------------------
 Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
-1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software
-Foundation, Inc.
-This file is part of GNU Make.
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+2010 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
Index: /trunk/src/kmk/NMakefile.template
===================================================================
--- /trunk/src/kmk/NMakefile.template	(revision 2590)
+++ /trunk/src/kmk/NMakefile.template	(revision 2591)
@@ -5,5 +5,5 @@
 #
 # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-# 2006, 2007 Free Software Foundation, Inc.
+# 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 # This file is part of GNU Make.
 #
@@ -34,8 +34,7 @@
 
 LDFLAGS_debug = w32\subproc\WinDebug\subproc.lib /NOLOGO /SUBSYSTEM:console\
-	/INCREMENTAL:no /PDB:WinDebug/make.pdb /MACHINE:I386 \
-	/OUT:WinDebug/make.exe /DEBUG
+	/INCREMENTAL:no /PDB:WinDebug/make.pdb /OUT:WinDebug/make.exe /DEBUG
 LDFLAGS_release = w32\subproc\WinRel\subproc.lib /NOLOGO /SUBSYSTEM:console\
-	/INCREMENTAL:no /MACHINE:I386 /OUT:WinRel/make.exe
+	/INCREMENTAL:no /OUT:WinRel/make.exe
 
 all: config.h subproc Release Debug
Index: /trunk/src/kmk/README.Amiga
===================================================================
--- /trunk/src/kmk/README.Amiga	(revision 2590)
+++ /trunk/src/kmk/README.Amiga	(revision 2591)
@@ -64,5 +64,5 @@
 -------------------------------------------------------------------------------
 Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-2005, 2006, 2007 Free Software Foundation, Inc.
+2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
Index: /trunk/src/kmk/README.DOS.template
===================================================================
--- /trunk/src/kmk/README.DOS.template	(revision 2590)
+++ /trunk/src/kmk/README.DOS.template	(revision 2591)
@@ -327,5 +327,5 @@
 -------------------------------------------------------------------------------
 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-2006, 2007 Free Software Foundation, Inc.
+2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
Index: /trunk/src/kmk/README.OS2.template
===================================================================
--- /trunk/src/kmk/README.OS2.template	(revision 2590)
+++ /trunk/src/kmk/README.OS2.template	(revision 2591)
@@ -162,5 +162,6 @@
 
 -------------------------------------------------------------------------------
-Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
+Foundation, Inc.
 This file is part of GNU Make.
 
Index: /trunk/src/kmk/README.W32.template
===================================================================
--- /trunk/src/kmk/README.W32.template	(revision 2590)
+++ /trunk/src/kmk/README.W32.template	(revision 2591)
@@ -275,5 +275,5 @@
 -------------------------------------------------------------------------------
 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-2006, 2007, 2008 Free Software Foundation, Inc.
+2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
Index: /trunk/src/kmk/README.customs
===================================================================
--- /trunk/src/kmk/README.customs	(revision 2590)
+++ /trunk/src/kmk/README.customs	(revision 2591)
@@ -98,6 +98,6 @@
 
 -------------------------------------------------------------------------------
-Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free
-Software Foundation, Inc.
+Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
+2009, 2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
Index: /trunk/src/kmk/README.cvs
===================================================================
--- /trunk/src/kmk/README.cvs	(revision 2590)
+++ /trunk/src/kmk/README.cvs	(revision 2591)
@@ -2,6 +2,6 @@
 
 -------------------------------------------------------------------------------
-Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
-This file is part of GNU Make.
+Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 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
@@ -211,4 +211,8 @@
 make check
 
+Or, for a debugging version:
+
+autoreconf -i && ./configure CFLAGS=-g && make update && make && make check
+
 Or, all-in-one:
 
Index: /trunk/src/kmk/README.template
===================================================================
--- /trunk/src/kmk/README.template	(revision 2590)
+++ /trunk/src/kmk/README.template	(revision 2591)
@@ -174,6 +174,6 @@
 -------------------------------------------------------------------------------
 Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
-1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software
-Foundation, Inc.
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
Index: /trunk/src/kmk/SMakefile.template
===================================================================
--- /trunk/src/kmk/SMakefile.template	(revision 2590)
+++ /trunk/src/kmk/SMakefile.template	(revision 2591)
@@ -5,5 +5,5 @@
 #
 # Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-# 2005, 2006, 2007 Free Software Foundation, Inc.
+# 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 # This file is part of GNU Make.
 #
Index: /trunk/src/kmk/TODO.private
===================================================================
--- /trunk/src/kmk/TODO.private	(revision 2590)
+++ /trunk/src/kmk/TODO.private	(revision 2591)
@@ -66,8 +66,5 @@
 
  3) Multi-token pattern rule matching (allow %1/%2.c : %1/obj/%2.o,
-    etc., or something like that).  I have an implementation of this
-    already, it just needs some refinement... maybe.  Additionally I
-    think it only works for static pattern rules; it might need to be
-    fixed up to work with normal pattern rules, too.
+    etc., or something like that).  Maybe using regex?
 
  4) Provide a .TARGETS variable, containing the names of the targets
@@ -130,6 +127,6 @@
 
 -------------------------------------------------------------------------------
-Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
-Free Software Foundation, Inc.
+Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
Index: /trunk/src/kmk/acinclude.m4
===================================================================
--- /trunk/src/kmk/acinclude.m4	(revision 2590)
+++ /trunk/src/kmk/acinclude.m4	(revision 2591)
@@ -2,6 +2,6 @@
 dnl
 dnl Automake will incorporate this into its generated aclocal.m4.
-dnl Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
-dnl Free Software Foundation, Inc.
+dnl Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
+dnl 2008, 2009, 2010 Free Software Foundation, Inc.
 dnl This file is part of GNU Make.
 dnl
Index: /trunk/src/kmk/amiga.c
===================================================================
--- /trunk/src/kmk/amiga.c	(revision 2590)
+++ /trunk/src/kmk/amiga.c	(revision 2591)
@@ -1,5 +1,5 @@
 /* Running commands on Amiga
 Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-2005, 2006, 2007 Free Software Foundation, Inc.
+2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
Index: /trunk/src/kmk/amiga.h
===================================================================
--- /trunk/src/kmk/amiga.h	(revision 2590)
+++ /trunk/src/kmk/amiga.h	(revision 2591)
@@ -1,5 +1,5 @@
 /* Definitions for amiga specific things
 Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-2005, 2006, 2007 Free Software Foundation, Inc.
+2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
Index: /trunk/src/kmk/ar.c
===================================================================
--- /trunk/src/kmk/ar.c	(revision 2590)
+++ /trunk/src/kmk/ar.c	(revision 2591)
@@ -1,6 +1,7 @@
 /* Interface to `ar' archives 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 Free Software
-Foundation, Inc.
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+2010 Free Software Foundation, Inc.
+
 This file is part of GNU Make.
 
@@ -25,6 +26,7 @@
 #include <fnmatch.h>
 
-/* Return nonzero if NAME is an archive-member reference, zero if not.
-   An archive-member reference is a name like `lib(member)'.
+/* Return nonzero if NAME is an archive-member reference, zero if not.  An
+   archive-member reference is a name like `lib(member)' where member is a
+   non-empty string.
    If a name like `lib((entry))' is used, a fatal error is signaled at
    the attempt to use this unsupported feature.  */
@@ -40,5 +42,5 @@
 
   end = p + strlen (p) - 1;
-  if (*end != ')')
+  if (*end != ')' || end == p + 1)
     return 0;
 
@@ -199,7 +201,6 @@
     {
       /* We have a match.  Add it to the chain.  */
-      struct nameseq *new = xmalloc (state->size);
-      memset (new, '\0', state->size);
-      new->name = strcache_add (concat (state->arname, mem, ")"));
+      struct nameseq *new = xcalloc (state->size);
+      new->name = strcache_add (concat (4, state->arname, "(", mem, ")"));
       new->next = state->chain;
       state->chain = new;
@@ -216,5 +217,5 @@
 {
   const char *p;
-  int open = 0;
+  int opened = 0;
 
   for (p = pattern; *p != '\0'; ++p)
@@ -231,9 +232,9 @@
 
       case '[':
-	open = 1;
+	opened = 1;
 	break;
 
       case ']':
-	if (open)
+	if (opened)
 	  return 1;
 	break;
@@ -252,5 +253,4 @@
   struct nameseq *n;
   const char **names;
-  char *name;
   unsigned int i;
 
@@ -260,10 +260,5 @@
   /* Scan the archive for matches.
      ar_glob_match will accumulate them in STATE.chain.  */
-  i = strlen (arname);
-  name = alloca (i + 2);
-  memcpy (name, arname, i);
-  name[i] = '(';
-  name[i + 1] = '\0';
-  state.arname = name;
+  state.arname = arname;
   state.pattern = member_pattern;
   state.size = size;
@@ -282,5 +277,6 @@
 
   /* Sort them alphabetically.  */
-  qsort (names, i, sizeof (*names), alpha_compare);
+  /* MSVC erroneously warns without a cast here.  */
+  qsort ((void *)names, i, sizeof (*names), alpha_compare);
 
   /* Put them back into the chain in the sorted order.  */
Index: /trunk/src/kmk/arscan.c
===================================================================
--- /trunk/src/kmk/arscan.c	(revision 2590)
+++ /trunk/src/kmk/arscan.c	(revision 2591)
@@ -1,6 +1,6 @@
 /* Library function for scanning an archive file.
 Copyright (C) 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
-1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software
-Foundation, Inc.
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
@@ -67,5 +67,5 @@
   if (! (status & 1))
     {
-      error (NILF, _("lbr$set_module failed to extract module info, status = %d"),
+      error (NILF, _("lbr$set_module() failed to extract module info, status = %d"),
 	     status);
 
@@ -82,5 +82,26 @@
    * know if this causes problems in other VMS environments.
    */
-  val = decc$fix_time (&mhd->mhd$l_datim) + timezone - daylight*3600;
+  {
+    /* Modified by M. Gehre at 11-JAN-2008 because old formula is wrong:
+     * val = decc$fix_time (&mhd->mhd$l_datim) + timezone - daylight*3600;
+     * a) daylight specifies, if the timezone has daylight saving enabled, not
+     *    if it is active
+     * b) what we need is the information, if daylight saving was active, if
+     *    the library module was replaced. This information we get using the
+     *    localtime function
+     */
+
+    struct tm *tmp;
+
+    /* Conversion from VMS time to C time */
+    val = decc$fix_time (&mhd->mhd$l_datim);
+
+    /*
+     * Conversion from local time (stored in library) to GMT (needed for gmake)
+     * Note: The tm_gmtoff element is a VMS extension to the ANSI standard.
+     */
+    tmp = localtime (&val);
+    val -= tmp->tm_gmtoff;
+  }
 #endif
 
@@ -152,9 +173,10 @@
   if (! (status & 1))
     {
-      error (NILF, _("lbr$ini_control failed with status = %d"),status);
+      error (NILF, _("lbr$ini_control() failed with status = %d"), status);
       return -2;
     }
 
-  libdesc.dsc$a_pointer = archive;
+  /* there is no such descriptor with "const char *dsc$a_pointer" */
+  libdesc.dsc$a_pointer = (char *)archive;
   libdesc.dsc$w_length = strlen (archive);
 
@@ -251,4 +273,5 @@
   };
 # endif
+# define TOCHAR(_m)     (_m)
 #else
 /* These should allow us to read Windows (VC++) libraries (according to Frank
@@ -267,4 +290,6 @@
 # define ar_uid     UserID
 # define ar_gid     GroupID
+/* In Windows the member names have type BYTE so we must cast them.  */
+# define TOCHAR(_m)     ((char *)(_m))
 #endif
 
@@ -610,6 +635,6 @@
 
 #ifndef	M_XENIX
-	sscanf (member_header.ar_mode, "%o", &eltmode);
-	eltsize = atol (member_header.ar_size);
+	sscanf (TOCHAR (member_header.ar_mode), "%o", &eltmode);
+	eltsize = atol (TOCHAR (member_header.ar_size));
 #else	/* Xenix.  */
 	eltmode = (unsigned short int) member_header.ar_mode;
@@ -621,7 +646,7 @@
 		       member_offset + AR_HDR_SIZE, eltsize,
 #ifndef	M_XENIX
-		       atol (member_header.ar_date),
-		       atoi (member_header.ar_uid),
-		       atoi (member_header.ar_gid),
+		       atol (TOCHAR (member_header.ar_date)),
+		       atoi (TOCHAR (member_header.ar_uid)),
+		       atoi (TOCHAR (member_header.ar_gid)),
 #else	/* Xenix.  */
 		       member_header.ar_date,
@@ -794,5 +819,5 @@
   for (ui = 0; ui < sizeof ar_hdr.ar_date; ui++)
     ar_hdr.ar_date[ui] = ' ';
-  sprintf (ar_hdr.ar_date, "%ld", (long int) statbuf.st_mtime);
+  sprintf (TOCHAR (ar_hdr.ar_date), "%ld", (long int) statbuf.st_mtime);
 #ifdef AIAMAG
   ar_hdr.ar_date[strlen(ar_hdr.ar_date)] = ' ';
Index: /trunk/src/kmk/build.template
===================================================================
--- /trunk/src/kmk/build.template	(revision 2590)
+++ /trunk/src/kmk/build.template	(revision 2591)
@@ -4,5 +4,5 @@
 
 # Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 # This file is part of GNU Make.
 #
Index: /trunk/src/kmk/build_w32.bat
===================================================================
--- /trunk/src/kmk/build_w32.bat	(revision 2590)
+++ /trunk/src/kmk/build_w32.bat	(revision 2591)
@@ -1,20 +1,25 @@
-<<<<<<< .working
 @echo off
 rem Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-rem 2006 Free Software Foundation, Inc.
+rem 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 rem This file is part of GNU Make.
+rem
+rem GNU Make is free software; you can redistribute it and/or modify it under
+rem the terms of the GNU General Public License as published by the Free
+rem Software Foundation; either version 3 of the License, or (at your option)
+rem any later version.
+rem
+rem GNU Make is distributed in the hope that it will be useful, but WITHOUT
+rem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+rem FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for.
+rem more details.
+rem
+rem You should have received a copy of the GNU General Public License along
+rem with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-rem GNU Make is free software; you can redistribute it and/or modify it under the
-rem terms of the GNU General Public License as published by the Free Software
-rem Foundation; either version 2, or (at your option) any later version.
-
-rem GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
-rem WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-rem A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-
-rem You should have received a copy of the GNU General Public License along with
-rem GNU Make; see the file COPYING.  If not, write to the Free Software
-rem Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-
+if exist config.h.W32 GoTo NotCVS
+sed -n "s/^AC_INIT(\[GNU make\],\[\([^]]\+\)\].*/s,%%VERSION%%,\1,g/p" configure.in > config.h.W32.sed
+echo s,%%PACKAGE%%,make,g >> config.h.W32.sed
+sed -f config.h.W32.sed config.h.W32.template > config.h.W32
+:NotCVS
 if not exist config.h copy config.h.W32 config.h
 cd w32\subproc
@@ -90,7 +95,7 @@
 echo off
 echo "Linking WinDebug/%make%.exe"
-rem link.exe kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib w32\subproc\windebug\subproc.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes /PDB:.\WinDebug/%make%.pdb /DEBUG /MACHINE:I386 /OUT:.\WinDebug/%make%.exe .\WinDebug/variable.obj  .\WinDebug/rule.obj  .\WinDebug/remote-stub.obj  .\WinDebug/commands.obj  .\WinDebug/file.obj  .\WinDebug/getloadavg.obj  .\WinDebug/default.obj  .\WinDebug/signame.obj  .\WinDebug/expand.obj  .\WinDebug/dir.obj  .\WinDebug/main.obj  .\WinDebug/getopt1.obj  .\WinDebug/job.obj  .\WinDebug/read.obj  .\WinDebug/version.obj  .\WinDebug/getopt.obj  .\WinDebug/arscan.obj  .\WinDebug/remake.obj  .\WinDebug/hash.obj  .\WinDebug/strcache.obj  .\WinDebug/misc.obj  .\WinDebug/ar.obj  .\WinDebug/function.obj  .\WinDebug/vpath.obj  .\WinDebug/implicit.obj  .\WinDebug/dirent.obj  .\WinDebug/glob.obj  .\WinDebug/fnmatch.obj  .\WinDebug/pathstuff.obj
+rem link.exe kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib w32\subproc\windebug\subproc.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes /PDB:.\WinDebug/%make%.pdb /DEBUG /OUT:.\WinDebug/%make%.exe .\WinDebug/variable.obj  .\WinDebug/rule.obj  .\WinDebug/remote-stub.obj  .\WinDebug/commands.obj  .\WinDebug/file.obj  .\WinDebug/getloadavg.obj  .\WinDebug/default.obj  .\WinDebug/signame.obj  .\WinDebug/expand.obj  .\WinDebug/dir.obj  .\WinDebug/main.obj  .\WinDebug/getopt1.obj  .\WinDebug/job.obj  .\WinDebug/read.obj  .\WinDebug/version.obj  .\WinDebug/getopt.obj  .\WinDebug/arscan.obj  .\WinDebug/remake.obj  .\WinDebug/hash.obj  .\WinDebug/strcache.obj  .\WinDebug/misc.obj  .\WinDebug/ar.obj  .\WinDebug/function.obj  .\WinDebug/vpath.obj  .\WinDebug/implicit.obj  .\WinDebug/dirent.obj  .\WinDebug/glob.obj  .\WinDebug/fnmatch.obj  .\WinDebug/pathstuff.obj
 echo kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib w32\subproc\windebug\subproc.lib >>link.dbg
-link.exe /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes /PDB:.\WinDebug/%make%.pdb /DEBUG /MACHINE:I386 /OUT:.\WinDebug/%make%.exe @link.dbg
+link.exe /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes /PDB:.\WinDebug/%make%.pdb /DEBUG /OUT:.\WinDebug/%make%.exe @link.dbg
 if not exist .\WinDebug/%make%.exe echo "WinDebug build failed"
 if exist .\WinDebug/%make%.exe echo "WinDebug build succeeded!"
@@ -157,211 +162,7 @@
 echo off
 echo "Linking WinRel/%make%.exe"
-rem link.exe kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib w32\subproc\winrel\subproc.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no /PDB:.\WinRel/%make%.pdb /MACHINE:I386 /OUT:.\WinRel/%make%.exe .\WinRel/variable.obj  .\WinRel/rule.obj  .\WinRel/remote-stub.obj  .\WinRel/commands.obj  .\WinRel/file.obj  .\WinRel/getloadavg.obj  .\WinRel/default.obj  .\WinRel/signame.obj  .\WinRel/expand.obj  .\WinRel/dir.obj  .\WinRel/main.obj  .\WinRel/getopt1.obj  .\WinRel/job.obj  .\WinRel/read.obj  .\WinRel/version.obj  .\WinRel/getopt.obj  .\WinRel/arscan.obj  .\WinRel/remake.obj  .\WinRel/misc.obj  .\WinRel/hash.obj  .\WinRel/strcache.obj  .\WinRel/ar.obj  .\WinRel/function.obj  .\WinRel/vpath.obj  .\WinRel/implicit.obj  .\WinRel/dirent.obj  .\WinRel/glob.obj  .\WinRel/fnmatch.obj  .\WinRel/pathstuff.obj
+rem link.exe kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib w32\subproc\winrel\subproc.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no /PDB:.\WinRel/%make%.pdb /OUT:.\WinRel/%make%.exe .\WinRel/variable.obj  .\WinRel/rule.obj  .\WinRel/remote-stub.obj  .\WinRel/commands.obj  .\WinRel/file.obj  .\WinRel/getloadavg.obj  .\WinRel/default.obj  .\WinRel/signame.obj  .\WinRel/expand.obj  .\WinRel/dir.obj  .\WinRel/main.obj  .\WinRel/getopt1.obj  .\WinRel/job.obj  .\WinRel/read.obj  .\WinRel/version.obj  .\WinRel/getopt.obj  .\WinRel/arscan.obj  .\WinRel/remake.obj  .\WinRel/misc.obj  .\WinRel/hash.obj  .\WinRel/strcache.obj  .\WinRel/ar.obj  .\WinRel/function.obj  .\WinRel/vpath.obj  .\WinRel/implicit.obj  .\WinRel/dirent.obj  .\WinRel/glob.obj  .\WinRel/fnmatch.obj  .\WinRel/pathstuff.obj
 echo kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib w32\subproc\winrel\subproc.lib >>link.rel
-link.exe /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no /PDB:.\WinRel/%make%.pdb /MACHINE:I386 /OUT:.\WinRel/%make%.exe @link.rel
-if not exist .\WinRel/%make%.exe echo "WinRel build failed"
-if exist .\WinRel/%make%.exe echo "WinRel build succeeded!"
-set make=
-GoTo BuildEnd
-:GCCBuild
-echo on
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c variable.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c rule.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c remote-stub.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c commands.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c file.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c getloadavg.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c default.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c signame.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c expand.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c dir.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c main.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c getopt1.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c job.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c read.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c version.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c getopt.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c arscan.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c remake.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c hash.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c strcache.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c misc.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c ar.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c function.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c vpath.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c implicit.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c ./glob/glob.c -o glob.o
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c ./glob/fnmatch.c -o fnmatch.o
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c ./w32/pathstuff.c -o pathstuff.o
-gcc -mthreads -gstabs+ -ggdb3 -o gnumake.exe variable.o rule.o remote-stub.o commands.o file.o getloadavg.o default.o signame.o expand.o dir.o main.o getopt1.o job.o read.o version.o getopt.o arscan.o remake.o misc.o hash.o strcache.o ar.o function.o vpath.o implicit.o glob.o fnmatch.o pathstuff.o w32_misc.o sub_proc.o w32err.o -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lodbc32 -lodbccp32
-:BuildEnd
-echo on
-=======
-@echo off
-rem Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-rem 2006, 2007 Free Software Foundation, Inc.
-rem This file is part of GNU Make.
-rem
-rem GNU Make is free software; you can redistribute it and/or modify it under
-rem the terms of the GNU General Public License as published by the Free
-rem Software Foundation; either version 3 of the License, or (at your option)
-rem any later version.
-rem
-rem GNU Make is distributed in the hope that it will be useful, but WITHOUT
-rem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-rem FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for.
-rem more details.
-rem
-rem You should have received a copy of the GNU General Public License along
-rem with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-if exist config.h.W32 GoTo NotCVS
-sed -n "s/^AC_INIT(\[GNU make\],\[\([^]]\+\)\].*/s,%%VERSION%%,\1,g/p" configure.in > config.h.W32.sed
-echo s,%%PACKAGE%%,make,g >> config.h.W32.sed
-sed -f config.h.W32.sed config.h.W32.template > config.h.W32
-:NotCVS
-if not exist config.h copy config.h.W32 config.h
-cd w32\subproc
-echo "Creating the subproc library"
-%ComSpec% /c build.bat %1
-cd ..\..
-
-if exist link.dbg del link.dbg
-if exist link.rel del link.rel
-echo "Creating GNU Make for Windows 9X/NT/2K/XP"
-if "%1" == "gcc" GoTo GCCBuild
-set make=gnumake
-echo on
-if not exist .\WinDebug\nul mkdir .\WinDebug
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D TIVOLI /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c variable.c
-echo WinDebug\variable.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c rule.c
-echo WinDebug\rule.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c remote-stub.c
-echo WinDebug\remote-stub.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c commands.c
-echo WinDebug\commands.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c file.c
-echo WinDebug\file.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c getloadavg.c
-echo WinDebug\getloadavg.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c default.c
-echo WinDebug\default.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c signame.c
-echo WinDebug\signame.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c expand.c
-echo WinDebug\expand.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c dir.c
-echo WinDebug\dir.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c main.c
-echo WinDebug\main.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c getopt1.c
-echo WinDebug\getopt1.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c job.c
-echo WinDebug\job.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c read.c
-echo WinDebug\read.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c version.c
-echo WinDebug\version.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c getopt.c
-echo WinDebug\getopt.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c arscan.c
-echo WinDebug\arscan.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c hash.c
-echo WinDebug\hash.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c strcache.c
-echo WinDebug\strcache.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c remake.c
-echo WinDebug\remake.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c misc.c
-echo WinDebug\misc.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c ar.c
-echo WinDebug\ar.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c function.c
-echo WinDebug\function.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c vpath.c
-echo WinDebug\vpath.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c implicit.c
-echo WinDebug\implicit.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c  .\w32\compat\dirent.c
-echo WinDebug\dirent.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c  .\glob\glob.c
-echo WinDebug\glob.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c  .\glob\fnmatch.c
-echo WinDebug\fnmatch.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c  .\w32\pathstuff.c
-echo WinDebug\pathstuff.obj >>link.dbg
-echo off
-echo "Linking WinDebug/%make%.exe"
-rem link.exe kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib w32\subproc\windebug\subproc.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes /PDB:.\WinDebug/%make%.pdb /DEBUG /MACHINE:I386 /OUT:.\WinDebug/%make%.exe .\WinDebug/variable.obj  .\WinDebug/rule.obj  .\WinDebug/remote-stub.obj  .\WinDebug/commands.obj  .\WinDebug/file.obj  .\WinDebug/getloadavg.obj  .\WinDebug/default.obj  .\WinDebug/signame.obj  .\WinDebug/expand.obj  .\WinDebug/dir.obj  .\WinDebug/main.obj  .\WinDebug/getopt1.obj  .\WinDebug/job.obj  .\WinDebug/read.obj  .\WinDebug/version.obj  .\WinDebug/getopt.obj  .\WinDebug/arscan.obj  .\WinDebug/remake.obj  .\WinDebug/hash.obj  .\WinDebug/strcache.obj  .\WinDebug/misc.obj  .\WinDebug/ar.obj  .\WinDebug/function.obj  .\WinDebug/vpath.obj  .\WinDebug/implicit.obj  .\WinDebug/dirent.obj  .\WinDebug/glob.obj  .\WinDebug/fnmatch.obj  .\WinDebug/pathstuff.obj
-echo kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib w32\subproc\windebug\subproc.lib >>link.dbg
-link.exe /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes /PDB:.\WinDebug/%make%.pdb /DEBUG /MACHINE:I386 /OUT:.\WinDebug/%make%.exe @link.dbg
-if not exist .\WinDebug/%make%.exe echo "WinDebug build failed"
-if exist .\WinDebug/%make%.exe echo "WinDebug build succeeded!"
-if not exist .\WinRel\nul mkdir .\WinRel
-echo on
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /D TIVOLI /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c variable.c
-echo WinRel\variable.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c rule.c
-echo WinRel\rule.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c remote-stub.c
-echo WinRel\remote-stub.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c commands.c
-echo WinRel\commands.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c file.c
-echo WinRel\file.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c getloadavg.c
-echo WinRel\getloadavg.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c default.c
-echo WinRel\default.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c signame.c
-echo WinRel\signame.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c expand.c
-echo WinRel\expand.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c dir.c
-echo WinRel\dir.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c main.c
-echo WinRel\main.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c getopt1.c
-echo WinRel\getopt1.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c job.c
-echo WinRel\job.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c read.c
-echo WinRel\read.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c version.c
-echo WinRel\version.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c getopt.c
-echo WinRel\getopt.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c arscan.c
-echo WinRel\arscan.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c remake.c
-echo WinRel\remake.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c hash.c
-echo WinRel\hash.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c strcache.c
-echo WinRel\strcache.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c misc.c
-echo WinRel\misc.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c ar.c
-echo WinRel\ar.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c function.c
-echo WinRel\function.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c vpath.c
-echo WinRel\vpath.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c implicit.c
-echo WinRel\implicit.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c  .\w32\compat\dirent.c
-echo WinRel\dirent.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c  .\glob\glob.c
-echo WinRel\glob.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c  .\glob\fnmatch.c
-echo WinRel\fnmatch.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c  .\w32\pathstuff.c
-echo WinRel\pathstuff.obj >>link.rel
-echo off
-echo "Linking WinRel/%make%.exe"
-rem link.exe kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib w32\subproc\winrel\subproc.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no /PDB:.\WinRel/%make%.pdb /MACHINE:I386 /OUT:.\WinRel/%make%.exe .\WinRel/variable.obj  .\WinRel/rule.obj  .\WinRel/remote-stub.obj  .\WinRel/commands.obj  .\WinRel/file.obj  .\WinRel/getloadavg.obj  .\WinRel/default.obj  .\WinRel/signame.obj  .\WinRel/expand.obj  .\WinRel/dir.obj  .\WinRel/main.obj  .\WinRel/getopt1.obj  .\WinRel/job.obj  .\WinRel/read.obj  .\WinRel/version.obj  .\WinRel/getopt.obj  .\WinRel/arscan.obj  .\WinRel/remake.obj  .\WinRel/misc.obj  .\WinRel/hash.obj  .\WinRel/strcache.obj  .\WinRel/ar.obj  .\WinRel/function.obj  .\WinRel/vpath.obj  .\WinRel/implicit.obj  .\WinRel/dirent.obj  .\WinRel/glob.obj  .\WinRel/fnmatch.obj  .\WinRel/pathstuff.obj
-echo kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib w32\subproc\winrel\subproc.lib >>link.rel
-link.exe /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no /PDB:.\WinRel/%make%.pdb /MACHINE:I386 /OUT:.\WinRel/%make%.exe @link.rel
+link.exe /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no /PDB:.\WinRel/%make%.pdb /OUT:.\WinRel/%make%.exe @link.rel
 if not exist .\WinRel/%make%.exe echo "WinRel build failed"
 if exist .\WinRel/%make%.exe echo "WinRel build succeeded!"
@@ -401,3 +202,2 @@
 :BuildEnd
 echo on
->>>>>>> .merge-right.r1992
Index: /trunk/src/kmk/commands.c
===================================================================
--- /trunk/src/kmk/commands.c	(revision 2590)
+++ /trunk/src/kmk/commands.c	(revision 2591)
@@ -1,6 +1,6 @@
 /* Command processing 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 Free Software
-Foundation, Inc.
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
@@ -44,4 +44,77 @@
 
 
+#ifndef CONFIG_WITH_STRCACHE2
+
+static unsigned long
+dep_hash_1 (const void *key)
+{
+  const struct dep *d = key;
+  return_STRING_HASH_1 (dep_name (d));
+}
+
+static unsigned long
+dep_hash_2 (const void *key)
+{
+  const struct dep *d = key;
+  return_STRING_HASH_2 (dep_name (d));
+}
+
+static int
+dep_hash_cmp (const void *x, const void *y)
+{
+  const struct dep *dx = x;
+  const struct dep *dy = y;
+  return strcmp (dep_name (dx), dep_name (dy));
+}
+
+
+#else  /* CONFIG_WITH_STRCACHE2 */
+
+/* Exploit the fact that all names are in the string cache. This means equal
+   names shall have the same storage and there is no need for hashing or
+   comparing. Use the address as the first hash, avoiding any touching of
+   the name, and the length as the second. */
+
+static unsigned long
+dep_hash_1 (const void *key)
+{
+  const char *name = dep_name ((struct dep const *) key);
+  assert (strcache2_is_cached (&file_strcache, name));
+  return (size_t) name / sizeof(void *);
+}
+
+static unsigned long
+dep_hash_2 (const void *key)
+{
+  const char *name = dep_name ((struct dep const *) key);
+  return strcache2_get_len (&file_strcache, name);
+}
+
+static int
+dep_hash_cmp (const void *x, const void *y)
+{
+  struct dep *dx = (struct dep *) x;
+  struct dep *dy = (struct dep *) y;
+  const char *dxname = dep_name (dx);
+  const char *dyname = dep_name (dy);
+  int cmp = dxname == dyname ? 0 : 1;
+
+  /* check preconds: both cached and the cache contains no duplicates. */
+  assert (strcache2_is_cached (&file_strcache, dxname));
+  assert (strcache2_is_cached (&file_strcache, dyname));
+  assert (cmp == 0 || strcmp (dxname, dyname) != 0);
+
+  /* If the names are the same but ignore_mtimes are not equal, one of these
+     is an order-only prerequisite and one isn't.  That means that we should
+     remove the one that isn't and keep the one that is.  */
+
+  if (!cmp && dx->ignore_mtime != dy->ignore_mtime)
+    dx->ignore_mtime = dy->ignore_mtime = 0;
+
+  return cmp;
+}
+
+#endif /* CONFIG_WITH_STRCACHE2 */
+
 /* Set FILE's automatic variables up.  */
 
@@ -53,5 +126,5 @@
 #endif
 {
-  const struct dep *d;
+  struct dep *d;
   const char *at, *percent, *star, *less;
 #ifdef CONFIG_WITH_STRCACHE2
@@ -138,5 +211,6 @@
     if (!d->ignore_mtime)
       {
-        less = dep_name (d);
+        if (!d->need_2nd_expansion)
+          less = dep_name (d);
         break;
       }
@@ -214,15 +288,33 @@
     unsigned int len;
 
+    struct hash_table dep_hash;
+    void **slot;
+
     /* Compute first the value for $+, which is supposed to contain
        duplicate dependencies as they were listed in the makefile.  */
 
     plus_len = 0;
+    bar_len = 0;
     for (d = file->deps; d != 0; d = d->next)
       if (! d->ignore_mtime)
+      {
+        if (!d->need_2nd_expansion)
+          {
 #ifndef CONFIG_WITH_STRCACHE2
-	plus_len += strlen (dep_name (d)) + 1;
-#else
-	plus_len += strcache2_get_len (&file_strcache, dep_name (d)) + 1;
-#endif
+            if (d->ignore_mtime)
+              bar_len += strlen (dep_name (d)) + 1;
+            else
+              plus_len += strlen (dep_name (d)) + 1;
+#else
+            if (d->ignore_mtime)
+              bar_len += strcache2_get_len (&file_strcache, dep_name (d)) + 1;
+            else
+              plus_len += strcache2_get_len (&file_strcache, dep_name (d)) + 1;
+#endif
+          }
+      }
+
+    if (bar_len == 0)
+      bar_len++;
     if (plus_len == 0)
       plus_len++;
@@ -230,9 +322,10 @@
     if (plus_len > plus_max)
       plus_value = xrealloc (plus_value, plus_max = plus_len);
+
     cp = plus_value;
 
     qmark_len = plus_len + 1;	/* Will be this or less.  */
     for (d = file->deps; d != 0; d = d->next)
-      if (! d->ignore_mtime)
+      if (! d->ignore_mtime && ! d->need_2nd_expansion)
         {
           const char *c = dep_name (d);
@@ -255,5 +348,5 @@
           cp += len;
           *cp++ = FILE_LIST_SEPARATOR;
-          if (! d->changed)
+          if (! (d->changed || always_make_flag))
             qmark_len -= len + 1;	/* Don't space in $? for this one.  */
         }
@@ -263,21 +356,4 @@
     cp[cp > plus_value ? -1 : 0] = '\0';
     DEFINE_VARIABLE ("+", 1, plus_value);
-
-    /* Make sure that no dependencies are repeated.  This does not
-       really matter for the purpose of updating targets, but it
-       might make some names be listed twice for $^ and $?.  */
-
-    uniquize_deps (file->deps);
-
-    bar_len = 0;
-    for (d = file->deps; d != 0; d = d->next)
-      if (d->ignore_mtime)
-#ifndef CONFIG_WITH_STRCACHE2
-	bar_len += strlen (dep_name (d)) + 1;
-#else
-	bar_len += strcache2_get_len (&file_strcache, dep_name (d)) + 1;
-#endif
-    if (bar_len == 0)
-      bar_len++;
 
     /* Compute the values for $^, $?, and $|.  */
@@ -293,10 +369,41 @@
     bp = bar_value;
 
+    /* Make sure that no dependencies are repeated in $^, $?, and $|.  It
+       would be natural to combine the next two loops but we can't do it
+       because of a situation where we have two dep entries, the first
+       is order-only and the second is normal (see below).  */
+
+    hash_init (&dep_hash, 500, dep_hash_1, dep_hash_2, dep_hash_cmp);
+
     for (d = file->deps; d != 0; d = d->next)
       {
-	const char *c = dep_name (d);
-
+        if (d->need_2nd_expansion)
+          continue;
+
+        slot = hash_find_slot (&dep_hash, d);
+        if (HASH_VACANT (*slot))
+          hash_insert_at (&dep_hash, d, slot);
+        else
+          {
+            /* Check if the two prerequisites have different ignore_mtime.
+               If so then we need to "upgrade" one that is order-only.  */
+
+            struct dep* hd = (struct dep*) *slot;
+
+            if (d->ignore_mtime != hd->ignore_mtime)
+              d->ignore_mtime = hd->ignore_mtime = 0;
+          }
+      }
+
+    for (d = file->deps; d != 0; d = d->next)
+      {
+        const char *c;
+
+        if (d->need_2nd_expansion || hash_find_item (&dep_hash, d) != d)
+          continue;
+
+        c = dep_name (d);
 #ifndef	NO_ARCHIVES
-	if (ar_name (c))
+        if (ar_name (c))
 	  {
 	    c = strchr (c, '(') + 1;
@@ -313,14 +420,14 @@
         if (d->ignore_mtime)
           {
-	    memcpy (bp, c, len);
+            memcpy (bp, c, len);
 	    bp += len;
 	    *bp++ = FILE_LIST_SEPARATOR;
 	  }
 	else
-	  {
+          {
             memcpy (cp, c, len);
             cp += len;
             *cp++ = FILE_LIST_SEPARATOR;
-            if (d->changed)
+            if (d->changed || always_make_flag)
               {
                 memcpy (qp, c, len);
@@ -331,4 +438,6 @@
       }
 
+    hash_free (&dep_hash, 0);
+
     /* Kill the last spaces and define the variables.  */
 
@@ -352,5 +461,6 @@
       file->org_deps = copy_dep_chain (file->deps);
 
-      uniquize_deps (file->deps);
+      /** @todo do uniquize_deps (file->deps); in the $(dep-* ) functions, it'll
+       *        save even more space that way. */
    }
 #endif /* CONFIG_WITH_LAZY_DEPS_VARS */
@@ -365,5 +475,4 @@
 chop_commands (struct commands *cmds)
 {
-  const char *p;
   unsigned int nlines, idx;
   char **lines;
@@ -375,48 +484,66 @@
     return;
 
-  /* Chop CMDS->commands up into lines in CMDS->command_lines.
-	 Also set the corresponding CMDS->lines_flags elements,
-	 and the CMDS->any_recurse flag.  */
-
-  nlines = 5;
-  lines = xmalloc (5 * sizeof (char *));
-  idx = 0;
-  p = cmds->commands;
-  while (*p != '\0')
-    {
-      const char *end = p;
-    find_end:;
-      end = strchr (end, '\n');
-      if (end == 0)
-        end = p + strlen (p);
-      else if (end > p && end[-1] == '\\')
+  /* Chop CMDS->commands up into lines in CMDS->command_lines.  */
+
+  if (one_shell)
+    {
+      int l = strlen (cmds->commands);
+
+      nlines = 1;
+      lines = xmalloc (nlines * sizeof (char *));
+      lines[0] = xstrdup (cmds->commands);
+
+      /* Strip the trailing newline.  */
+      if (l > 0 && lines[0][l-1] == '\n')
+        lines[0][l-1] = '\0';
+    }
+  else
+    {
+      const char *p;
+
+      nlines = 5;
+      lines = xmalloc (nlines * sizeof (char *));
+      idx = 0;
+      p = cmds->commands;
+      while (*p != '\0')
         {
-          int backslash = 1;
-          const char *b;
-          for (b = end - 2; b >= p && *b == '\\'; --b)
-            backslash = !backslash;
-          if (backslash)
+          const char *end = p;
+        find_end:;
+          end = strchr (end, '\n');
+          if (end == 0)
+            end = p + strlen (p);
+          else if (end > p && end[-1] == '\\')
             {
-              ++end;
-              goto find_end;
+              int backslash = 1;
+              const char *b;
+              for (b = end - 2; b >= p && *b == '\\'; --b)
+                backslash = !backslash;
+              if (backslash)
+                {
+                  ++end;
+                  goto find_end;
+                }
             }
+
+          if (idx == nlines)
+            {
+              nlines += 2;
+              lines = xrealloc (lines, nlines * sizeof (char *));
+            }
+          lines[idx++] = xstrndup (p, end - p);
+          p = end;
+          if (*p != '\0')
+            ++p;
         }
 
-      if (idx == nlines)
+      if (idx != nlines)
         {
-          nlines += 2;
+          nlines = idx;
           lines = xrealloc (lines, nlines * sizeof (char *));
         }
-      lines[idx++] = savestring (p, end - p);
-      p = end;
-      if (*p != '\0')
-        ++p;
-    }
-
-  if (idx != nlines)
-    {
-      nlines = idx;
-      lines = xrealloc (lines, nlines * sizeof (char *));
-    }
+    }
+
+  /* Finally, set the corresponding CMDS->lines_flags elements and the
+     CMDS->any_recurse flag.  */
 
   cmds->ncommand_lines = nlines;
@@ -429,16 +556,12 @@
   cmds->lines_flags = xmalloc (nlines * sizeof (cmds->lines_flags[0]));
 #endif
+
   for (idx = 0; idx < nlines; ++idx)
     {
       int flags = 0;
-
-      for (p = lines[idx];
-#ifndef CONFIG_WITH_COMMANDS_FUNC
-            isblank ((unsigned char)*p) || *p == '-' || *p == '@' || *p == '+';
-#else
-           isblank ((unsigned char)*p) || *p == '-' || *p == '@' || *p == '+' || *p == '%';
-#endif
-           ++p)
-        switch (*p)
+      const char *p = lines[idx];
+
+      while (isblank (*p) || *p == '-' || *p == '@' || *p == '+' IF_WITH_COMMANDS_FUNC(|| *p == '%'))
+        switch (*(p++))
           {
           case '+':
Index: /trunk/src/kmk/commands.h
===================================================================
--- /trunk/src/kmk/commands.h	(revision 2590)
+++ /trunk/src/kmk/commands.h	(revision 2591)
@@ -1,6 +1,6 @@
 /* Definition of data structures describing shell commands 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 Free Software
-Foundation, Inc.
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
Index: /trunk/src/kmk/config.ami.template
===================================================================
--- /trunk/src/kmk/config.ami.template	(revision 2590)
+++ /trunk/src/kmk/config.ami.template	(revision 2591)
@@ -1,5 +1,5 @@
 /* config.h -- hand-massaged for Amiga                                  -*-C-*-
 Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-2005, 2006, 2007 Free Software Foundation, Inc.
+2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
Index: /trunk/src/kmk/config.h-vms.template
===================================================================
--- /trunk/src/kmk/config.h-vms.template	(revision 2590)
+++ /trunk/src/kmk/config.h-vms.template	(revision 2591)
@@ -2,5 +2,5 @@
 
 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-2006, 2007 Free Software Foundation, Inc.
+2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
@@ -76,4 +76,7 @@
 /* Define to 1 if you don't have vprintf but do have _doprnt.  */
 /* #undef HAVE_DOPRNT */
+
+/* Define to 1 if you have the fdopen function.  */
+#define HAVE_FDOPEN 1
 
 /* Define to 1 if your system has a working fnmatch function.  */
@@ -290,5 +293,5 @@
 
 /* Define to 1 if you have the strcasecmp function.  */
-/* #undef HAVE_STRCASECMP */
+#define HAVE_STRCASECMP 1
 
 /* Define to 1 if you have the strcmpi function.  */
Index: /trunk/src/kmk/config.h.W32.template
===================================================================
--- /trunk/src/kmk/config.h.W32.template	(revision 2590)
+++ /trunk/src/kmk/config.h.W32.template	(revision 2591)
@@ -2,5 +2,5 @@
 
 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-2006, 2007 Free Software Foundation, Inc.
+2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
@@ -25,4 +25,6 @@
 # pragma warning(disable:4131) /* uses old-style declarator */
 # pragma warning(disable:4702) /* unreachable code */
+# define _CRT_SECURE_NO_WARNINGS  /* function or variable may be unsafe */
+# define _CRT_NONSTDC_NO_WARNINGS /* functions w/o a leading underscore */
 #endif
 
@@ -228,8 +230,17 @@
 
 /* Define to 1 if you have the `strcmpi' function. */
-#define HAVE_STRCMPI 1
+/* #undef HAVE_STRCMPI */
 
 /* Define to 1 if you have the `stricmp' function. */
-/* #undef HAVE_STRICMP */
+#define HAVE_STRICMP 1
+
+/* Define to 1 if you have the `strncasecmp' function. */
+/* #undef HAVE_STRNCASECMP */
+
+/* Define to 1 if you have the `strncmpi' function. */
+/* #undef HAVE_STRNCMPI */
+
+/* Define to 1 if you have the `strnicmp' function. */
+#define HAVE_STRNICMP 1
 
 /* Define to 1 if you have the `strchr' function. */
@@ -427,5 +438,9 @@
 /* GCC 4.x reportedly defines pid_t.  */
 #ifndef _PID_T_
+#ifdef _WIN64
+#define pid_t __int64
+#else
 #define pid_t int
+#endif
 #endif
 
Index: /trunk/src/kmk/config.h.darwin
===================================================================
--- /trunk/src/kmk/config.h.darwin	(revision 2590)
+++ /trunk/src/kmk/config.h.darwin	(revision 2591)
@@ -41,4 +41,5 @@
 /* Define to 1 if you have the `bsd_signal' function. */
 #define HAVE_BSD_SIGNAL 1
+#define HAVE_DECL_BSD_SIGNAL 1
 
 /* Use case insensitive file names */
@@ -79,4 +80,7 @@
 #define HAVE_FDOPEN 1
 
+/* Define to 1 if you have the `fileno' function. */
+#define HAVE_FILENO 1
+
 /* Define to 1 if you have the `fork' function. */
 #define HAVE_FORK 1
@@ -202,4 +206,13 @@
 /* #undef HAVE_STRCMPI */
 
+/* Define to 1 if you have the `strncasecmp' function. */
+#define HAVE_STRNCASECMP 1
+
+/* Define to 1 if you have the `strncmpi' function. */
+/* #undef HAVE_STRNCMPI */
+
+/* Define to 1 if you have the `strncmp' function. */
+/* #undef HAVE_STRNICMP */
+
 /* Define to 1 if you have the `strcoll' function and it is properly defined.
    */
@@ -208,4 +221,7 @@
 /* Define to 1 if you have the `strdup' function. */
 #define HAVE_STRDUP 1
+
+/* Define to 1 if you have the `strndup' function. */
+/* #undef HAVE_STRNDUP  */
 
 /* Define to 1 if you have the `strerror' function. */
@@ -315,5 +331,5 @@
 
 /* Define to the full name and version of this package. */
-#define PACKAGE_STRING "GNU make 3.81.90"
+#define PACKAGE_STRING "GNU make 3.82"
 
 /* Define to the one symbol short name of this package. */
@@ -321,5 +337,5 @@
 
 /* Define to the version of this package. */
-#define PACKAGE_VERSION "3.81.90"
+#define PACKAGE_VERSION "3.82"
 
 /* Define to the character that separates directories in PATH. */
@@ -374,5 +390,5 @@
 
 /* Version number of package */
-#define VERSION "3.81.90"
+#define VERSION "3.82"
 
 /* Use platform specific coding */
Index: /trunk/src/kmk/config.h.freebsd
===================================================================
--- /trunk/src/kmk/config.h.freebsd	(revision 2590)
+++ /trunk/src/kmk/config.h.freebsd	(revision 2591)
@@ -319,5 +319,5 @@
 
 /* Define to the full name and version of this package. */
-#define PACKAGE_STRING "GNU make 3.81.90"
+#define PACKAGE_STRING "GNU make 3.82"
 
 /* Define to the one symbol short name of this package. */
@@ -325,5 +325,5 @@
 
 /* Define to the version of this package. */
-#define PACKAGE_VERSION "3.81.90"
+#define PACKAGE_VERSION "3.82"
 
 /* Define to the character that separates directories in PATH. */
@@ -378,5 +378,5 @@
 
 /* Version number of package */
-#define VERSION "3.81.90"
+#define VERSION "3.82"
 
 /* Use platform specific coding */
Index: /trunk/src/kmk/config.h.haiku
===================================================================
--- /trunk/src/kmk/config.h.haiku	(revision 2590)
+++ /trunk/src/kmk/config.h.haiku	(revision 2591)
@@ -315,5 +315,5 @@
 
 /* Define to the full name and version of this package. */
-#define PACKAGE_STRING "GNU make 3.81.90"
+#define PACKAGE_STRING "GNU make 3.82"
 
 /* Define to the one symbol short name of this package. */
@@ -324,5 +324,5 @@
 
 /* Define to the version of this package. */
-#define PACKAGE_VERSION "3.81.90"
+#define PACKAGE_VERSION "3.82"
 
 /* Define to the character that separates directories in PATH. */
@@ -391,5 +391,5 @@
 
 /* Version number of package */
-#define VERSION "3.81.90"
+#define VERSION "3.82"
 
 /* Use platform specific coding */
Index: /trunk/src/kmk/config.h.linux
===================================================================
--- /trunk/src/kmk/config.h.linux	(revision 2590)
+++ /trunk/src/kmk/config.h.linux	(revision 2591)
@@ -315,5 +315,5 @@
 
 /* Define to the full name and version of this package. */
-#define PACKAGE_STRING "GNU make 3.81.90"
+#define PACKAGE_STRING "GNU make 3.82"
 
 /* Define to the one symbol short name of this package. */
@@ -321,5 +321,5 @@
 
 /* Define to the version of this package. */
-#define PACKAGE_VERSION "3.81.90"
+#define PACKAGE_VERSION "3.82"
 
 /* Define to the character that separates directories in PATH. */
@@ -374,5 +374,5 @@
 
 /* Version number of package */
-#define VERSION "3.81.90"
+#define VERSION "3.82"
 
 /* Use platform specific coding */
Index: /trunk/src/kmk/config.h.os2
===================================================================
--- /trunk/src/kmk/config.h.os2	(revision 2590)
+++ /trunk/src/kmk/config.h.os2	(revision 2591)
@@ -332,5 +332,5 @@
 
 /* Define to the full name and version of this package. */
-#define PACKAGE_STRING "GNU make 3.81"
+#define PACKAGE_STRING "GNU make 3.82"
 
 /* Define to the one symbol short name of this package. */
@@ -338,5 +338,5 @@
 
 /* Define to the version of this package. */
-#define PACKAGE_VERSION "3.81"
+#define PACKAGE_VERSION "3.82"
 
 /* Define to 1 if the C compiler supports function prototypes. */
Index: /trunk/src/kmk/config.h.solaris
===================================================================
--- /trunk/src/kmk/config.h.solaris	(revision 2590)
+++ /trunk/src/kmk/config.h.solaris	(revision 2591)
@@ -315,5 +315,5 @@
 
 /* Define to the full name and version of this package. */
-#define PACKAGE_STRING "GNU make 3.81.90"
+#define PACKAGE_STRING "GNU make 3.82"
 
 /* Define to the one symbol short name of this package. */
@@ -321,5 +321,5 @@
 
 /* Define to the version of this package. */
-#define PACKAGE_VERSION "3.81.90"
+#define PACKAGE_VERSION "3.82"
 
 /* Define to the character that separates directories in PATH. */
@@ -374,5 +374,5 @@
 
 /* Version number of package */
-#define VERSION "3.81.90"
+#define VERSION "3.82"
 
 /* Use platform specific coding */
Index: /trunk/src/kmk/config.h.win
===================================================================
--- /trunk/src/kmk/config.h.win	(revision 2590)
+++ /trunk/src/kmk/config.h.win	(revision 2591)
@@ -344,5 +344,5 @@
 
 /* Define to the full name and version of this package. */
-#define PACKAGE_STRING "GNU make 3.81.90"
+#define PACKAGE_STRING "GNU make 3.82"
 
 /* Define to the one symbol short name of this package. */
@@ -350,5 +350,5 @@
 
 /* Define to the version of this package. */
-#define PACKAGE_VERSION "3.81.90"
+#define PACKAGE_VERSION "3.82"
 
 /* Define to 1 if the C compiler supports function prototypes. */
@@ -400,5 +400,5 @@
 
 /* Version number of package */
-#define VERSION "3.81.90"
+#define VERSION "3.82"
 
 /* Define if using the dmalloc debugging malloc package */
Index: /trunk/src/kmk/config/ChangeLog
===================================================================
--- /trunk/src/kmk/config/ChangeLog	(revision 2590)
+++ /trunk/src/kmk/config/ChangeLog	(revision 2591)
@@ -30,5 +30,6 @@
 
 
-Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software
+Foundation, Inc.
 This file is part of GNU Make.
 
Index: /trunk/src/kmk/config/Makefile.am
===================================================================
--- /trunk/src/kmk/config/Makefile.am	(revision 2590)
+++ /trunk/src/kmk/config/Makefile.am	(revision 2591)
@@ -1,5 +1,5 @@
 # -*-Makefile-*-, or close enough
-# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation,
-# Inc.
+# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free
+# Software Foundation, Inc.
 # This file is part of GNU Make.
 #
Index: /trunk/src/kmk/config/dospaths.m4
===================================================================
--- /trunk/src/kmk/config/dospaths.m4	(revision 2590)
+++ /trunk/src/kmk/config/dospaths.m4	(revision 2591)
@@ -3,5 +3,5 @@
 #
 # Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 # This file is part of GNU Make.
 #
Index: /trunk/src/kmk/configh.dos.template
===================================================================
--- /trunk/src/kmk/configh.dos.template	(revision 2590)
+++ /trunk/src/kmk/configh.dos.template	(revision 2591)
@@ -2,5 +2,5 @@
 
 Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
-2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
@@ -17,4 +17,8 @@
 this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
+/* Include this header to make __DJGPP_MINOR__ available because DJGPP ports
+   of GCC 4.3.0 and later no longer do it automatically.  */
+#include <sys/version.h>
+
 /* Many things are defined already by a system header.  */
 #include <sys/config.h>
@@ -22,5 +26,5 @@
 #if __DJGPP__ > 2 || __DJGPP_MINOR__ > 1
 
-/* Define to 1 if `sys_siglist' is declared by <signal.h>.  */
+/* Define to 1 if `sys_siglist' is declared by <signal.h> or <unistd.h>. */
 # define SYS_SIGLIST_DECLARED 1
 
@@ -108,7 +112,4 @@
 #define PROTOTYPES 1
 
-/* Define to 1 if `sys_siglist' is declared by <signal.h> or <unistd.h>. */
-#define SYS_SIGLIST_DECLARED 1
-
 /* Version number of package */
 #define VERSION "%VERSION%"
Index: /trunk/src/kmk/configure.bat
===================================================================
--- /trunk/src/kmk/configure.bat	(revision 2590)
+++ /trunk/src/kmk/configure.bat	(revision 2591)
@@ -1,69 +1,5 @@
-<<<<<<< .working
 @echo off
 rem Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
-rem 2004, 2005, 2006 Free Software Foundation, Inc.
-rem This file is part of GNU Make.
-
-rem GNU Make is free software; you can redistribute it and/or modify it under
-rem the terms of the GNU General Public License as published by the Free
-rem Software Foundation; either version 2, or (at your option) any later
-rem version.
-
-rem GNU Make is distributed in the hope that it will be useful, but WITHOUT
-rem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-rem FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-rem more details.
-
-rem You should have received a copy of the GNU General Public License along
-rem with GNU Make; see the file COPYING.  If not, write to the Free Software
-rem Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-
-echo Configuring MAKE for DJGPP
-
-rem The SmallEnv trick protects against too small environment block,
-rem in which case the values will be truncated and the whole thing
-rem goes awry.  COMMAND.COM will say "Out of environment space", but
-rem many people don't care, so we force them to care by refusing to go.
-
-rem Where is the srcdir?
-set XSRC=.
-if not "%XSRC%"=="." goto SmallEnv
-if "%1%"=="" goto SrcDone
-set XSRC=%1
-if not "%XSRC%"=="%1" goto SmallEnv
-
-:SrcDone
-
-update %XSRC%/configh.dos ./config.h
-
-rem Do they have Make?
-redir -o junk.$$$ -eo make -n -f NUL
-rem REDIR will return 1 if it cannot run Make.
-rem If it can run Make, it will usually return 2,
-rem but 0 is also OK with us.
-if errorlevel 2 goto MakeOk
-if not errorlevel 1 goto MakeOk
-if exist junk.$$$ del junk.$$$
-echo No Make program found--use DOSBUILD.BAT to build Make.
-goto End
-
-rem They do have Make.	Generate the Makefile.
-
-:MakeOk
-del junk.$$$
-update %XSRC%/Makefile.DOS ./Makefile
-echo Done.
-if not "%XSRC%"=="." echo Invoke Make thus: "make srcdir=%XSRC%"
-goto End
-
-:SmallEnv
-echo Your environment is too small.  Please enlarge it and run me again.
-
-:End
-set XRSC=
-=======
-@echo off
-rem Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
-rem 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+rem 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 rem This file is part of GNU Make.
 rem
@@ -124,3 +60,2 @@
 :End
 set XRSC=
->>>>>>> .merge-right.r1992
Index: /trunk/src/kmk/configure.in
===================================================================
--- /trunk/src/kmk/configure.in	(revision 2590)
+++ /trunk/src/kmk/configure.in	(revision 2591)
@@ -2,5 +2,5 @@
 #
 # Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 # This file is part of GNU Make.
 #
@@ -18,8 +18,8 @@
 # this program.  If not, see <http://www.gnu.org/licenses/>.
 
-AC_INIT([GNU make],[3.81.90],[bug-make@gnu.org])
+AC_INIT([GNU make],[3.82],[bug-make@gnu.org])
 
 AC_PREREQ(2.59)
-AC_REVISION([[$Id: configure.in,v 1.148 2007/07/04 19:35:17 psmith Exp $]])
+AC_REVISION([[$Id: configure.in,v 1.156 2010/07/28 05:39:50 psmith Exp $]])
 
 # Autoconf setup
@@ -149,10 +149,15 @@
 fi
 
-AC_CHECK_FUNCS( strdup mkstemp mktemp fdopen \
-	        bsd_signal dup2 getcwd realpath sigsetmask sigaction \
+AC_CHECK_FUNCS( strdup strndup mkstemp mktemp fdopen fileno \
+	        dup2 getcwd realpath sigsetmask sigaction \
                 getgroups seteuid setegid setlinebuf setreuid setregid \
                 getrlimit setrlimit setvbuf pipe strerror strsignal \
 		lstat readlink atexit)
 
+# We need to check declarations, not just existence, because on Tru64 this
+# function is not declared without special flags, which themselves cause
+# other problems.  We'll just use our own.
+AC_CHECK_DECLS([bsd_signal], [], [], [[#include <signal.h>]])
+
 AC_FUNC_SETVBUF_REVERSED
 
@@ -160,5 +165,5 @@
 # It doesn't hurt much to use our own if we can't find it so I don't
 # make the effort here.
-AC_CHECK_FUNCS(strcasecmp strcmpi stricmp)
+AC_CHECK_FUNCS(strcasecmp strncasecmp strcmpi strncmpi stricmp strnicmp)
 
 # strcoll() is used by the GNU glob library
@@ -349,5 +354,4 @@
 # Check the system to see if it provides GNU glob.  If not, use our
 # local version.
-
 AC_MSG_CHECKING(if system libc has GNU glob)
 AC_CACHE_VAL(make_cv_sys_gnu_glob, [
@@ -366,7 +370,12 @@
  ], [AC_MSG_RESULT(yes)
 make_cv_sys_gnu_glob=yes], [AC_MSG_RESULT([no; using local copy])
-AC_SUBST(GLOBINC) GLOBINC='-I$(srcdir)/glob'
-AC_SUBST(GLOBLIB) GLOBLIB=glob/libglob.a
 make_cv_sys_gnu_glob=no])])
+if test "$make_cv_sys_gnu_glob" = no; then
+  GLOBINC='-I$(srcdir)/glob'
+  GLOBLIB=glob/libglob.a
+fi
+AC_SUBST(GLOBINC)
+AC_SUBST(GLOBLIB)
+
 # Tell automake about this, so it can build the right .c files.
 AM_CONDITIONAL(USE_LOCAL_GLOB, test "$make_cv_sys_gnu_glob" = no)
Index: /trunk/src/kmk/debug.h
===================================================================
--- /trunk/src/kmk/debug.h	(revision 2590)
+++ /trunk/src/kmk/debug.h	(revision 2591)
@@ -1,5 +1,5 @@
 /* Debugging macros and interface.
-Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free
-Software Foundation, Inc.
+Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
+2009, 2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
Index: /trunk/src/kmk/default.c
===================================================================
--- /trunk/src/kmk/default.c	(revision 2590)
+++ /trunk/src/kmk/default.c	(revision 2591)
@@ -1,6 +1,6 @@
 /* Data base of default implicit rules 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 Free Software
-Foundation, Inc.
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
@@ -550,16 +550,12 @@
 
   if (no_builtin_rules_flag)
-    define_variable ("SUFFIXES", 8, "", o_default, 0);
+    define_variable_cname ("SUFFIXES", "", o_default, 0);
   else
     {
       char *p = default_suffixes;
-      suffix_file->deps = (struct dep *)
-#ifndef CONFIG_WITH_ALLOC_CACHES
-	multi_glob (parse_file_seq (&p, '\0', sizeof (struct dep), 1),
-		    sizeof (struct dep));
-#else
-        multi_glob (parse_file_seq (&p, '\0', &dep_cache, 1), &dep_cache);
-#endif
-      define_variable ("SUFFIXES", 8, default_suffixes, o_default, 0);
+      suffix_file->deps = enter_prereqs(PARSE_FILE_SEQ (&p, struct dep, '\0',
+                                                        NULL, 0),
+                                        NULL);
+      define_variable_cname ("SUFFIXES", default_suffixes, o_default, 0);
     }
 }
Index: /trunk/src/kmk/dep.h
===================================================================
--- /trunk/src/kmk/dep.h	(revision 2590)
+++ /trunk/src/kmk/dep.h	(revision 2591)
@@ -1,6 +1,6 @@
 /* Definitions of dependency data structures 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 Free Software
-Foundation, Inc.
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
@@ -44,4 +44,6 @@
     unsigned int staticpattern : 1;
     unsigned int need_2nd_expansion : 1;
+    unsigned int dontcare : 1;
+
 #ifdef CONFIG_WITH_INCLUDEDEP
     unsigned int includedep : 1;
@@ -59,18 +61,29 @@
 
 
+#define PARSEFS_NONE    (0x0000)
+#define PARSEFS_NOSTRIP (0x0001)
+#define PARSEFS_NOAR    (0x0002)
+#define PARSEFS_NOGLOB  (0x0004)
+#define PARSEFS_EXISTS  (0x0008)
+#define PARSEFS_NOCACHE (0x0010)
+
 #ifndef CONFIG_WITH_ALLOC_CACHES
-struct nameseq *multi_glob (struct nameseq *chain, unsigned int size);
+#define PARSE_FILE_SEQ(_s,_t,_c,_p,_f) \
+            (_t *)parse_file_seq ((_s),sizeof (_t),(_c),(_p),(_f))
 #else
-struct nameseq *multi_glob (struct nameseq *chain, struct alloccache *cache);
+# define PARSE_FILE_SEQ(_s,_t,_c,_p,_f) \
+            (_t *)parse_file_seq ((_s),sizeof (_t),(_c),(_p),(_f), \
+                                  &PARSE_FILE_SEQ_IGNORE_ ## _t ## _cache)
+# define PARSE_FILE_SEQ_IGNORE_struct
 #endif
+
 #ifdef VMS
-struct nameseq *parse_file_seq ();
+void *parse_file_seq ();
 #else
-# ifndef CONFIG_WITH_ALLOC_CACHES
-struct nameseq *parse_file_seq (char **stringp, int stopchar, unsigned int size, int strip);
-# else
-struct nameseq *parse_file_seq (char **stringp, int stopchar, struct alloccache *cache, int strip);
-# endif
+void *parse_file_seq (char **stringp, unsigned int size,
+                      int stopchar, const char *prefix, int flags
+                      IF_WITH_ALLOC_CACHES_PARAM(struct alloccache *cache));
 #endif
+
 char *tilde_expand (const char *name);
 
@@ -79,19 +92,23 @@
 #endif
 
-#define dep_name(d) ((d)->name == 0 ? (d)->file->name : (d)->name)
+#define dep_name(d)     ((d)->name == 0 ? (d)->file->name : (d)->name)
 
-struct dep *alloc_dep (void);
-void free_dep (struct dep *d);
+
+#ifndef CONFIG_WITH_ALLOC_CACHES
+#define alloc_dep()     (xcalloc (sizeof (struct dep)))
+#define free_ns(_n)     free (_n)
+#define free_dep(_d)    free_ns (_d)
+#else
+#define alloc_dep()     alloccache_calloc (&dep_cache)
+#define free_ns(_n)     alloccache_free (&nameseq_cache, _n)
+#define free_dep(_d)    alloccache_free (&dep_cache, _d)
+#endif
+
 struct dep *copy_dep_chain (const struct dep *d);
 void free_dep_chain (struct dep *d);
 void free_ns_chain (struct nameseq *n);
 struct dep *read_all_makefiles (const char **makefiles);
-#ifndef CONFIG_WITH_VALUE_LENGTH
-int eval_buffer (char *buffer);
-#else
-int eval_buffer (char *buffer, char *eos);
-#endif
+void eval_buffer (char *buffer IF_WITH_VALUE_LENGTH(COMMA char *eos));
 int update_goal_chain (struct dep *goals);
-void uniquize_deps (struct dep *);
 
 #ifdef CONFIG_WITH_INCLUDEDEP
@@ -100,11 +117,4 @@
 void eval_include_dep (const char *name, struct floc *f, enum incdep_op op);
 void incdep_flush_and_term (void);
-
-/* read.c */
-void record_files (struct nameseq *filenames, const char *pattern,
-                   const char *pattern_percent, struct dep *deps,
-                   unsigned int cmds_started, char *commands,
-                   unsigned int commands_idx, int two_colon,
-                   const struct floc *flocp);
 #endif
 
Index: /trunk/src/kmk/dir.c
===================================================================
--- /trunk/src/kmk/dir.c	(revision 2590)
+++ /trunk/src/kmk/dir.c	(revision 2591)
@@ -1,6 +1,6 @@
 /* Directory hashing 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 Free Software
-Foundation, Inc.
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
@@ -24,5 +24,6 @@
 # define NAMLEN(dirent) strlen((dirent)->d_name)
 # ifdef VMS
-char *vmsify (char *name, int type);
+/* its prototype is in vmsdir.h, which is not needed for HAVE_DIRENT_H */
+const char *vmsify (const char *name, int type);
 # endif
 #else
@@ -133,5 +134,4 @@
   static PATH_VAR (new_filename);
   char *df;
-  int i;
 
   if (filename == 0)
@@ -139,6 +139,4 @@
 
   df = new_filename;
-
-  /* First, transform the name part.  */
   while (*filename != '\0')
     {
@@ -156,5 +154,5 @@
 
 static int
-vms_hash (char *name)
+vms_hash (const char *name)
 {
   int h = 0;
@@ -182,5 +180,5 @@
 /* fake stat entry for a directory */
 static int
-vmsstat_dir (char *name, struct stat *st)
+vmsstat_dir (const char *name, struct stat *st)
 {
   char *s;
@@ -195,4 +193,5 @@
   if (s)
     {
+      /* to keep the compiler happy we said "const char *name", now we cheat */
       *s++ = 0;
       st->st_dev = (char *)vms_hash (name);
@@ -203,6 +202,5 @@
     {
       st->st_dev = 0;
-      s = name;
-      h = vms_hash (s);
+      h = vms_hash (name);
     }
 
@@ -496,5 +494,9 @@
 #else
   p = name + strlen (name);
+# if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS)
+  dir_key.name = strcache_add_len (downcase(name), p - name);
+# else
   dir_key.name = strcache_add_len (name, p - name);
+# endif
   dir_slot = (struct directory **) hash_find_slot_strcached (&directories, &dir_key);
 #endif
@@ -516,8 +518,12 @@
 #endif
 #ifndef CONFIG_WITH_STRCACHE2
+#if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS)
+      dir->name = strcache_add_len (downcase(name), p - name);
+#else
       dir->name = strcache_add_len (name, p - name);
-#else
+#endif
+#else  /* CONFIG_WITH_STRCACHE2 */
       dir->name = dir_key.name;
-#endif
+#endif /* CONFIG_WITH_STRCACHE2 */
       hash_insert_at (&directories, dir, dir_slot);
       /* The directory is not in the name hash table.
@@ -826,5 +832,9 @@
       dirfile_slot = (struct dirfile **) hash_find_slot (&dir->dirfiles, &dirfile_key);
 #else
+# if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS)
+      dirfile_key.name = strcache_add_len (downcase(d->d_name), len);
+# else
       dirfile_key.name = strcache_add_len (d->d_name, len);
+# endif
       dirfile_key.length = len;
       dirfile_slot = (struct dirfile **) hash_find_slot_strcached (&dir->dirfiles, &dirfile_key);
@@ -844,8 +854,12 @@
 #endif
 #ifndef CONFIG_WITH_STRCACHE2
+#if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS)
+          df->name = strcache_add_len (downcase(d->d_name), len);
+#else
 	  df->name = strcache_add_len (d->d_name, len);
-#else
+#endif
+#else  /* CONFIG_WITH_STRCACHE2 */
 	  df->name = dirfile_key.name;
-#endif
+#endif /* CONFIG_WITH_STRCACHE2 */
 	  df->length = len;
 	  df->impossible = 0;
@@ -854,5 +868,5 @@
       /* Check if the name matches the one we're searching for.  */
 #ifndef CONFIG_WITH_STRCACHE2
-      if (filename != 0 && strieq (d->d_name, filename))
+      if (filename != 0 && patheq (d->d_name, filename))
 #else
       if (filename != 0 && dirfile_key.name == filename)
@@ -1010,14 +1024,11 @@
 
   if (dir->contents == 0)
-    {
-      /* The directory could not be stat'd.  We allocate a contents
-	 structure for it, but leave it out of the contents hash table.  */
+    /* The directory could not be stat'd.  We allocate a contents
+       structure for it, but leave it out of the contents hash table.  */
 #ifndef CONFIG_WITH_ALLOC_CACHES
-      dir->contents = xmalloc (sizeof (struct directory_contents));
-#else
-      dir->contents = alloccache_alloc (&directory_contents_cache);
-#endif
-      memset (dir->contents, '\0', sizeof (struct directory_contents));
-    }
+    dir->contents = xcalloc (sizeof (struct directory_contents));
+#else
+    dir->contents = alloccache_calloc (&directory_contents_cache);
+#endif
 
   if (dir->contents->dirfiles.ht_vec == 0)
@@ -1040,5 +1051,9 @@
 #endif
   new->length = strlen (filename);
+#if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS)
+  new->name = strcache_add_len (downcase(filename), new->length);
+#else
   new->name = strcache_add_len (filename, new->length);
+#endif
   new->impossible = 1;
 #ifndef CONFIG_WITH_STRCACHE2
Index: /trunk/src/kmk/doc/Makefile.am
===================================================================
--- /trunk/src/kmk/doc/Makefile.am	(revision 2590)
+++ /trunk/src/kmk/doc/Makefile.am	(revision 2591)
@@ -1,5 +1,5 @@
 # -*-Makefile-*-, or close enough
-# Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software
-# Foundation, Inc.
+# Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+# 2010 Free Software Foundation, Inc.
 # This file is part of GNU Make.
 #
Index: /trunk/src/kmk/doc/make.texi
===================================================================
--- /trunk/src/kmk/doc/make.texi	(revision 2590)
+++ /trunk/src/kmk/doc/make.texi	(revision 2591)
@@ -4,6 +4,6 @@
 
 @include version.texi
-@set EDITION 0.70
-@set RCSID $Id: make.texi,v 1.52 2008/05/18 15:11:40 psmith Exp $
+@set EDITION 0.71
+@set RCSID $Id: make.texi,v 1.66 2010/07/19 07:10:54 psmith Exp $
 
 @settitle GNU @code{make}
@@ -14,6 +14,6 @@
 @syncodeindex pg cp
 @c FSF publishers: format makebook.texi instead of using this file directly.
-@c ISBN provided by Lisa M. Opus Goldstein <opus@gnu.org>, 5 May 2004
-@set ISBN 1-882114-83-5
+@c ISBN confirmed by Jasimin Huang <jasimin@fsf.org> on 25 Mar 2009
+@set ISBN 1-882114-83-3
 @c %**end of header
 
@@ -27,6 +27,6 @@
 
 Copyright @copyright{} 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
-1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007
-Free Software Foundation, Inc.
+1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007,
+2008, 2009, 2010 Free Software Foundation, Inc.
 
 @quotation
@@ -39,6 +39,6 @@
 License.''
 
-(a) The FSF's Back-Cover Text is: ``You are free to copy and modify
-this GNU Manual. Buying copies from GNU Press supports the FSF in
+(a) The FSF's Back-Cover Text is: ``You have the freedom to copy and
+modify this GNU manual.  Buying copies from the FSF supports it in
 developing GNU and promoting software freedom.''
 @end quotation
@@ -202,5 +202,5 @@
 * Interrupts::                  What happens when a recipe is interrupted.
 * Recursion::                   Invoking @code{make} from makefiles.
-* Sequences::                   Defining canned recipes.
+* Canned Recipes::              Defining canned recipes.
 * Empty Recipes::               Defining useful, do-nothing recipes.
 
@@ -234,6 +234,6 @@
 * Override Directive::          How to set a variable in the makefile even if
                                   the user has set it with a command argument.
-* Defining::                    An alternate way to set a variable
-                                  to a verbatim string.
+* Multi-Line::                  An alternate way to set a variable
+                                  to a multi-line string.
 * Environment::                 Variable values can come from the environment.
 * Target-specific::             Variable values can be defined on a per-target
@@ -241,4 +241,5 @@
 * Pattern-specific::            Target-specific variable values can be applied
                                   to a group of targets that match a pattern.
+* Suppressing Inheritance::     Suppress inheritance of variables.
 * Special Variables::           Variables with special meaning or behavior.
 
@@ -524,11 +525,11 @@
 
 @cindex tabs in rules
-A @dfn{recipe} is an action that @code{make} carries out.
-A recipe may have more than one command, each on its own line.
-@strong{Please note:} you need to put a tab character at the beginning of
-every command line!  This is an obscurity that catches the unwary.  If
-you prefer to prefix your recipes with a character other than tab,
-you can set the @code{.CMDPREFIX} variable to an alternate character
-(@pxref{Special Variables}).
+A @dfn{recipe} is an action that @code{make} carries out.  A recipe
+may have more than one command, either on the same line or each on its
+own line.  @strong{Please note:} you need to put a tab character at
+the beginning of every recipe line!  This is an obscurity that catches
+the unwary.  If you prefer to prefix your recipes with a character
+other than tab, you can set the @code{.RECIPEPREFIX} variable to an
+alternate character (@pxref{Special Variables}).
 
 Usually a recipe is in a rule with prerequisites and serves to create a
@@ -629,11 +630,11 @@
 prerequisites.  These recipes say how to update the target file.  A
 tab character (or whatever character is specified by the
-@code{.CMDPREFIX} variable; @pxref{Special Variables}) must come at
+@code{.RECIPEPREFIX} variable; @pxref{Special Variables}) must come at
 the beginning of every line in the recipe to distinguish recipes from
 other lines in the makefile.  (Bear in mind that @code{make} does not
 know anything about how the recipes work.  It is up to you to supply
 recipes that will update the target file properly.  All @code{make}
-does is execute the commands in the recipe you have specified when the
-target file needs to be updated.)@refill
+does is execute the recipe you have specified when the target file
+needs to be updated.)@refill
 @cindex recipe
 
@@ -996,5 +997,5 @@
 @item
 Defining a variable from a verbatim string containing multiple lines
-(@pxref{Defining, ,Defining Variables Verbatim}).
+(@pxref{Multi-Line, ,Defining Multi-Line Variables}).
 @end itemize
 
@@ -1097,5 +1098,5 @@
 Extra spaces are allowed and ignored at the beginning of the line, but
 the first character must not be a tab (or the value of
-@code{.CMDPREFIX})---if the line begins with a tab, it will be
+@code{.RECIPEPREFIX})---if the line begins with a tab, it will be
 considered a recipe line.  Whitespace is required between
 @code{include} and the file names, and between file names; extra
@@ -1171,5 +1172,5 @@
 
 If you want @code{make} to simply ignore a makefile which does not exist
-and cannot be remade, with no error message, use the @w{@code{-include}}
+or cannot be remade, with no error message, use the @w{@code{-include}}
 directive instead of @code{include}, like this:
 
@@ -1179,5 +1180,8 @@
 
 This acts like @code{include} in every way except that there is no
-error (not even a warning) if any of the @var{filenames} do not exist.
+error (not even a warning) if any of the @var{filenames} (or any
+prerequisites of any of the @var{filenames}) do not exist or cannot be
+remade.
+
 For compatibility with some other @code{make} implementations,
 @code{sinclude} is another name for @w{@code{-include}}.
@@ -1191,9 +1195,10 @@
 If the environment variable @code{MAKEFILES} is defined, @code{make}
 considers its value as a list of names (separated by whitespace) of
-additional makefiles to be read before the others.  This works much like
-the @code{include} directive: various directories are searched for those
-files (@pxref{Include, ,Including Other Makefiles}).  In addition, the
-default goal is never taken from one of these makefiles and it is not an
-error if the files listed in @code{MAKEFILES} are not found.@refill
+additional makefiles to be read before the others.  This works much
+like the @code{include} directive: various directories are searched
+for those files (@pxref{Include, ,Including Other Makefiles}).  In
+addition, the default goal is never taken from one of these makefiles
+(or any makefile included by them) and it is not an error if the files
+listed in @code{MAKEFILES} are not found.@refill
 
 @cindex recursion, and @code{MAKEFILES} variable
@@ -1269,5 +1274,5 @@
 
 When you use the @samp{-t} or @samp{--touch} option
-(@pxref{Instead of Execution, ,Instead of Executing the Recipe}),
+(@pxref{Instead of Execution, ,Instead of Executing Recipes}),
 you would not want to use an out-of-date makefile to decide which
 targets to touch.  So the @samp{-t} option has no effect on updating
@@ -1387,4 +1392,20 @@
 define @var{immediate}
   @var{deferred}
+endef
+
+define @var{immediate} =
+  @var{deferred}
+endef
+
+define @var{immediate} ?=
+  @var{deferred}
+endef
+
+define @var{immediate} :=
+  @var{immediate}
+endef
+
+define @var{immediate} +=
+  @var{deferred} or @var{immediate}
 endef
 @end example
@@ -1748,5 +1769,5 @@
 @cindex tab character (in commands)
 The @var{recipe} lines start with a tab character (or the first
-character in the value of the @code{.CMDPREFIX} variable;
+character in the value of the @code{.RECIPEPREFIX} variable;
 @pxref{Special Variables}).  The first recipe line may appear on the line
 after the prerequisites, with a tab character, or may appear on the
@@ -1802,10 +1823,10 @@
 GNU @code{make}: normal prerequisites such as described in the
 previous section, and @dfn{order-only} prerequisites.  A normal
-prerequisite makes two statements: first, it imposes an order of
-execution of recipes: any recipes necessary to build any of a
-target's prerequisites will be fully executed before any recipe
-necessary to build the target.  Second, it imposes a dependency
-relationship: if any prerequisite is newer than the target, then the
-target is considered out-of-date and must be rebuilt.
+prerequisite makes two statements: first, it imposes an order in which
+recipes will be invoked: the recipes for all prerequisites of a target
+will be completed before the recipe for the target is run.  Second, it
+imposes a dependency relationship: if any prerequisite is newer than
+the target, then the target is considered out-of-date and must be
+rebuilt.
 
 Normally, this is exactly what you want: if a target's prerequisite is
@@ -1949,7 +1970,9 @@
 @noindent
 then the value of the variable @code{objects} is the actual string
-@samp{*.o}.  However, if you use the value of @code{objects} in a target,
-prerequisite, or recipe, wildcard expansion will take place at that time.
-To set @code{objects} to the expansion, instead use:
+@samp{*.o}.  However, if you use the value of @code{objects} in a
+target or prerequisite, wildcard expansion will take place there.  If
+you use the value of @code{objects} in a recipe, the shell may perform
+wildcard expansion when the recipe runs.  To set @code{objects} to the
+expansion, instead use:
 
 @example
@@ -2403,6 +2426,7 @@
 
 When a prerequisite's name has the form @samp{-l@var{name}}, @code{make}
-handles it specially by searching for the file @file{lib@var{name}.so} in
-the current directory, in directories specified by matching @code{vpath}
+handles it specially by searching for the file @file{lib@var{name}.so},
+and, if it is not found, for the file @file{lib@var{name}.a} in the current
+directory, in directories specified by matching @code{vpath}
 search paths and the @code{VPATH} search path, and then in the
 directories @file{/lib}, @file{/usr/lib}, and @file{@var{prefix}/lib}
@@ -2410,7 +2434,4 @@
 @code{make} behave as if @var{prefix} is defined to be the root of the
 DJGPP installation tree).
-
-If that file is not found, then the file @file{lib@var{name}.a} is
-searched for, in the same directories as above.
 
 For example, if there is a @file{/usr/lib/libcurses.a} library on your
@@ -2435,6 +2456,5 @@
 @samp{-l@var{name}} is seen, @code{make} will replace the percent in
 each pattern in the list with @var{name} and perform the above directory
-searches using that library filename.  If no library is found, the next
-word in the list will be used.
+searches using each library filename.
 
 The default value for @code{.LIBPATTERNS} is @samp{lib%.so lib%.a},
@@ -2854,4 +2874,28 @@
 recipes in parallel (unless its makefile also contains this target).
 Any prerequisites on this target are ignored.
+
+@findex .ONESHELL
+@item .ONESHELL
+@cindex recipe execution, single invocation
+
+If @code{.ONESHELL} is mentioned as a target, then when a target is
+built all lines of the recipe will be given to a single invocation of
+the shell rather than each line being invoked separately
+(@pxref{Execution, ,Recipe Execution}).
+
+@findex .POSIX
+@item .POSIX
+@cindex POSIX-conforming mode, setting
+
+If @code{.POSIX} is mentioned as a target, then the makefile will be
+parsed and run in POSIX-conforming mode.  This does @emph{not} mean
+that only POSIX-conforming makefiles will be accepted: all advanced
+GNU @code{make} features are still available.  Rather, this target
+causes @code{make} to behave as required by POSIX in those areas
+where @code{make}'s default behavior differs.
+
+In particular, if this target is mentioned then recipes will be
+invoked as if the shell had been passed the @code{-e} flag: the first
+failing command in a recipe will cause the recipe to fail immediately.
 @end table
 
@@ -3168,7 +3212,9 @@
 @cindex @code{::} rules (double-colon)
 
-@dfn{Double-colon} rules are rules written with @samp{::} instead of
-@samp{:} after the target names.  They are handled differently from
-ordinary rules when the same target appears in more than one rule.
+@dfn{Double-colon} rules are explicit rules written with @samp{::}
+instead of @samp{:} after the target names.  They are handled
+differently from ordinary rules when the same target appears in more
+than one rule.  Pattern rules with double-colons have an entirely
+different meaning (@pxref{Match-Anything Rules}).
 
 When a target appears in multiple rules, all the rules must be the same
@@ -3351,5 +3397,5 @@
 Users use many different shell programs, but recipes in makefiles are
 always interpreted by @file{/bin/sh} unless the makefile specifies
-otherwise.  @xref{Execution, ,Command Execution}.
+otherwise.  @xref{Execution, ,Recipe Execution}.
 
 @menu
@@ -3361,5 +3407,5 @@
 * Interrupts::                  What happens when a recipe is interrupted.
 * Recursion::                   Invoking @code{make} from makefiles.
-* Sequences::                   Defining canned recipes.
+* Canned Recipes::              Defining canned recipes.
 * Empty Recipes::               Defining useful, do-nothing recipes.
 @end menu
@@ -3379,5 +3425,5 @@
 
 Each line in the recipe must start with a tab (or the first character
-in the value of the @code{.CMDPREFIX} variable; @pxref{Special
+in the value of the @code{.RECIPEPREFIX} variable; @pxref{Special
 Variables}), except that the first recipe line may be attached to the
 target-and-prerequisites line with a semicolon in between.  @emph{Any}
@@ -3629,10 +3675,10 @@
 @cindex @code{--dry-run}
 @cindex @code{--recon}
-When @code{make} is given the flag @samp{-n} or @samp{--just-print}
-it only echoes recipes, it won't execute them.  @xref{Options Summary,
-,Summary of Options}.  In this case and only this case, even the
-recipe lines starting with @samp{@@} are printed.  This flag is useful for
-finding out which recipes @code{make} thinks are necessary without
-actually doing them.
+When @code{make} is given the flag @samp{-n} or @samp{--just-print} it
+only echoes most recipes, without executing them.  @xref{Options
+Summary, ,Summary of Options}.  In this case even the recipe lines
+starting with @samp{@@} are printed.  This flag is useful for finding
+out which recipes @code{make} thinks are necessary without actually
+doing them.
 
 @cindex @code{-s}
@@ -3654,7 +3700,8 @@
 
 When it is time to execute recipes to update a target, they are
-executed by invoking a new subshell for each line of the recipe.  (In
-practice, @code{make} may take shortcuts that do not affect the
-results.)
+executed by invoking a new subshell for each line of the recipe,
+unless the @code{.ONESHELL} special target is in effect
+(@pxref{One Shell, ,Using One Shell})  (In practice, @code{make} may
+take shortcuts that do not affect the results.)
 
 @cindex @code{cd} (shell command)
@@ -3684,17 +3731,124 @@
 
 @menu
+* One Shell::                   One shell for all lines in a recipe
 * Choosing the Shell::          How @code{make} chooses the shell used
                                   to run recipes.
 @end menu
 
-@node Choosing the Shell,  , Execution, Execution
+@node One Shell, Choosing the Shell, Execution, Execution
+@subsection Using One Shell
+@cindex recipe lines, single shell
+@cindex @code{.ONESHELL}, use of
+@findex .ONESHELL
+
+Sometimes you would prefer that all the lines in the recipe be passed
+to a single invocation of the shell.  There are generally two
+situations where this is useful: first, it can improve performance in
+makefiles where recipes consist of many command lines, by avoiding
+extra processes.  Second, you might want newlines to be included in
+your recipe command (for example perhaps you are using a very
+different interpreter as your @code{SHELL}).  If the @code{.ONESHELL}
+special target appears anywhere in the makefile then @emph{all}
+recipe lines for each target will be provided to a single invocation
+of the shell.  Newlines between recipe lines will be preserved.  For
+example:
+
+@example
+.ONESHELL:
+foo : bar/lose
+        cd $(@@D)
+        gobble $(@@F) > ../$@@
+@end example
+
+@noindent
+would now work as expected even though the commands are on different
+recipe lines.
+
+If @code{.ONESHELL} is provided, then only the first line of the
+recipe will be checked for the special prefix characters (@samp{@@},
+@samp{-}, and @samp{+}).  Subsequent lines will include the special
+characters in the recipe line when the @code{SHELL} is invoked.  If
+you want your recipe to start with one of these special characters
+you'll need to arrange for them to not be the first characters on the
+first line, perhaps by adding a comment or similar.  For example, this
+would be a syntax error in Perl because the first @samp{@@} is removed
+by make:
+
+@example
+.ONESHELL:
+SHELL = /usr/bin/perl
+.SHELLFLAGS = -e
+show :
+        @@f = qw(a b c);
+        print "@@f\n";
+@end example
+
+@noindent
+However, either of these alternatives would work properly:
+
+@example
+.ONESHELL:
+SHELL = /usr/bin/perl
+.SHELLFLAGS = -e
+show :
+        # Make sure "@@" is not the first character on the first line
+        @@f = qw(a b c);
+        print "@@f\n";
+@end example
+
+@noindent
+or
+
+@example
+.ONESHELL:
+SHELL = /usr/bin/perl
+.SHELLFLAGS = -e
+show :
+        my @@f = qw(a b c);
+        print "@@f\n";
+@end example
+
+As a special feature, if @code{SHELL} is determined to be a
+POSIX-style shell, the special prefix characters in ``internal''
+recipe lines will @emph{removed} before the recipe is processed.  This
+feature is intended to allow existing makefiles to add the
+@code{.ONESHELL} special target and still run properly without
+extensive modifications.  Since the special prefix characters are not
+legal at the beginning of a line in a POSIX shell script this is not a
+loss in functionality.  For example, this works as expected:
+
+@example
+.ONESHELL:
+foo : bar/lose
+        @@cd $(@@D)
+        @@gobble $(@@F) > ../$@@
+@end example
+
+Even with this special feature, however, makefiles with
+@code{.ONESHELL} will behave differently in ways that could be
+noticeable.  For example, normally if any line in the recipe fails,
+that causes the rule to fail and no more recipe lines are processed.
+Under @code{.ONESHELL} a failure of any but the final recipe line will
+not be noticed by @code{make}.  You can modify @code{.SHELLFLAGS} to
+add the @code{-e} option to the shell which will cause any failure
+anywhere in the command line to cause the shell to fail, but this
+could itself cause your recipe to behave differently.  Ultimately you
+may need to harden your recipe lines to allow them to work with
+@code{.ONESHELL}.
+
+@node Choosing the Shell,  , One Shell, Execution
 @subsection Choosing the Shell
 @cindex shell, choosing the
 @cindex @code{SHELL}, value of
+@cindex @code{.SHELLFLAGS}, value of
 
 @vindex SHELL
+@vindex .SHELLFLAGS
 The program used as the shell is taken from the variable @code{SHELL}.
 If this variable is not set in your makefile, the program
-@file{/bin/sh} is used as the shell.
+@file{/bin/sh} is used as the shell.  The argument(s) passed to the
+shell are taken from the variable @code{.SHELLFLAGS}.  The default
+value of @code{.SHELLFLAGS} is @code{-c} normally, or @code{-ec} in
+POSIX-conforming mode.
 
 @cindex environment, @code{SHELL} in
@@ -3786,4 +3940,7 @@
 on MS-DOS unaltered if you have e.g.@: @file{sh.exe} installed in some
 directory along your @code{PATH}.
+
+@vindex SHELL
+@vindex .SHELLFLAGS
 
 @node Parallel, Errors, Execution, Recipes
@@ -4014,5 +4171,5 @@
 times to prevent other sorts of trouble.
 
-@node Recursion, Sequences, Interrupts, Recipes
+@node Recursion, Canned Recipes, Interrupts, Recipes
 @section Recursive Use of @code{make}
 @cindex recursion
@@ -4360,5 +4517,5 @@
 ensure that there are only @samp{N} jobs running at the same time
 between them all.  Note that any job that is marked recursive
-(@pxref{Instead of Execution, ,Instead of Executing the Recipes})
+(@pxref{Instead of Execution, ,Instead of Executing Recipes})
 doesn't count against the total jobs (otherwise we could get @samp{N}
 sub-@code{make}s running and have no slots left over for any real work!)
@@ -4496,5 +4653,5 @@
 disable it.
 
-@node Sequences, Empty Recipes, Recursion, Recipes
+@node Canned Recipes, Empty Recipes, Recursion, Recipes
 @section Defining Canned Recipes
 @cindex canned recipes
@@ -4509,8 +4666,8 @@
 not conflict with other variable names.
 
-Here is an example of defining a canned recipes:
-
-@example
-define run-yacc
+Here is an example of defining a canned recipe:
+
+@example
+define run-yacc =
 yacc $(firstword $^)
 mv y.tab.c $@@
@@ -4526,5 +4683,5 @@
 parentheses, variable names, and so on, all become part of the value of the
 variable you are defining.
-@xref{Defining, ,Defining Variables Verbatim},
+@xref{Multi-Line, ,Defining Multi-Line Variables},
 for a complete explanation of @code{define}.
 
@@ -4567,5 +4724,5 @@
 
 @example
-define frobnicate
+define frobnicate =
 @@echo "frobnicating target $@@"
 frob-step-1 $< -o $@@-step-1
@@ -4590,5 +4747,5 @@
 (@xref{Echoing, ,Recipe Echoing}, for a full explanation of @samp{@@}.)
 
-@node Empty Recipes,  , Sequences, Recipes
+@node Empty Recipes,  , Canned Recipes, Recipes
 @section Using Empty Recipes
 @cindex empty recipes
@@ -4685,6 +4842,8 @@
 * Override Directive::          How to set a variable in the makefile even if
                                   the user has set it with a command argument.
-* Defining::                    An alternate way to set a variable
-                                  to a verbatim string.
+* Multi-Line::                  An alternate way to set a variable
+                                  to a multi-line string.
+* Undefine Directive::          How to undefine a variable so that it appears
+                                  as if it was never set.
 * Environment::                 Variable values can come from the environment.
 * Target-specific::             Variable values can be defined on a per-target
@@ -4692,4 +4851,5 @@
 * Pattern-specific::            Target-specific variable values can be applied
                                   to a group of targets that match a pattern.
+* Suppressing Inheritance::     Suppress inheritance of variables.
 * Special Variables::           Variables with special meaning or behavior.
 @end menu
@@ -4761,5 +4921,5 @@
 Variables of this sort are defined by lines using @samp{=}
 (@pxref{Setting, ,Setting Variables}) or by the @code{define} directive
-(@pxref{Defining, ,Defining Variables Verbatim}).  The value you specify
+(@pxref{Multi-Line, ,Defining Multi-Line Variables}).  The value you specify
 is installed verbatim; if it contains references to other variables,
 these references are expanded whenever this variable is substituted (in
@@ -5188,5 +5348,5 @@
 dir = foo
 $(dir)_sources := $(wildcard $(dir)/*.c)
-define $(dir)_print
+define $(dir)_print =
 lpr $($(dir)_sources)
 endef
@@ -5217,5 +5377,5 @@
 You can specify a value in the makefile, either
 with an assignment (@pxref{Setting, ,Setting Variables}) or with a
-verbatim definition (@pxref{Defining, ,Defining Variables Verbatim}).@refill
+verbatim definition (@pxref{Multi-Line, ,Defining Multi-Line Variables}).@refill
 
 @item
@@ -5425,5 +5585,5 @@
 value.
 
-@node Override Directive, Defining, Appending, Using Variables
+@node Override Directive, Multi-Line, Appending, Using Variables
 @section The @code{override} Directive
 @findex override
@@ -5458,4 +5618,9 @@
 @xref{Appending, ,Appending More Text to Variables}.
 
+Variable assignments marked with the @code{override} flag have a
+higher priority than all other assignments, except another
+@code{override}.  Subsequent assignments or appends to this variable
+which are not marked @code{override} will be ignored.
+
 The @code{override} directive was not invented for escalation in the war
 between makefiles and command arguments.  It was invented so you can alter
@@ -5475,5 +5640,5 @@
 
 @example
-override define foo
+override define foo =
 bar
 endef
@@ -5485,11 +5650,13 @@
 @end iftex
 @ifnottex
-@xref{Defining, ,Defining Variables Verbatim}.
+@xref{Multi-Line, ,Defining Multi-Line Variables}.
 @end ifnottex
 
-@node Defining, Environment, Override Directive, Using Variables
-@section Defining Variables Verbatim
+@node Multi-Line, Undefine Directive, Override Directive, Using Variables
+@section Defining Multi-Line Variables
 @findex define
 @findex endef
+@cindex multi-line variable definition
+@cindex variables, multi-line
 @cindex verbatim variable definition
 @cindex defining variables verbatim
@@ -5498,18 +5665,25 @@
 Another way to set the value of a variable is to use the @code{define}
 directive.  This directive has an unusual syntax which allows newline
-characters to be included in the value, which is convenient for defining
-both canned sequences of commands
-(@pxref{Sequences, ,Defining Canned Command Sequences}), and also
-sections of makefile syntax to use with @code{eval} (@pxref{Eval Function}).
-
-The @code{define} directive is followed on the same line by the name of the
-variable and nothing more.  The value to give the variable appears on the
-following lines.  The end of the value is marked by a line containing just
-the word @code{endef}.  Aside from this difference in syntax, @code{define}
-works just like @samp{=}: it creates a recursively-expanded variable
-(@pxref{Flavors, ,The Two Flavors of Variables}).
-The variable name may contain function and variable references, which
-are expanded when the directive is read to find the actual variable name
+characters to be included in the value, which is convenient for
+defining both canned sequences of commands (@pxref{Canned Recipes,
+,Defining Canned Recipes}), and also sections of makefile syntax to
+use with @code{eval} (@pxref{Eval Function}).@refill
+
+The @code{define} directive is followed on the same line by the name
+of the variable being defined and an (optional) assignment operator,
+and nothing more.  The value to give the variable appears on the
+following lines.  The end of the value is marked by a line containing
+just the word @code{endef}.  Aside from this difference in syntax,
+@code{define} works just like any other variable definition.  The
+variable name may contain function and variable references, which are
+expanded when the directive is read to find the actual variable name
 to use.
+
+You may omit the variable assignment operator if you prefer.  If
+omitted, @code{make} assumes it to be @samp{=} and creates a
+recursively-expanded variable (@pxref{Flavors, ,The Two Flavors of Variables}).
+When using a @samp{+=} operator, the value is appended to the previous
+value as with any other append operation: with a single space
+separating the old and new values.
 
 You may nest @code{define} directives: @code{make} will keep track of
@@ -5518,8 +5692,8 @@
 prefix character are considered part of a recipe, so any @code{define}
 or @code{endef} strings appearing on such a line will not be
-considered @code{make} operators.
-
-@example
-define two-lines
+considered @code{make} directives.
+
+@example
+define two-lines =
 echo foo
 echo $(bar)
@@ -5551,5 +5725,5 @@
 
 @example
-override define two-lines
+override define two-lines =
 foo
 $(bar)
@@ -5560,5 +5734,40 @@
 @xref{Override Directive, ,The @code{override} Directive}.
 
-@node Environment, Target-specific, Defining, Using Variables
+@node Undefine Directive, Environment, Multi-Line, Using Variables
+@section Undefining Variables
+@findex undefine
+@cindex undefining variable
+
+If you want to clear a variable, setting its value to empty is usually
+sufficient. Expanding such a variable will yield the same result (empty
+string) regardless of whether it was set or not. However, if you are
+using the @code{flavor} (@pxref{Flavor Function}) and
+@code{origin} (@pxref{Origin Function}) functions, there is a difference
+between a variable that was never set and a variable with an empty value.
+In such situations you may want to use the @code{undefine} directive to
+make a variable appear as if it was never set. For example:
+
+@example
+foo := foo
+bar = bar
+
+undefine foo
+undefine bar
+
+$(info $(origin foo))
+$(info $(flavor bar))
+@end example
+
+This example will print ``undefined'' for both variables.
+
+If you want to undefine a command-line variable definition, you can use
+the @code{override} directive together with @code{undefine}, similar to
+how this is done for variable definitions:
+
+@example
+override undefine CFLAGS
+@end example
+
+@node Environment, Target-specific, Undefine Directive, Using Variables
 @section Variables from the Environment
 
@@ -5626,17 +5835,7 @@
 @end example
 
-@noindent
-or like this:
-
-@example
-@var{target} @dots{} : override @var{variable-assignment}
-@end example
-
-@noindent
-or like this:
-
-@example
-@var{target} @dots{} : export @var{variable-assignment}
-@end example
+Target-specific variable assignments can be prefixed with any or all of the
+special keywords @code{export}, @code{override}, or @code{private};
+these apply their normal behavior to this instance of the variable only.
 
 Multiple @var{target} values create a target-specific variable value for
@@ -5684,5 +5883,5 @@
 ignore the target-specific values from any other targets.
 
-@node Pattern-specific, Special Variables, Target-specific, Using Variables
+@node Pattern-specific, Suppressing Inheritance, Target-specific, Using Variables
 @section Pattern-specific Variable Values
 @cindex pattern-specific variables
@@ -5693,10 +5892,5 @@
 @code{make} supports pattern-specific variable values.  In this form,
 the variable is defined for any target that matches the pattern
-specified.  If a target matches more than one pattern, all the
-matching pattern-specific variables are interpreted in the order in
-which they were defined in the makefile, and collected together into
-one set.  Variables defined in this way are searched after any
-target-specific variables defined explicitly for that target, and
-before target-specific variables defined for the parent target.
+specified.
 
 Set a pattern-specific variable value like this:
@@ -5705,13 +5899,4 @@
 @var{pattern} @dots{} : @var{variable-assignment}
 @end example
-
-@noindent
-or like this:
-
-@example
-@var{pattern} @dots{} : override @var{variable-assignment}
-@end example
-
-@noindent
 where @var{pattern} is a %-pattern.  As with target-specific variable
 values, multiple @var{pattern} values create a pattern-specific variable
@@ -5730,5 +5915,66 @@
 matching the pattern @code{%.o}.
 
-@node Special Variables,  , Pattern-specific, Using Variables
+If a target matches more than one pattern, the matching pattern-specific
+variables with longer stems are interpreted first. This results in more
+specific variables taking precedence over the more generic ones, for
+example:
+
+@example
+%.o: %.c
+        $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@@
+
+lib/%.o: CFLAGS := -fPIC -g
+%.o: CFLAGS := -g
+
+all: foo.o lib/bar.o
+@end example
+
+In this example the first definition of the @code{CFLAGS} variable
+will be used to update @file{lib/bar.o} even though the second one
+also applies to this target. Pattern-specific variables which result
+in the same stem length are considered in the order in which they
+were defined in the makefile.
+
+Pattern-specific variables are searched after any target-specific
+variables defined explicitly for that target, and before target-specific
+variables defined for the parent target.
+
+@node Suppressing Inheritance, Special Variables, Pattern-specific, Using Variables
+@section Suppressing Inheritance
+@findex private
+@cindex suppressing inheritance
+@cindex inheritance, suppressing
+
+As described in previous sections, @code{make} variables are inherited
+by prerequisites.  This capability allows you to modify the behavior
+of a prerequisite based on which targets caused it to be rebuilt.  For
+example, you might set a target-specific variable on a @code{debug}
+target, then running @samp{make debug} will cause that variable to be
+inherited by all prerequisites of @code{debug}, while just running
+@samp{make all} (for example) would not have that assignment.
+
+Sometimes, however, you may not want a variable to be inherited.  For
+these situations, @code{make} provides the @code{private} modifier.
+Although this modifier can be used with any variable assignment, it
+makes the most sense with target- and pattern-specific variables.  Any
+variable marked @code{private} will be visible to its local target but
+will not be inherited by prerequisites of that target.  A global
+variable marked @code{private} will be visible in the global scope but
+will not be inherited by any target, and hence will not be visible
+in any recipe.
+
+As an example, consider this makefile:
+@example
+EXTRA_CFLAGS =
+
+prog: private EXTRA_CFLAGS = -L/usr/local/lib
+prog: a.o b.o
+@end example
+
+Due to the @code{private} modifier, @code{a.o} and @code{b.o} will not
+inherit the @code{EXTRA_CFLAGS} variable assignment from the
+@code{progs} target.
+
+@node Special Variables,  , Suppressing Inheritance, Using Variables
 @comment  node-name,  next,  previous,  up
 @section Other Special Variables
@@ -5834,6 +6080,6 @@
 variable).  You should not set, modify, or export this variable.
 
-@vindex .CMDPREFIX @r{(change the recipe prefix character)}
-@item .CMDPREFIX
+@vindex .RECIPEPREFIX @r{(change the recipe prefix character)}
+@item .RECIPEPREFIX
 The first character of the value of this variable is used as the
 character make assumes is introducing a recipe line.  If the variable
@@ -5843,5 +6089,5 @@
 @example
 @group
-.CMDPREFIX = >
+.RECIPEPREFIX = >
 all:
 > @@echo Hello, world
@@ -5849,5 +6095,5 @@
 @end example
 
-The value of @code{.CMDPREFIX} can be changed multiple times; once set
+The value of @code{.RECIPEPREFIX} can be changed multiple times; once set
 it stays in effect for all rules parsed until it is modified.
 
@@ -7175,5 +7421,5 @@
 all: $(PROGRAMS)
 
-define PROGRAM_template
+define PROGRAM_template =
  $(1): $$($(1)_OBJS) $$($(1)_LIBS:%=-l%)
  ALL_OBJS   += $$($(1)_OBJS)
@@ -7228,12 +7474,13 @@
 @item environment
 
-if @var{variable} was defined as an environment variable and the
-@samp{-e} option is @emph{not} turned on (@pxref{Options Summary, ,Summary of Options}).
+if @var{variable} was inherited from the environment provided to
+@code{make}.
 
 @item environment override
 
-if @var{variable} was defined as an environment variable and the
-@w{@samp{-e}} option @emph{is} turned on (@pxref{Options Summary,
-,Summary of Options}).@refill
+if @var{variable} was inherited from the environment provided to
+@code{make}, and is overriding a setting for @var{variable} in the
+makefile as a result of the @w{@samp{-e}} option (@pxref{Options
+Summary, ,Summary of Options}).@refill
 
 @item file
@@ -7476,5 +7723,5 @@
 The exit status is one if you use the @samp{-q} flag and @code{make}
 determines that some target is not already up to date.
-@xref{Instead of Execution, ,Instead of Executing the Recipes}.
+@xref{Instead of Execution, ,Instead of Executing Recipes}.
 @end table
 
@@ -7653,5 +7900,5 @@
 
 @node Instead of Execution, Avoiding Compilation, Goals, Running
-@section Instead of Executing the Recipes
+@section Instead of Executing Recipes
 @cindex execution, instead of
 @cindex recipes, instead of executing
@@ -7673,5 +7920,6 @@
 
 ``No-op''.  The activity is to print what recipe would be used to make
-the targets up to date, but not actually execute it.
+the targets up to date, but not actually execute it.  Some recipes are
+still executed, even with this flag (@pxref{MAKE Variable, ,How the @code{MAKE} Variable Works}).
 
 @item -t
@@ -7715,5 +7963,5 @@
 
 With the @samp{-n} flag, @code{make} prints the recipe that it would
-normally execute but does not execute it.
+normally execute but usually does not execute it.
 
 With the @samp{-t} flag, @code{make} ignores the recipes in the rules
@@ -7741,4 +7989,9 @@
 not run unless they too begin with @samp{+} or contain @samp{$(MAKE)} or
 @samp{$@{MAKE@}} (@xref{MAKE Variable, ,How the @code{MAKE} Variable Works}.)
+
+@cindex phony targets and recipe execution
+The @samp{-t} flag prevents phony targets (@pxref{Phony Targets}) from
+being updated, unless there are recipe lines beginning with @samp{+}
+or containing @samp{$(MAKE)} or @samp{$@{MAKE@}}.
 
 The @samp{-W} flag provides two features:
@@ -8007,4 +8260,13 @@
 @xref{Environment, ,Variables from the Environment}.
 
+@item --eval=@var{string}
+@cindex @code{--eval}
+@c Extra blank line here makes the table look better.
+
+Evaluate @var{string} as makefile syntax.  This is a command-line
+version of the @code{eval} function (@pxref{Eval Function}).  The
+evaluation is performed after the default rules and variables have
+been defined, but before any makefiles are read.
+
 @item -f @var{file}
 @cindex @code{-f}
@@ -8090,6 +8352,7 @@
 @c Extra blank line here makes the table look better.
 
-Print the recipe that would be executed, but do not execute it.
-@xref{Instead of Execution, ,Instead of Executing the Recipes}.
+Print the recipe that would be executed, but do not execute it (except
+in certain circumstances).
+@xref{Instead of Execution, ,Instead of Executing Recipes}.
 
 @item -o @var{file}
@@ -8128,5 +8391,5 @@
 return an exit status that is zero if the specified targets are already
 up to date, one if any remaking is required, or two if an error is
-encountered.  @xref{Instead of Execution, ,Instead of Executing the
+encountered.  @xref{Instead of Execution, ,Instead of Executing
 Recipes}.@refill
 
@@ -8190,5 +8453,5 @@
 instead of running their recipes.  This is used to pretend that the
 recipes were done, in order to fool future invocations of
-@code{make}.  @xref{Instead of Execution, ,Instead of Executing the Recipes}.
+@code{make}.  @xref{Instead of Execution, ,Instead of Executing Recipes}.
 
 @item -v
@@ -8231,5 +8494,5 @@
 @code{make}, except that the modification time is changed only in the
 imagination of @code{make}.
-@xref{Instead of Execution, ,Instead of Executing the Recipes}.
+@xref{Instead of Execution, ,Instead of Executing Recipes}.
 
 @item --warn-undefined-variables
@@ -8421,5 +8684,5 @@
 @pindex .c
 @file{@var{n}.o} is made automatically from @file{@var{n}.c} with
-a recipe of the form @samp{$(CC) -c $(CPPFLAGS) $(CFLAGS)}.@refill
+a recipe of the form @samp{$(CC) $(CPPFLAGS) $(CFLAGS) -c}.@refill
 
 @item Compiling C++ programs
@@ -8431,5 +8694,5 @@
 @file{@var{n}.o} is made automatically from @file{@var{n}.cc},
 @file{@var{n}.cpp}, or @file{@var{n}.C} with a recipe of the form
-@samp{$(CXX) -c $(CPPFLAGS) $(CXXFLAGS)}.  We encourage you to use the
+@samp{$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c}.  We encourage you to use the
 suffix @samp{.cc} for C++ source files instead of @samp{.C}.@refill
 
@@ -8439,5 +8702,5 @@
 @pindex .p
 @file{@var{n}.o} is made automatically from @file{@var{n}.p}
-with the recipe @samp{$(PC) -c $(PFLAGS)}.@refill
+with the recipe @samp{$(PC) $(PFLAGS) -c}.@refill
 
 @item Compiling Fortran and Ratfor programs
@@ -8454,9 +8717,9 @@
 @table @samp
 @item .f
-@samp{$(FC) -c $(FFLAGS)}.
+@samp{$(FC) $(FFLAGS) -c}.
 @item .F
-@samp{$(FC) -c $(FFLAGS) $(CPPFLAGS)}.
+@samp{$(FC) $(FFLAGS) $(CPPFLAGS) -c}.
 @item .r
-@samp{$(FC) -c $(FFLAGS) $(RFLAGS)}.
+@samp{$(FC) $(FFLAGS) $(RFLAGS) -c}.
 @end table
 
@@ -8469,7 +8732,7 @@
 @table @samp
 @item .F
-@samp{$(FC) -F $(CPPFLAGS) $(FFLAGS)}.
+@samp{$(FC) $(CPPFLAGS) $(FFLAGS) -F}.
 @item .r
-@samp{$(FC) -F $(FFLAGS) $(RFLAGS)}.
+@samp{$(FC) $(FFLAGS) $(RFLAGS) -F}.
 @end table
 
@@ -9066,4 +9329,8 @@
 pattern.  @xref{Last Resort}.
 
+More than one pattern rule may match a target.  In this case
+@code{make} will choose the ``best fit'' rule.  @xref{Pattern Match,
+,How Patterns Match}.
+
 @c !!! The end of of this paragraph should be rewritten.  --bob
 Pattern rules may have more than one target.  Unlike normal rules,
@@ -9081,14 +9348,4 @@
 @cindex target, multiple in pattern rule
 
-The order in which pattern rules appear in the makefile is important
-since this is the order in which they are considered.
-Of equally applicable
-rules, only the first one found is used.  The rules you write take precedence
-over those that are built in.  Note however, that a rule whose
-prerequisites actually exist or are mentioned always takes priority over a
-rule with prerequisites that must be made by chaining other implicit rules.
-@cindex pattern rules, order of
-@cindex order of pattern rules
-
 @node Pattern Examples, Automatic Variables, Pattern Intro, Pattern Rules
 @subsection Pattern Rule Examples
@@ -9403,4 +9660,48 @@
 @file{src/car}.@refill
 
+@cindex pattern rules, order of
+@cindex order of pattern rules
+A pattern rule can be used to build a given file only if there is a
+target pattern that matches the file name, @emph{and} all
+prerequisites in that rule either exist or can be built.  The rules
+you write take precedence over those that are built in. Note however,
+that a rule whose prerequisites actually exist or are mentioned always
+takes priority over a rule with prerequisites that must be made by
+chaining other implicit rules.
+
+@cindex stem, shortest
+It is possible that more than one pattern rule will meet these
+criteria.  In that case, @code{make} will choose the rule with the
+shortest stem (that is, the pattern that matches most specifically).
+If more than one pattern rule has the shortest stem, @code{make} will
+choose the first one found in the makefile.
+
+This algorithm results in more specific rules being preferred over
+more generic ones; for example:
+
+@example
+%.o: %.c
+        $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@@
+
+%.o : %.f
+        $(COMPILE.F) $(OUTPUT_OPTION) $<
+
+lib/%.o: lib/%.c
+        $(CC) -fPIC -c $(CFLAGS) $(CPPFLAGS) $< -o $@@
+@end example
+
+Given these rules and asked to build @file{bar.o} where both
+@file{bar.c} and @file{bar.f} exist, @code{make} will choose the first
+rule and compile @file{bar.c} into @file{bar.o}.  In the same
+situation where @file{bar.c} does not exist, then @code{make} will
+choose the second rule and compile @file{bar.f} into @file{bar.o}.
+
+If @code{make} is asked to build @file{lib/bar.o} and both
+@file{lib/bar.c} and @file{lib/bar.f} exist, then the third rule will
+be chosen since the stem for this rule (@samp{bar}) is shorter than
+the stem for the first rule (@samp{lib/bar}).  If @file{lib/bar.c}
+does not exist then the third rule is not eligible and the second rule
+will be used, even though the stem is longer.
+
 @node Match-Anything Rules, Canceling Rules, Pattern Match, Pattern Rules
 @subsection Match-Anything Pattern Rules
@@ -10084,5 +10385,5 @@
 The ``what if'' flag (@samp{-W} in GNU @code{make}) was (as far as we know)
 invented by Andrew Hume in @code{mk}.
-@xref{Instead of Execution, ,Instead of Executing the Recipes}.
+@xref{Instead of Execution, ,Instead of Executing Recipes}.
 
 @item
@@ -10102,5 +10403,5 @@
 @item
 The special significance of @samp{+} characters preceding recipe lines
-(@pxref{Instead of Execution, ,Instead of Executing the Recipes}) is
+(@pxref{Instead of Execution, ,Instead of Executing Recipes}) is
 mandated by @cite{IEEE Standard 1003.2-1992} (POSIX.2).
 
@@ -10147,5 +10448,5 @@
 @item
 Make verbatim variable definitions with @code{define}.
-@xref{Defining, ,Defining Variables Verbatim}.
+@xref{Multi-Line, ,Defining Multi-Line Variables}.
 
 @item
@@ -10355,8 +10656,15 @@
 @table @code
 @item define @var{variable}
+@itemx define @var{variable} =
+@itemx define @var{variable} :=
+@itemx define @var{variable} +=
+@itemx define @var{variable} ?=
 @itemx endef
-
-Define a multi-line, recursively-expanded variable.@*
-@xref{Sequences}.
+Define multi-line variables.@*
+@xref{Multi-Line}.
+
+@item undefine @var{variable}
+Undefining variables.@*
+@xref{Undefine Directive}.
 
 @item ifdef @var{variable}
@@ -10370,5 +10678,4 @@
 @itemx else
 @itemx endif
-
 Conditionally evaluate part of the makefile.@*
 @xref{Conditionals}.
@@ -10377,15 +10684,8 @@
 @itemx -include @var{file}
 @itemx sinclude @var{file}
-
 Include another makefile.@*
 @xref{Include, ,Including Other Makefiles}.
 
-@item override @var{variable} = @var{value}
-@itemx override @var{variable} := @var{value}
-@itemx override @var{variable} += @var{value}
-@itemx override @var{variable} ?= @var{value}
-@itemx override define @var{variable}
-@itemx endef
-
+@item override @var{variable-assignment}
 Define a variable, overriding any previous definition, even one from
 the command line.@*
@@ -10393,17 +10693,17 @@
 
 @item export
-
 Tell @code{make} to export all variables to child processes by default.@*
 @xref{Variables/Recursion, , Communicating Variables to a Sub-@code{make}}.
 
 @item export @var{variable}
-@itemx export @var{variable} = @var{value}
-@itemx export @var{variable} := @var{value}
-@itemx export @var{variable} += @var{value}
-@itemx export @var{variable} ?= @var{value}
+@itemx export @var{variable-assignment}
 @itemx unexport @var{variable}
 Tell @code{make} whether or not to export a particular variable to child
 processes.@*
 @xref{Variables/Recursion, , Communicating Variables to a Sub-@code{make}}.
+
+@item private @var{variable-assignment}
+Do not allow this variable assignment to be inherited by prerequisites.@*
+@xref{Suppressing Inheritance}.
 
 @item vpath @var{pattern} @var{path}
@@ -10515,5 +10815,4 @@
 
 @item $(error @var{text}@dots{})
-
 When this function is evaluated, @code{make} generates a fatal error
 with the message @var{text}.@*
@@ -10521,5 +10820,4 @@
 
 @item $(warning @var{text}@dots{})
-
 When this function is evaluated, @code{make} generates a warning with
 the message @var{text}.@*
@@ -10527,10 +10825,8 @@
 
 @item $(shell @var{command})
-
 Execute a shell command and return its output.@*
 @xref{Shell Function, , The @code{shell} Function}.
 
 @item $(origin @var{variable})
-
 Return a string describing how the @code{make} variable @var{variable} was
 defined.@*
@@ -10538,5 +10834,4 @@
 
 @item $(flavor @var{variable})
-
 Return a string describing the flavor of the @code{make} variable
 @var{variable}.@*
@@ -10544,11 +10839,28 @@
 
 @item $(foreach @var{var},@var{words},@var{text})
-
 Evaluate @var{text} with @var{var} bound to each word in @var{words},
 and concatenate the results.@*
 @xref{Foreach Function, ,The @code{foreach} Function}.
 
+@item $(if @var{condition},@var{then-part}[,@var{else-part}])
+Evaluate the condition @var{condition}; if it's non-empty substitute
+the expansion of the @var{then-part} otherwise substitute the
+expansion of the @var{else-part}.@*
+@xref{Conditional Functions, ,Functions for Conditionals}.
+
+@item $(or @var{condition1}[,@var{condition2}[,@var{condition3}@dots{}]])
+Evaluate each condition @var{conditionN} one at a time; substitute the
+first non-empty expansion.  If all expansions are empty, substitute
+the empty string.@*
+@xref{Conditional Functions, ,Functions for Conditionals}.
+
+@item $(and @var{condition1}[,@var{condition2}[,@var{condition3}@dots{}]])
+Evaluate each condition @var{conditionN} one at a time; if any
+expansion results in the empty string substitute the empty string.  If
+all expansions result in a non-empty string, substitute the expansion
+of the last @var{condition}.@*
+@xref{Conditional Functions, ,Functions for Conditionals}.
+
 @item $(call @var{var},@var{param},@dots{})
-
 Evaluate the variable @var{var} replacing any references to @code{$(1)},
 @code{$(2)} with the first, second, etc.@: @var{param} values.@*
@@ -10556,5 +10868,4 @@
 
 @item $(eval @var{text})
-
 Evaluate @var{text} then read the results as makefile commands.
 Expands to the empty string.@*
@@ -10562,5 +10873,4 @@
 
 @item $(value @var{var})
-
 Evaluates to the contents of the variable @var{var}, with no expansion
 performed on it.@*
@@ -10747,5 +11057,5 @@
 second form of the error above.  Remember that every line in the
 recipe must begin with a tab character (unless you set
-@code{.CMDPREFIX}; @pxref{Special Variables}).  Eight spaces do not
+@code{.RECIPEPREFIX}; @pxref{Special Variables}).  Eight spaces do not
 count.  @xref{Rule Syntax}.
 
@@ -11007,16 +11317,14 @@
 #### End of system configuration section. ####
 
-SRC1 =  tar.c create.c extract.c buffer.c \
-        getoldopt.c update.c gnu.c mangle.c
-SRC2 =  version.c list.c names.c diffarch.c \
-        port.c wildmat.c getopt.c
-SRC3 =  getopt1.c regex.c getdate.y
-SRCS =  $(SRC1) $(SRC2) $(SRC3)
-OBJ1 =  tar.o create.o extract.o buffer.o \
-        getoldopt.o update.o gnu.o mangle.o
-OBJ2 =  version.o list.o names.o diffarch.o \
-        port.o wildmat.o getopt.o
-OBJ3 =  getopt1.o regex.o getdate.o $(RTAPELIB)
-OBJS =  $(OBJ1) $(OBJ2) $(OBJ3)
+@group
+SRCS_C  = tar.c create.c extract.c buffer.c   \
+          getoldopt.c update.c gnu.c mangle.c \
+          version.c list.c names.c diffarch.c \
+          port.c wildmat.c getopt.c getopt1.c \
+          regex.c
+SRCS_Y  = getdate.y
+SRCS    = $(SRCS_C) $(SRCS_Y)
+OBJS    = $(SRCS_C:.c=.o) $(SRCS_Y:.y=.o) $(RTAPELIB)
+@end group
 @group
 AUX =   README COPYING ChangeLog Makefile.in  \
Index: /trunk/src/kmk/dosbuild.bat
===================================================================
--- /trunk/src/kmk/dosbuild.bat	(revision 2590)
+++ /trunk/src/kmk/dosbuild.bat	(revision 2591)
@@ -1,5 +1,5 @@
 @echo off
-rem Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
-rem Free Software Foundation, Inc.
+rem Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
+rem 2008, 2009, 2010 Free Software Foundation, Inc.
 rem This file is part of GNU Make.
 rem
Index: /trunk/src/kmk/electric.c
===================================================================
--- /trunk/src/kmk/electric.c	(revision 2590)
+++ /trunk/src/kmk/electric.c	(revision 2591)
@@ -159,9 +159,9 @@
 
 void *
-xcalloc (size_t size, size_t items)
+xcalloc (unsigned size)
 {
     void *result;
-    result = xmalloc (size * items);
-    return memset (result, 0, size * items);
+    result = xmalloc (size);
+    return memset (result, 0, size);
 }
 
Index: /trunk/src/kmk/electric.h
===================================================================
--- /trunk/src/kmk/electric.h	(revision 2590)
+++ /trunk/src/kmk/electric.h	(revision 2591)
@@ -33,5 +33,5 @@
 
 void xfree (void *);
-void *xcalloc (size_t, size_t);
+void *xcalloc (unsigned int);
 void *xmalloc (unsigned int);
 void *xrealloc (void *, unsigned int);
@@ -39,5 +39,5 @@
 
 #define free(a)         xfree(a)
-#define calloc(a,b)     xcalloc((a),(b))
+#define calloc(a,b)     xcalloc((a) * (b))
 #define malloc(a)       xmalloc(a)
 #define realloc(a,b)    xrealloc((a),(b))
Index: /trunk/src/kmk/expand.c
===================================================================
--- /trunk/src/kmk/expand.c	(revision 2590)
+++ /trunk/src/kmk/expand.c	(revision 2591)
@@ -1,6 +1,6 @@
 /* Variable expansion functions 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 Free Software
-Foundation, Inc.
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
@@ -539,6 +539,6 @@
       if (*p == '\0')
 	break;
-      else
-	++p;
+
+      ++p;
     }
 
@@ -845,5 +845,6 @@
 {
 #ifndef CONFIG_WITH_VALUE_LENGTH
-  char *tmp;
+  char *tmp, *alloc = NULL;
+  char *r;
 #endif
 
@@ -855,9 +856,18 @@
     return allocated_variable_expand (str);
 
-  tmp = alloca (end - str + 1);
+  if (end - str + 1 > 1000)
+    tmp = alloc = xmalloc (end - str + 1);
+  else
+    tmp = alloca (end - str + 1);
+
   memcpy (tmp, str, end - str);
   tmp[end - str] = '\0';
 
-  return allocated_variable_expand (tmp);
+  r = allocated_variable_expand (tmp);
+
+  if (alloc)
+    free (alloc);
+
+  return r;
 #else  /* CONFIG_WITH_VALUE_LENGTH */
   if (!end)
@@ -1103,9 +1113,4 @@
   value = variable_expand_for_file (line, file);
 
-#if 0
-  /* Waste a little memory and save time.  */
-  value = xrealloc (value, strlen (value))
-#endif
-
   variable_buffer = obuf;
   variable_buffer_length = olen;
Index: /trunk/src/kmk/file.c
===================================================================
--- /trunk/src/kmk/file.c	(revision 2590)
+++ /trunk/src/kmk/file.c	(revision 2591)
@@ -1,6 +1,6 @@
 /* Target file management 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 Free Software
-Foundation, Inc.
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
@@ -119,8 +119,18 @@
       name += 2;
 #endif
-  while (name[0] == '.' && name[1] == '/' && name[2] != '\0')
+  while (name[0] == '.'
+#ifdef HAVE_DOS_PATHS
+	 && (name[1] == '/' || name[1] == '\\')
+#else
+	 && name[1] == '/'
+#endif
+	 && name[2] != '\0')
     {
       name += 2;
-      while (*name == '/')
+      while (*name == '/'
+#ifdef HAVE_DOS_PATHS
+	     || *name == '\\'
+#endif
+	     )
 	/* Skip following slashes: ".//foo" is "foo", not "/foo".  */
 	++name;
@@ -230,6 +240,5 @@
 
 #ifndef CONFIG_WITH_ALLOC_CACHES
-  new = xmalloc (sizeof (struct file));
-  memset (new, '\0', sizeof (struct file));
+  new = xcalloc (sizeof (struct file));
 #else
   new = alloccache_calloc (&file_cache);
@@ -511,15 +520,11 @@
 
 
+/* Given a string containing prerequisites (fully expanded), break it up into
+   a struct dep list.  Enter each of these prereqs into the file database.
+ */
 struct dep *
-parse_prereqs (char *p)
-{
-#ifndef CONFIG_WITH_ALLOC_CACHES
-  struct dep *new = (struct dep *)
-    multi_glob (parse_file_seq (&p, '|', sizeof (struct dep), 1),
-                sizeof (struct dep));
-#else
-  struct dep *new = (struct dep *)
-    multi_glob (parse_file_seq (&p, '|', &dep_cache, 1), &dep_cache);
-#endif
+split_prereqs (char *p)
+{
+  struct dep *new = PARSE_FILE_SEQ (&p, struct dep, '|', NULL, 0);
 
   if (*p)
@@ -530,12 +535,5 @@
 
       ++p;
-#ifndef CONFIG_WITH_ALLOC_CACHES
-      ood = (struct dep *)
-        multi_glob (parse_file_seq (&p, '\0', sizeof (struct dep), 1),
-                    sizeof (struct dep));
-#else
-      ood = (struct dep *)
-        multi_glob (parse_file_seq (&p, '\0', &dep_cache, 1), &dep_cache);
-#endif
+      ood = PARSE_FILE_SEQ (&p, struct dep, '\0', NULL, 0);
 
       if (! new)
@@ -556,4 +554,83 @@
 }
 
+/* Given a list of prerequisites, enter them into the file database.
+   If STEM is set then first expand patterns using STEM.  */
+struct dep *
+enter_prereqs (struct dep *deps, const char *stem)
+{
+  struct dep *d1;
+
+  if (deps == 0)
+    return 0;
+
+  /* If we have a stem, expand the %'s.  We use patsubst_expand to translate
+     the prerequisites' patterns into plain prerequisite names.  */
+  if (stem)
+    {
+      const char *pattern = "%";
+      char *buffer = variable_expand ("");
+      struct dep *dp = deps, *dl = 0;
+
+      while (dp != 0)
+        {
+          char *percent;
+          int nl = strlen (dp->name) + 1;
+          char *nm = alloca (nl);
+          memcpy (nm, dp->name, nl);
+          percent = find_percent (nm);
+          if (percent)
+            {
+              char *o;
+
+              /* We have to handle empty stems specially, because that
+                 would be equivalent to $(patsubst %,dp->name,) which
+                 will always be empty.  */
+              if (stem[0] == '\0')
+                {
+                  memmove (percent, percent+1, strlen (percent));
+                  o = variable_buffer_output (buffer, nm, strlen (nm) + 1);
+                }
+              else
+                o = patsubst_expand_pat (buffer, stem, pattern, nm,
+                                         pattern+1, percent+1);
+
+              /* If the name expanded to the empty string, ignore it.  */
+              if (buffer[0] == '\0')
+                {
+                  struct dep *df = dp;
+                  if (dp == deps)
+                    dp = deps = deps->next;
+                  else
+                    dp = dl->next = dp->next;
+                  free_dep (df);
+                  continue;
+                }
+
+              /* Save the name.  */
+              dp->name = strcache_add_len (buffer, o - buffer);
+            }
+          dp->stem = stem;
+          dp->staticpattern = 1;
+          dl = dp;
+          dp = dp->next;
+        }
+    }
+
+  /* Enter them as files, unless they need a 2nd expansion.  */
+  for (d1 = deps; d1 != 0; d1 = d1->next)
+    {
+      if (d1->need_2nd_expansion)
+        continue;
+
+      d1->file = lookup_file (d1->name);
+      if (d1->file == 0)
+        d1->file = enter_file (d1->name);
+      d1->staticpattern = 0;
+      d1->name = 0;
+    }
+
+  return deps;
+}
+
 /* Set the intermediate flag.  */
 
@@ -570,22 +647,27 @@
 {
   struct dep *d;
-  struct dep *old = f->deps;
+  struct dep **dp;
   const char *file_stem = f->stem;
-  unsigned int last_dep_has_cmds = f->updating;
   int initialized = 0;
 
   f->updating = 0;
-  f->deps = 0;
-
-  for (d = old; d != 0; d = d->next)
-    {
-      struct dep *new, *d1;
+
+  /* Walk through the dependencies.  For any dependency that needs 2nd
+     expansion, expand it then insert the result into the list.  */
+  dp = &f->deps;
+  d = f->deps;
+  while (d != 0)
+    {
       char *p;
-#ifdef CONFIG_WITH_STRCACHE2
-      unsigned int len;
-#endif
-
-      if (! d->name)
-        continue;
+      struct dep *new, *next;
+      char *name = (char *)d->name;
+
+      if (! d->name || ! d->need_2nd_expansion)
+        {
+          /* This one is all set already.  */
+          dp = &d->next;
+          d = d->next;
+          continue;
+        }
 
 #ifdef CONFIG_WITH_INCLUDEDEP
@@ -597,5 +679,5 @@
       if (d->includedep)
         {
-          new = d1 = alloc_dep();
+          struct dep *d1 = new = alloc_dep();
           d1->staticpattern = 0;
           d1->need_2nd_expansion = 0;
@@ -618,188 +700,83 @@
         }
       else
+      {
+#endif /* CONFIG_WITH_INCLUDEDEP */
+
+      /* If it's from a static pattern rule, convert the patterns into
+         "$*" so they'll expand properly.  */
+      if (d->staticpattern)
         {
-#endif
-
-      /* Create the dependency list.
-         If we're not doing 2nd expansion, then it's just the name.  We will
-         still need to massage it though.  */
-      if (! d->need_2nd_expansion)
+          char *o;
+          d->name = o = variable_expand ("");
+          o = subst_expand (o, name, "%", "$*", 1, 2, 0);
+          *o = '\0';
+          free (name);
+#ifndef CONFIG_WITH_STRCACHE2
+          d->name = name = xstrdup (variable_buffer); /* bird not d->name, can be reallocated */
+#else
+          d->name = strcache2_add (&file_strcache, variable_buffer, o - variable_buffer);
+#endif
+          d->staticpattern = 0;
+        }
+
+      /* We're going to do second expansion so initialize file variables for
+         the file. Since the stem for static pattern rules comes from
+         individual dep lines, we will temporarily set f->stem to d->stem.  */
+      if (!initialized)
         {
-          p = variable_expand ("");
-#ifndef CONFIG_WITH_STRCACHE2
-          variable_buffer_output (p, d->name, strlen (d->name) + 1);
+          initialize_file_variables (f, 0);
+          initialized = 1;
+        }
+
+      if (d->stem != 0)
+        f->stem = d->stem;
+
+#if defined(CONFIG_WITH_COMMANDS_FUNC) || defined (CONFIG_WITH_DOT_MUST_MAKE)
+      set_file_variables (f, 0 /* real call, f->deps == 0 so we're ok. */);
 #else
-          len = strcache2_get_len (&file_strcache, d->name);
-          variable_buffer_output (p, d->name, len + 1);
-#endif
-          p = variable_buffer;
+      set_file_variables (f);
+#endif
+
+      p = variable_expand_for_file (d->name, f);
+
+      if (d->stem != 0)
+        f->stem = file_stem;
+
+      /* At this point we don't need the name anymore: free it.  */
+      free (name);
+
+      /* Parse the prerequisites and enter them into the file database.  */
+      new = enter_prereqs (split_prereqs (p), d->stem);
+
+      /* If there were no prereqs here (blank!) then throw this one out.  */
+      if (new == 0)
+        {
+          *dp = d->next;
+          free_dep (d);
+          d = *dp;
+          continue;
         }
-      else
-        {
-          /* If it's from a static pattern rule, convert the patterns into
-             "$*" so they'll expand properly.  */
-          if (d->staticpattern)
-            {
-              char *o;
-              char *buffer = variable_expand ("");
-
-              o = subst_expand (buffer, d->name, "%", "$*", 1, 2, 0);
-              buffer = variable_buffer; /* bird - variable_buffer may have been reallocated. */
-
-              d->name = strcache_add_len (variable_buffer,
-                                          o - variable_buffer);
-              d->staticpattern = 0; /* Clear staticpattern so that we don't
-                                       re-expand %s below. */
-            }
-
-          /* We are going to do second expansion so initialize file variables
-             for the file. Since the stem for static pattern rules comes from
-             individual dep lines, we will temporarily set f->stem to d->stem.
-          */
-          if (!initialized)
-            {
-              initialize_file_variables (f, 0);
-              initialized = 1;
-            }
-
-          if (d->stem != 0)
-            f->stem = d->stem;
-
-#if defined(CONFIG_WITH_COMMANDS_FUNC) || defined (CONFIG_WITH_DOT_MUST_MAKE)
-          set_file_variables (f, 0 /* real call, f->deps == 0 so we're ok. */);
-#else
-          set_file_variables (f);
-#endif
-
-#if !defined (CONFIG_WITH_VALUE_LENGTH) || !defined (CONFIG_WITH_STRCACHE2)
-          p = variable_expand_for_file (d->name, f);
-#else
-          len = strcache2_get_len (&file_strcache, d->name);
-          p = variable_expand_for_file_2 (NULL, d->name, len, f, &len);
-#endif
-
-          if (d->stem != 0)
-            f->stem = file_stem;
-        }
-
-      /* Parse the prerequisites.  */
-      new = parse_prereqs (p);
-
-      /* If this dep list was from a static pattern rule, expand the %s.  We
-         use patsubst_expand to translate the prerequisites' patterns into
-         plain prerequisite names.  */
-      if (new && d->staticpattern)
-        {
-          const char *pattern = "%";
-          char *buffer = variable_expand ("");
-          struct dep *dp = new, *dl = 0;
-
-          while (dp != 0)
-            {
-              char *percent;
-#ifndef KMK
-              int nl = strlen (dp->name) + 1;
-              char *nm = alloca (nl);
-              memcpy (nm, dp->name, nl);
-              percent = find_percent (nm);
-#else  /* KMK - don't make a stack copy unless it's actually required! */
-              unsigned int nl = strcache2_get_len (&file_strcache, dp->name);
-              char *nm;
-              percent = memchr (dp->name, '%', nl);
-              if (percent)
-                {
-                  nm = alloca (nl + 1);
-                  memcpy (nm, dp->name, nl + 1);
-                  percent = find_percent (nm);
-                }
-#endif /* KMK */
-              if (percent)
-                {
-                  char *o;
-
-                  /* We have to handle empty stems specially, because that
-                     would be equivalent to $(patsubst %,dp->name,) which
-                     will always be empty.  */
-                  if (d->stem[0] == '\0')
-                    {
-                      memmove (percent, percent+1, strlen (percent));
-                      o = variable_buffer_output (buffer, nm, strlen (nm) + 1);
-                    }
-                  else
-                    {
-                      o = patsubst_expand_pat (buffer, d->stem, pattern, nm,
-                                               pattern+1, percent+1);
-                      o = variable_buffer_output (o, "", 1); /* bird fix - patsubst_expand_pat doesn't terminate,
-                                                                the if case does and strcache would appreciate it. */
-                    }
-                  buffer = variable_buffer; /* bird fix - variable_buffer may have been reallocated. */
-
-
-                  /* If the name expanded to the empty string, ignore it.  */
-                  if (buffer[0] == '\0')
-                    {
-                      struct dep *df = dp;
-                      if (dp == new)
-                        dp = new = new->next;
-                      else
-                        dp = dl->next = dp->next;
-                      free_dep (df);
-                      continue;
-                    }
-
-                  /* Save the name.  */
-                  dp->name = strcache_add_len (buffer, o - buffer - 1); /* bird fix - don't include the terminator. */
-                }
-              dl = dp;
-              dp = dp->next;
-            }
-        }
-
-      /* Enter them as files. */
-      for (d1 = new; d1 != 0; d1 = d1->next)
-        {
-          d1->file = lookup_file (d1->name);
-          if (d1->file == 0)
-            d1->file = enter_file (d1->name);
-          d1->name = 0;
-          d1->staticpattern = 0;
-          d1->need_2nd_expansion = 0;
-        }
 
 #ifdef CONFIG_WITH_INCLUDEDEP
-        }
-#endif
-
-      /* Add newly parsed deps to f->deps. If this is the last dependency
-         line and this target has commands then put it in front so the
-         last dependency line (the one with commands) ends up being the
-         first. This is important because people expect $< to hold first
-         prerequisite from the rule with commands. If it is not the last
-         dependency line or the rule does not have commands then link it
-         at the end so it appears in makefile order.  */
-
-      if (new != 0)
-        {
-          if (d->next == 0 && last_dep_has_cmds)
-            {
-              struct dep **d_ptr;
-              for (d_ptr = &new; *d_ptr; d_ptr = &(*d_ptr)->next)
-                ;
-
-              *d_ptr = f->deps;
-              f->deps = new;
-            }
-          else
-            {
-              struct dep **d_ptr;
-              for (d_ptr = &f->deps; *d_ptr; d_ptr = &(*d_ptr)->next)
-                ;
-
-              *d_ptr = new;
-            }
-        }
-    }
-
-  free_dep_chain (old);
+      }
+#endif
+
+      /* Add newly parsed prerequisites.  */
+      next = d->next;
+      *dp = new;
+      for (dp = &new->next, d = new->next; d != 0; dp = &d->next, d = d->next)
+        ;
+      *dp = next;
+      d = *dp;
+    }
+}
+
+/* Reset the updating flag.  */
+
+static void
+reset_updating (const void *item)
+{
+  struct file *f = (struct file *) item;
+  f->updating = 0;
 }
 
@@ -816,13 +793,8 @@
   struct file *f2;
   struct dep *d;
-  struct file **file_slot_0;
-  struct file **file_slot;
-  struct file **file_end;
-
-  /* Perform second expansion and enter each dependency name as a file. */
-
-  /* Expand .SUFFIXES first; it's dependencies are used for $$* calculation. */
-  for (f = lookup_file (".SUFFIXES"); f != 0; f = f->prev)
-    expand_deps (f);
+
+  /* Remember that we've done this.  Once we start snapping deps we can no
+     longer define new targets.  */
+  snapped_deps = 1;
 
 #ifdef CONFIG_WITH_2ND_TARGET_EXPANSION
@@ -832,4 +804,5 @@
   if (second_target_expansion)
     {
+      struct file **file_slot_0, **file_end, **file_slot;
 # ifdef KMK /* turn on warnings here. */
       int save = warn_undefined_variables_flag;
@@ -862,33 +835,53 @@
 #endif /* CONFIG_WITH_INCLUDEDEP */
 
-  /* For every target that's not .SUFFIXES, expand its dependencies.
-     We must use hash_dump (), because within this loop we might add new files
-     to the table, possibly causing an in-situ table expansion.  */
-  file_slot_0 = (struct file **) hash_dump (&files, 0, 0);
-  file_end = file_slot_0 + files.ht_fill;
-  for (file_slot = file_slot_0; file_slot < file_end; file_slot++)
-    for (f = *file_slot; f != 0; f = f->prev)
-#ifndef CONFIG_WITH_STRCACHE2
-      if (strcmp (f->name, ".SUFFIXES") != 0)
-#else
-      if (f->name != suffixes_strcached)
-#endif
+  /* Perform second expansion and enter each dependency name as a file.  We
+     must use hash_dump() here because within these loops we likely add new
+     files to the table, possibly causing an in-situ table expansion.
+
+     We only need to do this if second_expansion has been defined; if it
+     hasn't then all deps were expanded as the makefile was read in.  If we
+     ever change make to be able to unset .SECONDARY_EXPANSION this will have
+     to change.  */
+
+  if (second_expansion)
+    {
+      struct file **file_slot_0 = (struct file **) hash_dump (&files, 0, 0);
+      struct file **file_end = file_slot_0 + files.ht_fill;
+      struct file **file_slot;
+      const char *suffixes;
+
+      /* Expand .SUFFIXES: its prerequisites are used for $$* calc.  */
+      f = lookup_file (".SUFFIXES");
+      suffixes = f ? f->name : 0;
+      for (; f != 0; f = f->prev)
         expand_deps (f);
+
 #ifdef KMK
-  /* This is a HACK to work around the still broken test #9 in
-     features/double_colon.  It produces the wrong result if the build is
-     parallel because of changed evaluation order.  Just make these
-     problematic rules execute in single field till a proper fix is
-     forthcomming...  */
-
-  for (file_slot = file_slot_0; file_slot < file_end; file_slot++)
-    if (   (f = *file_slot) != 0
-        && f->double_colon
-        && (   f->double_colon != f
-            || f->last != f))
-      for (f2 = f->double_colon; f2 != 0; f2 = f2->prev)
-        f2->command_flags |= COMMANDS_NOTPARALLEL;
+      /* This is a HACK to work around the still broken test #9 in
+         features/double_colon.  It produces the wrong result if the build is
+         parallel because of changed evaluation order.  Just make these
+         problematic rules execute in single field till a proper fix is
+         forthcomming...  */
+
+      for (file_slot = file_slot_0; file_slot < file_end; file_slot++)
+        if (   (f = *file_slot) != 0
+            && f->double_colon
+            && (   f->double_colon != f
+                || f->last != f))
+          for (f2 = f->double_colon; f2 != 0; f2 = f2->prev)
+            f2->command_flags |= COMMANDS_NOTPARALLEL;
 #endif /* KMK */
-  free (file_slot_0);
+
+      /* For every target that's not .SUFFIXES, expand its prerequisites.  */
+
+      for (file_slot = file_slot_0; file_slot < file_end; file_slot++)
+        for (f = *file_slot; f != 0; f = f->prev)
+          if (f->name != suffixes)
+            expand_deps (f);
+      free (file_slot_0);
+    }
+  else
+    /* We're not doing second expansion, so reset updating.  */
+    hash_map (&files, reset_updating);
 
   /* Now manage all the special targets.  */
@@ -985,10 +978,7 @@
   /* This needs more work: what if the user sets this in the makefile?
   if (posix_pedantic)
-    define_variable (STRING_SIZE_TUPLE("OUTPUT_OPTION"), "", o_default, 1);
+    define_variable_cname ("OUTPUT_OPTION", "", o_default, 1);
   */
 #endif
-
-  /* Remember that we've done this. */
-  snapped_deps = 1;
 }
 
@@ -1121,10 +1111,32 @@
 /* Print the data base of files.  */
 
+void
+print_prereqs (const struct dep *deps)
+{
+  const struct dep *ood = 0;
+
+  /* Print all normal dependencies; note any order-only deps.  */
+  for (; deps != 0; deps = deps->next)
+    if (! deps->ignore_mtime)
+      printf (" %s", dep_name (deps));
+    else if (! ood)
+      ood = deps;
+
+  /* Print order-only deps, if we have any.  */
+  if (ood)
+    {
+      printf (" | %s", dep_name (ood));
+      for (ood = ood->next; ood != 0; ood = ood->next)
+        if (ood->ignore_mtime)
+          printf (" %s", dep_name (ood));
+    }
+
+  putchar ('\n');
+}
+
 static void
 print_file (const void *item)
 {
   const struct file *f = item;
-  struct dep *d;
-  struct dep *ood = 0;
 
   putchar ('\n');
@@ -1158,21 +1170,5 @@
     printf ("%s:%s", f->name, f->double_colon ? ":" : "");
 
-  /* Print all normal dependencies; note any order-only deps.  */
-  for (d = f->deps; d != 0; d = d->next)
-    if (! d->ignore_mtime)
-      printf (" %s", dep_name (d));
-    else if (! ood)
-      ood = d;
-
-  /* Print order-only deps, if we have any.  */
-  if (ood)
-    {
-      printf (" | %s", dep_name (ood));
-      for (d = ood->next; d != 0; d = d->next)
-        if (d->ignore_mtime)
-          printf (" %s", dep_name (d));
-    }
-
-  putchar ('\n');
+  print_prereqs (f->deps);
 
 #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
@@ -1206,4 +1202,5 @@
   if (f->also_make != 0)
     {
+      const struct dep *d;
       fputs (_("#  Also makes:"), stdout);
       for (d = f->also_make; d != 0; d = d->next)
@@ -1300,5 +1297,5 @@
     do{\
         if (_p->_n && _p->_n[0] && !strcache_iscached (_p->_n)) \
-          printf ("%s: Field %s not cached: %s\n", _p->name, # _n, _p->_n); \
+          error (NULL, "%s: Field '%s' not cached: %s\n", _p->name, # _n, _p->_n); \
     }while(0)
 
@@ -1317,5 +1314,6 @@
   for (d = f->deps; d != 0; d = d->next)
     {
-      VERIFY_CACHED (d, name);
+      if (! d->need_2nd_expansion)
+        VERIFY_CACHED (d, name);
       VERIFY_CACHED (d, stem);
     }
Index: /trunk/src/kmk/filedef.h
===================================================================
--- /trunk/src/kmk/filedef.h	(revision 2590)
+++ /trunk/src/kmk/filedef.h	(revision 2591)
@@ -1,6 +1,6 @@
 /* Definition of target file data structures 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 Free Software
-Foundation, Inc.
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
@@ -107,4 +107,7 @@
     unsigned int considered:1;  /* equal to 'considered' if file has been
                                    considered on current scan of goal chain */
+    unsigned int no_diag:1;     /* True if the file failed to update and no
+                                   diagnostics has been issued (dontcare). */
+
 #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
     unsigned int multi_maybe:1; /* Nonzero if this file isn't always updated
@@ -117,10 +120,8 @@
                                   and the expanding done in snap_deps. */
 #endif
-
   };
 
 
-extern struct file *default_goal_file, *suffix_file, *default_file;
-extern char **default_goal_name;
+extern struct file *suffix_file, *default_file;
 
 
@@ -130,5 +131,6 @@
 #endif
 struct file *enter_file (const char *name);
-struct dep *parse_prereqs (char *prereqs);
+struct dep *split_prereqs (char *prereqstr);
+struct dep *enter_prereqs (struct dep *prereqs, const char *stem);
 void remove_intermediates (int sig);
 void snap_deps (void);
@@ -139,4 +141,6 @@
 void init_hash_files (void);
 char *build_target_list (char *old_list);
+void print_prereqs (const struct dep *deps);
+void print_file_data_base (void);
 
 #if FILE_TIMESTAMP_HI_RES
Index: /trunk/src/kmk/function.c
===================================================================
--- /trunk/src/kmk/function.c	(revision 2590)
+++ /trunk/src/kmk/function.c	(revision 2591)
@@ -1,6 +1,6 @@
 /* Builtin function expansion 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 Free Software
-Foundation, Inc.
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
@@ -514,21 +514,9 @@
   unsigned int idx;
 
-#ifndef CONFIG_WITH_ALLOC_CACHES
-  chain = multi_glob (parse_file_seq
-		      (&line, '\0', sizeof (struct nameseq),
-		       /* We do not want parse_file_seq to strip `./'s.
-			  That would break examples like:
-			  $(patsubst ./%.c,obj/%.o,$(wildcard ./?*.c)).  */
-		       0),
-		      sizeof (struct nameseq));
-#else  /* CONFIG_WITH_ALLOC_CACHES */
-  chain = multi_glob (parse_file_seq
-                      (&line, '\0', &nameseq_cache,
-                       /* We do not want parse_file_seq to strip `./'s.
-                          That would break examples like:
-                          $(patsubst ./%.c,obj/%.o,$(wildcard ./?*.c)).  */
-                       0),
-                      &nameseq_cache);
-#endif /* CONFIG_WITH_ALLOC_CACHES */
+  chain = PARSE_FILE_SEQ (&line, struct nameseq, '\0', NULL,
+                          /* We do not want parse_file_seq to strip `./'s.
+                             That would break examples like:
+                             $(patsubst ./%.c,obj/%.o,$(wildcard ./?*.c)).  */
+                          PARSEFS_NOSTRIP|PARSEFS_NOCACHE|PARSEFS_EXISTS);
 
   if (result == 0)
@@ -541,8 +529,18 @@
   while (chain != 0)
     {
-      const char *name = chain->name;
-      unsigned int len = strlen (name);
-
       struct nameseq *next = chain->next;
+      unsigned int len = strlen (chain->name);
+
+      if (idx + len + 1 > length)
+        {
+          length += (len + 1) * 2;
+          result = xrealloc (result, length);
+        }
+      memcpy (&result[idx], chain->name, len);
+      idx += len;
+      result[idx++] = ' ';
+
+      /* Because we used PARSEFS_NOCACHE above, we have to free() NAME.  */
+      free ((char *)chain->name);
 #ifndef CONFIG_WITH_ALLOC_CACHES
       free (chain);
@@ -551,18 +549,4 @@
 #endif
       chain = next;
-
-      /* multi_glob will pass names without globbing metacharacters
-	 through as is, but we want only files that actually exist.  */
-      if (file_exists_p (name))
-	{
-	  if (idx + len + 1 > length)
-	    {
-	      length += (len + 1) * 2;
-	      result = xrealloc (result, length);
-	    }
-	  memcpy (&result[idx], name, len);
-	  idx += len;
-	  result[idx++] = ' ';
-	}
     }
 
@@ -1346,5 +1330,5 @@
 
       free (var->value);
-      var->value = savestring (p, len);
+      var->value = xstrndup (p, len);
 
       result = allocated_variable_expand (body);
@@ -2220,5 +2204,5 @@
 
 void
-windows32_openpipe (int *pipedes, int *pid_p, char **command_argv, char **envp)
+windows32_openpipe (int *pipedes, pid_t *pid_p, char **command_argv, char **envp)
 {
   SECURITY_ATTRIBUTES saAttr;
@@ -2241,5 +2225,5 @@
 		      TRUE,
 		      DUPLICATE_SAME_ACCESS) == FALSE) {
-    fatal (NILF, _("create_child_process: DuplicateHandle(In) failed (e=%ld)\n"),
+    fatal (NILF, _("windows32_openpipe(): DuplicateHandle(In) failed (e=%ld)\n"),
 	   GetLastError());
 
@@ -2252,5 +2236,5 @@
 		      TRUE,
 		      DUPLICATE_SAME_ACCESS) == FALSE) {
-    fatal (NILF, _("create_child_process: DuplicateHandle(Err) failed (e=%ld)\n"),
+    fatal (NILF, _("windows32_open_pipe(): DuplicateHandle(Err) failed (e=%ld)\n"),
 	   GetLastError());
   }
@@ -2262,8 +2246,11 @@
 
   if (!hProcess)
-    fatal (NILF, _("windows32_openpipe (): process_init_fd() failed\n"));
+    fatal (NILF, _("windows32_openpipe(): process_init_fd() failed\n"));
 
   /* make sure that CreateProcess() has Path it needs */
   sync_Path_environment();
+  /* `sync_Path_environment' may realloc `environ', so take note of
+     the new value.  */
+  envp = environ;
 
   if (!process_begin(hProcess, command_argv, envp, command_argv[0], NULL)) {
@@ -2272,11 +2259,11 @@
 
     /* set the pid for returning to caller */
-    *pid_p = (int) hProcess;
+    *pid_p = (pid_t) hProcess;
 
   /* set up to read data from child */
-  pipedes[0] = _open_osfhandle((long) hChildOutRd, O_RDONLY);
+  pipedes[0] = _open_osfhandle((intptr_t) hChildOutRd, O_RDONLY);
 
   /* this will be closed almost right away */
-  pipedes[1] = _open_osfhandle((long) hChildOutWr, O_APPEND);
+  pipedes[1] = _open_osfhandle((intptr_t) hChildOutWr, O_APPEND);
   } else {
     /* reap/cleanup the failed process */
@@ -2293,5 +2280,5 @@
     /* set status for return */
     pipedes[0] = pipedes[1] = -1;
-    *pid_p = -1;
+    *pid_p = (pid_t)-1;
   }
 }
@@ -2366,5 +2353,5 @@
 #ifndef _AMIGA
 static char *
-func_shell (char *o, char **argv, const char *funcname UNUSED)
+func_shell (char * volatile o, char **argv, const char *funcname UNUSED)
 {
   char *batch_filename = NULL;
@@ -2374,8 +2361,8 @@
 #endif
   char **command_argv;
-  const char *error_prefix;
+  const char * volatile error_prefix; /* bird: this volatile and the 'o' one, is for shutting up gcc warnings */
   char **envp;
   int pipedes[2];
-  int pid;
+  pid_t pid;
 
 #ifndef __MSDOS__
@@ -2467,9 +2454,9 @@
       free (command_argv);
 
-      /* Close the write side of the pipe.  */
-# ifdef _MSC_VER /* Avoid annoying msvcrt when debugging. (bird) */
-      if (pipedes[1] != -1)
-# endif
-      close (pipedes[1]);
+      /* Close the write side of the pipe.  We test for -1, since
+	 pipedes[1] is -1 on MS-Windows, and some versions of MS
+	 libraries barf when `close' is called with -1.  */
+      if (pipedes[1] >= 0)
+	close (pipedes[1]);
 #endif
 
@@ -3442,4 +3429,12 @@
 
 
+#ifdef HAVE_DOS_PATHS
+#define IS_ABSOLUTE(n) (n[0] && n[1] == ':')
+#define ROOT_LEN 3
+#else
+#define IS_ABSOLUTE(n) (n[0] == '/')
+#define ROOT_LEN 1
+#endif
+
 /* Return the absolute name of file NAME which does not contain any `.',
    `..' components nor any repeated path separators ('/').   */
@@ -3453,4 +3448,5 @@
   char *dest;
   const char *start, *end, *apath_limit;
+  unsigned long root_len = ROOT_LEN;
 
   if (name[0] == '\0' || apath == NULL)
@@ -3479,16 +3475,5 @@
   apath_limit = apath + GET_PATH_MAX;
 
-#ifdef HAVE_DOS_PATHS /* bird added this */
-  if (isalpha(name[0]) && name[1] == ':')
-    {
-      /* drive spec */
-      apath[0] = toupper(name[0]);
-      apath[1] = ':';
-      apath[2] = '/';
-      name += 2;
-    }
-  else
-#endif /* HAVE_DOS_PATHS */
-  if (name[0] != '/')
+  if (!IS_ABSOLUTE(name))
     {
       /* It is unlikely we would make it until here but just to make sure. */
@@ -3498,10 +3483,45 @@
       strcpy (apath, starting_directory);
 
+#ifdef HAVE_DOS_PATHS
+      if (IS_PATHSEP(name[0]))
+	{
+	  if (IS_PATHSEP(name[1]))
+	    {
+	      /* A UNC.  Don't prepend a drive letter.  */
+	      apath[0] = name[0];
+	      apath[1] = name[1];
+	      root_len = 2;
+	    }
+	  /* We have /foo, an absolute file name except for the drive
+	     letter.  Assume the missing drive letter is the current
+	     drive, which we can get if we remove from starting_directory
+	     everything past the root directory.  */
+	  apath[root_len] = '\0';
+	}
+#endif
+
       dest = strchr (apath, '\0');
     }
   else
     {
-      apath[0] = '/';
-      dest = apath + 1;
+      strncpy (apath, name, root_len);
+      apath[root_len] = '\0';
+      dest = apath + root_len;
+      /* Get past the root, since we already copied it.  */
+      name += root_len;
+#ifdef HAVE_DOS_PATHS
+      if (!IS_PATHSEP(apath[2]))
+	{
+	  /* Convert d:foo into d:./foo and increase root_len.  */
+	  apath[2] = '.';
+	  apath[3] = '/';
+	  dest++;
+	  root_len++;
+	  /* strncpy above copied one character too many.  */
+	  name--;
+	}
+      else
+	apath[2] = '/';	/* make sure it's a forward slash */
+#endif
     }
 
@@ -3511,9 +3531,9 @@
 
       /* Skip sequence of multiple path-separators.  */
-      while (*start == '/')
+      while (IS_PATHSEP(*start))
 	++start;
 
       /* Find end of path component.  */
-      for (end = start; *end != '\0' && *end != '/'; ++end)
+      for (end = start; *end != '\0' && !IS_PATHSEP(*end); ++end)
         ;
 
@@ -3527,10 +3547,10 @@
 	{
 	  /* Back up to previous component, ignore if at root already.  */
-	  if (dest > apath + 1)
-	    while ((--dest)[-1] != '/');
+	  if (dest > apath + root_len)
+	    for (--dest; !IS_PATHSEP(dest[-1]); --dest);
 	}
       else
 	{
-	  if (dest[-1] != '/')
+	  if (!IS_PATHSEP(dest[-1]))
             *dest++ = '/';
 
@@ -3546,9 +3566,5 @@
 
   /* Unless it is root strip trailing separator.  */
-#ifdef HAVE_DOS_PATHS /* bird (is this correct? what about UNC?) */
-  if (dest > apath + 1 + (apath[0] != '/') && dest[-1] == '/')
-#else
-  if (dest > apath + 1 && dest[-1] == '/')
-#endif
+  if (dest > apath + root_len && IS_PATHSEP(dest[-1]))
     --dest;
 
@@ -3567,4 +3583,7 @@
   int doneany = 0;
   unsigned int len = 0;
+#ifndef HAVE_REALPATH
+  struct stat st;
+#endif
   PATH_VAR (in);
   PATH_VAR (out);
@@ -3581,5 +3600,5 @@
               realpath (in, out)
 #else
-              abspath (in, out)
+              abspath (in, out) && stat (out, &st) == 0
 #endif
              )
Index: /trunk/src/kmk/getloadavg.c
===================================================================
--- /trunk/src/kmk/getloadavg.c	(revision 2590)
+++ /trunk/src/kmk/getloadavg.c	(revision 2591)
@@ -1,6 +1,6 @@
 /* Get the system load averages.
 Copyright (C) 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
-1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
-Free Software Foundation, Inc.
+1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
+2008, 2009, 2010 Free Software Foundation, Inc.
 
 GNU Make is free software; you can redistribute it and/or modify it under the
Index: /trunk/src/kmk/getopt.c
===================================================================
--- /trunk/src/kmk/getopt.c	(revision 2590)
+++ /trunk/src/kmk/getopt.c	(revision 2591)
@@ -5,6 +5,6 @@
 
 Copyright (C) 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
-1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software
-Foundation, Inc.
+1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+2010 Free Software Foundation, Inc.
 
 NOTE: The canonical source of this file is maintained with the GNU C Library.
@@ -683,14 +683,16 @@
 		{
 		  if (opterr)
-		   if (argv[optind - 1][1] == '-')
-		    /* --option */
-		    fprintf (stderr,
-		     _("%s: option `--%s' doesn't allow an argument\n"),
-		     argv[0], pfound->name);
-		   else
-		    /* +option or -option */
-		    fprintf (stderr,
-		     _("%s: option `%c%s' doesn't allow an argument\n"),
-		     argv[0], argv[optind - 1][0], pfound->name);
+                    {
+		      if (argv[optind - 1][1] == '-')
+                        /* --option */
+                        fprintf (stderr,
+                         _("%s: option `--%s' doesn't allow an argument\n"),
+                         argv[0], pfound->name);
+		      else
+		        /* +option or -option */
+		        fprintf (stderr,
+		         _("%s: option `%c%s' doesn't allow an argument\n"),
+		         argv[0], argv[optind - 1][0], pfound->name);
+                    }
 
 		  nextchar += strlen (nextchar);
Index: /trunk/src/kmk/getopt.h
===================================================================
--- /trunk/src/kmk/getopt.h	(revision 2590)
+++ /trunk/src/kmk/getopt.h	(revision 2591)
@@ -1,6 +1,6 @@
 /* Declarations for getopt.
 Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation,
-Inc.
+1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free
+Software Foundation, Inc.
 
 NOTE: The canonical source of this file is maintained with the GNU C Library.
Index: /trunk/src/kmk/getopt1.c
===================================================================
--- /trunk/src/kmk/getopt1.c	(revision 2590)
+++ /trunk/src/kmk/getopt1.c	(revision 2591)
@@ -1,6 +1,6 @@
 /* getopt_long and getopt_long_only entry points for GNU getopt.
 Copyright (C) 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1997,
-1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software
-Foundation, Inc.
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+2010 Free Software Foundation, Inc.
 
 NOTE: The canonical source of this file is maintained with the GNU C Library.
Index: /trunk/src/kmk/gettext.h
===================================================================
--- /trunk/src/kmk/gettext.h	(revision 2590)
+++ /trunk/src/kmk/gettext.h	(revision 2591)
@@ -1,5 +1,5 @@
 /* Convenience header for conditional use of GNU <libintl.h>.
 Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005,
-2006, 2007 Free Software Foundation, Inc.
+2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
Index: /trunk/src/kmk/glob/ChangeLog
===================================================================
--- /trunk/src/kmk/glob/ChangeLog	(revision 2590)
+++ /trunk/src/kmk/glob/ChangeLog	(revision 2591)
@@ -1,5 +1,11 @@
+2008-09-28  Juan Manuel Guerrero  <juan.guerrero@gmx.de>
+
+	* glob.c (my_realloc) [__DJGPP__]: Don't define, and don't
+	redefine realloc to call it, since the DJGPP's realloc handles
+	NULL pointers correctly.
+
 2007-12-22  Juan Manuel Guerrero  <juan.guerrero@gmx.de>  (tiny change)
 
-	* glob/glob.c [__GNU_LIBRARY__ && __DJGPP__]: Add a realloc
+	* glob.c [__GNU_LIBRARY__ && __DJGPP__]: Add a realloc
 	declaration that matches the one in the DJGPP libc.
 
Index: /trunk/src/kmk/glob/glob.c
===================================================================
--- /trunk/src/kmk/glob/glob.c	(revision 2590)
+++ /trunk/src/kmk/glob/glob.c	(revision 2591)
@@ -183,5 +183,5 @@
 #endif
 
-#if !defined(__GNU_LIBRARY__) && !defined(ELECTRIC_HEAP) && !defined(__APPLE__) /* bird (last two) */
+#if !defined __GNU_LIBRARY__ && !defined __DJGPP__ && !defined ELECTRIC_HEAP && !defined __APPLE__ /* bird (last two) */
 # ifdef	__GNUC__
 __inline
@@ -192,7 +192,4 @@
 static void *
 my_realloc (void *p, unsigned int n)
-#  elif defined(__DJGPP__)
-static void *
-my_realloc (void *p, size_t n)
 #  else
 static char *
@@ -210,5 +207,5 @@
 # define	realloc	my_realloc
 # endif /* __SASC */
-#endif /* __GNU_LIBRARY__ */
+#endif /* __GNU_LIBRARY__ || __DJGPP__ */
 
 
@@ -390,5 +387,5 @@
 	  /* Allocate working buffer large enough for our work.  Note that
 	    we have at least an opening and closing brace.  */
-	  size_t firstc;
+	  size_t firstc;  /* bird: correct type. */
 	  char *alt_start;
 	  const char *p;
Index: /trunk/src/kmk/hash.c
===================================================================
--- /trunk/src/kmk/hash.c	(revision 2590)
+++ /trunk/src/kmk/hash.c	(revision 2591)
@@ -1,4 +1,4 @@
 /* hash.c -- hash table maintenance
-Copyright (C) 1995, 1999, 2002 Free Software Foundation, Inc.
+Copyright (C) 1995, 1999, 2002, 2010 Free Software Foundation, Inc.
 Written by Greg McGary <gkm@gnu.org> <greg@mcgary.org>
 
@@ -51,6 +51,6 @@
   if (ht->ht_vec == 0)
     {
-      fprintf (stderr, _("can't allocate %ld bytes for hash table: memory exhausted"),
-	       ht->ht_size * sizeof(struct token *));
+      fprintf (stderr, _("can't allocate %lu bytes for hash table: memory exhausted"),
+	       ht->ht_size * (unsigned long) sizeof (struct token *));
       exit (1);
     }
@@ -252,5 +252,5 @@
 {
   void **slot = hash_find_slot (ht, item);
-  const void *old_item = slot ? *slot : 0;
+  const void *old_item = *slot;
   hash_insert_at (ht, item, slot);
   return (void *)((HASH_VACANT (old_item)) ? 0 : old_item);
Index: /trunk/src/kmk/hash.h
===================================================================
--- /trunk/src/kmk/hash.h	(revision 2590)
+++ /trunk/src/kmk/hash.h	(revision 2591)
@@ -1,4 +1,4 @@
 /* hash.h -- decls for hash table
-Copyright (C) 1995, 1999, 2002 Free Software Foundation, Inc.
+Copyright (C) 1995, 1999, 2002, 2010 Free Software Foundation, Inc.
 Written by Greg McGary <gkm@gnu.org> <greg@mcgary.org>
 
@@ -98,4 +98,7 @@
 /* hash and comparison macros for case-sensitive string keys. */
 
+/* Due to the strcache, it's not uncommon for the string pointers to
+   be identical.  Take advantage of that to short-circuit string compares.  */
+
 #define STRING_HASH_1(KEY, RESULT) do { \
   unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \
@@ -121,8 +124,8 @@
 
 #define STRING_COMPARE(X, Y, RESULT) do { \
-  RESULT = strcmp ((X), (Y)); \
+    RESULT = (X) == (Y) ? 0 : strcmp ((X), (Y)); \
 } while (0)
 #define return_STRING_COMPARE(X, Y) do { \
-  return strcmp ((X), (Y)); \
+  return (X) == (Y) ? 0 : strcmp ((X), (Y)); \
 } while (0)
 
@@ -157,8 +160,8 @@
 
 #define STRING_N_COMPARE(X, Y, N, RESULT) do { \
-  RESULT = strncmp ((X), (Y), (N)); \
+  RESULT = (X) == (Y) ? 0 : strncmp ((X), (Y), (N)); \
 } while (0)
 #define return_STRING_N_COMPARE(X, Y, N) do { \
-  return strncmp ((X), (Y), (N)); \
+  return (X) == (Y) ? 0 : strncmp ((X), (Y), (N)); \
 } while (0)
 
@@ -190,8 +193,8 @@
 
 #define ISTRING_COMPARE(X, Y, RESULT) do { \
-  RESULT = strcasecmp ((X), (Y)); \
+  RESULT = (X) == (Y) ? 0 : strcasecmp ((X), (Y)); \
 } while (0)
 #define return_ISTRING_COMPARE(X, Y) do { \
-  return strcasecmp ((X), (Y)); \
+  return (X) == (Y) ? 0 : strcasecmp ((X), (Y)); \
 } while (0)
 
Index: /trunk/src/kmk/implicit.c
===================================================================
--- /trunk/src/kmk/implicit.c	(revision 2590)
+++ /trunk/src/kmk/implicit.c	(revision 2591)
@@ -1,6 +1,6 @@
 /* Implicit rule searching 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 Free Software
-Foundation, Inc.
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
@@ -49,5 +49,5 @@
     return 1;
 
-#ifndef	NO_ARCHIVES
+#ifndef NO_ARCHIVES
   /* If this is an archive member reference, use just the
      archive member name to search for implicit rules.  */
@@ -57,5 +57,5 @@
            _("Looking for archive-member implicit rule for `%s'.\n"));
       if (pattern_search (file, 1, depth, 0))
-	return 1;
+        return 1;
     }
 #endif
@@ -64,37 +64,4 @@
 }
 
-
-
-#ifdef CONFIG_WITH_ALLOC_CACHES
-struct alloccache idep_cache;
-#endif
-
-/* Struct idep captures information about implicit prerequisites
-   that come from implicit rules. */
-struct idep
-{
-  struct idep *next;              /* struct dep -compatible interface */
-  const char *name;               /* name of the prerequisite */
-  struct file *intermediate_file; /* intermediate file, 0 otherwise */
-  const char *intermediate_pattern; /* pattern for intermediate file */
-  unsigned char had_stem;         /* had % substituted with stem */
-  unsigned char ignore_mtime;     /* ignore_mtime flag */
-};
-
-static void
-free_idep_chain (struct idep *p)
-{
-  struct idep *n;
-
-  for (; p != 0; p = n)
-    {
-      n = p->next;
-#ifndef CONFIG_WITH_ALLOC_CACHES
-      free (p);
-#else
-      alloccache_free (&idep_cache, p);
-#endif
-    }
-}
 
 
@@ -103,5 +70,5 @@
    length of the word.  */
 
-static char *
+static const char *
 get_next_word (const char *buffer, unsigned int *length)
 {
@@ -181,5 +148,47 @@
     *length = p - beg;
 
-  return (char *)beg;
+  return beg;
+}
+
+/* This structure stores information about the expanded prerequisites for a
+   pattern rule.  NAME is always set to the strcache'd name of the prereq.
+   FILE and PATTERN will be set for intermediate files only.  IGNORE_MTIME is
+   copied from the prerequisite we expanded.
+ */
+struct patdeps
+  {
+    const char *name;
+    const char *pattern;
+    struct file *file;
+    unsigned int ignore_mtime : 1;
+  };
+
+/* This structure stores information about pattern rules that we need
+   to try.
+*/
+struct tryrule
+  {
+    struct rule *rule;
+
+    /* Index of the target in this rule that matched the file. */
+    unsigned int matches;
+
+    /* Stem length for this match. */
+    unsigned int stemlen;
+
+    /* Definition order of this rule. Used to implement stable sort.*/
+    unsigned int order;
+
+    /* Nonzero if the LASTSLASH logic was used in matching this rule. */
+    char checked_lastslash;
+  };
+
+int
+stemlen_compare (const void *v1, const void *v2)
+{
+  const struct tryrule *r1 = v1;
+  const struct tryrule *r2 = v2;
+  int r = r1->stemlen - r2->stemlen;
+  return r != 0 ? r : (int)(r1->order - r2->order);
 }
 
@@ -209,18 +218,18 @@
 
   /* The last slash in FILENAME (or nil if there is none).  */
-  char *lastslash;
+  const char *lastslash;
 
   /* This is a file-object used as an argument in
      recursive calls.  It never contains any data
      except during a recursive call.  */
-  struct file *intermediate_file = 0;
-
-  /* This linked list records all the prerequisites actually
-     found for a rule along with some other useful information
-     (see struct idep for details). */
-  struct idep* deps = 0;
-
-  /* 1 if we need to remove explicit prerequisites, 0 otherwise. */
-  unsigned int remove_explicit_deps = 0;
+  struct file *int_file = 0;
+
+  /* List of dependencies found recursively.  */
+  struct patdeps *deplist
+    = xmalloc (max_pattern_deps * sizeof (struct patdeps));
+  struct patdeps *pat = deplist;
+
+  /* All the prerequisites actually found for a rule, after expansion.  */
+  struct dep *deps;
 
   /* Names of possible dependencies are constructed in this buffer.  */
@@ -233,18 +242,10 @@
 
   /* Buffer in which we store all the rules that are possibly applicable.  */
-  struct rule **tryrules = xmalloc (num_pattern_rules * max_pattern_targets
-                                    * sizeof (struct rule *));
+  struct tryrule *tryrules = xmalloc (num_pattern_rules * max_pattern_targets
+                                      * sizeof (struct tryrule));
 
   /* Number of valid elements in TRYRULES.  */
   unsigned int nrules;
 
-  /* The numbers of the rule targets of each rule
-     in TRYRULES that matched the target file.  */
-  unsigned int *matches = alloca (num_pattern_rules * sizeof (unsigned int));
-
-  /* Each element is nonzero if LASTSLASH was used in
-     matching the corresponding element of TRYRULES.  */
-  char *checked_lastslash = alloca (num_pattern_rules * sizeof (char));
-
   /* The index in TRYRULES of the rule we found.  */
   unsigned int foundrule;
@@ -252,4 +253,7 @@
   /* Nonzero if should consider intermediate files as dependencies.  */
   int intermed_ok;
+
+  /* Nonzero if we have initialized file variables for this target.  */
+  int file_vars_initialized = 0;
 
   /* Nonzero if we have matched a pattern-rule target
@@ -257,20 +261,15 @@
   int specific_rule_matched = 0;
 
+  struct dep dep_simple;
+
   unsigned int ri;  /* uninit checks OK */
   struct rule *rule;
-  struct dep *dep, *expl_d;
-
-  struct idep *d;
-  struct idep **id_ptr;
-  struct dep **d_ptr;
+
+  char *pathdir = NULL;
+  unsigned long pathlen;
 
   PATH_VAR (stem_str); /* @@ Need to get rid of stem, stemlen, etc. */
 
-#ifdef CONFIG_WITH_ALLOC_CACHES
-  if (!idep_cache.size)
-    alloccache_init (&idep_cache, sizeof (struct idep), "idep", NULL, NULL);
-#endif
-
-#ifndef	NO_ARCHIVES
+#ifndef NO_ARCHIVES
   if (archive || ar_name (filename))
     lastslash = 0;
@@ -279,30 +278,32 @@
     {
       /* Set LASTSLASH to point at the last slash in FILENAME
-	 but not counting any slash at the end.  (foo/bar/ counts as
-	 bar/ in directory foo/, not empty in directory foo/bar/.)  */
+         but not counting any slash at the end.  (foo/bar/ counts as
+         bar/ in directory foo/, not empty in directory foo/bar/.)  */
 #ifdef VMS
       lastslash = strrchr (filename, ']');
       if (lastslash == 0)
-	lastslash = strrchr (filename, ':');
+        lastslash = strrchr (filename, ':');
 #else
       lastslash = strrchr (filename, '/');
 #ifdef HAVE_DOS_PATHS
       /* Handle backslashes (possibly mixed with forward slashes)
-	 and the case of "d:file".  */
+         and the case of "d:file".  */
       {
-	char *bslash = strrchr (filename, '\\');
-	if (lastslash == 0 || bslash > lastslash)
-	  lastslash = bslash;
-	if (lastslash == 0 && filename[0] && filename[1] == ':')
-	  lastslash = (char *)filename + 1;
+        char *bslash = strrchr (filename, '\\');
+        if (lastslash == 0 || bslash > lastslash)
+          lastslash = bslash;
+        if (lastslash == 0 && filename[0] && filename[1] == ':')
+          lastslash = filename + 1;
       }
 #endif
 #endif
       if (lastslash != 0 && lastslash[1] == '\0')
-	lastslash = 0;
+        lastslash = 0;
     }
 
-  /* First see which pattern rules match this target
-     and may be considered.  Put them in TRYRULES.  */
+  pathlen = lastslash - filename + 1;
+
+  /* First see which pattern rules match this target and may be considered.
+     Put them in TRYRULES.  */
 
   nrules = 0;
@@ -312,39 +313,39 @@
 
       /* If the pattern rule has deps but no commands, ignore it.
-	 Users cancel built-in rules by redefining them without commands.  */
+         Users cancel built-in rules by redefining them without commands.  */
       if (rule->deps != 0 && rule->cmds == 0)
-	continue;
+        continue;
 
       /* If this rule is in use by a parent pattern_search,
-	 don't use it here.  */
+         don't use it here.  */
       if (rule->in_use)
-	{
-	  DBS (DB_IMPLICIT, (_("Avoiding implicit rule recursion.\n")));
-	  continue;
-	}
+        {
+          DBS (DB_IMPLICIT, (_("Avoiding implicit rule recursion.\n")));
+          continue;
+        }
 
       for (ti = 0; ti < rule->num; ++ti)
-	{
-	  const char *target = rule->targets[ti];
-	  const char *suffix = rule->suffixes[ti];
-	  int check_lastslash;
-
-	  /* Rules that can match any filename and are not terminal
-	     are ignored if we're recursing, so that they cannot be
-	     intermediate files.  */
-	  if (recursions > 0 && target[1] == '\0' && !rule->terminal)
-	    continue;
-
-	  if (rule->lens[ti] > namelen)
-	    /* It can't possibly match.  */
-	    continue;
-
-	  /* From the lengths of the filename and the pattern parts,
-	     find the stem: the part of the filename that matches the %.  */
-	  stem = filename + (suffix - target - 1);
-	  stemlen = namelen - rule->lens[ti] + 1;
-
-	  /* Set CHECK_LASTSLASH if FILENAME contains a directory
-	     prefix and the target pattern does not contain a slash.  */
+        {
+          const char *target = rule->targets[ti];
+          const char *suffix = rule->suffixes[ti];
+          int check_lastslash;
+
+          /* Rules that can match any filename and are not terminal
+             are ignored if we're recursing, so that they cannot be
+             intermediate files.  */
+          if (recursions > 0 && target[1] == '\0' && !rule->terminal)
+            continue;
+
+          if (rule->lens[ti] > namelen)
+            /* It can't possibly match.  */
+            continue;
+
+          /* From the lengths of the filename and the pattern parts,
+             find the stem: the part of the filename that matches the %.  */
+          stem = filename + (suffix - target - 1);
+          stemlen = namelen - rule->lens[ti] + 1;
+
+          /* Set CHECK_LASTSLASH if FILENAME contains a directory
+             prefix and the target pattern does not contain a slash.  */
 
           check_lastslash = 0;
@@ -366,52 +367,62 @@
 #endif
             }
-	  if (check_lastslash)
-	    {
-	      /* If so, don't include the directory prefix in STEM here.  */
-	      unsigned int difference = lastslash - filename + 1;
-	      if (difference > stemlen)
-		continue;
-	      stemlen -= difference;
-	      stem += difference;
-	    }
-
-	  /* Check that the rule pattern matches the text before the stem.  */
-	  if (check_lastslash)
-	    {
-	      if (stem > (lastslash + 1)
-		  && !strneq (target, lastslash + 1, stem - lastslash - 1))
-		continue;
-	    }
-	  else if (stem > filename
-		   && !strneq (target, filename, stem - filename))
-	    continue;
-
-	  /* Check that the rule pattern matches the text after the stem.
-	     We could test simply use 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 (*suffix != stem[stemlen]
-	      || (*suffix != '\0' && !streq (&suffix[1], &stem[stemlen + 1])))
-	    continue;
-
-	  /* Record if we match a rule that not all filenames will match.  */
-	  if (target[1] != '\0')
-	    specific_rule_matched = 1;
-
-	  /* A rule with no dependencies and no commands exists solely to set
-	     specific_rule_matched when it matches.  Don't try to use it.  */
-	  if (rule->deps == 0 && rule->cmds == 0)
-	    continue;
-
-	  /* Record this rule in TRYRULES and the index of the matching
-	     target in MATCHES.  If several targets of the same rule match,
-	     that rule will be in TRYRULES more than once.  */
-	  tryrules[nrules] = rule;
-	  matches[nrules] = ti;
-	  checked_lastslash[nrules] = check_lastslash;
-	  ++nrules;
-	}
+          if (check_lastslash)
+            {
+              /* If so, don't include the directory prefix in STEM here.  */
+              if (pathlen > stemlen)
+                continue;
+              stemlen -= pathlen;
+              stem += pathlen;
+            }
+
+          /* Check that the rule pattern matches the text before the stem.  */
+          if (check_lastslash)
+            {
+              if (stem > (lastslash + 1)
+                  && !strneq (target, lastslash + 1, stem - lastslash - 1))
+                continue;
+            }
+          else if (stem > filename
+                   && !strneq (target, filename, stem - filename))
+            continue;
+
+          /* Check that the rule pattern matches the text after the stem.
+             We could test simply use 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 (*suffix != stem[stemlen]
+              || (*suffix != '\0' && !streq (&suffix[1], &stem[stemlen + 1])))
+            continue;
+
+          /* Record if we match a rule that not all filenames will match.  */
+          if (target[1] != '\0')
+            specific_rule_matched = 1;
+
+          /* A rule with no dependencies and no commands exists solely to set
+             specific_rule_matched when it matches.  Don't try to use it.  */
+          if (rule->deps == 0 && rule->cmds == 0)
+            continue;
+
+          /* Record this rule in TRYRULES and the index of the matching
+             target in MATCHES.  If several targets of the same rule match,
+             that rule will be in TRYRULES more than once.  */
+          tryrules[nrules].rule = rule;
+	  tryrules[nrules].matches = ti;
+          tryrules[nrules].stemlen = stemlen + (check_lastslash ? pathlen : 0);
+          tryrules[nrules].order = nrules;
+	  tryrules[nrules].checked_lastslash = check_lastslash;
+          ++nrules;
+        }
     }
+
+  /* Bail out early if we haven't found any rules. */
+  if (nrules == 0)
+    goto done;
+
+  /* Sort the rules to place matches with the shortest stem first. This
+     way the most specific rules will be tried first. */
+  if (nrules > 1)
+    qsort (tryrules, nrules, sizeof (struct tryrule), stemlen_compare);
 
   /* If we have found a matching rule that won't match all filenames,
@@ -419,68 +430,78 @@
   if (specific_rule_matched)
     for (ri = 0; ri < nrules; ++ri)
-      if (!tryrules[ri]->terminal)
-	{
-	  unsigned int j;
-	  for (j = 0; j < tryrules[ri]->num; ++j)
-	    if (tryrules[ri]->targets[j][1] == '\0')
+      if (!tryrules[ri].rule->terminal)
+        {
+          unsigned int j;
+          for (j = 0; j < tryrules[ri].rule->num; ++j)
+            if (tryrules[ri].rule->targets[j][1] == '\0')
               {
-                tryrules[ri] = 0;
+                tryrules[ri].rule = 0;
                 break;
               }
-	}
-
-  /* We are going to do second expansion so initialize file variables
-     for the rule. */
-  initialize_file_variables (file, 0);
+        }
 
   /* Try each rule once without intermediate files, then once with them.  */
-  for (intermed_ok = 0; intermed_ok == !!intermed_ok; ++intermed_ok)
+  for (intermed_ok = 0; intermed_ok < 2; ++intermed_ok)
     {
-      /* Try each pattern rule till we find one that applies.
-	 If it does, expand its dependencies (as substituted)
-	 and chain them in DEPS.  */
-
+      pat = deplist;
+
+      /* Try each pattern rule till we find one that applies.  If it does,
+         expand its dependencies (as substituted) and chain them in DEPS.  */
       for (ri = 0; ri < nrules; ri++)
-	{
-          struct file *f;
+        {
+          struct dep *dep;
+          int check_lastslash;
           unsigned int failed = 0;
-	  int check_lastslash;
           int file_variables_set = 0;
-
-	  rule = tryrules[ri];
-
-          remove_explicit_deps = 0;
-
-	  /* RULE is nil when we discover that a rule,
-	     already placed in TRYRULES, should not be applied.  */
-	  if (rule == 0)
-	    continue;
-
-	  /* Reject any terminal rules if we're
-	     looking to make intermediate files.  */
-	  if (intermed_ok && rule->terminal)
-	    continue;
-
-	  /* Mark this rule as in use so a recursive
-	     pattern_search won't try to use it.  */
-	  rule->in_use = 1;
-
-	  /* From the lengths of the filename and the matching pattern parts,
-	     find the stem: the part of the filename that matches the %.  */
-	  stem = filename
-	    + (rule->suffixes[matches[ri]] - rule->targets[matches[ri]]) - 1;
-	  stemlen = namelen - rule->lens[matches[ri]] + 1;
-	  check_lastslash = checked_lastslash[ri];
-	  if (check_lastslash)
-	    {
-	      stem += lastslash - filename + 1;
-	      stemlen -= (lastslash - filename) + 1;
-	    }
-
-	  DBS (DB_IMPLICIT, (_("Trying pattern rule with stem `%.*s'.\n"),
+          unsigned int deps_found = 0;
+          /* NPTR points to the part of the prereq we haven't processed.  */
+          const char *nptr = 0;
+          const char *dir = NULL;
+          int order_only = 0;
+          unsigned int matches;
+
+          rule = tryrules[ri].rule;
+
+          /* RULE is nil when we discover that a rule, already placed in
+             TRYRULES, should not be applied.  */
+          if (rule == 0)
+            continue;
+
+          /* Reject any terminal rules if we're looking to make intermediate
+             files.  */
+          if (intermed_ok && rule->terminal)
+            continue;
+
+          /* From the lengths of the filename and the matching pattern parts,
+             find the stem: the part of the filename that matches the %.  */
+          matches = tryrules[ri].matches;
+          stem = filename + (rule->suffixes[matches]
+                             - rule->targets[matches]) - 1;
+          stemlen = (namelen - rule->lens[matches]) + 1;
+          check_lastslash = tryrules[ri].checked_lastslash;
+          if (check_lastslash)
+            {
+              stem += pathlen;
+              stemlen -= pathlen;
+
+              /* We need to add the directory prefix, so set it up.  */
+              if (! pathdir)
+                {
+                  pathdir = alloca (pathlen + 1);
+                  memcpy (pathdir, filename, pathlen);
+                  pathdir[pathlen] = '\0';
+                }
+              dir = pathdir;
+            }
+
+          DBS (DB_IMPLICIT, (_("Trying pattern rule with stem `%.*s'.\n"),
                              (int) stemlen, stem));
 
           strncpy (stem_str, stem, stemlen);
           stem_str[stemlen] = '\0';
+
+          /* If there are no prerequisites, then this rule matches.  */
+          if (rule->deps == 0)
+            break;
 
           /* Temporary assign STEM to file->stem (needed to set file
@@ -488,314 +509,316 @@
           file->stem = stem_str;
 
-	  /* Try each dependency; see if it "exists".  */
-
-	  for (dep = rule->deps; dep != 0; dep = dep->next)
-	    {
-              unsigned int len;
+          /* Mark this rule as in use so a recursive pattern_search won't try
+             to use it.  */
+          rule->in_use = 1;
+
+          /* Try each prerequisite; see if it exists or can be created.  We'll
+             build a list of prereq info in DEPLIST.  Due to 2nd expansion we
+             may have to process multiple prereqs for a single dep entry.  */
+
+          pat = deplist;
+          dep = rule->deps;
+          nptr = dep_name (dep);
+          while (1)
+            {
+              struct dep *dl, *d;
               char *p;
-              char *p2;
-              unsigned int order_only = 0; /* Set if '|' was seen. */
-
-              /* In an ideal world we would take the dependency line,
-                 substitute the stem, re-expand the whole line and chop it
-                 into individual prerequisites. Unfortunately this won't work
-                 because of the "check_lastslash" twist.  Instead, we will
-                 have to go word by word, taking $()'s into account, for each
-                 word we will substitute the stem, re-expand, chop it up, and,
-                 if check_lastslash != 0, add the directory part to each
+
+              /* If we're out of name to parse, start the next prereq.  */
+              if (! nptr)
+                {
+                  dep = dep->next;
+                  if (dep == 0)
+                    break;
+                  nptr = dep_name (dep);
+                }
+
+              /* If we don't need a second expansion, just replace the %.  */
+              if (! dep->need_2nd_expansion)
+                {
+                  dep_simple = *dep;
+                  dep_simple.next = 0;
+                  p = strchr (nptr, '%');
+                  if (p == 0)
+                    dep_simple.name = nptr;
+                  else
+                    {
+                      char *o = depname;
+                      if (check_lastslash)
+                        {
+                          memcpy (o, filename, pathlen);
+                          o += pathlen;
+                        }
+                      memcpy (o, nptr, p - nptr);
+                      o += p - nptr;
+                      memcpy (o, stem_str, stemlen);
+                      o += stemlen;
+                      strcpy (o, p + 1);
+                      dep_simple.name = strcache_add (depname);
+                    }
+                  dl = &dep_simple;
+
+                  /* We've used up this dep, so next time get a new one.  */
+                  nptr = 0;
+                  ++deps_found;
+                }
+
+              /* We have to perform second expansion on this prereq.  In an
+                 ideal world we would take the dependency line, substitute the
+                 stem, re-expand the whole line and chop it into individual
+                 prerequisites.  Unfortunately this won't work because of the
+                 "check_lastslash" twist.  Instead, we will have to go word by
+                 word, taking $()'s into account.  For each word we will
+                 substitute the stem, re-expand, chop it up, and, if
+                 check_lastslash != 0, add the directory part to each
                  resulting prerequisite.  */
-
-              p = get_next_word (dep->name, &len);
-
-              while (1)
+              else
                 {
                   int add_dir = 0;
-                  int had_stem = 0;
-
+                  unsigned int len;
+
+                  nptr = get_next_word (nptr, &len);
+                  if (nptr == 0)
+                    continue;
+
+                  /* See this is a transition to order-only prereqs.  */
+                  if (! order_only && len == 1 && nptr[0] == '|')
+                    {
+                      order_only = 1;
+                      nptr += len;
+                      continue;
+                    }
+
+                  /* If the dependency name has %, substitute the stem.  If we
+                     just replace % with the stem value then later, when we do
+                     the 2nd expansion, we will re-expand this stem value
+                     again.  This is not good if you have certain characters
+                     in your stem (like $).
+
+                     Instead, we will replace % with $* and allow the second
+                     expansion to take care of it for us.  This way (since $*
+                     is a simple variable) there won't be additional
+                     re-expansion of the stem.  */
+
+                  p = lindex (nptr, nptr + len, '%');
                   if (p == 0)
-                    break; /* No more words */
-
-                  /* Is there a pattern in this prerequisite?  */
-
-                  for (p2 = p; p2 < p + len && *p2 != '%'; ++p2)
-                    ;
-
-                  if (dep->need_2nd_expansion)
-                    {
-                      /* If the dependency name has %, substitute the stem.
-
-                         Watch out, we are going to do something tricky
-                         here. If we just replace % with the stem value,
-                         later, when we do the second expansion, we will
-                         re-expand this stem value once again. This is not
-                         good especially if you have certain characters in
-                         your stem (like $).
-
-                         Instead, we will replace % with $* and allow the
-                         second expansion to take care of it for us. This way
-                         (since $* is a simple variable) there won't be
-                         additional re-expansion of the stem.  */
-
-                      if (p2 < p + len)
-                        {
-                          unsigned int i = p2 - p;
-                          memcpy (depname, p, i);
-                          memcpy (depname + i, "$*", 2);
-                          memcpy (depname + i + 2, p2 + 1, len - i - 1);
-                          depname[len + 2 - 1] = '\0';
-
-                          if (check_lastslash)
-                            add_dir = 1;
-
-                          had_stem = 1;
-                        }
-                      else
-                        {
-                          memcpy (depname, p, len);
-                          depname[len] = '\0';
-                        }
-
-                      /* Set file variables. Note that we cannot do it once
-                         at the beginning of the function because of the stem
-                         value.  */
-                      if (!file_variables_set)
-                        {
+                    {
+                      memcpy (depname, nptr, len);
+                      depname[len] = '\0';
+                    }
+                  else
+                    {
+                      unsigned int i = p - nptr;
+                      memcpy (depname, nptr, i);
+                      memcpy (depname + i, "$*", 2);
+                      memcpy (depname + i + 2, p + 1, len - i - 1);
+                      depname[len + 2 - 1] = '\0';
+
+                      if (check_lastslash)
+                        add_dir = 1;
+                    }
+
+                  /* Initialize and set file variables if we haven't already
+                     done so. */
+                  if (!file_vars_initialized)
+                    {
+                      initialize_file_variables (file, 0);
 #if defined(CONFIG_WITH_COMMANDS_FUNC) || defined (CONFIG_WITH_DOT_MUST_MAKE)
-                          set_file_variables (file, 0 /* real call */);
+                      set_file_variables (file, 0 /* real call */);
 #else
-                          set_file_variables (file);
+                      set_file_variables (file);
 #endif
-                          file_variables_set = 1;
-                        }
-
-                      p2 = variable_expand_for_file (depname, file);
-                    }
-                  else
-                    {
-                       if (p2 < p + len)
-                        {
-                          unsigned int i = p2 - p;
-                          memcpy (depname, p, i);
-                          memcpy (depname + i, stem_str, stemlen);
-                          memcpy (depname + i + stemlen, p2 + 1, len - i - 1);
-                          depname[len + stemlen - 1] = '\0';
-
-                          if (check_lastslash)
-                            add_dir = 1;
-
-                          had_stem = 1;
-                        }
-                      else
-                        {
-                          memcpy (depname, p, len);
-                          depname[len] = '\0';
-                        }
-
-                       p2 = depname;
-                    }
-
-                  /* Parse the dependencies. */
-
-                  while (1)
-                    {
-                      id_ptr = &deps;
-
-                      for (; *id_ptr; id_ptr = &(*id_ptr)->next)
-                        ;
-
-#ifndef CONFIG_WITH_ALLOC_CACHES
-                      *id_ptr = (struct idep *)
-                        multi_glob (
-                          parse_file_seq (&p2,
-                                          order_only ? '\0' : '|',
-                                          sizeof (struct idep),
-                                          1), sizeof (struct idep));
-#else
-                      *id_ptr = (struct idep *)
-                        multi_glob (
-                          parse_file_seq (&p2,
-                                          order_only ? '\0' : '|',
-                                          &idep_cache, 1),
-                          &idep_cache);
-#endif
-
-                      /* @@ It would be nice to teach parse_file_seq or
-                         multi_glob to add prefix. This would save us some
-                         reallocations. */
-
-                      if (order_only || add_dir || had_stem)
-                        {
-                          unsigned long l = lastslash - filename + 1;
-
-                          for (d = *id_ptr; d != 0; d = d->next)
-                            {
-                              if (order_only)
-                                d->ignore_mtime = 1;
-
-                              if (add_dir)
-                                {
-                                  char *n = alloca (strlen (d->name) + l + 1);
-                                  memcpy (n, filename, l);
-                                  memcpy (n+l, d->name, strlen (d->name) + 1);
-                                  d->name = strcache_add (n);
-                                }
-
-                              if (had_stem)
-                                d->had_stem = 1;
-                            }
-                        }
-
-                      if (!order_only && *p2)
+                      file_vars_initialized = 1;
+                    }
+                  /* Update the stem value in $* for this rule.  */
+                  else if (!file_variables_set)
+                    {
+                      define_variable_for_file (
+                        "*", 1, file->stem, o_automatic, 0, file);
+                      file_variables_set = 1;
+                    }
+
+                  /* Perform the 2nd expansion.  */
+                  p = variable_expand_for_file (depname, file);
+
+                  /* Parse the expanded string. */
+                  dl = PARSE_FILE_SEQ (&p, struct dep, order_only ? '\0' : '|',
+                                       add_dir ? dir : NULL, 0);
+
+                  for (d = dl; d != NULL; d = d->next)
+                    {
+                      ++deps_found;
+                      if (order_only)
+                        d->ignore_mtime = 1;
+                    }
+
+                  /* Set up for the next word.  */
+                  nptr += len;
+                }
+
+              /* If there are more than max_pattern_deps prerequisites (due to
+                 2nd expansion), reset it and realloc the arrays.  */
+
+              if (deps_found > max_pattern_deps)
+                {
+                  unsigned int l = pat - deplist;
+                  deplist = xrealloc (deplist,
+                                      deps_found * sizeof (struct patdeps));
+                  pat = deplist + l;
+                  max_pattern_deps = deps_found;
+                }
+
+              /* Go through the nameseq and handle each as a prereq name.  */
+              for (d = dl; d != 0; d = d->next)
+                {
+                  struct dep *expl_d;
+                  int is_rule = d->name == dep_name (dep);
+
+                  if (file_impossible_p (d->name))
+                    {
+                      /* If this prereq has already been ruled "impossible",
+                         then the rule fails.  Don't bother trying it on the
+                         second pass either since we know that will fail.  */
+                      DBS (DB_IMPLICIT,
+                           (is_rule
+                            ? _("Rejecting impossible rule prerequisite `%s'.\n")
+                            : _("Rejecting impossible implicit prerequisite `%s'.\n"),
+                            d->name));
+                      tryrules[ri].rule = 0;
+
+                      failed = 1;
+                      break;
+                    }
+
+                  memset (pat, '\0', sizeof (struct patdeps));
+                  pat->ignore_mtime = d->ignore_mtime;
+
+                  DBS (DB_IMPLICIT,
+                       (is_rule
+                        ? _("Trying rule prerequisite `%s'.\n")
+                        : _("Trying implicit prerequisite `%s'.\n"), d->name));
+
+                  /* If this prereq is also explicitly mentioned for FILE,
+                     skip all tests below since it must be built no matter
+                     which implicit rule we choose. */
+
+                  for (expl_d = file->deps; expl_d != 0; expl_d = expl_d->next)
+                    if (streq (dep_name (expl_d), d->name))
+                      break;
+                  if (expl_d != 0)
+                    {
+                      (pat++)->name = d->name;
+                      continue;
+                    }
+
+                  /* The DEP->changed flag says that this dependency resides
+                     in a nonexistent directory.  So we normally can skip
+                     looking for the file.  However, if CHECK_LASTSLASH is
+                     set, then the dependency file we are actually looking for
+                     is in a different directory (the one gotten by prepending
+                     FILENAME's directory), so it might actually exist.  */
+
+                  /* @@ dep->changed check is disabled. */
+                  if (lookup_file (d->name) != 0
+                      /*|| ((!dep->changed || check_lastslash) && */
+                      || file_exists_p (d->name))
+                    {
+                      (pat++)->name = d->name;
+                      continue;
+                    }
+
+                  /* This code, given FILENAME = "lib/foo.o", dependency name
+                     "lib/foo.c", and VPATH=src, searches for
+                     "src/lib/foo.c".  */
+                  {
+                    const char *vname = vpath_search (d->name, 0, NULL, NULL);
+                    if (vname)
                       {
-                        ++p2;
-                        order_only = 1;
+                        DBS (DB_IMPLICIT,
+                             (_("Found prerequisite `%s' as VPATH `%s'\n"),
+                              d->name, vname));
+                        (pat++)->name = d->name;
                         continue;
                       }
-
-                      break;
-                    }
-
-                  p += len;
-                  p = get_next_word (p, &len);
-                }
-	    }
-
-          /* Reset the stem in FILE. */
-
-          file->stem = 0;
-
-          /* @@ This loop can be combined with the previous one. I do
-             it separately for now for transparency.*/
-
-          for (d = deps; d != 0; d = d->next)
-            {
-              const char *name = d->name;
-
-              if (file_impossible_p (name))
-                {
-                  /* If this dependency has already been ruled "impossible",
-                     then the rule fails and don't bother trying it on the
-                     second pass either since we know that will fail too.  */
-                  DBS (DB_IMPLICIT,
-                       (d->had_stem
-                        ? _("Rejecting impossible implicit prerequisite `%s'.\n")
-                        : _("Rejecting impossible rule prerequisite `%s'.\n"),
-                        name));
-                  tryrules[ri] = 0;
-
+                  }
+
+                  /* We could not find the file in any place we should look.
+                     Try to make this dependency as an intermediate file, but
+                     only on the second pass.  */
+
+                  if (intermed_ok)
+                    {
+                      DBS (DB_IMPLICIT,
+                           (_("Looking for a rule with intermediate file `%s'.\n"),
+                            d->name));
+
+                      if (int_file == 0)
+                        int_file = alloca (sizeof (struct file));
+                      memset (int_file, '\0', sizeof (struct file));
+                      int_file->name = d->name;
+
+                      if (pattern_search (int_file,
+                                          0,
+                                          depth + 1,
+                                          recursions + 1))
+                        {
+                          pat->pattern = int_file->name;
+                          int_file->name = d->name;
+                          pat->file = int_file;
+                          (pat++)->name = d->name;
+                          int_file = 0;
+                          continue;
+                        }
+
+                      /* If we have tried to find P as an intermediate file
+                         and failed, mark that name as impossible so we won't
+                         go through the search again later.  */
+                      if (int_file->variables)
+                        free_variable_set (int_file->variables);
+                      if (int_file->pat_variables)
+                        free_variable_set (int_file->pat_variables);
+                      file_impossible (d->name);
+                    }
+
+                  /* A dependency of this rule does not exist. Therefore, this
+                     rule fails.  */
                   failed = 1;
                   break;
                 }
 
-              DBS (DB_IMPLICIT,
-                   (d->had_stem
-                    ? _("Trying implicit prerequisite `%s'.\n")
-                    : _("Trying rule prerequisite `%s'.\n"), name));
-
-              /* If this prerequisite also happened to be explicitly mentioned
-                 for FILE skip all the test below since it it has to be built
-                 anyway, no matter which implicit rule we choose. */
-
-              for (expl_d = file->deps; expl_d != 0; expl_d = expl_d->next)
-                if (streq (dep_name (expl_d), name))
-                  break;
-              if (expl_d != 0)
-                continue;
-
-              /* The DEP->changed flag says that this dependency resides in a
-                 nonexistent directory.  So we normally can skip looking for
-                 the file.  However, if CHECK_LASTSLASH is set, then the
-                 dependency file we are actually looking for is in a different
-                 directory (the one gotten by prepending FILENAME's directory),
-                 so it might actually exist.  */
-
-              /* @@ dep->changed check is disabled. */
-              if (((f = lookup_file (name)) != 0 && f->is_target)
-                  /*|| ((!dep->changed || check_lastslash) && */
-                  || file_exists_p (name))
-                continue;
-
-              /* This code, given FILENAME = "lib/foo.o", dependency name
-                 "lib/foo.c", and VPATH=src, searches for "src/lib/foo.c".  */
-              {
-                const char *vname = vpath_search (name, 0);
-                if (vname)
-                  {
-                    DBS (DB_IMPLICIT,
-                         (_("Found prerequisite `%s' as VPATH `%s'\n"),
-                          name, vname));
-                    continue;
-                  }
-              }
-
-
-              /* We could not find the file in any place we should look.  Try
-                 to make this dependency as an intermediate file, but only on
-                 the second pass.  */
-
-              if (intermed_ok)
-                {
-                  if (intermediate_file == 0)
-                    intermediate_file = alloca (sizeof (struct file));
-
-                  DBS (DB_IMPLICIT,
-                       (_("Looking for a rule with intermediate file `%s'.\n"),
-                        name));
-
-                  memset (intermediate_file, '\0', sizeof (struct file));
-                  intermediate_file->name = name;
-                  if (pattern_search (intermediate_file,
-                                      0,
-                                      depth + 1,
-                                      recursions + 1))
-                    {
-                      d->intermediate_pattern = intermediate_file->name;
-                      intermediate_file->name = strcache_add (name);
-                      d->intermediate_file = intermediate_file;
-                      intermediate_file = 0;
-
-                      continue;
-                    }
-
-                  /* If we have tried to find P as an intermediate
-                     file and failed, mark that name as impossible
-                     so we won't go through the search again later.  */
-                  if (intermediate_file->variables)
-                    free_variable_set (intermediate_file->variables);
-                  file_impossible (name);
-                }
-
-              /* A dependency of this rule does not exist. Therefore,
-                 this rule fails.  */
-              failed = 1;
-              break;
+              /* Free the ns chain.  */
+              if (dl != &dep_simple)
+                free_dep_chain (dl);
+
+              if (failed)
+                break;
             }
 
+          /* Reset the stem in FILE. */
+
+          file->stem = 0;
+
           /* This rule is no longer `in use' for recursive searches.  */
-	  rule->in_use = 0;
-
-          if (failed)
-            {
-              /* This pattern rule does not apply. If some of its
-                 dependencies succeeded, free the data structure
-                 describing them.  */
-              free_idep_chain (deps);
-              deps = 0;
-            }
-	  else
-	    /* This pattern rule does apply.  Stop looking for one.  */
-	    break;
-	}
-
-      /* If we found an applicable rule without
-	 intermediate files, don't try with them.  */
+          rule->in_use = 0;
+
+          if (! failed)
+            /* This pattern rule does apply.  Stop looking for one.  */
+            break;
+
+          /* This pattern rule does not apply. If some of its dependencies
+             succeeded, free the data structure describing them.  */
+          /* free_idep_chain (deps); */
+          deps = 0;
+        }
+
+      /* If we found an applicable rule without intermediate files, don't try
+         with them.  */
       if (ri < nrules)
-	break;
+        break;
 
       rule = 0;
     }
 
-  /* RULE is nil if the loop went all the way
-     through the list and everything failed.  */
+  /* RULE is nil if the loop went through the list but everything failed.  */
   if (rule == 0)
     goto done;
@@ -803,48 +826,30 @@
   foundrule = ri;
 
-  /* If we are recursing, store the pattern that matched
-     FILENAME in FILE->name for use in upper levels.  */
+  /* If we are recursing, store the pattern that matched FILENAME in
+     FILE->name for use in upper levels.  */
 
   if (recursions > 0)
     /* Kludge-o-matic */
-    file->name = rule->targets[matches[foundrule]];
-
-  /* FOUND_FILES lists the dependencies for the rule we found.
-     This includes the intermediate files, if any.
-     Convert them into entries on the deps-chain of FILE.  */
-
-  if (remove_explicit_deps)
+    file->name = rule->targets[tryrules[foundrule].matches];
+
+  /* DEPLIST lists the prerequisites for the rule we found.  This includes the
+     intermediate files, if any.  Convert them into entries on the deps-chain
+     of FILE.  */
+
+  while (pat-- > deplist)
     {
-      /* Remove all the dependencies that didn't come from
-         this implicit rule. */
-
-      dep = file->deps;
-      while (dep != 0)
+      struct dep *dep;
+      const char *s;
+
+      if (pat->file != 0)
         {
-          struct dep *next = dep->next;
-          free_dep (dep);
-          dep = next;
-        }
-      file->deps = 0;
-  }
-
-  expl_d = file->deps; /* We will add them at the end. */
-  d_ptr = &file->deps;
-
-  for (d = deps; d != 0; d = d->next)
-    {
-      const char *s;
-
-      if (d->intermediate_file != 0)
-	{
-	  /* If we need to use an intermediate file,
-	     make sure it is entered as a target, with the info that was
-	     found for it in the recursive pattern_search call.
-	     We know that the intermediate file did not already exist as
-	     a target; therefore we can assume that the deps and cmds
-	     of F below are null before we change them.  */
-
-	  struct file *imf = d->intermediate_file;
-	  register struct file *f = lookup_file (imf->name);
+          /* If we need to use an intermediate file, make sure it is entered
+             as a target, with the info that was found for it in the recursive
+             pattern_search call.  We know that the intermediate file did not
+             already exist as a target; therefore we can assume that the deps
+             and cmds of F below are null before we change them.  */
+
+          struct file *imf = pat->file;
+          struct file *f = lookup_file (imf->name);
 
           /* We don't want to delete an intermediate file that happened
@@ -854,65 +859,62 @@
             f->precious = 1;
           else
-            f = enter_file (strcache_add (imf->name));
-
-	  f->deps = imf->deps;
-	  f->cmds = imf->cmds;
-	  f->stem = imf->stem;
+            f = enter_file (imf->name);
+
+          f->deps = imf->deps;
+          f->cmds = imf->cmds;
+          f->stem = imf->stem;
+          f->variables = imf->variables;
+          f->pat_variables = imf->pat_variables;
+          f->pat_searched = imf->pat_searched;
           f->also_make = imf->also_make;
           f->is_target = 1;
-
-          if (!f->precious)
+          f->intermediate = 1;
+          f->tried_implicit = 1;
+
+          imf = lookup_file (pat->pattern);
+          if (imf != 0 && imf->precious)
+            f->precious = 1;
+
+          for (dep = f->deps; dep != 0; dep = dep->next)
             {
-              imf = lookup_file (d->intermediate_pattern);
-              if (imf != 0 && imf->precious)
-                f->precious = 1;
+              dep->file = enter_file (dep->name);
+              dep->name = 0;
+              dep->file->tried_implicit |= dep->changed;
             }
-
-	  f->intermediate = 1;
-	  f->tried_implicit = 1;
-	  for (dep = f->deps; dep != 0; dep = dep->next)
-	    {
-	      dep->file = enter_file (dep->name);
-	      dep->name = 0;
-	      dep->file->tried_implicit |= dep->changed;
-	    }
-	}
+        }
 
       dep = alloc_dep ();
-      dep->ignore_mtime = d->ignore_mtime;
-      s = d->name; /* Hijacking the name. */
-      d->name = 0;
-      if (recursions == 0)
-	{
-	  dep->file = lookup_file (s);
-	  if (dep->file == 0)
-	    dep->file = enter_file (s);
-	}
+      dep->ignore_mtime = pat->ignore_mtime;
+      s = strcache_add (pat->name);
+      if (recursions)
+        dep->name = s;
       else
-        dep->name = s;
-
-      if (d->intermediate_file == 0 && tryrules[foundrule]->terminal)
-	{
-	  /* If the file actually existed (was not an intermediate file),
-	     and the rule that found it was a terminal one, then we want
-	     to mark the found file so that it will not have implicit rule
-	     search done for it.  If we are not entering a `struct file' for
-	     it now, we indicate this with the `changed' flag.  */
-	  if (dep->file == 0)
-	    dep->changed = 1;
-	  else
-	    dep->file->tried_implicit = 1;
-	}
-
-      *d_ptr = dep;
-      d_ptr = &dep->next;
+        {
+          dep->file = lookup_file (s);
+          if (dep->file == 0)
+            dep->file = enter_file (s);
+        }
+
+      if (pat->file == 0 && tryrules[foundrule].rule->terminal)
+        {
+          /* If the file actually existed (was not an intermediate file), and
+             the rule that found it was a terminal one, then we want to mark
+             the found file so that it will not have implicit rule search done
+             for it.  If we are not entering a `struct file' for it now, we
+             indicate this with the `changed' flag.  */
+          if (dep->file == 0)
+            dep->changed = 1;
+          else
+            dep->file->tried_implicit = 1;
+        }
+
+      dep->next = file->deps;
+      file->deps = dep;
     }
 
-  *d_ptr = expl_d;
-
-  if (!checked_lastslash[foundrule])
+  if (!tryrules[foundrule].checked_lastslash)
     {
-      /* Always allocate new storage, since STEM might be
-         on the stack for an intermediate file.  */
+      /* Always allocate new storage, since STEM might be on the stack for an
+         intermediate file.  */
       file->stem = strcache_add_len (stem, stemlen);
       fullstemlen = stemlen;
@@ -924,5 +926,5 @@
 
       /* We want to prepend the directory from
-	 the original FILENAME onto the stem.  */
+         the original FILENAME onto the stem.  */
       fullstemlen = dirlen + stemlen;
       sp = alloca (fullstemlen + 1);
@@ -942,5 +944,5 @@
   /* Set precious flag. */
   {
-    struct file *f = lookup_file (rule->targets[matches[foundrule]]);
+    struct file *f = lookup_file (rule->targets[tryrules[foundrule].matches]);
     if (f && f->precious)
       file->precious = 1;
@@ -952,38 +954,39 @@
   if (rule->num > 1)
     for (ri = 0; ri < rule->num; ++ri)
-      if (ri != matches[foundrule])
-	{
-          char *p = alloca (rule->lens[ri] + fullstemlen + 1);
-	  struct file *f;
-	  struct dep *new = alloc_dep ();
-
-	  /* GKM FIMXE: handle '|' here too */
-	  memcpy (p, rule->targets[ri],
+      if (ri != tryrules[foundrule].matches)
+        {
+          char *nm = alloca (rule->lens[ri] + fullstemlen + 1);
+          char *p = nm;
+          struct file *f;
+          struct dep *new = alloc_dep ();
+
+          /* GKM FIMXE: handle '|' here too */
+          memcpy (p, rule->targets[ri],
                   rule->suffixes[ri] - rule->targets[ri] - 1);
-	  p += rule->suffixes[ri] - rule->targets[ri] - 1;
-	  memcpy (p, file->stem, fullstemlen);
-	  p += fullstemlen;
-	  memcpy (p, rule->suffixes[ri],
+          p += rule->suffixes[ri] - rule->targets[ri] - 1;
+          memcpy (p, file->stem, fullstemlen);
+          p += fullstemlen;
+          memcpy (p, rule->suffixes[ri],
                   rule->lens[ri] - (rule->suffixes[ri] - rule->targets[ri])+1);
-          new->name = strcache_add (p);
-	  new->file = enter_file (new->name);
-	  new->next = file->also_make;
-
-	  /* Set precious flag. */
-	  f = lookup_file (rule->targets[ri]);
-	  if (f && f->precious)
+          new->name = strcache_add (nm);
+          new->file = enter_file (new->name);
+          new->next = file->also_make;
+
+          /* Set precious flag. */
+          f = lookup_file (rule->targets[ri]);
+          if (f && f->precious)
             new->file->precious = 1;
 
-          /* Set the is_target flag so that this file is not treated
-             as intermediate by the pattern rule search algorithm and
+          /* Set the is_target flag so that this file is not treated as
+             intermediate by the pattern rule search algorithm and
              file_exists_p cannot pick it up yet.  */
           new->file->is_target = 1;
 
-	  file->also_make = new;
-	}
+          file->also_make = new;
+        }
 
  done:
-  free_idep_chain (deps);
   free (tryrules);
+  free (deplist);
 
   return rule != 0;
Index: /trunk/src/kmk/incdep.c
===================================================================
--- /trunk/src/kmk/incdep.c	(revision 2590)
+++ /trunk/src/kmk/incdep.c	(revision 2591)
@@ -114,17 +114,11 @@
 };
 
-struct incdep_recorded_files
-{
-    struct incdep_recorded_files *next;
+struct incdep_recorded_file
+{
+    struct incdep_recorded_file *next;
 
     /* the parameters */
     struct strcache2_entry *filename_entry; /* dep strcache; converted to a nameseq record. */
-    const char *pattern;                    /* NULL */
-    const char *pattern_percent;            /* NULL */
     struct dep *deps;                       /* All the names are dep strcache entries. */
-    unsigned int cmds_started;              /* 0 */
-    char *commands;                         /* NULL */
-    unsigned int commands_idx;              /* 0 */
-    int two_colon;                          /* 0 */
     const struct floc *flocp;               /* NILF */
 };
@@ -149,6 +143,6 @@
   struct incdep_variable_def *recorded_variable_defs_tail;
 
-  struct incdep_recorded_files *recorded_files_head;
-  struct incdep_recorded_files *recorded_files_tail;
+  struct incdep_recorded_file *recorded_file_head;
+  struct incdep_recorded_file *recorded_file_tail;
 #endif
 
@@ -232,4 +226,6 @@
 static void incdep_flush_it (struct floc *);
 static void eval_include_dep_file (struct incdep *, struct floc *);
+static void incdep_commit_recorded_file (const char *filename, struct dep *deps,
+                                         const struct floc *flocp);
 
 
@@ -501,5 +497,5 @@
   assert (!cur->recorded_variables_in_set_head);
   assert (!cur->recorded_variable_defs_head);
-  assert (!cur->recorded_files_head);
+  assert (!cur->recorded_file_head);
 #endif
 
@@ -727,6 +723,6 @@
           if (rec_size < sizeof (struct incdep_variable_def))
             rec_size = sizeof (struct incdep_variable_def);
-          if (rec_size < sizeof (struct incdep_recorded_files))
-            rec_size = sizeof (struct incdep_recorded_files);
+          if (rec_size < sizeof (struct incdep_recorded_file))
+            rec_size = sizeof (struct incdep_recorded_file);
           alloccache_init (&incdep_rec_caches[i], rec_size, "incdep rec",
                            incdep_cache_allocator, (void *)(size_t)i);
@@ -849,5 +845,5 @@
   struct incdep_variable_in_set *rec_vis;
   struct incdep_variable_def *rec_vd;
-  struct incdep_recorded_files *rec_f;
+  struct incdep_recorded_file *rec_f;
 
   /* define_variable_in_set */
@@ -898,6 +894,6 @@
   /* record_files */
 
-  rec_f = cur->recorded_files_head;
-  cur->recorded_files_head = cur->recorded_files_tail = NULL;
+  rec_f = cur->recorded_file_head;
+  cur->recorded_file_head = cur->recorded_file_tail = NULL;
   if (rec_f)
     do
@@ -905,22 +901,11 @@
         void *free_me = rec_f;
         struct dep *dep;
-        struct nameseq *filenames;
 
         for (dep = rec_f->deps; dep; dep = dep->next)
           dep->name = incdep_flush_strcache_entry ((struct strcache2_entry *)dep->name);
 
-        filenames = (struct nameseq *) alloccache_alloc (&nameseq_cache);
-        filenames->next = 0;
-        filenames->name = incdep_flush_strcache_entry (rec_f->filename_entry);
-
-        record_files (filenames,
-                      rec_f->pattern,
-                      rec_f->pattern_percent,
-                      rec_f->deps,
-                      rec_f->cmds_started,
-                      rec_f->commands,
-                      rec_f->commands_idx,
-                      rec_f->two_colon,
-                      rec_f->flocp);
+        incdep_commit_recorded_file (incdep_flush_strcache_entry (rec_f->filename_entry),
+                                     rec_f->deps,
+                                     rec_f->flocp);
 
         rec_f = rec_f->next;
@@ -1074,43 +1059,83 @@
 }
 
-/* Record files.*/
+/* Similar to record_files in read.c, only much much simpler. */
 static void
-incdep_record_files (struct incdep *cur,
-                     const char *filename, const char *pattern,
-                     const char *pattern_percent, struct dep *deps,
-                     unsigned int cmds_started, char *commands,
-                     unsigned int commands_idx, int two_colon,
-                     const struct floc *flocp)
+incdep_commit_recorded_file (const char *filename, struct dep *deps,
+                             const struct floc *flocp)
+{
+  struct file *f;
+
+  /* Perform some validations. */
+  if (filename[0] == '.'
+      && (   streq(filename, ".POSIX")
+          || streq(filename, ".EXPORT_ALL_VARIABLES")
+          || streq(filename, ".INTERMEDIATE")
+          || streq(filename, ".LOW_RESOLUTION_TIME")
+          || streq(filename, ".NOTPARALLEL")
+          || streq(filename, ".ONESHELL")
+          || streq(filename, ".PHONY")
+          || streq(filename, ".PRECIOUS")
+          || streq(filename, ".SECONDARY")
+          || streq(filename, ".SECONDTARGETEXPANSION")
+          || streq(filename, ".SILENT")
+          || streq(filename, ".SHELLFLAGS")
+          || streq(filename, ".SUFFIXES")
+         )
+     )
+    {
+      error (flocp, _("reserved filename '%s' used in dependency file, ignored"), filename);
+      return;
+    }
+
+  /* Lookup or create an entry in the database. */
+  f = enter_file (filename);
+  if (f->double_colon)
+    {
+      error (flocp, _("dependency file '%s' has a double colon entry already, ignoring"), filename);
+      return;
+    }
+  f->is_target = 1;
+
+  /* Append dependencies. */
+  deps = enter_prereqs (deps, NULL);
+  if (deps)
+    {
+      struct dep *last = f->deps;
+      if (!last)
+        f->deps = deps;
+      else
+        {
+          while (last->next)
+            last = last->next;
+          last->next = deps;
+        }
+    }
+}
+
+/* Record a file.*/
+static void
+incdep_record_file (struct incdep *cur,
+                    const char *filename,
+                    struct dep *deps,
+                    const struct floc *flocp)
 {
   if (cur->worker_tid == -1)
-    {
-      struct nameseq *filenames = (struct nameseq *) alloccache_alloc (&nameseq_cache);
-      filenames->next = 0;
-      filenames->name = filename;
-      record_files (filenames, pattern, pattern_percent, deps, cmds_started,
-                    commands, commands_idx, two_colon, flocp);
-    }
+    incdep_commit_recorded_file (filename, deps, flocp);
 #ifdef PARSE_IN_WORKER
   else
     {
-      struct incdep_recorded_files *rec =
-        (struct incdep_recorded_files *) incdep_alloc_rec (cur);
+      struct incdep_recorded_file *rec =
+        (struct incdep_recorded_file *) incdep_alloc_rec (cur);
 
       rec->filename_entry = (struct strcache2_entry *)filename;
-      rec->pattern = pattern;
-      rec->pattern_percent = pattern_percent;
       rec->deps = deps;
-      rec->cmds_started = cmds_started;
-      rec->commands = commands;
-      rec->commands_idx = commands_idx;
-      rec->two_colon = two_colon;
       rec->flocp = flocp;
 
       rec->next = NULL;
-      if (cur->recorded_files_tail)
-        cur->recorded_files_tail->next = rec;
+      if (cur->recorded_file_tail)
+        cur->recorded_file_tail->next = rec;
       else
-        cur->recorded_files_head = rec;
-      cur->recorded_files_tail = rec;
+        cur->recorded_file_head = rec;
+      cur->recorded_file_tail = rec;
     }
 #endif
@@ -1531,6 +1556,5 @@
 
               /* enter the file with its dependencies. */
-              incdep_record_files (curdep,
-                                   filename, NULL, NULL, deps, 0, NULL, 0, 0, f);
+              incdep_record_file (curdep, filename, deps, f);
             }
         }
@@ -1630,6 +1654,6 @@
        cur->recorded_variable_defs_head = NULL;
        cur->recorded_variable_defs_tail = NULL;
-       cur->recorded_files_head = NULL;
-       cur->recorded_files_tail = NULL;
+       cur->recorded_file_head = NULL;
+       cur->recorded_file_tail = NULL;
 #endif
 
Index: /trunk/src/kmk/job.c
===================================================================
--- /trunk/src/kmk/job.c	(revision 2590)
+++ /trunk/src/kmk/job.c	(revision 2591)
@@ -1,6 +1,6 @@
 /* Job execution and handling 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 Free Software
-Foundation, Inc.
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
@@ -182,5 +182,5 @@
 #endif	/* Don't have `union wait'.  */
 
-#ifndef	HAVE_UNISTD_H
+#if !defined(HAVE_UNISTD_H) && !defined(WINDOWS32)
 # ifndef _MSC_VER /* bird */
 int dup2 ();
@@ -196,4 +196,20 @@
 #endif
 
+/* Different systems have different requirements for pid_t.
+   Plus we have to support gettext string translation... Argh.  */
+static const char *
+pid2str (pid_t pid)
+{
+  static char pidstring[100];
+#if defined(WINDOWS32) && (__GNUC__ > 3 || _MSC_VER > 1300)
+  /* %Id is only needed for 64-builds, which were not supported by
+      older versions of Windows compilers.  */
+  sprintf (pidstring, "%Id", pid);
+#else
+  sprintf (pidstring, "%lu", (unsigned long) pid);
+#endif
+  return pidstring;
+}
+
 int getloadavg (double loadavg[], int nelem);
 int start_remote_job (char **argv, char **envp, int stdin_fd, int *is_remote,
@@ -248,5 +264,5 @@
  */
 int
-w32_kill(int pid, int sig)
+w32_kill(pid_t pid, int sig)
 {
   return ((process_kill((HANDLE)pid, sig) == TRUE) ? 0 : -1);
@@ -261,5 +277,5 @@
 {
   const char *const ext = unixy ? "sh" : "bat";
-  const char *error = NULL;
+  const char *error_string = NULL;
   char temp_path[MAXPATHLEN]; /* need to know its length */
   unsigned path_size = GetTempPath(sizeof temp_path, temp_path);
@@ -307,5 +323,5 @@
           else
             {
-              error = map_windows32_error_to_string (er);
+              error_string = map_windows32_error_to_string (er);
               break;
             }
@@ -316,5 +332,5 @@
           char *const path = xmalloc (final_size);
           memcpy (path, temp_path, final_size);
-          *fd = _open_osfhandle ((long)h, 0);
+          *fd = _open_osfhandle ((intptr_t)h, 0);
           if (unixy)
             {
@@ -330,7 +346,7 @@
 
   *fd = -1;
-  if (error == NULL)
-    error = _("Cannot create a temporary file\n");
-  fatal (NILF, error);
+  if (error_string == NULL)
+    error_string = _("Cannot create a temporary file\n");
+  fatal (NILF, error_string);
 
   /* not reached */
@@ -383,4 +399,51 @@
 #endif /* __EMX__ */
 
+/* determines whether path looks to be a Bourne-like shell. */
+int
+is_bourne_compatible_shell (const char *path)
+{
+  /* list of known unix (Bourne-like) shells */
+  const char *unix_shells[] = {
+    "sh",
+    "bash",
+    "ksh",
+    "rksh",
+    "zsh",
+    "ash",
+    "dash",
+    NULL
+  };
+  unsigned i, len;
+
+  /* find the rightmost '/' or '\\' */
+  const char *name = strrchr (path, '/');
+  char *p = strrchr (path, '\\');
+
+  if (name && p)    /* take the max */
+    name = (name > p) ? name : p;
+  else if (p)       /* name must be 0 */
+    name = p;
+  else if (!name)   /* name and p must be 0 */
+    name = path;
+
+  if (*name == '/' || *name == '\\') name++;
+
+  /* this should be able to deal with extensions on Windows-like systems */
+  for (i = 0; unix_shells[i] != NULL; i++) {
+    len = strlen(unix_shells[i]);
+#if defined(WINDOWS32) || defined(__MSDOS__)
+    if ((strncasecmp (name, unix_shells[i], len) == 0) &&
+      (strlen(name) >= len && (name[len] == '\0' || name[len] == '.')))
+#else
+    if ((strncmp (name, unix_shells[i], len) == 0) &&
+      (strlen(name) >= len && name[len] == '\0'))
+#endif
+	return 1; /* a known unix-style shell */
+  }
+
+  /* if not on the list, assume it's not a Bourne-like shell */
+  return 0;
+}
+
 
 
@@ -537,14 +600,14 @@
             {
               completed_child = c;
-              DB (DB_JOBS, (_("builtin child 0x%08lx (%s) PID %ld %s Status %ld\n"),
-                            (unsigned long int) c, c->file->name,
-                            (long) c->pid, c->remote ? _(" (remote)") : "",
+              DB (DB_JOBS, (_("builtin child %p (%s) PID %s %s Status %ld\n"),
+                            (void *)c, c->file->name,
+                            pid2str (c->pid), c->remote ? _(" (remote)") : "",
                             (long) c->status));
             }
           else
 #endif
-	  DB (DB_JOBS, (_("Live child 0x%08lx (%s) PID %ld %s\n"),
-                        (unsigned long int) c, c->file->name,
-                        (long) c->pid, c->remote ? _(" (remote)") : ""));
+	  DB (DB_JOBS, (_("Live child %p (%s) PID %s %s\n"),
+                        (void *)c, c->file->name, pid2str (c->pid),
+                        c->remote ? _(" (remote)") : ""));
 #ifdef VMS
 	  break;
@@ -681,6 +744,5 @@
                   }
                 else
-                  DB (DB_VERBOSE, ("Main thread handle = 0x%08lx\n",
-                                   (unsigned long)main_thread));
+                  DB (DB_VERBOSE, ("Main thread handle = %p\n", main_thread));
               }
 
@@ -745,8 +807,7 @@
 
       DB (DB_JOBS, (child_failed
-                    ? _("Reaping losing child 0x%08lx PID %ld %s\n")
-                    : _("Reaping winning child 0x%08lx PID %ld %s\n"),
-                    (unsigned long int) c, (long) c->pid,
-                    c->remote ? _(" (remote)") : ""));
+                    ? _("Reaping losing child %p PID %s %s\n")
+                    : _("Reaping winning child %p PID %s %s\n"),
+                    (void *)c, pid2str (c->pid), c->remote ? _(" (remote)") : ""));
 
       if (c->sh_batch_file) {
@@ -859,7 +920,6 @@
         notice_finished_file (c->file);
 
-      DB (DB_JOBS, (_("Removing child 0x%08lx PID %ld%s from chain.\n"),
-                    (unsigned long int) c, (long) c->pid,
-                    c->remote ? _(" (remote)") : ""));
+      DB (DB_JOBS, (_("Removing child %p PID %s%s from chain.\n"),
+                    (void *)c, pid2str (c->pid), c->remote ? _(" (remote)") : ""));
 
       /* Block fatal signals while frobnicating the list, so that
@@ -908,6 +968,6 @@
 #endif
   if (!jobserver_tokens)
-    fatal (NILF, "INTERNAL: Freeing child 0x%08lx (%s) but no tokens left!\n",
-           (unsigned long int) child, child->file->name);
+    fatal (NILF, "INTERNAL: Freeing child %p (%s) but no tokens left!\n",
+           (void *)child, child->file->name);
 
   /* If we're using the jobserver and this child is not the only outstanding
@@ -925,6 +985,6 @@
 	pfatal_with_name (_("write jobserver"));
 
-      DB (DB_JOBS, (_("Released token for child 0x%08lx (%s).\n"),
-                    (unsigned long int) child, child->file->name));
+      DB (DB_JOBS, (_("Released token for child %p (%s).\n"),
+                    (void *)child, child->file->name));
     }
 
@@ -1031,5 +1091,5 @@
   rval = sigaction (SIGCLD, &sa, NULL);
 #endif
-  if (rval != 0) 
+  if (rval != 0)
     fprintf (stderr, "sigaction: %s (%d)\n", strerror (errno), errno);
 #if defined SIGALRM
@@ -1062,10 +1122,13 @@
   static int bad_stdin = -1;
 #endif
-  register char *p;
-  int flags;
+  char *p;
+  /* Must be volatile to silence bogus GCC warning about longjmp/vfork.  */
+  /*volatile*/ int flags;
 #ifdef VMS
   char *argv;
 #else
   char **argv;
+  char ** volatile volatile_argv;
+  int volatile volatile_flags;
 #endif
 
@@ -1229,8 +1292,11 @@
       unixy_shell	/* the test is complicated and we already did it */
 #else
-      (argv[0] && !strcmp (argv[0], "/bin/sh"))
-#endif
-      && (argv[1]
-          && argv[1][0] == '-' && argv[1][1] == 'c' && argv[1][2] == '\0')
+      (argv[0] && is_bourne_compatible_shell(argv[0]))
+#endif
+      && (argv[1] && argv[1][0] == '-'
+	&&
+	    ((argv[1][1] == 'c' && argv[1][2] == '\0')
+	  ||
+	     (argv[1][1] == 'e' && argv[1][2] == 'c' && argv[1][3] == '\0')))
       && (argv[2] && argv[2][0] == ':' && argv[2][1] == '\0')
       && argv[3] == NULL)
@@ -1435,7 +1501,10 @@
 
 #else  /* !__EMX__ */
+      volatile_argv  = argv;            /* shut up gcc */
+      volatile_flags = flags;           /* ditto */
 
       child->pid = vfork ();
       environ = parent_environ;	/* Restore value child may have clobbered.  */
+      argv = volatile_argv;             /* shut up gcc */
       if (child->pid == 0)
 	{
@@ -1445,5 +1514,5 @@
           /* If we aren't running a recursive command and we have a jobserver
              pipe, close it before exec'ing.  */
-          if (!(flags & COMMANDS_RECURSE) && job_fds[0] >= 0)
+          if (!(volatile_flags & COMMANDS_RECURSE) && job_fds[0] >= 0)
             {
               close (job_fds[0]);
@@ -1452,4 +1521,10 @@
           if (job_rfd >= 0)
             close (job_rfd);
+
+#ifdef SET_STACK_SIZE
+          /* Reset limits, if necessary.  */
+          if (stack_limit.rlim_cur)
+            setrlimit (RLIMIT_STACK, &stack_limit);
+#endif
 
 	  child_execute_job (child->good_stdin ? 0 : bad_stdin, 1,
@@ -1553,5 +1628,5 @@
 
       if (hPID != INVALID_HANDLE_VALUE)
-        child->pid = (int) hPID;
+        child->pid = (pid_t) hPID;
       else {
         int i;
@@ -1675,7 +1750,7 @@
     case cs_running:
       c->next = children;
-      DB (DB_JOBS, (_("Putting child 0x%08lx (%s) PID %ld%s on the chain.\n"),
-                    (unsigned long int) c, c->file->name,
-                    (long) c->pid, c->remote ? _(" (remote)") : ""));
+      DB (DB_JOBS, (_("Putting child %p (%s) PID %s%s on the chain.\n"),
+                    (void *)c, c->file->name, pid2str (c->pid),
+                    c->remote ? _(" (remote)") : ""));
       children = c;
       /* One more job slot is in use.  */
@@ -1820,5 +1895,5 @@
 	 Copy the remaining uninteresting text to the output.  */
       if (out != in)
-	strcpy (out, in);
+	memmove (out, in, strlen (in) + 1);
 
       /* Finally, expand the line.  */
@@ -1830,6 +1905,5 @@
      `struct child', and add that to the chain.  */
 
-  c = xmalloc (sizeof (struct child));
-  memset (c, '\0', sizeof (struct child));
+  c = xcalloc (sizeof (struct child));
   c->file = file;
   c->command_lines = lines;
@@ -1935,6 +2009,6 @@
 	if (got_token == 1)
           {
-            DB (DB_JOBS, (_("Obtained token for child 0x%08lx (%s).\n"),
-                          (unsigned long int) c, c->file->name));
+            DB (DB_JOBS, (_("Obtained token for child %p (%s).\n"),
+                          (void *)c, c->file->name));
             break;
           }
@@ -2288,5 +2362,5 @@
       int i;
       fprintf(stderr,
-              _("process_easy() failed failed to launch process (e=%ld)\n"),
+              _("process_easy() failed to launch process (e=%ld)\n"),
               process_last_err(hPID));
       for (i = 0; argv[i]; i++)
@@ -2317,7 +2391,12 @@
           break;
       else
+	{
+	  char *pidstr = xstrdup (pid2str ((pid_t)hWaitPID));
+
           fprintf(stderr,
-                  _("make reaped child pid %ld, still waiting for pid %ld\n"),
-                  (DWORD)hWaitPID, (DWORD)hPID);
+                  _("make reaped child pid %s, still waiting for pid %s\n"),
+		  pidstr, pid2str ((pid_t)hPID));
+	  free (pidstr);
+	}
     }
 
@@ -2478,5 +2557,5 @@
 static char **
 construct_command_argv_internal (char *line, char **restp, char *shell,
-                                 char *ifs, int flags,
+                                 char *shellflags, char *ifs, int flags,
 				 char **batch_filename_ptr)
 {
@@ -2519,5 +2598,5 @@
 				 "continue", "export", "read", "readonly",
 				 "shift", "times", "trap", "switch", "unset",
-                                 0 };
+                                 "ulimit", 0 };
 
   char *sh_chars;
@@ -2561,10 +2640,13 @@
 #elif defined (WINDOWS32)
   static char sh_chars_dos[] = "\"|&<>";
-  static char *sh_cmds_dos[] = { "break", "call", "cd", "chcp", "chdir", "cls",
-			     "copy", "ctty", "date", "del", "dir", "echo",
-			     "erase", "exit", "for", "goto", "if", "if", "md",
-			     "mkdir", "path", "pause", "prompt", "rd", "rem",
-                             "ren", "rename", "rmdir", "set", "shift", "time",
-                             "type", "ver", "verify", "vol", ":", 0 };
+  static char *sh_cmds_dos[] = { "assoc", "break", "call", "cd", "chcp",
+				 "chdir", "cls", "color", "copy", "ctty",
+				 "date", "del", "dir", "echo", "echo.",
+				 "endlocal", "erase", "exit", "for", "ftype",
+				 "goto", "if", "if", "md", "mkdir", "path",
+				 "pause", "prompt", "rd", "rem", "ren",
+				 "rename", "rmdir", "set", "setlocal",
+				 "shift", "time", "title", "type", "ver",
+				 "verify", "vol", ":", 0 };
   static char sh_chars_sh[] = "#;\"*?[]&|<>(){}$`^";
   static char *sh_cmds_sh[] = { "cd", "eval", "exec", "exit", "login",
@@ -2588,5 +2670,5 @@
                              "login", "logout", "read", "readonly", "set",
                              "shift", "switch", "test", "times", "trap",
-                             "umask", "wait", "while", 0 };
+                             "ulimit", "umask", "unset", "wait", "while", 0 };
 # ifdef HAVE_DOS_PATHS
   /* This is required if the MSYS/Cygwin ports (which do not define
@@ -2727,4 +2809,10 @@
       if (*ap != ' ' && *ap != '\t' && *ap != '\n')
 	goto slow;
+
+  if (shellflags != 0)
+    if (shellflags[0] != '-'
+        || ((shellflags[1] != 'c' || shellflags[2] != '\0')
+            && (shellflags[1] != 'e' || shellflags[2] != 'c' || shellflags[3] != '\0')))
+      goto slow;
 
   i = strlen (line) + 1;
@@ -2810,4 +2898,7 @@
 	goto slow;
 #endif /* !KMK */
+      else if (one_shell && *p == '\n')
+	/* In .ONESHELL mode \n is a separator like ; or && */
+	goto slow;
 #ifdef  __MSDOS__
       else if (*p == '.' && p[1] == '.' && p[2] == '.' && p[3] != '.')
@@ -3032,32 +3123,95 @@
     return 0;
 #endif /* WINDOWS32 */
+
   {
     /* SHELL may be a multi-word command.  Construct a command line
-       "SHELL -c LINE", with all special chars in LINE escaped.
+       "$(SHELL) $(.SHELLFLAGS) LINE", with all special chars in LINE escaped.
        Then recurse, expanding this command line to get the final
        argument list.  */
 
     unsigned int shell_len = strlen (shell);
-#ifndef VMS
-    static char minus_c[] = " -c ";
-#else
-    static char minus_c[] = "";
-#endif
     unsigned int line_len = strlen (line);
-
-    char *new_line = alloca (shell_len + (sizeof (minus_c)-1)
-                             + (line_len*2) + 1);
+    unsigned int sflags_len = strlen (shellflags);
     char *command_ptr = NULL; /* used for batch_mode_shell mode */
+    char *new_line;
 
 # ifdef __EMX__ /* is this necessary? */
     if (!unixy_shell)
-      minus_c[1] = '/'; /* " /c " */
+      shellflags[0] = '/'; /* "/c" */
 # endif
 
+    /* In .ONESHELL mode we are allowed to throw the entire current
+	recipe string at a single shell and trust that the user
+	has configured the shell and shell flags, and formatted
+	the string, appropriately. */
+    if (one_shell)
+      {
+	/* If the shell is Bourne compatible, we must remove and ignore
+	   interior special chars [@+-] because they're meaningless to
+	   the shell itself. If, however, we're in .ONESHELL mode and
+	   have changed SHELL to something non-standard, we should
+	   leave those alone because they could be part of the
+	   script. In this case we must also leave in place
+	   any leading [@+-] for the same reason.  */
+
+	/* Remove and ignore interior prefix chars [@+-] because they're
+	     meaningless given a single shell. */
+#if defined __MSDOS__ || defined (__EMX__)
+	if (unixy_shell)     /* the test is complicated and we already did it */
+#else
+	if (is_bourne_compatible_shell(shell))
+#endif
+          {
+            const char *f = line;
+            char *t = line;
+
+            /* Copy the recipe, removing and ignoring interior prefix chars
+               [@+-]: they're meaningless in .ONESHELL mode.  */
+            while (f[0] != '\0')
+              {
+                int esc = 0;
+
+                /* This is the start of a new recipe line.
+                   Skip whitespace and prefix characters.  */
+                while (isblank (*f) || *f == '-' || *f == '@' || *f == '+')
+                  ++f;
+
+                /* Copy until we get to the next logical recipe line.  */
+                while (*f != '\0')
+                  {
+                    *(t++) = *(f++);
+                    if (f[-1] == '\\')
+                      esc = !esc;
+                    else
+                      {
+                        /* On unescaped newline, we're done with this line.  */
+                        if (f[-1] == '\n' && ! esc)
+                          break;
+
+                        /* Something else: reset the escape sequence.  */
+                        esc = 0;
+                      }
+                  }
+              }
+            *t = '\0';
+          }
+
+	new_argv = xmalloc (4 * sizeof (char *));
+	new_argv[0] = xstrdup(shell);
+	new_argv[1] = xstrdup(shellflags);
+	new_argv[2] = line;
+	new_argv[3] = NULL;
+	return new_argv;
+      }
+
+    new_line = alloca (shell_len + 1 + sflags_len + 1
+                             + (line_len*2) + 1);
     ap = new_line;
     memcpy (ap, shell, shell_len);
     ap += shell_len;
-    memcpy (ap, minus_c, sizeof (minus_c) - 1);
-    ap += sizeof (minus_c) - 1;
+    *(ap++) = ' ';
+    memcpy (ap, shellflags, sflags_len);
+    ap += sflags_len;
+    *(ap++) = ' ';
     command_ptr = ap;
     for (p = line; *p != '\0'; ++p)
@@ -3109,5 +3263,5 @@
 	*ap++ = *p;
       }
-    if (ap == new_line + shell_len + sizeof (minus_c) - 1)
+    if (ap == new_line + shell_len + sflags_len + 2)
       /* Line was empty.  */
       return 0;
@@ -3161,6 +3315,8 @@
     } else
 #endif /* WINDOWS32 */
+
     if (unixy_shell)
-      new_argv = construct_command_argv_internal (new_line, 0, 0, 0, flags, 0);
+      new_argv = construct_command_argv_internal (new_line, 0, 0, 0, 0, flags, 0);
+
 #ifdef __EMX__
     else if (!unixy_shell)
@@ -3173,6 +3329,9 @@
         char *q = new_line;
         memcpy (new_line, line, line_len + 1);
-        /* replace all backslash-newline combination and also following tabs */
-        while (*q != '\0')
+        /* Replace all backslash-newline combination and also following tabs.
+           Important: stop at the first '\n' because that's what the loop above
+           did. The next line starting at restp[0] will be executed during the
+           next call of this function. */
+        while (*q != '\0' && *q != '\n')
           {
             if (q[0] == '\\' && q[1] == '\n')
@@ -3235,8 +3394,8 @@
            cannot backslash-escape the special characters (see above).  */
         new_argv = xmalloc (sizeof (char *));
-        line_len = strlen (new_line) - shell_len - sizeof (minus_c) + 1;
+        line_len = strlen (new_line) - shell_len - sflags_len - 2;
         new_argv[0] = xmalloc (line_len + 1);
         strncpy (new_argv[0],
-                 new_line + shell_len + sizeof (minus_c) - 1, line_len);
+                 new_line + shell_len + sflags_len + 2, line_len);
         new_argv[0][line_len] = '\0';
       }
@@ -3270,5 +3429,5 @@
                         int cmd_flags, char **batch_filename_ptr)
 {
-  char *shell, *ifs;
+  char *shell, *ifs, *shellflags;
   char **argv;
 
@@ -3375,4 +3534,5 @@
 #endif /* __EMX__ */
 
+    shellflags = allocated_variable_expand_for_file ("$(.SHELLFLAGS)", file);
     ifs = allocated_variable_expand_for_file ("$(IFS)", file);
 
@@ -3400,5 +3560,5 @@
     unixy_shell = 1;
     batch_mode_shell = 0;
-    argv = construct_command_argv_internal (line, restp, shell, ifs,
+    argv = construct_command_argv_internal (line, restp, shell, shellflags, ifs,
                                             cmd_flags, batch_filename_ptr);
     batch_mode_shell = saved_batch_mode_shell;
@@ -3410,8 +3570,9 @@
   else
 #endif /* CONFIG_WITH_KMK_BUILTIN */
-  argv = construct_command_argv_internal (line, restp, shell, ifs,
+  argv = construct_command_argv_internal (line, restp, shell, shellflags, ifs,
                                           cmd_flags, batch_filename_ptr);
 
   free (shell);
+  free (shellflags);
   free (ifs);
 #endif /* !VMS */
@@ -3437,5 +3598,5 @@
   return fd;
 }
-#endif /* !HAPE_DUP2 && !_AMIGA */
+#endif /* !HAVE_DUP2 && !_AMIGA */
 
 #ifdef CONFIG_WITH_PRINT_TIME_SWITCH
Index: /trunk/src/kmk/job.h
===================================================================
--- /trunk/src/kmk/job.h	(revision 2590)
+++ /trunk/src/kmk/job.h	(revision 2591)
@@ -1,5 +1,6 @@
 /* Definitions for managing subprocesses in GNU Make.
 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
+Foundation, Inc.
 This file is part of GNU Make.
 
@@ -54,4 +55,5 @@
     int efn;			/* Completion event flag number */
     int cstatus;		/* Completion status */
+    char *comname;              /* Temporary command file name */
 #endif
     char *sh_batch_file;        /* Script file for shell commands */
@@ -74,4 +76,5 @@
 extern struct child *children;
 
+int is_bourne_compatible_shell(const char *path);
 void new_job (struct file *file);
 void reap_children (int block, int err);
Index: /trunk/src/kmk/kmkbuiltin.c
===================================================================
--- /trunk/src/kmk/kmkbuiltin.c	(revision 2590)
+++ /trunk/src/kmk/kmkbuiltin.c	(revision 2591)
@@ -120,5 +120,5 @@
         if (!argv[argc])
         {
-            printf("kmk_builtin: out of memory. argc=%d len=%d\n", argc, pszEnd - pszCmd + 1);
+            printf("kmk_builtin: out of memory. argc=%d len=%d\n", argc, (int)(pszEnd - pszCmd + 1));
             break;
         }
Index: /trunk/src/kmk/kmkbuiltin/cmp_util.c
===================================================================
--- /trunk/src/kmk/kmkbuiltin/cmp_util.c	(revision 2590)
+++ /trunk/src/kmk/kmkbuiltin/cmp_util.c	(revision 2591)
@@ -363,9 +363,9 @@
 
         bytes_read = read(fd1, b1, blk_sz);
-        if (bytes_read != blk_sz)
+        if (bytes_read != (off_t)blk_sz)
             goto l_read_error;
 
         bytes_read = read(fd2, b2, blk_sz);
-        if (bytes_read != blk_sz)
+        if (bytes_read != (off_t)blk_sz)
             goto l_read_error;
 
Index: /trunk/src/kmk/kmkbuiltin/darwin.c
===================================================================
--- /trunk/src/kmk/kmkbuiltin/darwin.c	(revision 2590)
+++ /trunk/src/kmk/kmkbuiltin/darwin.c	(revision 2591)
@@ -29,4 +29,5 @@
 #include "config.h"
 #include <sys/stat.h>
+#include <sys/time.h>
 #include <unistd.h>
 
Index: /trunk/src/kmk/kmkbuiltin/echo.c
===================================================================
--- /trunk/src/kmk/kmkbuiltin/echo.c	(revision 2590)
+++ /trunk/src/kmk/kmkbuiltin/echo.c	(revision 2591)
@@ -39,5 +39,5 @@
 #endif /* not lint */
 #include <sys/cdefs.h>
-//__FBSDID("$FreeBSD: src/bin/echo/echo.c,v 1.17 2004/04/06 20:06:46 markm Exp $");
+/*__FBSDID("$FreeBSD: src/bin/echo/echo.c,v 1.17 2004/04/06 20:06:46 markm Exp $");*/
 #endif
 
Index: /trunk/src/kmk/kmkbuiltin/expr.c
===================================================================
--- /trunk/src/kmk/kmkbuiltin/expr.c	(revision 2590)
+++ /trunk/src/kmk/kmkbuiltin/expr.c	(revision 2591)
@@ -281,4 +281,7 @@
 }
 
+#ifdef __GNUC__
+__attribute__((noreturn))
+#endif
 static void
 error(void)
Index: /trunk/src/kmk/kmkbuiltin/kDepObj.c
===================================================================
--- /trunk/src/kmk/kmkbuiltin/kDepObj.c	(revision 2590)
+++ /trunk/src/kmk/kmkbuiltin/kDepObj.c	(revision 2591)
@@ -274,5 +274,5 @@
 
         /* process selected record types. */
-        dprintf(("%#07x: %#04x %#05x\n", (const KU8*)pHdr - pbFile, pHdr->bType, pHdr->cbRec));
+        dprintf(("%#07" KUPTR_PRI ": %#04x %#05x\n", (const KU8*)pHdr - pbFile, pHdr->bType, pHdr->cbRec));
         switch (pHdr->bType)
         {
@@ -692,5 +692,5 @@
         if (off + 8 > cbSrcFiles)
         {
-            fprintf(stderr, "%s: CV source file entry at %08" KX32_PRI " is too long; cbSrcFiles=%#" KSIZE_PRI "\n",
+            fprintf(stderr, "%s: CV source file entry at %08" KX32_PRI " is too long; cbSrcFiles=%#" KX32_PRI "\n",
                     argv0, off, cbSrcFiles);
             return 1;
@@ -701,5 +701,5 @@
         if (off + cbSrc > cbSrcFiles)
         {
-            fprintf(stderr, "%s: CV source file entry at %08" KX32_PRI " is too long; cbSrc=%#" KX32_PRI " cbSrcFiles=%#" KSIZE_PRI "\n",
+            fprintf(stderr, "%s: CV source file entry at %08" KX32_PRI " is too long; cbSrc=%#" KX32_PRI " cbSrcFiles=%#" KX32_PRI "\n",
                     argv0, off, cbSrc, cbSrcFiles);
             return 1;
Index: /trunk/src/kmk/kmkbuiltin/kbuild_version.c
===================================================================
--- /trunk/src/kmk/kmkbuiltin/kbuild_version.c	(revision 2590)
+++ /trunk/src/kmk/kmkbuiltin/kbuild_version.c	(revision 2591)
@@ -53,5 +53,5 @@
 
     printf("%.*s - kBuild version %d.%d.%d (r%u)\n",
-           tmp - argv0, argv0,
+           (int)(tmp - argv0), argv0,
            KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH,
            KBUILD_SVN_REV);
Index: /trunk/src/kmk/kmkbuiltin/printf.c
===================================================================
--- /trunk/src/kmk/kmkbuiltin/printf.c	(revision 2590)
+++ /trunk/src/kmk/kmkbuiltin/printf.c	(revision 2591)
@@ -207,5 +207,5 @@
 	(void)funcname;
 	if (rc != 0)
-		fatal (NILF, _("$(%s): failure rc=%d\n"), rc);
+		fatal (NILF, _("$(%s): failure rc=%d\n"), funcname, rc);
 	return o;
 }
Index: /trunk/src/kmk/main.c
===================================================================
--- /trunk/src/kmk/main.c	(revision 2590)
+++ /trunk/src/kmk/main.c	(revision 2591)
@@ -1,6 +1,6 @@
 /* Argument parsing and main program of GNU Make.
 Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
-1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software
-Foundation, Inc.
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
@@ -81,5 +81,4 @@
 void print_dir_data_base (void);
 void print_rule_data_base (void);
-void print_file_data_base (void);
 void print_vpath_data_base (void);
 
@@ -110,5 +109,5 @@
 static void decode_switches (int argc, char **argv, int env);
 static void decode_env_switches (char *envar, unsigned int len);
-static void define_makeflags (int all, int makefile);
+static const char *define_makeflags (int all, int makefile);
 static char *quote_for_env (char *out, const char *in);
 static void initialize_global_hash_tables (void);
@@ -265,4 +264,11 @@
 static struct stringlist *makefiles = 0;
 
+/* Size of the stack when we started.  */
+
+#ifdef SET_STACK_SIZE
+struct rlimit stack_limit;
+#endif
+
+
 /* Number of job slots (commands that can be run at once).  */
 
@@ -309,4 +315,7 @@
 
 static struct stringlist *new_files = 0;
+
+/* List of strings to be eval'd.  */
+static struct stringlist *eval_strings = 0;
 
 /* If nonzero, we should just print usage and exit.  */
@@ -382,4 +391,6 @@
   -e, --environment-overrides\n\
                               Environment variables override makefiles.\n"),
+    N_("\
+  --eval=STRING               Evaluate STRING as a makefile statement.\n"),
     N_("\
   -f FILE, --file=FILE, --makefile=FILE\n\
@@ -544,4 +555,5 @@
     { CHAR_MAX+5, flag, &warn_undefined_variables_flag, 1, 1, 0, 0, 0,
       "warn-undefined-variables" },
+    { CHAR_MAX+6, string, &eval_strings, 1, 0, 0, 0, 0, "eval" },
     { 0, 0, 0, 0, 0, 0, 0, 0, 0 }
   };
@@ -596,13 +608,11 @@
 unsigned int makelevel;
 
-/* First file defined in the makefile whose name does not
-   start with `.'.  This is the default to remake if the
-   command line does not specify.  */
-
-struct file *default_goal_file;
-
-/* Pointer to the value of the .DEFAULT_GOAL special
-   variable.  */
-char ** default_goal_name;
+/* Pointer to the value of the .DEFAULT_GOAL special variable.
+   The value will be the name of the goal to remake if the command line
+   does not override it.  It can be set by the makefile, or else it's
+   the first target defined in the makefile whose name does not start
+   with '.'.  */
+
+struct variable * default_goal_var;
 
 /* Pointer to structure for the file .DEFAULT
@@ -622,4 +632,10 @@
 int second_expansion;
 
+/* Nonzero if we have seen the '.ONESHELL' target.
+   This causes the entire recipe to be handed to SHELL
+   as a single string, potentially containing newlines.  */
+
+int one_shell;
+
 #ifdef CONFIG_WITH_2ND_TARGET_EXPANSION
 /* Nonzero if we have seen the '.SECONDTARGETEXPANSION' target.
@@ -630,4 +646,5 @@
 
 #ifndef CONFIG_WITH_EXTENDED_NOTPARALLEL
+
 /* Nonzero if we have seen the `.NOTPARALLEL' target.
    This turns off parallel builds for this invocation of make.  */
@@ -667,9 +684,9 @@
 #endif
 
-#if !defined HAVE_BSD_SIGNAL && !defined bsd_signal
+#if !HAVE_DECL_BSD_SIGNAL && !defined bsd_signal
 # if !defined HAVE_SIGACTION
 #  define bsd_signal signal
 # else
-typedef RETSIGTYPE (*bsd_signal_ret_t) ();
+typedef RETSIGTYPE (*bsd_signal_ret_t) (int);
 
 static bsd_signal_ret_t
@@ -924,6 +941,6 @@
     {
       sprintf(errmsg,
-              _("%s: Interrupt/Exception caught (code = 0x%lx, addr = 0x%lx)\n"),
-              prg, exrec->ExceptionCode, (DWORD)exrec->ExceptionAddress);
+              _("%s: Interrupt/Exception caught (code = 0x%lx, addr = 0x%p)\n"),
+              prg, exrec->ExceptionCode, exrec->ExceptionAddress);
       fprintf(stderr, errmsg);
       exit(255);
@@ -931,7 +948,7 @@
 
   sprintf(errmsg,
-          _("\nUnhandled exception filter called from program %s\nExceptionCode = %lx\nExceptionFlags = %lx\nExceptionAddress = %lx\n"),
+          _("\nUnhandled exception filter called from program %s\nExceptionCode = %lx\nExceptionFlags = %lx\nExceptionAddress = 0x%p\n"),
           prg, exrec->ExceptionCode, exrec->ExceptionFlags,
-          (DWORD)exrec->ExceptionAddress);
+          exrec->ExceptionAddress);
 
   if (exrec->ExceptionCode == EXCEPTION_ACCESS_VIOLATION
@@ -939,7 +956,7 @@
     sprintf(&errmsg[strlen(errmsg)],
             (exrec->ExceptionInformation[0]
-             ? _("Access violation: write operation at address %lx\n")
-             : _("Access violation: read operation at address %lx\n")),
-            exrec->ExceptionInformation[1]);
+             ? _("Access violation: write operation at address 0x%p\n")
+             : _("Access violation: read operation at address 0x%p\n")),
+            (PVOID)exrec->ExceptionInformation[1]);
 
   /* turn this on if we want to put stuff in the event log too */
@@ -1015,6 +1032,6 @@
     sprintf (sh_path, "%s", search_token);
     default_shell = xstrdup (w32ify (sh_path, 0));
-    DB (DB_VERBOSE,
-        (_("find_and_set_shell setting default_shell = %s\n"), default_shell));
+    DB (DB_VERBOSE, (_("find_and_set_shell() setting default_shell = %s\n"),
+                     default_shell));
     sh_found = 1;
   } else if (!no_default_sh_exe &&
@@ -1026,6 +1043,6 @@
     sprintf (sh_path, "%s", search_token);
     default_shell = xstrdup (w32ify (sh_path, 0));
-    DB (DB_VERBOSE,
-        (_("find_and_set_shell setting default_shell = %s\n"), default_shell));
+    DB (DB_VERBOSE, (_("find_and_set_shell() setting default_shell = %s\n"),
+                     default_shell));
     sh_found = 1;
   } else {
@@ -1068,5 +1085,5 @@
       if (sh_found)
         DB (DB_VERBOSE,
-            (_("find_and_set_shell path search set default_shell = %s\n"),
+            (_("find_and_set_shell() path search set default_shell = %s\n"),
              default_shell));
     }
@@ -1383,9 +1400,13 @@
 
     /* Set the stack limit huge so that alloca does not fail.  */
-    if (getrlimit (RLIMIT_STACK, &rlim) == 0)
+    if (getrlimit (RLIMIT_STACK, &rlim) == 0
+        && rlim.rlim_cur > 0 && rlim.rlim_cur < rlim.rlim_max)
       {
+        stack_limit = rlim;
         rlim.rlim_cur = rlim.rlim_max;
         setrlimit (RLIMIT_STACK, &rlim);
       }
+    else
+      stack_limit.rlim_cur = 0;
   }
 #endif
@@ -1402,5 +1423,4 @@
 #endif
 
-  default_goal_file = 0;
   reading_file = 0;
 
@@ -1419,7 +1439,9 @@
   /* Set up gettext/internationalization support.  */
   setlocale (LC_ALL, "");
+  /* The cast to void shuts up compiler warnings on systems that
+     disable NLS.  */
 #ifdef LOCALEDIR /* bird */
-  bindtextdomain (PACKAGE, LOCALEDIR);
-  textdomain (PACKAGE);
+  (void)bindtextdomain (PACKAGE, LOCALEDIR);
+  (void)textdomain (PACKAGE);
 #endif
 
@@ -1432,5 +1454,5 @@
 #define	ADD_SIG(sig)	fatal_signal_mask |= sigmask (sig)
 #else
-#define	ADD_SIG(sig)
+#define	ADD_SIG(sig)    (void)sig      /* Needed to avoid warnings in MSVC.  */
 #endif
 #endif
@@ -1587,32 +1609,34 @@
 
   /* Initialize the special variables.  */
-  define_variable (".VARIABLES", 10, "", o_default, 0)->special = 1;
-  /* define_variable (".TARGETS", 8, "", o_default, 0)->special = 1; */
-  define_variable (".RECIPEPREFIX", 13, "", o_default, 0)->special = 1;
-
-  /* Set up .FEATURES */
-  define_variable (".FEATURES", 9,
-                   "target-specific order-only second-expansion else-if",
-                   o_default, 0);
+  define_variable_cname (".VARIABLES", "", o_default, 0)->special = 1;
+  /* define_variable_cname (".TARGETS", "", o_default, 0)->special = 1; */
+  define_variable_cname (".RECIPEPREFIX", "", o_default, 0)->special = 1;
+  define_variable_cname (".SHELLFLAGS", "-c", o_default, 0);
+
+  /* Set up .FEATURES
+     We must do this in multiple calls because define_variable_cname() is
+     a macro and some compilers (MSVC) don't like conditionals in macros.  */
+  {
+    const char *features = "target-specific order-only second-expansion"
+                           " else-if shortest-stem undefine"
 #ifndef NO_ARCHIVES
-  do_variable_definition (NILF, ".FEATURES", "archives",
-                          o_default, f_append, 0);
+                           " archives"
 #endif
 #ifdef MAKE_JOBSERVER
-  do_variable_definition (NILF, ".FEATURES", "jobserver",
-                          o_default, f_append, 0);
+                           " jobserver"
 #endif
 #ifdef MAKE_SYMLINKS
-  do_variable_definition (NILF, ".FEATURES", "check-symlink",
-                          o_default, f_append, 0);
+                           " check-symlink"
 #endif
 #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
-  do_variable_definition (NILF, ".FEATURES", "explicit-multitarget",
-                          o_default, f_append, 0);
+                           " explicit-multitarget"
 #endif
 #ifdef CONFIG_WITH_PREPEND_ASSIGNMENT
-  do_variable_definition (NILF, ".FEATURES", "prepend-assignment",
-                          o_default, f_append, 0);
-#endif
+                           " prepend-assignment"
+#endif
+                           ;
+
+    define_variable_cname (".FEATURES", features, o_default, 0);
+  }
 
 #ifdef KMK
@@ -1675,12 +1699,11 @@
                 shell_var.name = v->name;
 #endif
-                shell_var.length = 5; /* bird - gotta set the length too! */
+                shell_var.length = 5;
 #ifndef CONFIG_WITH_VALUE_LENGTH
                 shell_var.value = xstrdup (ep + 1);
 #else
-                shell_var.value = savestring (v->value, v->value_length);
+                shell_var.value = xstrndup (v->value, v->value_length);
                 shell_var.value_length = v->value_length;
 #endif
-
               }
 
@@ -1699,7 +1722,6 @@
      */
     if (!unix_path)
-      define_variable("PATH", 4,
-                      windows32_path ? windows32_path : "",
-                      o_env, 1)->export = v_export;
+      define_variable_cname ("PATH", windows32_path ? windows32_path : "",
+                             o_env, 1)->export = v_export;
 #endif
 #else /* For Amiga, read the ENV: device, ignoring all dirs */
@@ -1747,5 +1769,7 @@
 #endif
 #endif /* !KMK */
+
   decode_switches (argc, argv, 0);
+
 #ifdef WINDOWS32
   if (suspend_flag) {
@@ -1815,5 +1839,5 @@
 # endif
       )
-    argv[0] = xstrdup (concat (current_directory, "/", argv[0]));
+    argv[0] = xstrdup (concat (3, current_directory, "/", argv[0]));
 #else  /* !__MSDOS__ */
   if (current_directory[0] != '\0'
@@ -1824,5 +1848,5 @@
 #endif
       )
-    argv[0] = xstrdup (concat (current_directory, "/", argv[0]));
+    argv[0] = xstrdup (concat (3, current_directory, "/", argv[0]));
 #endif /* !__MSDOS__ */
 #endif /* WINDOWS32 */
@@ -1831,6 +1855,6 @@
   /* The extra indirection through $(MAKE_COMMAND) is done
      for hysterical raisins.  */
-  (void) define_variable ("MAKE_COMMAND", 12, argv[0], o_default, 0);
-  (void) define_variable ("MAKE", 4, "$(MAKE_COMMAND)", o_default, 1);
+  define_variable_cname ("MAKE_COMMAND", argv[0], o_default, 0);
+  define_variable_cname ("MAKE", "$(MAKE_COMMAND)", o_default, 1);
 #ifdef KMK
   (void) define_variable ("KMK", 3, argv[0], o_default, 1);
@@ -1873,6 +1897,5 @@
       /* Define an unchangeable variable with a name that no POSIX.2
 	 makefile could validly use for its own variable.  */
-      (void) define_variable ("-*-command-variables-*-", 23,
-			      value, o_automatic, 0);
+      define_variable_cname ("-*-command-variables-*-", value, o_automatic, 0);
 
       /* Define the variable; this will not override any user definition.
@@ -1883,9 +1906,9 @@
          a reference to this hidden variable is written instead. */
 #ifdef KMK
-      (void) define_variable ("KMK_OVERRIDES", 13,
-			      "${-*-command-variables-*-}", o_env, 1);
+      define_variable_cname ("KMK_OVERRIDES", "${-*-command-variables-*-}",
+                             o_env, 1);
 #else
-      (void) define_variable ("MAKEOVERRIDES", 13,
-			      "${-*-command-variables-*-}", o_env, 1);
+      define_variable_cname ("MAKEOVERRIDES", "${-*-command-variables-*-}",
+                             o_env, 1);
 #endif
     }
@@ -2058,5 +2081,5 @@
     }
 
-  (void) define_variable ("CURDIR", 6, current_directory, o_file, 0);
+  define_variable_cname ("CURDIR", current_directory, o_file, 0);
 
   /* Read any stdin makefiles into temporary files.  */
@@ -2198,8 +2221,42 @@
   default_file = enter_file (strcache_add (".DEFAULT"));
 
-  {
-    struct variable *v = define_variable (".DEFAULT_GOAL", 13, "", o_file, 0);
-    default_goal_name = &v->value;
-  }
+  default_goal_var = define_variable_cname (".DEFAULT_GOAL", "", o_file, 0);
+
+  /* Evaluate all strings provided with --eval.
+     Also set up the $(-*-eval-flags-*-) variable.  */
+
+  if (eval_strings)
+    {
+      char *p, *value;
+      unsigned int i;
+      unsigned int len = sizeof ("--eval=") * eval_strings->idx;
+
+      for (i = 0; i < eval_strings->idx; ++i)
+        {
+#ifndef CONFIG_WITH_VALUE_LENGTH
+          p = xstrdup (eval_strings->list[i]);
+          len += 2 * strlen (p);
+          eval_buffer (p);
+#else
+          unsigned int sub_len = strlen(eval_strings->list[i]);
+          p = xstrndup (eval_strings->list[i], sub_len);
+          len += 2 * sub_len;
+          eval_buffer (p, p + sub_len);
+#endif
+          free (p);
+        }
+
+      p = value = alloca (len);
+      for (i = 0; i < eval_strings->idx; ++i)
+        {
+          strcpy (p, "--eval=");
+          p += strlen (p);
+          p = quote_for_env (p, eval_strings->list[i]);
+          *(p++) = ' ';
+        }
+      p[-1] = '\0';
+
+      define_variable_cname ("-*-eval-flags-*-", value, o_automatic, 0);
+    }
 
   /* Read all the makefiles.  */
@@ -2264,58 +2321,58 @@
 
   if (jobserver_fds)
-  {
-    const char *cp;
-    unsigned int ui;
-
-    for (ui=1; ui < jobserver_fds->idx; ++ui)
-      if (!streq (jobserver_fds->list[0], jobserver_fds->list[ui]))
-        fatal (NILF, _("internal error: multiple --jobserver-fds options"));
-
-    /* Now parse the fds string and make sure it has the proper format.  */
-
-    cp = jobserver_fds->list[0];
-
-    if (sscanf (cp, "%d,%d", &job_fds[0], &job_fds[1]) != 2)
-      fatal (NILF,
-             _("internal error: invalid --jobserver-fds string `%s'"), cp);
-
-    DB (DB_JOBS,
-	(_("Jobserver client (fds %d,%d)\n"), job_fds[0], job_fds[1]));
-
-    /* The combination of a pipe + !job_slots means we're using the
-       jobserver.  If !job_slots and we don't have a pipe, we can start
-       infinite jobs.  If we see both a pipe and job_slots >0 that means the
-       user set -j explicitly.  This is broken; in this case obey the user
-       (ignore the jobserver pipe for this make) but print a message.  */
-
-    if (job_slots > 0)
-      error (NILF,
-             _("warning: -jN forced in submake: disabling jobserver mode."));
-
-    /* Create a duplicate pipe, that will be closed in the SIGCHLD
-       handler.  If this fails with EBADF, the parent has closed the pipe
-       on us because it didn't think we were a submake.  If so, print a
-       warning then default to -j1.  */
-
-    else if ((job_rfd = dup (job_fds[0])) < 0)
-      {
-        if (errno != EBADF)
-          pfatal_with_name (_("dup jobserver"));
-
+    {
+      const char *cp;
+      unsigned int ui;
+
+      for (ui=1; ui < jobserver_fds->idx; ++ui)
+        if (!streq (jobserver_fds->list[0], jobserver_fds->list[ui]))
+          fatal (NILF, _("internal error: multiple --jobserver-fds options"));
+
+      /* Now parse the fds string and make sure it has the proper format.  */
+
+      cp = jobserver_fds->list[0];
+
+      if (sscanf (cp, "%d,%d", &job_fds[0], &job_fds[1]) != 2)
+        fatal (NILF,
+               _("internal error: invalid --jobserver-fds string `%s'"), cp);
+
+      DB (DB_JOBS,
+          (_("Jobserver client (fds %d,%d)\n"), job_fds[0], job_fds[1]));
+
+      /* The combination of a pipe + !job_slots means we're using the
+         jobserver.  If !job_slots and we don't have a pipe, we can start
+         infinite jobs.  If we see both a pipe and job_slots >0 that means the
+         user set -j explicitly.  This is broken; in this case obey the user
+         (ignore the jobserver pipe for this make) but print a message.  */
+
+      if (job_slots > 0)
         error (NILF,
-               _("warning: jobserver unavailable: using -j1.  Add `+' to parent make rule."));
-        job_slots = 1;
-      }
-
-    if (job_slots > 0)
-      {
-        close (job_fds[0]);
-        close (job_fds[1]);
-        job_fds[0] = job_fds[1] = -1;
-        free (jobserver_fds->list);
-        free (jobserver_fds);
-        jobserver_fds = 0;
-      }
-  }
+               _("warning: -jN forced in submake: disabling jobserver mode."));
+
+      /* Create a duplicate pipe, that will be closed in the SIGCHLD
+         handler.  If this fails with EBADF, the parent has closed the pipe
+         on us because it didn't think we were a submake.  If so, print a
+         warning then default to -j1.  */
+
+      else if ((job_rfd = dup (job_fds[0])) < 0)
+        {
+          if (errno != EBADF)
+            pfatal_with_name (_("dup jobserver"));
+
+          error (NILF,
+                 _("warning: jobserver unavailable: using -j1.  Add `+' to parent make rule."));
+          job_slots = 1;
+        }
+
+      if (job_slots > 0)
+        {
+          close (job_fds[0]);
+          close (job_fds[1]);
+          job_fds[0] = job_fds[1] = -1;
+          free (jobserver_fds->list);
+          free (jobserver_fds);
+          jobserver_fds = 0;
+        }
+    }
 
   /* If we have >1 slot but no jobserver-fds, then we're a top-level make.
@@ -2435,6 +2492,6 @@
       FILE_TIMESTAMP *makefile_mtimes = 0;
       unsigned int mm_idx = 0;
-      char **nargv = argv;
-      int nargc = argc;
+      char **nargv;
+      int nargc;
       int orig_db_level = db_level;
       int status;
@@ -2605,10 +2662,9 @@
 		if (strneq (argv[i], "-f", 2)) /* XXX */
 		  {
-		    char *p = &argv[i][2];
-		    if (*p == '\0')
+		    if (argv[i][2] == '\0')
                       /* This cast is OK since we never modify argv.  */
 		      argv[++i] = (char *) makefiles->list[j];
 		    else
-		      argv[i] = xstrdup (concat ("-f", makefiles->list[j], ""));
+		      argv[i] = xstrdup (concat (2, "-f", makefiles->list[j]));
 		    ++j;
 		  }
@@ -2616,11 +2672,14 @@
 
           /* Add -o option for the stdin temporary file, if necessary.  */
+          nargc = argc;
           if (stdin_nm)
             {
               nargv = xmalloc ((nargc + 2) * sizeof (char *));
               memcpy (nargv, argv, argc * sizeof (char *));
-              nargv[nargc++] = xstrdup (concat ("-o", stdin_nm, ""));
+              nargv[nargc++] = xstrdup (concat (2, "-o", stdin_nm));
               nargv[nargc] = 0;
             }
+          else
+            nargv = argv;
 
 	  if (directories != 0 && directories->idx > 0)
@@ -2639,4 +2698,12 @@
 
           ++restarts;
+
+          /* Reset makeflags in case they were changed.  */
+          {
+            const char *pv = define_makeflags (1, 1);
+            char *p = alloca (sizeof ("MAKEFLAGS=") + strlen (pv) + 1);
+            sprintf (p, "MAKEFLAGS=%s", pv);
+            putenv (p);
+          }
 
 	  if (ISDB (DB_BASIC))
@@ -2758,69 +2825,71 @@
     perror_with_name (_("unlink (temporary file): "), stdin_nm);
 
+  /* If there were no command-line goals, use the default.  */
+  if (goals == 0)
+    {
+      char *p;
+
+      if (default_goal_var->recursive)
+        p = variable_expand (default_goal_var->value);
+      else
+        {
+          p = variable_buffer_output (variable_buffer, default_goal_var->value,
+                                      strlen (default_goal_var->value));
+          *p = '\0';
+          p = variable_buffer;
+        }
+
+      if (*p != '\0')
+        {
+          struct file *f = lookup_file (p);
+
+          /* If .DEFAULT_GOAL is a non-existent target, enter it into the
+             table and let the standard logic sort it out. */
+          if (f == 0)
+            {
+              struct nameseq *ns;
+              ns = PARSE_FILE_SEQ (&p, struct nameseq, '\0', NULL, 0);
+              if (ns)
+                {
+                  /* .DEFAULT_GOAL should contain one target. */
+                  if (ns->next != 0)
+                    fatal (NILF, _(".DEFAULT_GOAL contains more than one target"));
+
+#ifndef CONFIG_WITH_VALUE_LENGTH
+                  f = enter_file (strcache_add (ns->name));
+#else
+                  f = enter_file (ns->name);
+#endif
+
+                  ns->name = 0; /* It was reused by enter_file(). */
+                  free_ns_chain (ns);
+                }
+            }
+
+          if (f)
+            {
+              goals = alloc_dep ();
+              goals->file = f;
+            }
+        }
+    }
+  else
+    lastgoal->next = 0;
+
+
+  if (!goals)
+    {
+      if (read_makefiles == 0)
+        fatal (NILF, _("No targets specified and no makefile found"));
+
+      fatal (NILF, _("No targets"));
+    }
+
+  /* Update the goals.  */
+
+  DB (DB_BASIC, (_("Updating goal targets....\n")));
+
   {
     int status;
-
-    /* If there were no command-line goals, use the default.  */
-    if (goals == 0)
-      {
-        if (**default_goal_name != '\0')
-          {
-            if (default_goal_file == 0 ||
-                strcmp (*default_goal_name, default_goal_file->name) != 0)
-              {
-                default_goal_file = lookup_file (*default_goal_name);
-
-                /* In case user set .DEFAULT_GOAL to a non-existent target
-                   name let's just enter this name into the table and let
-                   the standard logic sort it out. */
-                if (default_goal_file == 0)
-                  {
-                    struct nameseq *ns;
-                    char *p = *default_goal_name;
-
-#ifndef CONFIG_WITH_ALLOC_CACHES
-                    ns = multi_glob (
-                      parse_file_seq (&p, '\0', sizeof (struct nameseq), 1),
-                      sizeof (struct nameseq));
-#else
-                    ns = multi_glob (
-                      parse_file_seq (&p, '\0', &nameseq_cache, 1),
-                      &nameseq_cache);
-#endif
-
-                    /* .DEFAULT_GOAL should contain one target. */
-                    if (ns->next != 0)
-                      fatal (NILF, _(".DEFAULT_GOAL contains more than one target"));
-
-#ifndef CONFIG_WITH_VALUE_LENGTH
-                    default_goal_file = enter_file (strcache_add (ns->name));
-#else
-                    default_goal_file = enter_file (ns->name);
-#endif
-
-                    ns->name = 0; /* It was reused by enter_file(). */
-                    free_ns_chain (ns);
-                  }
-              }
-
-            goals = alloc_dep ();
-            goals->file = default_goal_file;
-          }
-      }
-    else
-      lastgoal->next = 0;
-
-
-    if (!goals)
-      {
-        if (read_makefiles == 0)
-          fatal (NILF, _("No targets specified and no makefile found"));
-
-        fatal (NILF, _("No targets"));
-      }
-
-    /* Update the goals.  */
-
-    DB (DB_BASIC, (_("Updating goal targets....\n")));
 
     switch (update_goal_chain (goals))
@@ -2933,9 +3002,5 @@
     /* Ignore plain `-' for compatibility.  */
     return;
-#ifndef CONFIG_WITH_VALUE_LENGTH
-  v = try_variable_definition (0, arg, o_command, 0);
-#else
-  v = try_variable_definition (0, arg, NULL, o_command, 0);
-#endif
+  v = try_variable_definition (0, arg IF_WITH_VALUE_LENGTH_PARAM(NULL), o_command, 0);
   if (v != 0)
     {
@@ -2999,5 +3064,5 @@
             value = vp;
           }
-        define_variable ("MAKECMDGOALS", 12, value, o_default, 0);
+        define_variable_cname ("MAKECMDGOALS", value, o_default, 0);
       }
     }
@@ -3110,6 +3175,14 @@
                   else if (*optarg == '\0')
                     {
-                      error (NILF, _("the `-%c' option requires a non-empty string argument"),
-                             cs->c);
+                      char opt[2] = "c";
+                      const char *op = opt;
+
+                      if (short_option (cs->c))
+                        opt[0] = cs->c;
+                      else
+                        op = cs->long_name;
+
+                      error (NILF, _("the `%s%s' option requires a non-empty string argument"),
+                             short_option (cs->c) ? "-" : "--", op);
                       bad = 1;
                     }
@@ -3128,5 +3201,6 @@
 		    {
 		      sl->max += 5;
-		      sl->list = xrealloc ((void *)sl->list, /* bird */
+                      /* MSVC erroneously warns without a cast here.  */
+		      sl->list = xrealloc ((void *)sl->list,
                                            sl->max * sizeof (char *));
 		    }
@@ -3275,5 +3349,5 @@
        need permanent storage for this in case decode_switches saves
        pointers into the value.  */
-    argv[1] = xstrdup (concat ("-", argv[1], ""));
+    argv[1] = xstrdup (concat (2, "-", argv[1]));
 
   /* Parse those words.  */
@@ -3307,5 +3381,5 @@
    Don't include options with the `no_makefile' flag set if MAKEFILE.  */
 
-static void
+static const char *
 define_makeflags (int all, int makefile)
 {
@@ -3313,8 +3387,9 @@
   static const char ref[] = "$(KMK_OVERRIDES)";
 #else
-  static const char ref[] = "$(MAKEOVERRIDES)";
-#endif
-  static const char posixref[] = "$(-*-command-variables-*-)";
-  register const struct command_switch *cs;
+  static /*<- bird*/ const char ref[] = "$(MAKEOVERRIDES)";
+#endif
+  static /*<- bird*/ const char posixref[] = "$(-*-command-variables-*-)";
+  static /*<- bird*/ const char evalref[] = "$(-*-eval-flags-*-)";
+  const struct command_switch *cs;
   char *flagstring;
   register char *p;
@@ -3337,5 +3412,5 @@
 #define	ADD_FLAG(ARG, LEN) \
   do {									      \
-    struct flag *new = alloca (sizeof (struct flag));                         \
+    struct flag *new = alloca (sizeof (struct flag));			      \
     new->cs = cs;							      \
     new->arg = (ARG);							      \
@@ -3345,5 +3420,6 @@
       ++flagslen;		/* Just a single flag letter.  */	      \
     else								      \
-      flagslen += 1 + 1 + 1 + 1 + 3 * (LEN); /* " -x foo" */		      \
+      /* " -x foo", plus space to expand "foo".  */			      \
+      flagslen += 1 + 1 + 1 + 1 + (3 * (LEN));				      \
     if (!short_option (cs->c))						      \
       /* This switch has no single-letter version, so we use the long.  */    \
@@ -3434,5 +3510,6 @@
 	}
 
-  flagslen += 4 + sizeof posixref; /* Four more for the possible " -- ".  */
+  /* Four more for the possible " -- ".  */
+  flagslen += 4 + sizeof (posixref) + sizeof (evalref);
 
 #undef	ADD_FLAG
@@ -3507,6 +3584,19 @@
   /* Since MFLAGS is not parsed for flags, there is no reason to
      override any makefile redefinition.  */
-  (void) define_variable ("MFLAGS", 6, flagstring, o_env, 1);
+  define_variable_cname ("MFLAGS", flagstring, o_env, 1);
 #endif /* !KMK */
+
+  /* Write a reference to -*-eval-flags-*-, which contains all the --eval
+     flag options.  */
+  if (eval_strings)
+    {
+      if (p == &flagstring[1])
+	/* No flags written, so elide the leading dash already written.  */
+	p = flagstring;
+      else
+        *p++ = ' ';
+      memcpy (p, evalref, sizeof (evalref) - 1);
+      p += sizeof (evalref) - 1;
+    }
 
   if (all && command_variables != 0)
@@ -3535,11 +3625,11 @@
       if (posix_pedantic)
 	{
-	  memcpy (p, posixref, sizeof posixref - 1);
-	  p += sizeof posixref - 1;
+	  memcpy (p, posixref, sizeof (posixref) - 1);
+	  p += sizeof (posixref) - 1;
 	}
       else
 	{
-	  memcpy (p, ref, sizeof ref - 1);
-	  p += sizeof ref - 1;
+	  memcpy (p, ref, sizeof (ref) - 1);
+	  p += sizeof (ref) - 1;
 	}
     }
@@ -3555,35 +3645,29 @@
   *p = '\0';
 
+  /* If there are switches, omit the leading dash unless it is a single long
+     option with two leading dashes.  */
+  if (flagstring[0] == '-' && flagstring[1] != '-')
+    ++flagstring;
+
 #ifdef KMK
-  v = define_variable ("KMK_FLAGS", 9,
-                       /* If there are switches, omit the leading dash
-                          unless it is a single long option with two
-                          leading dashes.  */
-                       &flagstring[(flagstring[0] == '-'
-                                    && flagstring[1] != '-')
-                                   ? 1 : 0],
-                       /* This used to use o_env, but that lost when a
-                          makefile defined MAKEFLAGS.  Makefiles set
-                          MAKEFLAGS to add switches, but we still want
-                          to redefine its value with the full set of
-                          switches.  Of course, an override or command
-                          definition will still take precedence.  */
-                       o_file, 1);
+  v = define_variable_cname ("KMK_FLAGS", flagstring,
+                             /* This used to use o_env, but that lost when a
+                                makefile defined MAKEFLAGS.  Makefiles set
+                                MAKEFLAGS to add switches, but we still want
+                                to redefine its value with the full set of
+                                switches.  Of course, an override or command
+                                definition will still take precedence.  */
+                             o_file, 1);
 #else
-  v = define_variable ("MAKEFLAGS", 9,
-		       /* If there are switches, omit the leading dash
-			  unless it is a single long option with two
-			  leading dashes.  */
-		       &flagstring[(flagstring[0] == '-'
-				    && flagstring[1] != '-')
-				   ? 1 : 0],
-		       /* This used to use o_env, but that lost when a
-			  makefile defined MAKEFLAGS.  Makefiles set
-			  MAKEFLAGS to add switches, but we still want
-			  to redefine its value with the full set of
-			  switches.  Of course, an override or command
-			  definition will still take precedence.  */
-		       o_file, 1);
-#endif
+  v = define_variable_cname ("MAKEFLAGS", flagstring,
+                             /* This used to use o_env, but that lost when a
+                                makefile defined MAKEFLAGS.  Makefiles set
+                                MAKEFLAGS to add switches, but we still want
+                                to redefine its value with the full set of
+                                switches.  Of course, an override or command
+                                definition will still take precedence.  */
+                             o_file, 1);
+#endif
+
   if (! all)
     /* The first time we are called, set MAKEFLAGS to always be exported.
@@ -3597,29 +3681,25 @@
     char val[32];
     sprintf (val, "%u", job_slots);
-    define_variable ("KMK_OPTS_JOBS", sizeof("KMK_OPTS_JOBS") - 1,
-                     val, o_default, 1);
-    define_variable ("KMK_OPTS_KEEP_GOING", sizeof("KMK_OPTS_KEEP_GOING") - 1,
-                     keep_going_flag ? "1" : "0", o_default, 1);
-    define_variable ("KMK_OPTS_JUST_PRINT", sizeof("KMK_OPTS_JUST_PRINT") - 1,
-                     just_print_flag ? "1" : "0", o_default, 1);
-    define_variable ("KMK_OPTS_PRETTY_COMMAND_PRINTING", sizeof("KMK_OPTS_PRETTY_COMMAND_PRINTING") - 1,
-                     pretty_command_printing ? "1" : "0", o_default, 1);
+    define_variable_cname ("KMK_OPTS_JOBS", val, o_default, 1);
+    define_variable_cname ("KMK_OPTS_KEEP_GOING", keep_going_flag ? "1" : "0", o_default, 1);
+    define_variable_cname ("KMK_OPTS_JUST_PRINT", just_print_flag ? "1" : "0", o_default, 1);
+    define_variable_cname ("KMK_OPTS_PRETTY_COMMAND_PRINTING",
+                           pretty_command_printing ? "1" : "0", o_default, 1);
     sprintf (val, "%u", process_priority);
-    define_variable ("KMK_OPTS_PRORITY", sizeof("KMK_OPTS_PRORITY") - 1,
-                     val, o_default, 1);
+    define_variable_cname ("KMK_OPTS_PRORITY", val, o_default, 1);
     sprintf (val, "%u", process_affinity);
-    define_variable ("KMK_OPTS_AFFINITY", sizeof("KMK_OPTS_AFFINITY") - 1,
-                     val, o_default, 1);
-#if defined (CONFIG_WITH_MAKE_STATS) || defined (CONFIG_WITH_MINIMAL_STATS)
-    define_variable ("KMK_OPTS_STATISTICS", sizeof("KMK_OPTS_STATISTICS") - 1,
-                     make_expensive_statistics ? "1" : "0", o_default, 1);
+    define_variable_cname ("KMK_OPTS_AFFINITY", val, o_default, 1);
+# if defined (CONFIG_WITH_MAKE_STATS) || defined (CONFIG_WITH_MINIMAL_STATS)
+    define_variable_cname ("KMK_OPTS_STATISTICS", make_expensive_statistics ? "1" : "0",
+                           o_default, 1);
 # endif
-#ifdef CONFIG_WITH_PRINT_TIME_SWITCH
+# ifdef CONFIG_WITH_PRINT_TIME_SWITCH
     sprintf (val, "%u", print_time_min);
-    define_variable ("KMK_OPTS_PRINT_TIME", sizeof("KMK_OPTS_PRINT_TIME") - 1,
-                     val, o_default, 1);
-#endif
+    define_variable_cname ("KMK_OPTS_PRINT_TIME", val, o_default, 1);
+# endif
   }
 #endif
+
+  return v->value;
 }
 
@@ -3661,5 +3741,5 @@
      word "Copyright", so it hardly seems worth it.  */
 
-  printf ("%sCopyright (C) 2007  Free Software Foundation, Inc.\n", precede);
+  printf ("%sCopyright (C) 2010  Free Software Foundation, Inc.\n", precede);
 
   printf (_("%sLicense GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n\
@@ -3818,4 +3898,16 @@
 
       close (job_fds[0]);
+
+      /* Clean out jobserver_fds so we don't pass this information to any
+         sub-makes.  Also reset job_slots since it will be put on the command
+         line, not in MAKEFLAGS.  */
+      job_slots = default_job_slots;
+      if (jobserver_fds)
+        {
+          /* MSVC erroneously warns without a cast here.  */
+          free ((void *)jobserver_fds->list);
+          free (jobserver_fds);
+          jobserver_fds = 0;
+        }
     }
 }
@@ -3882,5 +3974,9 @@
          of relative pathnames fail.  */
       if (directory_before_chdir != 0)
-	chdir (directory_before_chdir);
+        {
+          /* If it fails we don't care: shut up GCC.  */
+          int _x;
+          _x = chdir (directory_before_chdir);
+        }
 
 #ifdef CONFIG_WITH_PRINT_TIME_SWITCH
Index: /trunk/src/kmk/maintMakefile
===================================================================
--- /trunk/src/kmk/maintMakefile	(revision 2590)
+++ /trunk/src/kmk/maintMakefile	(revision 2591)
@@ -148,12 +148,10 @@
 	  && (cd "$$tmppo" \
 		&& $(WGET) -r -l1 -nd --no-parent -A '*.po' $(po_repo)) \
-	  && cp "$$tmppo"/*.po po && rm -rf "$$tmppo"
+	  && cp "$$tmppo"/*.po $(top_srcdir)/po && rm -rf "$$tmppo"
 	cd po && $(MAKE) update-po
 	$(MAKE) po-check
 
 po-update:
-	if test -d "po"; then \
-	  $(MAKE) do-po-update; \
-	fi
+	[ -d "po" ] && $(MAKE) do-po-update
 
 # -------------------------- #
@@ -165,8 +163,9 @@
 # regularly updated from the specified URL.
 
-savannah-url = http://savannah.gnu.org/cgi-bin/viewcvs/~checkout~
+cvs-url = http://savannah.gnu.org/cgi-bin/viewcvs/~checkout~
+git-url = http://git.savannah.gnu.org/cgit
 target = $(patsubst get-%,%,$@)
 
-config-url = $(savannah-url)/config/config/$(patsubst get-config/%,%,$@)
+config-url = $(git-url)/config.git/plain/$(patsubst get-config/%,%,$@)
 get-config/config.guess get-config/config.sub:
 	@echo $(WGET) $(config-url) -O $(target) \
@@ -174,5 +173,5 @@
 	  && $(move_if_change)
 
-gnulib-url = $(savannah-url)/gnulib/gnulib/build-aux/$(patsubst get-config/%,%,$@)
+gnulib-url = $(git-url)/gnulib.git/plain/build-aux/$(patsubst get-config/%,%,$@)
 get-config/texinfo.tex:
 	@echo $(WGET) $(gnulib-url) -O $(target) \
@@ -180,5 +179,5 @@
 	  && $(move_if_change)
 
-gnustandards-url = $(savannah-url)/gnustandards/gnustandards/$(patsubst get-doc/%,%,$@)
+gnustandards-url = $(cvs-url)/gnustandards/gnustandards/$(patsubst get-doc/%,%,$@)
 get-doc/make-stds.texi get-doc/fdl.texi:
 	@echo $(WGET) $(gnustandards-url) -O $(target) \
@@ -186,6 +185,6 @@
 	  && $(move_if_change)
 
-.PHONY: cvs-update
-cvs-update: get-config/texinfo.tex get-config/config.guess get-config/config.sub get-doc/make-stds.texi get-doc/fdl.texi
+.PHONY: scm-update
+scm-update: get-config/texinfo.tex get-config/config.guess get-config/config.sub get-doc/make-stds.texi get-doc/fdl.texi
 
 
@@ -195,5 +194,5 @@
 
 .PHONY: update
-update: po-update cvs-update
+update: po-update scm-update
 
 
@@ -209,5 +208,5 @@
 
 changelog-check:
-	if head ChangeLog | grep 'Version $(VERSION)' >/dev/null; then \
+	if head $(top_srcdir)/ChangeLog | grep 'Version $(VERSION)' >/dev/null; then \
 	  :; \
 	else \
@@ -251,5 +250,5 @@
 	@echo "Creating directive file '$@':"
 	@( \
-	   echo 'verstion: 1.1'; \
+	   echo 'version: 1.1'; \
 	   echo 'directory: make'; \
 	   echo 'filename: $*'; \
@@ -262,14 +261,16 @@
 
 FTPPUT = ncftpput
-gnu-url = ftp-upload.gnu.org /incoming
+gnu-upload-host = ftp-upload.gnu.org
+gnu-upload-dir  = /incoming
+
 
 UPLOADS = upload-alpha upload-ftp
 .PHONY: $(UPLOADS)
 $(UPLOADS): $(DIST_ARCHIVES) $(DIST_ARCHIVES_SIG) $(DIST_ARCHIVES_DIRECTIVE)
-	$(FTPPUT) "$(gnu-url)/$(@:upload-%=%)" $^
+	$(FTPPUT) "$(gnu-upload-host)" "$(gnu-upload-dir)/$(@:upload-%=%)" $^
 
 
 # Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
-# 2007 Free Software Foundation, Inc.
+# 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 # This file is part of GNU Make.
 #
Index: /trunk/src/kmk/make.1
===================================================================
--- /trunk/src/kmk/make.1	(revision 2590)
+++ /trunk/src/kmk/make.1	(revision 2591)
@@ -224,5 +224,6 @@
 .TP 0.5i
 .BR \-n , " \-\-just\-print" , " \-\-dry\-run" , " \-\-recon"
-Print the commands that would be executed, but do not execute them.
+Print the commands that would be executed, but do not execute them (except in
+certain circumstances).
 .TP 0.5i
 \fB\-o\fR \fIfile\fR, \fB\-\-old\-file\fR=\fIfile\fR, \fB\-\-assume\-old\fR=\fIfile\fR
Index: /trunk/src/kmk/make.h
===================================================================
--- /trunk/src/kmk/make.h	(revision 2590)
+++ /trunk/src/kmk/make.h	(revision 2591)
@@ -1,6 +1,6 @@
 /* Miscellaneous global declarations and portability cruft 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 Free Software
-Foundation, Inc.
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
@@ -24,12 +24,17 @@
 #define HAVE_CONFIG_H 1
 
+/* Specify we want GNU source code.  This must be defined before any
+   system headers are included.  */
+
+#define _GNU_SOURCE 1
+
 /* AIX requires this to be the first thing in the file.  */
-#ifndef __GNUC__
-# if HAVE_ALLOCA_H
-#  include <alloca.h>
-# else
-#  ifdef _AIX
+#if HAVE_ALLOCA_H
+# include <alloca.h>
+#else
+# ifdef _AIX
  #pragma alloca
-#  else
+# else
+#  if !defined(__GNUC__) && !defined(WINDOWS32)
 #   ifndef alloca /* predefined by HP cc +Olibcalls */
 char *alloca ();
@@ -37,13 +42,5 @@
 #  endif
 # endif
-#elif defined(__sun__) && defined (HAVE_ALLOCA_H) /* bird: kill warnings. */
-# include <alloca.h>
-#endif
-
-
-/* Specify we want GNU source code.  This must be defined before any
-   system headers are included.  */
-
-#define _GNU_SOURCE 1
+#endif
 
 
@@ -240,4 +237,32 @@
 #endif
 
+/* bird - start */
+#define COMMA ,
+#ifdef CONFIG_WITH_VALUE_LENGTH
+# define IF_WITH_VALUE_LENGTH(a_Expr)           a_Expr
+# define IF_WITH_VALUE_LENGTH_PARAM(a_Expr)     , a_Expr
+#else
+# define IF_WITH_VALUE_LENGTH(a_Expr)
+# define IF_WITH_VALUE_LENGTH_PARAM(a_Expr)
+#endif
+
+#ifdef CONFIG_WITH_ALLOC_CACHES
+# define IF_WITH_ALLOC_CACHES(a_Expr)           a_Expr
+# define IF_WITH_ALLOC_CACHES_PARAM(a_Expr)     , a_Expr
+#else
+# define IF_WITH_ALLOC_CACHES(a_Expr)
+# define IF_WITH_ALLOC_CACHES_PARAM(a_Expr)
+#endif
+
+#ifdef CONFIG_WITH_COMMANDS_FUNC
+# define IF_WITH_COMMANDS_FUNC(a_Expr)          a_Expr
+# define IF_WITH_COMMANDS_FUNC_PARAM(a_Expr)    , a_Expr
+#else
+# define IF_WITH_COMMANDS_FUNC(a_Expr)
+# define IF_WITH_COMMANDS_FUNC_PARAM(a_Expr)
+#endif
+
+/* bird - end */
+
 
 #ifndef CHAR_BIT
@@ -363,21 +388,21 @@
 #define ISDIGIT(c) ((unsigned) (c) - '0' <= 9)
 
-#ifndef iAPX286
-# define streq(a, b) \
+/* Test if two strings are equal. Is this worthwhile?  Should be profiled.  */
+#define streq(a, b) \
    ((a) == (b) || \
     (*(a) == *(b) && (*(a) == '\0' || !strcmp ((a) + 1, (b) + 1))))
-# ifdef HAVE_CASE_INSENSITIVE_FS
-#  define strieq(a, b) \
+
+/* Test if two strings are equal, but match case-insensitively on systems
+   which have case-insensitive filesystems.  Should only be used for
+   filenames!  */
+#ifdef HAVE_CASE_INSENSITIVE_FS
+# define patheq(a, b) \
     ((a) == (b) \
      || (tolower((unsigned char)*(a)) == tolower((unsigned char)*(b)) \
          && (*(a) == '\0' || !strcasecmp ((a) + 1, (b) + 1))))
-# else
-#  define strieq(a, b) streq(a, b)
-# endif
-#else
-/* Buggy compiler can't handle this.  */
-# define streq(a, b) (strcmp ((a), (b)) == 0)
-# define strieq(a, b) (strcmp ((a), (b)) == 0)
-#endif
+#else
+# define patheq(a, b) streq(a, b)
+#endif
+
 #define strneq(a, b, l) (strncmp ((a), (b), (l)) == 0)
 
@@ -425,5 +450,5 @@
 
 void sync_Path_environment (void);
-int w32_kill (int pid, int sig);
+int w32_kill (pid_t pid, int sig);
 char *end_of_token_w32 (const char *s, char stopchar);
 int find_and_set_default_shell (const char *token);
@@ -435,4 +460,12 @@
 extern int unixy_shell;
 #endif  /* WINDOWS32 */
+
+#if defined(HAVE_SYS_RESOURCE_H) && defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT)
+# define SET_STACK_SIZE
+#endif
+#ifdef SET_STACK_SIZE
+# include <sys/resource.h>
+struct rlimit stack_limit;
+#endif
 
 struct floc
@@ -475,4 +508,5 @@
 
 #if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H
+const char *concat (unsigned int, ...);
 void message (int prefix, const char *fmt, ...)
               __attribute__ ((__format__ (__printf__, 2, 3)));
@@ -482,4 +516,5 @@
                    __attribute__ ((noreturn, __format__ (__printf__, 2, 3)));
 #else
+const char *concat ();
 void message ();
 void error ();
@@ -491,9 +526,9 @@
 void pfatal_with_name (const char *) __attribute__ ((noreturn));
 void perror_with_name (const char *, const char *);
-char *savestring (const char *, unsigned int);
-char *concat (const char *, const char *, const char *);
 void *xmalloc (unsigned int);
+void *xcalloc (unsigned int);
 void *xrealloc (void *, unsigned int);
 char *xstrdup (const char *);
+char *xstrndup (const char *, unsigned int);
 #ifdef CONFIG_WITH_PRINT_STATS_SWITCH
 void print_heap_stats (void);
@@ -553,5 +588,6 @@
 void build_vpath_lists (void);
 void construct_vpath_list (char *pattern, char *dirpath);
-const char *vpath_search (const char *file, FILE_TIMESTAMP *mtime_ptr);
+const char *vpath_search (const char *file, FILE_TIMESTAMP *mtime_ptr,
+                          unsigned int* vpath_index, unsigned int* path_index);
 int gpath_search (const char *file, unsigned int len);
 
@@ -696,4 +732,15 @@
 #endif
 
+#if !HAVE_STRNCASECMP
+# if HAVE_STRNICMP
+#  define strncasecmp strnicmp
+# elif HAVE_STRNCMPI
+#  define strncasecmp strncmpi
+# else
+/* Create our own, in misc.c */
+int strncasecmp (const char *s1, const char *s2, int n);
+# endif
+#endif
+
 extern const struct floc *reading_file;
 extern const struct floc **expanding_var;
@@ -709,4 +756,6 @@
 extern int warn_undefined_variables_flag, posix_pedantic, not_parallel;
 extern int second_expansion, clock_skew_detected, rebuilding_makefiles;
+extern int one_shell;
+
 #ifdef CONFIG_WITH_2ND_TARGET_EXPANSION
 extern int second_target_expansion;
Index: /trunk/src/kmk/makefile.com
===================================================================
--- /trunk/src/kmk/makefile.com	(revision 2590)
+++ /trunk/src/kmk/makefile.com	(revision 2591)
@@ -140,5 +140,5 @@
 $!-----------------------------------------------------------------------------
 $!Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-$!2006, 2007 Free Software Foundation, Inc.
+$!2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 $!This file is part of GNU Make.
 $!
Index: /trunk/src/kmk/makefile.vms
===================================================================
--- /trunk/src/kmk/makefile.vms	(revision 2590)
+++ /trunk/src/kmk/makefile.vms	(revision 2591)
@@ -2,5 +2,5 @@
 #
 # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-# 2006, 2007 Free Software Foundation, Inc.
+# 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 # This file is part of GNU Make.
 #
Index: /trunk/src/kmk/misc.c
===================================================================
--- /trunk/src/kmk/misc.c	(revision 2590)
+++ /trunk/src/kmk/misc.c	(revision 2591)
@@ -1,6 +1,6 @@
 /* Miscellaneous generic support functions 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 Free Software
-Foundation, Inc.
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
@@ -166,9 +166,11 @@
       ++in;
 
-      /* If the newline is quoted, discard following whitespace
-	 and any preceding whitespace; leave just one space.  */
+      /* If the newline is escaped, discard following whitespace leaving just
+	 one space.  POSIX requires that each backslash/newline/following
+	 whitespace sequence be reduced to a single space.  */
       if (backslash)
 	{
 	  in = next_token (in);
+          /* Removing this loop will fix Savannah bug #16670: do we want to? */
 	  while (out > line && isblank ((unsigned char)out[-1]))
 	    --out;
@@ -218,29 +220,55 @@
 
 
-/* Return a string whose contents concatenate those of s1, s2, s3.
+/* Return a string whose contents concatenate the NUM strings provided
    This string lives in static, re-used memory.  */
 
-char *
-concat (const char *s1, const char *s2, const char *s3)
-{
-  unsigned int len1, len2, len3;
+const char *
+#if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H
+concat (unsigned int num, ...)
+#else
+concat (num, va_alist)
+     unsigned int num;
+     va_dcl
+#endif
+{
   static unsigned int rlen = 0;
   static char *result = NULL;
-
-  len1 = (s1 && *s1 != '\0') ? strlen (s1) : 0;
-  len2 = (s2 && *s2 != '\0') ? strlen (s2) : 0;
-  len3 = (s3 && *s3 != '\0') ? strlen (s3) : 0;
-
-  if (len1 + len2 + len3 + 1 > rlen)
-    result = xrealloc (result, (rlen = len1 + len2 + len3 + 10));
-
-  if (len1)
-    memcpy (result, s1, len1);
-  if (len2)
-    memcpy (result + len1, s2, len2);
-  if (len3)
-    memcpy (result + len1 + len2, s3, len3);
-
-  result[len1+len2+len3] = '\0';
+  unsigned int ri = 0; /* bird: must be unsigned */
+
+#if USE_VARIADIC
+  va_list args;
+#endif
+
+  VA_START (args, num);
+
+  while (num-- > 0)
+    {
+      const char *s = va_arg (args, const char *);
+      unsigned int l = s ? strlen (s) : 0;
+
+      if (l == 0)
+        continue;
+
+      if (ri + l > rlen)
+        {
+          rlen = ((rlen ? rlen : 60) + l) * 2;
+          result = xrealloc (result, rlen);
+        }
+
+      memcpy (result + ri, s, l);
+      ri += l;
+    }
+
+  VA_END (args);
+
+  /* Get some more memory if we don't have enough space for the
+     terminating '\0'.   */
+  if (ri == rlen)
+    {
+      rlen = (rlen ? rlen : 60) * 2;
+      result = xrealloc (result, rlen);
+    }
+
+  result[ri] = '\0';
 
   return result;
@@ -397,4 +425,5 @@
 
 #undef xmalloc
+#undef xcalloc
 #undef xrealloc
 #undef xstrdup
@@ -403,5 +432,5 @@
 xmalloc (unsigned int size)
 {
-  /* Make sure we don't allocate 0, for pre-ANSI libraries.  */
+  /* Make sure we don't allocate 0, for pre-ISO implementations.  */
   void *result = malloc (size ? size : 1);
   if (result == 0)
@@ -415,4 +444,15 @@
     make_stats_allocated += size;
 #endif
+  return result;
+}
+
+
+void *
+xcalloc (unsigned int size)
+{
+  /* Make sure we don't allocate 0, for pre-ISO implementations.  */
+  void *result = calloc (size ? size : 1, 1);
+  if (result == 0)
+    fatal (NILF, _("virtual memory exhausted"));
   return result;
 }
@@ -432,5 +472,5 @@
 #endif
 
-  /* Some older implementations of realloc() don't conform to ANSI.  */
+  /* Some older implementations of realloc() don't conform to ISO.  */
   if (! size)
     size = 1;
@@ -480,11 +520,20 @@
 
 char *
-savestring (const char *str, unsigned int length)
-{
-  char *out = xmalloc (length + 1);
+xstrndup (const char *str, unsigned int length)
+{
+  char *result;
+
+#if defined(HAVE_STRNDUP) && !defined(KMK)
+  result = strndup (str, length);
+  if (result == 0)
+    fatal (NILF, _("virtual memory exhausted"));
+#else
+  result = xmalloc (length + 1);
   if (length > 0)
-    memcpy (out, str, length);
-  out[length] = '\0';
-  return out;
+    strncpy (result, str, length);
+  result[length] = '\0';
+#endif
+
+  return result;
 }
 
@@ -786,33 +835,5 @@
 
 
-/* Allocate a new `struct dep' with all fields initialized to 0.   */
-
-struct dep *
-alloc_dep ()
-{
-#ifndef CONFIG_WITH_ALLOC_CACHES
-  struct dep *d = xmalloc (sizeof (struct dep));
-  memset (d, '\0', sizeof (struct dep));
-  return d;
-#else
-  return (struct dep *) alloccache_calloc (&dep_cache);
-#endif
-}
-
-
-/* Free `struct dep' along with `name' and `stem'.   */
-
-void
-free_dep (struct dep *d)
-{
-#ifndef CONFIG_WITH_ALLOC_CACHES
-  free (d);
-#else
-  alloccache_free (&dep_cache, d);
-#endif
-}
-
-/* Copy a chain of `struct dep', making a new chain
-   with the same contents as the old one.  */
+/* Copy a chain of `struct dep'.  For 2nd expansion deps, dup the name.  */
 
 struct dep *
@@ -827,7 +848,11 @@
       struct dep *c = xmalloc (sizeof (struct dep));
 #else
-      struct dep *c = (struct dep *) alloccache_alloc (&dep_cache);
+      struct dep *c = alloccache_alloc(&dep_cache);
 #endif
       memcpy (c, d, sizeof (struct dep));
+
+      /** @todo KMK: Check if we need this duplication! */
+      if (c->need_2nd_expansion)
+        c->name = xstrdup (c->name);
 
       c->next = 0;
@@ -852,9 +877,5 @@
       struct dep *df = d;
       d = d->next;
-#ifndef CONFIG_WITH_ALLOC_CACHES
       free_dep (df);
-#else
-      alloccache_free (&dep_cache, df);
-#endif
     }
 }
@@ -903,4 +924,32 @@
       return (c1 - c2);
     }
+}
+#endif
+
+#if !HAVE_STRNCASECMP && !HAVE_STRNICMP && !HAVE_STRNCMPI
+
+/* If we don't have strncasecmp() (from POSIX), or anything that can
+   substitute for it, define our own version.  */
+
+int
+strncasecmp (const char *s1, const char *s2, int n)
+{
+  while (n-- > 0)
+    {
+      int c1 = (int) *(s1++);
+      int c2 = (int) *(s2++);
+
+      if (isalpha (c1))
+        c1 = tolower (c1);
+      if (isalpha (c2))
+        c2 = tolower (c2);
+
+      if (c1 != '\0' && c1 == c2)
+        continue;
+
+      return (c1 - c2);
+    }
+
+  return 0;
 }
 #endif
@@ -1234,10 +1283,12 @@
 
   malloc_zone_statistics (NULL, &s);
-  printf (_("\n# CRT Heap: %zu bytes in use, in %u blocks, avg %zu bytes/block\n"),
-          s.size_in_use, s.blocks_in_use, s.size_in_use / s.blocks_in_use);
-  printf (_("#           %zu bytes max in use (high water mark)\n"),
-          s.max_size_in_use);
-  printf (_("#           %zu bytes reserved,  %zu bytes free (estimate)\n"),
-          s.size_allocated, s.size_allocated - s.size_in_use);
+  printf (_("\n# CRT Heap: %u bytes in use, in %u blocks, avg %u bytes/block\n"),
+          (unsigned)s.size_in_use, (unsigned)s.blocks_in_use,
+          (unsigned)(s.size_in_use / s.blocks_in_use));
+  printf (_("#           %u bytes max in use (high water mark)\n"),
+          (unsigned)s.max_size_in_use);
+  printf (_("#           %u bytes reserved,  %u bytes free (estimate)\n"),
+          (unsigned)s.size_allocated,
+          (unsigned)(s.size_allocated - s.size_in_use));
 # endif /* __APPLE__ */
 
@@ -1374,5 +1425,5 @@
 format_elapsed_nano (char *buf, size_t size, big_int ts)
 {
-  int sz;
+  unsigned sz;
   if (ts < 1000)
     sz = sprintf (buf, "%uns", (unsigned)ts);
@@ -1407,6 +1458,6 @@
     }
   if (sz >= size)
-    fatal (NILF, _("format_elapsed_nano buffer overflow: %d written, %d buffer"),
-           sz, size);
+    fatal (NILF, _("format_elapsed_nano buffer overflow: %u written, %lu buffer"),
+           sz, (unsigned long)size);
   return sz;
 }
Index: /trunk/src/kmk/po/ChangeLog
===================================================================
--- /trunk/src/kmk/po/ChangeLog	(revision 2590)
+++ /trunk/src/kmk/po/ChangeLog	(revision 2591)
@@ -1,2 +1,6 @@
+2009-09-16  Paul Smith  <psmith@gnu.org>
+
+	* LINGUAS: Added new translation for Italian (it).
+
 2008-05-17  Paul Smith  <psmith@gnu.org>
 
@@ -63,5 +67,6 @@
 
 
-Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software
+Foundation, Inc.
 This file is part of GNU Make.
 
Index: /trunk/src/kmk/po/LINGUAS
===================================================================
--- /trunk/src/kmk/po/LINGUAS	(revision 2590)
+++ /trunk/src/kmk/po/LINGUAS	(revision 2591)
@@ -1,5 +1,5 @@
-# Set of available languages: 23 languages
+# Set of available languages: 24 languages
 
-be da de es fi fr ga gl he hr id ja ko lt nl pl pt_BR ru sv tr uk vi zh_CN
+be da de es fi fr ga gl he hr id it ja ko lt nl pl pt_BR ru sv tr uk vi zh_CN
 
 # Can't seem to get en@quot and en@boldquot to build properly?
Index: /trunk/src/kmk/po/Makevars
===================================================================
--- /trunk/src/kmk/po/Makevars	(revision 2590)
+++ /trunk/src/kmk/po/Makevars	(revision 2591)
@@ -1,5 +1,5 @@
 # This is a -*-Makefile-*-
-# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation,
-# Inc.
+# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free
+# Software Foundation, Inc.
 # This file is part of GNU Make.
 #
Index: /trunk/src/kmk/po/POTFILES.in
===================================================================
--- /trunk/src/kmk/po/POTFILES.in	(revision 2590)
+++ /trunk/src/kmk/po/POTFILES.in	(revision 2591)
@@ -1,5 +1,5 @@
 # List of source files containing translatable strings.
-# Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software
-# Foundation, Inc.
+# Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+# 2010 Free Software Foundation, Inc.
 # This file is part of GNU Make.
 #
Index: /trunk/src/kmk/read.c
===================================================================
--- /trunk/src/kmk/read.c	(revision 2590)
+++ /trunk/src/kmk/read.c	(revision 2591)
@@ -1,6 +1,6 @@
 /* Reading and parsing of makefiles 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 Free Software
-Foundation, Inc.
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
@@ -60,4 +60,16 @@
     FILE *fp;           /* File, or NULL if this is an internal buffer.  */
     struct floc floc;   /* Info on the file in fp (if any).  */
+  };
+
+/* Track the modifiers we can have on variable assignments */
+
+struct vmodifiers
+  {
+    unsigned int assign_v:1;
+    unsigned int define_v:1;
+    unsigned int undefine_v:1;
+    unsigned int export_v:1;
+    unsigned int override_v:1;
+    unsigned int private_v:1;
   };
 
@@ -149,9 +161,11 @@
 
 static int eval_makefile (const char *filename, int flags);
-static int eval (struct ebuffer *buffer, int flags);
+static void eval (struct ebuffer *buffer, int flags);
 
 static long readline (struct ebuffer *ebuf);
-static void do_define (char *name, unsigned int namelen,
-                       enum variable_origin origin, struct ebuffer *ebuf);
+static void do_undefine (char *name, enum variable_origin origin,
+                         struct ebuffer *ebuf);
+static struct variable *do_define (char *name IF_WITH_VALUE_LENGTH_PARAM(char *eos),
+                                   enum variable_origin origin, struct ebuffer *ebuf);
 #ifndef CONFIG_WITH_VALUE_LENGTH
 static int conditional_line (char *line, int len, const struct floc *flocp);
@@ -159,13 +173,12 @@
 static int conditional_line (char *line, char *eol, int len, const struct floc *flocp);
 #endif
-#ifndef CONFIG_WITH_INCLUDEDEP
 static void record_files (struct nameseq *filenames, const char *pattern,
-                          const char *pattern_percent, struct dep *deps,
+                          const char *pattern_percent, char *depstr,
                           unsigned int cmds_started, char *commands,
                           unsigned int commands_idx, int two_colon,
                           const struct floc *flocp);
-#endif /* !KMK */
 static void record_target_var (struct nameseq *filenames, char *defn,
-                               enum variable_origin origin, int enabled,
+                               enum variable_origin origin,
+                               struct vmodifiers *vmod,
                                const struct floc *flocp);
 static enum make_word_type get_next_mword (char *buffer, char *delim,
@@ -198,4 +211,11 @@
 
 
+/* Compare a word, both length and contents.
+   P must point to the word to be tested, and WLEN must be the length.
+*/
+#define	word1eq(s)	(wlen == sizeof(s)-1 && strneq (s, p, sizeof(s)-1))
+
+
+
 /* Read in all the makefiles and return the chain of their names.  */
 
@@ -208,5 +228,5 @@
      we will be reading. */
 
-  define_variable ("MAKEFILE_LIST", sizeof ("MAKEFILE_LIST")-1, "", o_file, 0);
+  define_variable_cname ("MAKEFILE_LIST", "", o_file, 0);
 
   DB (DB_BASIC, (_("Reading makefiles...\n")));
@@ -320,5 +340,5 @@
 	      struct dep *d = alloc_dep ();
 	      d->file = enter_file (strcache_add (*p));
-	      d->file->dontcare = 1;
+	      d->dontcare = 1;
 	      /* Tell update_goal_chain to bail out as soon as this file is
 		 made, and main not to die if we can't make this file.  */
@@ -388,5 +408,4 @@
   char *expanded = 0;
   int makefile_errno;
-  int r;
 
   filename = strcache_add (filename);
@@ -431,5 +450,6 @@
       for (i = 0; include_directories[i] != 0; ++i)
 	{
-	  const char *included = concat (include_directories[i], "/", filename);
+	  const char *included = concat (3, include_directories[i],
+                                         "/", filename);
 	  ebuf.fp = fopen (included, "r");
 	  if (ebuf.fp)
@@ -455,5 +475,5 @@
   deps->changed = flags;
   if (flags & RM_DONTCARE)
-    deps->file->dontcare = 1;
+    deps->dontcare = 1;
 
   if (expanded)
@@ -470,4 +490,10 @@
       return 0;
     }
+
+  /* Set close-on-exec to avoid leaking the makefile to children, such as
+     $(shell ...).  */
+#ifdef HAVE_FILENO
+  CLOSE_ON_EXEC (fileno (ebuf.fp));
+#endif
 
   /* Add this makefile to the list. */
@@ -506,5 +532,5 @@
   reading_file = &ebuf.floc;
 
-  r = eval (&ebuf, !(flags & RM_NO_DEFAULT_GOAL));
+  eval (&ebuf, !(flags & RM_NO_DEFAULT_GOAL));
 
   reading_file = curfile;
@@ -519,8 +545,9 @@
   free (ebuf.bufstart);
   alloca (0);
-  return r;
+
+  return 1;
 }
 
-int
+void
 #ifndef CONFIG_WITH_VALUE_LENGTH
 eval_buffer (char *buffer)
@@ -533,5 +560,4 @@
   struct conditionals new;
   const struct floc *curfile;
-  int r;
 
   /* Evaluate the buffer */
@@ -547,5 +573,8 @@
   ebuf.fp = NULL;
 
-  ebuf.floc = *reading_file;
+  if (reading_file)
+    ebuf.floc = *reading_file;
+  else
+    ebuf.floc.filenm = NULL;
 
   curfile = reading_file;
@@ -554,5 +583,5 @@
   saved = install_conditionals (&new);
 
-  r = eval (&ebuf, 1);
+  eval (&ebuf, 1);
 
   restore_conditionals (saved);
@@ -561,8 +590,82 @@
 
   alloca (0);
-  return r;
 }
 
 
+/* Check LINE to see if it's a variable assignment or undefine.
+
+   It might use one of the modifiers "export", "override", "private", or it
+   might be one of the conditional tokens like "ifdef", "include", etc.
+
+   If it's not a variable assignment or undefine, VMOD.V_ASSIGN is 0.
+   Returns LINE.
+
+   Returns a pointer to the first non-modifier character, and sets VMOD
+   based on the modifiers found if any, plus V_ASSIGN is 1.
+ */
+static char *
+parse_var_assignment (const char *line, struct vmodifiers *vmod)
+{
+  const char *p;
+  memset (vmod, '\0', sizeof (*vmod));
+
+  /* Find the start of the next token.  If there isn't one we're done.  */
+  line = next_token (line);
+  if (*line == '\0')
+    return (char *)line;
+
+  p = line;
+  while (1)
+    {
+      int wlen;
+      const char *p2;
+      enum variable_flavor flavor;
+
+      p2 = parse_variable_definition (p, &flavor);
+
+      /* If this is a variable assignment, we're done.  */
+      if (p2)
+        break;
+
+      /* It's not a variable; see if it's a modifier.  */
+      p2 = end_of_token (p);
+      wlen = p2 - p;
+
+      if (word1eq ("export"))
+        vmod->export_v = 1;
+      else if (word1eq ("override"))
+        vmod->override_v = 1;
+      else if (word1eq ("private"))
+        vmod->private_v = 1;
+      else if (word1eq ("define"))
+        {
+          /* We can't have modifiers after 'define' */
+          vmod->define_v = 1;
+          p = next_token (p2);
+          break;
+        }
+      else if (word1eq ("undefine"))
+        {
+          /* We can't have modifiers after 'undefine' */
+          vmod->undefine_v = 1;
+          p = next_token (p2);
+          break;
+        }
+      else
+        /* Not a variable or modifier: this is not a variable assignment.  */
+        return (char *)line;
+
+      /* It was a modifier.  Try the next word.  */
+      p = next_token (p2);
+      if (*p == '\0')
+        return (char *)line;
+    }
+
+  /* Found a variable assignment or undefine.  */
+  vmod->assign_v = 1;
+  return (char *)p;
+}
+
+
 
 /* Read file FILENAME as a makefile and add its contents to the data base.
@@ -570,6 +673,5 @@
    SET_DEFAULT is true if we are allowed to set the default goal.  */
 
-
-static int
+static void
 eval (struct ebuffer *ebuf, int set_default)
 {
@@ -583,5 +685,5 @@
   int no_targets = 0;		/* Set when reading a rule without targets.  */
   struct nameseq *filenames = 0;
-  struct dep *deps = 0;
+  char *depstr = 0;
   long nlines = 0;
   int two_colon = 0;
@@ -604,9 +706,9 @@
         {                                                                     \
 	  fi.lineno = tgts_started;                                           \
-	  record_files (filenames, pattern, pattern_percent, deps,            \
+	  record_files (filenames, pattern, pattern_percent, depstr,          \
                         cmds_started, commands, commands_idx, two_colon,      \
                         &fi);                                                 \
+          filenames = 0;						      \
         }                                                                     \
-      filenames = 0;							      \
       commands_idx = 0;							      \
       no_targets = 0;                                                         \
@@ -642,5 +744,7 @@
       char *p;
       char *p2;
-
+      struct vmodifiers vmod;
+
+      /* At the top of this loop, we are starting a brand new line.  */
       /* Grab the next line to be evaluated */
       ebuf->floc.lineno += nlines;
@@ -672,5 +776,5 @@
 
 	  /* If there is no preceding rule line, don't treat this line
-	     as a command, even though it begins with a tab character.
+	     as a command, even though it begins with a recipe prefix.
 	     SunOS 4 make appears to behave this way.  */
 
@@ -711,5 +815,5 @@
 	}
 
-      /* This line is not a shell command line.  Don't worry about tabs.
+      /* This line is not a shell command line.  Don't worry about whitespace.
          Get more space if we need it; we don't need to preserve the current
          contents of the buffer.  */
@@ -720,4 +824,5 @@
           if (collapsed)
             free (collapsed);
+          /* Don't need xrealloc: we don't need to preserve the content.  */
 	  collapsed = xmalloc (collapsed_length);
 	}
@@ -736,125 +841,88 @@
 #endif
 
-      /* Compare a word, both length and contents. */
-#define	word1eq(s)	(wlen == sizeof(s)-1 && strneq (s, p, sizeof(s)-1))
+      /* Get rid if starting space (including formfeed, vtab, etc.)  */
       p = collapsed;
       while (isspace ((unsigned char)*p))
-	++p;
-
-      if (*p == '\0')
-	/* This line is completely empty--ignore it.  */
-	continue;
-
-      /* Find the end of the first token.  Note we don't need to worry about
-       * ":" here since we compare tokens by length (so "export" will never
-       * be equal to "export:").
-       */
-      for (p2 = p+1; *p2 != '\0' && !isspace ((unsigned char)*p2); ++p2)
-        ;
-      wlen = p2 - p;
-
-      /* Find the start of the second token.  If it looks like a target or
-         variable definition it can't be a preprocessor token so skip
-         them--this allows variables/targets named `ifdef', `export', etc. */
-      while (isspace ((unsigned char)*p2))
-        ++p2;
-
-      if ((p2[0] == ':' || p2[0] == '+' || p2[0] == '=') && p2[1] == '\0')
+        ++p;
+
+      /* See if this is a variable assignment.  We need to do this early, to
+         allow variables with names like 'ifdef', 'export', 'private', etc.  */
+      p = parse_var_assignment(p, &vmod);
+      if (vmod.assign_v)
         {
-          /* It can't be a preprocessor token so skip it if we're ignoring */
-          if (ignoring)
-            continue;
-
-          goto skip_conditionals;
-        }
-
-      /* We must first check for conditional and `define' directives before
-	 ignoring anything, since they control what we will do with
-	 following lines.  */
-
-      if (!in_ignored_define)
-	{
-#ifndef CONFIG_WITH_VALUE_LENGTH
- 	  int i = conditional_line (p, wlen, fstart);
-#else
- 	  int i = conditional_line (p, eol, wlen, fstart);
-#endif
-          if (i != -2)
+          struct variable *v;
+          enum variable_origin origin = vmod.override_v ? o_override : o_file;
+
+          /* If we're ignoring then we're done now.  */
+	  if (ignoring)
             {
-              if (i == -1)
-                fatal (fstart, _("invalid syntax in conditional"));
-
-              ignoring = i;
+              if (vmod.define_v)
+                in_ignored_define = 1;
               continue;
             }
-	}
-
-      if (word1eq ("endef"))
+
+          if (vmod.undefine_v)
+          {
+            do_undefine (p, origin, ebuf);
+
+            /* This line has been dealt with.  */
+            goto rule_complete;
+          }
+          else if (vmod.define_v)
+            v = do_define (p IF_WITH_VALUE_LENGTH_PARAM(NULL), origin, ebuf);
+          else
+            v = try_variable_definition (fstart, p IF_WITH_VALUE_LENGTH_PARAM(NULL), origin, 0);
+
+          assert (v != NULL);
+
+          if (vmod.export_v)
+            v->export = v_export;
+          if (vmod.private_v)
+            v->private_var = 1;
+
+          /* This line has been dealt with.  */
+          goto rule_complete;
+        }
+
+      /* If this line is completely empty, ignore it.  */
+      if (*p == '\0')
+	continue;
+
+      p2 = end_of_token (p);
+      wlen = p2 - p;
+      p2 = next_token (p2);
+
+      /* If we're in an ignored define, skip this line (but maybe get out).  */
+      if (in_ignored_define)
 	{
-	  if (!in_ignored_define)
-	    fatal (fstart, _("extraneous `endef'"));
-          in_ignored_define = 0;
+          /* See if this is an endef line (plus optional comment).  */
+          if (word1eq ("endef") && (*p2 == '\0' || *p2 == '#'))
+            in_ignored_define = 0;
+
 	  continue;
 	}
 
-      if (word1eq ("define"))
-	{
-	  if (ignoring)
-	    in_ignored_define = 1;
-	  else
-	    {
-              if (*p2 == '\0')
-                fatal (fstart, _("empty variable name"));
-
-	      /* Let the variable name be the whole rest of the line,
-		 with trailing blanks stripped (comments have already been
-		 removed), so it could be a complex variable/function
-		 reference that might contain blanks.  */
-	      p = strchr (p2, '\0');
-	      while (isblank ((unsigned char)p[-1]))
-		--p;
-	      do_define (p2, p - p2, o_file, ebuf);
-	    }
-	  continue;
-	}
-
-      if (word1eq ("override"))
-        {
-	  if (*p2 == '\0')
-	    error (fstart, _("empty `override' directive"));
-
-	  if (strneq (p2, "define", 6)
-	      && (isblank ((unsigned char)p2[6]) || p2[6] == '\0'))
-	    {
-	      if (ignoring)
-		in_ignored_define = 1;
-	      else
-		{
-		  p2 = next_token (p2 + 6);
-                  if (*p2 == '\0')
-                    fatal (fstart, _("empty variable name"));
-
-		  /* Let the variable name be the whole rest of the line,
-		     with trailing blanks stripped (comments have already been
-		     removed), so it could be a complex variable/function
-		     reference that might contain blanks.  */
-		  p = strchr (p2, '\0');
-		  while (isblank ((unsigned char)p[-1]))
-		    --p;
-		  do_define (p2, p - p2, o_override, ebuf);
-		}
-	    }
-	  else if (!ignoring
+      /* Check for conditional state changes.  */
+      {
 #ifndef CONFIG_WITH_VALUE_LENGTH
-		   && !try_variable_definition (fstart, p2, o_override, 0))
-#else
-		   && !try_variable_definition (fstart, p2, eol, o_override, 0))
-#endif
-	    error (fstart, _("invalid `override' directive"));
-
-	  continue;
-	}
+        int i = conditional_line (p, wlen, fstart);
+#else
+        int i = conditional_line (p, eol, wlen, fstart);
+#endif
+        if (i != -2)
+          {
+            if (i == -1)
+              fatal (fstart, _("invalid syntax in conditional"));
+
+            ignoring = i;
+            continue;
+          }
+      }
+
+      /* Nothing to see here... move along.  */
+      if (ignoring)
+	continue;
+
 #ifdef CONFIG_WITH_LOCAL_VARIABLES
-
       if (word1eq ("local"))
         {
@@ -880,13 +948,9 @@
                   while (isblank ((unsigned char)p[-1]))
                     --p;
-                  do_define (p2, p - p2, o_local, ebuf);
+                  do_define (p2 IF_WITH_VALUE_LENGTH_PARAM(p), o_local, ebuf);
                 }
             }
           else if (!ignoring
-# ifndef CONFIG_WITH_VALUE_LENGTH
-                   && !try_variable_definition (fstart, p2, o_local, 0))
-# else
-                   && !try_variable_definition (fstart, p2, eol, o_local, 0))
-# endif
+                   && !try_variable_definition (fstart, p2 IF_WITH_VALUE_LENGTH_PARAM(eol), o_local, 0))
             error (fstart, _("invalid `local' directive"));
 
@@ -894,9 +958,4 @@
         }
 #endif /* CONFIG_WITH_LOCAL_VARIABLES */
-
-      if (ignoring)
-	/* Ignore the line.  We continue here so conditionals
-	   can appear in the middle of a rule.  */
-	continue;
 
 #ifdef KMK
@@ -918,94 +977,48 @@
 
 #endif /* KMK */
-      if (word1eq ("export"))
+
+      /* Manage the "export" keyword used outside of variable assignment
+         as well as "unexport".  */
+      if (word1eq ("export") || word1eq ("unexport"))
 	{
-          /* 'export' by itself causes everything to be exported. */
+          int exporting = *p == 'u' ? 0 : 1;
+
+          /* (un)export by itself causes everything to be (un)exported. */
 	  if (*p2 == '\0')
-            export_all_variables = 1;
+            export_all_variables = exporting;
           else
             {
-              struct variable *v;
-
+              unsigned int l;
+              const char *cp;
+              char *ap;
+
+              /* Expand the line so we can use indirect and constructed
+                 variable names in an (un)export command.  */
 #ifndef CONFIG_WITH_VALUE_LENGTH
-              v = try_variable_definition (fstart, p2, o_file, 0);
-#else
-              v = try_variable_definition (fstart, p2, eol, o_file, 0);
-#endif
-              if (v != 0)
-                v->export = v_export;
-              else
+              cp = ap = allocated_variable_expand (p2);
+#else
+              unsigned int buf_len;
+              cp = ap = allocated_variable_expand_3 (p2, eol - p2, NULL, &buf_len);
+#endif
+
+              for (p = find_next_token (&cp, &l); p != 0;
+                   p = find_next_token (&cp, &l))
                 {
-                  unsigned int l;
-                  const char *cp;
-                  char *ap;
-
-                  /* Expand the line so we can use indirect and constructed
-                     variable names in an export command.  */
+                  struct variable *v = lookup_variable (p, l);
+                  if (v == 0)
+                    v = define_variable_loc (p, l, "", o_file, 0, fstart);
+                  v->export = exporting ? v_export : v_noexport;
+                }
+
 #ifndef CONFIG_WITH_VALUE_LENGTH
-                  cp = ap = allocated_variable_expand (p2);
-#else
-                  unsigned int buf_len;
-                  cp = ap = allocated_variable_expand_3 (p2, eol - p2, NULL, &buf_len);
-#endif
-
-                  for (p = find_next_token (&cp, &l); p != 0;
-                       p = find_next_token (&cp, &l))
-                    {
-                      v = lookup_variable (p, l);
-                      if (v == 0)
-                        v = define_variable_loc (p, l, "", o_file, 0, fstart);
-                      v->export = v_export;
-                    }
-
-#ifndef CONFIG_WITH_VALUE_LENGTH
-                  free (ap);
-#else
-                  recycle_variable_buffer (ap, buf_len);
-#endif
-                }
+              free (ap);
+#else
+              recycle_variable_buffer (ap, buf_len);
+#endif
             }
           goto rule_complete;
 	}
 
-      if (word1eq ("unexport"))
-	{
-	  if (*p2 == '\0')
-	    export_all_variables = 0;
-          else
-            {
-              unsigned int l;
-              struct variable *v;
-              const char *cp;
-              char *ap;
-
-              /* Expand the line so we can use indirect and constructed
-                 variable names in an unexport command.  */
-#ifndef CONFIG_WITH_VALUE_LENGTH
-              cp = ap = allocated_variable_expand (p2);
-#else
-              unsigned int buf_len;
-              cp = ap = allocated_variable_expand_3 (p2, eol - p2, NULL, &buf_len);
-#endif
-
-              for (p = find_next_token (&cp, &l); p != 0;
-                   p = find_next_token (&cp, &l))
-                {
-                  v = lookup_variable (p, l);
-                  if (v == 0)
-                    v = define_variable_loc (p, l, "", o_file, 0, fstart);
-
-                  v->export = v_noexport;
-                }
-
-#ifndef CONFIG_WITH_VALUE_LENGTH
-              free (ap);
-#else
-              recycle_variable_buffer (ap, buf_len);
-#endif
-            }
-          goto rule_complete;
-	}
-
- skip_conditionals:
+      /* Handle the special syntax for vpath.  */
       if (word1eq ("vpath"))
 	{
@@ -1017,5 +1030,5 @@
 	  if (p != 0)
 	    {
-	      vpat = savestring (p, l);
+	      vpat = xstrndup (p, l);
 	      p = find_next_token (&cp, &l);
 	      /* No searchpath means remove all previous
@@ -1069,4 +1082,5 @@
 #endif /* CONFIG_WITH_INCLUDEDEP */
 
+      /* Handle include and variants.  */
       if (word1eq ("include") || word1eq ("-include") || word1eq ("sinclude"))
 	{
@@ -1098,15 +1112,8 @@
             }
 
-	  /* Parse the list of file names.  */
+	  /* Parse the list of file names.  Don't expand archive references!  */
 	  p2 = p;
-#ifndef CONFIG_WITH_ALLOC_CACHES
-	  files = multi_glob (parse_file_seq (&p2, '\0',
-					      sizeof (struct nameseq),
-					      1),
-			      sizeof (struct nameseq));
-#else
-          files = multi_glob (parse_file_seq (&p2, '\0', &nameseq_cache, 1),
-                              &nameseq_cache);
-#endif
+	  files = PARSE_FILE_SEQ (&p2, struct nameseq, '\0', NULL,
+                                  PARSEFS_NOAR);
 #ifndef CONFIG_WITH_VALUE_LENGTH
 	  free (p);
@@ -1130,13 +1137,11 @@
               int r;
 
-#ifndef CONFIG_WITH_ALLOC_CACHES
-	      free (files);
-#else
-	      alloccache_free (&nameseq_cache, files);
-#endif
+	      free_ns (files);
 	      files = next;
 
-              r = eval_makefile (name, (RM_INCLUDED | RM_NO_TILDE
-                                        | (noerror ? RM_DONTCARE : 0)));
+              r = eval_makefile (name,
+                                 (RM_INCLUDED | RM_NO_TILDE
+                                  | (noerror ? RM_DONTCARE : 0)
+                                  | (set_default ? 0 : RM_NO_DEFAULT_GOAL)));
 	      if (!r && !noerror)
                 error (fstart, "%s: %s", name, strerror (errno));
@@ -1148,12 +1153,4 @@
           goto rule_complete;
 	}
-
-#ifndef CONFIG_WITH_VALUE_LENGTH
-      if (try_variable_definition (fstart, p, o_file, 0))
-#else
-      if (try_variable_definition (fstart, p, eol, o_file, 0))
-#endif
-	/* This line has been dealt with.  */
-	goto rule_complete;
 
       /* This line starts with a tab but was not caught above because there
@@ -1175,6 +1172,4 @@
       {
         enum make_word_type wtype;
-        enum variable_origin v_origin;
-        int exported;
         char *cmdleft, *semip, *lb_next;
         unsigned int plen = 0;
@@ -1347,13 +1342,5 @@
            looking for targets.  */
         *colonp = '\0';
-#ifndef CONFIG_WITH_ALLOC_CACHES
-        filenames = multi_glob (parse_file_seq (&p2, '\0',
-                                                sizeof (struct nameseq),
-                                                1),
-                                sizeof (struct nameseq));
-#else
-        filenames = multi_glob (parse_file_seq (&p2, '\0', &nameseq_cache, 1),
-                                &nameseq_cache);
-#endif
+        filenames = PARSE_FILE_SEQ (&p2, struct nameseq, '\0', NULL, 0);
         *p2 = ':';
 
@@ -1386,29 +1373,6 @@
           }
 
-        /* See if it's an "override" or "export" keyword; if so see if what
-           comes after it looks like a variable definition.  */
-
-        wtype = get_next_mword (p2, NULL, &p, &wlen);
-
-        v_origin = o_file;
-        exported = 0;
-        if (wtype == w_static)
-          {
-            if (word1eq ("override"))
-              {
-                v_origin = o_override;
-                wtype = get_next_mword (p+wlen, NULL, &p, &wlen);
-              }
-            else if (word1eq ("export"))
-              {
-                exported = 1;
-                wtype = get_next_mword (p+wlen, NULL, &p, &wlen);
-              }
-          }
-
-        if (wtype != w_eol)
-          wtype = get_next_mword (p+wlen, NULL, NULL, NULL);
-
-        if (wtype == w_varassign)
+        p2 = parse_var_assignment (p2, &vmod);
+        if (vmod.assign_v)
           {
             /* If there was a semicolon found, add it back, plus anything
@@ -1418,9 +1382,16 @@
                 unsigned int l = p - variable_buffer;
                 *(--semip) = ';';
+#ifndef CONFIG_WITH_VALUE_LENGTH
+                collapse_continuations (semip);
+#else
+                collapse_continuations (semip, strlen(semip)); /** @todo fix this */
+#endif
                 variable_buffer_output (p2 + strlen (p2),
                                         semip, strlen (semip)+1);
                 p = variable_buffer + l;
               }
-            record_target_var (filenames, p, v_origin, exported, fstart);
+            record_target_var (filenames, p2,
+                               vmod.override_v ? o_override : o_file,
+                               &vmod, fstart);
             filenames = 0;
             continue;
@@ -1463,6 +1434,6 @@
         while (p != 0 && p[-1] == '\\')
           {
-            register char *q = &p[-1];
-            register int backslash = 0;
+            char *q = &p[-1];
+            int backslash = 0;
             while (*q-- == '\\')
               backslash = !backslash;
@@ -1507,9 +1478,6 @@
           {
             struct nameseq *target;
-#ifndef CONFIG_WITH_ALLOC_CACHES
-            target = parse_file_seq (&p2, ':', sizeof (struct nameseq), 1);
-#else
-            target = parse_file_seq (&p2, ':', &nameseq_cache, 1);
-#endif
+            target = PARSE_FILE_SEQ (&p2, struct nameseq, ':', NULL,
+                                     PARSEFS_NOGLOB);
             ++p2;
             if (target == 0)
@@ -1521,9 +1489,5 @@
             if (pattern_percent == 0)
               fatal (fstart, _("target pattern contains no `%%' (target `%s')"), target->name); /* bird */
-#ifndef CONFIG_WITH_ALLOC_CACHES
-            free (target);
-#else
-            alloccache_free (&nameseq_cache, target);
-#endif
+            free_ns (target);
           }
         else
@@ -1535,23 +1499,9 @@
         strip_whitespace (&beg, &end);
 
+        /* Put all the prerequisites here; they'll be parsed later.  */
         if (beg <= end && *beg != '\0')
-          {
-            /* Put all the prerequisites here; they'll be parsed later.  */
-            deps = alloc_dep ();
-#ifndef CONFIG_WITH_VALUE_LENGTH
-            deps->name = strcache_add_len (beg, end - beg + 1);
-#else  /* CONFIG_WITH_VALUE_LENGTH */
-            {
-              /* Make sure the strcache_add_len input is terminated so it
-                 doesn't have to make a temporary copy on the stack. */
-              char saved = end[1];
-              ((char *)end)[1] = '\0';
-              deps->name = strcache_add_len (beg, end - beg + 1);
-              ((char *)end)[1] = saved;
-            }
-#endif /* CONFIG_WITH_VALUE_LENGTH */
-          }
+          depstr = xstrndup (beg, end - beg + 1);
         else
-          deps = 0;
+          depstr = 0;
 
         commands_idx = 0;
@@ -1587,8 +1537,7 @@
            Because the target is not recorded until after ifeq directive is
            evaluated the .DEFAULT_GOAL does not contain foo yet as one
-           would expect. Because of this we have to move some of the logic
-           here.  */
-
-        if (**default_goal_name == '\0' && set_default)
+           would expect. Because of this we have to move the logic here.  */
+
+        if (set_default && default_goal_var->value[0] == '\0')
           {
             const char *name;
@@ -1680,6 +1629,4 @@
     free (collapsed);
   free (commands);
-
-  return 1;
 }
 
@@ -1758,40 +1705,81 @@
 #endif /* CONFIG_WITH_VALUE_LENGTH */
 
+/* Execute a `undefine' directive.
+   The undefine line has already been read, and NAME is the name of
+   the variable to be undefined. */
+
+static void
+do_undefine (char *name, enum variable_origin origin, struct ebuffer *ebuf)
+{
+  char *p, *var;
+
+  /* Expand the variable name and find the beginning (NAME) and end.  */
+  var = allocated_variable_expand (name);
+  name = next_token (var);
+  if (*name == '\0')
+    fatal (&ebuf->floc, _("empty variable name"));
+  p = name + strlen (name) - 1;
+  while (p > name && isblank ((unsigned char)*p))
+    --p;
+  p[1] = '\0';
+
+  undefine_variable_global (name, p - name + 1, origin);
+  free (var);
+}
+
 /* Execute a `define' directive.
    The first line has already been read, and NAME is the name of
    the variable to be defined.  The following lines remain to be read.  */
 
-static void
-do_define (char *name, unsigned int namelen,
+static struct variable *
+do_define (char *name IF_WITH_VALUE_LENGTH_PARAM(char *eos),
            enum variable_origin origin, struct ebuffer *ebuf)
 {
+  struct variable *v;
+  enum variable_flavor flavor;
   struct floc defstart;
-  long nlines = 0;
   int nlevels = 1;
   unsigned int length = 100;
   char *definition = xmalloc (length);
   unsigned int idx = 0;
-  char *p;
-
-  /* Expand the variable name.  */
-  char *var = alloca (namelen + 1);
-  memcpy (var, name, namelen);
-  var[namelen] = '\0';
-  var = variable_expand (var);
+  char *p, *var;
 
   defstart = ebuf->floc;
 
+  p = parse_variable_definition (name, &flavor);
+  if (p == NULL)
+    /* No assignment token, so assume recursive.  */
+    flavor = f_recursive;
+  else
+    {
+      if (*(next_token (p)) != '\0')
+        error (&defstart, _("extraneous text after `define' directive"));
+
+      /* Chop the string before the assignment token to get the name.  */
+      p[flavor == f_recursive ? -1 : -2] = '\0';
+    }
+
+  /* Expand the variable name and find the beginning (NAME) and end.  */
+  var = allocated_variable_expand (name);
+  name = next_token (var);
+  if (*name == '\0')
+    fatal (&defstart, _("empty variable name"));
+  p = name + strlen (name) - 1;
+  while (p > name && isblank ((unsigned char)*p))
+    --p;
+  p[1] = '\0';
+
+  /* Now read the value of the variable.  */
   while (1)
     {
       unsigned int len;
       char *line;
-
-      nlines = readline (ebuf);
+      long nlines = readline (ebuf);
+
+      /* If there is nothing left to be eval'd, there's no 'endef'!!  */
+      if (nlines < 0)
+        fatal (&defstart, _("missing `endef', unterminated `define'"));
+
       ebuf->floc.lineno += nlines;
-
-      /* If there is nothing left to eval, we're done. */
-      if (nlines < 0)
-        break;
-
       line = ebuf->buffer;
 
@@ -1803,7 +1791,5 @@
 
       /* If the line doesn't begin with a tab, test to see if it introduces
-         another define, or ends one.  */
-
-      /* Stop if we find an 'endef' */
+         another define, or ends one.  Stop if we find an 'endef' */
       if (line[0] != cmd_prefix)
         {
@@ -1832,26 +1818,14 @@
               ebuf->eol = remove_comments (p, ebuf->eol);
 #endif
-              if (*next_token (p) != '\0')
+              if (*(next_token (p)) != '\0')
                 error (&ebuf->floc,
-                       _("Extraneous text after `endef' directive"));
+                       _("extraneous text after `endef' directive"));
 
               if (--nlevels == 0)
-                {
-                  /* Define the variable.  */
-                  if (idx == 0)
-                    definition[0] = '\0';
-                  else
-                    definition[idx - 1] = '\0';
-
-                  /* Always define these variables in the global set.  */
-                  define_variable_global (var, strlen (var), definition,
-                                          origin, 1, &defstart);
-                  free (definition);
-                  return;
-                }
+                break;
             }
         }
 
-      /* Otherwise add this line to the variable definition.  */
+      /* Add this line to the variable definition.  */
 #ifndef CONFIG_WITH_VALUE_LENGTH
       len = strlen (line);
@@ -1872,9 +1846,14 @@
     }
 
-  /* No `endef'!!  */
-  fatal (&defstart, _("missing `endef', unterminated `define'"));
-
-  /* NOTREACHED */
-  return;
+  /* We've got what we need; define the variable.  */
+  if (idx == 0)
+    definition[0] = '\0';
+  else
+    definition[idx - 1] = '\0';
+
+  v = do_variable_definition (&defstart, name, definition, origin, flavor, 0);
+  free (definition);
+  free (var);
+  return (v);
 }
 
@@ -2267,118 +2246,4 @@
 
 
-/* Remove duplicate dependencies in CHAIN.  */
-#ifndef CONFIG_WITH_STRCACHE2
-
-static unsigned long
-dep_hash_1 (const void *key)
-{
-  return_STRING_HASH_1 (dep_name ((struct dep const *) key));
-}
-
-static unsigned long
-dep_hash_2 (const void *key)
-{
-  return_STRING_HASH_2 (dep_name ((struct dep const *) key));
-}
-
-static int
-dep_hash_cmp (const void *x, const void *y)
-{
-  struct dep *dx = (struct dep *) x;
-  struct dep *dy = (struct dep *) y;
-  int cmp = strcmp (dep_name (dx), dep_name (dy));
-
-  /* If the names are the same but ignore_mtimes are not equal, one of these
-     is an order-only prerequisite and one isn't.  That means that we should
-     remove the one that isn't and keep the one that is.  */
-
-  if (!cmp && dx->ignore_mtime != dy->ignore_mtime)
-    dx->ignore_mtime = dy->ignore_mtime = 0;
-
-  return cmp;
-}
-
-#else  /* CONFIG_WITH_STRCACHE2 */
-
-/* Exploit the fact that all names are in the string cache. This means equal
-   names shall have the same storage and there is no need for hashing or
-   comparing. Use the address as the first hash, avoiding any touching of
-   the name, and the length as the second. */
-
-static unsigned long
-dep_hash_1 (const void *key)
-{
-  const char *name = dep_name ((struct dep const *) key);
-  assert (strcache2_is_cached (&file_strcache, name));
-  return (size_t) name / sizeof(void *);
-}
-
-static unsigned long
-dep_hash_2 (const void *key)
-{
-  const char *name = dep_name ((struct dep const *) key);
-  return strcache2_get_len (&file_strcache, name);
-}
-
-static int
-dep_hash_cmp (const void *x, const void *y)
-{
-  struct dep *dx = (struct dep *) x;
-  struct dep *dy = (struct dep *) y;
-  const char *dxname = dep_name (dx);
-  const char *dyname = dep_name (dy);
-  int cmp = dxname == dyname ? 0 : 1;
-
-  /* check preconds: both cached and the cache contains no duplicates. */
-  assert (strcache2_is_cached (&file_strcache, dxname));
-  assert (strcache2_is_cached (&file_strcache, dyname));
-  assert (cmp == 0 || strcmp (dxname, dyname) != 0);
-
-  /* If the names are the same but ignore_mtimes are not equal, one of these
-     is an order-only prerequisite and one isn't.  That means that we should
-     remove the one that isn't and keep the one that is.  */
-
-  if (!cmp && dx->ignore_mtime != dy->ignore_mtime)
-    dx->ignore_mtime = dy->ignore_mtime = 0;
-
-  return cmp;
-}
-
-#endif /* CONFIG_WITH_STRCACHE2 */
-
-void
-uniquize_deps (struct dep *chain)
-{
-  struct hash_table deps;
-  register struct dep **depp;
-
-  hash_init (&deps, 500, dep_hash_1, dep_hash_2, dep_hash_cmp);
-
-  /* Make sure that no dependencies are repeated.  This does not
-     really matter for the purpose of updating targets, but it
-     might make some names be listed twice for $^ and $?.  */
-
-  depp = &chain;
-  while (*depp)
-    {
-      struct dep *dep = *depp;
-      struct dep **dep_slot = (struct dep **) hash_find_slot (&deps, dep);
-      if (HASH_VACANT (*dep_slot))
-	{
-	  hash_insert_at (&deps, dep, dep_slot);
-	  depp = &dep->next;
-	}
-      else
-	{
-	  /* Don't bother freeing duplicates.
-	     It's dangerous and little benefit accrues.  */
-	  *depp = dep->next;
-	}
-    }
-
-  hash_free (&deps, 0);
-}
-
-
 /* Record target-specific variable values for files FILENAMES.
    TWO_COLON is nonzero if a double colon was used.
@@ -2392,5 +2257,5 @@
 static void
 record_target_var (struct nameseq *filenames, char *defn,
-                   enum variable_origin origin, int exported,
+                   enum variable_origin origin, struct vmodifiers *vmod,
                    const struct floc *flocp)
 {
@@ -2412,9 +2277,5 @@
 
       nextf = filenames->next;
-#ifndef CONFIG_WITH_ALLOC_CACHES
-      free (filenames);
-#else
-      alloccache_free (&nameseq_cache, filenames);
-#endif
+      free_ns (filenames);
 
       /* If it's a pattern target, then add it to the pattern-specific
@@ -2428,11 +2289,8 @@
           /* I don't think this can fail since we already determined it was a
              variable definition.  */
-#ifndef CONFIG_WITH_VALUE_LENGTH
-          v = parse_variable_definition (&p->variable, defn);
-#else
-          v = parse_variable_definition (&p->variable, defn, NULL);
-#endif
+          v = assign_variable_definition (&p->variable, defn IF_WITH_VALUE_LENGTH_PARAM(NULL));
           assert (v != 0);
 
+          v->origin = origin;
           if (v->flavor == f_simple)
             v->value = allocated_variable_expand (v->value);
@@ -2468,22 +2326,18 @@
 
           current_variable_set_list = f->variables;
-#ifndef CONFIG_WITH_VALUE_LENGTH
-          v = try_variable_definition (flocp, defn, origin, 1);
-#else
-          v = try_variable_definition (flocp, defn, NULL, origin, 1);
-#endif
+          v = try_variable_definition (flocp, defn IF_WITH_VALUE_LENGTH_PARAM(NULL), origin, 1);
           if (!v)
-            error (flocp, _("Malformed target-specific variable definition"));
+            fatal (flocp, _("Malformed target-specific variable definition"));
           current_variable_set_list = global;
         }
 
       /* Set up the variable to be *-specific.  */
-      v->origin = origin;
       v->per_target = 1;
-      v->export = exported ? v_export : v_default;
+      v->private_var = vmod->private_v;
+      v->export = vmod->export_v ? v_export : v_default;
 
       /* If it's not an override, check to see if there was a command-line
          setting.  If so, reset the value.  */
-      if (origin != o_override)
+      if (v->origin != o_override)
         {
           struct variable *gv;
@@ -2507,5 +2361,5 @@
               v->value = xstrdup (gv->value);
 #else
-              v->value = savestring (gv->value, gv->value_length);
+              v->value = xstrndup (gv->value, gv->value_length);
               v->value_length = gv->value_length;
 #endif
@@ -2530,20 +2384,11 @@
    that are not incorporated into other data structures.  */
 
-#ifndef CONFIG_WITH_INCLUDEDEP
 static void
-#else
-void
-#endif
 record_files (struct nameseq *filenames, const char *pattern,
-              const char *pattern_percent, struct dep *deps,
+              const char *pattern_percent, char *depstr,
               unsigned int cmds_started, char *commands,
               unsigned int commands_idx, int two_colon,
               const struct floc *flocp)
 {
-  struct nameseq *nextf;
-  int implicit = 0;
-  unsigned int max_targets = 0, target_idx = 0;
-  const char **targets = 0, **target_percents = 0;
-  struct commands *cmds;
 #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
   struct file *prev_file = 0;
@@ -2551,4 +2396,8 @@
     multi_mode = !two_colon && !pattern ? m_unsettled : m_no;
 #endif
+  struct commands *cmds;
+  struct dep *deps;
+  const char *implicit_percent;
+  const char *name;
 
   /* If we've already snapped deps, that means we're in an eval being
@@ -2559,4 +2408,9 @@
     fatal (flocp, _("prerequisites cannot be defined in recipes"));
 
+  /* Determine if this is a pattern rule or not.  */
+  name = filenames->name;
+  implicit_percent = find_percent_cached (&name);
+
+  /* If there's a recipe, set up a struct for it.  */
   if (commands_idx > 0)
     {
@@ -2568,5 +2422,5 @@
       cmds->fileinfo.filenm = flocp->filenm;
       cmds->fileinfo.lineno = cmds_started;
-      cmds->commands = savestring (commands, commands_idx);
+      cmds->commands = xstrndup (commands, commands_idx);
       cmds->command_lines = 0;
 #ifdef CONFIG_WITH_MEMORY_OPTIMIZATIONS
@@ -2575,25 +2429,98 @@
     }
   else
-    cmds = 0;
-
-  for (; filenames != 0; filenames = nextf)
+     cmds = 0;
+
+  /* If there's a prereq string then parse it--unless it's eligible for 2nd
+     expansion: if so, snap_deps() will do it.  */
+  if (depstr == 0)
+    deps = 0;
+  else if (second_expansion && strchr (depstr, '$'))
     {
-      const char *name = filenames->name;
+      deps = alloc_dep ();
+      deps->name = depstr;
+      deps->need_2nd_expansion = 1;
+      deps->staticpattern = pattern != 0;
+    }
+  else
+    {
+      deps = split_prereqs (depstr);
+      free (depstr);
+
+      /* We'll enter static pattern prereqs later when we have the stem.  We
+         don't want to enter pattern rules at all so that we don't think that
+         they ought to exist (make manual "Implicit Rule Search Algorithm",
+         item 5c).  */
+      if (! pattern && ! implicit_percent)
+        deps = enter_prereqs (deps, NULL);
+    }
+
+  /* For implicit rules, _all_ the targets must have a pattern.  That means we
+     can test the first one to see if we're working with an implicit rule; if
+     so we handle it specially. */
+
+  if (implicit_percent)
+    {
+      struct nameseq *nextf;
+      const char **targets, **target_pats;
+      unsigned int c;
+
+      if (pattern != 0)
+        fatal (flocp, _("mixed implicit and static pattern rules"));
+
+      /* Count the targets to create an array of target names.
+         We already have the first one.  */
+      nextf = filenames->next;
+      free_ns (filenames);
+      filenames = nextf;
+
+      for (c = 1; nextf; ++c, nextf = nextf->next)
+        ;
+      targets = xmalloc (c * sizeof (const char *));
+      target_pats = xmalloc (c * sizeof (const char *));
+
+      targets[0] = name;
+      target_pats[0] = implicit_percent;
+
+      c = 1;
+      while (filenames)
+        {
+          name = filenames->name;
+          implicit_percent = find_percent_cached (&name);
+
+          if (implicit_percent == 0)
+            fatal (flocp, _("mixed implicit and normal rules"));
+
+	  targets[c] = name;
+	  target_pats[c] = implicit_percent;
+          ++c;
+
+          nextf = filenames->next;
+          free_ns (filenames);
+          filenames = nextf;
+        }
+
+      create_pattern_rule (targets, target_pats, c, two_colon, deps, cmds, 1);
+
+      return;
+    }
+
+
+  /* Walk through each target and create it in the database.
+     We already set up the first target, above.  */
+  while (1)
+    {
+      struct nameseq *nextf = filenames->next;
       struct file *f;
       struct dep *this = 0;
-      const char *implicit_percent;
-
-      nextf = filenames->next;
-#ifndef CONFIG_WITH_ALLOC_CACHES
-      free (filenames);
-#else
-      alloccache_free (&nameseq_cache, filenames);
-#endif
+
+      free_ns (filenames);
 
       /* Check for special targets.  Do it here instead of, say, snap_deps()
          so that we can immediately use the value.  */
-
       if (streq (name, ".POSIX"))
-        posix_pedantic = 1;
+        {
+          posix_pedantic = 1;
+          define_variable_cname (".SHELLFLAGS", "-ec", o_default, 0);
+        }
       else if (streq (name, ".SECONDEXPANSION"))
         second_expansion = 1;
@@ -2602,35 +2529,8 @@
         second_target_expansion = 1;
 #endif
-
-      implicit_percent = find_percent_cached (&name);
-      implicit |= implicit_percent != 0;
-
-      if (implicit)
-        {
-          if (pattern != 0)
-            fatal (flocp, _("mixed implicit and static pattern rules"));
-
-          if (implicit_percent == 0)
-            fatal (flocp, _("mixed implicit and normal rules"));
-
-	  if (targets == 0)
-	    {
-	      max_targets = 5;
-	      targets = xmalloc (5 * sizeof (char *));
-	      target_percents = xmalloc (5 * sizeof (char *));
-	      target_idx = 0;
-	    }
-	  else if (target_idx == max_targets - 1)
-	    {
-	      max_targets += 5;
-	      targets = xrealloc ((void *)targets, max_targets * sizeof (char *));
-	      target_percents = xrealloc ((void *)target_percents,
-                                          max_targets * sizeof (char *));
-	    }
-	  targets[target_idx] = name;
-	  target_percents[target_idx] = implicit_percent;
-	  ++target_idx;
-	  continue;
-	}
+#if !defined(WINDOWS32) && !defined (__MSDOS__) && !defined (__EMX__)
+      else if (streq (name, ".ONESHELL"))
+        one_shell = 1;
+#endif
 
 #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
@@ -2670,5 +2570,5 @@
                 }
               multi_mode = name[1] == '\0' ? m_yes : m_yes_maybe;
-              continue;
+              goto l_next;
             }
         }
@@ -2678,22 +2578,19 @@
 
       /* If this is a static pattern rule:
-         `targets: target%pattern: dep%pattern; cmds',
+         `targets: target%pattern: prereq%pattern; recipe',
          make sure the pattern matches this target name.  */
       if (pattern && !pattern_matches (pattern, pattern_percent, name))
         error (flocp, _("target `%s' doesn't match the target pattern"), name);
       else if (deps)
-        {
-          /* If there are multiple filenames, copy the chain DEPS for all but
-             the last one.  It is not safe for the same deps to go in more
-             than one place in the database.  */
-          this = nextf != 0 ? copy_dep_chain (deps) : deps;
-          this->need_2nd_expansion = (second_expansion
-				      && strchr (this->name, '$'));
-        }
-
+        /* If there are multiple targets, copy the chain DEPS for all but the
+           last one.  It is not safe for the same deps to go in more than one
+           place in the database.  */
+        this = nextf != 0 ? copy_dep_chain (deps) : deps;
+
+      /* Find or create an entry in the file database for this target.  */
       if (!two_colon)
 	{
-	  /* Single-colon.  Combine these dependencies
-	     with others in file's existing record, if any.  */
+	  /* Single-colon.  Combine this rule with the file's existing record,
+	     if any.  */
 #ifndef KMK
 	  f = enter_file (strcache_add (name));
@@ -2701,5 +2598,4 @@
 	  f = enter_file (name);
 #endif
-
 	  if (f->double_colon)
 	    fatal (flocp,
@@ -2726,6 +2622,4 @@
 	    }
 
-	  f->is_target = 1;
-
 	  /* Defining .DEFAULT with no deps or cmds clears it.  */
 	  if (f == default_file && this == 0 && cmds == 0)
@@ -2759,66 +2653,4 @@
               free_dep_chain (f->deps);
 	      f->deps = 0;
-	    }
-          else if (this != 0)
-	    {
-	      /* Add the file's old deps and the new ones in THIS together.  */
-
-              if (f->deps != 0)
-                {
-                  struct dep **d_ptr = &f->deps;
-
-                  while ((*d_ptr)->next != 0)
-                    d_ptr = &(*d_ptr)->next;
-
-                  if (cmds != 0)
-                    /* This is the rule with commands, so put its deps
-                       last. The rationale behind this is that $< expands to
-                       the first dep in the chain, and commands use $<
-                       expecting to get the dep that rule specifies.  However
-                       the second expansion algorithm reverses the order thus
-                       we need to make it last here.  */
-                    (*d_ptr)->next = this;
-                  else
-                    {
-                      /* This is the rule without commands. Put its
-                         dependencies at the end but before dependencies from
-                         the rule with commands (if any). This way everything
-                         appears in makefile order.  */
-
-                      if (f->cmds != 0)
-                        {
-#ifndef KMK /* bugfix: Don't chop the chain! */
-                          this->next = *d_ptr;
-                          *d_ptr = this;
-#else   /* KMK */
-                          struct dep *this_last = this;
-                          while (this_last->next)
-                            this_last = this_last->next;
-                          this_last->next = *d_ptr;
-                          *d_ptr = this;
-#endif  /* KMK */
-                        }
-                      else
-                        (*d_ptr)->next = this;
-                    }
-                }
-              else
-                f->deps = this;
-
-              /* This is a hack. I need a way to communicate to snap_deps()
-                 that the last dependency line in this file came with commands
-                 (so that logic in snap_deps() can put it in front and all
-                 this $< -logic works). I cannot simply rely on file->cmds
-                 being not 0 because of the cases like the following:
-
-                 foo: bar
-                 foo:
-                     ...
-
-                 I am going to temporarily "borrow" UPDATING member in
-                 `struct file' for this.   */
-
-              if (cmds != 0)
-                f->updating = 1;
 	    }
 	}
@@ -2832,9 +2664,10 @@
 #endif /* CONFIG_WITH_STRCACHE2 */
 
-	  /* Check for both : and :: rules.  Check is_target so
-	     we don't lose on default suffix rules or makefiles.  */
+	  /* Check for both : and :: rules.  Check is_target so we don't lose
+	     on default suffix rules or makefiles.  */
 	  if (f != 0 && f->is_target && !f->double_colon)
 	    fatal (flocp,
                    _("target file `%s' has both : and :: entries"), f->name);
+
 #ifndef KMK
 	  f = enter_file (strcache_add (name));
@@ -2850,12 +2683,13 @@
 	       double_colon pointer to itself.  */
 	    f->double_colon = f;
-	  f->is_target = 1;
-	  f->deps = this;
+
 	  f->cmds = cmds;
 	}
 
+      f->is_target = 1;
+
       /* If this is a static pattern rule, set the stem to the part of its
          name that matched the `%' in the pattern, so you can use $* in the
-         commands.  */
+         commands.  If we didn't do it before, enter the prereqs now.  */
       if (pattern)
         {
@@ -2869,24 +2703,55 @@
           if (this)
             {
-              this->staticpattern = 1;
-              this->stem = f->stem;
+              if (! this->need_2nd_expansion)
+                this = enter_prereqs (this, f->stem);
+              else
+                this->stem = f->stem;
             }
         }
 
+      /* Add the dependencies to this file entry.  */
+      if (this != 0)
+        {
+          /* Add the file's old deps and the new ones in THIS together.  */
+          if (f->deps == 0)
+            f->deps = this;
+          else if (cmds != 0)
+            {
+              struct dep *d = this;
+
+              /* If this rule has commands, put these deps first.  */
+              while (d->next != 0)
+                d = d->next;
+
+              d->next = f->deps;
+              f->deps = this;
+            }
+          else
+            {
+              struct dep *d = f->deps;
+
+              /* A rule without commands: put its prereqs at the end.  */
+              while (d->next != 0)
+                d = d->next;
+
+              d->next = this;
+            }
+        }
+
       name = f->name;
 
-      /* If this target is a default target, update DEFAULT_GOAL_FILE.  */
-      if (streq (*default_goal_name, name)
-          && (default_goal_file == 0
-              || ! streq (default_goal_file->name, name)))
-        default_goal_file = f;
-    }
-
-  if (implicit)
-    {
-      if (deps)
-        deps->need_2nd_expansion = second_expansion;
-      create_pattern_rule (targets, target_percents, target_idx,
-                           two_colon, deps, cmds, 1);
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+l_next:
+#endif
+      /* All done!  Set up for the next one.  */
+      if (nextf == 0)
+        break;
+
+      filenames = nextf;
+
+      /* Reduce escaped percents.  If there are any unescaped it's an error  */
+      name = filenames->name;
+      if (find_percent_cached (&name))
+        fatal (flocp, _("mixed implicit and normal rules"));
     }
 }
@@ -3111,269 +2976,4 @@
 
 
-/* Parse a string into a sequence of filenames represented as a
-   chain of struct nameseq's in reverse order and return that chain.
-
-   The string is passed as STRINGP, the address of a string pointer.
-   The string pointer is updated to point at the first character
-   not parsed, which either is a null char or equals STOPCHAR.
-
-   SIZE is how big to construct chain elements.
-   This is useful if we want them actually to be other structures
-   that have room for additional info.
-
-   If STRIP is nonzero, strip `./'s off the beginning.  */
-
-#ifndef CONFIG_WITH_ALLOC_CACHES
-struct nameseq *
-parse_file_seq (char **stringp, int stopchar, unsigned int size, int strip)
-#else
-struct nameseq *
-parse_file_seq (char **stringp, int stopchar, struct alloccache *cache, int strip)
-#endif
-{
-  struct nameseq *new = 0;
-  struct nameseq *new1;
-#ifndef NO_ARCHIVES /* bird: MSC warning */
-  struct nameseq *lastnew1;
-#endif
-  char *p = *stringp;
-
-#ifdef VMS
-# define VMS_COMMA ','
-#else
-# define VMS_COMMA 0
-#endif
-
-  while (1)
-    {
-      const char *name;
-      char *q;
-
-      /* Skip whitespace; see if any more names are left.  */
-      p = next_token (p);
-      if (*p == '\0')
-	break;
-      if (*p == stopchar)
-	break;
-
-      /* There are, so find the end of the next name.  */
-      q = p;
-      p = find_char_unquote (q, stopchar, VMS_COMMA, 1, 0);
-#ifdef VMS
-	/* convert comma separated list to space separated */
-      if (p && *p == ',')
-	*p =' ';
-#endif
-#ifdef _AMIGA
-      if (stopchar == ':' && p && *p == ':'
-          && !(isspace ((unsigned char)p[1]) || !p[1]
-               || isspace ((unsigned char)p[-1])))
-	p = find_char_unquote (p+1, stopchar, VMS_COMMA, 1, 0);
-#endif
-#ifdef HAVE_DOS_PATHS
-    /* For DOS paths, skip a "C:\..." or a "C:/..." until we find the
-       first colon which isn't followed by a slash or a backslash.
-       Note that tokens separated by spaces should be treated as separate
-       tokens since make doesn't allow path names with spaces */
-    if (stopchar == ':')
-      while (p != 0 && !isspace ((unsigned char)*p) &&
-             (p[1] == '\\' || p[1] == '/') && isalpha ((unsigned char)p[-1]))
-        p = find_char_unquote (p + 1, stopchar, VMS_COMMA, 1, 0);
-#endif
-      if (p == 0)
-	p = q + strlen (q);
-
-      if (strip)
-#ifdef VMS
-	/* Skip leading `[]'s.  */
-	while (p - q > 2 && q[0] == '[' && q[1] == ']')
-#else
-	/* Skip leading `./'s.  */
-	while (p - q > 2 && q[0] == '.' && q[1] == '/')
-#endif
-	  {
-	    q += 2;		/* Skip "./".  */
-	    while (q < p && *q == '/')
-	      /* Skip following slashes: ".//foo" is "foo", not "/foo".  */
-	      ++q;
-	  }
-
-      /* Extract the filename just found, and skip it.  */
-
-      if (q == p)
-	/* ".///" was stripped to "". */
-#if defined(VMS)
-	continue;
-#elif defined(_AMIGA)
-        name = "";
-#else
-	name = "./";
-#endif
-      else
-#ifdef VMS
-/* VMS filenames can have a ':' in them but they have to be '\'ed but we need
- *  to remove this '\' before we can use the filename.
- * Savestring called because q may be read-only string constant.
- */
-	{
-	  char *qbase = xstrdup (q);
-	  char *pbase = qbase + (p-q);
-	  char *q1 = qbase;
-	  char *q2 = q1;
-	  char *p1 = pbase;
-
-	  while (q1 != pbase)
-	    {
-	      if (*q1 == '\\' && *(q1+1) == ':')
-		{
-		  q1++;
-		  p1--;
-		}
-	      *q2++ = *q1++;
-	    }
-	  name = strcache_add_len (qbase, p1 - qbase);
-	  free (qbase);
-	}
-#elif !defined (CONFIG_WITH_VALUE_LENGTH) || defined (CONFIG_WITH_STRCACHE2)
-	name = strcache_add_len (q, p - q);
-#else  /* CONFIG_WITH_VALUE_LENGTH */
-       {
-         /* Make sure it's terminated, strcache_add_len has to make a
-            temp copy on the stack otherwise. */
-         char saved = *p;
-         if (!saved)
-           *p = '\0';
-         name = strcache_add_len (q, p - q);
-         if (saved)
-           *p = saved;
-       }
-#endif /* CONFIG_WITH_VALUE_LENGTH */
-
-      /* Add it to the front of the chain.  */
-#ifndef CONFIG_WITH_ALLOC_CACHES
-      new1 = xmalloc (size);
-      memset (new1, '\0', size);
-#else
-      new1 = (struct nameseq *) alloccache_calloc (cache);
-#endif
-      new1->name = name;
-      new1->next = new;
-      new = new1;
-    }
-
-#ifndef NO_ARCHIVES
-
-  /* Look for multi-word archive references.
-     They are indicated by a elt ending with an unmatched `)' and
-     an elt further down the chain (i.e., previous in the file list)
-     with an unmatched `(' (e.g., "lib(mem").  */
-
-  new1 = new;
-  lastnew1 = 0;
-  while (new1 != 0)
-    if (new1->name[0] != '('	/* Don't catch "(%)" and suchlike.  */
-	&& new1->name[strlen (new1->name) - 1] == ')'
-	&& strchr (new1->name, '(') == 0)
-      {
-	/* NEW1 ends with a `)' but does not contain a `('.
-	   Look back for an elt with an opening `(' but no closing `)'.  */
-
-	struct nameseq *n = new1->next, *lastn = new1;
-	char *paren = 0;
-	while (n != 0 && (paren = strchr (n->name, '(')) == 0)
-	  {
-	    lastn = n;
-	    n = n->next;
-	  }
-	if (n != 0
-	    /* Ignore something starting with `(', as that cannot actually
-	       be an archive-member reference (and treating it as such
-	       results in an empty file name, which causes much lossage).  */
-	    && n->name[0] != '(')
-	  {
-	    /* N is the first element in the archive group.
-	       Its name looks like "lib(mem" (with no closing `)').  */
-
-	    char *libname;
-
-	    /* Copy "lib(" into LIBNAME.  */
-	    ++paren;
-	    libname = alloca (paren - n->name + 1);
-	    memcpy (libname, n->name, paren - n->name);
-	    libname[paren - n->name] = '\0';
-
-	    if (*paren == '\0')
-	      {
-		/* N was just "lib(", part of something like "lib( a b)".
-		   Edit it out of the chain and free its storage.  */
-		lastn->next = n->next;
-#ifndef CONFIG_WITH_ALLOC_CACHES
-		free (n);
-#else
-                alloccache_free (cache, n);
-#endif
-		/* LASTN->next is the new stopping elt for the loop below.  */
-		n = lastn->next;
-	      }
-	    else
-	      {
-		/* Replace N's name with the full archive reference.  */
-		n->name = strcache_add (concat (libname, paren, ")"));
-	      }
-
-	    if (new1->name[1] == '\0')
-	      {
-		/* NEW1 is just ")", part of something like "lib(a b )".
-		   Omit it from the chain and free its storage.  */
-		if (lastnew1 == 0)
-		  new = new1->next;
-		else
-		  lastnew1->next = new1->next;
-		lastn = new1;
-		new1 = new1->next;
-#ifndef CONFIG_WITH_ALLOC_CACHES
-		free (lastn);
-#else
-                alloccache_free (cache, lastn);
-#endif
-	      }
-	    else
-	      {
-		/* Replace also NEW1->name, which already has closing `)'.  */
-		new1->name = strcache_add (concat (libname, new1->name, ""));
-		new1 = new1->next;
-	      }
-
-	    /* Trace back from NEW1 (the end of the list) until N
-	       (the beginning of the list), rewriting each name
-	       with the full archive reference.  */
-
-	    while (new1 != n)
-	      {
-		new1->name = strcache_add (concat (libname, new1->name, ")"));
-		lastnew1 = new1;
-		new1 = new1->next;
-	      }
-	  }
-	else
-	  {
-	    /* No frobnication happening.  Just step down the list.  */
-	    lastnew1 = new1;
-	    new1 = new1->next;
-	  }
-      }
-    else
-      {
-	lastnew1 = new1;
-	new1 = new1->next;
-      }
-
-#endif
-
-  *stringp = p;
-  return new;
-}
-
-
 /* Find the next line of text in an eval buffer, combining continuation lines
    into one line.
@@ -3412,14 +3012,14 @@
     {
       int backslash = 0;
-      char *bol = eol;
-      char *p;
+      const char *bol = eol;
+      const char *p;
 
       /* Find the next newline.  At EOS, stop.  */
 #ifndef CONFIG_WITH_VALUE_LENGTH
-      eol = p = strchr (eol , '\n');
+      p = eol = strchr (eol , '\n');
 #else
       p = (char *)memchr (eol, '\n', end - eol);
       assert (!memchr (eol, '\0', p != 0 ? p - eol : end - eol));
-      eol = p;
+      eol = (char *)p;
 #endif
       if (!eol)
@@ -3933,5 +3533,5 @@
       if (home_dir != 0)
 	{
-	  char *new = xstrdup (concat (home_dir, "", name + 1));
+	  char *new = xstrdup (concat (2, home_dir, name + 1));
 	  if (is_variable)
 	    free (home_dir);
@@ -3952,5 +3552,5 @@
 	    return xstrdup (pwent->pw_dir);
 	  else
-	    return xstrdup (concat (pwent->pw_dir, "/", userend + 1));
+	    return xstrdup (concat (3, pwent->pw_dir, "/", userend + 1));
 	}
       else if (userend != 0)
@@ -3962,153 +3562,365 @@
 }
 
-/* Given a chain of struct nameseq's describing a sequence of filenames,
-   in reverse of the intended order, return a new chain describing the
-   result of globbing the filenames.  The new chain is in forward order.
-   The links of the old chain are freed or used in the new chain.
-   Likewise for the names in the old chain.
+
+/* Parse a string into a sequence of filenames represented as a chain of
+   struct nameseq's and return that chain.  Optionally expand the strings via
+   glob().
+
+   The string is passed as STRINGP, the address of a string pointer.
+   The string pointer is updated to point at the first character
+   not parsed, which either is a null char or equals STOPCHAR.
 
    SIZE is how big to construct chain elements.
    This is useful if we want them actually to be other structures
-   that have room for additional info.  */
-
+   that have room for additional info.
+
+   PREFIX, if non-null, is added to the beginning of each filename.
+
+   FLAGS allows one or more of the following bitflags to be set:
+        PARSEFS_NOSTRIP - Do no strip './'s off the beginning
+        PARSEFS_NOAR    - Do not check filenames for archive references
+        PARSEFS_NOGLOB  - Do not expand globbing characters
+        PARSEFS_EXISTS  - Only return globbed files that actually exist
+                          (cannot also set NOGLOB)
+        PARSEFS_NOCACHE - Do not add filenames to the strcache (caller frees)
+  */
+
+void *
+parse_file_seq (char **stringp, unsigned int size, int stopchar,
+                const char *prefix, int flags
+                IF_WITH_ALLOC_CACHES_PARAM(struct alloccache *alloc_cache) )
+{
+  extern void dir_setup_glob (glob_t *glob);
+
+  /* tmp points to tmpbuf after the prefix, if any.
+     tp is the end of the buffer. */
+  static char *tmpbuf = NULL;
+  static int tmpbuf_len = 0;
+
+  int cachep = (! (flags & PARSEFS_NOCACHE));
+
+  struct nameseq *new = 0;
+  struct nameseq **newp = &new;
 #ifndef CONFIG_WITH_ALLOC_CACHES
-struct nameseq *
-multi_glob (struct nameseq *chain, unsigned int size)
-#else
-struct nameseq *
-multi_glob (struct nameseq *chain, struct alloccache *cache)
-#endif
-{
-  void dir_setup_glob (glob_t *);
-  struct nameseq *new = 0;
-  struct nameseq *old;
-  struct nameseq *nexto;
+#define NEWELT(_n)  do { \
+                        const char *__n = (_n); \
+                        *newp = xcalloc (size); \
+                        (*newp)->name = (cachep ? strcache_add (__n) : xstrdup (__n)); \
+                        newp = &(*newp)->next; \
+                    } while(0)
+#else
+# define NEWELT(_n)  do { \
+                        const char *__n = (_n); \
+                        *newp = alloccache_calloc (alloc_cache); \
+                        (*newp)->name = (cachep ? strcache_add (__n) : xstrdup (__n)); \
+                        newp = &(*newp)->next; \
+                    } while(0)
+#endif
+
+  char *p;
   glob_t gl;
-#if defined(KMK) || defined(__EMX__) /* speed optimization */
-  int rc;
-#endif
-
-  dir_setup_glob (&gl);
-
-  for (old = chain; old != 0; old = nexto)
+  char *tp;
+
+#ifdef VMS
+# define VMS_COMMA ','
+#else
+# define VMS_COMMA 0
+#endif
+
+  if (size < sizeof (struct nameseq))
+    size = sizeof (struct nameseq);
+
+  if (! (flags & PARSEFS_NOGLOB))
+    dir_setup_glob (&gl);
+
+  /* Get enough temporary space to construct the largest possible target.  */
+  {
+    int l = strlen (*stringp) + 1;
+    if (l > tmpbuf_len)
+      {
+        tmpbuf = xrealloc (tmpbuf, l);
+        tmpbuf_len = l;
+      }
+  }
+  tp = tmpbuf;
+
+  /* Parse STRING.  P will always point to the end of the parsed content.  */
+  p = *stringp;
+  while (1)
     {
-      const char *gname;
+      const char *name;
+      const char **nlist = 0;
+      char *tildep = 0;
 #ifndef NO_ARCHIVES
       char *arname = 0;
       char *memname = 0;
 #endif
-      nexto = old->next;
-      gname = old->name;
-
-      if (gname[0] == '~')
+      char *s;
+      int nlen;
+      int i;
+
+      /* Skip whitespace; at the end of the string or STOPCHAR we're done.  */
+      p = next_token (p);
+      if (*p == '\0' || *p == stopchar)
+	break;
+
+      /* There are names left, so find the end of the next name.
+         Throughout this iteration S points to the start.  */
+      s = p;
+      p = find_char_unquote (p, stopchar, VMS_COMMA, 1, 0);
+#ifdef VMS
+	/* convert comma separated list to space separated */
+      if (p && *p == ',')
+	*p =' ';
+#endif
+#ifdef _AMIGA
+      if (stopchar == ':' && p && *p == ':'
+          && !(isspace ((unsigned char)p[1]) || !p[1]
+               || isspace ((unsigned char)p[-1])))
+	p = find_char_unquote (p+1, stopchar, VMS_COMMA, 1, 0);
+#endif
+#ifdef HAVE_DOS_PATHS
+    /* For DOS paths, skip a "C:\..." or a "C:/..." until we find the
+       first colon which isn't followed by a slash or a backslash.
+       Note that tokens separated by spaces should be treated as separate
+       tokens since make doesn't allow path names with spaces */
+    if (stopchar == ':')
+      while (p != 0 && !isspace ((unsigned char)*p) &&
+             (p[1] == '\\' || p[1] == '/') && isalpha ((unsigned char)p[-1]))
+        p = find_char_unquote (p + 1, stopchar, VMS_COMMA, 1, 0);
+#endif
+      if (p == 0)
+	p = s + strlen (s);
+
+      /* Strip leading "this directory" references.  */
+      if (! (flags & PARSEFS_NOSTRIP))
+#ifdef VMS
+	/* Skip leading `[]'s.  */
+	while (p - s > 2 && s[0] == '[' && s[1] == ']')
+#else
+	/* Skip leading `./'s.  */
+	while (p - s > 2 && s[0] == '.' && s[1] == '/')
+#endif
+	  {
+            /* Skip "./" and all following slashes.  */
+	    s += 2;
+	    while (*s == '/')
+	      ++s;
+	  }
+
+      /* Extract the filename just found, and skip it.
+         Set NAME to the string, and NLEN to its length.  */
+
+      if (s == p)
+        {
+	/* The name was stripped to empty ("./"). */
+#if defined(VMS)
+          continue;
+#elif defined(_AMIGA)
+          /* PDS-- This cannot be right!! */
+          tp[0] = '\0';
+          nlen = 0;
+#else
+          tp[0] = '.';
+          tp[1] = '/';
+          tp[2] = '\0';
+          nlen = 2;
+#endif
+        }
+      else
 	{
-	  char *newname = tilde_expand (old->name);
-	  if (newname != 0)
-            gname = newname;
+#ifdef VMS
+/* VMS filenames can have a ':' in them but they have to be '\'ed but we need
+ *  to remove this '\' before we can use the filename.
+ * xstrdup called because S may be read-only string constant.
+ */
+	  char *n = tp;
+	  while (s < p)
+	    {
+	      if (s[0] == '\\' && s[1] == ':')
+                ++s;
+	      *(n++) = *(s++);
+	    }
+          n[0] = '\0';
+          nlen = strlen (tp);
+#else
+          nlen = p - s;
+          memcpy (tp, s, nlen);
+          tp[nlen] = '\0';
+#endif
+        }
+
+      /* At this point, TP points to the element and NLEN is its length.  */
+
+#ifndef NO_ARCHIVES
+      /* If this is the start of an archive group that isn't complete, set up
+         to add the archive prefix for future files.  A file list like:
+         "libf.a(x.o y.o z.o)" needs to be expanded as:
+         "libf.a(x.o) libf.a(y.o) libf.a(z.o)"
+
+         TP == TMP means we're not already in an archive group.  Ignore
+         something starting with `(', as that cannot actually be an
+         archive-member reference (and treating it as such results in an empty
+         file name, which causes much lossage).  Also if it ends in ")" then
+         it's a complete reference so we don't need to treat it specially.
+
+         Finally, note that archive groups must end with ')' as the last
+         character, so ensure there's some word ending like that before
+         considering this an archive group.  */
+      if (! (flags & PARSEFS_NOAR)
+          && tp == tmpbuf && tp[0] != '(' && tp[nlen-1] != ')')
+        {
+          char *n = strchr (tp, '(');
+          if (n)
+            {
+              /* This looks like the first element in an open archive group.
+                 A valid group MUST have ')' as the last character.  */
+              const char *e = p + nlen;
+              do
+                {
+                  e = next_token (e);
+                  /* Find the end of this word.  We don't want to unquote and
+                     we don't care about quoting since we're looking for the
+                     last char in the word. */
+                  while (*e != '\0' && *e != stopchar && *e != VMS_COMMA
+                         && ! isblank ((unsigned char) *e))
+                    ++e;
+                  if (e[-1] == ')')
+                    {
+                      /* Found the end, so this is the first element in an
+                         open archive group.  It looks like "lib(mem".
+                         Reset TP past the open paren.  */
+                      nlen -= (n + 1) - tp;
+                      tp = n + 1;
+
+                      /* If we have just "lib(", part of something like
+                         "lib( a b)", go to the next item.  */
+                      if (! nlen)
+                        continue;
+
+                      /* We can stop looking now.  */
+                      break;
+                    }
+                }
+              while (*e != '\0');
+            }
+        }
+
+      /* If we are inside an archive group, make sure it has an end.  */
+      if (tp > tmpbuf)
+        {
+          if (tp[nlen-1] == ')')
+            {
+              /* This is the natural end; reset TP.  */
+              tp = tmpbuf;
+
+              /* This is just ")", something like "lib(a b )": skip it.  */
+              if (nlen == 1)
+                continue;
+            }
+          else
+            {
+              /* Not the end, so add a "fake" end.  */
+              tp[nlen++] = ')';
+              tp[nlen] = '\0';
+            }
+        }
+#endif
+
+      /* If we're not globbing we're done: add it to the end of the chain.
+         Go to the next item in the string.  */
+      if (flags & PARSEFS_NOGLOB)
+        {
+          NEWELT (concat (2, prefix, tp));
+          continue;
+        }
+
+      /* If we get here we know we're doing glob expansion.
+         TP is a string in tmpbuf.  NLEN is no longer used.
+         We may need to do more work: after this NAME will be set.  */
+      name = tp;
+
+      /* Expand tilde if applicable.  */
+      if (tp[0] == '~')
+	{
+	  tildep = tilde_expand (tp);
+	  if (tildep != 0)
+            name = tildep;
 	}
 
 #ifndef NO_ARCHIVES
-      if (ar_name (gname))
+      /* If NAME is an archive member reference replace it with the archive
+         file name, and save the member name in MEMNAME.  We will glob on the
+         archive name and then reattach MEMNAME later.  */
+      if (! (flags & PARSEFS_NOAR) && ar_name (name))
 	{
-	  /* OLD->name is an archive member reference.  Replace it with the
-	     archive file name, and save the member name in MEMNAME.  We will
-	     glob on the archive name and then reattach MEMNAME later.  */
-	  ar_parse_name (gname, &arname, &memname);
-	  gname = arname;
+	  ar_parse_name (name, &arname, &memname);
+	  name = arname;
 	}
 #endif /* !NO_ARCHIVES */
 
-#if defined(KMK) || defined(__EMX__) /* speed optimization */
-      if (!strpbrk(gname, "*?["))
-        {
-          gl.gl_pathc = 1;
-          gl.gl_pathv = (char **)&gname;
-          rc = 0;
-        }
-      else
-        rc = glob (gname, GLOB_NOCHECK|GLOB_ALTDIRFUNC, NULL, &gl);
-      switch (rc)
-#else
-      switch (glob (gname, GLOB_NOCHECK|GLOB_ALTDIRFUNC, NULL, &gl))
-#endif
+      switch (glob (name, GLOB_NOSORT|GLOB_ALTDIRFUNC, NULL, &gl))
 	{
-	case 0:			/* Success.  */
-	  {
-	    int i = gl.gl_pathc;
-	    while (i-- > 0)
-	      {
-#ifndef NO_ARCHIVES
-		if (memname != 0)
-		  {
-		    /* Try to glob on MEMNAME within the archive.  */
-		    struct nameseq *found
-		      = ar_glob (gl.gl_pathv[i], memname, size);
-		    if (! found)
-		      {
-			/* No matches.  Use MEMNAME as-is.  */
-			unsigned int alen = strlen (gl.gl_pathv[i]);
-			unsigned int mlen = strlen (memname);
-                        char *name;
-			struct nameseq *elt = xmalloc (size);
-                        memset (elt, '\0', size);
-
-                        name = alloca (alen + 1 + mlen + 2);
-			memcpy (name, gl.gl_pathv[i], alen);
-			name[alen] = '(';
-			memcpy (name+alen+1, memname, mlen);
-			name[alen + 1 + mlen] = ')';
-			name[alen + 1 + mlen + 1] = '\0';
-                        elt->name = strcache_add (name);
-			elt->next = new;
-			new = elt;
-		      }
-		    else
-		      {
-			/* Find the end of the FOUND chain.  */
-			struct nameseq *f = found;
-			while (f->next != 0)
-			  f = f->next;
-
-			/* Attach the chain being built to the end of the FOUND
-			   chain, and make FOUND the new NEW chain.  */
-			f->next = new;
-			new = found;
-		      }
-		  }
-		else
-#endif /* !NO_ARCHIVES */
-		  {
-#ifndef CONFIG_WITH_ALLOC_CACHES
-		    struct nameseq *elt = xmalloc (size);
-                    memset (elt, '\0', size);
-#else
-		    struct nameseq *elt = alloccache_calloc (cache);
-#endif
-		    elt->name = strcache_add (gl.gl_pathv[i]);
-		    elt->next = new;
-		    new = elt;
-		  }
-	      }
-#if defined(KMK) || defined(__EMX__) /* speed optimization */
-            if (gl.gl_pathv != (char **)&gname)
-#endif
-	    globfree (&gl);
-#ifndef CONFIG_WITH_ALLOC_CACHES
-	    free (old);
-#else
-            alloccache_free (cache, old);
-#endif
-	    break;
-	  }
-
 	case GLOB_NOSPACE:
 	  fatal (NILF, _("virtual memory exhausted"));
-	  break;
+
+	case 0:
+          /* Success.  */
+          i = gl.gl_pathc;
+          nlist = (const char **)gl.gl_pathv;
+          break;
+
+        case GLOB_NOMATCH:
+          /* If we want only existing items, skip this one.  */
+          if (flags & PARSEFS_EXISTS)
+            {
+              i = 0;
+              break;
+            }
+          /* FALLTHROUGH */
 
 	default:
-	  old->next = new;
-	  new = old;
-	  break;
+          /* By default keep this name.  */
+          i = 1;
+          nlist = &name;
+          break;
 	}
+
+      /* For each matched element, add it to the list.  */
+      while (i-- > 0)
+#ifndef NO_ARCHIVES
+        if (memname != 0)
+          {
+            /* Try to glob on MEMNAME within the archive.  */
+            struct nameseq *found = ar_glob (nlist[i], memname, size);
+            if (! found)
+              /* No matches.  Use MEMNAME as-is.  */
+              NEWELT (concat (5, prefix, nlist[i], "(", memname, ")"));
+            else
+              {
+                /* We got a chain of items.  Attach them.  */
+                (*newp)->next = found;
+
+                /* Find and set the new end.  Massage names if necessary.  */
+                while (1)
+                  {
+                    if (! cachep)
+                      found->name = xstrdup (concat (2, prefix, name));
+                    else if (prefix)
+                      found->name = strcache_add (concat (2, prefix, name));
+
+                    if (found->next == 0)
+                      break;
+
+                    found = found->next;
+                  }
+                newp = &found->next;
+              }
+          }
+        else
+#endif /* !NO_ARCHIVES */
+          NEWELT (concat (2, prefix, nlist[i]));
+
+        globfree (&gl);
 
 #ifndef NO_ARCHIVES
@@ -4116,6 +3928,10 @@
         free (arname);
 #endif
+
+      if (tildep)
+        free (tildep);
     }
 
+  *stringp = p;
   return new;
 }
Index: /trunk/src/kmk/readme.vms
===================================================================
--- /trunk/src/kmk/readme.vms	(revision 2590)
+++ /trunk/src/kmk/readme.vms	(revision 2591)
@@ -1,15 +1,12 @@
 This is the VMS version of GNU Make, updated by Hartmut Becker
 
-Changes are based on GNU make 3.80. Latest changes are for OpenVMS/I64
-and new VMS CRTLs.
-
-This version was tested on OpenVMS/I64 V8.2 (field test) with hp C
-X7.1-024 OpenVMS/Alpha V7.3-2 with Compaq C V6.5-001 and OpenVMS/VAX 7.1
-with Compaq C V6.2-003 There are still some warning and informational
-message issued by the compilers.
+Changes are based on GNU make 3.82.
+
+This version was built and tested on OpenVMS V7.3 (VAX), V7.3-2 (Alpha) and
+V8.3-1H1 (I64).
 
 Build instructions
 Make a 1st version
-       $ @makefile.com
+       $ @makefile.com  ! ignore any compiler and/or linker warning
        $ rena make.exe 1st-make.exe
 Use the 1st version to generate a 2nd version
@@ -21,5 +18,88 @@
        $ mc sys$disk:[]2nd-make
 
-Changes:
+Changes (3.81.90)
+
+Michael Gehre (at VISTEC-SEMI dot COM) supplied a fix for a problem with
+timestamps of object modules in OLBs. The timestamps were not correctly
+adjusted to GMT based time, if the local VMS time was using a daylight saving
+algorithm and if daylight saving was switched off.
+
+John Eisenbraun (at HP dot COM) supplied fixes and and an enhancement to append
+output redirection in action lines.
+
+Rework of ctrl+c and ctrl+y handling.
+
+Fix a problem with cached strings, which showed on case-insensitive file
+systems.
+
+Build fixes for const-ified code in VMS specific sources.
+
+Build notes:
+- Try to avoid HP C V7.2-001, which has an incompatible change
+how __STDC__ is defined. This results at least in compile time warnings.
+
+- On V8.3-1H1, if you press Ctrl+C you may see a traceback, starting with
+%SYSTEM-F-CONTROLC, operation completed under CTRL/C
+%TRACE-F-TRACEBACK, symbolic stack dump follows
+image     module    routine               line      rel PC           abs PC
+
+DECC$SHR  C$SIGNAL  gsignal              27991 0000000000001180
+FFFFFFFF84AB2DA0
+DECC$SHR  C$SIGNAL  raise                28048 0000000000001280
+FFFFFFFF84AB2EA0
+DECC$SHR  C$SIGPENDING  decc$$deliver_signals
+                                         12475 0000000000000890
+FFFFFFFF84C13690
+...
+This looks like an incompatibility to the Alpha and VAX behavior, so it looks
+like a problem in I64 VMS version(s).
+
+- There is no clean build on VAX. In the environment I tested, I had to use GNU
+make's alloca which produced a couple of compile time warnings. It seems too
+much effort to work on a clean build on VAX.
+
+A note on appending the redirected output. With this change, a simple mechanism
+is implemented to make ">>" work in action lines. In VMS there is no simple
+feature like ">>" to have DCL command or program output redirected and appended
+to a file. GNU make for VMS already implements the redirection of output. If
+such a redirection is detected, an ">" on the action line, GNU make creates a
+DCL command procedure to execute the action and to redirect its output. Based
+on that, now ">>" is also recognized and a similar but different command
+procedure is created to implement the append. The main idea here is to create a
+temporary file which collects the output and which is appended to the wanted
+output file. Then the temporary file is deleted. This is all done in the
+command procedure to keep changes in make small and simple. This obviously has
+some limitations but it seems good enough compared with the current ">"
+implementation. (And in my opinion, redirection is not really what GNU make has
+to do.) With this approach, it may happen that the temporary file is not yet
+appended and is left in SYS$SCRATCH. The temporary file names look like
+"CMDxxxxx.". Any time the created command procedure can not complete, this
+happens. Pressing Ctrl+Y to abort make is one case. In case of Ctrl+Y the
+associated command procedure is left in SYS$SCRATCH as well. Its name is
+CMDxxxxx.COM.
+
+Change in the Ctrl+Y handling
+
+Ctrl+Y was: The CtrlY handler called $forcex for the current child.
+
+Ctrl+Y changed: The CtrlY handler uses $delprc to delete all children. This way
+also actions with DCL commands will be stopped. As before Ctrl+Y then sends
+SIGQUIT to itself, which is handled in common code.
+
+Change in deleteing temporary command files
+
+Temporary command files were deleted in the main line, after returning from the
+vms child termination handler. If Ctrl+C was pressed, the handler is called but
+did not return to main line.
+
+Now, temporary command files are deleted in the vms child termination
+handler. That deletes the them even if a Ctrl+C was pressed.
+
+The behavior of pressing Ctrl+C is not changed. It still has only an effect,
+after the current action is terminated. If that doesn't happen or takes too
+long, Ctrl+Y should be used instead.
+
+
+Changes (3.80)
 
 . In default.c define variable ARCH as IA64 for VMS on Itanium systems.
@@ -300,5 +380,5 @@
 -------------------------------------------------------------------------------
 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-2006, 2007 Free Software Foundation, Inc.
+2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
Index: /trunk/src/kmk/remake.c
===================================================================
--- /trunk/src/kmk/remake.c	(revision 2590)
+++ /trunk/src/kmk/remake.c	(revision 2591)
@@ -1,6 +1,6 @@
 /* Basic dependency engine 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 Free Software
-Foundation, Inc.
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
@@ -90,5 +90,4 @@
 {
   int t = touch_flag, q = question_flag, n = just_print_flag;
-  unsigned int j = job_slots;
   int status = -1;
 
@@ -142,4 +141,7 @@
 	      unsigned int ocommands_started;
 	      int x;
+
+              file->dontcare = g->dontcare;
+
 	      check_renamed (file);
 	      if (rebuilding_makefiles)
@@ -215,4 +217,6 @@
 	      any_not_updated |= !file->updated;
 
+              file->dontcare = 0;
+
 	      if (stop)
 		break;
@@ -275,5 +279,4 @@
       question_flag = q;
       just_print_flag = n;
-      job_slots = j;
     }
 
@@ -308,6 +311,12 @@
   if (f->considered == considered)
     {
-      DBF (DB_VERBOSE, _("Pruning file `%s'.\n"));
-      return f->command_state == cs_finished ? f->update_status : 0;
+      /* Check for the case where a target has been tried and failed but
+         the diagnostics hasn't been issued. If we need the diagnostics
+         then we will have to continue. */
+      if (!(f->updated && f->update_status > 0 && !f->dontcare && f->no_diag))
+        {
+          DBF (DB_VERBOSE, _("Pruning file `%s'.\n"));
+          return f->command_state == cs_finished ? f->update_status : 0;
+        }
     }
 
@@ -326,5 +335,5 @@
       /* If we got an error, don't bother with double_colon etc.  */
       if (status != 0 && !keep_going_flag)
-	return status;
+        return status;
 
       if (f->command_state == cs_running
@@ -358,5 +367,5 @@
 
 static void
-complain (const struct file *file)
+complain (struct file *file)
 {
   const char *msg_noparent
@@ -365,56 +374,80 @@
     = _("%sNo rule to make target `%s', needed by `%s'%s");
 
+  /* If this file has no_diag set then it means we tried to update it
+     before in the dontcare mode and failed. The target that actually
+     failed is not necessarily this file but could be one of its direct
+     or indirect dependencies. So traverse this file's dependencies and
+     find the one that actually caused the failure. */
+
+  struct dep *d;
+
+  for (d = file->deps; d != 0; d = d->next)
+    {
+      if (d->file->updated && d->file->update_status > 0 && file->no_diag)
+        {
+          complain (d->file);
+          break;
+        }
+    }
+
+  if (d == 0)
+    {
+      /* Didn't find any dependencies to complain about. */
+
 #ifdef KMK
-  /* jokes */
-  if (!keep_going_flag && file->parent == 0)
-    {
-      const char *msg_joke = 0;
-      extern struct dep *goals;
-
-      /* classics */
-      if (!strcmp (file->name, "fire")
-       || !strcmp (file->name, "Fire"))
-        msg_joke = "No matches.\n";
-      else if (!strcmp (file->name, "love")
-            || !strcmp (file->name, "Love")
-            || !strcmp (file->name, "peace")
-            || !strcmp (file->name, "Peace"))
-        msg_joke = "Not war.\n";
-      else if (!strcmp (file->name, "war"))
-        msg_joke = "Don't know how to make war.\n";
-
-      /* http://xkcd.com/149/ - GNU Make bug #23273. */
-      else if ((   !strcmp (file->name, "me")
-                && goals != 0
-                && !strcmp (dep_name(goals), "me")
-                && goals->next != 0
-                && !strcmp (dep_name(goals->next), "a")
-                && goals->next->next != 0)
-            || !strncmp (file->name, "me a ", 5))
-        msg_joke =
+      /* jokes */
+      if (!keep_going_flag && file->parent == 0)
+        {
+          const char *msg_joke = 0;
+          extern struct dep *goals;
+
+          /* classics */
+          if (!strcmp (file->name, "fire")
+           || !strcmp (file->name, "Fire"))
+            msg_joke = "No matches.\n";
+          else if (!strcmp (file->name, "love")
+                || !strcmp (file->name, "Love")
+                || !strcmp (file->name, "peace")
+                || !strcmp (file->name, "Peace"))
+            msg_joke = "Not war.\n";
+          else if (!strcmp (file->name, "war"))
+            msg_joke = "Don't know how to make war.\n";
+
+          /* http://xkcd.com/149/ - GNU Make bug #23273. */
+          else if ((   !strcmp (file->name, "me")
+                    && goals != 0
+                    && !strcmp (dep_name(goals), "me")
+                    && goals->next != 0
+                    && !strcmp (dep_name(goals->next), "a")
+                    && goals->next->next != 0)
+                || !strncmp (file->name, "me a ", 5))
+            msg_joke =
 # ifdef HAVE_UNISTD_H
                    getuid () == 0 ? "Okay.\n" :
 # endif
-                   "What? Make it yourself!\n";
-      if (msg_joke)
+                       "What? Make it yourself!\n";
+          if (msg_joke)
+            {
+              fputs (msg_joke, stderr);
+              die (2);
+            }
+        }
+#endif /* KMK */
+
+      if (!keep_going_flag)
         {
-          fputs (msg_joke, stderr);
-          die (2);
+          if (file->parent == 0)
+            fatal (NILF, msg_noparent, "", file->name, "");
+
+          fatal (NILF, msg_parent, "", file->name, file->parent->name, "");
         }
-    }
-#endif /* KMK */
-
-  if (!keep_going_flag)
-    {
+
       if (file->parent == 0)
-        fatal (NILF, msg_noparent, "", file->name, "");
-
-      fatal (NILF, msg_parent, "", file->name, file->parent->name, "");
-    }
-
-  if (file->parent == 0)
-    error (NILF, msg_noparent, "*** ", file->name, ".");
-  else
-    error (NILF, msg_parent, "*** ", file->name, file->parent->name, ".");
+        error (NILF, msg_noparent, "*** ", file->name, ".");
+      else
+        error (NILF, msg_parent, "*** ", file->name, file->parent->name, ".");
+
+      file->no_diag = 0;
+    }
 }
 
@@ -424,10 +457,13 @@
 update_file_1 (struct file *file, unsigned int depth)
 {
-  register FILE_TIMESTAMP this_mtime;
+  FILE_TIMESTAMP this_mtime;
   int noexist, must_make, deps_changed;
   int dep_status = 0;
-  register struct dep *d, *lastd;
+  struct file *ofile;
+  struct dep *d, *ad;
+  struct dep amake;
   int running = 0;
 #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+  struct file *org_file = file;
   struct file *f2, *f3;
 
@@ -438,5 +474,5 @@
       DBS (DB_VERBOSE, (_("Considering target file `%s' -> multi head `%s'.\n"),
                           file->name, file->multi_head->name));
-      file = file->multi_head;
+      org_file = file = file->multi_head;
     }
   else
@@ -451,13 +487,10 @@
                _("Recently tried and failed to update file `%s'.\n"));
 
-          /* If the file we tried to make is marked dontcare then no message
+          /* If the file we tried to make is marked no_diag then no message
              was printed about it when it failed during the makefile rebuild.
              If we're trying to build it again in the normal rebuild, print a
              message now.  */
-          if (file->dontcare && !rebuilding_makefiles)
-            {
-              file->dontcare = 0;
+          if (file->no_diag && !file->dontcare)
               complain (file);
-            }
 
 	  return file->update_status;
@@ -483,8 +516,16 @@
     }
 
+  /* Determine whether the diagnostics will be issued should this update
+     fail. */
+  file->no_diag = file->dontcare;
+
   ++depth;
 
   /* Notice recursive update of the same file.  */
   start_updating (file);
+
+  /* We might change file if we find a different one via vpath;
+     remember this one to turn off updating.  */
+  ofile = file;
 
   /* Looking at the file's modtime beforehand allows the possibility
@@ -554,20 +595,30 @@
     }
 
-  /* Update all non-intermediate files we depend on, if necessary,
-     and see whether any of them is more recent than this file.
-     For explicit multitarget rules we must iterate all the output
+  /* Update all non-intermediate files we depend on, if necessary, and see
+     whether any of them is more recent than this file.  We need to walk our
+     deps, AND the deps of any also_make targets to ensure everything happens
+     in the correct order.
+
+     bird: For explicit multitarget rules we must iterate all the output
      files to get the correct picture.  The special .MUST_MAKE
-     target variable call is also done from this context.  */
+     target variable call is also done from this context. */
 
 #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
-  for (f2 = file; f2; f2 = f2->multi_next)
-    {
-      lastd = 0;
-      d = f2->deps;
-#else
-      lastd = 0;
-      d = file->deps;
-#endif
-      while (d != 0)
+ assert (file == org_file);
+ for (f2 = file; f2; file = f2 = f2->multi_next)
+ {
+#endif
+  amake.file = file;
+  amake.next = file->also_make;
+  ad = &amake;
+  while (ad)
+    {
+      struct dep *lastd = 0;
+
+      /* Find the deps we're scanning */
+      d = ad->file->deps;
+      ad = ad->next;
+
+      while (d)
         {
           FILE_TIMESTAMP mtime;
@@ -584,5 +635,5 @@
 #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
               /* silently ignore the order-only dep hack. */
-              if (f2->multi_maybe && d->file == file)
+              if (file->multi_maybe && d->file == org_file)
                 {
                   lastd = d;
@@ -593,18 +644,10 @@
 
               error (NILF, _("Circular %s <- %s dependency dropped."),
-#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
-                     f2->name, d->file->name);
-#else
                      file->name, d->file->name);
-#endif
               /* We cannot free D here because our the caller will still have
                  a reference to it when we were called recursively via
                  check_dep below.  */
               if (lastd == 0)
-#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
-                f2->deps = d->next;
-#else
                 file->deps = d->next;
-#endif
               else
                 lastd->next = d->next;
@@ -613,9 +656,5 @@
             }
 
-#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
-          d->file->parent = f2;
-#else
           d->file->parent = file;
-#endif
           maybe_make = must_make;
 
@@ -626,5 +665,4 @@
               d->file->dontcare = file->dontcare;
             }
-
 
           dep_status |= check_dep (d->file, depth, this_mtime, &maybe_make);
@@ -664,9 +702,11 @@
           d = d->next;
         }
+    }
 
 #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
-      if (dep_status != 0 && !keep_going_flag)
-        break;
-    }
+    if (dep_status != 0 && !keep_going_flag)
+      break;
+  }
+  file = org_file;
 #endif
 
@@ -677,5 +717,5 @@
 # ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
   if (!must_make)
-    for (f2 = file; f2 && !must_make; f2 = f2->multi_next)
+    for (f2 = org_file; f2 && !must_make; f2 = f2->multi_next)
       must_make = call_must_make_target_var (f2, depth);
 # else
@@ -691,9 +731,7 @@
     {
 #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
-      for (f2 = file; f2; f2 = f2->multi_next)
-        for (d = f2->deps; d != 0; d = d->next)
-#else
+      for (file = f2 = org_file; f2; file = f2 = f2->multi_next)
+#endif
         for (d = file->deps; d != 0; d = d->next)
-#endif
           if (d->file->intermediate)
             {
@@ -702,9 +740,5 @@
               FILE_TIMESTAMP mtime = file_mtime (d->file);
               check_renamed (d->file);
-#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
-              d->file->parent = f2;
-#else
               d->file->parent = file;
-#endif
 
               /* Inherit dontcare flag from our parent. */
@@ -741,14 +775,14 @@
 
               if (!running)
-#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
-                d->changed = ((f2->phony && f2->cmds != 0)
-#else
                 d->changed = ((file->phony && file->cmds != 0)
-#endif
           	            || file_mtime (d->file) != mtime);
             }
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+      file = org_file;
+#endif
     }
 
   finish_updating (file);
+  finish_updating (ofile);
 
   DBF (DB_VERBOSE, _("Finished prerequisites of target file `%s'.\n"));
@@ -797,5 +831,5 @@
   deps_changed = 0;
 #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
-  for (f2 = file; f2; f2 = f2->multi_next)
+  for (file = f2 = org_file; f2; file = f2 = f2->multi_next)
 #endif
     for (d = file->deps; d != 0; d = d->next)
@@ -803,5 +837,5 @@
         FILE_TIMESTAMP d_mtime = file_mtime (d->file);
 #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
-        if (d->file == file && f2->multi_maybe)
+        if (d->file == file && file->multi_maybe)
           continue;
 #endif
@@ -858,4 +892,7 @@
           }
       }
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+  file = org_file;
+#endif
 
   /* Here depth returns to the value it had when we were called.  */
@@ -1170,5 +1207,5 @@
          would have been updated. */
 
-      if (question_flag || just_print_flag || touch_flag)
+      if ((question_flag || just_print_flag || touch_flag) && file->cmds)
         {
           for (i = file->cmds->ncommand_lines; i > 0; --i)
@@ -1278,4 +1315,5 @@
            FILE_TIMESTAMP this_mtime, int *must_make_ptr)
 {
+  struct file *ofile;
   struct dep *d;
   int dep_status = 0;
@@ -1283,4 +1321,8 @@
   ++depth;
   start_updating (file);
+
+  /* We might change file if we find a different one via vpath;
+     remember this one to turn off updating.  */
+  ofile = file;
 
   if (file->phony || !file->intermediate)
@@ -1333,21 +1375,14 @@
              necessary, and see whether any of them is more recent than the
              file on whose behalf we are checking.  */
-	  struct dep *lastd;
+	  struct dep *ld;
           int deps_running = 0;
 
-          /* Reset this target's state so that we check it fresh.  It could be
-             that it's already been checked as part of an order-only
-             prerequisite and so wasn't rebuilt then, but should be now.
-
-             bird: What if we're already running the recipe?  We don't wish
-                   it to be started once again do we?  This happens with the
-                   SECONDARY Test #9 here now... If the idea is to re-evaluate
-                   the target regardless of whether it's running or no, then
-                   perhaps saving and restoring is a better idea?
-                   See bug #15919.  */
-          if (file->command_state != cs_running) /* bird */
+          /* If this target is not running, set it's state so that we check it
+             fresh.  It could be it was checked as part of an order-only
+             prerequisite and so wasn't rebuilt then, but should be now.  */
+          if (file->command_state != cs_running)
             set_command_state (file, cs_not_started);
 
-	  lastd = 0;
+	  ld = 0;
 	  d = file->deps;
 	  while (d != 0)
@@ -1359,5 +1394,5 @@
 		  error (NILF, _("Circular %s <- %s dependency dropped."),
 			 file->name, d->file->name);
-		  if (lastd == 0)
+		  if (ld == 0)
 		    {
 		      file->deps = d->next;
@@ -1367,7 +1402,7 @@
 		  else
 		    {
-		      lastd->next = d->next;
+		      ld->next = d->next;
                       free_dep (d);
-		      d = lastd->next;
+		      d = ld->next;
 		    }
 		  continue;
@@ -1388,5 +1423,5 @@
 		deps_running = 1;
 
-	      lastd = d;
+	      ld = d;
 	      d = d->next;
 	    }
@@ -1401,4 +1436,6 @@
 
   finish_updating (file);
+  finish_updating (ofile);
+
   return dep_status;
 }
@@ -1588,5 +1625,5 @@
 	{
 	  /* If name_mtime failed, search VPATH.  */
-	  const char *name = vpath_search (file->name, &mtime);
+	  const char *name = vpath_search (file->name, &mtime, NULL, NULL);
 	  if (name
 	      /* Last resort, is it a library (-lxxx)?  */
@@ -1839,7 +1876,6 @@
     };
 
-  static char *libpatterns = NULL;
-
-  const char *libname = lib+2;	/* Name without the '-l'.  */
+  const char *file = 0;
+  char *libpatterns;
   FILE_TIMESTAMP mtime;
 
@@ -1848,19 +1884,21 @@
   const char *p2;
   unsigned int len;
+  unsigned int liblen;
+
+  /* Information about the earliest (in the vpath sequence) match.  */
+  unsigned int best_vpath = 0, best_path = 0; /* bird: gcc maybe used uninitialized (both) */
+  unsigned int std_dirs = 0;
 
   char **dp;
 
-  /* If we don't have libpatterns, get it.  */
-  if (!libpatterns)
-    {
-      int save = warn_undefined_variables_flag;
-      warn_undefined_variables_flag = 0;
-
-      libpatterns = xstrdup (variable_expand ("$(strip $(.LIBPATTERNS))"));
-
-      warn_undefined_variables_flag = save;
-    }
-
-  /* Loop through all the patterns in .LIBPATTERNS, and search on each one.  */
+  libpatterns = xstrdup (variable_expand ("$(.LIBPATTERNS)"));
+
+  /* Skip the '-l'.  */
+  lib += 2;
+  liblen = strlen (lib);
+
+  /* Loop through all the patterns in .LIBPATTERNS, and search on each one.
+     To implement the linker-compatible behavior we have to search through
+     all entries in .LIBPATTERNS and choose the "earliest" one.  */
   p2 = libpatterns;
   while ((p = find_next_token (&p2, &len)) != 0)
@@ -1872,5 +1910,5 @@
       const size_t libbuf_offset = libbuf - variable_buffer; /* bird */
 
-      /* Expand the pattern using LIBNAME as a replacement.  */
+      /* Expand the pattern using LIB as a replacement.  */
       {
 	char c = p[len];
@@ -1881,14 +1919,11 @@
 	if (!p3)
 	  {
-	    /* Give a warning if there is no pattern, then remove the
-	       pattern so it's ignored next time.  */
+	    /* Give a warning if there is no pattern.  */
 	    error (NILF, _(".LIBPATTERNS element `%s' is not a pattern"), p);
-	    for (; len; --len, ++p)
-	      *p = ' ';
-	    *p = c;
+            p[len] = c;
 	    continue;
 	  }
 	p4 = variable_buffer_output (libbuf, p, p3-p);
-	p4 = variable_buffer_output (p4, libname, strlen (libname));
+	p4 = variable_buffer_output (p4, lib, liblen);
 	p4 = variable_buffer_output (p4, p3+1, len - (p3-p));
 	p[len] = c;
@@ -1902,5 +1937,7 @@
 	  if (mtime_ptr != 0)
 	    *mtime_ptr = mtime;
-	  return strcache_add (libbuf);
+	  file = strcache_add (libbuf);
+          /* This by definition will have the best index, so stop now.  */
+          break;
 	}
 
@@ -1908,7 +1945,22 @@
 
       {
-        const char *file = vpath_search (libbuf, mtime_ptr);
-        if (file)
-          return file;
+        unsigned int vpath_index, path_index;
+        const char* f = vpath_search (libbuf, mtime_ptr ? &mtime : NULL,
+                                      &vpath_index, &path_index);
+        if (f)
+          {
+            /* If we have a better match, record it.  */
+            if (file == 0 ||
+                vpath_index < best_vpath ||
+                (vpath_index == best_vpath && path_index < best_path))
+              {
+                file = f;
+                best_vpath = vpath_index;
+                best_path = path_index;
+
+                if (mtime_ptr != 0)
+                  *mtime_ptr = mtime;
+              }
+          }
       }
 
@@ -1916,33 +1968,49 @@
 
       if (!buflen)
-	{
-	  for (dp = dirs; *dp != 0; ++dp)
-	    {
-	      int l = strlen (*dp);
-	      if (l > libdir_maxlen)
-		libdir_maxlen = l;
-	    }
-	  buflen = strlen (libbuf);
-	  buf = xmalloc(libdir_maxlen + buflen + 2);
-	}
+        {
+          for (dp = dirs; *dp != 0; ++dp)
+            {
+              int l = strlen (*dp);
+              if (l > libdir_maxlen)
+                libdir_maxlen = l;
+              std_dirs++;
+            }
+          buflen = strlen (libbuf);
+          buf = xmalloc(libdir_maxlen + buflen + 2);
+        }
       else if (buflen < strlen (libbuf))
-	{
-	  buflen = strlen (libbuf);
-	  buf = xrealloc (buf, libdir_maxlen + buflen + 2);
-	}
-
-      for (dp = dirs; *dp != 0; ++dp)
-	{
-	  sprintf (buf, "%s/%s", *dp, libbuf);
-	  mtime = name_mtime (buf);
-	  if (mtime != NONEXISTENT_MTIME)
-	    {
-	      if (mtime_ptr != 0)
-		*mtime_ptr = mtime;
-	      return strcache_add (buf);
-	    }
-	}
-    }
-
-  return 0;
+        {
+          buflen = strlen (libbuf);
+          buf = xrealloc (buf, libdir_maxlen + buflen + 2);
+        }
+
+      {
+        /* Use the last std_dirs index for standard directories. This
+           was it will always be greater than the VPATH index.  */
+        unsigned int vpath_index = ~((unsigned int)0) - std_dirs;
+
+        for (dp = dirs; *dp != 0; ++dp)
+	  {
+            sprintf (buf, "%s/%s", *dp, libbuf);
+            mtime = name_mtime (buf);
+            if (mtime != NONEXISTENT_MTIME)
+	      {
+                if (file == 0 || vpath_index < best_vpath)
+                  {
+                    file = strcache_add (buf);
+                    best_vpath = vpath_index;
+
+                    if (mtime_ptr != 0)
+                      *mtime_ptr = mtime;
+                  }
+              }
+
+            vpath_index++;
+          }
+      }
+
+    }
+
+  free (libpatterns);
+  return file;
 }
Index: /trunk/src/kmk/remote-cstms.c
===================================================================
--- /trunk/src/kmk/remote-cstms.c	(revision 2590)
+++ /trunk/src/kmk/remote-cstms.c	(revision 2591)
@@ -5,6 +5,6 @@
 
 Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
-1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software
-Foundation, Inc.
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
Index: /trunk/src/kmk/remote-stub.c
===================================================================
--- /trunk/src/kmk/remote-stub.c	(revision 2590)
+++ /trunk/src/kmk/remote-stub.c	(revision 2591)
@@ -1,6 +1,6 @@
 /* Template for the remote job exportation interface to GNU Make.
 Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
-1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software
-Foundation, Inc.
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
Index: /trunk/src/kmk/rule.c
===================================================================
--- /trunk/src/kmk/rule.c	(revision 2590)
+++ /trunk/src/kmk/rule.c	(revision 2591)
@@ -1,6 +1,6 @@
 /* Pattern and suffix rule internals 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 Free Software
-Foundation, Inc.
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
@@ -97,17 +97,18 @@
       for (dep = rule->deps; dep != 0; dep = dep->next)
 	{
-	  unsigned int len = strlen (dep->name);
+          const char *dname = dep_name (dep);
+          unsigned int len = strlen (dname);
 
 #ifdef VMS
-	  const char *p = strrchr (dep->name, ']');
+          const char *p = strrchr (dname, ']');
           const char *p2;
           if (p == 0)
-            p = strrchr (dep->name, ':');
-          p2 = p != 0 ? strchr (dep->name, '%') : 0;
+            p = strrchr (dname, ':');
+          p2 = p != 0 ? strchr (dname, '%') : 0;
 #else
-	  const char *p = strrchr (dep->name, '/');
-	  const char *p2 = p != 0 ? strchr (dep->name, '%') : 0;
+          const char *p = strrchr (dname, '/');
+          const char *p2 = p != 0 ? strchr (dname, '%') : 0;
 #endif
-	  ndeps++;
+          ndeps++;
 
 	  if (len > max_pattern_dep_length)
@@ -118,13 +119,13 @@
 	      /* There is a slash before the % in the dep name.
 		 Extract the directory name.  */
-	      if (p == dep->name)
+	      if (p == dname)
 		++p;
-	      if (p - dep->name > namelen)
+	      if (p - dname > namelen)
 		{
-		  namelen = p - dep->name;
+		  namelen = p - dname;
 		  name = xrealloc (name, namelen + 1);
 		}
-	      memcpy (name, dep->name, p - dep->name);
-	      name[p - dep->name] = '\0';
+	      memcpy (name, dname, p - dname);
+	      name[p - dname] = '\0';
 
 	      /* In the deps of an implicit rule the `changed' flag
@@ -380,13 +381,5 @@
 
   ptr = p->dep;
-#ifndef CONFIG_WITH_ALLOC_CACHES
-  r->deps = (struct dep *) multi_glob (parse_file_seq (&ptr, '\0',
-                                                       sizeof (struct dep), 1),
-				       sizeof (struct dep));
-#else
-  r->deps = (struct dep *) multi_glob (parse_file_seq (&ptr, '\0',
-						       &dep_cache, 1),
-				       &dep_cache);
-#endif
+  r->deps = PARSE_FILE_SEQ (&ptr, struct dep, '\0', NULL, 0);
 
   if (new_pattern_rule (r, 0))
@@ -419,16 +412,10 @@
 {
   struct rule *next = rule->next;
-  struct dep *dep;
-
-  dep = rule->deps;
-  while (dep)
-    {
-      struct dep *t = dep->next;
-      free_dep (dep);
-      dep = t;
-    }
-
-  free (rule->targets);
-  free (rule->suffixes);
+
+  free_dep_chain (rule->deps);
+
+  /* MSVC erroneously warns without a cast here.  */
+  free ((void *)rule->targets);
+  free ((void *)rule->suffixes);
   free (rule->lens);
 
@@ -505,5 +492,4 @@
 {
   unsigned int i;
-  struct dep *d;
 
   for (i = 0; i < r->num; ++i)
@@ -515,7 +501,5 @@
     putchar (':');
 
-  for (d = r->deps; d != 0; d = d->next)
-    printf (" %s", dep_name (d));
-  putchar ('\n');
+  print_prereqs (r->deps);
 
   if (r->cmds != 0)
@@ -564,5 +548,5 @@
          makefiles and thus count_implicit_rule_limits wasn't called yet.  */
       if (num_pattern_rules != 0)
-        fatal (NILF, _("BUG: num_pattern_rules wrong!  %u != %u"),
+        fatal (NILF, _("BUG: num_pattern_rules is wrong!  %u != %u"),
                num_pattern_rules, rules);
     }
Index: /trunk/src/kmk/rule.h
===================================================================
--- /trunk/src/kmk/rule.h	(revision 2590)
+++ /trunk/src/kmk/rule.h	(revision 2591)
@@ -1,6 +1,6 @@
 /* Definitions for using pattern rules in GNU Make.
 Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
-1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software
-Foundation, Inc.
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
Index: /trunk/src/kmk/signame.c
===================================================================
--- /trunk/src/kmk/signame.c	(revision 2590)
+++ /trunk/src/kmk/signame.c	(revision 2591)
@@ -1,5 +1,6 @@
 /* Convert between signal names and numbers.
 Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
+Foundation, Inc.
 This file is part of GNU Make.
 
@@ -229,5 +230,5 @@
 
 char *
-strsignal (int signal)
+strsignal (int sig)
 {
   static char buf[] = "Signal 12345678901234567890";
@@ -246,8 +247,8 @@
 #endif
 
-  if (signal > 0 || signal < NSIG)
-    return (char *) sys_siglist[signal];
-
-  sprintf (buf, "Signal %d", signal);
+  if (sig > 0 || sig < NSIG)
+    return (char *) sys_siglist[sig];
+
+  sprintf (buf, "Signal %d", sig);
   return buf;
 }
Index: /trunk/src/kmk/strcache.c
===================================================================
--- /trunk/src/kmk/strcache.c	(revision 2590)
+++ /trunk/src/kmk/strcache.c	(revision 2591)
@@ -1,4 +1,4 @@
 /* Constant string caching for GNU Make.
-Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
Index: /trunk/src/kmk/subproc.bat
===================================================================
--- /trunk/src/kmk/subproc.bat	(revision 2590)
+++ /trunk/src/kmk/subproc.bat	(revision 2591)
@@ -1,5 +1,5 @@
 @echo off
 rem Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-rem 2005, 2006, 2007 Free Software Foundation, Inc.
+rem 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 rem This file is part of GNU Make.
 rem
Index: /trunk/src/kmk/tests/ChangeLog
===================================================================
--- /trunk/src/kmk/tests/ChangeLog	(revision 2590)
+++ /trunk/src/kmk/tests/ChangeLog	(revision 2591)
@@ -1,2 +1,186 @@
+2010-07-28  Paul Smith  <psmith@gnu.org>
+
+	* scripts/targets/POSIX: Compatibility issues with Solaris (and
+	Tru64?); "false" returns different exit codes, and set -x shows
+	output with extra whitespace.  Run the commands by hand first to
+	find out what the real shell would do, then compare what make does.
+	* scripts/variables/SHELL: Ditto.
+
+2010-07-12  Paul Smith  <psmith@gnu.org>
+
+	* test_driver.pl: Add a new $perl_name containing the path to Perl.
+	* run_make_tests.pl (run_make_test): Replace the special string
+	#PERL# in a makefile etc. with the path the Perl executable so
+	makefiles can use it.
+
+	* scripts/targets/ONESHELL: Add a new set of regression tests for
+	the .ONESHELL feature.
+
+2010-07-06  Paul Smith  <psmith@gnu.org>
+
+	* scripts/variables/SHELL: Test the new .SHELLFLAGS variable.
+
+	* scripts/targets/POSIX: New file.  Test the .POSIX special target.
+	Verify that enabling .POSIX changes the shell flags to set -e.
+
+2010-07-01  Paul Smith  <psmith@gnu.org>
+
+	* scripts/features/recursion: Add a space to separate command-line
+	args.  Fixes Savannah bug #29968.
+
+2009-11-12  Boris Kolpackov  <boris@codesynthesis.com>
+
+	* scripts/features/vpath3: Test for the new library search
+	behavior.
+
+2009-10-06  Boris Kolpackov  <boris@codesynthesis.com>
+
+	* scripts/features/se_explicit: Enable the test for now fixed
+	Savannah bug 25780.
+
+2009-10-06  Boris Kolpackov  <boris@codesynthesis.com>
+
+	* scripts/variables/undefine: Tests for the new undefine feature.
+
+2009-10-03  Paul Smith  <psmith@gnu.org>
+
+	* scripts/features/parallelism: Test for open Savannah bug #26846.
+
+	* scripts/variables/MAKE: Rewrite for new run_make_test() format.
+
+	* scripts/variables/MAKEFLAGS: Created.
+	Add test for Savannah bug #2216 (still open).
+
+	* scripts/features/include: Test for Savannah bug #102 (still open).
+
+2009-09-30  Boris Kolpackov  <boris@codesynthesis.com>
+
+	* scripts/features/include: Add diagnostics issuing tests for
+	cases where targets have been updated and failed with the
+	dontcare flag. Savannah bugs #15110, #25493, #12686, #17740.
+
+2009-09-28  Paul Smith  <psmith@gnu.org>
+
+	* scripts/functions/shell: Add regression test for Savannah bug
+	#20513 (still open).
+
+	* scripts/features/se_explicit: Add regression tests for Savannah
+	bug #25780 (still open).
+
+	* run_make_tests.pl (valid_option): Add a new flag, -all([-_]?tests)?
+	that runs tests we know will fail.  This allows us to add
+	regression tests to the test suite for bugs that haven't been
+	fixed yet.
+
+2009-09-28  Boris Kolpackov  <boris@codesynthesis.com>
+
+	* scripts/features/patspecific_vars: Add a test for the shortest
+	stem first order.
+
+	* scripts/features/patternrules: Add a test for the shortest stem
+	first order.
+
+2009-09-24  Paul Smith  <psmith@gnu.org>
+
+	* scripts/features/se_implicit: Add a test for order-only
+	secondary expansion prerequisites.
+
+2009-09-23  Paul Smith  <psmith@gnu.org>
+
+	* scripts/features/patternrules: Test that we can remove pattern
+	rules, both single and multiple prerequisites.  Savannah bug #18622.
+
+	* scripts/features/echoing: Rework for run_make_test().
+
+2009-06-14  Paul Smith  <psmith@gnu.org>
+
+	* scripts/features/vpath: Verify we don't get bogus circular
+	dependency warnings if we choose a different file via vpath during
+	update.  Savannah bug #13529.
+
+2009-06-13  Paul Smith  <psmith@gnu.org>
+
+	* scripts/variables/MAKEFILES: Verify that MAKEFILES included
+	files (and files included by them) don't set the default goal.
+	Savannah bug #13401.
+
+	* scripts/functions/wildcard: Test that wildcards with
+	non-existent glob matchers return empty.
+
+2009-06-09  Paul Smith  <psmith@gnu.org>
+
+	* scripts/options/dash-B: Test the $? works correctly with -B.
+	Savannah bug #17825.
+
+	* scripts/features/patternrules: Test that dependencies of
+	"also_make" targets are created properly.  Savannah bug #19108.
+
+	* test_driver.pl (compare_output): Create a "run" file for failed
+	tests containing the command that was run.
+	(get_runfile): New function.
+
+	* run_make_tests.pl (valid_option): Enhanced support for valgrind:
+	allow memcheck and massif tools.
+
+	* scripts/features/patternrules: Have to comment out a line in the
+	first test due to backing out a change that broke the implicit
+	rule search algorithm.  Savannah bug #17752.
+	* scripts/misc/general4: Remove a test that is redundant with
+	patternrules.
+
+	* scripts/features/parallelism: Add a test for re-exec with
+	jobserver master override.  Savannah bug #18124.
+
+2009-06-08  Paul Smith  <psmith@gnu.org>
+
+	* scripts/features/targetvars: Add a test for continued target
+	vars after a semicolon.  Savannah bug #17521.
+
+2009-06-07  Paul Smith  <psmith@gnu.org>
+
+	* scripts/features/se_explicit: Make sure we catch defining
+	prereqs during snap_deps().  Savannah bug #24622.
+
+	* scripts/variables/automatic: Check prereq ordering when the
+	target with the recipe has no prereqs.  Savannah bug #21198.
+
+	* scripts/variables/LIBPATTERNS: Add a new set of test for
+	$(.LIBPATTERNS) (previously untested!)
+
+2009-06-04  Paul Smith  <psmith@gnu.org>
+
+	* scripts/variables/SHELL: The export target-specific SHELL test
+	has an incorrect known-good-value.
+
+	* scripts/misc/general4: Check for whitespace (ffeed, vtab, etc.)
+
+	* scripts/features/se_explicit: Add tests for Savannah bug #24588.
+
+2009-05-31  Paul Smith  <psmith@gnu.org>
+
+	* scripts/variables/DEFAULT_GOAL: Add tests for Savannah bug #25697.
+
+	* scripts/features/targetvars: Add tests of overrides for Savannah
+	bug #26207.
+	* scripts/features/patspecific_vars: Ditto.
+
+	* scripts/features/patternrules: Add a test for Savannah bug #26593.
+
+2009-05-30  Paul Smith  <psmith@gnu.org>
+
+	* scripts/variables/flavors: Update with new variable flavor tests.
+	* scripts/variables/define: Create a new set of tests for
+	define/endef and move those aspects of the flavors suite here.
+
+2009-05-25  Paul Smith  <psmith@gnu.org>
+
+	* scripts/features/targetvars: Ditto.
+
+	* scripts/features/export: Test new variable parsing abilities.
+
+2009-02-23  Ramon Garcia  <ramon.garcia.f@gmail.com>
+
+	* scripts/variables/private: Create a new suite of tests for 'private'.
+
 2007-11-04  Paul Smith  <psmith@gnu.org>
 
@@ -881,5 +1065,5 @@
 
 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
Index: /trunk/src/kmk/tests/NEWS
===================================================================
--- /trunk/src/kmk/tests/NEWS	(revision 2590)
+++ /trunk/src/kmk/tests/NEWS	(revision 2591)
@@ -165,5 +165,5 @@
 -------------------------------------------------------------------------------
 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
Index: /trunk/src/kmk/tests/README
===================================================================
--- /trunk/src/kmk/tests/README	(revision 2590)
+++ /trunk/src/kmk/tests/README	(revision 2591)
@@ -9,5 +9,5 @@
  -----------------------------------------------------------------------------
  Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
  This file is part of GNU Make.
 
Index: /trunk/src/kmk/tests/mkshadow
===================================================================
--- /trunk/src/kmk/tests/mkshadow	(revision 2590)
+++ /trunk/src/kmk/tests/mkshadow	(revision 2591)
@@ -5,5 +5,6 @@
 #
 # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-# 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
+# Foundation, Inc.
 # This file is part of GNU Make.
 #
Index: /trunk/src/kmk/tests/run_make_tests.pl
===================================================================
--- /trunk/src/kmk/tests/run_make_tests.pl	(revision 2590)
+++ /trunk/src/kmk/tests/run_make_tests.pl	(revision 2591)
@@ -13,5 +13,6 @@
 
 # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-# 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
+# Foundation, Inc.
 # This file is part of GNU Make.
 #
@@ -29,7 +30,14 @@
 # this program.  If not, see <http://www.gnu.org/licenses/>.
 
+
 $valgrind = 0;              # invoke make with valgrind
-$valgrind_args = '--num-callers=15 --tool=memcheck --leak-check=full';
+$valgrind_args = '';
+$memcheck_args = '--num-callers=15 --tool=memcheck --leak-check=full';
+$massif_args = '--num-callers=15 --tool=massif --alloc-fn=xmalloc --alloc-fn=xcalloc --alloc-fn=xrealloc --alloc-fn=xstrdup --alloc-fn=xstrndup';
 $pure_log = undef;
+
+$command_string = '';
+
+$all_tests = 0;
 
 require "test_driver.pl";
@@ -44,18 +52,28 @@
    local($option) = @_;
 
-   if ($option =~ /^-make([-_]?path)?$/)
-   {
-      $make_path = shift @argv;
-      if (!-f $make_path)
-      {
-	 print "$option $make_path: Not found.\n";
-	 exit 0;
-      }
-      return 1;
-   }
-
-   if ($option =~ /^-valgrind$/i) {
-     $valgrind = 1;
-     return 1;
+   if ($option =~ /^-make([-_]?path)?$/i) {
+       $make_path = shift @argv;
+       if (!-f $make_path) {
+           print "$option $make_path: Not found.\n";
+           exit 0;
+       }
+       return 1;
+   }
+
+   if ($option =~ /^-all([-_]?tests)?$/i) {
+       $all_tests = 1;
+       return 1;
+   }
+
+   if ($option =~ /^-(valgrind|memcheck)$/i) {
+       $valgrind = 1;
+       $valgrind_args = $memcheck_args;
+       return 1;
+   }
+
+   if ($option =~ /^-massif$/i) {
+       $valgrind = 1;
+       $valgrind_args = $massif_args;
+       return 1;
    }
 
@@ -106,4 +124,5 @@
     $makestring =~ s/#MAKEPATH#/$mkpath/g;
     $makestring =~ s/#MAKE#/$make_name/g;
+    $makestring =~ s/#PERL#/$perl_name/g;
     $makestring =~ s/#PWD#/$pwd/g;
 
@@ -120,4 +139,5 @@
   $answer =~ s/#MAKEPATH#/$mkpath/g;
   $answer =~ s/#MAKE#/$make_name/g;
+  $answer =~ s/#PERL#/$perl_name/g;
   $answer =~ s/#PWD#/$pwd/g;
 
@@ -149,4 +169,6 @@
   }
 
+  $command_string = "$command\n";
+
   if ($valgrind) {
     print VALGRIND "\n\nExecuting: $command\n";
@@ -156,5 +178,8 @@
   {
       my $old_timeout = $test_timeout;
-      $test_timeout = $timeout if $timeout;
+      $timeout and $test_timeout = $timeout;
+
+      # If valgrind is enabled, turn off the timeout check
+      $valgrind and $test_timeout = 0;
 
       $code = &run_command_with_output($logname,$command);
@@ -184,8 +209,10 @@
     print "Error running $make_path (expected $expected_code; got $code): $command\n";
     $test_passed = 0;
+    $runf = &get_runfile;
+    &create_file (&get_runfile, $command_string);
     # If it's a SIGINT, stop here
     if ($code & 127) {
       print STDERR "\nCaught signal ".($code & 127)."!\n";
-      exit($code);
+      ($code & 127) == 2 and exit($code);
     }
     return 0;
@@ -196,5 +223,5 @@
   }
 
-  1;
+  return 1;
 }
 
@@ -202,11 +229,20 @@
 {
    &print_standard_usage ("run_make_tests",
-                          "[-make_path make_pathname] [-valgrind]",);
+                          "[-make_path make_pathname] [-memcheck] [-massif]",);
 }
 
 sub print_help
 {
-   &print_standard_help ("-make_path",
-          "\tYou may specify the pathname of the copy of make to run.");
+   &print_standard_help (
+        "-make_path",
+        "\tYou may specify the pathname of the copy of make to run.",
+        "-valgrind",
+        "-memcheck",
+        "\tRun the test suite under valgrind's memcheck tool.",
+        "\tChange the default valgrind args with the VALGRIND_ARGS env var.",
+        "-massif",
+        "\tRun the test suite under valgrind's massif toool.",
+        "\tChange the default valgrind args with the VALGRIND_ARGS env var."
+       );
 }
 
@@ -336,9 +372,10 @@
 
    if ($valgrind) {
+     my $args = $valgrind_args;
      open(VALGRIND, "> valgrind.out")
        || die "Cannot open valgrind.out: $!\n";
      #  -q --leak-check=yes
-     exists $ENV{VALGRIND_ARGS} and $valgrind_args = $ENV{VALGRIND_ARGS};
-     $make_path = "valgrind --log-fd=".fileno(VALGRIND)." $valgrind_args $make_path";
+     exists $ENV{VALGRIND_ARGS} and $args = $ENV{VALGRIND_ARGS};
+     $make_path = "valgrind --log-fd=".fileno(VALGRIND)." $args $make_path";
      # F_SETFD is 2
      fcntl(VALGRIND, 2, 0) or die "fcntl(setfd) failed: $!\n";
Index: /trunk/src/kmk/tests/scripts/features/echoing
===================================================================
--- /trunk/src/kmk/tests/scripts/features/echoing	(revision 2590)
+++ /trunk/src/kmk/tests/scripts/features/echoing	(revision 2591)
@@ -1,69 +1,57 @@
-$description = "The following test creates a makefile to test command \n"
-              ."echoing.  It tests that when a command line starts with \n"
-              ."a '\@', the echoing of that line is suppressed.  It also \n"
-              ."tests the -n option which tells make to ONLY echo the  \n"
-              ."commands and no execution happens.  In this case, even \n"
-              ."the commands with '\@' are printed. Lastly, it tests the \n"
-              ."-s flag which tells make to prevent all echoing, as if \n"
-              ."all commands started with a '\@'.";
+#                                                                    -*-perl-*-
+$description = "The following test creates a makefile to test command
+echoing.  It tests that when a command line starts with
+a '\@', the echoing of that line is suppressed.  It also
+tests the -n option which tells make to ONLY echo the
+commands and no execution happens.  In this case, even
+the commands with '\@' are printed. Lastly, it tests the
+-s flag which tells make to prevent all echoing, as if
+all commands started with a '\@'.";
 
-$details = "This test is similar to the 'clean' test except that a '\@' has\n"
-          ."been placed in front of the delete command line.  Four tests \n"
-          ."are run here.  First, make is run normally and the first echo\n"
-          ."command should be executed.  In this case there is no '\@' so \n"
-          ."we should expect make to display the command AND display the \n"
-          ."echoed message.  Secondly, make is run with the clean target, \n"
-          ."but since there is a '\@' at the beginning of the command, we\n"
-          ."expect no output; just the deletion of a file which we check \n"
-          ."for.  Third, we give the clean target again except this time\n"
-          ."we give make the -n option.  We now expect the command to be \n"
-          ."displayed but not to be executed.  In this case we need only \n"
-          ."to check the output since an error message would be displayed\n"
-          ."if it actually tried to run the delete command again and the \n"
-          ."file didn't exist. Lastly, we run the first test again with \n"
-          ."the -s option and check that make did not echo the echo \n"
-          ."command before printing the message.";
+$details = "This test is similar to the 'clean' test except that a '\@' has
+been placed in front of the delete command line.  Four tests
+are run here.  First, make is run normally and the first echo
+command should be executed.  In this case there is no '\@' so
+we should expect make to display the command AND display the
+echoed message.  Secondly, make is run with the clean target,
+but since there is a '\@' at the beginning of the command, we
+expect no output; just the deletion of a file which we check
+for.  Third, we give the clean target again except this time
+we give make the -n option.  We now expect the command to be
+displayed but not to be executed.  In this case we need only
+to check the output since an error message would be displayed
+if it actually tried to run the delete command again and the
+file didn't exist. Lastly, we run the first test again with
+the -s option and check that make did not echo the echo
+command before printing the message.\n";
 
 $example = "EXAMPLE_FILE";
 
-open(MAKEFILE,"> $makefile");
-
-# The Contents of the MAKEFILE ...
-
-print MAKEFILE "all: \n";
-print MAKEFILE "\techo This makefile did not clean the dir... good\n";
-print MAKEFILE "clean: \n";
-print MAKEFILE "\t\@$delete_command $example\n";
-
-# END of Contents of MAKEFILE
-
-close(MAKEFILE);
-
-&touch($example);
+touch($example);
 
 # TEST #1
 # -------
 
-&run_make_with_options($makefile,"",&get_logfile,0);
-$answer = "echo This makefile did not clean the dir... good\n"
-         ."This makefile did not clean the dir... good\n";
-&compare_output($answer,&get_logfile(1));
-
+run_make_test("
+all:
+\techo This makefile did not clean the dir... good
+clean:
+\t\@$delete_command $example\n",
+              '', 'echo This makefile did not clean the dir... good
+This makefile did not clean the dir... good');
 
 # TEST #2
 # -------
 
-&run_make_with_options($makefile,"clean",&get_logfile,0);
+run_make_test(undef, 'clean', '');
 if (-f $example) {
   $test_passed = 0;
+  unlink($example);
 }
-&compare_output('',&get_logfile(1));
 
 # TEST #3
 # -------
 
-&run_make_with_options($makefile,"-n clean",&get_logfile,0);
-$answer = "$delete_command $example\n";
-&compare_output($answer,&get_logfile(1));
+run_make_test(undef, '-n clean', "$delete_command $example\n");
 
 
@@ -71,17 +59,6 @@
 # -------
 
-&run_make_with_options($makefile,"-s",&get_logfile,0);
-$answer = "This makefile did not clean the dir... good\n";
-&compare_output($answer,&get_logfile(1));
+run_make_test(undef, '-s', "This makefile did not clean the dir... good\n");
 
 
 1;
-
-
-
-
-
-
-
-
-
Index: /trunk/src/kmk/tests/scripts/features/export
===================================================================
--- /trunk/src/kmk/tests/scripts/features/export	(revision 2590)
+++ /trunk/src/kmk/tests/scripts/features/export	(revision 2591)
@@ -7,10 +7,5 @@
 # about that here.
 
-open(MAKEFILE,"> $makefile");
-
-# The Contents of the MAKEFILE ...
-
-print MAKEFILE <<'EOMAKE';
-
+&run_make_test('
 FOO = foo
 BAR = bar
@@ -41,17 +36,7 @@
 	@echo "FOO=$(FOO) BAR=$(BAR) BAZ=$(BAZ) BOZ=$(BOZ) BITZ=$(BITZ) BOTZ=$(BOTZ)"
 	@echo "FOO=$$FOO BAR=$$BAR BAZ=$$BAZ BOZ=$$BOZ BITZ=$$BITZ BOTZ=$$BOTZ"
-
-EOMAKE
-
-close(MAKEFILE);
-
-# TEST 0: basics
-
-&run_make_with_options($makefile,"",&get_logfile,0);
-
-$answer = "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
-FOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n";
-
-&compare_output($answer,&get_logfile(1));
+',
+           '', "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
+FOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n");
 
 # TEST 1: make sure vars inherited from the parent are exported
@@ -59,56 +44,34 @@
 $extraENV{FOO} = 1;
 
-&run_make_with_options($makefile,"",&get_logfile,0);
-
-$answer = "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
-FOO=foo BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n";
-
-&compare_output($answer,&get_logfile(1));
+&run_make_test(undef, '', "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
+FOO=foo BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n");
 
 # TEST 2: global export.  Explicit unexport takes precedence.
 
-&run_make_with_options($makefile,"EXPORT_ALL=1",&get_logfile,0);
-
-$answer = "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
-FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n";
-
-&compare_output($answer,&get_logfile(1));
+run_make_test(undef, "EXPORT_ALL=1" ,
+              "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
+FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n");
 
 # TEST 3: global unexport.  Explicit export takes precedence.
 
-&run_make_with_options($makefile,"UNEXPORT_ALL=1",&get_logfile,0);
-
-$answer = "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
-FOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n";
-
-&compare_output($answer,&get_logfile(1));
+&run_make_test(undef, "UNEXPORT_ALL=1",
+               "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
+FOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n");
 
 # TEST 4: both: in the above makefile the unexport comes last so that rules.
 
-&run_make_with_options($makefile,"EXPORT_ALL=1 UNEXPORT_ALL=1",&get_logfile,0);
-
-$answer = "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
-FOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n";
-
-&compare_output($answer,&get_logfile(1));
+&run_make_test(undef, "EXPORT_ALL=1 UNEXPORT_ALL=1",
+               "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
+FOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n");
 
 # TEST 5: test the pseudo target.
 
-&run_make_with_options($makefile,"EXPORT_ALL_PSEUDO=1",&get_logfile,0);
-
-$answer = "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
-FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n";
-
-&compare_output($answer,&get_logfile(1));
-
+&run_make_test(undef, "EXPORT_ALL_PSEUDO=1",
+               "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
+FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n");
 
 # TEST 6: Test the expansion of variables inside export
 
-$makefile2 = &get_tmpfile;
-
-open(MAKEFILE, "> $makefile2");
-
-print MAKEFILE <<'EOF';
-
+&run_make_test('
 foo = f-ok
 bar = b-ok
@@ -126,22 +89,10 @@
 	@echo foo=$(foo) bar=$(bar)
 	@echo foo=$$foo bar=$$bar
-
-EOF
-
-close(MAKEFILE);
-
-&run_make_with_options($makefile2,"",&get_logfile,0);
-$answer = "foo=f-ok bar=b-ok\nfoo=f-ok bar=b-ok\n";
-&compare_output($answer,&get_logfile(1));
-
+',
+             "", "foo=f-ok bar=b-ok\nfoo=f-ok bar=b-ok\n");
 
 # TEST 7: Test the expansion of variables inside unexport
 
-$makefile3 = &get_tmpfile;
-
-open(MAKEFILE, "> $makefile3");
-
-print MAKEFILE <<'EOF';
-
+&run_make_test('
 foo = f-ok
 bar = b-ok
@@ -161,22 +112,10 @@
 	@echo foo=$(foo) bar=$(bar)
 	@echo foo=$$foo bar=$$bar
-
-EOF
-
-close(MAKEFILE);
-
-&run_make_with_options($makefile3,"",&get_logfile,0);
-$answer = "foo=f-ok bar=b-ok\nfoo= bar=\n";
-&compare_output($answer,&get_logfile(1));
-
+',
+              '', "foo=f-ok bar=b-ok\nfoo= bar=\n");
 
 # TEST 7: Test exporting multiple variables on the same line
 
-$makefile4 = &get_tmpfile;
-
-open(MAKEFILE, "> $makefile4");
-
-print MAKEFILE <<'EOF';
-
+&run_make_test('
 A = a
 B = b
@@ -197,21 +136,12 @@
 
 all: ; @echo A=$$A B=$$B C=$$C D=$$D E=$$E F=$$F G=$$G H=$$H I=$$I J=$$J
-EOF
-
-close(MAKEFILE);
-
-&run_make_with_options($makefile4,"",&get_logfile,0);
-$answer = "A=a B=b C=c D=d E=e F=f G=g H=h I=i J=j\n";
-&compare_output($answer,&get_logfile(1));
-
+',
+               '', "A=a B=b C=c D=d E=e F=f G=g H=h I=i J=j\n");
 
 # TEST 8: Test unexporting multiple variables on the same line
 
-$makefile5 = &get_tmpfile;
+@extraENV{qw(A B C D E F G H I J)} = qw(1 2 3 4 5 6 7 8 9 10);
 
-open(MAKEFILE, "> $makefile5");
-
-print MAKEFILE <<'EOF';
-
+&run_make_test('
 A = a
 B = b
@@ -232,14 +162,24 @@
 
 all: ; @echo A=$$A B=$$B C=$$C D=$$D E=$$E F=$$F G=$$G H=$$H I=$$I J=$$J
-EOF
+',
+               '', "A= B= C= D= E= F= G= H= I= J=\n");
 
-close(MAKEFILE);
+# TEST 9: Check setting a variable named "export"
 
-@extraENV{qw(A B C D E F G H I J)} = qw(1 2 3 4 5 6 7 8 9 10);
+&run_make_test('
+export = 123
+export export
+export export = 456
+a: ; @echo "\$$(export)=$(export) / \$$export=$$export"
+',
+               '', "\$(export)=456 / \$export=456\n");
 
-&run_make_with_options($makefile5,"",&get_logfile,0);
-$answer = "A= B= C= D= E= F= G= H= I= J=\n";
-&compare_output($answer,&get_logfile(1));
+# TEST 9: Check "export" as a target
 
+&run_make_test('
+a: export
+export: ; @echo "$@"
+',
+               '', "export\n");
 
 # This tells the test driver that the perl test script executed properly.
Index: /trunk/src/kmk/tests/scripts/features/include
===================================================================
--- /trunk/src/kmk/tests/scripts/features/include	(revision 2590)
+++ /trunk/src/kmk/tests/scripts/features/include	(revision 2591)
@@ -91,6 +91,4 @@
 ', '', '');
 
-1;
-
 
 # Make sure that we don't die when the command fails but we dontcare.
@@ -118,3 +116,64 @@
 sinclude', '', '');
 
+
+# Test that the diagnostics is issued even if the target has been
+# tried before with the dontcare flag (direct dependency case).
+#
+run_make_test('
+-include foo
+
+all: bar
+
+foo: baz
+bar: baz
+',
+'',
+"#MAKE#: *** No rule to make target `baz', needed by `bar'.  Stop.\n",
+512);
+
+# Test that the diagnostics is issued even if the target has been
+# tried before with the dontcare flag (indirect dependency case).
+#
+run_make_test('
+-include foo
+
+all: bar
+
+foo: baz
+bar: baz
+baz: end
+',
+'',
+"#MAKE#: *** No rule to make target `end', needed by `baz'.  Stop.\n",
+512);
+
+# Test that the diagnostics is issued even if the target has been
+# tried before with the dontcare flag (include/-include case).
+#
+run_make_test('
+include bar
+-include foo
+
+all:
+
+foo: baz
+bar: baz
+baz: end
+',
+'',
+"#MAKEFILE#:2: bar: No such file or directory
+#MAKE#: *** No rule to make target `end', needed by `baz'.  Stop.\n",
+512);
+
+if ($all_tests) {
+    # Test that include of a rebuild-able file doesn't show a warning
+    # Savannah bug #102
+    run_make_test(q!
+include foo
+foo: ; @echo foo = bar > $@
+!,
+                  '', "#MAKE#: `foo' is up to date.\n");
+    rmfiles('foo');
+}
+
 1;
Index: /trunk/src/kmk/tests/scripts/features/override
===================================================================
--- /trunk/src/kmk/tests/scripts/features/override	(revision 2590)
+++ /trunk/src/kmk/tests/scripts/features/override	(revision 2591)
@@ -1,34 +1,45 @@
-$description = "The following test creates a makefile to ...";
+#                                                                    -*-perl-*-
+
+$description = "Test the override directive on variable assignments.";
 
 $details = "";
 
-open(MAKEFILE,"> $makefile");
+# TEST 0: Basic override
 
-# The Contents of the MAKEFILE ...
+run_make_test('
+X = start
+override recur = $(X)
+override simple := $(X)
+X = end
+all: ; @echo "$(recur) $(simple)"
+',
+              'recur=I simple=J', "end start\n");
 
-print MAKEFILE "override define foo\n"
-              ."\@echo First comes the definition.\n"
-              ."\@echo Then comes the override.\n"
-              ."endef\n"
-              ."all: \n"
-              ."\t\$(foo)\n";
+# TEST 1: Override with append
 
-# END of Contents of MAKEFILE
+run_make_test('
+X += X1
+override X += X2
+override Y += Y1
+Y += Y2
+all: ; @echo "$(X) $(Y)"
+',
+              '', "X1 X2 Y1\n");
 
-close(MAKEFILE);
+# TEST 2: Override with append to the command line
 
-&run_make_with_options($makefile,"foo=Hello",&get_logfile);
+run_make_test(undef, 'X=C Y=C', "C X2 C Y1\n");
 
-# Create the answer to what should be produced by this Makefile
-$answer = "First comes the definition.\n"
-         ."Then comes the override.\n";
+# Test override of define/endef
 
-&compare_output($answer,&get_logfile(1));
+run_make_test('
+override define foo
+@echo First comes the definition.
+@echo Then comes the override.
+endef
+all: ; $(foo)
+',
+              'foo=Hello', "First comes the definition.\nThen comes the override.\n");
+
 
 1;
-
-
-
-
-
-
Index: /trunk/src/kmk/tests/scripts/features/parallelism
===================================================================
--- /trunk/src/kmk/tests/scripts/features/parallelism	(revision 2590)
+++ /trunk/src/kmk/tests/scripts/features/parallelism	(revision 2591)
@@ -44,5 +44,5 @@
               "ONE.inc\nTHREE.inc\nTWO.inc\nONE\nTHREE\nTWO\nsuccess\n");
 
-unlink('1.inc', '2.inc');
+rmfiles(qw(1.inc 2.inc));
 
 
@@ -63,5 +63,5 @@
               "ONE.inc\nTHREE.inc\nTWO.inc\nONE\nTHREE\nTWO\nsuccess\n");
 
-unlink('1.inc', '2.inc');
+rmfiles(qw(1.inc 2.inc));
 
 # Grant Taylor reports a problem where tokens can be lost (not written back
@@ -153,6 +153,81 @@
 .PHONY: phony
 phony: ; : phony', '-rR -j', ': phony');
-unlink('target');
-
+rmfiles('target');
+
+# TEST #10: Don't put --jobserver-fds into a re-exec'd MAKEFLAGS.
+# We can't test this directly because there's no way a makefile can
+# show the value of MAKEFLAGS we were re-exec'd with.  We can intuit it
+# by looking for "disabling jobserver mode" warnings; we should only
+# get one from the original invocation and none from the re-exec.
+# See Savannah bug #18124
+
+run_make_test(q!
+-include inc.mk
+recur:
+#	@echo 'MAKEFLAGS = $(MAKEFLAGS)'
+	@rm -f inc.mk
+	@$(MAKE) -j2 -f #MAKEFILE# all
+all:
+#	@echo 'MAKEFLAGS = $(MAKEFLAGS)'
+	@echo $@
+inc.mk:
+#	@echo 'MAKEFLAGS = $(MAKEFLAGS)'
+	@echo 'FOO = bar' > $@
+!,
+              '--no-print-directory -j2', "#MAKE#[1]: warning: -jN forced in submake: disabling jobserver mode.\nall\n");
+
+rmfiles('inc.mk');
+
+if ($all_tests) {
+    # Implicit files aren't properly recreated during parallel builds
+    # Savannah bug #26864
+
+    # The first run works fine
+    run_make_test(q!
+%.bar: %.x foo.y ; cat $^ > $@
+%.x: ; touch $@
+foo.y: foo.y.in ; cp $< $@
+foo.y.in: ; touch $@
+!,
+                  '-j2 main.bar',
+                  "touch foo.y.in
+touch main.x
+cp foo.y.in foo.y
+cat main.x foo.y > main.bar
+rm main.x");
+
+    # Now we touch the .in file and make sure it still works
+    touch('foo.y.in');
+
+    run_make_test(undef, '-j2 main.bar', "cp foo.y.in foo.y
+touch main.x
+cat main.x foo.y > main.bar
+rm main.x");
+
+    # Clean up
+    rmfiles(qw(foo.y foo.y.in main.bar));
+}
+
+if ($all_tests) {
+    # Jobserver FD handling is messed up in some way.
+    # Savannah bug #28189
+    # It doesn't look like that bug anymore but this is the code it runs
+
+    run_make_test(q!
+ifdef EXTRA
+vpath %.dst /
+xxx.dst: ; true
+yyy.dst: ; true
+endif
+
+M := $(MAKE)
+xx: ; $M --no-print-directory -j2 -f $(MAKEFILE_LIST) xxx.dst yyy.dst EXTRA=1
+!,
+                  '-j2',
+                  '#MAKE#[1]: warning: -jN forced in submake: disabling jobserver mode.
+true
+true
+');
+}
 
 # Make sure that all jobserver FDs are closed if we need to re-exec the
@@ -183,5 +258,5 @@
 #               'bar');
 
-# unlink('dependfile', 'output');
+# rmfiles(qw(dependfile output));
 
 
@@ -189,5 +264,5 @@
 # run_make_test(undef, '-j2 recurse INCL=false', 'bar');
 
-# unlink('dependfile', 'output');
+# rmfiles(qw(dependfile output));
 
 1;
Index: /trunk/src/kmk/tests/scripts/features/patspecific_vars
===================================================================
--- /trunk/src/kmk/tests/scripts/features/patspecific_vars	(revision 2590)
+++ /trunk/src/kmk/tests/scripts/features/patspecific_vars	(revision 2591)
@@ -121,4 +121,28 @@
 pattrn: global: new $t pattern: good $t inherit: good $t;');
 
+# TEST #8: override in pattern-specific variables
+
+run_make_test('
+a%: override FOO += f1
+a%: FOO += f2
+ab: ; @echo "$(FOO)"
+',
+              '', "f1\n");
+
+run_make_test(undef, 'FOO=C', "C f1\n");
+
+# TEST #9: Test shortest stem selection in pattern-specific variables.
+
+run_make_test('
+%-mt.x: x := two
+%.x: x := one
+
+all: foo.x foo-mt.x
+
+foo.x: ;@echo $x
+foo-mt.x: ;@echo $x
+',
+'',
+"one\ntwo");
 
 1;
Index: /trunk/src/kmk/tests/scripts/features/patternrules
===================================================================
--- /trunk/src/kmk/tests/scripts/features/patternrules	(revision 2590)
+++ /trunk/src/kmk/tests/scripts/features/patternrules	(revision 2591)
@@ -16,9 +16,11 @@
 #
 
-run_make_test('
+run_make_test(q!
 .PHONY: all
 
 all: case.1 case.2 case.3
-a: void
+
+# We can't have this, due to "Implicit Rule Search Algorithm" step 5c
+#xxx: void
 
 # 1 - existing file
@@ -42,7 +44,5 @@
 
 3.implicit-phony:
-',
-'',
-'');
+!, '', '');
 
 # TEST #1: make sure files that are built via implicit rules are marked
@@ -150,4 +150,79 @@
 unlink('foo.in', 'foo.h', 'foo.c', 'foo.o');
 
+# TEST #5: make sure both prefix and suffix patterns work with multiple
+#          target patterns (Savannah bug #26593).
+#
+run_make_test('
+all: foo.s1 foo.s2 p1.foo p2.foo
+
+p1.% p2.%: %.orig
+	@echo $@
+%.s1 %.s2: %.orig
+	@echo $@
+
+.PHONY: foo.orig
+',
+              '', "foo.s1\np1.foo\n");
+
+# TEST 6: Make sure that non-target files are still eligible to be created
+# as part of implicit rule chaining.  Savannah bug #17752.
+
+run_make_test(q!
+BIN = xyz
+COPY = $(BIN).cp
+SRC = $(BIN).c
+allbroken: $(COPY) $(BIN) ; @echo ok
+$(SRC): ; @echo 'main(){}' > $@
+%.cp: % ; @cp $< $@
+% : %.c ; @cp $< $@
+clean: ; @rm -rf $(SRC) $(COPY) $(BIN)
+!,
+              '', "ok\n");
+
+unlink(qw(xyz xyz.cp xyz.c));
+
+# TEST 7: Make sure that all prereqs of all "also_make" targets get created
+# before any of the things that depend on any of them.  Savannah bug #19108.
+
+run_make_test(q!
+final: x ; @echo $@
+x: x.t1 x.t2 ; @echo $@
+x.t2: dep
+dep: ; @echo $@
+%.t1 %.t2: ; @echo $*.t1 ; echo $*.t2
+!,
+              '', "dep\nx.t1\nx.t2\nx\nfinal\n");
+
+
+# TEST 8: Verify we can remove pattern rules.  Savannah bug #18622.
+
+my @f = (qw(foo.w foo.ch));
+touch(@f);
+
+run_make_test(q!
+CWEAVE := :
+
+# Disable builtin rules
+%.tex : %.w
+%.tex : %.w %.ch
+!,
+              'foo.tex',
+              "#MAKE#: *** No rule to make target `foo.tex'.  Stop.", 512);
+
+unlink(@f);
+
+# TEST #9: Test shortest stem selection in pattern rules.
+
+run_make_test('
+%.x: ;@echo one
+%-mt.x: ;@echo two
+
+all: foo.x foo-mt.x
+',
+'',
+"one\ntwo");
+
+1;
+
 # This tells the test driver that the perl test script executed properly.
 1;
Index: /trunk/src/kmk/tests/scripts/features/recursion
===================================================================
--- /trunk/src/kmk/tests/scripts/features/recursion	(revision 2590)
+++ /trunk/src/kmk/tests/scripts/features/recursion	(revision 2591)
@@ -17,5 +17,5 @@
 	@echo THE END
 ',
-              ('CFLAGS=-O -w' . ($parallel_jobs ? '-j 2' : '')),
+              ('CFLAGS=-O -w' . ($parallel_jobs ? ' -j 2' : '')),
               ($vos
                ? "#MAKE#: Entering directory `#PWD#'
Index: /trunk/src/kmk/tests/scripts/features/se_explicit
===================================================================
--- /trunk/src/kmk/tests/scripts/features/se_explicit	(revision 2590)
+++ /trunk/src/kmk/tests/scripts/features/se_explicit	(revision 2591)
@@ -27,7 +27,7 @@
 # TEST #1: automatic variables.
 #
-run_make_test('
+run_make_test(q!
 .SECONDEXPANSION:
-.DEFAULT: ; @echo $@
+.DEFAULT: ; @echo '$@'
 
 foo: bar baz
@@ -42,5 +42,5 @@
      $$*.6
 
-',
+!,
 '-j1',
 'bar
@@ -63,7 +63,7 @@
 # Test #2: target/pattern -specific variables.
 #
-run_make_test('
+run_make_test(q!
 .SECONDEXPANSION:
-.DEFAULT: ; @echo $@
+.DEFAULT: ; @echo '$@'
 
 foo.x: $$a $$b
@@ -72,6 +72,5 @@
 
 %.x: b := baz
-
-',
+!,
 '',
 'bar
@@ -82,37 +81,25 @@
 # Test #3: order of prerequisites.
 #
-run_make_test('
+run_make_test(q!
 .SECONDEXPANSION:
-.DEFAULT: ; @echo $@
+.DEFAULT: ; @echo '$@'
 
 all: foo bar baz
 
 # Subtest #1
-#
 foo: foo.1; @:
-
 foo: foo.2
-
 foo: foo.3
 
-
 # Subtest #2
-#
 bar: bar.2
-
 bar: bar.1; @:
-
 bar: bar.3
 
-
 # Subtest #3
-#
 baz: baz.1
-
 baz: baz.2
-
 baz: ; @:
-
-',
+!,
 '-j1',
 'foo.1
@@ -126,4 +113,46 @@
 ');
 
+# TEST #4: eval in a context where there is no reading_file
+run_make_test(q!
+.SECONDEXPANSION:
+all : $$(eval $$(info test))
+!,
+            '', "test\n#MAKE#: Nothing to be done for `all'.\n");
+
+# TEST #5: (NEGATIVE) catch eval in a prereq list trying to create new
+# target/prereq relationships.
+
+run_make_test(q!
+.SECONDEXPANSION:
+proj1.exe : proj1.o $$(eval $$(test))
+define test
+proj1.o : proj1.c
+proj1.c: proj1.h
+endef
+!,
+              '', "#MAKE#: *** prerequisites cannot be defined in recipes.  Stop.\n", 512);
+
+
+# Automatic $$+ variable expansion issue.  Savannah bug #25780
+run_make_test(q!
+all : foo foo
+.SECONDEXPANSION:
+all : $$+ ; @echo '$+'
+foo : ;
+!,
+                  '', "foo foo foo foo\n");
+
+
+# Automatic $$+ variable expansion issue.  Savannah bug #25780
+run_make_test(q!
+all : bar bar
+bar : ;
+q%x : ;
+.SECONDEXPANSION:
+a%l: q1x $$+ q2x ; @echo '$+'
+!,
+                  '', "q1x bar bar q2x bar bar\n");
+
+
 # This tells the test driver that the perl test script executed properly.
 1;
Index: /trunk/src/kmk/tests/scripts/features/se_implicit
===================================================================
--- /trunk/src/kmk/tests/scripts/features/se_implicit	(revision 2590)
+++ /trunk/src/kmk/tests/scripts/features/se_implicit	(revision 2591)
@@ -12,7 +12,7 @@
 # Test #1: automatic variables.
 #
-run_make_test('
-.SECONDEXPANSION:
-.DEFAULT: ; @echo $@
+run_make_test(q!
+.SECONDEXPANSION:
+.DEFAULT: ; @echo '$@'
 
 foo.a: bar baz
@@ -38,7 +38,7 @@
 5.buz \
 6.a:
-	@echo $@
-
-',
+	@echo '$@'
+
+!,
 '-j1',
 '1.foo.a
@@ -61,5 +61,5 @@
 # Test #2: target/pattern -specific variables.
 #
-run_make_test('
+run_make_test(q!
 .SECONDEXPANSION:
 foo.x:
@@ -72,18 +72,14 @@
 %.x: x_b := baz
 
-bar baz: ; @echo $@
-
-',
-'',
-'bar
-baz
-');
+bar baz: ; @echo '$@'
+!,
+              '', "bar\nbaz\n");
 
 
 # Test #3: order of prerequisites.
 #
-run_make_test('
-.SECONDEXPANSION:
-.DEFAULT: ; @echo $@
+run_make_test(q!
+.SECONDEXPANSION:
+.DEFAULT: ; @echo '$@'
 
 all: foo bar baz
@@ -98,5 +94,5 @@
 foo: foo.3
 
-foo.1: ; @echo $@
+foo.1: ; @echo '$@'
 
 
@@ -109,5 +105,5 @@
 bar: bar.3
 
-bar.1: ; @echo $@
+bar.1: ; @echo '$@'
 
 
@@ -119,7 +115,6 @@
 
 %az: ; @:
-
-',
-'-j1',
+!,
+              '-j1',
 'foo.1
 foo.2
@@ -135,18 +130,16 @@
 # Test #4: stem splitting logic.
 #
-run_make_test('
+run_make_test(q!
 .SECONDEXPANSION:
 $(dir)/tmp/bar.o:
 
-$(dir)/tmp/foo/bar.c: ; @echo $@
-$(dir)/tmp/bar/bar.c: ; @echo $@
-foo.h: ; @echo $@
+$(dir)/tmp/foo/bar.c: ; @echo '$@'
+$(dir)/tmp/bar/bar.c: ; @echo '$@'
+foo.h: ; @echo '$@'
 
 %.o: $$(addsuffix /%.c,foo bar) foo.h
-	@echo $@: {$<} $^
-
-',
-"dir=$dir",
-"$dir/tmp/foo/bar.c
+	@echo '$@: {$<} $^'
+!,
+              "dir=$dir", "$dir/tmp/foo/bar.c
 $dir/tmp/bar/bar.c
 foo.h
@@ -157,16 +150,15 @@
 # Test #5: stem splitting logic and order-only prerequisites.
 #
-run_make_test('
+run_make_test(q!
 .SECONDEXPANSION:
 $(dir)/tmp/foo.o: $(dir)/tmp/foo.c
-$(dir)/tmp/foo.c: ; @echo $@
-bar.h: ; @echo $@
+$(dir)/tmp/foo.c: ; @echo '$@'
+bar.h: ; @echo '$@'
 
 %.o: %.c|bar.h
-	@echo $@: {$<} {$|} $^
-
-',
-"dir=$dir",
-"$dir/tmp/foo.c
+	@echo '$@: {$<} {$|} $^'
+
+!,
+              "dir=$dir", "$dir/tmp/foo.c
 bar.h
 $dir/tmp/foo.o: {$dir/tmp/foo.c} {bar.h} $dir/tmp/foo.c
@@ -176,56 +168,58 @@
 # Test #6: lack of implicit prerequisites.
 #
-run_make_test('
+run_make_test(q!
 .SECONDEXPANSION:
 foo.o: foo.c
-foo.c: ; @echo $@
+foo.c: ; @echo '$@'
 
 %.o:
-	@echo $@: {$<} $^
-
-',
-'',
-'foo.c
-foo.o: {foo.c} foo.c
-');
+	@echo '$@: {$<} $^'
+!,
+              '', "foo.c\nfoo.o: {foo.c} foo.c\n");
+
 
 # Test #7: Test stem from the middle of the name.
 #
-run_make_test('
+run_make_test(q!
 .SECONDEXPANSION:
 foobarbaz:
 
 foo%baz: % $$*.1
-	@echo $*
+	@echo '$*'
 
 bar bar.1:
-	@echo $@
-
-',
-'',
-'bar
-bar.1
-bar
-');
+	@echo '$@'
+!,
+              '', "bar\nbar.1\nbar\n");
+
 
 # Test #8: Make sure stem triple-expansion does not happen.
 #
-run_make_test('
+run_make_test(q!
 .SECONDEXPANSION:
 foo$$bar:
 
 f%r: % $$*.1
-	@echo \'$*\'
+	@echo '$*'
 
 oo$$ba oo$$ba.1:
-	@echo \'$@\'
-
-',
-'',
-'oo$ba
+	@echo '$@'
+!,
+              '', 'oo$ba
 oo$ba.1
 oo$ba
 ');
 
+# Test #9: Check the value of $^
+run_make_test(q!
+.SECONDEXPANSION:
+
+%.so: | $$(extra) ; @echo $^
+
+foo.so: extra := foo.o
+foo.so:
+foo.o:
+!,
+              '', "\n");
 
 # This tells the test driver that the perl test script executed properly.
Index: /trunk/src/kmk/tests/scripts/features/se_statpat
===================================================================
--- /trunk/src/kmk/tests/scripts/features/se_statpat	(revision 2590)
+++ /trunk/src/kmk/tests/scripts/features/se_statpat	(revision 2591)
@@ -6,10 +6,10 @@
 # Test #1: automatic variables.
 #
-run_make_test('
+# bird: Had to add -j1 here earlier...
+run_make_test(q!
 .SECONDEXPANSION:
-.DEFAULT: ; @echo $@
+.DEFAULT: ; @echo '$@'
 
 foo.a foo.b: foo.%: bar.% baz.%
-
 foo.a foo.b: foo.%: biz.% | buz.%
 
@@ -20,8 +20,6 @@
                     $$|.5 \
                     $$*.6
-
-',
-'-j1',
-'bar.a
+!,
+              '', 'bar.a
 baz.a
 biz.a
@@ -42,7 +40,7 @@
 # Test #2: target/pattern -specific variables.
 #
-run_make_test('
+run_make_test(q!
 .SECONDEXPANSION:
-.DEFAULT: ; @echo $@
+.DEFAULT: ; @echo '$@'
 
 foo.x foo.y: foo.%: $$(%_a) $$($$*_b)
@@ -51,50 +49,35 @@
 
 %.x: x_b := baz
-
-
-',
-'',
-'bar
-baz
-');
+!,
+              '', "bar\nbaz\n");
 
 
 # Test #3: order of prerequisites.
 #
-run_make_test('
+# bird: Had to add -j1 here earlier...
+run_make_test(q!
 .SECONDEXPANSION:
-.DEFAULT: ; @echo $@
+.DEFAULT: ; @echo '$@'
 
 all: foo.a bar.a baz.a
 
 # Subtest #1
-#
 foo.a foo.b: foo.%: foo.%.1; @:
-
 foo.a foo.b: foo.%: foo.%.2
-
 foo.a foo.b: foo.%: foo.%.3
 
 
 # Subtest #2
-#
 bar.a bar.b: bar.%: bar.%.2
-
 bar.a bar.b: bar.%: bar.%.1; @:
-
 bar.a bar.b: bar.%: bar.%.3
 
 
 # Subtest #3
-#
 baz.a baz.b: baz.%: baz.%.1
-
 baz.a baz.b: baz.%: baz.%.2
-
 baz.a baz.b: ; @:
-
-',
-'-j1',
-'foo.a.1
+!,
+             '', 'foo.a.1
 foo.a.2
 foo.a.3
@@ -109,15 +92,13 @@
 # Test #4: Make sure stem triple-expansion does not happen.
 #
-run_make_test('
+run_make_test(q!
 .SECONDEXPANSION:
 foo$$bar: f%r: % $$*.1
-	@echo \'$*\'
+	@echo '$*'
 
 oo$$ba oo$$ba.1:
-	@echo \'$@\'
-
-',
-'',
-'oo$ba
+	@echo '$@'
+!,
+              '', 'oo$ba
 oo$ba.1
 oo$ba
Index: /trunk/src/kmk/tests/scripts/features/targetvars
===================================================================
--- /trunk/src/kmk/tests/scripts/features/targetvars	(revision 2590)
+++ /trunk/src/kmk/tests/scripts/features/targetvars	(revision 2591)
@@ -7,7 +7,5 @@
 rules, semicolon interference, etc.";
 
-open(MAKEFILE,"> $makefile");
-
-print MAKEFILE <<'EOF';
+run_make_test('
 SHELL = /bin/sh
 export FOO = foo
@@ -18,5 +16,5 @@
 three: ; BAR=1000
 	@echo $(FOO) $(BAR)
-# Some things that shouldn't be target vars
+# Some things that shouldn not be target vars
 funk : override
 funk : override adelic
@@ -25,8 +23,8 @@
 four:FOO=x
 four:VAR$(FOO)=ok
-four: ; @echo '$(FOO) $(VAR$(FOO)) $(VAR) $(VARx)'
+four: ; @echo "$(FOO) $(VAR$(FOO)) $(VAR) $(VARx)"
 five:FOO=x
 five six : VAR$(FOO)=good
-five six: ;@echo '$(FOO) $(VAR$(FOO)) $(VAR) $(VARx) $(VARfoo)'
+five six: ;@echo "$(FOO) $(VAR$(FOO)) $(VAR) $(VARx) $(VARfoo)"
 # Test per-target variable inheritance
 seven: eight
@@ -42,6 +40,6 @@
 # Test = escaping
 EQ = =
-ten: one\=two
-ten: one \= two
+ten: one$(EQ)two
+ten: one $(EQ) two
 ten one$(EQ)two $(EQ):;@echo $@
 .PHONY: one two three four five six seven eight nine ten $(EQ) one$(EQ)two
@@ -55,61 +53,38 @@
 foo.r : RVAR += rvar
 foo.t : TVAR := $(QVAR)
-EOF
-
-close(MAKEFILE);
-
-# TEST #1
-
-&run_make_with_options($makefile, "-j1 one two three", &get_logfile);
-$answer = "one bar\nfoo two\nBAR=1000\nfoo bar\n";
-&compare_output($answer,&get_logfile(1));
+',
+                 "one two three", "one bar\nfoo two\nBAR=1000\nfoo bar\n");
 
 # TEST #2
 
-&run_make_with_options($makefile, "-j1 one two FOO=1 BAR=2", &get_logfile);
-$answer = "one 2\n1 2\n";
-&compare_output($answer,&get_logfile(1));
+run_make_test(undef, "one two FOO=1 BAR=2", "one 2\n1 2\n");
 
 # TEST #3
 
-&run_make_with_options($makefile, "-j1 four", &get_logfile);
-$answer = "x ok  ok\n";
-&compare_output($answer,&get_logfile(1));
+run_make_test(undef, "four", "x ok  ok\n");
 
 # TEST #4
 
-&run_make_with_options($makefile, "-j1 seven", &get_logfile);
-$answer = "eight: seven eight\nseven: seven seven\n";
-&compare_output($answer,&get_logfile(1));
+run_make_test(undef, "seven", "eight: seven eight\nseven: seven seven\n");
 
 # TEST #5
 
-&run_make_with_options($makefile, "-j1 nine", &get_logfile);
-$answer = "wallace bar wallace bar\n";
-&compare_output($answer,&get_logfile(1));
+run_make_test(undef, "nine", "wallace bar wallace bar\n");
 
 # TEST #5-a
 
-&run_make_with_options($makefile, "-j1 nine-a", &get_logfile);
-$answer = "baz\n";
-&compare_output($answer,&get_logfile(1));
+run_make_test(undef, "nine-a", "baz\n");
 
 # TEST #6
 
-&run_make_with_options($makefile, "-j1 ten", &get_logfile);
-$answer = "one=two\none bar\n=\nfoo two\nten\n";
-&compare_output($answer,&get_logfile(1));
+run_make_test(undef, "ten", "one=two\none bar\n=\nfoo two\nten\n");
 
 # TEST #6
 
-&run_make_with_options($makefile, "-j1 foo.q bar.q", &get_logfile);
-$answer = "qvar = rvar\nqvar =\n";
-&compare_output($answer,&get_logfile(1));
+run_make_test(undef, "foo.q bar.q", "qvar = rvar\nqvar =\n");
 
 # TEST #7
 
-&run_make_with_options($makefile, "-j1 foo.t bar.s", &get_logfile);
-$answer = "qvar = qvar\nqvar =\n";
-&compare_output($answer,&get_logfile(1));
+run_make_test(undef, "foo.t bar.s", "qvar = qvar\nqvar =\n");
 
 
@@ -117,8 +92,5 @@
 # For PR/1378: Target-specific vars don't inherit correctly
 
-$makefile2 = &get_tmpfile;
-
-open(MAKEFILE,"> $makefile2");
-print MAKEFILE <<'EOF';
+run_make_test('
 foo: FOO = foo
 bar: BAR = bar
@@ -126,10 +98,5 @@
 bar: baz
 baz: ; @echo $(FOO) $(BAR)
-EOF
-close(MAKEFILE);
-
-&run_make_with_options("$makefile2", "", &get_logfile);
-$answer = "foo bar\n";
-&compare_output($answer, &get_logfile(1));
+', "", "foo bar\n");
 
 # TEST #9
@@ -137,8 +104,5 @@
 # Also PR/1831
 
-$makefile3 = &get_tmpfile;
-
-open(MAKEFILE,"> $makefile3");
-print MAKEFILE <<'EOF';
+run_make_test('
 .PHONY: all one
 all: FOO += baz
@@ -150,32 +114,19 @@
 one: FOO += boz
 one: ; @echo $(FOO)
-EOF
-close(MAKEFILE);
-
-&run_make_with_options("$makefile3", "", &get_logfile);
-$answer = "bar baz biz boz\nbar baz\n";
-&compare_output($answer, &get_logfile(1));
+',
+              '', "bar baz biz boz\nbar baz\n");
 
 # Test #10
 
-&run_make_with_options("$makefile3", "one", &get_logfile);
-$answer = "bar biz boz\n";
-&compare_output($answer, &get_logfile(1));
+run_make_test(undef, 'one', "bar biz boz\n");
 
 # Test #11
 # PR/1709: Test semicolons in target-specific variable values
 
-$makefile4 = &get_tmpfile;
-
-open(MAKEFILE, "> $makefile4");
-print MAKEFILE <<'EOF';
+run_make_test('
 foo : FOO = ; ok
-foo : ; @echo '$(FOO)'
-EOF
-close(MAKEFILE);
-
-&run_make_with_options("$makefile4", "", &get_logfile);
-$answer = "; ok\n";
-&compare_output($answer, &get_logfile(1));
+foo : ; @echo "$(FOO)"
+',
+              '', "; ok\n");
 
 # Test #12
@@ -183,8 +134,5 @@
 # I nailed it this time :-/.
 
-$makefile5 = &get_tmpfile;
-
-open(MAKEFILE, "> $makefile5");
-print MAKEFILE <<'EOF';
+run_make_test('
 .PHONY: a
 
@@ -196,18 +144,11 @@
 a: BLAH := bar
 a: COMMAND += snafu $(BLAH)
-EOF
-close(MAKEFILE);
-
-&run_make_with_options("$makefile5", "", &get_logfile);
-$answer = "bar snafu bar\n";
-&compare_output($answer, &get_logfile(1));
+',
+              '', "bar snafu bar\n");
 
 # Test #13
 # Test double-colon rules with target-specific variable values
 
-$makefile6 = &get_tmpfile;
-
-open(MAKEFILE, "> $makefile6");
-print MAKEFILE <<'EOF';
+run_make_test('
 W = bad
 X = bad
@@ -225,11 +166,6 @@
   fo% : Z = pat
 endif
-
-EOF
-close(MAKEFILE);
-
-&run_make_with_options("$makefile6", "foo", &get_logfile);
-$answer = "ok ok foo nopat\nok ok foo nopat\n";
-&compare_output($answer, &get_logfile(1));
+',
+             'foo', "ok ok foo nopat\nok ok foo nopat\n");
 
 # Test #14
@@ -237,15 +173,10 @@
 # inheritance
 
-&run_make_with_options("$makefile6", "bar", &get_logfile);
-$answer = "ok ok bar nopat\nok ok bar nopat\n";
-&compare_output($answer, &get_logfile(1));
+run_make_test(undef, 'bar', "ok ok bar nopat\nok ok bar nopat\n");
 
 # Test #15
 # Test double-colon rules with pattern-specific variable values
 
-&run_make_with_options("$makefile6", "foo PATTERN=yes", &get_logfile);
-$answer = "ok ok foo pat\nok ok foo pat\n";
-&compare_output($answer, &get_logfile(1));
-
+run_make_test(undef, 'foo PATTERN=yes', "ok ok foo pat\nok ok foo pat\n");
 
 # Test #16
@@ -253,18 +184,10 @@
 # (> make default buffer length)
 
-$makefile7 = &get_tmpfile;
-
-open(MAKEFILE, "> $makefile7");
-print MAKEFILE <<'EOF';
+run_make_test('
 base_metals_fmd_reports.sun5 base_metals_fmd_reports CreateRealPositions        CreateMarginFunds deals_changed_since : BUILD_OBJ=$(shell if [ -f               "build_information.generate" ]; then echo "$(OBJ_DIR)/build_information.o"; else echo "no build information"; fi  )
 
 deals_changed_since: ; @echo $(BUILD_OBJ)
-
-EOF
-close(MAKEFILE);
-
-&run_make_with_options("$makefile7", '', &get_logfile);
-$answer = "no build information\n";
-&compare_output($answer, &get_logfile(1));
+',
+              '', "no build information\n");
 
 # TEST #17
@@ -287,6 +210,5 @@
 .INTERMEDIATE: foo.x rules.mk
 ',
-              '-I t1',
-              'MYVAR= FOOVAR=bar ALLVAR=xxx');
+              '-I t1', 'MYVAR= FOOVAR=bar ALLVAR=xxx');
 
 rmfiles('t1/rules.mk');
@@ -298,10 +220,44 @@
 # double-expansion.  See Savannah bug #15913.
 
-run_make_test("
-VAR := \$\$FOO
+run_make_test('
+VAR := $$FOO
 foo: VAR += BAR
-foo: ; \@echo '\$(VAR)'",
-              '',
-              '$FOO BAR');
+foo: ; @echo '."'".'$(VAR)'."'".'
+',
+              '', '$FOO BAR');
+
+# TEST #19: Override with append variables
+
+run_make_test('
+a: override FOO += f1
+a: FOO += f2
+a: ; @echo "$(FOO)"
+',
+              '', "f1\n");
+
+run_make_test(undef, 'FOO=C', "C f1\n");
+
+# TEST #20: Check for continuation after semicolons
+
+run_make_test(q!
+a: A = 'hello; \
+world'
+a: ; @echo $(A)
+!,
+              '', "hello; world\n");
+
+# TEST #19: Test define/endef variables as target-specific vars
+
+# run_make_test('
+# define b
+# @echo global
+# endef
+# a: define b
+# @echo local
+# endef
+
+# a: ; $(b)
+# ',
+#               '', "local\n");
 
 1;
Index: /trunk/src/kmk/tests/scripts/features/vpath
===================================================================
--- /trunk/src/kmk/tests/scripts/features/vpath	(revision 2590)
+++ /trunk/src/kmk/tests/scripts/features/vpath	(revision 2591)
@@ -1,2 +1,4 @@
+#                                                                     -*-perl-*-
+
 $description = "The following test creates a makefile to test the \n"
               ."vpath directive which allows you to specify a search \n"
@@ -61,3 +63,20 @@
 }
 
+# TEST 2: after vpath lookup ensure we don't get incorrect circular dependency
+# warnings due to change of struct file ptr.  Savannah bug #13529.
+
+mkdir('vpath-d', 0777);
+
+run_make_test(q!
+vpath %.te vpath-d/
+.SECONDARY:
+default: vpath-d/a vpath-d/b
+vpath-d/a: fail.te
+vpath-d/b : fail.te
+vpath-d/fail.te:
+!,
+              '', "#MAKE#: Nothing to be done for `default'.\n");
+
+rmdir('vpath-d');
+
 1;
Index: /trunk/src/kmk/tests/scripts/features/vpath3
===================================================================
--- /trunk/src/kmk/tests/scripts/features/vpath3	(revision 2591)
+++ /trunk/src/kmk/tests/scripts/features/vpath3	(revision 2591)
@@ -0,0 +1,50 @@
+#                                                                     -*-perl-*-
+
+$description = "Test the interaction of the -lfoo feature and vpath";
+$details = "";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "vpath %.a a1\n";
+print MAKEFILE "vpath %.so b1\n";
+print MAKEFILE "vpath % a2 b2\n";
+print MAKEFILE "vpath % b3\n";
+print MAKEFILE "all: -l1 -l2 -l3; \@echo \$^\n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+mkdir("a1", 0777);
+mkdir("b1", 0777);
+mkdir("a2", 0777);
+mkdir("b2", 0777);
+mkdir("b3", 0777);
+
+@files_to_touch = ("a1${pathsep}lib1.a",
+		   "b1${pathsep}lib1.so",
+		   "a2${pathsep}lib2.a",
+		   "b2${pathsep}lib2.so",
+		   "lib3.a",
+		   "b3${pathsep}lib3.so");
+
+&touch(@files_to_touch);
+
+&run_make_with_options($makefile,"",&get_logfile);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "a1${pathsep}lib1.a a2${pathsep}lib2.a lib3.a\n";
+
+if (&compare_output($answer,&get_logfile(1)))
+{
+  unlink @files_to_touch;
+  rmdir("a1");
+  rmdir("b1");
+  rmdir("a2");
+  rmdir("b2");
+  rmdir("b3");
+}
+
+1;
Index: /trunk/src/kmk/tests/scripts/functions/shell
===================================================================
--- /trunk/src/kmk/tests/scripts/functions/shell	(revision 2590)
+++ /trunk/src/kmk/tests/scripts/functions/shell	(revision 2591)
@@ -12,4 +12,13 @@
 
 
+# Test unescaped comment characters in shells.  Savannah bug #20513
+if ($all_tests) {
+    run_make_test(q!
+FOO := $(shell echo '#')
+foo: ; echo '$(FOO)'
+!,
+              '', "#\n");
+}
+
 # Test shells inside exported environment variables.
 # This is the test that fails if we try to put make exported variables into
Index: /trunk/src/kmk/tests/scripts/functions/wildcard
===================================================================
--- /trunk/src/kmk/tests/scripts/functions/wildcard	(revision 2590)
+++ /trunk/src/kmk/tests/scripts/functions/wildcard	(revision 2591)
@@ -82,13 +82,10 @@
 &compare_output($answer,&get_logfile(1));
 
+# TEST #4: Verify that failed wildcards don't return the pattern
+
+run_make_test(q!
+all: ; @echo $(wildcard xz--y*.7)
+!,
+              '', "\n");
 
 1;
-
-
-
-
-
-
-
-
-
Index: /trunk/src/kmk/tests/scripts/misc/general4
===================================================================
--- /trunk/src/kmk/tests/scripts/misc/general4	(revision 2590)
+++ /trunk/src/kmk/tests/scripts/misc/general4	(revision 2591)
@@ -30,18 +30,4 @@
 !$is_kmk ? 0 : 512);
 unlink('foo.c');
-
-
-# Test other implicit rule searching
-
-&touch('bar');
-run_make_test('
-test.foo:
-%.foo : baz ; @echo done $<
-%.foo : bar ; @echo done $<
-fox: baz
-',
-              '',
-              'done bar');
-unlink('bar');
 
 
@@ -84,3 +70,16 @@
               '', "mkdir -p dir/subdir\ntouch dir/subdir/file.\$b\ncp dir/subdir/file.\$b dir/subdir/file.\$a\n");
 
+# Test odd whitespace at the beginning of a line
+
+run_make_test("
+all:
+   \f
+
+    \\
+ \f  \\
+    \013 \\
+all: ; \@echo hi
+",
+              '', "hi\n");
+
 1;
Index: /trunk/src/kmk/tests/scripts/options/dash-B
===================================================================
--- /trunk/src/kmk/tests/scripts/options/dash-B	(revision 2590)
+++ /trunk/src/kmk/tests/scripts/options/dash-B	(revision 2591)
@@ -71,3 +71,15 @@
 rmfiles('foo.x', 'blah.x');
 
+# Test that $? is set properly with -B; all prerequisites will be newer!
+
+utouch(-10, 'x.b');
+touch('x.a');
+
+run_make_test(q!
+x.a: x.b ; @echo $?
+!,
+              '-B', "x.b\n");
+
+unlink(qw(x.a x.b));
+
 1;
Index: /trunk/src/kmk/tests/scripts/options/eval
===================================================================
--- /trunk/src/kmk/tests/scripts/options/eval	(revision 2591)
+++ /trunk/src/kmk/tests/scripts/options/eval	(revision 2591)
@@ -0,0 +1,19 @@
+#                                                                    -*-perl-*-
+
+$description = "Test the --eval option.";
+
+$details = "Verify that --eval options take effect,
+and are passed to sub-makes.";
+
+# Verify that --eval is evaluated first
+run_make_test(q!
+BAR = bar
+all: ; @echo all
+recurse: ; @$(MAKE) -f #MAKEFILE# && echo recurse!,
+              '--eval=\$\(info\ eval\) FOO=\$\(BAR\)', "eval\nall");
+
+# Make sure that --eval is handled correctly during recursion
+run_make_test(undef, '--no-print-directory --eval=\$\(info\ eval\) recurse',
+              "eval\neval\nall\nrecurse");
+
+1;
Index: /trunk/src/kmk/tests/scripts/targets/ONESHELL
===================================================================
--- /trunk/src/kmk/tests/scripts/targets/ONESHELL	(revision 2591)
+++ /trunk/src/kmk/tests/scripts/targets/ONESHELL	(revision 2591)
@@ -0,0 +1,69 @@
+#                                                                    -*-perl-*-
+
+$description = "Test the behaviour of the .ONESHELL target.";
+
+$details = "";
+
+
+# Simple
+
+run_make_test(q!
+.ONESHELL:
+all:
+	a=$$$$
+	[ 0"$$a" -eq "$$$$" ] || echo fail
+!,
+              '', 'a=$$
+[ 0"$a" -eq "$$" ] || echo fail
+');
+
+# Again, but this time with inner prefix chars
+
+run_make_test(q!
+.ONESHELL:
+all:
+	a=$$$$
+	@-+    [ 0"$$a" -eq "$$$$" ] || echo fail
+!,
+              '', 'a=$$
+[ 0"$a" -eq "$$" ] || echo fail
+');
+
+# This time with outer prefix chars
+
+run_make_test(q!
+.ONESHELL:
+all:
+	   @a=$$$$
+	    [ 0"$$a" -eq "$$$$" ] || echo fail
+!,
+              '', '');
+
+
+# This time with outer and inner prefix chars
+
+run_make_test(q!
+.ONESHELL:
+all:
+	   @a=$$$$
+	    -@     +[ 0"$$a" -eq "$$$$" ] || echo fail
+!,
+              '', '');
+
+
+# Now try using a different interpreter
+
+run_make_test(q!
+.RECIPEPREFIX = >
+.ONESHELL:
+SHELL = #PERL#
+.SHELLFLAGS = -e
+all:
+>	   @$$a=5
+>	    +7;
+>	@y=qw(a b c);
+>print "a = $$a, y = (@y)\n";
+!,
+              '', "a = 12, y = (a b c)\n");
+
+1;
Index: /trunk/src/kmk/tests/scripts/targets/POSIX
===================================================================
--- /trunk/src/kmk/tests/scripts/targets/POSIX	(revision 2591)
+++ /trunk/src/kmk/tests/scripts/targets/POSIX	(revision 2591)
@@ -0,0 +1,33 @@
+#                                                                    -*-perl-*-
+
+$description = "Test the behaviour of the .PHONY target.";
+
+$details = "";
+
+
+# Ensure turning on .POSIX enables the -e flag for the shell
+# We can't assume the exit value of "false" because on different systems it's
+# different.
+
+my $script = 'false; true';
+my $flags = '-ec';
+my $out = `/bin/sh $flags '$script' 2>&1`;
+my $err = $? >> 8;
+run_make_test(qq!
+.POSIX:
+all: ; \@$script
+!,
+              '', "#MAKE#: *** [all] Error $err\n", 512);
+
+# User settings must override .POSIX
+$flags = '-xc';
+$out = `/bin/sh $flags '$script' 2>&1`;
+run_make_test(qq!
+.SHELLFLAGS = $flags
+.POSIX:
+all: ; \@$script
+!,
+              '', $out);
+
+# This tells the test driver that the perl test script executed properly.
+1;
Index: /trunk/src/kmk/tests/scripts/variables/DEFAULT_GOAL
===================================================================
--- /trunk/src/kmk/tests/scripts/variables/DEFAULT_GOAL	(revision 2590)
+++ /trunk/src/kmk/tests/scripts/variables/DEFAULT_GOAL	(revision 2591)
@@ -74,4 +74,13 @@
 'foo');
 
+# TEST #5: .DEFAULT_GOAL containing just whitespace (Savannah bug #25697)
+
+run_make_test('
+N =
+.DEFAULT_GOAL = $N  $N  # Just whitespace
+
+foo: ; @echo "boo"
+',
+              '', "#MAKE#: *** No targets.  Stop.\n", 512);
 
 # This tells the test driver that the perl test script executed properly.
Index: /trunk/src/kmk/tests/scripts/variables/LIBPATTERNS
===================================================================
--- /trunk/src/kmk/tests/scripts/variables/LIBPATTERNS	(revision 2591)
+++ /trunk/src/kmk/tests/scripts/variables/LIBPATTERNS	(revision 2591)
@@ -0,0 +1,38 @@
+#                                                                    -*-perl-*-
+
+$description = "Test .LIBPATTERNS special variable.";
+
+$details = "";
+
+# TEST 0: basics
+
+touch('mtest_foo.a');
+
+run_make_test('
+.LIBPATTERNS = mtest_%.a
+all: -lfoo ; @echo "build $@ from $<"
+',
+              '', "build all from mtest_foo.a\n");
+
+# TEST 1: Handle elements that are not patterns.
+
+run_make_test('
+.LIBPATTERNS = mtest_foo.a mtest_%.a
+all: -lfoo ; @echo "build $@ from $<"
+',
+              '', "#MAKE#: .LIBPATTERNS element `mtest_foo.a' is not a pattern
+build all from mtest_foo.a\n");
+
+# TEST 2: target-specific override
+
+# Uncomment this when we add support, see Savannah bug #25703
+# run_make_test('
+# .LIBPATTERNS = mbad_%.a
+# all: .LIBPATTERNS += mtest_%.a
+# all: -lfoo ; @echo "build $@ from $<"
+# ',
+#               '', "build all from mtest_foo.a\n");
+
+unlink('mtest_foo.a');
+
+1;
Index: /trunk/src/kmk/tests/scripts/variables/MAKE
===================================================================
--- /trunk/src/kmk/tests/scripts/variables/MAKE	(revision 2590)
+++ /trunk/src/kmk/tests/scripts/variables/MAKE	(revision 2591)
@@ -1,35 +1,24 @@
 #								     -*-perl-*-
 
-$description = "The following test creates a makefile to test MAKE \n"
-              ."(very generic)";
+$description = "Test proper behavior of the MAKE variable";
 
 $details = "DETAILS";
 
-open(MAKEFILE,"> $makefile");
+run_make_test(q!
+TMP  := $(MAKE)
+MAKE := $(subst X=$(X),,$(MAKE))
+all:
+	@echo $(TMP)
+	$(MAKE) -f #MAKEFILE# foo
 
-# The Contents of the MAKEFILE ...
+foo:
+	@echo $(MAKE)
+!,
+              '',
+              "#MAKEPATH#\n#MAKEPATH# -f #MAKEFILE# foo\n"
+              . "#MAKE#[1]: Entering directory `#PWD#'\n"
+              . "#MAKEPATH#\n#MAKE#[1]: Leaving directory `#PWD#'\n");
 
-print MAKEFILE "TMP  := \$(MAKE)\n";
-print MAKEFILE "MAKE := \$(subst X=\$(X),,\$(MAKE))\n\n";
-print MAKEFILE "all:\n";
-print MAKEFILE "\t\@echo \$(TMP)\n";
-print MAKEFILE "\t\$(MAKE) -f $makefile foo\n\n";
-print MAKEFILE "foo:\n";
-print MAKEFILE "\t\@echo \$(MAKE)\n";
-
-# END of Contents of MAKEFILE
-
-close(MAKEFILE);
-
-# Create the answer to what should be produced by this Makefile
-$answer = "$mkpath\n$mkpath -f $makefile foo\n"
-	. "${make_name}[1]: Entering directory `$pwd'\n"
-	. "$mkpath\n${make_name}[1]: Leaving directory `$pwd'\n";
-
-&run_make_with_options($makefile,"",&get_logfile,0);
-
-&rmfiles("foo");
-# COMPARE RESULTS
-&compare_output($answer,&get_logfile(1));
+rmfiles("foo");
 
 1;
Index: /trunk/src/kmk/tests/scripts/variables/MAKEFILES
===================================================================
--- /trunk/src/kmk/tests/scripts/variables/MAKEFILES	(revision 2590)
+++ /trunk/src/kmk/tests/scripts/variables/MAKEFILES	(revision 2591)
@@ -32,3 +32,22 @@
 &compare_output($answer,&get_logfile(1));
 
+# TEST 2: Verify that included makefiles don't set the default goal.
+# See Savannah bug #13401.
+
+create_file('xx-inc.mk', '
+include_goal: ; @echo $@
+include xx-ind.mk
+');
+
+create_file('xx-ind.mk', '
+indirect_goal: ; @echo $@
+');
+
+run_make_test(q!
+top: ; @echo $@
+!,
+              'MAKEFILES=xx-inc.mk', "top\n");
+
+unlink(qw(xx-inc.mk xx-ind.mk));
+
 1;
Index: /trunk/src/kmk/tests/scripts/variables/MAKEFLAGS
===================================================================
--- /trunk/src/kmk/tests/scripts/variables/MAKEFLAGS	(revision 2591)
+++ /trunk/src/kmk/tests/scripts/variables/MAKEFLAGS	(revision 2591)
@@ -0,0 +1,43 @@
+#								     -*-perl-*-
+
+$description = "Test proper behavior of MAKEFLAGS";
+
+$details = "DETAILS";
+
+# Normal flags aren't prefixed with "-"
+run_make_test(q!
+all: ; @echo $(MAKEFLAGS)
+!,
+              '-e -r -R', 'Rre');
+
+# Long arguments mean everything is prefixed with "-"
+run_make_test(q!
+all: ; @echo $(MAKEFLAGS)
+!,
+              '--no-print-directory -e -r -R', '--no-print-directory -Rre');
+
+
+if ($all_tests) {
+    # Recursive invocations of make should accumulate MAKEFLAGS values.
+    # Savannah bug #2216
+    run_make_test(q!
+MSG = Fails
+all:
+	@echo '$@: MAKEFLAGS=$(MAKEFLAGS)'
+	@MSG=Works $(MAKE) -e -f #MAKEFILE# jump
+jump:
+	@echo '$@: MAKEFLAGS=$(MAKEFLAGS)'
+	@$(MAKE) -f #MAKEFILE# print
+print:
+	@echo '$@: MAKEFLAGS=$(MAKEFLAGS)'
+	@echo $(MSG)
+.PHONY: all jump print
+!,
+                  '--no-print-directory',
+                  'all: MAKEFLAGS= --no-print-directory
+jump: MAKEFLAGS= --no-print-directory -e
+print: MAKEFLAGS= --no-print-directory -e
+Works');
+}
+
+1;
Index: /trunk/src/kmk/tests/scripts/variables/SHELL
===================================================================
--- /trunk/src/kmk/tests/scripts/variables/SHELL	(revision 2590)
+++ /trunk/src/kmk/tests/scripts/variables/SHELL	(revision 2591)
@@ -50,8 +50,38 @@
 $extraENV{SHELL} = $mshell;
 
-# bird: This was wrong, see Savannah bug #24655. Fixed in kBuild.
-run_make_test("all: export SHELL := /./$mshell\n".'
-all:;@echo "$(SHELL) $$SHELL"
-', '', "/./$mshell /./$mshell");
+# bird: This was wrong at some point, see Savannah bug #24655. Was first fixed in kBuild.
+run_make_test("
+SHELL := /././$mshell
+one: two
+two: export SHELL := /./$mshell\n".'
+one two:;@echo "$@: $(SHELL) $$SHELL"
+', '', "two: /./$mshell /./$mshell\none: /././$mshell $mshell\n");
+
+# Test .SHELLFLAGS
+
+# We don't know the output here: on Solaris for example, every line printed
+# by the shell in -x mode has a trailing space (!!)
+my $script = 'true; true';
+my $flags = '-xc';
+my $out = `/bin/sh $flags '$script' 2>&1`;
+
+run_make_test(qq!
+.SHELLFLAGS = $flags
+all: ; \@$script
+!,
+              '', $out);
+
+# We can't just use "false" because on different systems it provides a
+# different exit code--once again Solaris: false exits with 255 not 1
+$script = 'true; false; true';
+$flags = '-xec';
+$out = `/bin/sh $flags '$script' 2>&1`;
+my $err = $? >> 8;
+
+run_make_test(qq!
+.SHELLFLAGS = $flags
+all: ; \@$script
+!,
+              '', "$out#MAKE#: *** [all] Error $err\n", 512);
 
 1;
Index: /trunk/src/kmk/tests/scripts/variables/automatic
===================================================================
--- /trunk/src/kmk/tests/scripts/variables/automatic	(revision 2590)
+++ /trunk/src/kmk/tests/scripts/variables/automatic	(revision 2591)
@@ -108,3 +108,15 @@
 unlink('foo');
 
+# TEST #4: ensure prereq ordering is correct when the commmand target has none
+# See Savannah bug #21198
+
+run_make_test('
+all : A B
+all : ; @echo $@ -- $^ -- $<
+all : C D
+all : E F
+A B C D E F G H : ; @:
+',
+              '', "all -- A B C D E F -- A\n");
+
 1;
Index: /trunk/src/kmk/tests/scripts/variables/define
===================================================================
--- /trunk/src/kmk/tests/scripts/variables/define	(revision 2591)
+++ /trunk/src/kmk/tests/scripts/variables/define	(revision 2591)
@@ -0,0 +1,234 @@
+#                                                                    -*-perl-*-
+
+$description = "Test define/endef variable assignments.";
+
+$details = "";
+
+# TEST 0: old-style basic define/endef
+
+run_make_test('
+define multi
+@echo hi
+echo there
+endef
+
+all: ; $(multi)
+',
+              '', "hi\necho there\nthere\n");
+
+# TEST 1: Various new-style define/endef
+
+run_make_test('
+FOO = foo
+
+define multi =
+echo hi
+@echo $(FOO)
+endef # this is the end
+
+define simple :=
+@echo $(FOO)
+endef
+
+append = @echo a
+
+define append +=
+
+@echo b
+endef
+
+define cond ?= # this is a conditional
+@echo first
+endef
+
+define cond ?=
+@echo second
+endef
+
+FOO = there
+
+all: ; $(multi)
+	$(simple)
+	$(append)
+	$(cond)
+',
+              '', "echo hi\nhi\nthere\nfoo\na\nb\nfirst\n");
+
+# TEST 2: define in true section of conditional (containing conditional)
+
+run_make_test('
+FOO = foo
+NAME = def
+def =
+ifdef BOGUS
+ define  $(subst e,e,$(NAME))     =
+  ifeq (1,1)
+   FOO = bar
+  endif
+ endef
+endif
+
+$(eval $(def))
+all: ; @echo $(FOO)
+',
+              'BOGUS=1', "bar\n");
+
+# TEST 3: define in false section of conditional (containing conditional)
+
+run_make_test(undef, '', "foo\n");
+
+# TEST 4: nested define (supported?)
+
+run_make_test('
+define outer
+ define inner
+  A = B
+ endef
+endef
+
+$(eval $(outer))
+
+outer: ; @echo $(inner)
+',
+              '', "A = B\n");
+
+# TEST 5: NEGATIVE: Missing variable name
+
+run_make_test('
+NAME =
+define $(NAME)  =
+ouch
+endef
+all: ; @echo ouch
+',
+              '', "#MAKEFILE#:3: *** empty variable name.  Stop.\n", 512);
+
+# TEST 6: NEGATIVE: extra text after define
+
+run_make_test('
+NAME =
+define NAME = $(NAME)
+ouch
+endef
+all: ; @echo ok
+',
+              '', "#MAKEFILE#:3: extraneous text after `define' directive\nok\n");
+
+# TEST 7: NEGATIVE: extra text after endef
+
+run_make_test('
+NAME =
+define NAME =
+ouch
+endef $(NAME)
+all: ; @echo ok
+',
+              '', "#MAKEFILE#:5: extraneous text after `endef' directive\nok\n");
+
+# TEST 8: NEGATIVE: missing endef
+
+run_make_test('
+NAME =
+all: ; @echo ok
+define NAME =
+ouch
+endef$(NAME)
+',
+              '', "#MAKEFILE#:4: *** missing `endef', unterminated `define'.  Stop.\n", 512);
+
+# -------------------------
+# Make sure that prefix characters apply properly to define/endef values.
+#
+# There's a bit of oddness here if you try to use a variable to hold the
+# prefix character for a define.  Even though something like this:
+#
+#       define foo
+#       echo bar
+#       endef
+#
+#       all: ; $(V)$(foo)
+#
+# (where V=@) can be seen by the user to be obviously different than this:
+#
+#       define foo
+#       $(V)echo bar
+#       endef
+#
+#       all: ; $(foo)
+#
+# and the user thinks it should behave the same as when the "@" is literal
+# instead of in a variable, that can't happen because by the time make
+# expands the variables for the command line and sees it begins with a "@" it
+# can't know anymore whether the prefix character came before the variable
+# reference or was included in the first line of the variable reference.
+
+# TEST #5
+# -------
+
+run_make_test('
+define FOO
+$(V1)echo hello
+$(V2)echo world
+endef
+all: ; @$(FOO)
+', '', 'hello
+world');
+
+# TEST #6
+# -------
+
+run_make_test(undef, 'V1=@ V2=@', 'hello
+world');
+
+# TEST #7
+# -------
+
+run_make_test('
+define FOO
+$(V1)echo hello
+$(V2)echo world
+endef
+all: ; $(FOO)
+', 'V1=@', 'hello
+echo world
+world');
+
+# TEST #8
+# -------
+
+run_make_test(undef, 'V2=@', 'echo hello
+hello
+world');
+
+# TEST #9
+# -------
+
+run_make_test(undef, 'V1=@ V2=@', 'hello
+world');
+
+# TEST #10
+# -------
+# Test the basics; a "@" internally to the variable applies to only one line.
+# A "@" before the variable applies to the entire variable.
+
+run_make_test('
+define FOO
+@echo hello
+echo world
+endef
+define BAR
+echo hello
+echo world
+endef
+
+all: foo bar
+foo: ; $(FOO)
+bar: ; @$(BAR)
+', '', 'hello
+echo world
+world
+hello
+world
+');
+
+1;
Index: /trunk/src/kmk/tests/scripts/variables/flavors
===================================================================
--- /trunk/src/kmk/tests/scripts/variables/flavors	(revision 2590)
+++ /trunk/src/kmk/tests/scripts/variables/flavors	(revision 2591)
@@ -5,179 +5,72 @@
 $details = "";
 
-open(MAKEFILE, "> $makefile");
+# TEST 0: Recursive
 
-# The Contents of the MAKEFILE ...
-
-print MAKEFILE <<'EOF';
+run_make_test('
+ugh = Goodbye
 foo = $(bar)
 bar = ${ugh}
 ugh = Hello
+all: ; @echo $(foo)
+',
+              '', "Hello\n");
 
-all: multi ; @echo $(foo)
-
-multi: ; $(multi)
-
-x := foo
-y := $(x) bar
-x := later
-
-nullstring :=
-space := $(nullstring) $(nullstring)
-
-next: ; @echo $x$(space)$y
-
-define multi
-@echo hi
-echo there
-endef
-
-ifdef BOGUS
-define
-@echo error
-endef
-endif
-
-define outer
- define inner
-  A = B
- endef
-endef
-
-$(eval $(outer))
-
-outer: ; @echo $(inner)
-
-EOF
-
-# END of Contents of MAKEFILE
-
-close(MAKEFILE);
-
-# TEST #1
-# -------
-
-&run_make_with_options($makefile, "", &get_logfile);
-$answer = "hi\necho there\nthere\nHello\n";
-&compare_output($answer, &get_logfile(1));
-
-# TEST #2
-# -------
-
-&run_make_with_options($makefile, "next", &get_logfile);
-$answer = "later foo bar\n";
-&compare_output($answer, &get_logfile(1));
-
-# TEST #3
-# -------
-
-&run_make_with_options($makefile, "BOGUS=true", &get_logfile, 512);
-$answer = "$makefile:24: *** empty variable name.  Stop.\n";
-&compare_output($answer, &get_logfile(1));
-
-# TEST #4
-# -------
-
-&run_make_with_options($makefile, "outer", &get_logfile);
-$answer = "A = B\n";
-&compare_output($answer, &get_logfile(1));
-
-# Clean up from "old style" testing.  If all the above tests are converted to
-# run_make_test() syntax than this line can be removed.
-$makefile = undef;
-
-# -------------------------
-# Make sure that prefix characters apply properly to define/endef values.
-#
-# There's a bit of oddness here if you try to use a variable to hold the
-# prefix character for a define.  Even though something like this:
-#
-#       define foo
-#       echo bar
-#       endef
-#
-#       all: ; $(V)$(foo)
-#
-# (where V=@) can be seen by the user to be obviously different than this:
-#
-#       define foo
-#       $(V)echo bar
-#       endef
-#
-#       all: ; $(foo)
-#
-# and the user thinks it should behave the same as when the "@" is literal
-# instead of in a variable, that can't happen because by the time make
-# expands the variables for the command line and sees it begins with a "@" it
-# can't know anymore whether the prefix character came before the variable
-# reference or was included in the first line of the variable reference.
-
-# TEST #5
-# -------
+# TEST 1: Simple
 
 run_make_test('
-define FOO
-$(V1)echo hello
-$(V2)echo world
-endef
-all: ; @$(FOO)
-', '', 'hello
-world');
+bar = Goodbye
+foo := $(bar)
+bar = ${ugh}
+ugh = Hello
+all: ; @echo $(foo)
+',
+              '', "Goodbye\n");
 
-# TEST #6
-# -------
-
-run_make_test(undef, 'V1=@ V2=@', 'hello
-world');
-
-# TEST #7
-# -------
+# TEST 2: Append to recursive
 
 run_make_test('
-define FOO
-$(V1)echo hello
-$(V2)echo world
-endef
-all: ; $(FOO)
-', 'V1=@', 'hello
-echo world
-world');
+foo = Hello
+ugh = Goodbye
+foo += $(bar)
+bar = ${ugh}
+ugh = Hello
+all: ; @echo $(foo)
+',
+              '', "Hello Hello\n");
 
-# TEST #8
-# -------
-
-run_make_test(undef, 'V2=@', 'echo hello
-hello
-world');
-
-# TEST #9
-# -------
-
-run_make_test(undef, 'V1=@ V2=@', 'hello
-world');
-
-# TEST #10
-# -------
-# Test the basics; a "@" internally to the variable applies to only one line.
-# A "@" before the variable applies to the entire variable.
+# TEST 3: Append to simple
 
 run_make_test('
-define FOO
-@echo hello
-echo world
-endef
-define BAR
-echo hello
-echo world
-endef
+foo := Hello
+ugh = Goodbye
+bar = ${ugh}
+foo += $(bar)
+ugh = Hello
+all: ; @echo $(foo)
+',
+              '', "Hello Goodbye\n");
 
-all: foo bar
-foo: ; $(FOO)
-bar: ; @$(BAR)
-', '-j1', 'hello
-echo world
-world
-hello
-world
-');
+# TEST 4: Conditional pre-set
+
+run_make_test('
+foo = Hello
+ugh = Goodbye
+bar = ${ugh}
+foo ?= $(bar)
+ugh = Hello
+all: ; @echo $(foo)
+',
+              '', "Hello\n");
+
+# TEST 5: Conditional unset
+
+run_make_test('
+ugh = Goodbye
+bar = ${ugh}
+foo ?= $(bar)
+ugh = Hello
+all: ; @echo $(foo)
+',
+              '', "Hello\n");
 
 1;
Index: /trunk/src/kmk/tests/scripts/variables/private
===================================================================
--- /trunk/src/kmk/tests/scripts/variables/private	(revision 2591)
+++ /trunk/src/kmk/tests/scripts/variables/private	(revision 2591)
@@ -0,0 +1,78 @@
+#                                                                    -*-perl-*-
+
+$description = "Test 'private' variables.";
+
+$details = "";
+
+# 1: Simple verification that private variables are not inherited
+&run_make_test('
+a:
+F = g
+a: F = a
+b: private F = b
+
+a b c: ; @echo $@: F=$(F)
+a: b
+b: c
+',
+              '', "c: F=a\nb: F=b\na: F=a\n");
+
+# 2: Again, but this time we start with "b" so "a"'s variable is not in scope
+&run_make_test(undef, 'b', "c: F=g\nb: F=b\n");
+
+# 3: Verification with pattern-specific variables
+&run_make_test('
+t.a:
+
+F1 = g
+F2 = g
+%.a: private F1 = a
+%.a: F2 = a
+
+t.a t.b: ; @echo $@: F1=$(F1) / F2=$(F2)
+t.a: t.b
+',
+               '', "t.b: F1=g / F2=a\nt.a: F1=a / F2=a\n");
+
+# 4: Test private global variables
+&run_make_test('
+a:
+private F = g
+G := $(F)
+a:
+b: F = b
+
+a b: ; @echo $@: F=$(F) / G=$(G)
+a: b
+',
+               '', "b: F=b / G=g\na: F= / G=g\n");
+
+# 5: Multiple conditions on the same variable.  Test export.
+delete $ENV{'_X'};
+&run_make_test('
+_X = x
+a: export override private _X = a
+a: ; @echo _X=$(_X) / _X=$$_X
+',
+               '', "_X=a / _X=a");
+
+# 6: Test override.
+&run_make_test(undef, '_X=c', "_X=a / _X=a\n");
+
+# 7: Ensure keywords still work as targets
+&run_make_test('
+a: export override private foo bar
+foo bar export override private: ; @echo $@
+',
+               '', "export\noverride\nprivate\nfoo\nbar\n");
+
+# 8: Ensure keywords still work as variables
+&run_make_test('
+private = g
+a: private = a
+a: b
+a b: ; @echo $@=$(private)
+',
+               '', "b=a\na=a\n");
+
+1;
Index: /trunk/src/kmk/tests/scripts/variables/undefine
===================================================================
--- /trunk/src/kmk/tests/scripts/variables/undefine	(revision 2591)
+++ /trunk/src/kmk/tests/scripts/variables/undefine	(revision 2591)
@@ -0,0 +1,73 @@
+#                                                                    -*-perl-*-
+
+$description = "Test variable undefine.";
+
+$details = "";
+
+# TEST 0: basic undefine functionality
+
+run_make_test('
+a = a
+b := b
+define c
+c
+endef
+
+$(info $(flavor a) $(flavor b) $(flavor c))
+
+n := b
+
+undefine a
+undefine $n
+undefine c
+
+$(info $(flavor a) $(flavor b) $(flavor c))
+
+
+all: ;@:
+',
+'', "recursive simple recursive\nundefined undefined undefined");
+
+
+# TEST 1: override
+
+run_make_test('
+undefine a
+override undefine b
+
+$(info $(flavor a) $(flavor b))
+
+
+all: ;@:
+',
+'a=a b=b', "recursive undefined");
+
+1;
+
+# TEST 2: undefine in eval (make sure we undefine from the global var set)
+
+run_make_test('
+define undef
+$(eval undefine $$1)
+endef
+
+a := a
+$(call undef,a)
+$(info $(flavor a))
+
+
+all: ;@:
+',
+'', "undefined");
+
+
+# TEST 3: Missing variable name
+
+run_make_test('
+a =
+undefine $a
+all: ;@echo ouch
+',
+'', "#MAKEFILE#:3: *** empty variable name.  Stop.\n", 512);
+
+1;
Index: /trunk/src/kmk/tests/test_driver.pl
===================================================================
--- /trunk/src/kmk/tests/test_driver.pl	(revision 2590)
+++ /trunk/src/kmk/tests/test_driver.pl	(revision 2591)
@@ -7,5 +7,6 @@
 #
 # Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-# 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+# 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
+# Foundation, Inc.
 # This file is part of GNU Make.
 #
@@ -30,5 +31,5 @@
 # variables and then calls &toplevel, which does all the real work.
 
-# $Id: test_driver.pl,v 1.24 2007/11/04 21:54:02 psmith Exp $
+# $Id: test_driver.pl,v 1.30 2010/07/28 05:39:50 psmith Exp $
 
 
@@ -54,4 +55,6 @@
 $test_timeout = 5;
 
+# Path to Perl
+$perl_name = $^X;
 
 # %makeENV is the cleaned-out environment.
@@ -239,6 +242,7 @@
 {
   # Set up an initial value.  In perl5 we can do it the easy way.
-  #
   $osname = defined($^O) ? $^O : '';
+
+  # Find a path to Perl
 
   # See if the filesystem supports long file names with multiple
@@ -276,5 +280,5 @@
     if ($osname =~ /not found/i)
     {
-	$osname = "(something unixy with no uname)";
+	$osname = "(something posixy with no uname)";
     }
     elsif ($@ ne "" || $?)
@@ -283,5 +287,5 @@
         if ($@ ne "" || $?)
         {
-	    $osname = "(something unixy)";
+	    $osname = "(something posixy)";
 	}
     }
@@ -460,4 +464,5 @@
       $diffext = 'd';
       $baseext = 'b';
+      $runext = 'r';
       $extext = '';
     } else {
@@ -465,4 +470,5 @@
       $diffext = 'diff';
       $baseext = 'base';
+      $runext = 'run';
       $extext = '.';
     }
@@ -470,4 +476,5 @@
     $diff_filename = "$testpath.$diffext";
     $base_filename = "$testpath.$baseext";
+    $run_filename = "$testpath.$runext";
     $tmp_filename = "$testpath.$tmpfilesuffix";
 
@@ -483,4 +490,5 @@
     $tests_run = 0;
     $tests_passed = 0;
+
     $code = do $perl_testname;
 
@@ -716,4 +724,5 @@
 
     &create_file (&get_basefile, $answer);
+    &create_file (&get_runfile, $command_string);
 
     print "\nCreating Difference File ...\n" if $debug;
@@ -723,4 +732,6 @@
     local($command) = "diff -c " . &get_basefile . " " . $logfile;
     &run_command_with_output(&get_difffile,$command);
+  } else {
+      &rmfiles ();
   }
 
@@ -816,5 +827,5 @@
       local $SIG{ALRM} = sub { die "timeout\n"; };
       alarm $test_timeout;
-      $code = system @_;
+      $code = system(@_);
       alarm 0;
   };
@@ -853,5 +864,5 @@
   my $filename = shift;
 
-  print "\nrun_command_with_output($filename): @_\n" if $debug;
+  print "\nrun_command_with_output($filename,$runname): @_\n" if $debug;
   &attach_default_output ($filename);
   my $code = _run_command(@_);
@@ -1226,4 +1237,13 @@
 }
 
+# This subroutine returns a command filename with a number appended
+# to the end corresponding to how many logfiles (and thus command files)
+# have been created in the current running test.
+
+sub get_runfile
+{
+  return ($run_filename . &num_suffix ($num_of_logfiles));
+}
+
 # just like logfile, only a generic tmp filename for use by the test.
 # they are automatically cleaned up unless -keep was used, or the test fails.
Index: /trunk/src/kmk/variable.c
===================================================================
--- /trunk/src/kmk/variable.c	(revision 2590)
+++ /trunk/src/kmk/variable.c	(revision 2591)
@@ -1,6 +1,6 @@
 /* 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 Free Software
-Foundation, Inc.
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
@@ -47,25 +47,59 @@
 static struct pattern_var *pattern_vars;
 
-/* Pointer to last struct in the chain, so we can add onto the end.  */
-
-static struct pattern_var *last_pattern_var;
-
-/* Create a new pattern-specific variable struct.  */
+/* Pointer to the last struct in the pack of a specific size, from 1 to 255.*/
+
+static struct pattern_var *last_pattern_vars[256];
+
+/* Create a new pattern-specific variable struct. The new variable is
+   inserted into the PATTERN_VARS list in the shortest patterns first
+   order to support the shortest stem matching (the variables are
+   matched in the reverse order so the ones with the longest pattern
+   will be considered first). Variables with the same pattern length
+   are inserted in the definition order. */
 
 struct pattern_var *
 create_pattern_var (const char *target, const char *suffix)
 {
+  register unsigned int len = strlen (target);
   register struct pattern_var *p = xmalloc (sizeof (struct pattern_var));
 
-  if (last_pattern_var != 0)
-    last_pattern_var->next = p;
+  if (pattern_vars != 0)
+    {
+      if (len < 256 && last_pattern_vars[len] != 0)
+        {
+          p->next = last_pattern_vars[len]->next;
+          last_pattern_vars[len]->next = p;
+        }
+      else
+        {
+          /* Find the position where we can insert this variable. */
+          register struct pattern_var **v;
+
+          for (v = &pattern_vars; ; v = &(*v)->next)
+            {
+              /* Insert at the end of the pack so that patterns with the
+                 same length appear in the order they were defined .*/
+
+              if (*v == 0 || (*v)->len > len)
+                {
+                  p->next = *v;
+                  *v = p;
+                  break;
+                }
+            }
+        }
+    }
   else
-    pattern_vars = p;
-  last_pattern_var = p;
-  p->next = 0;
+    {
+      pattern_vars = p;
+      p->next = 0;
+    }
 
   p->target = target;
-  p->len = strlen (target);
+  p->len = len;
   p->suffix = suffix + 1;
+
+  if (len < 256)
+    last_pattern_vars[len] = p;
 
   return p;
@@ -170,5 +204,5 @@
 static struct variable_set global_variable_set;
 static struct variable_set_list global_setlist
-  = { 0, &global_variable_set };
+  = { 0, &global_variable_set, 0 };
 struct variable_set_list *current_variable_set_list = &global_setlist;
 
@@ -344,5 +378,5 @@
 #endif
 #ifndef CONFIG_WITH_STRCACHE2
-  v->name = savestring (name, length);
+  v->name = xstrndup (name, length);
 #else
   v->name = name; /* already cached. */
@@ -387,4 +421,5 @@
   v->per_target = 0;
   v->append = 0;
+  v->private_var = 0;
   v->export = v_default;
   MAKE_STATS_2(v->changes = 0);
@@ -414,4 +449,49 @@
 }
 
+
+
+/* Undefine variable named NAME in SET. LENGTH is the length of NAME, which
+   does not need to be null-terminated. ORIGIN specifies the origin of the
+   variable (makefile, command line or environment). */
+
+static void
+free_variable_name_and_value (const void *item);
+
+void
+undefine_variable_in_set (const char *name, unsigned int length,
+                          enum variable_origin origin,
+                          struct variable_set *set)
+{
+  struct variable *v;
+  struct variable **var_slot;
+  struct variable var_key;
+
+  if (set == NULL)
+    set = &global_variable_set;
+
+  var_key.name = (char *) name;
+  var_key.length = length;
+  var_slot = (struct variable **) hash_find_slot (&set->table, &var_key);
+
+  if (env_overrides && origin == o_env)
+    origin = o_env_override;
+
+  v = *var_slot;
+  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;
+
+      /* 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);
+	}
+    }
+}
 
 /* If the variable passed in is "special", handle its special nature.
@@ -515,5 +595,5 @@
 
 
-#ifdef KMK /* bird: speed */
+#if 0 /*FIX THIS - def KMK*/ /* bird: speed */
 MY_INLINE struct variable *
 lookup_cached_variable (const char *name)
@@ -646,5 +726,5 @@
 lookup_variable (const char *name, unsigned int length)
 {
-#ifndef KMK
+#if 1 /*FIX THIS - ndef KMK*/
   const struct variable_set_list *setlist;
   struct variable var_key;
@@ -652,4 +732,5 @@
   struct variable *v;
 #endif /* KMK */
+  int is_parent = 0;
 #ifdef CONFIG_WITH_STRCACHE2
   const char *cached_name;
@@ -662,5 +743,5 @@
   name = cached_name;
 #endif /* CONFIG_WITH_STRCACHE2 */
-#ifndef KMK
+#if 1  /*FIX THIS - ndef KMK */
 
   var_key.name = (char *) name;
@@ -678,6 +759,8 @@
       v = (struct variable *) hash_find_item_strcached ((struct hash_table *) &set->table, &var_key);
 # endif /* CONFIG_WITH_STRCACHE2 */
-      if (v)
+      if (v && (!is_parent || !v->private_var))
 	return v->special ? lookup_special_var (v) : v;
+
+      is_parent |= setlist->next_is_parent;
     }
 
@@ -747,7 +830,5 @@
 #endif /* VMS */
 
-#if !defined (KMK) || defined(VMS)
   return 0;
-#endif
 }
 
@@ -838,4 +919,5 @@
       initialize_file_variables (file->double_colon, reading);
       l->next = file->double_colon->variables;
+      l->next_is_parent = 0;
       return;
     }
@@ -848,4 +930,5 @@
       l->next = file->parent->variables;
     }
+  l->next_is_parent = 1;
 
   /* If we're not reading makefiles and we haven't looked yet, see if
@@ -900,4 +983,5 @@
               v->per_target = p->variable.per_target;
               v->export = p->variable.export;
+              v->private_var = p->variable.private_var;
             }
           while ((p = lookup_pattern_var (p, file->name)) != 0);
@@ -913,5 +997,7 @@
     {
       file->pat_variables->next = l->next;
+      file->pat_variables->next_is_parent = l->next_is_parent;
       l->next = file->pat_variables;
+      l->next_is_parent = 0;
     }
 }
@@ -949,4 +1035,5 @@
   setlist->set = set;
   setlist->next = current_variable_set_list;
+  setlist->next_is_parent = 0;
 
   return setlist;
@@ -1031,4 +1118,5 @@
       global_setlist.set = setlist->set;
       global_setlist.next = setlist->next;
+      global_setlist.next_is_parent = setlist->next_is_parent;
     }
 
@@ -1169,5 +1257,5 @@
 
   sprintf (buf, "%u", makelevel);
-  (void) define_variable (MAKELEVEL_NAME, MAKELEVEL_LENGTH, buf, o_env, 0);
+  define_variable_cname (MAKELEVEL_NAME, buf, o_env, 0);
 
   sprintf (buf, "%s%s%s",
@@ -1178,28 +1266,23 @@
 	   ? "" : remote_description);
 #ifndef KMK
-  (void) define_variable ("MAKE_VERSION", 12, buf, o_default, 0);
+  define_variable_cname ("MAKE_VERSION", buf, o_default, 0);
 #else /* KMK */
 
   /* Define KMK_VERSION to indicate kMk. */
-  (void) define_variable ("KMK_VERSION", 11, buf, o_default, 0);
+  define_variable_cname ("KMK_VERSION", buf, o_default, 0);
 
   /* Define KBUILD_VERSION* */
   sprintf (buf, "%d", KBUILD_VERSION_MAJOR);
-  define_variable ("KBUILD_VERSION_MAJOR", sizeof ("KBUILD_VERSION_MAJOR") - 1,
-                   buf, o_default, 0);
+  define_variable_cname ("KBUILD_VERSION_MAJOR", buf, o_default, 0);
   sprintf (buf, "%d", KBUILD_VERSION_MINOR);
-  define_variable ("KBUILD_VERSION_MINOR", sizeof("KBUILD_VERSION_MINOR") - 1,
-                   buf, o_default, 0);
+  define_variable_cname ("KBUILD_VERSION_MINOR", buf, o_default, 0);
   sprintf (buf, "%d", KBUILD_VERSION_PATCH);
-  define_variable ("KBUILD_VERSION_PATCH", sizeof ("KBUILD_VERSION_PATCH") - 1,
-                   buf, o_default, 0);
+  define_variable_cname ("KBUILD_VERSION_PATCH", buf, o_default, 0);
   sprintf (buf, "%d", KBUILD_SVN_REV);
-  define_variable ("KBUILD_KMK_REVISION", sizeof ("KBUILD_KMK_REVISION") - 1,
-                   buf, o_default, 0);
+  define_variable_cname ("KBUILD_KMK_REVISION", buf, o_default, 0);
 
   sprintf (buf, "%d.%d.%d-r%d", KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR,
            KBUILD_VERSION_PATCH, KBUILD_SVN_REV);
-  define_variable ("KBUILD_VERSION", sizeof ("KBUILD_VERSION") - 1,
-                   buf, o_default, 0);
+  define_variable_cname ("KBUILD_VERSION", buf, o_default, 0);
 
   /* The host defaults. The BUILD_* stuff will be replaced by KBUILD_* soon. */
@@ -1210,9 +1293,7 @@
     error (NULL, _("KBUILD_HOST and BUILD_PLATFORM differs, using KBUILD_HOST=%s."), val);
   if (!envvar1)
-    define_variable ("KBUILD_HOST", sizeof ("KBUILD_HOST") - 1,
-                     val, o_default, 0);
+    define_variable_cname ("KBUILD_HOST", val, o_default, 0);
   if (!envvar2)
-    define_variable ("BUILD_PLATFORM", sizeof ("BUILD_PLATFORM") - 1,
-                     val, o_default, 0);
+    define_variable_cname ("BUILD_PLATFORM", val, o_default, 0);
 
   envvar1 = lookup_variable (STRING_SIZE_TUPLE ("KBUILD_HOST_ARCH"));
@@ -1222,9 +1303,7 @@
     error (NULL, _("KBUILD_HOST_ARCH and BUILD_PLATFORM_ARCH differs, using KBUILD_HOST_ARCH=%s."), val);
   if (!envvar1)
-    define_variable ("KBUILD_HOST_ARCH", sizeof ("KBUILD_HOST_ARCH") - 1,
-                     val, o_default, 0);
+    define_variable_cname ("KBUILD_HOST_ARCH", val, o_default, 0);
   if (!envvar2)
-    define_variable ("BUILD_PLATFORM_ARCH", sizeof ("BUILD_PLATFORM_ARCH") - 1,
-                     val, o_default, 0);
+    define_variable_cname ("BUILD_PLATFORM_ARCH", val, o_default, 0);
 
   envvar1 = lookup_variable (STRING_SIZE_TUPLE ("KBUILD_HOST_CPU"));
@@ -1234,9 +1313,7 @@
     error (NULL, _("KBUILD_HOST_CPU and BUILD_PLATFORM_CPU differs, using KBUILD_HOST_CPU=%s."), val);
   if (!envvar1)
-    define_variable ("KBUILD_HOST_CPU", sizeof ("KBUILD_HOST_CPU") - 1,
-                     val, o_default, 0);
+    define_variable_cname ("KBUILD_HOST_CPU", val, o_default, 0);
   if (!envvar2)
-    define_variable ("BUILD_PLATFORM_CPU", sizeof ("BUILD_PLATFORM_CPU") - 1,
-                     val, o_default, 0);
+    define_variable_cname ("BUILD_PLATFORM_CPU", val, o_default, 0);
 
   /* The host kernel version. */
@@ -1277,29 +1354,21 @@
 
   sprintf (buf, "%lu.%lu.%lu.%lu", ulMajor, ulMinor, ulPatch, ul4th);
-  define_variable ("KBUILD_HOST_VERSION", sizeof ("KBUILD_HOST_VERSION") - 1,
-                   buf, o_default, 0);
+  define_variable_cname ("KBUILD_HOST_VERSION", buf, o_default, 0);
 
   sprintf (buf, "%lu", ulMajor);
-  define_variable ("KBUILD_HOST_VERSION_MAJOR", sizeof ("KBUILD_HOST_VERSION_MAJOR") - 1,
-                   buf, o_default, 0);
+  define_variable_cname ("KBUILD_HOST_VERSION_MAJOR", buf, o_default, 0);
 
   sprintf (buf, "%lu", ulMinor);
-  define_variable ("KBUILD_HOST_VERSION_MINOR", sizeof ("KBUILD_HOST_VERSION_MINOR") - 1,
-                   buf, o_default, 0);
+  define_variable_cname ("KBUILD_HOST_VERSION_MINOR", buf, o_default, 0);
 
   sprintf (buf, "%lu", ulPatch);
-  define_variable ("KBUILD_HOST_VERSION_PATCH", sizeof ("KBUILD_HOST_VERSION_PATCH") - 1,
-                   buf, o_default, 0);
+  define_variable_cname ("KBUILD_HOST_VERSION_PATCH", buf, o_default, 0);
 
   /* The kBuild locations. */
-  define_variable ("KBUILD_PATH", sizeof ("KBUILD_PATH") - 1,
-                   get_kbuild_path (), o_default, 0);
-  define_variable ("KBUILD_BIN_PATH", sizeof ("KBUILD_BIN_PATH") - 1,
-                   get_kbuild_bin_path (), o_default, 0);
-
-  define_variable ("PATH_KBUILD", sizeof ("PATH_KBUILD") - 1,
-                   get_kbuild_path (), o_default, 0);
-  define_variable ("PATH_KBUILD_BIN", sizeof ("PATH_KBUILD_BIN") - 1,
-                   get_kbuild_bin_path (), o_default, 0);
+  define_variable_cname ("KBUILD_PATH", get_kbuild_path (), o_default, 0);
+  define_variable_cname ("KBUILD_BIN_PATH", get_kbuild_bin_path (), o_default, 0);
+
+  define_variable_cname ("PATH_KBUILD", get_kbuild_path (), o_default, 0);
+  define_variable_cname ("PATH_KBUILD_BIN", get_kbuild_bin_path (), o_default, 0);
 
   /* Define KMK_FEATURES to indicate various working KMK features. */
@@ -1330,34 +1399,34 @@
   && defined (CONFIG_WITH_DEFINED_FUNCTIONS) \
   && defined (KMK_HELPERS)
-  (void) define_variable ("KMK_FEATURES", 12,
-                          "append-dash-n abspath includedep-queue install-hard-linking umask"
-                          " kBuild-define"
-                          " rsort"
-                          " abspathex"
-                          " toupper tolower"
-                          " defined"
-                          " comp-vars comp-cmds comp-cmds-ex"
-                          " stack"
-                          " math-int"
-                          " xargs"
-                          " explicit-multitarget"
-                          " dot-must-make"
-                          " prepend-assignment"
-                          " set-conditionals intersects"
-                          " date"
-                          " file-size"
-                          " expr if-expr select"
-                          " where"
-                          " which"
-                          " evalctx evalval evalvalctx evalcall evalcall2 eval-opt-var"
-                          " make-stats"
-                          " commands"
-                          " printf"
-                          " for while"
-                          " root"
-                          " length insert pos lastpos substr translate"
-                          " kb-src-tool kb-obj-base kb-obj-suff kb-src-prop kb-src-one kb-exp-tmpl"
-                          " firstdefined lastdefined"
-                          , o_default, 0);
+  define_variable_cname ("KMK_FEATURES",
+                         "append-dash-n abspath includedep-queue install-hard-linking umask"
+                         " kBuild-define"
+                         " rsort"
+                         " abspathex"
+                         " toupper tolower"
+                         " defined"
+                         " comp-vars comp-cmds comp-cmds-ex"
+                         " stack"
+                         " math-int"
+                         " xargs"
+                         " explicit-multitarget"
+                         " dot-must-make"
+                         " prepend-assignment"
+                         " set-conditionals intersects"
+                         " date"
+                         " file-size"
+                         " expr if-expr select"
+                         " where"
+                         " which"
+                         " evalctx evalval evalvalctx evalcall evalcall2 eval-opt-var"
+                         " make-stats"
+                         " commands"
+                         " printf"
+                         " for while"
+                         " root"
+                         " length insert pos lastpos substr translate"
+                         " kb-src-tool kb-obj-base kb-obj-suff kb-src-prop kb-src-one kb-exp-tmpl"
+                         " firstdefined lastdefined"
+                         , o_default, 0);
 # else /* MSC can't deal with strings mixed with #if/#endif, thus the slow way. */
 #  error "All features should be enabled by default!"
@@ -1442,5 +1511,5 @@
   strcat (buf, " kb-src-tool kb-obj-base kb-obj-suff kb-src-prop kb-src-one kb-exp-tmpl");
 #  endif
-  (void) define_variable ("KMK_FEATURES", 12, buf, o_default, 0);
+  define_variable_cname ("KMK_FEATURES", buf, o_default, 0);
 # endif
 
@@ -1449,5 +1518,5 @@
 #ifdef CONFIG_WITH_KMK_BUILTIN
   /* The supported kMk Builtin commands. */
-  (void) define_variable ("KMK_BUILTIN", 11, "append cat chmod cp cmp echo expr install kDepIDB ln md5sum mkdir mv printf rm rmdir sleep test", o_default, 0);
+  define_variable_cname ("KMK_BUILTIN", "append cat chmod cp cmp echo expr install kDepIDB ln md5sum mkdir mv printf rm rmdir sleep test", o_default, 0);
 #endif
 
@@ -1461,5 +1530,5 @@
     struct variable *comp = lookup_variable ("COMSPEC", 7);
 
-    /* Make $MAKESHELL override $SHELL even if -e is in effect.  */
+    /* $(MAKESHELL) overrides $(SHELL) even if -e is in effect.  */
     if (mshp)
       (void) define_variable (shell_str, shlen,
@@ -1467,5 +1536,5 @@
     else if (comp)
       {
-	/* $COMSPEC shouldn't override $SHELL.  */
+	/* $(COMSPEC) shouldn't override $(SHELL).  */
 	struct variable *shp = lookup_variable (shell_str, shlen);
 
@@ -1526,5 +1595,5 @@
   /* This won't override any definition, but it will provide one if there
      isn't one there.  */
-  v = define_variable ("SHELL", 5, default_shell, o_default, 0);
+  v = define_variable_cname ("SHELL", default_shell, o_default, 0);
 #ifdef __MSDOS__
   v->export = v_export;  /*  Export always SHELL.  */
@@ -1555,5 +1624,5 @@
 
   /* Make sure MAKEFILES gets exported if it is set.  */
-  v = define_variable ("MAKEFILES", 9, "", o_default, 0);
+  v = define_variable_cname ("MAKEFILES", "", o_default, 0);
   v->export = v_ifset;
 
@@ -1562,27 +1631,27 @@
 
 #ifdef VMS
-  define_variable ("@D", 2, "$(dir $@)", o_automatic, 1);
-  define_variable ("%D", 2, "$(dir $%)", o_automatic, 1);
-  define_variable ("*D", 2, "$(dir $*)", o_automatic, 1);
-  define_variable ("<D", 2, "$(dir $<)", o_automatic, 1);
-  define_variable ("?D", 2, "$(dir $?)", o_automatic, 1);
-  define_variable ("^D", 2, "$(dir $^)", o_automatic, 1);
-  define_variable ("+D", 2, "$(dir $+)", o_automatic, 1);
+  define_variable_cname ("@D", "$(dir $@)", o_automatic, 1);
+  define_variable_cname ("%D", "$(dir $%)", o_automatic, 1);
+  define_variable_cname ("*D", "$(dir $*)", o_automatic, 1);
+  define_variable_cname ("<D", "$(dir $<)", o_automatic, 1);
+  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
-  define_variable ("@D", 2, "$(patsubst %/,%,$(dir $@))", o_automatic, 1);
-  define_variable ("%D", 2, "$(patsubst %/,%,$(dir $%))", o_automatic, 1);
-  define_variable ("*D", 2, "$(patsubst %/,%,$(dir $*))", o_automatic, 1);
-  define_variable ("<D", 2, "$(patsubst %/,%,$(dir $<))", o_automatic, 1);
-  define_variable ("?D", 2, "$(patsubst %/,%,$(dir $?))", o_automatic, 1);
-  define_variable ("^D", 2, "$(patsubst %/,%,$(dir $^))", o_automatic, 1);
-  define_variable ("+D", 2, "$(patsubst %/,%,$(dir $+))", o_automatic, 1);
-#endif
-  define_variable ("@F", 2, "$(notdir $@)", o_automatic, 1);
-  define_variable ("%F", 2, "$(notdir $%)", o_automatic, 1);
-  define_variable ("*F", 2, "$(notdir $*)", o_automatic, 1);
-  define_variable ("<F", 2, "$(notdir $<)", o_automatic, 1);
-  define_variable ("?F", 2, "$(notdir $?)", o_automatic, 1);
-  define_variable ("^F", 2, "$(notdir $^)", o_automatic, 1);
-  define_variable ("+F", 2, "$(notdir $+)", o_automatic, 1);
+  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);
+  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);
+  define_variable_cname ("+D", "$(patsubst %/,%,$(dir $+))", o_automatic, 1);
+#endif
+  define_variable_cname ("@F", "$(notdir $@)", o_automatic, 1);
+  define_variable_cname ("%F", "$(notdir $%)", o_automatic, 1);
+  define_variable_cname ("*F", "$(notdir $*)", o_automatic, 1);
+  define_variable_cname ("<F", "$(notdir $<)", o_automatic, 1);
+  define_variable_cname ("?F", "$(notdir $?)", o_automatic, 1);
+  define_variable_cname ("^F", "$(notdir $^)", o_automatic, 1);
+  define_variable_cname ("+F", "$(notdir $+)", o_automatic, 1);
 #ifdef CONFIG_WITH_LAZY_DEPS_VARS
   define_variable ("^", 1, "$(deps $@)", o_automatic, 1);
@@ -1753,5 +1822,5 @@
 	      convert_Path_to_windows32(value, ';');
 #endif
-	    *result++ = xstrdup (concat (v->name, "=", value));
+	    *result++ = xstrdup (concat (3, v->name, "=", value));
 	    free (value);
 	  }
@@ -1763,5 +1832,5 @@
               convert_Path_to_windows32(v->value, ';');
 #endif
-	    *result++ = xstrdup (concat (v->name, "=", v->value));
+	    *result++ = xstrdup (concat (3, v->name, "=", v->value));
 	  }
       }
@@ -1954,5 +2023,5 @@
           value_len = strlen (value);
         if (!free_value)
-          p = alloc_value = savestring (value, value_len);
+          p = alloc_value = xstrndup (value, value_len);
         else
           {
@@ -2048,5 +2117,5 @@
             unsigned int oldlen, vallen;
             const char *val;
-            char *tp;
+            char *tp = NULL;
 
             val = value;
@@ -2061,24 +2130,26 @@
                  memory for the expansion as we may still need the rest of the
                  buffer if we're looking at a target-specific variable.  */
-              val = alloc_value = allocated_variable_expand (val);
+              val = tp = allocated_variable_expand (val);
 
             oldlen = strlen (v->value);
             vallen = strlen (val);
-            tp = alloca (oldlen + 1 + vallen + 1);
+            p = alloc_value = xmalloc (oldlen + 1 + vallen + 1);
 # ifdef CONFIG_WITH_PREPEND_ASSIGNMENT
             if (org_flavor == f_prepend)
               {
-                memcpy (tp, val, vallen);
-                tp[oldlen] = ' ';
-                memcpy (&tp[oldlen + 1], v->value, oldlen + 1);
+                memcpy (alloc_value, val, vallen);
+                alloc_value[oldlen] = ' ';
+                memcpy (&alloc_value[oldlen + 1], v->value, oldlen + 1);
               }
             else
 # endif /* CONFIG_WITH_PREPEND_ASSIGNMENT */
               {
-                memcpy (tp, v->value, oldlen);
-                tp[oldlen] = ' ';
-                memcpy (&tp[oldlen + 1], val, vallen + 1);
+                memcpy (alloc_value, v->value, oldlen);
+                alloc_value[oldlen] = ' ';
+                memcpy (&alloc_value[oldlen + 1], val, vallen + 1);
               }
-            p = tp;
+
+            if (tp)
+              free (tp);
 #endif /* !CONFIG_WITH_VALUE_LENGTH */
           }
@@ -2193,8 +2264,8 @@
       else
         {
-          if (alloc_value)
-            free (alloc_value);
+          char *tp = alloc_value;
 
           alloc_value = allocated_variable_expand (p);
+
           if (find_and_set_default_shell (alloc_value))
             {
@@ -2212,4 +2283,7 @@
           else
             v = lookup_variable (varname, varname_len);
+
+          if (tp)
+            free (tp);
         }
     }
@@ -2250,78 +2324,30 @@
 
 
-/* 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 *
-#ifndef CONFIG_WITH_VALUE_LENGTH
-parse_variable_definition (struct variable *v, char *line)
-#else
-parse_variable_definition (struct variable *v, char *line, char *eos)
-#endif
-{
-  register int c;
-  register char *p = line;
-  register char *beg;
-  register char *end;
-  enum variable_flavor flavor = f_bogus;
-#ifndef CONFIG_WITH_VALUE_LENGTH
-  char *name;
-#endif
+/* Parse P (a null-terminated string) as a variable definition.
+
+   If it is not a variable definition, return NULL.
+
+   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.  */
+
+char *
+parse_variable_definition (const char *p, enum variable_flavor *flavor)
+{
+  int wspace = 0;
+
+  p = next_token (p);
 
   while (1)
     {
-      c = *p++;
+      int c = *p++;
+
+      /* If we find a comment or EOS, it's not a variable definition.  */
       if (c == '\0' || c == '#')
-	return 0;
-      if (c == '=')
+	return NULL;
+
+      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;
-	}
-#ifdef CONFIG_WITH_PREPEND_ASSIGNMENT
-      else if (c == '<' && *p == '=')
-        {
-          end = p++ - 1;
-          flavor = f_prepend;
-          break;
-        }
-#endif
-      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 +=.  */
+	  /* This begins a variable expansion reference.  Make sure we don't
+	     treat chars inside the reference as assignment tokens.  */
 	  char closeparen;
 	  int count;
@@ -2332,5 +2358,6 @@
 	    closeparen = '}';
 	  else
-	    continue;		/* Nope.  */
+            /* '$$' or '$X'.  Either way, nothing special to do here.  */
+	    continue;
 
 	  /* P now points past the opening paren or brace.
@@ -2347,17 +2374,98 @@
 		}
 	    }
+          continue;
 	}
-    }
-  v->flavor = flavor;
+
+      /* If we find whitespace skip it, and remember we found it.  */
+      if (isblank ((unsigned char)c))
+        {
+          wspace = 1;
+          p = next_token (p);
+          c = *p;
+          if (c == '\0')
+            return NULL;
+          ++p;
+        }
+
+
+      if (c == '=')
+	{
+	  *flavor = f_recursive;
+	  return (char *)p;
+	}
+
+      /* Match assignment variants (:=, +=, ?=)  */
+      if (*p == '=')
+        {
+          switch (c)
+            {
+              case ':':
+                *flavor = f_simple;
+                break;
+              case '+':
+                *flavor = f_append;
+                break;
+#ifdef CONFIG_WITH_PREPEND_ASSIGNMENT
+              case '<':
+               *flavor = f_prepend;
+                break;
+#endif
+              case '?':
+                *flavor = f_conditional;
+                break;
+              default:
+                /* If we skipped whitespace, non-assignments means no var.  */
+                if (wspace)
+                  return NULL;
+
+                /* Might be assignment, or might be $= or #=.  Check.  */
+                continue;
+            }
+          return (char *)++p;
+        }
+      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;
+    }
+
+  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
+   variable' is returned.  If LINE is not a variable definition, NULL is
+   returned.  */
+
+struct variable *
+assign_variable_definition (struct variable *v, char *line IF_WITH_VALUE_LENGTH_PARAM(char *eos))
+{
+  char *beg;
+  char *end;
+  enum variable_flavor flavor;
+#ifndef CONFIG_WITH_VALUE_LENGTH
+  char *name;
+#endif
 
   beg = next_token (line);
+  line = parse_variable_definition (beg, &flavor);
+  if (!line)
+    return NULL;
+
+  end = line - (flavor == f_recursive ? 1 : 2);
   while (end > beg && isblank ((unsigned char)end[-1]))
     --end;
-  p = next_token (p);
-  v->value = p;
+  line = next_token (line);
+  v->value = line;
+  v->flavor = flavor;
 #ifdef CONFIG_WITH_VALUE_LENGTH
   v->value_alloc_len = ~(unsigned int)0;
-  v->value_length = eos != NULL ? eos - p : -1;
-  assert (eos == NULL || strchr (p, '\0') == eos);
+  v->value_length = eos != NULL ? eos - line : -1;
+  assert (eos == NULL || strchr (line, '\0') == eos);
 # ifdef CONFIG_WITH_RDONLY_VARIABLE_VALUE
   v->rdonly_val = 0;
@@ -2389,5 +2497,5 @@
    or without the -e switch, or the command line.
 
-   See the comments for parse_variable_definition().
+   See the comments for assign_variable_definition().
 
    If LINE was recognized as a variable definition, a pointer to its `struct
@@ -2396,11 +2504,7 @@
 
 struct variable *
-#ifndef CONFIG_WITH_VALUE_LENGTH
-try_variable_definition (const struct floc *flocp, char *line,
+try_variable_definition (const struct floc *flocp, char *line
+                         IF_WITH_VALUE_LENGTH_PARAM(char *eos),
                          enum variable_origin origin, int target_var)
-#else
-try_variable_definition (const struct floc *flocp, char *line, char *eos,
-                         enum variable_origin origin, int target_var)
-#endif
 {
   struct variable v;
@@ -2413,5 +2517,5 @@
 
 #ifndef CONFIG_WITH_VALUE_LENGTH
-  if (!parse_variable_definition (&v, line))
+  if (!assign_variable_definition (&v, line))
     return 0;
 
@@ -2419,5 +2523,5 @@
                                origin, v.flavor, target_var);
 #else
-  if (!parse_variable_definition (&v, line, eos))
+  if (!assign_variable_definition (&v, line, eos))
     return 0;
 
@@ -2486,4 +2590,6 @@
   fputs ("# ", stdout);
   fputs (origin, stdout);
+  if (v->private_var)
+    fputs (" private", stdout);
   if (v->fileinfo.filenm)
     printf (_(" (from `%s', line %lu)"),
@@ -2514,5 +2620,5 @@
   else
     {
-      register char *p;
+      char *p;
 
       printf ("%s %s= ", v->name, v->recursive ? v->append ? "+" : "" : ":");
@@ -2660,5 +2766,5 @@
    */
   convert_Path_to_windows32 (path, ';');
-  environ_path = xstrdup (concat ("PATH", "=", path));
+  environ_path = xstrdup (concat (3, "PATH", "=", path));
   putenv (environ_path);
   free (path);
Index: /trunk/src/kmk/variable.h
===================================================================
--- /trunk/src/kmk/variable.h	(revision 2590)
+++ /trunk/src/kmk/variable.h	(revision 2591)
@@ -82,4 +82,6 @@
                                    exported.  */
     unsigned int expanding:1;	/* Nonzero if currently being expanded.  */
+    unsigned int private_var:1; /* Nonzero avoids inheritance of this
+                                   target-specific variable.  */
     unsigned int exp_count:EXP_COUNT_BITS;
                                 /* If >1, allow this many self-referential
@@ -122,4 +124,5 @@
     struct variable_set_list *next;	/* Link in the chain.  */
     struct variable_set *set;		/* Variable set.  */
+    int next_is_parent;                 /* True if next is a parent target.  */
   };
 
@@ -137,12 +140,15 @@
 extern char *variable_buffer;
 extern struct variable_set_list *current_variable_set_list;
+extern struct variable *default_goal_var;
+
 #ifdef KMK
 extern unsigned int variable_buffer_length;
-#define VARIABLE_BUFFER_ZONE    5
+# define VARIABLE_BUFFER_ZONE   5
 #endif
 
 /* expand.c */
 #ifndef KMK
-char *variable_buffer_output (char *ptr, const char *string, unsigned int length);
+char *
+variable_buffer_output (char *ptr, const char *string, unsigned int length);
 #else /* KMK */
 /* Subroutine of variable_expand and friends:
@@ -209,7 +215,9 @@
 char *expand_argument (const char *str, const char *end);
 #ifndef CONFIG_WITH_VALUE_LENGTH
-char *variable_expand_string (char *line, const char *string, long length);
+char *
+variable_expand_string (char *line, const char *string, long length);
 #else  /* CONFIG_WITH_VALUE_LENGTH */
-char *variable_expand_string_2 (char *line, const char *string, long length, char **eol);
+char *
+variable_expand_string_2 (char *line, const char *string, long length, char **eol);
 __inline static char *
 variable_expand_string (char *line, const char *string, long length)
@@ -314,13 +322,8 @@
                                          enum variable_flavor flavor,
                                          int target_var);
-struct variable *parse_variable_definition (struct variable *v, char *line);
-struct variable *try_variable_definition (const struct floc *flocp, char *line,
-                                          enum variable_origin origin,
-                                          int target_var);
 #else  /* CONFIG_WITH_VALUE_LENGTH */
 # define do_variable_definition(flocp, varname, value, origin, flavor, target_var) \
     do_variable_definition_2 ((flocp), (varname), (value), ~0U, 0, NULL, \
                               (origin), (flavor), (target_var))
-
 struct variable *do_variable_definition_2 (const struct floc *flocp,
                                            const char *varname,
@@ -331,11 +334,12 @@
                                            enum variable_flavor flavor,
                                            int target_var);
-struct variable *parse_variable_definition (struct variable *v, char *line,
-                                            char *eos);
-struct variable *try_variable_definition (const struct floc *flocp, char *line,
-                                          char *eos,
+#endif /* CONFIG_WITH_VALUE_LENGTH */
+char *parse_variable_definition (const char *line,
+                                          enum variable_flavor *flavor);
+struct variable *assign_variable_definition (struct variable *v, char *line IF_WITH_VALUE_LENGTH_PARAM(char *eos));
+struct variable *try_variable_definition (const struct floc *flocp, char *line
+                                          IF_WITH_VALUE_LENGTH_PARAM(char *eos),
                                           enum variable_origin origin,
                                           int target_var);
-#endif /* CONFIG_WITH_VALUE_LENGTH */
 void init_hash_global_variable_set (void);
 void hash_init_function_table (void);
@@ -367,4 +371,10 @@
                                  current_variable_set_list->set,NILF)
 
+/* Define a variable with a constant name in the current variable set.  */
+
+#define define_variable_cname(n,v,o,r) \
+          define_variable_in_set((n),(sizeof (n) - 1),(v),~0U,1,(o),(r),\
+                                 current_variable_set_list->set,NILF)
+
 /* Define a variable with a location in the current variable set.  */
 
@@ -401,4 +411,10 @@
                                  current_variable_set_list->set,NILF)           /* force merge conflict */
 
+/* Define a variable with a constant name in the current variable set.  */
+
+#define define_variable_cname(n,v,o,r) \
+          define_variable_in_set((n),(sizeof (n) - 1),(v),(o),(r),\
+                                 current_variable_set_list->set,NILF)           /* force merge conflict */
+
 /* Define a variable with a location in the current variable set.  */
 
@@ -418,4 +434,13 @@
 
 #endif /* !CONFIG_WITH_VALUE_LENGTH */
+
+void undefine_variable_in_set (const char *name, unsigned int length,
+                                         enum variable_origin origin,
+                                         struct variable_set *set);
+
+/* Remove variable from the current variable set. */
+
+#define undefine_variable_global(n,l,o) \
+          undefine_variable_in_set((n),(l),(o),NULL)
 
 /* Warn that NAME is an undefined variable.  */
@@ -444,2 +469,3 @@
 #endif
 #define MAKELEVEL_LENGTH (sizeof (MAKELEVEL_NAME) - 1)
+
Index: /trunk/src/kmk/version.c
===================================================================
--- /trunk/src/kmk/version.c	(revision 2590)
+++ /trunk/src/kmk/version.c	(revision 2591)
@@ -1,6 +1,6 @@
 /* Record version and build host architecture 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 Free Software
-Foundation, Inc.
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
Index: /trunk/src/kmk/vmsdir.h
===================================================================
--- /trunk/src/kmk/vmsdir.h	(revision 2590)
+++ /trunk/src/kmk/vmsdir.h	(revision 2591)
@@ -1,5 +1,5 @@
 /* dirent.h for vms
 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
-2007 Free Software Foundation, Inc.
+2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
Index: /trunk/src/kmk/vmsfunctions.c
===================================================================
--- /trunk/src/kmk/vmsfunctions.c	(revision 2590)
+++ /trunk/src/kmk/vmsfunctions.c	(revision 2591)
@@ -1,5 +1,5 @@
 /* VMS functions
 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
-2007 Free Software Foundation, Inc.
+2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
@@ -35,10 +35,8 @@
 opendir (char *dspec)
 {
-  struct DIR *dir  = (struct DIR *)xmalloc (sizeof (struct DIR));
-  struct NAM *dnam = (struct NAM *)xmalloc (sizeof (struct NAM));
+  struct DIR *dir  = xcalloc (sizeof (struct DIR));
+  struct NAM *dnam = xmalloc (sizeof (struct NAM));
   struct FAB *dfab = &dir->fab;
   char *searchspec = xmalloc (MAXNAMLEN + 1);
-
-  memset (dir, 0, sizeof *dir);
 
   *dfab = cc$rms_fab;
@@ -92,5 +90,5 @@
   if (!((i = sys$search (dfab)) & 1))
     {
-      DB (DB_VERBOSE, (_("sys$search failed with %d\n"), i));
+      DB (DB_VERBOSE, (_("sys$search() failed with %d\n"), i));
       return (NULL);
     }
@@ -142,4 +140,8 @@
 }
 
+#if 0
+/*
+ * Is this used? I don't see any reference, so I suggest to remove it.
+ */
 int
 vms_stat (char *name, struct stat *buf)
@@ -238,4 +240,5 @@
   return 0;
 }
+#endif
 
 char *
Index: /trunk/src/kmk/vmsify.c
===================================================================
--- /trunk/src/kmk/vmsify.c	(revision 2590)
+++ /trunk/src/kmk/vmsify.c	(revision 2591)
@@ -1,5 +1,5 @@
 /* vmsify.c -- Module for vms <-> unix file name conversion
 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
-2007 Free Software Foundation, Inc.
+2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
@@ -121,5 +121,9 @@
   char *s;
 
-  INIT_DSC_CSTRING (name_dsc, name);
+  /*
+   * the string isn't changed, but there is no string descriptor with
+   * "const char *dsc$a_pointer"
+   */
+  INIT_DSC_CSTRING (name_dsc, (char *)name);
 
   stat = lib$sys_trnlog (&name_dsc, &resltlen, &reslt_dsc);
@@ -228,4 +232,7 @@
   int as_dir;
   int count;
+  const char *s;
+  const char *s1;
+  const char *s2;
 
   if (name == 0)
@@ -240,6 +247,6 @@
   if (t != 0)
     {
-      const char *s1;
-      const char *s2;
+//      const char *s1;
+//      const char *s2;
 
       if (type == 1)
@@ -273,6 +280,7 @@
   if (t != 0)
     {
-      const char *s;
-      const char *s1 = strchr (t+1, '[');
+//      const char *s;
+//      const char *s1 = strchr (t+1, '[');
+      s1 = strchr (t+1, '[');
       if (s1 == 0)
 	{
@@ -389,6 +397,6 @@
 	  case 3:				/* '//' at start */
             {
-            const char *s;
-            const char *s1;
+//            const char *s;
+//            const char *s1;
             char *vp;
 	    while (*fptr == '/')	/* collapse all '/' */
Index: /trunk/src/kmk/vmsjobs.c
===================================================================
--- /trunk/src/kmk/vmsjobs.c	(revision 2590)
+++ /trunk/src/kmk/vmsjobs.c	(revision 2591)
@@ -3,5 +3,5 @@
 
 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
-2007 Free Software Foundation, Inc.
+2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
@@ -111,6 +111,9 @@
 }
 
-/* This is called as an AST when a child process dies (it won't get
-   interrupted by anything except a higher level AST).
+static int ctrlYPressed= 0;
+/* This is called at main or AST level. It is at AST level for DONTWAITFORCHILD
+   and at main level otherwise. In any case it is called when a child process
+   terminated. At AST level it won't get interrupted by anything except a
+   inner mode level AST.
 */
 int
@@ -124,4 +127,10 @@
 
     lib$free_ef(&child->efn);
+    if (child->comname)
+      {
+        if (!ISDB (DB_JOBS)&&!ctrlYPressed)
+          unlink (child->comname);
+        free (child->comname);
+      }
 
     (void) sigblock (fatal_signal_mask);
@@ -220,6 +229,5 @@
 static int oldCtrlMask;
 static int setupYAstTried= 0;
-static int pidToAbort= 0;
-static int chan= 0;
+static unsigned short int chan= 0;
 
 static void
@@ -229,12 +237,13 @@
 }
 
-static void
-astHandler (void)
+static int
+astYHandler (void)
 {
-	if (pidToAbort) {
-		sys$forcex (&pidToAbort, 0, SS$_ABORT);
-		pidToAbort= 0;
-	}
+	struct child *c;
+	for (c = children; c != 0; c = c->next)
+		sys$delprc (&c->pid, 0, 0);
+	ctrlYPressed= 1;
 	kill (getpid(),SIGQUIT);
+	return SS$_NORMAL;
 }
 
@@ -248,9 +257,12 @@
 		int	dvi;
 	} iosb;
+	unsigned short int loc_chan;
 
 	setupYAstTried++;
 
-	if (!chan) {
-		status= sys$assign(&inputDsc,&chan,0,0);
+	if (chan)
+          loc_chan= chan;
+	else {
+		status= sys$assign(&inputDsc,&loc_chan,0,0);
 		if (!(status&SS$_NORMAL)) {
 			lib$signal(status);
@@ -258,20 +270,13 @@
 		}
 	}
-	status= sys$qiow (0, chan, IO$_SETMODE|IO$M_CTRLYAST,&iosb,0,0,
-		astHandler,0,0,0,0,0);
-	if (status==SS$_NORMAL)
-		status= iosb.status;
-        if (status==SS$_ILLIOFUNC || status==SS$_NOPRIV) {
-		sys$dassgn(chan);
-#ifdef	CTRLY_ENABLED_ANYWAY
-		fprintf (stderr,
-                         _("-warning, CTRL-Y will leave sub-process(es) around.\n"));
-#else
-		return;
-#endif
-	}
-	else if (!(status&SS$_NORMAL)) {
-		sys$dassgn(chan);
-		lib$signal(status);
+	status= sys$qiow (0, loc_chan, IO$_SETMODE|IO$M_CTRLYAST,&iosb,0,0,
+                          astYHandler,0,0,0,0,0);
+        if (status==SS$_NORMAL)
+          	status= iosb.status;
+	if (status!=SS$_NORMAL) {
+		if (!chan)
+			sys$dassgn(loc_chan);
+		if (status!=SS$_ILLIOFUNC && status!=SS$_NOPRIV)
+			lib$signal(status);
 		return;
 	}
@@ -288,4 +293,6 @@
 		return;
 	}
+	if (!chan)
+		chan = loc_chan;
 }
 
@@ -300,4 +307,5 @@
   static struct dsc$descriptor_s efiledsc;
   int have_redirection = 0;
+  int have_append = 0;
   int have_newline = 0;
 
@@ -306,5 +314,5 @@
   char *cmd = alloca (strlen (argv) + 512), *p, *q;
   char ifile[256], ofile[256], efile[256];
-  char *comname = 0;
+  int comnamelen;
   char procname[100];
   int in_string;
@@ -315,4 +323,5 @@
   ofile[0] = 0;
   efile[0] = 0;
+  child->comname = NULL;
 
   DB (DB_JOBS, ("child_execute_job (%s)\n", argv));
@@ -384,4 +393,9 @@
 	    else
 	      {
+                if (*(p+1) == '>')
+                  {
+                    have_append = 1;
+                    p += 1;
+                  }
 		p = vms_redirect (&ofiledsc, ofile, p);
 	      }
@@ -482,7 +496,8 @@
 	}
 
-      outfile = open_tmpfile (&comname, "sys$scratch:CMDXXXXXX.COM");
+      outfile = open_tmpfile (&child->comname, "sys$scratch:CMDXXXXXX.COM");
       if (outfile == 0)
 	pfatal_with_name (_("fopen (temporary file)"));
+      comnamelen = strlen (child->comname);
 
       if (ifile[0])
@@ -502,7 +517,17 @@
       if (ofile[0])
 	{
-	  fprintf (outfile, "$ define sys$output %s\n", ofile);
-	  DB (DB_JOBS, (_("Redirected output to %s\n"), ofile));
-	  ofiledsc.dsc$w_length = 0;
+          if (have_append)
+            {
+              fprintf (outfile, "$ set noon\n");
+              fprintf (outfile, "$ define sys$output %.*s\n", comnamelen-3, child->comname);
+              DB (DB_JOBS, (_("Append output to %s\n"), ofile));
+              ofiledsc.dsc$w_length = 0;
+            }
+          else
+            {
+              fprintf (outfile, "$ define sys$output %s\n", ofile);
+              DB (DB_JOBS, (_("Redirected output to %s\n"), ofile));
+              ofiledsc.dsc$w_length = 0;
+            }
 	}
 
@@ -559,10 +584,23 @@
   	}
 
-      fwrite (p, 1, q - p, outfile);
+      if (*p)
+        {
+          fwrite (p, 1, --q - p, outfile);
       fputc ('\n', outfile);
+        }
+
+      if (have_append)
+        {
+          fprintf (outfile, "$ deassign sys$output ! 'f$verify(0)\n");
+          fprintf (outfile, "$ append:=append\n");
+          fprintf (outfile, "$ delete:=delete\n");
+          fprintf (outfile, "$ append/new %.*s %s\n", comnamelen-3, child->comname, ofile);
+          fprintf (outfile, "$ delete %.*s;*\n", comnamelen-3, child->comname);
+          DB (DB_JOBS, (_("Append %.*s and cleanup\n"), comnamelen-3, child->comname));
+        }
 
       fclose (outfile);
 
-      sprintf (cmd, "$ @%s", comname);
+      sprintf (cmd, "$ @%s", child->comname);
 
       DB (DB_JOBS, (_("Executing %s instead\n"), cmd));
@@ -579,5 +617,13 @@
       status = lib$get_ef ((unsigned long *)&child->efn);
       if (!(status & 1))
-	return 0;
+        {
+          if (child->comname)
+            {
+              if (!ISDB (DB_JOBS))
+                unlink (child->comname);
+              free (child->comname);
+            }
+          return 0;
+        }
     }
 
@@ -648,7 +694,5 @@
   if (status & 1)
     {
-      pidToAbort= child->pid;
       status= sys$waitfr (child->efn);
-      pidToAbort= 0;
       vmsHandleChildTerm(child);
     }
@@ -678,7 +722,4 @@
     }
 
-  if (comname && !ISDB (DB_JOBS))
-    unlink (comname);
-
   return (status & 1);
 }
Index: /trunk/src/kmk/vpath.c
===================================================================
--- /trunk/src/kmk/vpath.c	(revision 2590)
+++ /trunk/src/kmk/vpath.c	(revision 2591)
@@ -1,6 +1,6 @@
 /* Implementation of pattern-matching file search paths 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 Free Software
-Foundation, Inc.
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
@@ -150,5 +150,5 @@
 
 
-/* Construct the VPATH listing for the pattern and searchpath given.
+/* Construct the VPATH listing for the PATTERN and DIRPATH given.
 
    This function is called to generate selective VPATH lists and also for
@@ -158,7 +158,7 @@
    variable.
 
-   If SEARCHPATH is nil, remove all previous listings with the same
+   If DIRPATH is nil, remove all previous listings with the same
    pattern.  If PATTERN is nil, remove all VPATH listings.  Existing
-   and readable directories that are not "." given in the searchpath
+   and readable directories that are not "." given in the DIRPATH
    separated by the path element separator (defined in make.h) are
    loaded into the directory hash table if they are not there already
@@ -205,5 +205,6 @@
 
 	      /* Free its unused storage.  */
-	      free (path->searchpath);
+              /* MSVC erroneously warns without a cast here.  */
+	      free ((void *)path->searchpath);
 	      free (path);
 	    }
@@ -310,5 +311,6 @@
   else
     /* There were no entries, so free whatever space we allocated.  */
-    free (vpath);
+    /* MSVC erroneously warns without a cast here.  */
+    free ((void *)vpath);
 }
 
@@ -335,9 +337,10 @@
    FILE exists.  If it is found, we return a cached name of the existing file
    and set *MTIME_PTR (if MTIME_PTR is not NULL) to its modtime (or zero if no
-   stat call was done).  Otherwise we return NULL.  */
+   stat call was done). Also set the matching directory index in PATH_INDEX
+   if it is not NULL. Otherwise we return NULL.  */
 
 static const char *
 selective_vpath_search (struct vpath *path, const char *file,
-                        FILE_TIMESTAMP *mtime_ptr)
+                        FILE_TIMESTAMP *mtime_ptr, unsigned int* path_index)
 {
   int not_target;
@@ -519,4 +522,7 @@
           /* Store the name we found and return it.  */
 
+          if (path_index)
+            *path_index = i;
+
           return strcache_add_len (name, (p + 1 - name) + flen);
 	}
@@ -530,8 +536,10 @@
    exists.  If it is found, return the cached name of an existing file, and
    set *MTIME_PTR (if MTIME_PTR is not NULL) to its modtime (or zero if no
-   stat call was done).  Otherwise we return 0.  */
+   stat call was done). Also set the matching directory index in VPATH_INDEX
+   and PATH_INDEX if they are not NULL.  Otherwise we return 0.  */
 
 const char *
-vpath_search (const char *file, FILE_TIMESTAMP *mtime_ptr)
+vpath_search (const char *file, FILE_TIMESTAMP *mtime_ptr,
+              unsigned int* vpath_index, unsigned int* path_index)
 {
   struct vpath *v;
@@ -547,15 +555,29 @@
     return 0;
 
+  if (vpath_index)
+    {
+      *vpath_index = 0;
+      *path_index = 0;
+    }
+
   for (v = vpaths; v != 0; v = v->next)
-    if (pattern_matches (v->pattern, v->percent, file))
-      {
-        const char *p = selective_vpath_search (v, file, mtime_ptr);
-        if (p)
-          return p;
-      }
+    {
+      if (pattern_matches (v->pattern, v->percent, file))
+        {
+          const char *p = selective_vpath_search (
+            v, file, mtime_ptr, path_index);
+          if (p)
+            return p;
+        }
+
+      if (vpath_index)
+        ++*vpath_index;
+    }
+
 
   if (general_vpath != 0)
     {
-      const char *p = selective_vpath_search (general_vpath, file, mtime_ptr);
+      const char *p = selective_vpath_search (
+        general_vpath, file, mtime_ptr, path_index);
       if (p)
         return p;
@@ -564,4 +586,7 @@
   return 0;
 }
+
+
+
 
 
Index: /trunk/src/kmk/w32/Makefile.am
===================================================================
--- /trunk/src/kmk/w32/Makefile.am	(revision 2590)
+++ /trunk/src/kmk/w32/Makefile.am	(revision 2591)
@@ -1,5 +1,5 @@
 # Makefile.am to create libw32.a for mingw32 host.
 # Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
-# 2007 Free Software Foundation, Inc.
+# 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 # This file is part of GNU Make.
 #
Index: /trunk/src/kmk/w32/compat/dirent.c
===================================================================
--- /trunk/src/kmk/w32/compat/dirent.c	(revision 2590)
+++ /trunk/src/kmk/w32/compat/dirent.c	(revision 2591)
@@ -1,5 +1,5 @@
 /* Directory entry code for Window platforms.
 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-2006, 2007 Free Software Foundation, Inc.
+2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
@@ -17,7 +17,5 @@
 
 
-#ifdef KMK
-# include "config.h" /* my_stat */
-#endif
+#include <config.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -142,5 +140,5 @@
 
 	/* fill in struct dirent values */
-	pDir->dir_sdReturn.d_ino = -1;
+	pDir->dir_sdReturn.d_ino = (ino_t)-1;
 	strcpy(pDir->dir_sdReturn.d_name, wfdFindData.cFileName);
 
Index: /trunk/src/kmk/w32/include/dirent.h
===================================================================
--- /trunk/src/kmk/w32/include/dirent.h	(revision 2590)
+++ /trunk/src/kmk/w32/include/dirent.h	(revision 2591)
@@ -1,5 +1,5 @@
 /* Windows version of dirent.h
 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
-2007 Free Software Foundation, Inc.
+2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
Index: /trunk/src/kmk/w32/include/pathstuff.h
===================================================================
--- /trunk/src/kmk/w32/include/pathstuff.h	(revision 2590)
+++ /trunk/src/kmk/w32/include/pathstuff.h	(revision 2591)
@@ -1,5 +1,5 @@
 /* Definitions for Windows path manipulation.
 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
-2007 Free Software Foundation, Inc.
+2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
Index: /trunk/src/kmk/w32/include/sub_proc.h
===================================================================
--- /trunk/src/kmk/w32/include/sub_proc.h	(revision 2590)
+++ /trunk/src/kmk/w32/include/sub_proc.h	(revision 2591)
@@ -1,5 +1,5 @@
 /* Definitions for Windows process invocation.
 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-2006, 2007 Free Software Foundation, Inc.
+2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
@@ -22,9 +22,9 @@
  * Component Name:
  *
- * $Date: 2007/10/24 20:06:32 $
+ * $Date: 2010/07/13 01:20:43 $
  *
  * $Source: /sources/make/make/w32/include/sub_proc.h,v $
  *
- * $Id: sub_proc.h,v 1.10 2007/10/24 20:06:32 eliz Exp $
+ * $Id: sub_proc.h,v 1.12 2010/07/13 01:20:43 psmith Exp $
  */
 
Index: /trunk/src/kmk/w32/include/w32err.h
===================================================================
--- /trunk/src/kmk/w32/include/w32err.h	(revision 2590)
+++ /trunk/src/kmk/w32/include/w32err.h	(revision 2591)
@@ -1,5 +1,5 @@
 /* Definitions for Windows error handling.
 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-2006, 2007 Free Software Foundation, Inc.
+2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
Index: /trunk/src/kmk/w32/pathstuff.c
===================================================================
--- /trunk/src/kmk/w32/pathstuff.c	(revision 2590)
+++ /trunk/src/kmk/w32/pathstuff.c	(revision 2591)
@@ -1,5 +1,5 @@
 /* Path conversion for Windows pathnames.
 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
-2007, 2009 Free Software Foundation, Inc.
+2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
@@ -17,8 +17,7 @@
 
 #include <Windows.h> /* bird */
-#include <stdio.h>   /* bird */
+#include "make.h"
 #include <string.h>
 #include <stdlib.h>
-#include "make.h"
 #include "pathstuff.h"
 
@@ -83,5 +82,5 @@
                 *etok = to_delim;
                 p = ++etok;
-            } else
+	    } else
                 p += strlen(p);
         } else {
Index: /trunk/src/kmk/w32/subproc/NMakefile
===================================================================
--- /trunk/src/kmk/w32/subproc/NMakefile	(revision 2590)
+++ /trunk/src/kmk/w32/subproc/NMakefile	(revision 2591)
@@ -3,5 +3,5 @@
 #
 # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-# 2006, 2007 Free Software Foundation, Inc.
+# 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 # This file is part of GNU Make.
 #
Index: /trunk/src/kmk/w32/subproc/build.bat
===================================================================
--- /trunk/src/kmk/w32/subproc/build.bat	(revision 2590)
+++ /trunk/src/kmk/w32/subproc/build.bat	(revision 2591)
@@ -19,5 +19,5 @@
 @echo off
 rem Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-rem 2005, 2006, 2007 Free Software Foundation, Inc.
+rem 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 rem This file is part of GNU Make.
 rem
Index: /trunk/src/kmk/w32/subproc/misc.c
===================================================================
--- /trunk/src/kmk/w32/subproc/misc.c	(revision 2590)
+++ /trunk/src/kmk/w32/subproc/misc.c	(revision 2591)
@@ -1,5 +1,5 @@
 /* Process handling for Windows
 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-2006, 2007 Free Software Foundation, Inc.
+2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
@@ -16,4 +16,5 @@
 this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
+#include <config.h>
 #include <stddef.h>
 #include <stdlib.h>
@@ -78,5 +79,5 @@
 	}
 
-        free(tmp);
+	free(tmp);
 	return TRUE;
 }
Index: /trunk/src/kmk/w32/subproc/proc.h
===================================================================
--- /trunk/src/kmk/w32/subproc/proc.h	(revision 2590)
+++ /trunk/src/kmk/w32/subproc/proc.h	(revision 2591)
@@ -1,5 +1,5 @@
 /* Definitions for Windows
 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-2006, 2007 Free Software Foundation, Inc.
+2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
Index: /trunk/src/kmk/w32/subproc/sub_proc.c
===================================================================
--- /trunk/src/kmk/w32/subproc/sub_proc.c	(revision 2590)
+++ /trunk/src/kmk/w32/subproc/sub_proc.c	(revision 2591)
@@ -1,5 +1,5 @@
 /* Process handling for Windows.
 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-2006, 2007 Free Software Foundation, Inc.
+2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
@@ -16,6 +16,12 @@
 this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
+#include <config.h>
 #include <stdlib.h>
 #include <stdio.h>
+#ifdef _MSC_VER
+# include <stddef.h>    /* for intptr_t */
+#else
+# include <stdint.h>
+#endif
 #include <process.h>  /* for msvc _beginthreadex, _endthreadex */
 #include <signal.h>
@@ -25,13 +31,13 @@
 #include "proc.h"
 #include "w32err.h"
-#include "config.h"
 #include "debug.h"
 
 static char *make_command_line(char *shell_name, char *exec_path, char **argv);
+extern char *xmalloc (unsigned int);
 
 typedef struct sub_process_t {
-	int sv_stdin[2];
-	int sv_stdout[2];
-	int sv_stderr[2];
+	intptr_t sv_stdin[2];
+	intptr_t sv_stdout[2];
+	intptr_t sv_stderr[2];
 	int using_pipes;
 	char *inp;
@@ -41,5 +47,5 @@
 	char * volatile errp;
 	volatile DWORD errcnt;
-	int pid;
+	pid_t pid;
 	int exit_code;
 	int signal;
@@ -316,10 +322,10 @@
 		return((HANDLE)pproc);
 	}
-	pproc->sv_stdin[0]  = (int) stdin_pipes[0];
-	pproc->sv_stdin[1]  = (int) stdin_pipes[1];
-	pproc->sv_stdout[0] = (int) stdout_pipes[0];
-	pproc->sv_stdout[1] = (int) stdout_pipes[1];
-	pproc->sv_stderr[0] = (int) stderr_pipes[0];
-	pproc->sv_stderr[1] = (int) stderr_pipes[1];
+	pproc->sv_stdin[0]  = (intptr_t) stdin_pipes[0];
+	pproc->sv_stdin[1]  = (intptr_t) stdin_pipes[1];
+	pproc->sv_stdout[0] = (intptr_t) stdout_pipes[0];
+	pproc->sv_stdout[1] = (intptr_t) stdout_pipes[1];
+	pproc->sv_stderr[0] = (intptr_t) stderr_pipes[0];
+	pproc->sv_stderr[1] = (intptr_t) stderr_pipes[1];
 
 	pproc->using_pipes = 1;
@@ -343,7 +349,7 @@
 	 * pipe, bypassing pipes altogether.
 	 */
-	pproc->sv_stdin[1]  = (int) stdinh;
-	pproc->sv_stdout[1] = (int) stdouth;
-	pproc->sv_stderr[1] = (int) stderrh;
+	pproc->sv_stdin[1]  = (intptr_t) stdinh;
+	pproc->sv_stdout[1] = (intptr_t) stdouth;
+	pproc->sv_stderr[1] = (intptr_t) stderrh;
 
 	pproc->last_err = pproc->lerrno = 0;
@@ -354,68 +360,52 @@
 
 static HANDLE
-find_file(char *exec_path, LPOFSTRUCT file_info)
+find_file(const char *exec_path, const char *path_var,
+	  char *full_fname, DWORD full_len)
 {
 	HANDLE exec_handle;
 	char *fname;
 	char *ext;
-#ifdef KMK
-	size_t exec_path_len;
-
-	/*
-	 * if there is an .exe extension there already, don't waste time here.
-	 * If .exe scripts become common, they can be handled in a CreateProcess
-	 * failure path instead of here.
-	 */
-	exec_path_len = strlen(exec_path);
-	if (	exec_path_len > 4
-		&&	exec_path[exec_path_len - 4] == '.'
-		&&  !stricmp(exec_path + exec_path_len - 3, "exe")){
-		return((HANDLE)HFILE_ERROR);
-	}
-
-	fname = malloc(exec_path_len + 5);
-#else
-	fname = malloc(strlen(exec_path) + 5);
-#endif
+	DWORD req_len;
+	int i;
+	static const char *extensions[] =
+	  /* Should .com come before no-extension case?  */
+	  { ".exe", ".cmd", ".bat", "", ".com", NULL };
+
+	fname = xmalloc(strlen(exec_path) + 5);
 	strcpy(fname, exec_path);
 	ext = fname + strlen(fname);
 
-	strcpy(ext, ".exe");
-	if ((exec_handle = (HANDLE)OpenFile(fname, file_info,
-			OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) {
-		free(fname);
-		return(exec_handle);
-	}
-
-	strcpy(ext, ".cmd");
-	if ((exec_handle = (HANDLE)OpenFile(fname, file_info,
-			OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) {
-		free(fname);
-		return(exec_handle);
-	}
-
-	strcpy(ext, ".bat");
-	if ((exec_handle = (HANDLE)OpenFile(fname, file_info,
-			OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) {
-		free(fname);
-		return(exec_handle);
-	}
-
-	/* should .com come before this case? */
-	if ((exec_handle = (HANDLE)OpenFile(exec_path, file_info,
-			OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) {
-		free(fname);
-		return(exec_handle);
-	}
-
-	strcpy(ext, ".com");
-	if ((exec_handle = (HANDLE)OpenFile(fname, file_info,
-			OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) {
-		free(fname);
-		return(exec_handle);
+	for (i = 0; extensions[i]; i++) {
+		strcpy(ext, extensions[i]);
+		if (((req_len = SearchPath (path_var, fname, NULL, full_len,
+					    full_fname, NULL)) > 0
+		     /* For compatibility with previous code, which
+			used OpenFile, and with Windows operation in
+			general, also look in various default
+			locations, such as Windows directory and
+			Windows System directory.  Warning: this also
+			searches PATH in the Make's environment, which
+			might not be what the Makefile wants, but it
+			seems to be OK as a fallback, after the
+			previous SearchPath failed to find on child's
+			PATH.  */
+		     || (req_len = SearchPath (NULL, fname, NULL, full_len,
+					       full_fname, NULL)) > 0)
+		    && req_len <= full_len
+		    && (exec_handle =
+				CreateFile(full_fname,
+					   GENERIC_READ,
+					   FILE_SHARE_READ | FILE_SHARE_WRITE,
+					   NULL,
+					   OPEN_EXISTING,
+					   FILE_ATTRIBUTE_NORMAL,
+					   NULL)) != INVALID_HANDLE_VALUE) {
+			free(fname);
+			return(exec_handle);
+		}
 	}
 
 	free(fname);
-	return(exec_handle);
+	return INVALID_HANDLE_VALUE;
 }
 
@@ -440,4 +430,7 @@
 	int file_not_found=0;
 	HANDLE exec_handle;
+	char exec_fname[MAX_PATH];
+	const char *path_var = NULL;
+	char **ep;
 	char buf[256];
 	DWORD bytes_returned;
@@ -447,24 +440,50 @@
 	PROCESS_INFORMATION procInfo;
 	char *envblk=NULL;
-	OFSTRUCT file_info;
-
+#ifdef KMK
+        size_t exec_path_len;
+#endif
+
+
+        /*
+         *  Shell script detection...  if the exec_path starts with #! then
+         *  we want to exec shell-script-name exec-path, not just exec-path
+         *  NT doesn't recognize #!/bin/sh or #!/etc/Tivoli/bin/perl.  We do not
+         *  hard-code the path to the shell or perl or whatever:  Instead, we
+         *  assume it's in the path somewhere (generally, the NT tools
+         *  bin directory)
+         */
+
+#ifdef KMK
+        /* kmk performace: Don't bother looking for shell scripts in .exe files. */
+        exec_path_len = strlen(exec_path);
+        if (exec_path_len > 4
+            && exec_path[exec_path_len - 4] == '.'
+            && !stricmp(exec_path + exec_path_len - 3, "exe")) {
+                exec_handle =  INVALID_HANDLE_VALUE;
+        }
+        else {
+#endif /* KMK */
+        	/* Use the Makefile's value of PATH to look for the program to
+        	   execute, because it could be different from Make's PATH
+        	   (e.g., if the target sets its own value.  */
+        	if (envp)
+        		for (ep = envp; *ep; ep++) {
+        			if (strncmp (*ep, "PATH=", 5) == 0
+        			    || strncmp (*ep, "Path=", 5) == 0) {
+        				path_var = *ep + 5;
+        				break;
+        			}
+        		}
+        	exec_handle = find_file(exec_path, path_var,
+        				exec_fname, sizeof(exec_fname));
+#ifdef KMK
+        }
+#endif
 
 	/*
-	 *  Shell script detection...  if the exec_path starts with #! then
-	 *  we want to exec shell-script-name exec-path, not just exec-path
-	 *  NT doesn't recognize #!/bin/sh or #!/etc/Tivoli/bin/perl.  We do not
-	 *  hard-code the path to the shell or perl or whatever:  Instead, we
-	 *  assume it's in the path somewhere (generally, the NT tools
-	 *  bin directory)
-	 *  We use OpenFile here because it is capable of searching the Path.
+	 * If we couldn't open the file, just assume that Windows will be
+	 * somehow able to find and execute it.
 	 */
-
-	exec_handle = find_file(exec_path, &file_info);
-
-	/*
-	 * If we couldn't open the file, just assume that Windows32 will be able
-	 * to find and execute it.
-	 */
-	if (exec_handle == (HANDLE)HFILE_ERROR) {
+	if (exec_handle == INVALID_HANDLE_VALUE) {
 		file_not_found++;
 	}
@@ -520,6 +539,5 @@
 		command_line = make_command_line( shell_name, exec_path, argv);
 	else
-		command_line = make_command_line( shell_name, file_info.szPathName,
-				 argv);
+		command_line = make_command_line( shell_name, exec_fname, argv);
 
 	if ( command_line == NULL ) {
@@ -541,5 +559,5 @@
 		exec_path = 0;	/* Search for the program in %Path% */
 	} else {
-		exec_path = file_info.szPathName;
+		exec_path = exec_fname;
 	}
 
@@ -608,5 +626,5 @@
 	}
 
-	pproc->pid = (int)procInfo.hProcess;
+	pproc->pid = (pid_t)procInfo.hProcess;
 	/* Close the thread handle -- we'll just watch the process */
 	CloseHandle(procInfo.hThread);
Index: /trunk/src/kmk/w32/subproc/w32err.c
===================================================================
--- /trunk/src/kmk/w32/subproc/w32err.c	(revision 2590)
+++ /trunk/src/kmk/w32/subproc/w32err.c	(revision 2591)
@@ -1,5 +1,5 @@
 /* Error handling for Windows
 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-2006, 2007 Free Software Foundation, Inc.
+2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
