Index: branches/GNU/src/gmake/.cvsignore
===================================================================
--- branches/GNU/src/gmake/.cvsignore	(revision 157)
+++ branches/GNU/src/gmake/.cvsignore	(revision 280)
@@ -12,5 +12,5 @@
 *.cp *.cps *.fn *.fns *.vr *.vrs *.tp *.tps *.ky *.kys *.pg *.pgs
 
-README README.DOS README.W32
+README README.DOS README.W32 README.OS2
 aclocal.m4 autom4te.cache
 config.h.in config.h config.status config.cache configure
Index: branches/GNU/src/gmake/AUTHORS
===================================================================
--- branches/GNU/src/gmake/AUTHORS	(revision 157)
+++ branches/GNU/src/gmake/AUTHORS	(revision 280)
@@ -7,4 +7,6 @@
 Development starting with GNU make 3.76 by:
     Paul D. Smith <psmith@gnu.org>
+    Additional development starting with GNU make 3.81 by:
+        Boris Kolpackov <boris@kolpackov.net>
 
 
@@ -24,4 +26,5 @@
   Port to VMS by:
       Klaus Kaempf <kkaempf@progis.de>
+      Hartmut Becker <Hartmut.Becker@hp.com>
       Archive support/Bug fixes by:
         John W. Eaton <jwe@bevo.che.wisc.edu>
@@ -31,9 +34,11 @@
       Aaron Digulla <digulla@fh-konstanz.de>
 
-
-  Port to MS-DOS (DJGPP) and MS-Windows 95/NT by:
+  Port to MS-DOS (DJGPP), OS/2, and MS-Windows (native/MinGW) by:
       DJ Delorie <dj@delorie.com>
       Rob Tulloh <rob_tulloh@tivoli.com>
       Eli Zaretskii <eliz@is.elta.co.il>
+      Jonathan Grant <jg@jguk.org>
+      Andreas Beuning <andreas.buening@nexgo.de>
+      Earnie Boyd <earnie@uses.sf.net>
 
 -----------------------------------
@@ -48,5 +53,7 @@
   David Lubbren <uhay@rz.uni-karlsruhe.de>
   Tim Magill <tim.magill@telops.gte.com>
+  Markus Mauhart <qwe123@chello.at>
   Greg McGary <greg@mcgary.org>
+  Thomas Riedl <thomas.riedl@siemens.com>
   Han-Wen Nienhuys <hanwen@cs.uu.nl>
   Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
Index: branches/GNU/src/gmake/ChangeLog
===================================================================
--- branches/GNU/src/gmake/ChangeLog	(revision 157)
+++ branches/GNU/src/gmake/ChangeLog	(revision 280)
@@ -1,2 +1,645 @@
+2005-05-13  Paul D. Smith  <psmith@gnu.org>
+
+	Implement "if... else if... endif" syntax.
+
+	* read.c (eval): Push all checks for conditional words ("ifeq",
+	"else", etc.) down into the conditional_line() function.
+	(conditional_line): Rework to allow "else if..." clause.  New
+	return value -2 for lines which are not conditionals.  The
+	ignoring flag can now also be 2, which means "already parsed a
+	true branch".  If that value is seen no other branch of this
+	conditional can be considered true.  In the else parsing if there
+	is extra text after the else, invoke conditional_line()
+	recursively to see if it's another conditional.  If not, it's an
+	error.  If so, raise the conditional value to this level instead
+	of creating a new conditional nesting level.  Special check for
+	"else" and "endif", which aren't allowed on the "else" line.
+	* doc/make.texi (Conditional Syntax): Document the new syntax.
+
+2005-05-09  Paul D. Smith  <psmith@gnu.org>
+
+	* Makefile.am (EXTRA_make_SOURCES): Add vmsjobs.c
+	(MAYBE_W32): Rework how SUBDIRS are handled so that "make dist"
+	recurses to the w32 directory, even on non-Windows systems.  Use
+	the method suggested in the automake manual.
+	* configure.in: Add w32/Makefile to AC_CONFIG_FILES.
+	* maintMakefile (gnulib-url): They moved the texinfo.tex files.
+
+2005-05-07  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (die): If we're dying with a fatal error (not that a
+	command has failed), write back any leftover tokens before we go.
+
+	* job.c (set_child_handler_action_flags): If there are jobs
+	waiting for the load to go down, set an alarm to go off in 1
+	second.  This allows us to wake up from a potentially long-lasting
+	read() and start a new job if the load has gone down.  Turn it off
+	after the read.
+	(job_noop): Dummy signal handler function.
+	(new_job): Invoke it with the new semantics.
+
+	* docs/make.texi: Document secondary expansion.  Various cleanups
+	and random work.
+
+2005-05-03  Paul D. Smith  <psmith@gnu.org>
+
+	Rename .DEFAULT_TARGET to .DEFAULT_GOAL: in GNU make terminology
+	the targets which are to ultimately be made are called "goals";
+	see the GNU make manual.  Also, MAKECMDGOALS, etc.
+
+	* filedef.h, read.c, main.c: Change .DEFAULT_TARGET to
+	.DEFAULT_GOAL, and default_target_name to default_goal_name.
+	* doc/make.texi (Special Variables): Document .DEFAULT_GOAL.
+
+2005-05-02  Paul D. Smith  <psmith@gnu.org>
+
+	* job.c, vmsjobs.c (vmsWaitForChildren, vms_redirect,
+	vms_handle_apos, vmsHandleChildTerm, reEnableAst, astHandler,
+	tryToSetupYAst, child_execute_job) [VMS]: Move VMS-specific
+	functions to vmsjobs.c.  #include it into jobs.c.
+
+	Grant Taylor <gtaylor@picante.com> reports that -j# can lose
+	jobserver tokens.  I found that this happens when an exported
+	recursive variable contains a $(shell ...) function reference: in
+	this situation we could "forget" to write back a token.
+
+	* job.c, job.h: Add variable jobserver_tokens: counts the tokens
+	we have.  It's not reliable to depend on the number of children in
+	our linked list so keep a separate count.
+	(new_job): Check jobserver_tokens rather than children &&
+	waiting_jobs.  Increment jobserver_tokens when we get one.
+	(free_child): If jobserver_tokens is 0, internal error.  If it's
+	>1, write a token back to the jobserver pipe (we don't write a
+	token for the "free" job).  Decrement jobserver_tokens.
+
+	* main.c: Add variable master_job_slots.
+	(main): Set it to hold the number of jobs requested if we're the
+	master process, when using the jobserver.
+	(die): Sanity checks: first test jobserver_tokens to make sure
+	this process isn't holding any tokens we didn't write back.
+	Second, if master_job_slots is set count the tokens left in the
+	jobserver pipe and ensure it's the same as master_job_slots (- 1).
+
+2005-04-24  Paul D. Smith  <psmith@gnu.org>
+
+	Grant Taylor <gtaylor@picante.com> reports that -j# in conjunction
+	with -l# can lose jobserver tokens, because waiting jobs are not
+	consulted properly when checking for the "free" token.
+
+	* job.c (free_child): Count waiting_jobs as having tokens.
+	* job.c (new_job): Ditto.  Plus, call start_waiting_jobs() here to
+	handle jobs waiting for the load to drop.
+
+2005-04-23  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (main): Be careful to not core if a variable setting in
+	the environment doesn't contain an '='.  This is illegal but can
+	happen in broken setups.
+	Reported by Joerg Schilling <schilling@fokus.fraunhofer.de>.
+
+2005-04-12  Paul D. Smith  <psmith@gnu.org>
+
+	The second expansion feature causes significant slowdown.  Timing
+	a complex makefile (GCC 4.1) shows a slowdown from .25s to just
+	read the makefile before the feature, to 11+s to do the same
+	operations after the feature.  Additionally, memory usage
+	increased drastically.  To fix this I added some intelligence that
+	avoids the overhead of the second expansion unless it's required.
+
+	* dep.h: Add a new boolean field, need_2nd_expansion.
+
+	* read.c (eval): When creating the struct dep for the target,
+	check if the name contains a "$"; if so set need_2nd_expansion to 1.
+	(record_files): If there's a "%" in a static pattern rule, it gets
+	converted to "$*" so set need_2nd_expansion to 1.
+
+	* file.c (expand_deps): Rework to be more efficient.  Only perform
+	initialize_file_variables(), set_file_variables(), and
+	variable_expand_for_file() if the need_2nd_expansion is set.
+
+	* implicit.c (pattern_search): Default need_2nd_expansion to 0.
+	(pattern_search): Ditto.
+	* main.c (handle_non_switch_argument): Ditto.
+	(main): Ditto.
+	* read.c (read_all_makefiles): Ditto.
+	(eval_makefile): Ditto.
+
+2005-04-07  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (main) [WINDOWS32]: Export PATH to sub-shells, not Path.
+	* variable.c (sync_Path_environment): Ditto.
+	Patch by Alessandro Vesely.  Fixes Savannah bug #12209.
+
+	* main.c (main): Define the .FEATURES variable.
+	* NEWS: Announce .FEATURES.
+	* doc/make.texi (Special Variables): Document .FEATURES.
+
+	* remake.c (check_dep): If a file is .PHONY, update it even if
+	it's marked intermediate.  Fixes Savannah bug #12331.
+
+2005-03-15  Boris Kolpackov  <boris@kolpackov.net>
+
+	* file.c (expand_deps): Factor out the second expansion and
+	prerequisite line parsing logic from snap_deps().
+
+	* file.c (snap_deps): Use expand_deps(). Expand and parse
+	prerequisites of the .SUFFIXES special target first. Fixes
+	Savannah bug #12320.
+
+2005-03-13  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (main) [MSDOS]: Export SHELL in MSDOS.  Requested by Eli
+	Zaretskii.
+
+2005-03-11  Paul D. Smith  <psmith@gnu.org>
+
+	* signame.c (strsignal): HAVE_DECL_SYS_SIGLIST is 0 when not
+	available, not undefined (from Earnie Boyd).
+
+2005-03-10  Boris Kolpackov  <boris@kolpackov.net>
+
+	* implicit.c (pattern_search): Mark an intermediate target as
+	precious if it happened to be a prerequisite of some (other)
+	target. Fixes Savannah bug #12267.
+
+2005-03-09  Paul D. Smith  <psmith@gnu.org>
+
+	* read.c (eval_makefile): Add alloca(0).
+	(eval_buffer): Ditto.
+
+2005-03-09  Boris Kolpackov  <boris@kolpackov.net>
+
+	* main.c (main): Use o_file instead of o_default when defining
+	the .DEFAULT_TARGET special variable.
+	* read.c (eval): Use define_variable_global() instead of
+	define_variable() when setting new value for the .DEFAULT_TARGET
+	special variable.  Fixes Savannah bug #12266.
+
+2005-03-04  Boris Kolpackov  <boris@kolpackov.net>
+
+	* imlicit.c (pattern_search): Mark files for which an implicit
+	rule has been found as targets. Fixes Savannah bug #12202.
+
+2005-03-04  Paul D. Smith  <psmith@gnu.org>
+
+	* AUTHORS: Update.
+	* doc/make.texi (Automatic Variables): Document $|.
+
+2005-03-03  Boris Kolpackov  <boris@kolpackov.net>
+
+	* read.c (record_files): Instead of substituting % with
+	actual stem value in dependency list replace it with $*.
+	This fixes stem triple expansion bug.
+
+	* implicit.c (pattern_search): Copy stem to a separate
+	buffer and make it a properly terminated string. Assign
+	this buffer instead of STEM (which is not terminated) to
+	f->stem. Instead of substituting % with actual stem value
+	in dependency list replace it with $*. This fixes stem
+	triple expansion bug.
+
+2005-03-01  Paul D. Smith  <psmith@gnu.org>
+
+	* commands.c (fatal_error_signal) [WINDOWS32]: Don't call kill()
+	on Windows, as it takes a handle not a pid.  Just exit.
+	Fix from patch #3679, provided by Alessandro Vesely.
+
+	* configure.in: Update check for sys_siglist[] from autoconf manual.
+	* signame.c (strsignal): Update to use the new autoconf macro.
+
+2005-03-01  Boris Kolpackov  <boris@kolpackov.net>
+
+	* read.c (record_files): Add a check for the list of prerequisites
+	of a static pattern rule being empty. Fixes Savannah bug #12180.
+
+2005-02-28  Paul D. Smith  <psmith@gnu.org>
+
+	* doc/make.texi (Text Functions): Update docs to allow the end
+	ordinal for $(wordlist ...) to be 0.
+	* function.c (func_wordlist): Fail if the start ordinal for
+	$(wordlist ...) is <1.  Matches documentation.
+	Resolves Savannah support request #103195.
+
+	* remake.c (update_goal_chain): Fix logic for stopping in -q:
+	previously we were stopping when !-q, exactly the opposite.  This
+	has been wrong since version 1.34, in 1994!
+	(update_file): If we got an error don't break out to run more
+	double-colon rules: just return immediately.
+	Fixes Savannah bug #7144.
+
+2005-02-27  Paul D. Smith  <psmith@gnu.org>
+
+	* misc.c (end_of_token): Make argument const.
+	* make.h: Update prototype.
+
+	* function.c (abspath, func_realpath, func_abspath): Use
+	PATH_VAR() and GET_PATH_MAX instead of PATH_MAX.
+	* dir.c (downcase): Use PATH_VAR() instead of PATH_MAX.
+	* read.c (record_files): Ditto.
+	* variable.c (do_variable_definition): Ditto.
+
+	* function.c (func_error): Create a new function $(info ...) that
+	simply prints the message to stdout with no extras.
+	(function_table_init): Add new function to the table.
+	* NEWS: Add $(info ...) reference.
+	* doc/make.texi (Make Control Functions): Document it.
+
+	New feature: if the system supports symbolic links, and the user
+	provides the -L/--check-symlink-time flag, then use the latest
+	mtime between the symlink(s) and the target file.
+
+	* configure.in (MAKE_SYMLINKS): Check for lstat() and
+	readlink().  If both are available, define MAKE_SYMLINKS.
+	* main.c: New variable: check_symlink_flag.
+	(usage): Add a line for -L/--check-symlink-times to the help string.
+	(switches): Add -L/--check-symlink-times command line argument.
+	(main): If MAKE_SYMLINKS is not defined but the user specified -L,
+	print a warning and disable it again.
+	* make.h: Declare check_symlink_flag.
+	* remake.c (name_mtime): If MAKE_SYMLINKS and check_symlink_flag,
+	if the file is a symlink then check each link in the chain and
+	choose the NEWEST mtime we find as the mtime for the file.  The
+	newest mtime might be the file itself!
+	* NEWS: Add information about this new feature.
+	* doc/make.texi (Options Summary): Add -L/--check-symlink-times docs.
+
+	Avoid core dumps described in Savannah bug # 12124:
+
+	* file.c: New variable snapped_deps remember whether we've run
+	snap_deps().
+	(snap_deps): Set it.
+	* filedef.h: Extern it.
+	* read.c (record_files): Check snapped_deps; if it's set then
+	we're trying to eval a new target/prerequisite relationship from
+	within a command script, which we don't support.  Fatal.
+
+2005-02-28  Boris Kolpackov  <boris@kolpackov.net>
+
+	Implementation of the .DEFAULT_TARGET special variable.
+
+	* read.c (eval): If necessary, update default_target_name when
+	reading rules.
+	* read.c (record_files): Update default_target_file if
+	default_target_name has changed.
+	* main.c (default_target_name): Define.
+	* main.c (main): Enter .DEFAULT_TARGET as make variable. If
+	default_target_name is set use default_target_file as a root
+	target to make.
+	* filedef.h (default_target_name): Declare.
+	* dep.h (free_dep_chain):
+	* misc.c (free_dep_chain): Change to operate on struct nameseq
+	and change name to free_ns_chain.
+	* file.c (snap_deps): Update to use free_ns_chain.
+
+2005-02-27  Boris Kolpackov  <boris@kolpackov.net>
+
+	Implementation of the second expansion in explicit rules,
+	static pattern rules and implicit rules.
+
+	* read.c (eval): Refrain from chopping up rule's dependencies.
+	Store them in a struct dep as a single dependency line. Remove
+	the code that implements SySV-style automatic variables.
+
+	* read.c (record_files): Adjust the code that handles static
+	pattern rules to expand all percents instead of only the first
+	one. Reverse the order in which dependencies are stored so that
+	when the second expansion reverses them again they appear in
+	the makefile order (with some exceptions, see comments in
+	the code). Remove the code that implements SySV-style automatic
+	variables.
+
+	* file.c (snap_deps): Implement the second expansion and chopping
+	of dependency lines for explicit rules.
+
+	* implicit.c (struct idep): Define an auxiliary data type to hold
+	implicit rule's dependencies after stem substitution and
+	expansion.
+
+	* implicit.c (free_idep_chain): Implement.
+
+	* implicit.c (get_next_word): Implement helper function for
+	parsing implicit rule's dependency lines into words taking
+	into account variable expansion requests. Used in the stem
+	splitting code.
+
+	* implicit.c (pattern_search): Implement the second expansion
+	for implicit rules. Also fixes bug #12091.
+
+	* commands.h (set_file_variables): Declare.
+	* commands.c (set_file_variables): Remove static specifier.
+
+	* dep.h (free_dep_chain): Declare.
+	* misc.c (free_dep_chain): Implement.
+
+	* variable.h (variable_expand_for_file): Declare.
+	* expand.c (variable_expand_for_file): Remove static specifier.
+
+	* make.h (strip_whitespace): Declare.
+	* function.c (strip_whitespace): Remove static specifier.
+
+2005-02-26  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (main): Check for ferror() when reading makefiles from stdin.
+	Apparently some shells in Windows don't close pipes properly and
+	require this check.
+
+2005-02-24  Jonathan Grant  <jg@jguk.org>
+
+	* configure.in: Add MinGW configuration options, and extra w32 code
+        directory.
+	* Makefile.am: Add MinGW configuration options, and extra w32 code
+        directory.
+	* main.c: Determine correct program string (after last \ without .exe).
+	* subproc/sub_proc.c: `GetExitCodeProcess' from incompatible pointer
+        type fix x2
+	* w32/Makefile.am: Import to build win32 lib of sub_proc etc.
+	* subproc/w32err.c: MSVC thread directive not applied to MinGW builds.
+	* tests/run_make_tests.pl, tests/test_driver.pl: MSYS testing
+        environment support.
+
+2004-04-16  Dmitry V. Levin  <ldv@altlinux.org>
+
+        * function.c (func_shell): When initializing error_prefix, check
+        that reading file name is not null.  This fixes long-standing
+        segfault in cases like "make 'a1=$(shell :)' 'a2:=$(a1)'".
+
+2005-02-09  Paul D. Smith  <psmith@gnu.org>
+
+	* maintMakefile: Update the CVS download URL to simplify them.
+	Also, the ftp://ftp.gnu.org/GNUinfo site was removed so I'm
+	downloading the .texi files from Savannah now.
+
+	Fixed these issues reported by Markus Mauhart <qwe123@chello.at>:
+
+	* main.c (handle_non_switch_argument): Only add variables to
+	command_variables if they're not already there: duplicate settings
+	waste space and can be confusing to read.
+
+	* w32/include/sub_proc.h: Remove WINDOWS32.  It's not needed since
+	this header is never included by non-WINDOWS32 code, and it
+	requires <config.h> to define which isn't always included first.
+
+	* dir.c (read_dirstream) [MINGW]: Use proper macro names when
+	testing MINGW32 versions.
+
+	* main.c (log_working_directory): flush stdout to be sure the WD
+	change is printed before any stderr messages show up.
+
+2005-02-01  Paul D. Smith  <psmith@gnu.org>
+
+	* maintMakefile (po_repo): Update the GNU translation site URL.
+
+2004-12-01  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (main): Change char* env_shell to struct variable shell_var.
+	* variable.c (target_environment): Use new shell_var.
+
+2004-11-30  Paul D. Smith  <psmith@gnu.org>
+
+	* configure.in: The old way we avoided creating build.sh from
+	build.sh.in before build.sh.in exists doesn't work anymore; we
+	have to use raw M4 (thanks to Andreas Schwab <schwab@suse.de> for
+	the help!).  This also keeps automake from complaining.
+	* Makefile.am (README): Add a dummy target so automake won't
+	complain that this file doesn't exist when we checkout from CVS.
+	* maintMakefile (.dep_segment): Rewrite this rule since newer
+	versions of automake don't provide DEP_FILES.
+
+2004-11-30  Boris Kolpackov  <boris@kolpackov.net>
+
+	Implementation of `realpath' and `abspath' built-in functions.
+
+	* configure.in: Check for realpath.
+	* function.c (abspath): Return an absolute file name that does
+	not contain any `.' or `..' components, nor repeated `/'.
+	* function.c (func_abspath): For each name call abspath.
+	* function.c (func_realpath): For each name call realpath
+	from libc or delegate to abspath if realpath is not available.
+	* doc/make.texi (Functions for File Names): Document new functions.
+	* doc/make.texi (Quick Reference): Ditto.
+
+2004-11-28  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (main) [WINDOWS32]: Remove any trailing slashes from -C
+	arguments.  Fixes bug #10252.
+
+	Fix for bug #1276: Handle SHELL according to POSIX requirements.
+
+	* main.c (main): Set SHELL to v_noexport by default.  Remember the
+	original environment setting of SHELL in the env_shell variable.
+	* main.h: Export new env_shell variable.
+	* variable.c (target_environment): If we find a v_noexport
+	variable for SHELL, add a SHELL variable with the env_shell value.
+	* doc/make.texi (Quick Reference): Document the POSIX behavior.
+	* doc/make.texi (Variables/Recursion): Ditto.
+
+2004-11-28  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (find_and_set_default_shell) [WINDOWS32]: check for
+	equality of "cmd"/"cmd.exe", not inequality.  Fixes bug #11155.
+	Patch by Alessandro Vesely.
+
+2004-11-12  Paul D. Smith  <psmith@gnu.org>
+
+	* job.c (child_execute_job) [VMS]: Don't treat "#" as a comment on
+	the command line if it's inside a string.
+	Patch by: Hartmut Becker <Hartmut.Becker@hp.com>
+
+2004-10-21  Boris Kolpackov  <boris@kolpackov.net>
+
+	* function.c (func_lastword): New function: return last word
+	from the list of words.
+	* doc/make.texi: Document $(lastword ). Fix broken links in
+	Quick Reference section.
+
+2004-10-06  Paul D. Smith  <psmith@gnu.org>
+
+	Apply patch from Alessandro Vesely, provided with bug # 9748.
+	Fix use of tmpnam() to work with Borland C.
+
+	* job.c (construct_command_argv_internal) [WINDOWS32]: Remove
+	construction of a temporary filename, and call new function
+	create_batch_filename().
+	(create_batch_filename) [WINDOWS32]: New function to create a
+	temporary filename.
+
+2004-10-05  Boris Kolpackov  <boris@kolpackov.net>
+
+	* read.c (record_target_var): Expand simple pattern-specific
+	variable.
+	* variable.c (initialize_file_variables): Do not expand simple
+	pattern-specific variable.
+
+2004-09-28  Boris Kolpackov  <boris@kolpackov.net>
+
+	* remake.c (update_file_1): When rebuilding makefiles inherit
+	dontcare flag from a target that triggered update.
+
+2004-09-27  Boris Kolpackov  <boris@kolpackov.net>
+
+	* variable.c (initialize_file_variables): Mark pattern-specific
+	variable as a per-target and copy export status.
+
+2004-09-21  Boris Kolpackov  <boris@kolpackov.net>
+
+	* file.c (snap_deps): Mark .PHONY prerequisites as targets.
+
+	* implicit.c (pattern_search): When considering an implicit rule's
+	prerequisite check that it is actually a target rather then
+	just an entry in the file hashtable.
+
+2004-09-21  Paul D. Smith  <psmith@gnu.org>
+
+	* read.c (readstring): Fix some logic errors in backslash handling.
+	(eval): Remove some unnecessary processing in buffer handling.
+	(record_target_var): Assert that parse_variable_definition() succeeded.
+	Reported by: Markus Mauhart <qwe123@chello.at>.
+
+	* misc.c: Removed the sindex() function.  All instances of this
+	function were trivially replaceable by the standard strstr()
+	function, and that function will always have better (or certainly
+	no worse) performance than the very simple-minded algorithm
+	sindex() used.  This can matter with complex makefiles.
+	* make.h: Remove the prototype for sindex().
+	* function.c (subst_expand): Convert sindex() call to strstr().
+	This means we no longer need to track the TLEN value so remove that.
+	(func_findstring): Convert sindex() to strstr().
+	* commands.c (chop_commands): Convert sindex() calls to strstr().
+	Suggested by: Markus Mauhart <qwe123@chello.at>.
+
+	* main.c (find_and_set_default_shell) [WINDOWS32]: Implement the
+	idea behind Savannah Patch #3144 from david.baird@homemail.com.
+	If SHELL is set to CMD.EXE then assume it's batch-mode and
+	non-unixy.  I wrote the code differently from the patch, though,
+	to make it safer.  This also resolves bug #9174.
+
+2004-09-20  Paul D. Smith  <psmith@gnu.org>
+
+	* expand.c (variable_expand_string): Modify to invoke
+	patsubst_expand() instead of subst_expand(); the latter didn't
+	handle suffix patterns correctly.
+	* function.c (subst_expand): Remove the SUFFIX_ONLY parameter; it
+	was used only from variable_expand_string() and is no longer used
+	there.
+	(func_subst): Ditto, on call to subst_expand().
+	(patsubst_expand): Require the percent pointers to point to the
+	character after the %, not to the % itself.
+	* read.c (record_files): New call criteria for patsubst_expand().
+	* variable.h: Remove SUFFIX_ONLY from subst_expand() prototype.
+	This is to fix a bug reported by Markus Mauhart <qwe123@chello.at>.
+
+2004-09-19  Paul D. Smith  <psmith@gnu.org>
+
+	* function.c (subst_expand): Fix a check in by_word: look for a
+	previous blank if we're beyond the beginning of the string, not
+	the beginning of the word.
+	Bugs reported by Markus Mauhart <qwe123@chello.at>.
+
+2004-05-16  Paul D. Smith  <psmith@gnu.org>
+
+	* remake.c (update_goal_chain): Change the argument specifying
+	whether we're rebuilding makefiles to be a global variable,
+	REBUILDING_MAKEFILES.
+	(complain): Extract the code that complains about no rules to make
+	a target into a separate function.
+	(update_file_1): If we tried to rebuild a file during the makefile
+	rebuild phase and it was dontcare, then no message was printed.
+	If we then try to build the same file during the normal build,
+	print a message this time.
+	(remake_file): Don't complain about un-remake-able files when
+	we're rebuilding makefiles.
+
+2004-05-11  Paul D. Smith  <psmith@gnu.org>
+
+	* job.c (construct_command_argv_internal): OS/2 patches from
+	Andreas Buening <andreas.buening@nexgo.de>.
+
+2004-05-10  Paul D. Smith  <psmith@gnu.org>
+
+	* remake.c (update_file): Don't walk the double-colon chain unless
+	this is a double-colon rule.  Fix suggested by Boris Kolpackov
+	<boris@kolpackov.net>.
+
+	* makefile.vms (CFLAGS): Remove glob/globfree (see readme.vms docs)
+	* readme.vms: New section describing OpenVMS support and issues.
+	* default.c (default_variables): Add support for IA64.
+	* job.c (tryToSetupYAst) [VMS]: On VMS running make in batch mode
+	without some privilege aborts make with the error
+	%SYSTEM-F-NOPRIV. It happens when setting up a handler for
+	pressing Ctrl+Y and the input device is no terminal. The change
+	catches this error and just continues.
+
+	Patches by Hartmut Becker <Hartmut.Becker@hp.com>
+
+2004-04-25  Paul D. Smith  <psmith@gnu.org>
+
+	* commands.c (set_file_variables): Set $< properly in the face of
+	order-only prerequisites.
+	Patch from Boris Kolpackov <boris@kolpackov.net>
+
+2004-04-21  Bob Byrnes  <byrnes@curl.com>
+
+	* main.c (main): Notice failures to remake makefiles.
+
+2004-03-28  Paul D. Smith  <psmith@gnu.org>
+
+	Patches for Acorn RISC OS by Peter Naulls <peter@chocky.org>
+
+	* job.c: No default shell for RISC OS.
+	(load_too_high): Hard-code the return to 1.
+	(construct_command_argv_internal): No sh_chars or sh_cmds.
+	* getloadavg.c: Don't set LOAD_AVE_TYPE on RISC OS.
+
+2004-03-20  Paul D. Smith  <psmith@gnu.org>
+
+	* variable.c (do_variable_definition): Don't append from the
+	global set if a previous non-appending target-specific variable
+	definition exists.  Reported by Oliver Schmidt <oschmidt@gmx.net>
+	(with fix).
+
+	* expand.c (reference_variable): Don't give up on variables with
+	no value that have the target-specific append flag set: they might
+	have a value after all.  Reported by Oliver Schmidt
+	<oschmidt@gmx.net> (with fix) and also by Maksim A. Nikulin
+	<nikulin@dx1cmd.inp.nsk.su>.
+
+	* rule.c (count_implicit_rule_limits): Don't delete patterns which
+	refer to absolute pathnames in directories that don't exist: some
+	portion of the makefile could create those directories before we
+	match the pattern.  Fixes bugs #775 and #108.
+
+	Fixes from Jonathan R. Grant  <jg-make@jguk.org>:
+
+	* main.c (main): Free makefile_mtimes if we have any.
+	* README.W32.template: Update documentation for the current status
+	of the MS-Windows port.
+	* NMakefile.template (MAKE): Add "MAKE = nmake".  A conflicting
+	environment variable is sometimes already defined which causes the
+	build to fail.
+	* main.c (debug_signal_handler): Only define this function if
+	SIGUSR1 is available.
+
+	Fixes for OS/2 from Andreas Beuning <andreas.buening@nexgo.de>:
+
+	* configure.in [OS/2]: Relocate setting of HAVE_SA_RESTART for OS/2.
+	* README.OS2.template: Documentation updates.
+	* build.template: Add LIBINTL into LOADLIBES.  Add $CFLAGS to the
+	link line for safety.
+	* maintMakefile (build.sh.in): Remove an extraneous ")".
+	* job.c (child_execute_job): Close saved FDs.
+	* job.c (exec_command) [OS/2]: exec_command(): If the command
+	can't be exec'ed and if the shell is not Unix-sh, then try again
+	with argv = { "cmd", "/c", ... }. Normally, this code is never
+	reached for the cmd shell unless the command really doesn't exist.
+	(construct_command_argv_internal) [OS/2]: The code for cmd
+	handling now uses new_argv = { "cmd", "/c", "original line", NULL}.
+	The CMD builtin commands are case insensitive so use strcasecmp().
+
+2004-03-19  Paul D. Smith  <psmith@gnu.org>
+
+	* read.c (do_define): Re-order line counter increment so the count
+	is accurate (we were losing one line per define).  Reported by
+	Dave Yost <Dave@Yost.com>.
+
 2004-03-06  Paul D. Smith  <psmith@gnu.org>
 
@@ -160,4 +803,9 @@
 	(get-config/config.guess get-config/config.sub): Get these files
 	from the Savannah config project instead of ftp.gnu.org.
+
+2003-10-05  Paul Eggert  <eggert@twinsun.com>
+
+	* main.c (main): Avoid potential subscript error if environ has
+	short strings.
 
 2003-08-22  Paul D. Smith  <psmith@gnu.org>
@@ -1052,4 +1700,13 @@
 	* i18n/ja.po: Installed an updated translation.
 
+2001-09-06  Paul Eggert  <eggert@twinsun.com>
+
+	* configure.in (AC_CHECK_HEADERS): Add sys/resource.h.
+	(AC_CHECK_FUNCS): Add getrlimit, setrlimit.
+
+	* main.c: Include <sys/resource.h> if it, getrlimit, and setrlimit
+	are available.
+	(main): Get rid of any avoidable limit on stack size.
+
 2001-09-04  Paul D. Smith  <psmith@gnu.org>
 
Index: branches/GNU/src/gmake/INSTALL
===================================================================
--- branches/GNU/src/gmake/INSTALL	(revision 157)
+++ branches/GNU/src/gmake/INSTALL	(revision 280)
@@ -1,6 +1,9 @@
-Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
-Foundation, Inc.
-
-   This file is free documentation; the Free Software Foundation gives
+Installation Instructions
+*************************
+
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004 Free
+Software Foundation, Inc.
+
+This file is free documentation; the Free Software Foundation gives
 unlimited permission to copy, distribute and modify it.
 
@@ -8,5 +11,5 @@
 ==================
 
-   These are generic installation instructions.
+These are generic installation instructions.
 
    The `configure' shell script attempts to guess correct values for
@@ -68,7 +71,7 @@
 =====================
 
-   Some systems require unusual options for compilation or linking that
-the `configure' script does not know about.  Run `./configure --help'
-for details on some of the pertinent environment variables.
+Some systems require unusual options for compilation or linking that the
+`configure' script does not know about.  Run `./configure --help' for
+details on some of the pertinent environment variables.
 
    You can give `configure' initial values for configuration parameters
@@ -83,5 +86,5 @@
 ====================================
 
-   You can compile the package for more than one kind of computer at the
+You can compile the package for more than one kind of computer at the
 same time, by placing the object files for each architecture in their
 own directory.  To do this, you must use a version of `make' that
@@ -100,17 +103,17 @@
 ==================
 
-   By default, `make install' will install the package's files in
+By default, `make install' will install the package's files in
 `/usr/local/bin', `/usr/local/man', etc.  You can specify an
 installation prefix other than `/usr/local' by giving `configure' the
-option `--prefix=PATH'.
+option `--prefix=PREFIX'.
 
    You can specify separate installation prefixes for
 architecture-specific files and architecture-independent files.  If you
-give `configure' the option `--exec-prefix=PATH', the package will use
-PATH as the prefix for installing programs and libraries.
+give `configure' the option `--exec-prefix=PREFIX', the package will
+use PREFIX as the prefix for installing programs and libraries.
 Documentation and other data files will still use the regular prefix.
 
    In addition, if you use an unusual directory layout you can give
-options like `--bindir=PATH' to specify different values for particular
+options like `--bindir=DIR' to specify different values for particular
 kinds of files.  Run `configure --help' for a list of the directories
 you can set and what kinds of files go in them.
@@ -123,5 +126,5 @@
 =================
 
-   Some packages pay attention to `--enable-FEATURE' options to
+Some packages pay attention to `--enable-FEATURE' options to
 `configure', where FEATURE indicates an optional part of the package.
 They may also pay attention to `--with-PACKAGE' options, where PACKAGE
@@ -138,9 +141,9 @@
 ==========================
 
-   There may be some features `configure' cannot figure out
-automatically, but needs to determine by the type of machine the package
-will run on.  Usually, assuming the package is built to be run on the
-_same_ architectures, `configure' can figure that out, but if it prints
-a message saying it cannot guess the machine type, give it the
+There may be some features `configure' cannot figure out automatically,
+but needs to determine by the type of machine the package will run on.
+Usually, assuming the package is built to be run on the _same_
+architectures, `configure' can figure that out, but if it prints a
+message saying it cannot guess the machine type, give it the
 `--build=TYPE' option.  TYPE can either be a short name for the system
 type, such as `sun4', or a canonical name which has the form:
@@ -168,7 +171,7 @@
 ================
 
-   If you want to set default values for `configure' scripts to share,
-you can create a site shell script called `config.site' that gives
-default values for variables like `CC', `cache_file', and `prefix'.
+If you want to set default values for `configure' scripts to share, you
+can create a site shell script called `config.site' that gives default
+values for variables like `CC', `cache_file', and `prefix'.
 `configure' looks for `PREFIX/share/config.site' if it exists, then
 `PREFIX/etc/config.site' if it exists.  Or, you can set the
@@ -179,5 +182,5 @@
 ==================
 
-   Variables not defined in a site shell script can be set in the
+Variables not defined in a site shell script can be set in the
 environment passed to `configure'.  However, some packages may run
 configure again during the build, and the customized values of these
@@ -193,6 +196,5 @@
 ======================
 
-   `configure' recognizes the following options to control how it
-operates.
+`configure' recognizes the following options to control how it operates.
 
 `--help'
Index: branches/GNU/src/gmake/Makefile.am
===================================================================
--- branches/GNU/src/gmake/Makefile.am	(revision 157)
+++ branches/GNU/src/gmake/Makefile.am	(revision 280)
@@ -4,5 +4,12 @@
 ACLOCAL_AMFLAGS	=  -I config
 
-SUBDIRS =	glob config po doc
+# Only process if target is MS-Windows
+if WINDOWSENV
+  MAYBE_W32 =	w32
+  W32INC =	-I $(top_srcdir)/w32/include
+  W32LIB =	-Lw32 -lw32
+endif
+
+SUBDIRS =	glob config po doc $(MAYBE_W32)
 
 bin_PROGRAMS =	make
@@ -20,5 +27,5 @@
 		variable.c version.c vpath.c hash.c
 
-EXTRA_make_SOURCES = remote-stub.c remote-cstms.c
+EXTRA_make_SOURCES = vmsjobs.c remote-stub.c remote-cstms.c
 
 noinst_HEADERS = commands.h dep.h filedef.h job.h make.h rule.h variable.h \
@@ -26,4 +33,8 @@
 
 make_LDADD =	@LIBOBJS@ @ALLOCA@ $(GLOBLIB) @GETLOADAVG_LIBS@ @LIBINTL@
+# Only process if target is MS-Windows
+if WINDOWSENV
+    make_LDADD += $(W32LIB)
+endif
 
 man_MANS =	make.1
@@ -32,4 +43,8 @@
 
 AM_CPPFLAGS =	$(GLOBINC)
+# Only process if target is MS-Windows
+if WINDOWSENV
+    AM_CPPFLAGS +=	$(W32INC)
+endif
 
 
@@ -115,9 +130,9 @@
 .PHONY: check-loadavg check-regression
 
-check-loadavg: loadavg
+check-loadavg: loadavg$(EXEEXT)
 	@echo The system uptime program believes the load average to be:
 	-uptime
 	@echo The GNU load average checking code thinks:
-	-./loadavg
+	-./loadavg$(EXEEXT)
 
 # The loadavg function is invoked during "make check" to test getloadavg.
@@ -158,3 +173,9 @@
 # --------------- Maintainer's Section
 
+# Tell automake that I haven't forgotten about this file and it will be
+# created before we build a distribution (see maintMakefile in the CVS
+# distribution).
+
+README:
+
 @MAINT_MAKEFILE@
Index: branches/GNU/src/gmake/NEWS
===================================================================
--- branches/GNU/src/gmake/NEWS	(revision 157)
+++ branches/GNU/src/gmake/NEWS	(revision 280)
@@ -1,20 +1,42 @@
 GNU make NEWS                                               -*-indented-text-*-
   History of user-visible changes.
-  06 March 2004
-
-Copyright (C) 2002,2003,2004  Free Software Foundation, Inc.
+  13 May 2005
+
+Copyright (C) 2002,2003,2004,2005  Free Software Foundation, Inc.
 See the end for copying conditions.
 
 All changes mentioned here are more fully described in the GNU make
 manual, which is contained in this distribution as the file doc/make.texi.
-
-Please send GNU make bug reports to <bug-make@gnu.org>.
-See the README file and the GNU make manual for details on reporting bugs.
-
-
-Version 3.81beta1
+See the README file and the GNU make manual for instructions for
+reporting bugs.
+
+
+Version 3.81beta3
 
 * GNU make is ported to OS/2.
-  Port provided by Andreas Buening <andreas.buening@nexgo.de>.
+
+* GNU make is ported to MinGW.
+
+* WARNING: Backward-incompatibility!
+  GNU make now implements a generic "second expansion" feature on the
+  prerequisites of both explicit and implicit (pattern) rules.  After
+  all rules have been parsed the prerequisites are expanded again, this
+  time with all the automatic variables in scope.  This means that in
+  addition to using standard SysV $$@ in prerequisites lists, you can
+  also use complex functions such as $$(notdir $$@) etc.  This behavior
+  applies to implicit rules, as well, where the second expansion occurs
+  after the rule is matched.  However, this means that you need to
+  double-quote any "$" in your filenames; instead of "foo: boo$$bar" you
+  must write "foo: foo$$$$bar"
+
+* New command-line option: -L (--check-symlink-times).  On systems that
+  support symbolic links, if this option is given then GNU make will
+  use the most recent modification time of any symbolic links that are
+  used to resolve target files.  The default behavior remains as it
+  always has: use the modification time of the actual target file only.
+
+* The "else" conditional line can now be followed by any other legal
+  conditional on the same line: this does not increase the depth of the
+  conditional nesting.
 
 * All pattern-specific variables that match a given target are now used
@@ -30,12 +52,45 @@
   This version of GNU make uses an algorithm suggested by Thomas Riedl
   <thomas.riedl@siemens.com> to track the number of jobs started in the
-  last second and adjust GNU make's view of the system's load average
-  accordingly.
-
-* Enhancements for POSIX compatibility:
+  last second and artificially adjust GNU make's view of the system's
+  load average accordingly.
+
+* New special variables available in this release:
+   - .FEATURES: Contains a list of special features available in this
+     version of GNU make.
+   - .DEFAULT_GOAL: Set the name of the default goal make will
+     use if no goals are provided on the command line.
+   - New automatic variable: $| (added in 3.80, actually): contains all
+     the order-only prerequisites defined for the target.
+
+* New functions available in this release:
+   - $(lastword ...) returns the last word in the list.  This gives
+     identical results as $(word $(words ...) ...), but is much faster.
+   - $(abspath ...) returns the absolute path (all "." and ".."
+     directories resolved, and any duplicate "/" characters removed) for
+     each path provided.
+   - $(realpath ...) returns the canonical pathname for each path
+     provided.  The canonical pathname is the absolute pathname, with
+     all symbolic links resolved as well.
+   - $(info ...) prints informative messages to stdout.  No makefile
+     name or line number info, etc. is printed, just the message.
+
+* Changes made for POSIX compatibility:
    - Only touch targets (under -t) if they have at least one command.
+   - Setting the SHELL make variable does NOT change the value of the
+     SHELL environment variable given to programs invoked by make.  As
+     an enhancement to POSIX, if you export the make variable SHELL then
+     it will be set in the environment, just as before.
+
+* On DOS and MS Windows systems, explicitly setting SHELL to a pathname
+  ending in "cmd" or "cmd.exe" (case-insensitive) will force GNU make to
+  use the DOS command interpreter in batch mode even if a UNIX-like
+  shell could be found on the system.
 
 * Updated to autoconf 2.59, automake 1.8.2, and gettext 0.14.1.  Users
   should not be impacted.
+
+* New translations for Swedish, Chinese (simplified), Ukrainian,
+  Belarusian, Finnish, Kinyarwandan, and Irish.  Many updated
+  translations.
 
 
Index: branches/GNU/src/gmake/NMakefile.template
===================================================================
--- branches/GNU/src/gmake/NMakefile.template	(revision 157)
+++ branches/GNU/src/gmake/NMakefile.template	(revision 280)
@@ -26,4 +26,5 @@
 LINK = link
 CC = cl
+MAKE = nmake
 
 OUTDIR=.
Index: branches/GNU/src/gmake/README.OS2.template
===================================================================
--- branches/GNU/src/gmake/README.OS2.template	(revision 157)
+++ branches/GNU/src/gmake/README.OS2.template	(revision 280)
@@ -47,5 +47,5 @@
 
  - sh compatible shell (ksh, bash, ash, but tested only with pdksh 5.2.14
-   (release 2)
+   release 2)
    If you use pdksh it is recommended to update to 5.2.14 release 2. Older
    versions may not work! You can get this version at
@@ -60,10 +60,10 @@
  - grep
  - sed
- - GNU make 3.79.1 (special OS/2 patched version)
+ - GNU make 3.79.1 (special OS/2 patched version) or higher
  - perl 5.005 or higher
  - GNU texinfo (you can use 3.1 (gnuinfo.zip), but I recommend 4.0)
 
 If you want to recreate the configuration files (developers only!)
-you need also: GNU m4 1.4, autoconf 2.57, automake 1.7.2 (or compatible)
+you need also: GNU m4 1.4, autoconf 2.59, automake 1.8.2 (or compatible)
 
 
@@ -148,10 +148,10 @@
 
   export CPPFLAGS="-D__ST_MT_ERRNO__ -DNO_CMD_DEFAULT -DNO_CHDIR2"
-  export CFLAGS="-Zomf -O2 -s -Zmt"
-  export LDFLAGS="-Zcrtdll -Zmt -s -Zlinker /exepack:2 -Zlinker /pm:vio -Zstack 0x8000"
+  export CFLAGS="-Zomf -O2 -Zmt"
+  export LDFLAGS="-Zcrtdll -s -Zlinker /exepack:2 -Zlinker /pm:vio -Zstack 0x8000"
   export RANLIB="echo"
   ./configure --prefix=x:/usr --disable-nls
   make AR=emxomfar
-  make checks
+  make check
 
 All tests should work fine with the exception of "default_names" which
Index: branches/GNU/src/gmake/README.W32.template
===================================================================
--- branches/GNU/src/gmake/README.W32.template	(revision 157)
+++ branches/GNU/src/gmake/README.W32.template	(revision 280)
@@ -6,5 +6,5 @@
 Tulloh, who is also the author of this README.
 
-To build with nmake on Windows NT, Windows 95, or Windows 98:
+To build with nmake on MS-Windows:
 
 	1. Make sure cl.exe is in your %Path%. Example:
@@ -64,12 +64,12 @@
 	There are very few true ports of Bourne shell for NT right now.
 	There is a version of GNU bash available from Cygnus "Cygwin"
-	porting effort (http://sourceware.cygnus.com/cygwin).
+	porting effort (http://www.cygwin.com/).
 	Other possibilities are the MKS version of sh.exe, or building
         your own with a package like NutCracker (DataFocus) or Portage
-        (Consensys).
+        (Consensys).  Also MinGW includes sh (http://mingw.org/).
 
 GNU make and brain-dead shells (BATCH_MODE_ONLY_SHELL):
 
-	Some versions of Bourne shell does not behave well when invoked
+	Some versions of Bourne shell do not behave well when invoked
 	as 'sh -c' from CreateProcess().  The main problem is they seem
 	to have a hard time handling quoted strings correctly. This can
@@ -80,9 +80,12 @@
 	a batch mode.  When BATCH_MODE_ONLY_SHELL is defined at compile
 	time, make forces all command lines to be executed via script
-	files instead of by command line.
+	files instead of by command line.  In this mode you must have a
+	working sh.exe in order to use parallel builds (-j).
 
 	A native Windows32 system with no Bourne shell will also run
 	in batch mode.  All command lines will be put into batch files
-	and executed via $(COMSPEC) (%COMSPEC%).
+	and executed via $(COMSPEC) (%COMSPEC%).  Note that parallel
+        builds (-j) require a working Bourne shell; they will not work
+        with COM.
 
 GNU make and Cygnus GNU Windows32 tools:
@@ -129,5 +132,6 @@
 	specification of paths.	 Make is able to figure out the intended
 	result and convert the paths internally to the format needed
-	when interacting with the operating system.
+	when interacting with the operating system, providing the path
+	is not within quotes, e.g. "x:/test/test.c".
 
 	You are encouraged to use colon as the separator character.
@@ -165,13 +169,15 @@
 
 	Unlike Unix, Windows 95/NT systems encourage pathnames which
-	contain white space (e.g. C:\Program Files\). These sorts of pathnames
-	are legal under Unix too, but are never encouraged. There is
-	at least one place in make (VPATH/vpath handling) where paths
-	containing white space will simply not work. There may be others
-	too. I chose to not try and port make in such a way so that
-	these sorts of paths could be handled. I offer these suggestions
-	as workarounds:
-
-		1. Use 8.3 notation
+	contain white space (e.g. C:\Program Files\). These sorts of
+	pathnames are legal under Unix too, but are never encouraged.
+	There is at least one place in make (VPATH/vpath handling) where
+	paths containing white space will simply not work. There may be
+	others too. I chose to not try and port make in such a way so
+	that these sorts of paths could be handled. I offer these
+	suggestions as workarounds:
+
+		1. Use 8.3 notation. i.e. "x:/long~1/", which is actually
+		   "x:\longpathtest".  Type "dir /x" to view these filenames
+		   within the cmd.exe shell.
 		2. Rename the directory so it does not contain white space.
 
Index: branches/GNU/src/gmake/README.cvs
===================================================================
--- branches/GNU/src/gmake/README.cvs	(revision 157)
+++ branches/GNU/src/gmake/README.cvs	(revision 280)
@@ -24,8 +24,8 @@
 -----------------
 
-To build GNU make from CVS, you will need Autoconf 2.57 (or better),
-Automake 1.7.3 (or better), and Gettext 0.11.5 (or better), and any
-tools that those utilities require (GNU m4, Perl, etc.).  You will also
-need a copy of wget.
+To build GNU make from CVS, you will need Autoconf, Automake, and
+Gettext, and any tools that those utilities require (GNU m4, Perl,
+etc.).  See the configure.in file to find the minimum versions of each
+of these tools.  You will also need a copy of wget.
 
 After checking out the code, you will need to perform these steps to get
Index: branches/GNU/src/gmake/README.template
===================================================================
--- branches/GNU/src/gmake/README.template	(revision 157)
+++ branches/GNU/src/gmake/README.template	(revision 280)
@@ -71,5 +71,5 @@
 project to submit new problem reports or search for existing ones:
 
-  http://savannah.gnu.org/bugs/?group_id=71
+  http://savannah.gnu.org/bugs/?group=make
 
 If you need help using GNU make, try these forums:
@@ -80,9 +80,9 @@
   news:gnu.utils.bug
 
-  http://savannah.gnu.org/support/?group_id=71
+  http://savannah.gnu.org/support/?group=make
 
 You may also find interesting patches to GNU Make available here:
 
-  http://savannah.gnu.org/patch/?group_id=71
+  http://savannah.gnu.org/patch/?group=make
 
 Note these patches are provided by our users as a service and we make no
@@ -98,5 +98,5 @@
 GNU Subversions CVS server; look here for details:
 
-  http://savannah.gnu.org/cvs/?group_id=71
+  http://savannah.gnu.org/cvs/?group=make
 
 Please note: you won't be able to build GNU make from CVS without
@@ -113,6 +113,12 @@
 
 It has been reported that the XLC 1.2 compiler on AIX 3.2 is buggy such
-that if you compile make with `cc -O' on AIX 3.2, it will not work correctly.
-It is said that using `cc' without `-O' does work.
+that if you compile make with `cc -O' on AIX 3.2, it will not work
+correctly.  It is said that using `cc' without `-O' does work.
+
+The standard /bin/sh on SunOS 4.1.3_U1 and 4.1.4 is broken and cannot be
+used to configure GNU make.  Please install a different shell such as
+bash or pdksh in order to run "configure".  See this message for more
+information:
+  http://mail.gnu.org/archive/html/bug-autoconf/2003-10/msg00190.html
 
 One area that is often a problem in configuration and porting is the code
Index: branches/GNU/src/gmake/build.template
===================================================================
--- branches/GNU/src/gmake/build.template	(revision 157)
+++ branches/GNU/src/gmake/build.template	(revision 280)
@@ -3,5 +3,5 @@
 # @configure_input@
 
-# Copyright (C) 1993, 1994, 1997, 2003 Free Software Foundation, Inc.
+# Copyright (C) 1993, 1994, 1997, 2003, 2004 Free Software Foundation, Inc.
 # This file is part of GNU Make.
 #
@@ -29,5 +29,5 @@
 LDFLAGS='@LDFLAGS@'
 ALLOCA='@ALLOCA@'
-LOADLIBES='@LIBS@'
+LOADLIBES='@LIBS@ @LIBINTL@'
 eval extras=\'@LIBOBJS@\'
 REMOTE='@REMOTE@'
@@ -79,5 +79,5 @@
 # Link all the objects together.
 echo linking make...
-$CC $LDFLAGS $objs $LOADLIBES -o makenew${EXEEXT}
+$CC $CFLAGS $LDFLAGS $objs $LOADLIBES -o makenew${EXEEXT}
 echo done
 mv -f makenew${EXEEXT} make${EXEEXT}
Index: branches/GNU/src/gmake/commands.c
===================================================================
--- branches/GNU/src/gmake/commands.c	(revision 157)
+++ branches/GNU/src/gmake/commands.c	(revision 280)
@@ -40,7 +40,8 @@
 /* Set FILE's automatic variables up.  */
 
-static void
+void
 set_file_variables (struct file *file)
 {
+  struct dep *d;
   char *at, *percent, *star, *less;
 
@@ -107,6 +108,12 @@
   star = file->stem;
 
-  /* $< is the first dependency.  */
-  less = file->deps != 0 ? dep_name (file->deps) : "";
+  /* $< is the first not order-only dependency.  */
+  less = "";
+  for (d = file->deps; d != 0; d = d->next)
+    if (!d->ignore_mtime)
+      {
+        less = dep_name (d);
+        break;
+      }
 
   if (file->cmds == default_file->cmds)
@@ -136,5 +143,4 @@
     char *qp;
     char *bp;
-    struct dep *d;
     unsigned int len;
 
@@ -343,11 +349,9 @@
             break;
           }
-      if (!(flags & COMMANDS_RECURSE))
-        {
-          unsigned int len = strlen (p);
-          if (sindex (p, len, "$(MAKE)", 7) != 0
-              || sindex (p, len, "${MAKE}", 7) != 0)
-            flags |= COMMANDS_RECURSE;
-        }
+
+      /* If no explicit '+' was given, look for MAKE variable references.  */
+      if (!(flags & COMMANDS_RECURSE)
+          && (strstr (p, "$(MAKE)") != 0 || strstr (p, "${MAKE}") != 0))
+        flags |= COMMANDS_RECURSE;
 
       cmds->lines_flags[idx] = flags;
@@ -482,8 +486,13 @@
 #endif
 
+#ifdef WINDOWS32
+  /* Cannot call W32_kill with a pid (it needs a handle) */
+  exit (EXIT_FAILURE);
+#else
   /* Signal the same code; this time it will really be fatal.  The signal
      will be unblocked when we return and arrive then to kill us.  */
   if (kill (getpid (), sig) < 0)
     pfatal_with_name ("kill");
+#endif /* not WINDOWS32 */
 #endif /* not Amiga */
 #endif /* not __MSDOS__  */
Index: branches/GNU/src/gmake/commands.h
===================================================================
--- branches/GNU/src/gmake/commands.h	(revision 157)
+++ branches/GNU/src/gmake/commands.h	(revision 280)
@@ -41,2 +41,3 @@
 extern void delete_child_targets PARAMS ((struct child *child));
 extern void chop_commands PARAMS ((struct commands *cmds));
+extern void set_file_variables PARAMS ((struct file *file));
Index: branches/GNU/src/gmake/config.ami.template
===================================================================
--- branches/GNU/src/gmake/config.ami.template	(revision 157)
+++ branches/GNU/src/gmake/config.ami.template	(revision 280)
@@ -147,4 +147,7 @@
 /* #undef STAT_MACROS_BROKEN */
 
+/* Define if your compiler conforms to the ANSI C standard. */
+#define HAVE_ANSI_COMPILER 1
+
 /* Define if you have the ANSI C header files.	*/
 #define STDC_HEADERS
@@ -278,4 +281,7 @@
 /* #undef HAVE_NDIR_H */
 
+/* Define to 1 if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
 /* Define if you have the <stdlib.h> header file.  */
 /* #undef HAVE_STDLIB_H */
Index: branches/GNU/src/gmake/config.h-vms.template
===================================================================
--- branches/GNU/src/gmake/config.h-vms.template	(revision 157)
+++ branches/GNU/src/gmake/config.h-vms.template	(revision 280)
@@ -306,4 +306,10 @@
 /* Define if you have the <ndir.h> header file.  */
 /* #undef HAVE_NDIR_H */
+
+/* Define if your compiler conforms to the ANSI C standard. */
+#define HAVE_ANSI_COMPILER 1
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
 
 /* Define if you have the <stdlib.h> header file.  */
Index: branches/GNU/src/gmake/config.h.W32.template
===================================================================
--- branches/GNU/src/gmake/config.h.W32.template	(revision 157)
+++ branches/GNU/src/gmake/config.h.W32.template	(revision 280)
@@ -159,4 +159,10 @@
 /* #undef STAT_MACROS_BROKEN */
 
+/* Define if your compiler conforms to the ANSI C standard. */
+#define HAVE_ANSI_COMPILER 1
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
 /* Define if you have the ANSI C header files.  */
 #undef STDC_HEADERS
Index: branches/GNU/src/gmake/config/.cvsignore
===================================================================
--- branches/GNU/src/gmake/config/.cvsignore	(revision 157)
+++ branches/GNU/src/gmake/config/.cvsignore	(revision 280)
@@ -1,4 +1,6 @@
 *.m4
 config.*
+mkinstalldirs
+texinfo.tex
 
 Makefile Makefile.in
Index: branches/GNU/src/gmake/configh.dos.template
===================================================================
--- branches/GNU/src/gmake/configh.dos.template	(revision 157)
+++ branches/GNU/src/gmake/configh.dos.template	(revision 280)
@@ -57,4 +57,10 @@
 #define HAVE_SELECT 1
 
+/* Define if your compiler conforms to the ANSI C standard. */
+#define HAVE_ANSI_COMPILER 1
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
 /* Define if you have the vprintf library function.  */
 #undef HAVE_VPRINTF
Index: branches/GNU/src/gmake/configure.in
===================================================================
--- branches/GNU/src/gmake/configure.in	(revision 157)
+++ branches/GNU/src/gmake/configure.in	(revision 280)
@@ -1,8 +1,8 @@
 # Process this file with autoconf to produce a configure script.
 
-AC_INIT([GNU make],[3.81beta1],[bug-make@gnu.org])
+AC_INIT([GNU make],[3.81beta3],[bug-make@gnu.org])
 
 AC_PREREQ(2.59)
-AC_REVISION([[$Id: configure.in,v 1.125 2004/03/06 08:05:19 psmith Exp $]])
+AC_REVISION([[$Id: configure.in,v 1.135 2005/05/10 01:38:18 psmith Exp $]])
 
 # Autoconf setup
@@ -51,5 +51,5 @@
 AC_HEADER_TIME
 AC_CHECK_HEADERS(stdlib.h locale.h unistd.h limits.h fcntl.h string.h \
-		 memory.h sys/param.h sys/time.h sys/timeb.h)
+		 memory.h sys/param.h sys/resource.h sys/time.h sys/timeb.h)
 
 # Set a flag if we have an ANSI C compiler
@@ -135,7 +135,8 @@
 
 AC_CHECK_FUNCS(	memcpy memmove strchr strdup mkstemp mktemp fdopen \
-	        bsd_signal dup2 getcwd sigsetmask sigaction getgroups \
-		seteuid setegid setlinebuf setreuid setregid setvbuf pipe \
-		strerror strsignal)
+	        bsd_signal dup2 getcwd realpath sigsetmask sigaction \
+                getgroups seteuid setegid setlinebuf setreuid setregid \
+                getrlimit setrlimit setvbuf pipe strerror strsignal \
+		lstat readlink)
 
 AC_FUNC_SETVBUF_REVERSED
@@ -167,5 +168,11 @@
 fi
 
-AC_CHECK_DECLS([sys_siglist])
+AC_CHECK_DECLS([sys_siglist],,,
+[#include <signal.h>
+/* NetBSD declares sys_siglist in unistd.h.  */
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+])
 
 
@@ -236,4 +243,13 @@
 AM_CONDITIONAL(USE_CUSTOMS, test "$use_customs" = true)
 
+# See if the user asked to handle case insensitive file systems.
+
+AH_TEMPLATE(HAVE_CASE_INSENSITIVE_FS, [Use case insensitive file names])
+AC_ARG_ENABLE(case-insensitive-file-system,
+  AC_HELP_STRING([--enable-case-insensitive-file-system],
+		 [enable case insensitive file system support]),
+  case_insensitive_fs="yes" AC_DEFINE(HAVE_CASE_INSENSITIVE_FS),
+  case_insensitive_fs="no")
+
 # See if we can handle the job server feature, and if the user wants it.
 
@@ -255,13 +271,14 @@
     [make_cv_sa_restart=no])])
 
-# enable make_cv_sa_restart for OS/2
-case "$host_os" in
-  os2*) make_cv_sa_restart=yes ;;
-esac
-
 if test "$make_cv_sa_restart" != no; then
   AC_DEFINE(HAVE_SA_RESTART, 1,
      [Define if <signal.h> defines the SA_RESTART constant.])
 fi
+
+# enable make_cv_sa_restart for OS/2 so that the jobserver will be enabled,
+# but do it after HAVE_SA_RESTART has been defined.
+case "$host_os" in
+  os2*) make_cv_sa_restart=yes ;;
+esac
 
 case "$ac_cv_func_pipe/$ac_cv_func_sigaction/$make_cv_sa_restart/$has_wait_nohang/$make_cv_job_server" in
@@ -269,4 +286,12 @@
     AC_DEFINE(MAKE_JOBSERVER, 1,
               [Define this to enable job server support in GNU make.]);;
+esac
+
+# if we have both lstat() and readlink() then we can support symlink
+# timechecks.
+case "$ac_cv_func_lstat/$ac_cv_func_readlink" in
+  yes/yes)
+    AC_DEFINE(MAKE_SYMLINKS, 1,
+              [Define this to enable symbolic link timestamp checking.]);;
 esac
 
@@ -331,4 +356,16 @@
 AC_SUBST(MAKE_HOST)
 
+w32_target_env=no
+AM_CONDITIONAL([WINDOWSENV], false)
+
+case "$host" in
+  *-*-mingw32)
+    AM_CONDITIONAL(WINDOWSENV, true)
+    w32_target_env=yes
+    AC_DEFINE([WINDOWS32], [1], [Use platform specific coding])
+    AC_DEFINE([HAVE_DOS_PATHS], [1], [Use platform specific coding])
+    ;;
+esac
+
 # Include the Maintainer's Makefile section, if it's here.
 
@@ -389,18 +426,16 @@
 
 # Specify what files are to be created.
+AC_CONFIG_FILES(Makefile glob/Makefile po/Makefile.in config/Makefile doc/Makefile w32/Makefile)
+
+# OK, do it!
+
+AC_OUTPUT
+
 # We only generate the build.sh if we have a build.sh.in; we won't have
 # one before we've created a distribution.
-
-AC_CONFIG_FILES(Makefile glob/Makefile po/Makefile.in config/Makefile doc/Makefile)
-
-if test -f $srcdir/build.sh.in; then
-  AC_CONFIG_FILES(build.sh)
-fi
-
-
-# OK, do it!
-
-AC_OUTPUT
-
+if test -f build.sh.in; then
+  ./config.status --file build.sh
+  chmod +x build.sh
+fi
 
 dnl Local Variables:
Index: branches/GNU/src/gmake/default.c
===================================================================
--- branches/GNU/src/gmake/default.c	(revision 157)
+++ branches/GNU/src/gmake/default.c	(revision 280)
@@ -309,5 +309,9 @@
 #ifdef __ALPHA
     "ARCH", "ALPHA",
-#else
+#endif
+#ifdef __ia64
+    "ARCH", "IA64",
+#endif
+#ifdef __VAX
     "ARCH", "VAX",
 #endif
Index: branches/GNU/src/gmake/dep.h
===================================================================
--- branches/GNU/src/gmake/dep.h	(revision 157)
+++ branches/GNU/src/gmake/dep.h	(revision 280)
@@ -41,4 +41,5 @@
     unsigned int changed : 8;
     unsigned int ignore_mtime : 1;
+    unsigned int need_2nd_expansion : 1;
   };
 
@@ -73,6 +74,7 @@
 
 extern struct dep *copy_dep_chain PARAMS ((struct dep *d));
+extern void free_ns_chain PARAMS ((struct nameseq *n));
 extern struct dep *read_all_makefiles PARAMS ((char **makefiles));
 extern int eval_buffer PARAMS ((char *buffer));
-extern int update_goal_chain PARAMS ((struct dep *goals, int makefiles));
+extern int update_goal_chain PARAMS ((struct dep *goals));
 extern void uniquize_deps PARAMS ((struct dep *));
Index: branches/GNU/src/gmake/dir.c
===================================================================
--- branches/GNU/src/gmake/dir.c	(revision 157)
+++ branches/GNU/src/gmake/dir.c	(revision 280)
@@ -124,9 +124,5 @@
 downcase (char *filename)
 {
-#ifdef _AMIGA
-  static char new_filename[136];
-#else
-  static char new_filename[PATH_MAX];
-#endif
+  static PATH_VAR (new_filename);
   char *df;
   int i;
@@ -1142,6 +1138,6 @@
 	  d = (struct dirent *) buf;
 #ifdef __MINGW32__
-# if __MINGW32_VERSION_MAJOR < 3 || (__MINGW32_VERSION_MAJOR == 3 && \
-				     __MINGW32_VERSION_MINOR == 0)
+# if __MINGW32_MAJOR_VERSION < 3 || (__MINGW32_MAJOR_VERSION == 3 && \
+				     __MINGW32_MINOR_VERSION == 0)
 	  d->d_name = xmalloc(len);
 # endif
@@ -1163,8 +1159,8 @@
 
 static void
-ansi_free(void *p)
-{
-    if (p)
-      free(p);
+ansi_free (void *p)
+{
+  if (p)
+    free(p);
 }
 
Index: branches/GNU/src/gmake/doc/make.texi
===================================================================
--- branches/GNU/src/gmake/doc/make.texi	(revision 157)
+++ branches/GNU/src/gmake/doc/make.texi	(revision 280)
@@ -8,11 +8,11 @@
 @c FSF publishers: format makebook.texi instead of using this file directly.
 
-@set RCSID $Id: make.texi,v 1.18 2004/02/23 06:25:54 psmith Exp $
-@set EDITION 0.61
+@set RCSID $Id: make.texi,v 1.30 2005/05/13 12:45:31 psmith Exp $
+@set EDITION 0.70
 @set VERSION 3.81
-@set UPDATED 02 May 2003
-@set UPDATE-MONTH May 2003
-@comment The ISBN number might need to change on next publication.
-@set ISBN 1-882114-81-7 @c From Brian Youmans <3diff@gnu.org>, 25 Apr 2000
+@set UPDATED 07 May 2005
+@set UPDATE-MONTH May 2005
+@c ISBN provided by Lisa M. Opus Goldstein <opus@gnu.org>, 5 May 2004
+@set ISBN 1-882114-83-5
 
 @c finalout
@@ -40,5 +40,5 @@
 
 Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
-1998, 1999, 2000, 2002, 2003, 2004
+1998, 1999, 2000, 2002, 2003, 2004, 2005
 Free Software Foundation, Inc.
 
@@ -163,4 +163,5 @@
                                   with another makefile.
 * Reading Makefiles::           How makefiles are parsed.
+* Secondary Expansion::         How and when secondary expansion is performed.
 
 Writing Rules
@@ -339,6 +340,4 @@
 * Install Command Categories::  Three categories of commands in the `install'
 
-Copying This Manual
-
 @end detailmenu
 @end menu
@@ -643,5 +642,5 @@
 prerequisites.  These shell commands say how to update the target file.
 A tab character must come at the beginning of every command line to
-distinguish commands lines from other lines in the makefile.  (Bear in
+distinguish command lines from other lines in the makefile.  (Bear in
 mind that @code{make} does not know anything about how the commands
 work.  It is up to you to supply commands that will update the target
@@ -674,5 +673,8 @@
 names start with @samp{.}).  This is called the @dfn{default goal}.
 (@dfn{Goals} are the targets that @code{make} strives ultimately to
-update.  @xref{Goals, , Arguments to Specify the Goals}.)
+update.    You can override this behavior using the command line
+(@pxref{Goals, , Arguments to Specify the Goals}) or with the
+@code{.DEFAULT_GOAL} special variable (@pxref{Special Variables, ,
+Other Special Variables}).
 @cindex default goal
 @cindex goal, default
@@ -956,4 +958,5 @@
                                   with another makefile.
 * Reading Makefiles::           How makefiles are parsed.
+* Secondary Expansion::         How and when secondary expansion is performed.
 @end menu
 
@@ -1224,4 +1227,5 @@
 @cindex makefiles, and @code{MAKEFILE_LIST} variable
 @cindex including (@code{MAKEFILE_LIST} variable)
+@vindex MAKEFILE_LIST
 
 As @code{make} reads various makefiles, including any obtained from the
@@ -1240,9 +1244,9 @@
 @example
 @group
-name1 := $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
+name1 := $(lastword $(MAKEFILE_LIST))
 
 include inc.mk
 
-name2 := $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
+name2 := $(lastword $(MAKEFILE_LIST))
 
 all:
@@ -1273,20 +1277,70 @@
 @cindex special variables
 
-GNU @code{make} also supports a special variable.  Note that any value
-you assign to this variable will be ignored; it will always return its
-special value.
-
-@vindex $(.VARIABLES)
+GNU @code{make} also supports other special variables.  Unless
+otherwise documented here, these values lose their special properties
+if they are set by a makefile or on the command line.
+
+@table @code
+
+@vindex .DEFAULT_GOAL @r{(define default goal)}
+@item .DEFAULT_GOAL
+Sets the default goal to be used if no targets were specified on the
+command line (@pxref{Goals, , Arguments to Specify the Goals}).  The
+@code{.DEFAULT_GOAL} variable allows you to discover the current
+default goal, restart the default goal selection algorithm by clearing
+its value, or to explicitly set the default goal. The following
+example illustrates these cases:
+
+@example
+@group
+# Query the default goal.
+ifeq ($(.DEFAULT_GOAL),)
+  $(warning no default goal is set)
+endif
+
+.PHONY: foo
+foo: ; @@echo $@@
+
+$(warning default goal is $(.DEFAULT_GOAL))
+
+# Reset the default goal.
+.DEFAULT_GOAL :=
+
+.PHONY: bar
+bar: ; @@echo $@@
+
+$(warning default goal is $(.DEFAULT_GOAL))
+
+# Set our own.
+.DEFAULT_GOAL := foo
+@end group
+@end example
+
+This makefile prints:
+
+@example
+@group
+no default goal is set
+default goal is foo
+default goal is bar
+foo
+@end group
+@end example
+
+Note that assigning more than one target name to @code{.DEFAULT_GOAL} is
+illegal and will result in an error.
+
 @vindex .VARIABLES @r{(list of variables)}
-The first special variable is @code{.VARIABLES}.  When expanded, the
-value consists of a list of the @emph{names} of all global variables
-defined in all makefiles read up until that point.  This includes
-variables which have empty values, as well as built-in variables
-(@pxref{Implicit Variables, , Variables Used by Implicit Rules}), but
-does not include any variables which are only defined in a
-target-specific context.
-
-@c @vindex $(.TARGETS)
+@item .VARIABLES
+Expands to a list of the @emph{names} of all global variables defined
+so far.  This includes variables which have empty values, as well as
+built-in variables (@pxref{Implicit Variables, , Variables Used by
+Implicit Rules}), but does not include any variables which are only
+defined in a target-specific context.  Note that any value you assign
+to this variable will be ignored; it will always return its special
+value.
+
 @c @vindex .TARGETS @r{(list of targets)}
+@c @item .TARGETS
 @c The second special variable is @code{.TARGETS}.  When expanded, the
 @c value consists of a list of all targets defined in all makefiles read
@@ -1296,4 +1350,33 @@
 @c file must appear as a target, on the left-hand side of a ``:'', to be
 @c considered a target for the purposes of this variable.
+
+@vindex .FEATURES @r{(list of supported features)}
+@item .FEATURES
+Expands to a list of special features supported by this version of
+@code{make}.  Possible values include:
+
+@table @samp
+@item target-specific
+Supports target-specific and pattern-specific variable assignments.
+@xref{Target-specific, ,Target-specific Variable Values}.
+
+@item order-only
+Supports order-only prerequisites.  @xref{Prerequisite Types, ,Types
+of Prerequisites}.
+
+@item second-expansion
+Supports secondary expansion of prerequisite lists.
+
+@item jobserver
+Supports ``job server'' enhanced parallel builds.  @xref{Parallel,
+,Parallel Execution}.
+
+@item check-symlink
+Supports the @code{-L} (@code{--check-symlink-times}) flag.
+@xref{Options Summary, ,Summary of Options}.
+
+@end table
+
+@end table
 
 @node Remaking Makefiles, Overriding Makefiles, Special Variables, Makefiles
@@ -1425,5 +1508,5 @@
 @file{force} itself and create a prerequisite loop!
 
-@node Reading Makefiles,  , Overriding Makefiles, Makefiles
+@node Reading Makefiles,  Secondary Expansion, Overriding Makefiles, Makefiles
 @section How @code{make} Reads a Makefile
 @cindex reading makefiles
@@ -1486,5 +1569,10 @@
 All instances of conditional syntax are parsed immediately, in their
 entirety; this includes the @code{ifdef}, @code{ifeq}, @code{ifndef},
-and @code{ifneq} forms.
+and @code{ifneq} forms.  Of course this means that automatic variables
+cannot be used in conditional statements, as automatic variables are
+not set until the command script for that rule is invoked.  If you
+need to use automatic variables in a conditional you @emph{must} use
+shell conditional syntax, in your command script proper, for these
+tests, not @code{make} conditionals.
 
 @subheading Rule Definition
@@ -1506,4 +1594,188 @@
 general rule is true for explicit rules, pattern rules, suffix rules,
 static pattern rules, and simple prerequisite definitions.
+
+@node Secondary Expansion, , Reading Makefiles, Makefiles
+@section Secondary Expansion
+@cindex secondary expansion
+@cindex expansion, secondary
+
+In the previous section we learned that GNU @code{make} works in two
+distinct phases: a read-in phase and a target-update phase
+(@pxref{Reading Makefiles, , How @code{make} Reads a Makefile}).
+There is an extra wrinkle that comes in between those two phases,
+right at the end of the read-in phase: at that time, all the
+prerequisites of all of the targets are expanded a @emph{second time}.
+In most circumstances this secondary expansion will have no effect,
+since all variable and function references will have been expanded
+during the initial parsing of the makefiles.  In order to take
+advantage of the secondary expansion phase of the parser, then, it's
+necessary to @emph{escape} the variable or function reference in the
+makefile.  In this case the first expansion merely un-escapes the
+reference but doesn't expand it, and expansion is left to the
+secondary expansion phase.  For example, consider this makefile:
+
+@example
+ONEVAR = onefile
+TWOVAR = twofile
+myfile: $(ONEVAR) $$(TWOVAR)
+@end example
+
+After the first expansion phase the prerequisites list of the
+@file{myfile} target will be @code{onefile} and @code{$(TWOVAR)}; the
+first (unescaped) variable reference to @var{ONEVAR} is expanded,
+while the second (escaped) variable reference is simply unescaped,
+without being recognized as a variable reference.  Now during the
+secondary expansion the first word is expanded again but since it
+contains no variable or function references it remains the static
+value @file{onefile}, while the second word is now a normal reference
+to the variable @var{TWOVAR}, which is expanded to the value
+@file{twofile}.  The final result is that there are two prerequisites,
+@file{onefile} and @file{twofile}.
+
+Obviously, this is not a very interesting case since the same result
+could more easily have been achieved simply by having both variables
+appear, unescaped, in the prerequisites list.  One difference becomes
+apparent if the variables are reset; consider this example:
+
+@example
+AVAR = top
+onefile: $(AVAR)
+twofile: $$(AVAR)
+AVAR = bottom
+@end example
+
+Here the prerequisite of @file{onefile} will be expanded immediately,
+and resolve to the value @file{top}, while the prerequisite of
+@file{twofile} will not be full expanded until the secondary expansion
+and yield a value of @file{bottom}.
+
+This is marginally more exciting, but the true power of this feature
+only becomes apparent when you discover that secondary expansions
+always take place within the scope of the automatic variables for that
+target.  This means that you can use variables such as @code{$@@},
+@code{$*}, etc. during the second expansion and they will have their
+expected values, just as in the command script.  All you have to do is
+defer the expansion by escaping the @code{$}.  Also, secondary
+expansion occurs for both explicit and implicit (pattern) rules.
+Knowing this, the possible uses for this feature are almost endless.
+For example:
+
+@example
+main_OBJS := main.o try.o test.o
+lib_OBJS := lib.o api.o
+
+main lib: $$($$@@_OBJS)
+@end example
+
+Here, after the initial expansion the prerequisites of both the
+@file{main} and @file{lib} targets will be @code{$($@@_OBJS)}.  During
+the secondary expansion, the @code{$@@} variable is set to the name of
+the target and so the expansion for the @file{main} target will yield
+@code{$(main_OBJS)}, or @code{main.o try.o test.o}, while the
+secondary expansion for the @file{lib} target will yield
+@code{$(lib_OBJS)}, or @code{lib.o api.o}.
+
+You can also mix functions here, as long as they are properly escaped:
+
+@example
+main_SRCS := main.c try.c test.c
+lib_SRCS := lib.c api.c
+
+main lib: $$(patsubst %.c,%.o,$$($$@@_SRCS))
+@end example
+
+This version allows users to specify source files rather than object
+files, but gives the same resulting prerequisites list as the previous
+example.
+
+Evaluation of automatic variables during the secondary expansion
+phase, especially of the target name variable @code{$$@@}, behaves
+similarly to evaluation within command scripts.  However, there are
+some subtle differences and ``corner cases'' which come into play for
+the different types of rule definitions that @code{make} understands.
+The subtleties of using the different automatic variables are
+described below.
+
+@subheading Secondary Expansion of Explicit Rules
+@cindex secondary expansion and explicit rules
+@cindex explicit rules, secondary expansion of
+
+During the secondary expansion of explicit rules, @code{$$@@} and
+@code{$$%} evaluate, respectively, to the file name of the target and,
+when the target is an archive member, the target member name.  The
+@code{$$<} variable evaluates to the first prerequisite in the first
+rule for this target.  @code{$$^} and @code{$$+} evaluate to the list
+of all prerequisites of rules @emph{that have already appeared} for
+the same target (@code{$$+} with repetitions and @code{$$^}
+without). The following example will help illustrate these behaviors:
+
+@example
+foo: foo.1 bar.1 $$< $$^ $$+    # line #1
+
+foo: foo.2 bar.2 $$< $$^ $$+    # line #2
+
+foo: foo.3 bar.3 $$< $$^ $$+    # line #3
+@end example
+
+For the first line, all three variables (@code{$$<}, @code{$$^}, and
+@code{$$+}) expand to the empty string. For the second line, they will
+have values @code{foo.1}, @code{foo.1 bar.1}, and @code{foo.1 bar.1}
+respectively. For the third they will have values @code{foo.1},
+@code{foo.1 bar.1 foo.2 bar.2}, and @code{foo.1 bar.1 foo.2 bar.2}
+respectively.
+
+Rules undergo secondary expansion in makefile order, except that
+the rule with the command script is always evaluated last.
+
+The variables @code{$$?} and @code{$$*} are not available and expand
+to the empty string.
+
+@subheading Secondary Expansion of Static Pattern Rules
+@cindex secondary expansion and static pattern rules
+@cindex static pattern rules, secondary expansion of
+
+Rules for secondary expansion of static pattern rules are identical to
+those for explicit rules, above, with one exception: for static
+pattern rules the @code{$$*} variable is set to the pattern stem.  As
+with explicit rules, @code{$$?} is not available and expands to the
+empty string.
+
+@subheading Secondary Expansion of Implicit Rules
+@cindex secondary expansion and implicit rules
+@cindex implicit rules, secondary expansion of
+
+As @code{make} searches for an implicit rule, it substitutes the stem
+and then performs secondary expansion for every rule with a matching
+target pattern.  The value of the automatic variables is derived in
+the same fashion as for static pattern rules.  As an example:
+
+@example
+foo: bar
+
+foo foz: fo%: bo%
+
+%oo: $$< $$^ $$+ $$*
+@end example
+
+When the implicit rule is tried for target @file{foo}, @code{$$<}
+expands to @file{bar}, @code{$$^} expands to @file{bar boo},
+@code{$$+} also expands to @file{bar boo}, and @code{$$*} expands to
+@file{f}.
+
+Note that the directory prefix (D), as described in @ref{Implicit Rule
+Search, ,Implicit Rule Search Algorithm}, is appended (after
+expansion) to all the patterns in the prerequisites list.  As an
+example:
+
+@example
+/tmp/foo.o:
+
+%.o: $$(addsuffix /%.c,foo bar) foo.h
+@end example
+
+The prerequisite list after the secondary expansion and directory
+prefix reconstruction will be @file{/tmp/foo/foo.c /tmp/var/bar/foo.c
+foo.h}.  If you are not interested in this reconstruction, you can use
+@code{$$*} instead of @code{%} in the prerequisites list.
 
 @node Rules, Commands, Makefiles, Top
@@ -1636,5 +1908,7 @@
 Because dollar signs are used to start variable references, if you really
 want a dollar sign in a rule you must write two of them, @samp{$$}
-(@pxref{Using Variables, ,How to Use Variables}).
+(@pxref{Using Variables, ,How to Use Variables}).  In prerequisite
+lists you must actually write @emph{four} dollar signs (@samp{$$$$}),
+due to secondary expansion (@pxref{Secondary Expansion}).
 You may split a long line by inserting a backslash
 followed by a newline, but this is not required, as @code{make} places no
@@ -2426,6 +2700,8 @@
 
 @noindent
-Now you can say just @samp{make} to remake all three programs, or specify
-as arguments the ones to remake (as in @samp{make prog1 prog3}).
+Now you can say just @samp{make} to remake all three programs, or
+specify as arguments the ones to remake (as in @samp{make prog1
+prog3}).  Phoniness is not inherited: the prerequisites of a phony
+target are not themselves phony, unless explicitly declared to be so.
 
 When one phony target is a prerequisite of another, it serves as a subroutine
@@ -3163,6 +3439,6 @@
 Note that the @samp{.d} files contain target definitions; you should
 be sure to place the @code{include} directive @emph{after} the first,
-default target in your makefiles or run the risk of having a random
-object file become the default target.
+default goal in your makefiles or run the risk of having a random
+object file become the default goal.
 @xref{How Make Works}.
 
@@ -3357,4 +3633,5 @@
 
 @cindex environment, @code{SHELL} in
+@vindex MAKESHELL @r{(MS-DOS alternative to @code{SHELL})}
 Unlike most variables, the variable @code{SHELL} is never set from the
 environment.  This is because the @code{SHELL} environment variable is
@@ -3733,7 +4010,13 @@
 characters other than letters, numbers, and underscores.
 
-The special variables @code{SHELL} and @code{MAKEFLAGS} are always
-exported (unless you unexport them).
-@code{MAKEFILES} is exported if you set it to anything.
+@cindex SHELL, exported value
+The value of the @code{make} variable @code{SHELL} is not exported.
+Instead, the value of the @code{SHELL} variable from the invoking
+environment is passed to the sub-@code{make}.  You can force
+@code{make} to export its value for @code{SHELL} by using the
+@code{export} directive, described below.
+
+The special variable @code{MAKEFLAGS} is always exported (unless you
+unexport it).  @code{MAKEFILES} is exported if you set it to anything.
 
 @code{make} automatically passes down variable values that were defined
@@ -5138,26 +5421,26 @@
 @cindex environment
 Variables in @code{make} can come from the environment in which
-@code{make} is run.  Every environment variable that @code{make} sees when
-it starts up is transformed into a @code{make} variable with the same name
-and value.  But an explicit assignment in the makefile, or with a command
-argument, overrides the environment.  (If the @samp{-e} flag is specified,
-then values from the environment override assignments in the makefile.
-@xref{Options Summary, ,Summary of Options}.
-But this is not recommended practice.)
+@code{make} is run.  Every environment variable that @code{make} sees
+when it starts up is transformed into a @code{make} variable with the
+same name and value.  However, an explicit assignment in the makefile,
+or with a command argument, overrides the environment.  (If the
+@samp{-e} flag is specified, then values from the environment override
+assignments in the makefile.  @xref{Options Summary, ,Summary of
+Options}.  But this is not recommended practice.)
 
 Thus, by setting the variable @code{CFLAGS} in your environment, you can
 cause all C compilations in most makefiles to use the compiler switches you
 prefer.  This is safe for variables with standard or conventional meanings
-because you know that no makefile will use them for other things.  (But
+because you know that no makefile will use them for other things.  (Note
 this is not totally reliable; some makefiles set @code{CFLAGS} explicitly
 and therefore are not affected by the value in the environment.)
 
-When @code{make} is invoked recursively, variables defined in the
-outer invocation can be passed to inner invocations through the
-environment (@pxref{Recursion, ,Recursive Use of @code{make}}).  By
-default, only variables that came from the environment or the command
-line are passed to recursive invocations.  You can use the
-@code{export} directive to pass other variables.
-@xref{Variables/Recursion, , Communicating Variables to a
+When @code{make} runs a command script, variables defined in the
+makefile are placed into the environment of that command.  This allows
+you to pass values to sub-@code{make} invocations. (@pxref{Recursion,
+,Recursive Use of @code{make}}).  By default, only variables that came
+from the environment or the command line are passed to recursive
+invocations.  You can use the @code{export} directive to pass other
+variables.  @xref{Variables/Recursion, , Communicating Variables to a
 Sub-@code{make}}, for full details.
 
@@ -5168,4 +5451,5 @@
 purpose of most makefiles.
 
+@cindex SHELL, import from environment
 Such problems would be especially likely with the variable @code{SHELL},
 which is normally present in the environment to specify the user's choice
@@ -5175,4 +5459,13 @@
 usually not set.  @xref{Execution, ,Special handling of SHELL on
 MS-DOS}.)@refill
+
+@cindex SHELL, export to environment
+The @code{SHELL} variable is special in another way: just as the value
+of the @code{make} variable @code{SHELL} is not taken from the
+environment, so also it is not placed into the environment of commands
+that @code{make} invokes.  Instead, the value of @code{SHELL} from the
+invoking environment is provided to the command.  You can use
+@code{export SHELL} to force the value of the @code{make} variable
+@code{SHELL} to be placed in the environment of commands.
 
 @node Target-specific, Pattern-specific, Environment, Using Variables
@@ -5431,12 +5724,28 @@
 @end example
 
-@noindent
-If the condition is true, @var{text-if-true} is used; otherwise,
-@var{text-if-false} is used instead.  The @var{text-if-false} can be any
-number of lines of text.
+or:
+
+@example
+@var{conditional-directive}
+@var{text-if-one-is-true}
+else @var{conditional-directive}
+@var{text-if-true}
+else
+@var{text-if-false}
+endif
+@end example
+
+@noindent
+There can be as many ``@code{else} @var{conditional-directive}''
+clauses as necessary.  Once a given condition is true,
+@var{text-if-true} is used and no other clause is used; if no
+condition is true then @var{text-if-false} is used.  The
+@var{text-if-true} and @var{text-if-false} can be any number of lines
+of text.
 
 The syntax of the @var{conditional-directive} is the same whether the
-conditional is simple or complex.  There are four different directives that
-test different conditions.  Here is a table of them:
+conditional is simple or complex; after an @code{else} or not.  There
+are four different directives that test different conditions.  Here is
+a table of them:
 
 @table @code
@@ -5479,10 +5788,24 @@
 
 @item ifdef @var{variable-name}
-If the variable @var{variable-name} has a non-empty value, the
-@var{text-if-true} is effective; otherwise, the @var{text-if-false},
-if any, is effective.  Variables that have never been defined have an
-empty value.  The variable @var{variable-name} is itself expanded, so
-it could be a variable or function that expands to the name of a
-variable.
+The @code{ifdef} form takes the @emph{name} of a variable as its
+argument, not a reference to a variable.  The value of that variable
+has a non-empty value, the @var{text-if-true} is effective; otherwise,
+the @var{text-if-false}, if any, is effective.  Variables that have
+never been defined have an empty value.  The text @var{variable-name}
+is expanded, so it could be a variable or function that expands
+to the name of a variable.  For example:
+
+@example
+bar = true
+foo = bar
+ifdef $(foo)
+frobozz = yes
+endif
+@end example
+
+The variable reference @code{$(foo)} is expanded, yielding @code{bar},
+which is considered to be the name of a variable.  The variable
+@code{bar} is not expanded, but its value is examined to determine if
+it is non-empty.
 
 Note that @code{ifdef} only tests whether a variable has a value.  It
@@ -5520,5 +5843,6 @@
 If the variable @var{variable-name} has an empty value, the
 @var{text-if-true} is effective; otherwise, the @var{text-if-false},
-if any, is effective.
+if any, is effective.  The rules for expansion and testing of
+@var{variable-name} are identical to the @code{ifdef} directive.
 @end table
 
@@ -5927,8 +6251,9 @@
 Returns the list of words in @var{text} starting with word @var{s} and
 ending with word @var{e} (inclusive).  The legitimate values of @var{s}
-and @var{e} start from 1.  If @var{s} is bigger than the number of words
-in @var{text}, the value is empty.  If @var{e} is bigger than the number
-of words in @var{text}, words up to the end of @var{text} are returned.
-If @var{s} is greater than @var{e}, nothing is returned.  For example,
+start from 1; @var{e} may start from 0.  If @var{s} is bigger than the
+number of words in @var{text}, the value is empty.  If @var{e} is
+bigger than the number of words in @var{text}, words up to the end of
+@var{text} are returned.  If @var{s} is greater than @var{e}, nothing
+is returned.  For example,
 
 @example
@@ -5964,5 +6289,25 @@
 @var{text})} is the same as @code{$(word 1,@var{text})}, the
 @code{firstword} function is retained for its simplicity.@refill
+
+
+@item $(lastword @var{names}@dots{})
+@findex lastword
+@cindex words, extracting last
+The argument @var{names} is regarded as a series of names, separated
+by whitespace.  The value is the last name in the series.
+
+For example,
+
+@example
+$(lastword foo bar)
+@end example
+
+@noindent
+produces the result @samp{bar}.  Although @code{$(lastword
+@var{text})} is the same as @code{$(word $(words @var{text}),@var{text})},
+the @code{lastword} function was added for its simplicity and better
+performance.@refill
 @end table
+
 
 Here is a realistic example of the use of @code{subst} and
@@ -6153,4 +6498,25 @@
 that match the pattern.
 @xref{Wildcards, ,Using Wildcard Characters in File Names}.
+
+@item $(realpath @var{names}@dots{})
+@findex realpath
+@cindex realpath
+@cindex file name, realpath of
+For each file name in @var{names} return the canonical absolute name.
+A canonical name does not contain any @code{.} or @code{..} components,
+nor any repeated path separators (@code{/}) or symlinks. In case of a
+failure the empty string is returned. Consult the @code{realpath(3)}
+documentation for a list of possible failure causes.
+
+@item $(abspath @var{names}@dots{})
+@findex abspath
+@cindex abspath
+@cindex file name, abspath of
+For each file name in @var{names} return an absolute name that does
+not contain any @code{.} or @code{..} components, nor any repeated path
+separators (@code{/}). Note that in contrast to @code{realpath}
+function, @code{abspath} does not resolve symlinks and does not require
+the file names to refer to an existing file or directory. Use the
+@code{wildcard} function to test for existence.
 @end table
 
@@ -6638,5 +7004,6 @@
 sets @code{files} to the expansion of @samp{*.c}.  Unless @code{make} is
 using a very strange shell, this has the same result as
-@w{@samp{$(wildcard *.c)}}.@refill
+@w{@samp{$(wildcard *.c)}} (as long as at least one @samp{.c} file
+exists).@refill
 
 @node Make Control Functions,  , Shell Function, Functions
@@ -6693,4 +7060,11 @@
 
 The result of the expansion of this function is the empty string.
+
+@item $(info @var{text}@dots{})
+@findex info
+@cindex printing messages
+This function does nothing more than print its (expanded) argument(s)
+to standard output.  No makefile name or line number is added.  The
+result of the expansion of this function is the empty string.
 @end table
 
@@ -6771,9 +7145,12 @@
 programs they describe.  If the first rule in the makefile has several
 targets, only the first target in the rule becomes the default goal, not
-the whole list.
-
-You can specify a different goal or goals with arguments to @code{make}.
-Use the name of the goal as an argument.  If you specify several goals,
-@code{make} processes each of them in turn, in the order you name them.
+the whole list.  You can manage the selection of the default goal from
+within your makefile using the @code{.DEFAULT_GOAL} variable
+(@pxref{Special Variables, , Other Special Variables}).
+
+You can also specify a different goal or goals with command-line
+arguments to @code{make}.  Use the name of the goal as an argument.
+If you specify several goals, @code{make} processes each of them in
+turn, in the order you name them.
 
 Any target in the makefile may be specified as a goal (unless it
@@ -6783,5 +7160,4 @@
 implicit rules that say how to make them.
 
-@cindex @code{MAKECMDGOALS}
 @vindex MAKECMDGOALS
 @code{Make} will set the special variable @code{MAKECMDGOALS} to the
@@ -7308,4 +7684,14 @@
 floating-point number).  With no argument, removes a previous load
 limit.  @xref{Parallel, ,Parallel Execution}.
+
+@item -L
+@cindex @code{-L}
+@itemx --check-symlink-times
+@cindex @code{--check-symlink-times}
+On systems that support symbolic links, this option causes @code{make}
+to consider the timestamps on any symbolic links in addition to the
+timestamp on the file referenced by those links.  When this option is
+provided, the most recent timestamp among the file and the symbolic
+links is taken as the modification time for this target file.
 
 @item -n
@@ -7520,6 +7906,6 @@
 * Chained Rules::               How to use a chain of implicit rules.
 * Pattern Rules::               How to define new implicit rules.
-* Last Resort::                 How to defining commands for rules
-                                  which cannot find any.
+* Last Resort::                 How to define commands for rules which
+                                cannot find any.
 * Suffix Rules::                The old-fashioned style of implicit rule.
 * Implicit Rule Search::        The precise algorithm for applying
@@ -8372,9 +8758,11 @@
 automatic variable values are available: they only have values within
 the command script.  In particular, you cannot use them anywhere
-within the target or prerequisite lists of a rule; they have no value
-there and will expand to the empty string.  A common mistake is
-attempting to use @code{$@@} within the prerequisites list in a rule;
-this will not work.  However, see below for information on the
-SysV-style @code{$$@@} variables.
+within the target list of a rule; they have no value there and will
+expand to the empty string.  Also, they cannot be accessed directly
+within the prerequisite list of a rule.  A common mistake is
+attempting to use @code{$@@} within the prerequisites list; this will
+not work.  However, there is a special feature of GNU @code{make},
+secondary expansion (@pxref{Secondary Expansion}), which will allow
+automatic variable values to be used in prerequisite lists.
 
 Here is a table of automatic variables:
@@ -8422,5 +8810,7 @@
 it depends on, no matter how many times each file is listed as a
 prerequisite.  So if you list a prerequisite more than once for a target,
-the value of @code{$^} contains just one copy of the name.
+the value of @code{$^} contains just one copy of the name.  This list
+does @strong{not} contain any of the order-only prerequisites; for those
+see the @samp{$|} variable, below.
 @cindex prerequisites, list of all
 @cindex list of all prerequisites
@@ -8433,4 +8823,10 @@
 primarily useful for use in linking commands where it is meaningful to
 repeat library file names in a particular order.
+
+@vindex $|
+@vindex | @r{(automatic variable)}
+@item $|
+The names of all the order-only prerequisites, with spaces between
+them.
 
 @vindex $*
@@ -8565,30 +8961,4 @@
 as @samp{$(CFLAGS)} refers to the variable named @code{CFLAGS}.
 You could just as well use @samp{$(<)} in place of @samp{$<}.
-
-@vindex $$@@
-@vindex $$(@@D)
-@vindex $$(@@F)
-@cindex $$@@, support for
-GNU @code{make} provides support for the SysV @code{make} feature that
-allows special variable references @code{$$@@}, @code{$$(@@D)}, and
-@code{$$(@@F)} (note the required double-''$''!) to appear with the
-@emph{prerequisites list} (normal automatic variables are available
-only within a command script).  When appearing in a prerequisites
-list, these variables are expanded to the name of the target, the
-directory component of the target, and the file component of the
-target, respectively.
-
-Note that these variables are available only within explicit and
-static pattern (@pxref{Static Pattern, ,Static Pattern Rules}) rules;
-they have no special significance within implicit (suffix or pattern)
-rules.  Also note that while SysV @code{make} actually expands its
-entire prerequisite list @emph{twice}, GNU @code{make} does not behave
-this way: instead it simply expands these special variables without
-re-expanding any other part of the prerequisites list.
-
-This somewhat bizarre feature is included only to provide some
-compatibility with SysV makefiles.  In a native GNU @code{make} file
-there are other ways to accomplish the same results.  This feature is
-disabled if the special pseudo target @code{.POSIX} is defined.
 
 @node Pattern Match, Match-Anything Rules, Automatic Variables, Pattern Rules
@@ -9446,4 +9816,5 @@
 The built-in variable @samp{MAKE_VERSION} gives the version number of
 @code{make}.
+@vindex MAKE_VERSION
 @end itemize
 
@@ -9635,5 +10006,5 @@
 @end table
 
-Here is a summary of the text manipulation functions (@pxref{Functions}):
+Here is a summary of the built-in functions (@pxref{Functions}):
 
 @table @code
@@ -9666,4 +10037,24 @@
 @xref{Text Functions, , Functions for String Substitution and Analysis}.
 
+@item $(word @var{n},@var{text})
+Extract the @var{n}th word (one-origin) of @var{text}.@*
+@xref{Text Functions, , Functions for String Substitution and Analysis}.
+
+@item $(words @var{text})
+Count the number of words in @var{text}.@*
+@xref{Text Functions, , Functions for String Substitution and Analysis}.
+
+@item $(wordlist @var{s},@var{e},@var{text})
+Returns the list of words in @var{text} from @var{s} to @var{e}.@*
+@xref{Text Functions, , Functions for String Substitution and Analysis}.
+
+@item $(firstword @var{names}@dots{})
+Extract the first word of @var{names}.@*
+@xref{Text Functions, , Functions for String Substitution and Analysis}.
+
+@item $(lastword @var{names}@dots{})
+Extract the last word of @var{names}.@*
+@xref{Text Functions, , Functions for String Substitution and Analysis}.
+
 @item $(dir @var{names}@dots{})
 Extract the directory part of each file name.@*
@@ -9692,20 +10083,4 @@
 @item $(join @var{list1},@var{list2})
 Join two parallel lists of words.@*
-@xref{File Name Functions, ,Functions for File Names}.
-
-@item $(word @var{n},@var{text})
-Extract the @var{n}th word (one-origin) of @var{text}.@*
-@xref{File Name Functions, ,Functions for File Names}.
-
-@item $(words @var{text})
-Count the number of words in @var{text}.@*
-@xref{File Name Functions, ,Functions for File Names}.
-
-@item $(wordlist @var{s},@var{e},@var{text})
-Returns the list of words in @var{text} from @var{s} to @var{e}.@*
-@xref{File Name Functions, ,Functions for File Names}.
-
-@item $(firstword @var{names}@dots{})
-Extract the first word of @var{names}.@*
 @xref{File Name Functions, ,Functions for File Names}.
 
@@ -9714,4 +10089,15 @@
 @samp{%} pattern).@*
 @xref{Wildcard Function, ,The Function @code{wildcard}}.
+
+@item $(realpath @var{names}@dots{})
+For each file name in @var{names}, expand to an absolute name that
+does not contain any @code{.}, @code{..}, nor symlinks.@*
+@xref{File Name Functions, ,Functions for File Names}.
+
+@item $(abspath @var{names}@dots{})
+For each file name in @var{names}, expand to an absolute name that
+does not contain any @code{.} or @code{..} components, but preserves
+symlinks.@*
+@xref{File Name Functions, ,Functions for File Names}.
 
 @item $(error @var{text}@dots{})
@@ -9840,5 +10226,7 @@
 The name of the system default command interpreter, usually @file{/bin/sh}.
 You can set @code{SHELL} in the makefile to change the shell used to run
-commands.  @xref{Execution, ,Command Execution}.
+commands.  @xref{Execution, ,Command Execution}.  The @code{SHELL}
+variable is handled specially when importing from and exporting to the
+environment.  @xref{Environment, ,Using Variable from the Environment}.
 
 @item MAKESHELL
@@ -9970,5 +10358,5 @@
 command line, and @code{make} couldn't find any makefiles to read in.
 The latter means that some makefile was found, but it didn't contain any
-default target and none was given on the command line.  GNU @code{make}
+default goal and none was given on the command line.  GNU @code{make}
 has nothing to do in these situations.
 @xref{Makefile Arguments, ,Arguments to Specify the Makefile}.@refill
@@ -10221,7 +10609,9 @@
 @end group
 
+.PHONY: all
 all:    tar rmt tar.info
 
 @group
+.PHONY: tar
 tar:    $(OBJS)
         $(CC) $(LDFLAGS) -o $@@ $(OBJS) $(LIBS)
@@ -10239,4 +10629,5 @@
 
 @group
+.PHONY: install
 install: all
         $(INSTALL) tar $(bindir)/$(binprefix)tar
@@ -10267,4 +10658,5 @@
 
 @group
+.PHONY: clean
 clean:
         rm -f *.o tar rmt testpad testpad.h core
@@ -10272,4 +10664,5 @@
 
 @group
+.PHONY: distclean
 distclean: clean
         rm -f TAGS Makefile config.status
@@ -10277,4 +10670,5 @@
 
 @group
+.PHONY: realclean
 realclean: distclean
         rm -f tar.info*
@@ -10282,4 +10676,5 @@
 
 @group
+.PHONY: shar
 shar: $(SRCS) $(AUX)
         shar $(SRCS) $(AUX) | compress \
@@ -10291,4 +10686,5 @@
 
 @group
+.PHONY: dist
 dist: $(SRCS) $(AUX)
         echo tar-`sed \
Index: branches/GNU/src/gmake/expand.c
===================================================================
--- branches/GNU/src/gmake/expand.c	(revision 157)
+++ branches/GNU/src/gmake/expand.c	(revision 280)
@@ -155,5 +155,6 @@
     warn_undefined (name, length);
 
-  if (v == 0 || *v->value == '\0')
+  /* If there's no variable by that name or it has no value, stop now.  */
+  if (v == 0 || (*v->value == '\0' && !v->append))
     return o;
 
@@ -306,49 +307,47 @@
 		      warn_undefined (beg, colon - beg);
 
+                    /* If the variable is not empty, perform the
+                       substitution.  */
 		    if (v != 0 && *v->value != '\0')
 		      {
-			char *value = (v->recursive ? recursively_expand (v)
+			char *pattern, *replace, *ppercent, *rpercent;
+			char *value = (v->recursive
+                                       ? recursively_expand (v)
 				       : v->value);
-			char *pattern, *percent;
-			if (free_beg)
-			  {
-			    *subst_end = '\0';
-			    pattern = subst_beg;
-			  }
+
+                        /* Copy the pattern and the replacement.  Add in an
+                           extra % at the beginning to use in case there
+                           isn't one in the pattern.  */
+                        pattern = (char *) alloca (subst_end - subst_beg + 2);
+                        *(pattern++) = '%';
+                        bcopy (subst_beg, pattern, subst_end - subst_beg);
+                        pattern[subst_end - subst_beg] = '\0';
+
+                        replace = (char *) alloca (replace_end
+                                                   - replace_beg + 2);
+                        *(replace++) = '%';
+                        bcopy (replace_beg, replace,
+                               replace_end - replace_beg);
+                        replace[replace_end - replace_beg] = '\0';
+
+                        /* Look for %.  Set the percent pointers properly
+                           based on whether we find one or not.  */
+			ppercent = find_percent (pattern);
+			if (ppercent)
+                          {
+                            ++ppercent;
+                            rpercent = 0;
+                          }
 			else
-			  {
-			    pattern = (char *) alloca (subst_end - subst_beg
-						       + 1);
-			    bcopy (subst_beg, pattern, subst_end - subst_beg);
-			    pattern[subst_end - subst_beg] = '\0';
-			  }
-			percent = find_percent (pattern);
-			if (percent != 0)
-			  {
-			    char *replace;
-			    if (free_beg)
-			      {
-				*replace_end = '\0';
-				replace = replace_beg;
-			      }
-			    else
-			      {
-				replace = (char *) alloca (replace_end
-							   - replace_beg
-							   + 1);
-				bcopy (replace_beg, replace,
-				       replace_end - replace_beg);
-				replace[replace_end - replace_beg] = '\0';
-			      }
-
-			    o = patsubst_expand (o, value, pattern, replace,
-						 percent, (char *) 0);
-			  }
-			else
-			  o = subst_expand (o, value,
-					    pattern, replace_beg,
-					    strlen (pattern),
-					    end - replace_beg,
-					    0, 1);
+                          {
+                            ppercent = pattern;
+                            rpercent = replace;
+                            --pattern;
+                            --replace;
+                          }
+
+                        o = patsubst_expand (o, value, pattern, replace,
+                                             ppercent, rpercent);
+
 			if (v->recursive)
 			  free (value);
@@ -447,5 +446,5 @@
    FILE's commands were found.  Expansion uses FILE's variable set list.  */
 
-static char *
+char *
 variable_expand_for_file (char *line, struct file *file)
 {
Index: branches/GNU/src/gmake/file.c
===================================================================
--- branches/GNU/src/gmake/file.c	(revision 157)
+++ branches/GNU/src/gmake/file.c	(revision 280)
@@ -31,4 +31,13 @@
 #include "hash.h"
 
+
+/* Remember whether snap_deps has been invoked: we need this to be sure we
+   don't add new rules (via $(eval ...)) afterwards.  In the future it would
+   be nice to support this, but it means we'd need to re-run snap_deps() or
+   at least its functionality... it might mean changing snap_deps() to be run
+   per-file, so we can invoke it after the eval... or remembering which files
+   in the hash have been snapped (a new boolean flag?) and having snap_deps()
+   only work on files which have not yet been snapped. */
+int snapped_deps = 0;
 
 /* Hash table of files the makefile knows how to make.  */
@@ -345,4 +354,8 @@
       {
 	register struct file *f = *file_slot;
+        /* Is this file eligible for automatic deletion?
+           Yes, IFF: it's marked intermediate, it's not secondary, it wasn't
+           given on the command-line, and it's either a -include makefile or
+           it's not precious.  */
 	if (f->intermediate && (f->dontcare || !f->precious)
 	    && !f->secondary && !f->cmd_target)
@@ -405,4 +418,117 @@
 }
 
+/* Expand and parse each dependency line. */
+static void
+expand_deps (struct file *f)
+{
+  struct dep *d, *d1;
+  struct dep *new = 0;
+  struct dep *old = f->deps;
+  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)
+    {
+      if (d->name != 0)
+        {
+          char *p;
+
+          /* If we need a second expansion on these, set up the file
+             variables, etc.  It takes a lot of extra memory and processing
+             to do this, so only do it if it's needed.  */
+          if (! d->need_2nd_expansion)
+            p = d->name;
+          else
+            {
+              /* We are going to do second expansion so initialize file
+                 variables for the file. */
+              if (!initialized)
+                {
+                  initialize_file_variables (f, 0);
+                  initialized = 1;
+                }
+
+              set_file_variables (f);
+
+              p = variable_expand_for_file (d->name, f);
+            }
+
+          /* Parse the dependencies.  */
+          new = (struct dep *)
+            multi_glob (
+              parse_file_seq (&p, '|', sizeof (struct dep), 1),
+              sizeof (struct dep));
+
+          if (*p)
+            {
+              /* Files that follow '|' are special prerequisites that
+                 need only exist in order to satisfy the dependency.
+                 Their modification times are irrelevant.  */
+              struct dep **d_ptr;
+
+              for (d_ptr = &new; *d_ptr; d_ptr = &(*d_ptr)->next)
+                ;
+              ++p;
+
+              *d_ptr = (struct dep *)
+                multi_glob (
+                  parse_file_seq (&p, '\0', sizeof (struct dep), 1),
+                  sizeof (struct dep));
+
+              for (d1 = *d_ptr; d1 != 0; d1 = d1->next)
+                d1->ignore_mtime = 1;
+            }
+
+          /* 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);
+              else
+                free (d1->name);
+              d1->name = 0;
+              d1->need_2nd_expansion = 0;
+            }
+
+          /* 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_ns_chain ((struct nameseq *) old);
+}
+
 /* For each dependency of each file, make the `struct dep' point
    at the appropriate `struct file' (which may have to be created).
@@ -414,12 +540,19 @@
 snap_deps (void)
 {
-  register struct file *f;
-  register struct file *f2;
-  register struct dep *d;
-  register struct file **file_slot_0;
-  register struct file **file_slot;
-  register struct file **file_end;
-
-  /* Enter each dependency name as a file.  */
+  struct file *f;
+  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);
+
   /* We must use hash_dump (), because within this loop
      we might add new files to the table, possibly causing
@@ -428,15 +561,9 @@
   file_end = file_slot_0 + files.ht_fill;
   for (file_slot = file_slot_0; file_slot < file_end; file_slot++)
-    for (f2 = *file_slot; f2 != 0; f2 = f2->prev)
-      for (d = f2->deps; d != 0; d = d->next)
-	if (d->name != 0)
-	  {
-	    d->file = lookup_file (d->name);
-	    if (d->file == 0)
-	      d->file = enter_file (d->name);
-	    else
-	      free (d->name);
-	    d->name = 0;
-	  }
+    for (f = *file_slot; f != 0; f = f->prev)
+      {
+        if (strcmp (f->name, ".SUFFIXES") != 0)
+          expand_deps (f);
+      }
   free (file_slot_0);
 
@@ -455,6 +582,7 @@
       for (f2 = d->file; f2 != 0; f2 = f2->prev)
 	{
-	  /* Mark this file as phony and nonexistent.  */
+	  /* Mark this file as phony nonexistent target.  */
 	  f2->phony = 1;
+          f2->is_target = 1;
 	  f2->last_mtime = NONEXISTENT_MTIME;
 	  f2->mtime_before_update = NONEXISTENT_MTIME;
@@ -525,4 +653,7 @@
   if (f != 0 && f->is_target)
     not_parallel = 1;
+
+  /* Remember that we've done this. */
+  snapped_deps = 1;
 }
 
@@ -687,5 +818,5 @@
     puts (_("#  Command-line target."));
   if (f->dontcare)
-    puts (_("#  A default or MAKEFILES makefile."));
+    puts (_("#  A default, MAKEFILES, or -include/sinclude makefile."));
   puts (f->tried_implicit
         ? _("#  Implicit rule search has been done.")
Index: branches/GNU/src/gmake/filedef.h
===================================================================
--- branches/GNU/src/gmake/filedef.h	(revision 157)
+++ branches/GNU/src/gmake/filedef.h	(revision 280)
@@ -101,4 +101,5 @@
 
 extern struct file *default_goal_file, *suffix_file, *default_file;
+extern char **default_goal_name;
 
 
@@ -198,2 +199,5 @@
 #define check_renamed(file) \
   while ((file)->renamed != 0) (file) = (file)->renamed /* No ; here.  */
+
+/* Have we snapped deps yet?  */
+extern int snapped_deps;
Index: branches/GNU/src/gmake/function.c
===================================================================
--- branches/GNU/src/gmake/function.c	(revision 157)
+++ branches/GNU/src/gmake/function.c	(revision 280)
@@ -74,20 +74,17 @@
    the length of SUBST and RLEN is the length of REPLACE.  If BY_WORD is
    nonzero, substitutions are done only on matches which are complete
-   whitespace-delimited words.  If SUFFIX_ONLY is nonzero, substitutions are
-   done only at the ends of whitespace-delimited words.  */
+   whitespace-delimited words.  */
 
 char *
 subst_expand (char *o, char *text, char *subst, char *replace,
-              unsigned int slen, unsigned int rlen,
-              int by_word, int suffix_only)
+              unsigned int slen, unsigned int rlen, int by_word)
 {
   char *t = text;
-  unsigned int tlen = strlen (text);
   char *p;
 
-  if (slen == 0 && !by_word && !suffix_only)
+  if (slen == 0 && !by_word)
     {
       /* The first occurrence of "" in any string is its end.  */
-      o = variable_buffer_output (o, t, tlen);
+      o = variable_buffer_output (o, t, strlen (t));
       if (rlen > 0)
 	o = variable_buffer_output (o, replace, rlen);
@@ -97,5 +94,5 @@
   do
     {
-      if ((by_word | suffix_only) && slen == 0)
+      if (by_word && slen == 0)
 	/* When matching by words, the empty string should match
 	   the end of each word, rather than the end of the whole text.  */
@@ -103,9 +100,9 @@
       else
 	{
-	  p = sindex (t, tlen, subst, slen);
+	  p = strstr (t, subst);
 	  if (p == 0)
 	    {
 	      /* No more matches.  Output everything left on the end.  */
-	      o = variable_buffer_output (o, t, tlen);
+	      o = variable_buffer_output (o, t, strlen (t));
 	      return o;
 	    }
@@ -118,9 +115,7 @@
       /* If we're substituting only by fully matched words,
 	 or only at the ends of words, check that this case qualifies.  */
-      if ((by_word
-	   && ((p > t && !isblank ((unsigned char)p[-1]))
-	       || (p[slen] != '\0' && !isblank ((unsigned char)p[slen]))))
-	  || (suffix_only
-	      && (p[slen] != '\0' && !isblank ((unsigned char)p[slen]))))
+      if (by_word
+          && ((p > text && !isblank ((unsigned char)p[-1]))
+              || (p[slen] != '\0' && !isblank ((unsigned char)p[slen]))))
 	/* Struck out.  Output the rest of the string that is
 	   no longer to be replaced.  */
@@ -130,8 +125,7 @@
 	o = variable_buffer_output (o, replace, rlen);
 
-      /* Advance T past the string to be replaced; adjust tlen.  */
+      /* Advance T past the string to be replaced.  */
       {
         char *nt = p + slen;
-        tlen -= nt - t;
         t = nt;
       }
@@ -140,4 +134,5 @@
   return o;
 }
+
 
 
@@ -147,5 +142,8 @@
    run through find_percent, and PATTERN_PERCENT is the result.
    If REPLACE_PERCENT is not nil, REPLACE has already been
-   run through find_percent, and REPLACE_PERCENT is the result.  */
+   run through find_percent, and REPLACE_PERCENT is the result.
+   Note that we expect PATTERN_PERCENT and REPLACE_PERCENT to point to the
+   character _AFTER_ the %, not to the % itself.
+*/
 
 char *
@@ -154,5 +152,5 @@
 {
   unsigned int pattern_prepercent_len, pattern_postpercent_len;
-  unsigned int replace_prepercent_len, replace_postpercent_len = 0;
+  unsigned int replace_prepercent_len, replace_postpercent_len;
   char *t;
   unsigned int len;
@@ -161,29 +159,39 @@
   /* We call find_percent on REPLACE before checking PATTERN so that REPLACE
      will be collapsed before we call subst_expand if PATTERN has no %.  */
-  if (replace_percent == 0)
-    replace_percent = find_percent (replace);
-  if (replace_percent != 0)
-    {
-      /* Record the length of REPLACE before and after the % so
-	 we don't have to compute these lengths more than once.  */
-      replace_prepercent_len = replace_percent - replace;
-      replace_postpercent_len = strlen (replace_percent + 1);
+  if (!replace_percent)
+    {
+      replace_percent = find_percent (replace);
+      if (replace_percent)
+        ++replace_percent;
+    }
+
+  /* Record the length of REPLACE before and after the % so we don't have to
+     compute these lengths more than once.  */
+  if (replace_percent)
+    {
+      replace_prepercent_len = replace_percent - replace - 1;
+      replace_postpercent_len = strlen (replace_percent);
     }
   else
-    /* We store the length of the replacement
-       so we only need to compute it once.  */
-    replace_prepercent_len = strlen (replace);
-
-  if (pattern_percent == 0)
-    pattern_percent = find_percent (pattern);
-  if (pattern_percent == 0)
+    {
+      replace_prepercent_len = strlen (replace);
+      replace_postpercent_len = 0;
+    }
+
+  if (!pattern_percent)
+    {
+      pattern_percent = find_percent (pattern);
+      if (pattern_percent)
+        ++pattern_percent;
+    }
+  if (!pattern_percent)
     /* With no % in the pattern, this is just a simple substitution.  */
     return subst_expand (o, text, pattern, replace,
-			 strlen (pattern), strlen (replace), 1, 0);
+			 strlen (pattern), strlen (replace), 1);
 
   /* Record the length of PATTERN before and after the %
      so we don't have to compute it more than once.  */
-  pattern_prepercent_len = pattern_percent - pattern;
-  pattern_postpercent_len = strlen (pattern_percent + 1);
+  pattern_prepercent_len = pattern_percent - pattern - 1;
+  pattern_postpercent_len = strlen (pattern_percent);
 
   while ((t = find_next_token (&text, &len)) != 0)
@@ -198,5 +206,5 @@
       if (!fail && pattern_prepercent_len > 0
 	  && (*t != *pattern
-	      || t[pattern_prepercent_len - 1] != pattern_percent[-1]
+	      || t[pattern_prepercent_len - 1] != pattern_percent[-2]
 	      || !strneq (t + 1, pattern + 1, pattern_prepercent_len - 1)))
 	fail = 1;
@@ -204,8 +212,8 @@
       /* Does the suffix match? */
       if (!fail && pattern_postpercent_len > 0
-	  && (t[len - 1] != pattern_percent[pattern_postpercent_len]
-	      || t[len - pattern_postpercent_len] != pattern_percent[1]
+	  && (t[len - 1] != pattern_percent[pattern_postpercent_len - 1]
+	      || t[len - pattern_postpercent_len] != *pattern_percent
 	      || !strneq (&t[len - pattern_postpercent_len],
-			  &pattern_percent[1], pattern_postpercent_len - 1)))
+			  pattern_percent, pattern_postpercent_len - 1)))
 	fail = 1;
 
@@ -228,5 +236,5 @@
 						 + pattern_postpercent_len));
 	      /* Output the part of the replacement after the %.  */
-	      o = variable_buffer_output (o, replace_percent + 1,
+	      o = variable_buffer_output (o, replace_percent,
 					  replace_postpercent_len);
 	    }
@@ -648,5 +656,5 @@
 {
   o = subst_expand (o, argv[2], argv[0], argv[1], strlen (argv[0]),
-		    strlen (argv[1]), 0, 0);
+		    strlen (argv[1]), 0);
 
   return o;
@@ -667,4 +675,20 @@
 }
 
+static char *
+func_lastword (char *o, char **argv, const char *funcname UNUSED)
+{
+  unsigned int i;
+  char *words = argv[0];    /* Use a temp variable for find_next_token */
+  char *p = 0;
+  char *t;
+
+  while ((t = find_next_token (&words, &i)))
+    p = t;
+
+  if (p != 0)
+    o = variable_buffer_output (o, p, i);
+
+  return o;
+}
 
 static char *
@@ -690,5 +714,5 @@
  * begpp-1.
  */
-static char *
+char *
 strip_whitespace (const char **begpp, const char **endpp)
 {
@@ -755,4 +779,8 @@
 
   start = atoi (argv[0]);
+  if (start < 1)
+    fatal (reading_file,
+           "invalid first argument to `wordlist' function: `%d'", start);
+
   count = atoi (argv[1]) - start + 1;
 
@@ -784,7 +812,6 @@
 {
   /* Find the first occurrence of the first string in the second.  */
-  int i = strlen (argv[0]);
-  if (sindex (argv[1], 0, argv[0], i) != 0)
-    o = variable_buffer_output (o, argv[0], i);
+  if (strstr (argv[1], argv[0]) != 0)
+    o = variable_buffer_output (o, argv[0], strlen (argv[0]));
 
   return o;
@@ -1067,10 +1094,21 @@
   strcpy (p, *argvp);
 
-  if (*funcname == 'e')
-    fatal (reading_file, "%s", msg);
+  switch (*funcname) {
+    case 'e':
+      fatal (reading_file, "%s", msg);
+
+    case 'w':
+      error (reading_file, "%s", msg);
+      break;
+
+    case 'i':
+      printf ("%s\n", msg);
+      break;
+
+    default:
+      fatal (reading_file, "Internal error: func_error: '%s'", funcname);
+  }
 
   /* The warning function expands to the empty string.  */
-  error (reading_file, "%s", msg);
-
   return o;
 }
@@ -1457,5 +1495,5 @@
 
   /* For error messages.  */
-  if (reading_file != 0)
+  if (reading_file && reading_file->filenm)
     {
       error_prefix = (char *) alloca (strlen (reading_file->filenm)+11+4);
@@ -1700,5 +1738,5 @@
  */
 static char *
-func_eq (char* o, char **argv, char *funcname)
+func_eq (char *o, char **argv, char *funcname)
 {
   int result = ! strcmp (argv[0], argv[1]);
@@ -1712,7 +1750,7 @@
  */
 static char *
-func_not (char* o, char **argv, char *funcname)
-{
-  char * s = argv[0];
+func_not (char *o, char **argv, char *funcname)
+{
+  char *s = argv[0];
   int result = 0;
   while (isspace ((unsigned char)*s))
@@ -1726,4 +1764,157 @@
 
 
+/* Return the absolute name of file NAME which does not contain any `.',
+   `..' components nor any repeated path separators ('/').   */
+
+static char *
+abspath (const char *name, char *apath)
+{
+  char *dest;
+  const char *start, *end, *apath_limit;
+
+  if (name[0] == '\0' || apath == NULL)
+    return NULL;
+
+  apath_limit = apath + GET_PATH_MAX;
+
+  if (name[0] != '/')
+    {
+      /* It is unlikely we would make it until here but just to make sure. */
+      if (!starting_directory)
+	return NULL;
+
+      strcpy (apath, starting_directory);
+
+      dest = strchr (apath, '\0');
+    }
+  else
+    {
+      apath[0] = '/';
+      dest = apath + 1;
+    }
+
+  for (start = end = name; *start != '\0'; start = end)
+    {
+      unsigned long len;
+
+      /* Skip sequence of multiple path-separators.  */
+      while (*start == '/')
+	++start;
+
+      /* Find end of path component.  */
+      for (end = start; *end != '\0' && *end != '/'; ++end)
+        ;
+
+      len = end - start;
+
+      if (len == 0)
+	break;
+      else if (len == 1 && start[0] == '.')
+	/* nothing */;
+      else if (len == 2 && start[0] == '.' && start[1] == '.')
+	{
+	  /* Back up to previous component, ignore if at root already.  */
+	  if (dest > apath + 1)
+	    while ((--dest)[-1] != '/');
+	}
+      else
+	{
+	  if (dest[-1] != '/')
+            *dest++ = '/';
+
+	  if (dest + len >= apath_limit)
+            return NULL;
+
+	  dest = memcpy (dest, start, len);
+          dest += len;
+	  *dest = '\0';
+	}
+    }
+
+  /* Unless it is root strip trailing separator.  */
+  if (dest > apath + 1 && dest[-1] == '/')
+    --dest;
+
+  *dest = '\0';
+
+  return apath;
+}
+
+
+static char *
+func_realpath (char *o, char **argv, const char *funcname UNUSED)
+{
+  /* Expand the argument.  */
+  char *p = argv[0];
+  char *path = 0;
+  int doneany = 0;
+  unsigned int len = 0;
+  PATH_VAR (in);
+  PATH_VAR (out);
+
+  while ((path = find_next_token (&p, &len)) != 0)
+    {
+      if (len < GET_PATH_MAX)
+        {
+          strncpy (in, path, len);
+          in[len] = '\0';
+
+          if
+          (
+#ifdef HAVE_REALPATH
+            realpath (in, out)
+#else
+            abspath (in, out)
+#endif
+          )
+            {
+              o = variable_buffer_output (o, out, strlen (out));
+              o = variable_buffer_output (o, " ", 1);
+              doneany = 1;
+            }
+        }
+    }
+
+  /* Kill last space.  */
+  if (doneany)
+    --o;
+
+ return o;
+}
+
+static char *
+func_abspath (char *o, char **argv, const char *funcname UNUSED)
+{
+  /* Expand the argument.  */
+  char *p = argv[0];
+  char *path = 0;
+  int doneany = 0;
+  unsigned int len = 0;
+  PATH_VAR (in);
+  PATH_VAR (out);
+
+  while ((path = find_next_token (&p, &len)) != 0)
+    {
+      if (len < GET_PATH_MAX)
+        {
+          strncpy (in, path, len);
+          in[len] = '\0';
+
+          if (abspath (in, out))
+            {
+              o = variable_buffer_output (o, out, strlen (out));
+              o = variable_buffer_output (o, " ", 1);
+              doneany = 1;
+            }
+        }
+    }
+
+  /* Kill last space.  */
+  if (doneany)
+    --o;
+
+ return o;
+}
+
 /* Lookup table for builtin functions.
 
@@ -1744,4 +1935,5 @@
 {
  /* Name/size */                    /* MIN MAX EXP? Function */
+  { STRING_SIZE_TUPLE("abspath"),       0,  1,  1,  func_abspath},
   { STRING_SIZE_TUPLE("addprefix"),     2,  2,  1,  func_addsuffix_addprefix},
   { STRING_SIZE_TUPLE("addsuffix"),     2,  2,  1,  func_addsuffix_addprefix},
@@ -1756,5 +1948,7 @@
   { STRING_SIZE_TUPLE("firstword"),     0,  1,  1,  func_firstword},
   { STRING_SIZE_TUPLE("join"),          2,  2,  1,  func_join},
+  { STRING_SIZE_TUPLE("lastword"),      0,  1,  1,  func_lastword},
   { STRING_SIZE_TUPLE("patsubst"),      3,  3,  1,  func_patsubst},
+  { STRING_SIZE_TUPLE("realpath"),      0,  1,  1,  func_realpath},
   { STRING_SIZE_TUPLE("shell"),         0,  1,  1,  func_shell},
   { STRING_SIZE_TUPLE("sort"),          0,  1,  1,  func_sort},
@@ -1767,4 +1961,5 @@
   { STRING_SIZE_TUPLE("foreach"),       3,  3,  0,  func_foreach},
   { STRING_SIZE_TUPLE("call"),          1,  0,  1,  func_call},
+  { STRING_SIZE_TUPLE("info"),          0,  1,  1,  func_error},
   { STRING_SIZE_TUPLE("error"),         0,  1,  1,  func_error},
   { STRING_SIZE_TUPLE("warning"),       0,  1,  1,  func_error},
Index: branches/GNU/src/gmake/getloadavg.c
===================================================================
--- branches/GNU/src/gmake/getloadavg.c	(revision 157)
+++ branches/GNU/src/gmake/getloadavg.c	(revision 280)
@@ -356,5 +356,5 @@
 /* LOAD_AVE_TYPE should only get defined if we're going to use the
    nlist method.  */
-# if !defined(LOAD_AVE_TYPE) && (defined(BSD) || defined(LDAV_CVT) || defined(KERNEL_FILE) || defined(LDAV_SYMBOL))
+# if !defined(LOAD_AVE_TYPE) && (defined(BSD) || defined(LDAV_CVT) || defined(KERNEL_FILE) || defined(LDAV_SYMBOL)) && !defined(__riscos__)
 #  define LOAD_AVE_TYPE double
 # endif
Index: branches/GNU/src/gmake/glob/ChangeLog
===================================================================
--- branches/GNU/src/gmake/glob/ChangeLog	(revision 157)
+++ branches/GNU/src/gmake/glob/ChangeLog	(revision 280)
@@ -1,2 +1,7 @@
+2005-03-11  Paul D. Smith  <psmith@gnu.org>
+
+	* glob.c (glob_in_dir): Change FNM_CASEFOLD to be enabled if
+	HAVE_CASE_INSENSITIVE_FS is defined.
+
 2003-01-30  Paul D. Smith  <psmith@gnu.org>
 
Index: branches/GNU/src/gmake/glob/glob.c
===================================================================
--- branches/GNU/src/gmake/glob/glob.c	(revision 157)
+++ branches/GNU/src/gmake/glob/glob.c	(revision 280)
@@ -1305,5 +1305,5 @@
 	      int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)
 			       | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)
-#if defined _AMIGA || defined VMS
+#if defined HAVE_CASE_INSENSITIVE_FS
 				   | FNM_CASEFOLD
 #endif
Index: branches/GNU/src/gmake/implicit.c
===================================================================
--- branches/GNU/src/gmake/implicit.c	(revision 157)
+++ branches/GNU/src/gmake/implicit.c	(revision 280)
@@ -1,4 +1,4 @@
 /* Implicit rule searching for GNU Make.
-Copyright (C) 1988,89,90,91,92,93,94,97,2000 Free Software Foundation, Inc.
+Copyright (C) 1988,1989,1990,1991,1992,1993,1994,1997,2000,2004,2005 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
@@ -23,7 +23,11 @@
 #include "dep.h"
 #include "debug.h"
-
-static int pattern_search PARAMS ((struct file *file, int archive, unsigned int depth,
-		unsigned int recursions));
+#include "variable.h"
+#include "job.h"      /* struct child, used inside commands.h */
+#include "commands.h" /* set_file_variables */
+
+static int
+pattern_search PARAMS ((struct file *file, int archive,
+                        unsigned int depth, unsigned int recursions));
 
 
@@ -64,4 +68,124 @@
 
 
+/* Struct idep captures information about implicit prerequisites
+   that come from implicit rules. */
+struct idep
+{
+  struct idep *next;              /* struct dep -compatible interface */
+  char *name;                     /* name of the prerequisite */
+  struct file *intermediate_file; /* intermediate file, 0 otherwise */
+  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)
+{
+  register struct idep* n;
+  register struct file *f;
+
+  for (; p != 0; p = n)
+    {
+      n = p->next;
+
+      if (p->name)
+        {
+          free (p->name);
+
+          f = p->intermediate_file;
+
+          if (f != 0
+              && (f->stem < f->name
+                  || f->stem > f->name + strlen (f->name)))
+            free (f->stem);
+        }
+
+      free (p);
+    }
+}
+
+
+/* Scans the BUFFER for the next word with whitespace as a separator.
+   Returns the pointer to the beginning of the word. LENGTH hold the
+   length of the word.  */
+
+static char *
+get_next_word (char *buffer, unsigned int *length)
+{
+  char *p = buffer, *beg;
+  char c;
+
+  /* Skip any leading whitespace.  */
+  while (isblank ((unsigned char)*p))
+    ++p;
+
+  beg = p;
+  c = *(p++);
+
+  if (c == '\0')
+    return 0;
+
+
+  /* We already found the first value of "c", above.  */
+  while (1)
+    {
+      char closeparen;
+      int count;
+
+      switch (c)
+        {
+        case '\0':
+        case ' ':
+        case '\t':
+          goto done_word;
+
+        case '$':
+          c = *(p++);
+          if (c == '$')
+            break;
+
+          /* This is a variable reference, so read it to the matching
+             close paren.  */
+
+          if (c == '(')
+            closeparen = ')';
+          else if (c == '{')
+            closeparen = '}';
+          else
+            /* This is a single-letter variable reference.  */
+            break;
+
+          for (count = 0; *p != '\0'; ++p)
+            {
+              if (*p == c)
+                ++count;
+              else if (*p == closeparen && --count < 0)
+                {
+                  ++p;
+                  break;
+                }
+            }
+          break;
+
+        case '|':
+          goto done;
+
+        default:
+          break;
+        }
+
+      c = *(p++);
+    }
+ done_word:
+  --p;
+
+ done:
+  if (length)
+    *length = p - beg;
+
+  return beg;
+}
+
 /* Search the pattern rules for a rule with an existing dependency to make
    FILE.  If a rule is found, the appropriate commands and deps are put in FILE
@@ -96,18 +220,11 @@
   struct file *intermediate_file = 0;
 
-  /* List of dependencies found recursively.  */
-  struct file **intermediate_files
-    = (struct file **) xmalloc (max_pattern_deps * sizeof (struct file *));
-
-  /* List of the patterns used to find intermediate files.  */
-  char **intermediate_patterns
-    = (char **) alloca (max_pattern_deps * sizeof (char *));
-
-  /* This buffer records all the dependencies actually found for a rule.  */
-  char **found_files = (char **) alloca (max_pattern_deps * sizeof (char *));
-  /* Remember whether the associated dep has an "ignore_mtime" flag set.  */
-  unsigned char *found_files_im = (unsigned char *) alloca (max_pattern_deps * sizeof (unsigned char));
-  /* Number of dep names now in FOUND_FILES.  */
-  unsigned int deps_found = 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;
 
   /* Names of possible dependencies are constructed in this buffer.  */
@@ -149,7 +266,13 @@
   register unsigned int i = 0;  /* uninit checks OK */
   register struct rule *rule;
-  register struct dep *dep;
-
-  char *p, *vp;
+  register struct dep *dep, *expl_d;
+
+  char *p, *vname;
+
+  struct idep *d;
+  struct idep **id_ptr;
+  struct dep **d_ptr;
+
+  PATH_VAR (stem_str); /* @@ Need to get rid of stem, stemlen, etc. */
 
 #ifndef	NO_ARCHIVES
@@ -298,16 +421,24 @@
 	}
 
+  /* 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)
     {
       /* Try each pattern rule till we find one that applies.
-	 If it does, copy the names of its dependencies (as substituted)
-	 and store them in FOUND_FILES.  DEPS_FOUND is the number of them.  */
+	 If it does, expand its dependencies (as substituted)
+	 and chain them in DEPS.  */
 
       for (i = 0; i < nrules; i++)
 	{
+          struct file *f;
+          unsigned int failed = 0;
 	  int check_lastslash;
 
 	  rule = tryrules[i];
+
+          remove_explicit_deps = 0;
 
 	  /* RULE is nil when we discover that a rule,
@@ -340,145 +471,270 @@
                              (int) stemlen, stem));
 
+          strncpy (stem_str, stem, stemlen);
+          stem_str[stemlen] = '\0';
+
+          /* Temporary assign STEM to file->stem and set file variables. */
+          file->stem = stem_str;
+          set_file_variables (file);
+
 	  /* Try each dependency; see if it "exists".  */
 
-	  deps_found = 0;
+          /* @@ There is always only one dep line for any given implicit
+                rule. So the loop is not necessary. Can rule->deps be 0?
+
+                Watch out for conversion of suffix rules to implicit rules.
+          */
+
 	  for (dep = rule->deps; dep != 0; dep = dep->next)
 	    {
-	      /* If the dependency name has a %, substitute the stem.  */
-	      p = strchr (dep_name (dep), '%');
-	      if (p != 0)
-		{
-		  register unsigned int i;
-		  if (check_lastslash)
-		    {
-		      /* Copy directory name from the original FILENAME.  */
-		      i = lastslash - filename + 1;
-		      bcopy (filename, depname, i);
-		    }
-		  else
-		    i = 0;
-		  bcopy (dep_name (dep), depname + i, p - dep_name (dep));
-		  i += p - dep_name (dep);
-		  bcopy (stem, depname + i, stemlen);
-		  i += stemlen;
-		  strcpy (depname + i, p + 1);
-		  p = depname;
-		}
-	      else
-		p = dep_name (dep);
-
-	      /* P is now the actual dependency name as substituted.  */
-
-	      if (file_impossible_p (p))
-		{
-		  /* 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,
-                       (p == depname
+              unsigned int len;
+              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 resulting prerequisite.  */
+
+              p = get_next_word (dep->name, &len);
+
+              while (1)
+                {
+                  int add_dir = 0;
+                  int had_stem = 0;
+
+                  if (p == 0)
+                    break; /* No more words */
+
+                  /* 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 setm (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.  */
+
+                  for (p2 = p; p2 < p + len && *p2 != '%'; ++p2)
+                    ;
+
+                  if (p2 < p + len)
+                    {
+                      register unsigned int i = p2 - p;
+                      bcopy (p, depname, i);
+                      bcopy ("$*", depname + i, 2);
+                      bcopy (p2 + 1, depname + i + 2, len - i - 1);
+                      depname[len + 2 - 1] = '\0';
+
+                      if (check_lastslash)
+                        add_dir = 1;
+
+                      had_stem = 1;
+                    }
+                  else
+                    {
+                      bcopy (p, depname, len);
+                      depname[len] = '\0';
+                    }
+
+                  p2 = variable_expand_for_file (depname, file);
+
+                  /* Parse the dependencies. */
+
+                  while (1)
+                    {
+                      id_ptr = &deps;
+
+                      for (; *id_ptr; id_ptr = &(*id_ptr)->next)
+                        ;
+
+                      *id_ptr = (struct idep *)
+                        multi_glob (
+                          parse_file_seq (&p2,
+                                          order_only ? '\0' : '|',
+                                          sizeof (struct idep),
+                                          1), sizeof (struct idep));
+
+                      /* @@ 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 *p = d->name;
+
+                                  d->name = xmalloc (strlen (p) + l + 1);
+
+                                  bcopy (filename, d->name, l);
+                                  bcopy (p, d->name + l, strlen (p) + 1);
+
+                                  free (p);
+                                }
+
+                              if (had_stem)
+                                d->had_stem = 1;
+                            }
+                        }
+
+                      if (!order_only && *p2)
+                      {
+                        ++p2;
+                        order_only = 1;
+                        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)
+            {
+              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"),
-                        p));
-		  tryrules[i] = 0;
-		  break;
-		}
-
-	      intermediate_files[deps_found] = 0;
-
-	      DBS (DB_IMPLICIT,
-                   (p == depname
+                        name));
+                  tryrules[i] = 0;
+
+                  failed = 1;
+                  break;
+                }
+
+              DBS (DB_IMPLICIT,
+                   (d->had_stem
                     ? _("Trying implicit prerequisite `%s'.\n")
-                    : _("Trying rule prerequisite `%s'.\n"), p));
-
-	      /* 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.  */
-
-	      if (lookup_file (p) != 0
-		  || ((!dep->changed || check_lastslash) && file_exists_p (p)))
-		{
-		  found_files_im[deps_found] = dep->ignore_mtime;
-		  found_files[deps_found++] = xstrdup (p);
-		  continue;
-		}
-	      /* This code, given FILENAME = "lib/foo.o", dependency name
-		 "lib/foo.c", and VPATH=src, searches for "src/lib/foo.c".  */
-	      vp = p;
-	      if (vpath_search (&vp, (FILE_TIMESTAMP *) 0))
-		{
-		  DBS (DB_IMPLICIT,
-                       (_("Found prerequisite `%s' as VPATH `%s'\n"), p, vp));
-		  strcpy (vp, p);
-		  found_files_im[deps_found] = dep->ignore_mtime;
-		  found_files[deps_found++] = vp;
-		  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
-		      = (struct file *) alloca (sizeof (struct file));
-
-		  DBS (DB_IMPLICIT,
+                    : _("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 (strcmp (dep_name (expl_d), name) == 0) 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".  */
+              vname = name;
+              if (vpath_search (&vname, (FILE_TIMESTAMP *) 0))
+                {
+                  DBS (DB_IMPLICIT,
+                       (_("Found prerequisite `%s' as VPATH `%s'\n"),
+                        name,
+                        vname));
+
+                  free (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
+                      = (struct file *) alloca (sizeof (struct file));
+
+                  DBS (DB_IMPLICIT,
                        (_("Looking for a rule with intermediate file `%s'.\n"),
-                        p));
-
-		  bzero ((char *) intermediate_file, sizeof (struct file));
-		  intermediate_file->name = p;
-		  if (pattern_search (intermediate_file, 0, depth + 1,
-				      recursions + 1))
-		    {
-		      p = xstrdup (p);
-		      intermediate_patterns[deps_found]
-			= intermediate_file->name;
-		      intermediate_file->name = p;
-		      intermediate_files[deps_found] = intermediate_file;
-		      intermediate_file = 0;
-		      found_files_im[deps_found] = dep->ignore_mtime;
-		      /* Allocate an extra copy to go in FOUND_FILES,
-			 because every elt of FOUND_FILES is consumed
-			 or freed later.  */
-		      found_files[deps_found++] = xstrdup (p);
-		      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.  */
-		  file_impossible (p);
-		}
-
-	      /* A dependency of this rule does not exist.
-		 Therefore, this rule fails.  */
-	      break;
-	    }
-
-	  /* This rule is no longer `in use' for recursive searches.  */
+                        name));
+
+                  bzero ((char *) intermediate_file, sizeof (struct file));
+                  intermediate_file->name = name;
+                  if (pattern_search (intermediate_file,
+                                      0,
+                                      depth + 1,
+                                      recursions + 1))
+                    {
+                      d->intermediate_file = intermediate_file;
+                      d->intermediate_pattern = intermediate_file->name;
+
+                      intermediate_file->name = xstrdup (name);
+                      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.  */
+                  file_impossible (name);
+                }
+
+              /* A dependency of this rule does not exist. Therefore,
+                 this rule fails.  */
+              failed = 1;
+              break;
+            }
+
+          /* This rule is no longer `in use' for recursive searches.  */
 	  rule->in_use = 0;
 
-	  if (dep != 0)
-	    {
-	      /* This pattern rule does not apply.
-		 If some of its dependencies succeeded,
-		 free the data structure describing them.  */
-	      while (deps_found-- > 0)
-		{
-		  register struct file *f = intermediate_files[deps_found];
-		  free (found_files[deps_found]);
-		  if (f != 0
-		      && (f->stem < f->name
-			  || f->stem > f->name + strlen (f->name)))
-		    free (f->stem);
-		}
-	    }
+          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.  */
@@ -512,9 +768,28 @@
      Convert them into entries on the deps-chain of FILE.  */
 
-  while (deps_found-- > 0)
+  if (remove_explicit_deps)
+    {
+      /* Remove all the dependencies that didn't come from
+         this implicit rule. */
+
+      dep = file->deps;
+      while (dep != 0)
+        {
+          struct dep *next = dep->next;
+          free (dep->name);
+          free ((char *)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)
     {
       register char *s;
 
-      if (intermediate_files[deps_found] != 0)
+      if (d->intermediate_file != 0)
 	{
 	  /* If we need to use an intermediate file,
@@ -525,13 +800,28 @@
 	     of F below are null before we change them.  */
 
-	  struct file *imf = intermediate_files[deps_found];
-	  register struct file *f = enter_file (imf->name);
+	  struct file *imf = d->intermediate_file;
+	  register struct file *f = lookup_file (imf->name);
+
+          /* We don't want to delete an intermediate file that happened
+             to be a prerequisite of some (other) target. Mark it as
+             precious.  */
+          if (f != 0)
+            f->precious = 1;
+          else
+            f = enter_file (imf->name);
+
 	  f->deps = imf->deps;
 	  f->cmds = imf->cmds;
 	  f->stem = imf->stem;
           f->also_make = imf->also_make;
-	  imf = lookup_file (intermediate_patterns[deps_found]);
-	  if (imf != 0 && imf->precious)
-	    f->precious = 1;
+          f->is_target = 1;
+
+          if (!f->precious)
+            {
+              imf = lookup_file (d->intermediate_pattern);
+              if (imf != 0 && imf->precious)
+                f->precious = 1;
+            }
+
 	  f->intermediate = 1;
 	  f->tried_implicit = 1;
@@ -548,6 +838,8 @@
 
       dep = (struct dep *) xmalloc (sizeof (struct dep));
-      dep->ignore_mtime = found_files_im[deps_found];
-      s = found_files[deps_found];
+      dep->ignore_mtime = d->ignore_mtime;
+      dep->need_2nd_expansion = 0;
+      s = d->name; /* Hijacking the name. */
+      d->name = 0;
       if (recursions == 0)
 	{
@@ -568,5 +860,5 @@
 	  dep->changed = 0;
 	}
-      if (intermediate_files[deps_found] == 0 && tryrules[foundrule]->terminal)
+      if (d->intermediate_file == 0 && tryrules[foundrule]->terminal)
 	{
 	  /* If the file actually existed (was not an intermediate file),
@@ -580,7 +872,10 @@
 	    dep->file->tried_implicit = 1;
 	}
-      dep->next = file->deps;
-      file->deps = dep;
+
+      *d_ptr = dep;
+      d_ptr = &dep->next;
     }
+
+  *d_ptr = expl_d;
 
   if (!checked_lastslash[foundrule])
@@ -605,4 +900,5 @@
 
   file->cmds = rule->cmds;
+  file->is_target = 1;
 
   /* If this rule builds other targets, too, put the others into FILE's
@@ -616,4 +912,5 @@
 	  /* GKM FIMXE: handle '|' here too */
 	  new->ignore_mtime = 0;
+	  new->need_2nd_expansion = 0;
 	  new->name = p = (char *) xmalloc (rule->lens[i] + fullstemlen + 1);
 	  bcopy (rule->targets[i], p,
@@ -630,5 +927,5 @@
 
  done:
-  free (intermediate_files);
+  free_idep_chain (deps);
   free (tryrules);
 
Index: branches/GNU/src/gmake/job.c
===================================================================
--- branches/GNU/src/gmake/job.c	(revision 157)
+++ branches/GNU/src/gmake/job.c	(revision 280)
@@ -1,4 +1,5 @@
 /* Job execution and handling for GNU Make.
-Copyright (C) 1988,89,90,91,92,93,94,95,96,97,99 Free Software Foundation, Inc.
+Copyright (C) 1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1999,
+2000,2001,2002,2003,2004,2005 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
@@ -61,4 +62,9 @@
 
 # include <descrip.h>
+char default_shell[] = "";
+int batch_mode_shell = 0;
+
+#elif defined (__riscos__)
+
 char default_shell[] = "";
 int batch_mode_shell = 0;
@@ -168,8 +174,4 @@
 #endif	/* Don't have `union wait'.  */
 
-#ifdef VMS
-static int vms_jobsefnmask = 0;
-#endif /* !VMS */
-
 #ifndef	HAVE_UNISTD_H
 extern int dup2 ();
@@ -199,7 +201,4 @@
 static int job_next_command PARAMS ((struct child *));
 static int start_waiting_job PARAMS ((struct child *));
-#ifdef VMS
-static void vmsWaitForChildren PARAMS ((int *));
-#endif
 
 
@@ -228,4 +227,7 @@
 unsigned long job_counter = 0;
 
+/* Number of jobserver tokens this instance is currently using.  */
+
+unsigned int jobserver_tokens = 0;
 
 
@@ -237,5 +239,88 @@
 w32_kill(int pid, int sig)
 {
-  return ((process_kill(pid, sig) == TRUE) ? 0 : -1);
+  return ((process_kill((HANDLE)pid, sig) == TRUE) ? 0 : -1);
+}
+
+/* This function creates a temporary file name with the given extension
+ * the unixy param controls both the extension and the path separator
+ * return an xmalloc'ed string of a newly created temp file or die.  */
+static char *
+create_batch_filename(char const *base, int unixy)
+{
+  const char *const ext = unixy ? "sh" : "bat";
+  const char *error = NULL;
+  char temp_path[MAXPATHLEN]; /* need to know its length */
+  unsigned path_size = GetTempPath(sizeof temp_path, temp_path);
+  int path_is_dot = 0;
+  unsigned uniq = 1;
+  const unsigned sizemax = strlen (base) + strlen (ext) + 10;
+
+  if (path_size == 0)
+    {
+      path_size = GetCurrentDirectory (sizeof temp_path, temp_path);
+      path_is_dot = 1;
+    }
+
+  while (path_size > 0 &&
+         path_size + sizemax < sizeof temp_path &&
+         uniq < 0x10000)
+    {
+      unsigned size = sprintf (temp_path + path_size,
+                               "%s%s-%x.%s",
+                               temp_path[path_size - 1] == '\\' ? "" : "\\",
+                               base, uniq, ext);
+      HANDLE h = CreateFile (temp_path,  /* file name */
+                             GENERIC_READ | GENERIC_WRITE, /* desired access */
+                             0,                            /* no share mode */
+                             NULL,                         /* default security attributes */
+                             CREATE_NEW,                   /* creation disposition */
+                             FILE_ATTRIBUTE_NORMAL |       /* flags and attributes */
+                             FILE_ATTRIBUTE_TEMPORARY,     /* we'll delete it */
+                             NULL);                        /* no template file */
+
+      if (h == INVALID_HANDLE_VALUE)
+        {
+          const DWORD er = GetLastError();
+
+          if (er == ERROR_FILE_EXISTS || er == ERROR_ALREADY_EXISTS)
+            ++uniq;
+
+          /* the temporary path is not guaranteed to exist */
+          else if (path_is_dot == 0)
+            {
+              path_size = GetCurrentDirectory (sizeof temp_path, temp_path);
+              path_is_dot = 1;
+            }
+
+          else
+            {
+              error = map_windows32_error_to_string (er);
+              break;
+            }
+        }
+      else
+        {
+          const unsigned final_size = path_size + size + 1;
+          char *const path = (char *) xmalloc (final_size);
+          memcpy (path, temp_path, final_size);
+          CloseHandle (h);
+          if (unixy)
+            {
+              char *p;
+              int ch;
+              for (p = path; (ch = *p) != 0; ++p)
+                if (ch == '\\')
+                  *p = '/';
+            }
+          return path; /* good return */
+        }
+    }
+
+  if (error == NULL)
+    error = _("Cannot create a temporary file\n");
+  fatal (NILF, error);
+
+  /* not reached */
+  return NULL;
 }
 #endif /* WINDOWS32 */
@@ -317,93 +402,4 @@
 
 
-#ifdef VMS
-/* Wait for nchildren children to terminate */
-static void
-vmsWaitForChildren(int *status)
-{
-  while (1)
-    {
-      if (!vms_jobsefnmask)
-	{
-	  *status = 0;
-	  return;
-	}
-
-      *status = sys$wflor (32, vms_jobsefnmask);
-    }
-  return;
-}
-
-/* Set up IO redirection.  */
-
-char *
-vms_redirect (struct dsc$descriptor_s *desc, char *fname, char *ibuf)
-{
-  char *fptr;
-  extern char *vmsify ();
-
-  ibuf++;
-  while (isspace ((unsigned char)*ibuf))
-    ibuf++;
-  fptr = ibuf;
-  while (*ibuf && !isspace ((unsigned char)*ibuf))
-    ibuf++;
-  *ibuf = 0;
-  if (strcmp (fptr, "/dev/null") != 0)
-    {
-      strcpy (fname, vmsify (fptr, 0));
-      if (strchr (fname, '.') == 0)
-	strcat (fname, ".");
-    }
-  desc->dsc$w_length = strlen(fname);
-  desc->dsc$a_pointer = fname;
-  desc->dsc$b_dtype = DSC$K_DTYPE_T;
-  desc->dsc$b_class = DSC$K_CLASS_S;
-
-  if (*fname == 0)
-    printf (_("Warning: Empty redirection\n"));
-  return ibuf;
-}
-
-
-/* found apostrophe at (p-1)
-   inc p until after closing apostrophe.
- */
-
-static char *
-vms_handle_apos (char *p)
-{
-  int alast;
-
-#define SEPCHARS ",/()= "
-
-  alast = 0;
-
-  while (*p != 0)
-    {
-      if (*p == '"')
-	{
-          if (alast)
-            {
-              alast = 0;
-              p++;
-	    }
-	  else
-	    {
-	      p++;
-	      if (strchr (SEPCHARS, *p))
-		break;
-	      alast = 1;
-	    }
-	}
-      else
-	p++;
-    }
-
-  return p;
-}
-
-#endif
-
 
 /* Handle a dead child.  This handler may or may not ever be installed.
@@ -474,5 +470,5 @@
     {
       int remote = 0;
-      register int pid;
+      pid_t pid;
       int exit_code, exit_sig, coredump;
       register struct child *lastc, *c;
@@ -543,4 +539,5 @@
 	    {
 #ifdef VMS
+              static void vmsWaitForChildren PARAMS ((int *));
 	      vmsWaitForChildren (&status);
 	      pid = c->pid;
@@ -616,27 +613,32 @@
             HANDLE hPID;
             int err;
+            exit_code = 0;
+            exit_sig = 0;
+            coredump = 0;
 
             /* wait for anything to finish */
-            if (hPID = process_wait_for_any()) {
-
-              /* was an error found on this process? */
-              err = process_last_err(hPID);
-
-              /* get exit data */
-              exit_code = process_exit_code(hPID);
-
-              if (err)
-                fprintf(stderr, "make (e=%d): %s",
-                  exit_code, map_windows32_error_to_string(exit_code));
-
-              /* signal */
-              exit_sig = process_signal(hPID);
-
-              /* cleanup process */
-              process_cleanup(hPID);
-
-              coredump = 0;
-            }
-            pid = (int) hPID;
+            hPID = process_wait_for_any();
+            if (hPID)
+              {
+
+                /* was an error found on this process? */
+                err = process_last_err(hPID);
+
+                /* get exit data */
+                exit_code = process_exit_code(hPID);
+
+                if (err)
+                  fprintf(stderr, "make (e=%d): %s",
+                          exit_code, map_windows32_error_to_string(exit_code));
+
+                /* signal */
+                exit_sig = process_signal(hPID);
+
+                /* cleanup process */
+                process_cleanup(hPID);
+
+                coredump = 0;
+              }
+            pid = (pid_t) hPID;
           }
 #endif /* WINDOWS32 */
@@ -812,9 +814,12 @@
 free_child (struct child *child)
 {
-  /* If this child is the only one it was our "free" job, so don't put a
-     token back for it.  This child has already been removed from the list,
-     so if there any left this wasn't the last one.  */
-
-  if (job_fds[1] >= 0 && children)
+  if (!jobserver_tokens)
+    fatal (NILF, "INTERNAL: Freeing child 0x%08lx (%s) but no tokens left!\n",
+           (unsigned long int) child, child->file->name);
+
+  /* If we're using the jobserver and this child is not the only outstanding
+     job, put a token back into the pipe for it.  */
+
+  if (job_fds[1] >= 0 && jobserver_tokens > 1)
     {
       char token = '+';
@@ -830,4 +835,6 @@
                     (unsigned long int) child, child->file->name));
     }
+
+  --jobserver_tokens;
 
   if (handling_fatal_signal) /* Don't bother free'ing if about to die.  */
@@ -870,5 +877,5 @@
 }
 
-#ifdef	POSIX
+#ifdef POSIX
 void
 unblock_sigs (void)
@@ -881,12 +888,22 @@
 
 #ifdef MAKE_JOBSERVER
+RETSIGTYPE
+job_noop (int sig UNUSED)
+{
+}
 /* Set the child handler action flags to FLAGS.  */
 static void
-set_child_handler_action_flags (int flags)
+set_child_handler_action_flags (int set_handler, int set_alarm)
 {
   struct sigaction sa;
+
+#ifdef __EMX__
+  /* The child handler must be turned off here.  */
+  signal (SIGCHLD, SIG_DFL);
+#endif
+
   bzero ((char *) &sa, sizeof sa);
   sa.sa_handler = child_handler;
-  sa.sa_flags = flags;
+  sa.sa_flags = set_handler ? 0 : SA_RESTART;
 #if defined SIGCHLD
   sigaction (SIGCHLD, &sa, NULL);
@@ -894,4 +911,16 @@
 #if defined SIGCLD && SIGCLD != SIGCHLD
   sigaction (SIGCLD, &sa, NULL);
+#endif
+#if defined SIGALRM
+  if (set_alarm)
+    {
+      /* If we're about to enter the read(), set an alarm to wake up in a
+         second so we can check if the load has dropped and we can start more
+         work.  On the way out, turn off the alarm and set SIG_DFL.  */
+      alarm (set_handler ? 1 : 0);
+      sa.sa_handler = set_handler ? job_noop : SIG_DFL;
+      sa.sa_flags = 0;
+      sigaction (SIGALRM, &sa, NULL);
+    }
 #endif
 }
@@ -1158,5 +1187,4 @@
 
 #ifdef VMS
-
       if (!child_execute_job (argv, child)) {
         /* Fork failed!  */
@@ -1582,5 +1610,5 @@
 
         /* If we don't already have a job started, use our "free" token.  */
-        if (!children)
+        if (!jobserver_tokens)
           break;
 
@@ -1617,17 +1645,23 @@
         reap_children (0, 0);
 
-        /* If our "free" token has become available, use it.  */
+        /* Kick off any jobs we have waiting for an opportunity that
+           can run now (ie waiting for load). */
+        start_waiting_jobs ();
+
+        /* If our "free" slot has become available, use it; we don't need an
+           actual token.  */
+        if (!jobserver_tokens)
+          break;
+
+        /* There must be at least one child already, or we have no business
+           waiting for a token. */
         if (!children)
-          break;
+          fatal (NILF, "INTERNAL: no children as we go to sleep on read\n");
 
         /* Set interruptible system calls, and read() for a job token.  */
-	set_child_handler_action_flags (0);
+	set_child_handler_action_flags (1, waiting_jobs != NULL);
 	got_token = read (job_rfd, &token, 1);
 	saved_errno = errno;
-#ifdef __EMX__
-        /* The child handler must be turned off here.  */
-        signal (SIGCHLD, SIG_DFL);
-#endif
-	set_child_handler_action_flags (SA_RESTART);
+	set_child_handler_action_flags (0, waiting_jobs != NULL);
 
         /* If we got one, we're done here.  */
@@ -1648,4 +1682,6 @@
       }
 #endif
+
+  ++jobserver_tokens;
 
   /* The job is now primed.  Start it running.
@@ -1728,5 +1764,5 @@
 load_too_high (void)
 {
-#if defined(__MSDOS__) || defined(VMS) || defined(_AMIGA)
+#if defined(__MSDOS__) || defined(VMS) || defined(_AMIGA) || defined(__riscos__)
   return 1;
 #else
@@ -1812,564 +1848,7 @@
 
 #ifndef WINDOWS32
-#ifdef VMS
-#include <descrip.h>
-#include <clidef.h>
-
-/* This is called as an AST when a child process dies (it won't get
-   interrupted by anything except a higher level AST).
-*/
-int vmsHandleChildTerm(struct child *child)
-{
-    int status;
-    register struct child *lastc, *c;
-    int child_failed;
-
-    vms_jobsefnmask &= ~(1 << (child->efn - 32));
-
-    lib$free_ef(&child->efn);
-
-    (void) sigblock (fatal_signal_mask);
-
-    child_failed = !(child->cstatus & 1 || ((child->cstatus & 7) == 0));
-
-    /* Search for a child matching the deceased one.  */
-    lastc = 0;
-#if defined(RECURSIVEJOBS) /* I've had problems with recursive stuff and process handling */
-    for (c = children; c != 0 && c != child; lastc = c, c = c->next);
-#else
-    c = child;
-#endif
-
-    if (child_failed && !c->noerror && !ignore_errors_flag)
-      {
-	/* The commands failed.  Write an error message,
-	   delete non-precious targets, and abort.  */
-	child_error (c->file->name, c->cstatus, 0, 0, 0);
-	c->file->update_status = 1;
-	delete_child_targets (c);
-      }
-    else
-      {
-	if (child_failed)
-	  {
-	    /* The commands failed, but we don't care.  */
-	    child_error (c->file->name, c->cstatus, 0, 0, 1);
-	    child_failed = 0;
-	  }
-
-#if defined(RECURSIVEJOBS) /* I've had problems with recursive stuff and process handling */
-	/* If there are more commands to run, try to start them.  */
-	start_job (c);
-
-	switch (c->file->command_state)
-	  {
-	  case cs_running:
-	    /* Successfully started.  */
-	    break;
-
-	  case cs_finished:
-	    if (c->file->update_status != 0) {
-		/* We failed to start the commands.  */
-		delete_child_targets (c);
-	    }
-	    break;
-
-	  default:
-	    error (NILF, _("internal error: `%s' command_state"),
-                   c->file->name);
-	    abort ();
-	    break;
-	  }
-#endif /* RECURSIVEJOBS */
-      }
-
-    /* Set the state flag to say the commands have finished.  */
-    c->file->command_state = cs_finished;
-    notice_finished_file (c->file);
-
-#if defined(RECURSIVEJOBS) /* I've had problems with recursive stuff and process handling */
-    /* Remove the child from the chain and free it.  */
-    if (lastc == 0)
-      children = c->next;
-    else
-      lastc->next = c->next;
-    free_child (c);
-#endif /* RECURSIVEJOBS */
-
-    /* There is now another slot open.  */
-    if (job_slots_used > 0)
-      --job_slots_used;
-
-    /* If the job failed, and the -k flag was not given, die.  */
-    if (child_failed && !keep_going_flag)
-      die (EXIT_FAILURE);
-
-    (void) sigsetmask (sigblock (0) & ~(fatal_signal_mask));
-
-    return 1;
-}
-
-/* VMS:
-   Spawn a process executing the command in ARGV and return its pid. */
-
-#define MAXCMDLEN 200
-
-/* local helpers to make ctrl+c and ctrl+y working, see below */
-#include <iodef.h>
-#include <libclidef.h>
-#include <ssdef.h>
-
-static int ctrlMask= LIB$M_CLI_CTRLY;
-static int oldCtrlMask;
-static int setupYAstTried= 0;
-static int pidToAbort= 0;
-static int chan= 0;
-
-static void reEnableAst(void) {
-	lib$enable_ctrl (&oldCtrlMask,0);
-}
-
-static astHandler (void) {
-	if (pidToAbort) {
-		sys$forcex (&pidToAbort, 0, SS$_ABORT);
-		pidToAbort= 0;
-	}
-	kill (getpid(),SIGQUIT);
-}
-
-static void tryToSetupYAst(void) {
-	$DESCRIPTOR(inputDsc,"SYS$COMMAND");
-	int	status;
-	struct {
-		short int	status, count;
-		int	dvi;
-	} iosb;
-
-	setupYAstTried++;
-
-	if (!chan) {
-		status= sys$assign(&inputDsc,&chan,0,0);
-		if (!(status&SS$_NORMAL)) {
-			lib$signal(status);
-			return;
-		}
-	}
-	status= sys$qiow (0, chan, IO$_SETMODE|IO$M_CTRLYAST,&iosb,0,0,
-		astHandler,0,0,0,0,0);
-	if (status==SS$_ILLIOFUNC) {
-		sys$dassgn(chan);
-#ifdef	CTRLY_ENABLED_ANYWAY
-		fprintf (stderr,
-                         _("-warning, CTRL-Y will leave sub-process(es) around.\n"));
-#else
-		return;
-#endif
-	}
-	if (status==SS$_NORMAL)
-		status= iosb.status;
-	if (!(status&SS$_NORMAL)) {
-		lib$signal(status);
-		return;
-	}
-
-	/* called from AST handler ? */
-	if (setupYAstTried>1)
-		return;
-	if (atexit(reEnableAst))
-		fprintf (stderr,
-                         _("-warning, you may have to re-enable CTRL-Y handling from DCL.\n"));
-	status= lib$disable_ctrl (&ctrlMask, &oldCtrlMask);
-	if (!(status&SS$_NORMAL)) {
-		lib$signal(status);
-		return;
-	}
-}
-int
-child_execute_job (char *argv, struct child *child)
-{
-  int i;
-  static struct dsc$descriptor_s cmddsc;
-  static struct dsc$descriptor_s pnamedsc;
-  static struct dsc$descriptor_s ifiledsc;
-  static struct dsc$descriptor_s ofiledsc;
-  static struct dsc$descriptor_s efiledsc;
-  int have_redirection = 0;
-  int have_newline = 0;
-
-  int spflags = CLI$M_NOWAIT;
-  int status;
-  char *cmd = alloca (strlen (argv) + 512), *p, *q;
-  char ifile[256], ofile[256], efile[256];
-  char *comname = 0;
-  char procname[100];
-
-  /* Parse IO redirection.  */
-
-  ifile[0] = 0;
-  ofile[0] = 0;
-  efile[0] = 0;
-
-  DB (DB_JOBS, ("child_execute_job (%s)\n", argv));
-
-  while (isspace ((unsigned char)*argv))
-    argv++;
-
-  if (*argv == 0)
-    return 0;
-
-  sprintf (procname, "GMAKE_%05x", getpid () & 0xfffff);
-  pnamedsc.dsc$w_length = strlen(procname);
-  pnamedsc.dsc$a_pointer = procname;
-  pnamedsc.dsc$b_dtype = DSC$K_DTYPE_T;
-  pnamedsc.dsc$b_class = DSC$K_CLASS_S;
-
-  /* Handle comments and redirection. */
-  for (p = argv, q = cmd; *p; p++, q++)
-    {
-      switch (*p)
-	{
-	  case '#':
-	    *p-- = 0;
-	    *q-- = 0;
-	    break;
-	  case '\\':
-	    p++;
-	    if (*p == '\n')
-	      p++;
-	    if (isspace ((unsigned char)*p))
-	      {
-		do { p++; } while (isspace ((unsigned char)*p));
-		p--;
-	      }
-	    *q = *p;
-	    break;
-	  case '<':
-	    p = vms_redirect (&ifiledsc, ifile, p);
-	    *q = ' ';
-	    have_redirection = 1;
-	    break;
-	  case '>':
-	    have_redirection = 1;
-	    if (*(p-1) == '2')
-	      {
-		q--;
-		if (strncmp (p, ">&1", 3) == 0)
-		  {
-		    p += 3;
-		    strcpy (efile, "sys$output");
-		    efiledsc.dsc$w_length = strlen(efile);
-		    efiledsc.dsc$a_pointer = efile;
-		    efiledsc.dsc$b_dtype = DSC$K_DTYPE_T;
-		    efiledsc.dsc$b_class = DSC$K_CLASS_S;
-		  }
-		else
-		  {
-		    p = vms_redirect (&efiledsc, efile, p);
-		  }
-	      }
-	    else
-	      {
-		p = vms_redirect (&ofiledsc, ofile, p);
-	      }
-	    *q = ' ';
-	    break;
-	  case '\n':
-	    have_newline = 1;
-	  default:
-	    *q = *p;
-	    break;
-	}
-    }
-  *q = *p;
-
-  if (strncmp (cmd, "builtin_", 8) == 0)
-    {
-      child->pid = 270163;
-      child->efn = 0;
-      child->cstatus = 1;
-
-      DB (DB_JOBS, (_("BUILTIN [%s][%s]\n"), cmd, cmd+8));
-
-      p = cmd + 8;
-
-      if ((*(p) == 'c')
-	  && (*(p+1) == 'd')
-	  && ((*(p+2) == ' ') || (*(p+2) == '\t')))
-	{
-	  p += 3;
-	  while ((*p == ' ') || (*p == '\t'))
-	    p++;
-	  DB (DB_JOBS, (_("BUILTIN CD %s\n"), p));
-	  if (chdir (p))
-	    return 0;
-	  else
-	    return 1;
-	}
-      else if ((*(p) == 'r')
-	  && (*(p+1) == 'm')
-	  && ((*(p+2) == ' ') || (*(p+2) == '\t')))
-	{
-	  int in_arg;
-
-	  /* rm  */
-	  p += 3;
-	  while ((*p == ' ') || (*p == '\t'))
-	    p++;
-	  in_arg = 1;
-
-	  DB (DB_JOBS, (_("BUILTIN RM %s\n"), p));
-	  while (*p)
-	    {
-	      switch (*p)
-		{
-		  case ' ':
-		  case '\t':
-		    if (in_arg)
-		      {
-			*p++ = ';';
-			in_arg = 0;
-		      }
-		    break;
-		  default:
-		    break;
-		}
-	      p++;
-	    }
-	}
-      else
-	{
-	  printf(_("Unknown builtin command '%s'\n"), cmd);
-	  fflush(stdout);
-	  return 0;
-	}
-    }
-
-  /* Create a *.com file if either the command is too long for
-     lib$spawn, or the command contains a newline, or if redirection
-     is desired. Forcing commands with newlines into DCLs allows to
-     store search lists on user mode logicals.  */
-
-  if (strlen (cmd) > MAXCMDLEN
-      || (have_redirection != 0)
-      || (have_newline != 0))
-    {
-      FILE *outfile;
-      char c;
-      char *sep;
-      int alevel = 0;	/* apostrophe level */
-
-      if (strlen (cmd) == 0)
-	{
-	  printf (_("Error, empty command\n"));
-	  fflush (stdout);
-	  return 0;
-	}
-
-      outfile = open_tmpfile (&comname, "sys$scratch:CMDXXXXXX.COM");
-      if (outfile == 0)
-	pfatal_with_name (_("fopen (temporary file)"));
-
-      if (ifile[0])
-	{
-	  fprintf (outfile, "$ assign/user %s sys$input\n", ifile);
-          DB (DB_JOBS, (_("Redirected input from %s\n"), ifile));
-	  ifiledsc.dsc$w_length = 0;
-	}
-
-      if (efile[0])
-	{
-	  fprintf (outfile, "$ define sys$error %s\n", efile);
-          DB (DB_JOBS, (_("Redirected error to %s\n"), efile));
-	  efiledsc.dsc$w_length = 0;
-	}
-
-      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;
-	}
-
-      p = sep = q = cmd;
-      for (c = '\n'; c; c = *q++)
-	{
-	  switch (c)
-	    {
-            case '\n':
-              /* At a newline, skip any whitespace around a leading $
-                 from the command and issue exactly one $ into the DCL. */
-              while (isspace ((unsigned char)*p))
-                p++;
-              if (*p == '$')
-                p++;
-              while (isspace ((unsigned char)*p))
-                p++;
-              fwrite (p, 1, q - p, outfile);
-              fputc ('$', outfile);
-              fputc (' ', outfile);
-              /* Reset variables. */
-              p = sep = q;
-              break;
-
-	      /* Nice places for line breaks are after strings, after
-		 comma or space and before slash. */
-            case '"':
-              q = vms_handle_apos (q);
-              sep = q;
-              break;
-            case ',':
-            case ' ':
-              sep = q;
-              break;
-            case '/':
-            case '\0':
-              sep = q - 1;
-              break;
-            default:
-              break;
-	    }
-	  if (sep - p > 78)
-	    {
-	      /* Enough stuff for a line. */
-	      fwrite (p, 1, sep - p, outfile);
-	      p = sep;
-	      if (*sep)
-		{
-		  /* The command continues.  */
-		  fputc ('-', outfile);
-		}
-	      fputc ('\n', outfile);
-	    }
-  	}
-
-      fwrite (p, 1, q - p, outfile);
-      fputc ('\n', outfile);
-
-      fclose (outfile);
-
-      sprintf (cmd, "$ @%s", comname);
-
-      DB (DB_JOBS, (_("Executing %s instead\n"), cmd));
-    }
-
-  cmddsc.dsc$w_length = strlen(cmd);
-  cmddsc.dsc$a_pointer = cmd;
-  cmddsc.dsc$b_dtype = DSC$K_DTYPE_T;
-  cmddsc.dsc$b_class = DSC$K_CLASS_S;
-
-  child->efn = 0;
-  while (child->efn < 32 || child->efn > 63)
-    {
-      status = lib$get_ef ((unsigned long *)&child->efn);
-      if (!(status & 1))
-	return 0;
-    }
-
-  sys$clref (child->efn);
-
-  vms_jobsefnmask |= (1 << (child->efn - 32));
-
-/*
-             LIB$SPAWN  [command-string]
-			[,input-file]
-			[,output-file]
-			[,flags]
-			[,process-name]
-			[,process-id] [,completion-status-address] [,byte-integer-event-flag-num]
-			[,AST-address] [,varying-AST-argument]
-			[,prompt-string] [,cli] [,table]
-*/
-
-#ifndef DONTWAITFORCHILD
-/*
- *	Code to make ctrl+c and ctrl+y working.
- *	The problem starts with the synchronous case where after lib$spawn is
- *	called any input will go to the child. But with input re-directed,
- *	both control characters won't make it to any of the programs, neither
- *	the spawning nor to the spawned one. Hence the caller needs to spawn
- *	with CLI$M_NOWAIT to NOT give up the input focus. A sys$waitfr
- *	has to follow to simulate the wanted synchronous behaviour.
- *	The next problem is ctrl+y which isn't caught by the crtl and
- *	therefore isn't converted to SIGQUIT (for a signal handler which is
- *	already established). The only way to catch ctrl+y, is an AST
- *	assigned to the input channel. But ctrl+y handling of DCL needs to be
- *	disabled, otherwise it will handle it. Not to mention the previous
- *	ctrl+y handling of DCL needs to be re-established before make exits.
- *	One more: At the time of LIB$SPAWN signals are blocked. SIGQUIT will
- *	make it to the signal handler after the child "normally" terminates.
- *	This isn't enough. It seems reasonable for simple command lines like
- *	a 'cc foobar.c' spawned in a subprocess but it is unacceptable for
- *	spawning make. Therefore we need to abort the process in the AST.
- *
- *	Prior to the spawn it is checked if an AST is already set up for
- *	ctrl+y, if not one is set up for a channel to SYS$COMMAND. In general
- *	this will work except if make is run in a batch environment, but there
- *	nobody can press ctrl+y. During the setup the DCL handling of ctrl+y
- *	is disabled and an exit handler is established to re-enable it.
- *	If the user interrupts with ctrl+y, the assigned AST will fire, force
- *	an abort to the subprocess and signal SIGQUIT, which will be caught by
- *	the already established handler and will bring us back to common code.
- *	After the spawn (now /nowait) a sys$waitfr simulates the /wait and
- *	enables the ctrl+y be delivered to this code. And the ctrl+c too,
- *	which the crtl converts to SIGINT and which is caught by the common
- *	signal handler. Because signals were blocked before entering this code
- *	sys$waitfr will always complete and the SIGQUIT will be processed after
- *	it (after termination of the current block, somewhere in common code).
- *	And SIGINT too will be delayed. That is ctrl+c can only abort when the
- *	current command completes. Anyway it's better than nothing :-)
- */
-
-  if (!setupYAstTried)
-    tryToSetupYAst();
-  status = lib$spawn (&cmddsc,					/* cmd-string  */
-		      (ifiledsc.dsc$w_length == 0)?0:&ifiledsc, /* input-file  */
-		      (ofiledsc.dsc$w_length == 0)?0:&ofiledsc, /* output-file */
-		      &spflags,					/* flags  */
-		      &pnamedsc,				/* proc name  */
-		      &child->pid, &child->cstatus, &child->efn,
-		      0, 0,
-		      0, 0, 0);
-  if (status & 1)
-    {
-      pidToAbort= child->pid;
-      status= sys$waitfr (child->efn);
-      pidToAbort= 0;
-      vmsHandleChildTerm(child);
-    }
-#else
-  status = lib$spawn (&cmddsc,
-		      (ifiledsc.dsc$w_length == 0)?0:&ifiledsc,
-		      (ofiledsc.dsc$w_length == 0)?0:&ofiledsc,
-		      &spflags,
-		      &pnamedsc,
-		      &child->pid, &child->cstatus, &child->efn,
-		      vmsHandleChildTerm, child,
-		      0, 0, 0);
-#endif
-
-  if (!(status & 1))
-    {
-      printf (_("Error spawning, %d\n") ,status);
-      fflush (stdout);
-      switch (status)
-        {
-        case 0x1c:
-          errno = EPROCLIM;
-          break;
-        default:
-          errno = EFAIL;
-        }
-    }
-
-  if (comname && !ISDB (DB_JOBS))
-    unlink (comname);
-
-  return (status & 1);
-}
-
-#else /* !VMS */
 
 /* EMX: Start a child process. This function returns the new pid.  */
-# if defined __MSDOS__ ||  defined __EMX__
+# if defined __MSDOS__ || defined __EMX__
 int
 child_execute_job (int stdin_fd, int stdout_fd, char **argv, char **envp)
@@ -2409,9 +1888,20 @@
   pid = exec_command (argv, envp);
 
-  /* Restore stdout/stdin of the parent process.  */
-  if (stdin_fd != 0 && dup2 (save_stdin, 0) != 0)
-    fatal (NILF, _("restoring of stdin failed\n"));
-  if (stdout_fd != 1 && dup2 (save_stdout, 1) != 1)
-    fatal (NILF, _("restoring of stdout failed\n"));
+  /* Restore stdout/stdin of the parent and close temporary FDs.  */
+  if (stdin_fd != 0)
+    {
+      if (dup2 (save_stdin, 0) != 0)
+        fatal (NILF, _("Could not restore stdin\n"));
+      else
+        close (save_stdin);
+    }
+
+  if (stdout_fd != 1)
+    {
+      if (dup2 (save_stdout, 1) != 1)
+        fatal (NILF, _("Could not restore stdout\n"));
+      else
+        close (save_stdout);
+    }
 
   return pid;
@@ -2440,5 +1930,4 @@
 }
 #endif /* !AMIGA && !__MSDOS__ */
-#endif /* !VMS */
 #endif /* !WINDOWS32 */
 
@@ -2452,5 +1941,5 @@
 int
 # else
- void
+void
 # endif
 exec_command (char **argv, char **envp)
@@ -2492,5 +1981,6 @@
 
   /* wait and reap last child */
-  while (hWaitPID = process_wait_for_any())
+  hWaitPID = process_wait_for_any();
+  while (hWaitPID)
     {
       /* was an error found on this process? */
@@ -2560,4 +2050,5 @@
 	char **new_argv;
 	int argc;
+        int i=1;
 
 # ifdef __EMX__
@@ -2578,10 +2069,25 @@
 	  ++argc;
 
+# ifdef __EMX__
+        if (!unixy_shell)
+          ++argc;
+# endif
+
 	new_argv = (char **) alloca ((1 + argc + 1) * sizeof (char *));
 	new_argv[0] = shell;
-	new_argv[1] = argv[0];
+
+# ifdef __EMX__
+        if (!unixy_shell)
+          {
+            new_argv[1] = "/c";
+            ++i;
+            --argc;
+          }
+# endif
+
+        new_argv[i] = argv[0];
 	while (argc > 0)
 	  {
-	    new_argv[1 + argc] = argv[argc];
+	    new_argv[i + argc] = argv[argc];
 	    --argc;
 	  }
@@ -2751,4 +2257,7 @@
   char*  sh_chars;
   char** sh_cmds;
+#elif defined(__riscos__)
+  static char sh_chars[] = "";
+  static char *sh_cmds[] = { 0 };
 #else  /* must be UNIX-ish */
   static char sh_chars[] = "#;\"*?[]&|<>(){}$`^~!";
@@ -3021,6 +2530,14 @@
 		register int j;
 		for (j = 0; sh_cmds[j] != 0; ++j)
-		  if (streq (sh_cmds[j], new_argv[0]))
-		    goto slow;
+                  {
+                    if (streq (sh_cmds[j], new_argv[0]))
+                      goto slow;
+# ifdef __EMX__
+                    /* Non-Unix shells are case insensitive.  */
+                    if (!unixy_shell
+                        && strcasecmp (sh_cmds[j], new_argv[0]) == 0)
+                      goto slow;
+# endif
+                  }
 	      }
 
@@ -3060,6 +2577,6 @@
     /* Line was empty.  */
     return 0;
-  else
-    return new_argv;
+
+  return new_argv;
 
  slow:;
@@ -3210,24 +2727,8 @@
       int id = GetCurrentProcessId();
       PATH_VAR(fbuf);
-      char* fname = NULL;
 
       /* create a file name */
       sprintf(fbuf, "make%d", id);
-      fname = tempnam(".", fbuf);
-
-	  /* create batch file name */
-      *batch_filename_ptr = xmalloc(strlen(fname) + 5);
-      strcpy(*batch_filename_ptr, fname);
-
-      /* make sure path name is in DOS backslash format */
-      if (!unixy_shell) {
-        fname = *batch_filename_ptr;
-        for (i = 0; fname[i] != '\0'; ++i)
-          if (fname[i] == '/')
-            fname[i] = '\\';
-        strcat(*batch_filename_ptr, ".bat");
-      } else {
-        strcat(*batch_filename_ptr, ".sh");
-      }
+      *batch_filename_ptr = create_batch_filename (fbuf, unixy_shell);
 
       DB (DB_JOBS, (_("Creating temporary batch file %s\n"),
@@ -3258,101 +2759,72 @@
                                                   (char *) 0, (char *) 0,
                                                   (char **) 0);
-# ifdef __EMX__
+#ifdef __EMX__
     else if (!unixy_shell)
       {
-	/* new_line is local, must not be freed therefore */
-	char *p, *q;
-	int quote;
-	size_t index;
-	size_t len;
-
-	/* handle quotes
-	   We have to remove all double quotes and to split the line
-	   into distinct arguments because of the strange handling
-	   of builtin commands by cmd: 'echo "bla"' prints "bla"
-	   (with quotes) while 'c:\bin\echo.exe "bla"' prints bla
-	   (without quotes). Some programs like autoconf rely
-	   on the second behaviour. */
-
-	len = strlen (new_line) + 1;
-
-	/* More than 1 arg per character is impossible.  */
-	new_argv = (char **) xmalloc (len * sizeof (char *));
-
-	/* All the args can fit in a buffer as big as new_line is.   */
-	new_argv[0] = (char *) xmalloc (len);
-
-	index = 0;
-	quote = 0;
-	q = new_line;
-	p = new_argv[index];
-	while(*q != '\0')
-	  {
-	    /* searching for closing quote */
-	    if (quote)
-	      {
-		if (*q == quote)
-		  {
-		    /* remove the quote */
-                    q++;
-		    quote = 0;
-		  }
-		else /* normal character: copy it */
-		  *p++ = *q++;
-	      }
-
-	    /* searching for opening quote */
-	    else if (*q == '\"'
-#  ifndef NO_CMD_DEFAULT
-		     || *q == '\''
-#  endif
-		     )
-	      {
-		/* remove opening quote */
-		quote = *q;
-                q++;
-	      }
-
-	    /* spaces outside of a quoted string: remove them
-	       and start a new argument */
-	    else if (*q == ' ' || *q == '\t')
-	      {
-		*p++ = '\0'; /* trailing '\0' for last argument */
-
-		/* remove all successive spaces */
-		do
-		  {
-		    q++;
-		  }
-		while(*q == ' ' || *q == '\t');
-
-		/* start new argument */
-		index++;
-		new_argv[index] = p;
-	      }
-
-	    /* normal character (no space) outside a quoted string*/
-	    else
-	      *p++ = *q++;
-	  } /* end while() */
-
-	*p = '\0'; /* trailing '\0' for the last argument */
-	new_argv[index + 1] = NULL;
-
-#  ifndef NO_CMD_DEFAULT
-	/* special case: echo x="y"
-	   (e.g. autoconf uses this to determine whether make works)
-	   this is pure idioty but cmd works this way:
-	   if 'echo' and 'x="y"' are two different arguments cmd
-	   will print '"x="y""' but if they are only one argument
-	   cmd will print 'bla="blurb"' as it should be
-	   note: if we do not allow cmd to be the default shell
-	   we do not need this kind of voodoo */
-	if (index == 3 && strcasecmp(new_argv[2], "echo") == 0)
-	  {
-	    new_argv[2][4] = ' ';
-	    new_argv[3] = NULL;
-	  }
-#  endif
+	/* new_line is local, must not be freed therefore
+           We use line here instead of new_line because we run the shell
+           manually.  */
+        size_t line_len = strlen (line);
+        char *p = new_line;
+        char *q = new_line;
+        memcpy (new_line, line, line_len + 1);
+        /* replace all backslash-newline combination and also following tabs */
+        while (*q != '\0')
+          {
+            if (q[0] == '\\' && q[1] == '\n')
+              {
+                q += 2; /* remove '\\' and '\n' */
+                if (q[0] == '\t')
+                  q++; /* remove 1st tab in the next line */
+              }
+            else
+              *p++ = *q++;
+          }
+        *p = '\0';
+
+# ifndef NO_CMD_DEFAULT
+        if (strnicmp (new_line, "echo", 4) == 0
+            && (new_line[4] == ' ' || new_line[4] == '\t'))
+          {
+            /* the builtin echo command: handle it separately */
+            size_t echo_len = line_len - 5;
+            char *echo_line = new_line + 5;
+
+            /* special case: echo 'x="y"'
+               cmd works this way: a string is printed as is, i.e., no quotes
+               are removed. But autoconf uses a command like echo 'x="y"' to
+               determine whether make works. autoconf expects the output x="y"
+               so we will do exactly that.
+               Note: if we do not allow cmd to be the default shell
+               we do not need this kind of voodoo */
+            if (echo_line[0] == '\''
+                && echo_line[echo_len - 1] == '\''
+                && strncmp (echo_line + 1, "ac_maketemp=",
+                            strlen ("ac_maketemp=")) == 0)
+              {
+                /* remove the enclosing quotes */
+                memmove (echo_line, echo_line + 1, echo_len - 2);
+                echo_line[echo_len - 2] = '\0';
+              }
+          }
+# endif
+
+        {
+          /* Let the shell decide what to do. Put the command line into the
+             2nd command line argument and hope for the best ;-)  */
+          size_t sh_len = strlen (shell);
+
+          /* exactly 3 arguments + NULL */
+          new_argv = (char **) xmalloc (4 * sizeof (char *));
+          /* Exactly strlen(shell) + strlen("/c") + strlen(line) + 3 times
+             the trailing '\0' */
+          new_argv[0] = (char *) malloc (sh_len + line_len + 5);
+          memcpy (new_argv[0], shell, sh_len + 1);
+          new_argv[1] = new_argv[0] + sh_len + 1;
+          memcpy (new_argv[1], "/c", 3);
+          new_argv[2] = new_argv[1] + 3;
+          memcpy (new_argv[2], new_line, line_len + 1);
+          new_argv[3] = NULL;
+        }
       }
 #elif defined(__MSDOS__)
@@ -3535,2 +3007,8 @@
 }
 #endif /* !HAPE_DUP2 && !_AMIGA */
+
+/* On VMS systems, include special VMS functions.  */
+
+#ifdef VMS
+#include "vmsjobs.c"
+#endif
Index: branches/GNU/src/gmake/job.h
===================================================================
--- branches/GNU/src/gmake/job.h	(revision 157)
+++ branches/GNU/src/gmake/job.h	(revision 280)
@@ -102,3 +102,5 @@
 #endif
 
+extern unsigned int jobserver_tokens;
+
 #endif /* SEEN_JOB_H */
Index: branches/GNU/src/gmake/main.c
===================================================================
--- branches/GNU/src/gmake/main.c	(revision 157)
+++ branches/GNU/src/gmake/main.c	(revision 280)
@@ -1,5 +1,5 @@
 /* Argument parsing and main program of GNU Make.
 Copyright (C) 1988, 1989, 1990, 1991, 1994, 1995, 1996, 1997, 1998, 1999,
-2002, 2003 Free Software Foundation, Inc.
+2002, 2003, 2005 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
@@ -36,4 +36,5 @@
 #ifdef WINDOWS32
 #include <windows.h>
+#include <io.h>
 #include "pathstuff.h"
 #endif
@@ -44,4 +45,12 @@
 #ifdef HAVE_FCNTL_H
 # include <fcntl.h>
+#endif
+
+#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>
 #endif
 
@@ -186,4 +195,8 @@
 int default_keep_going_flag = 0;
 
+/* Nonzero means check symlink mtimes.  */
+
+int check_symlink_flag = 0;
+
 /* Nonzero means print directory before starting and when done (-w).  */
 
@@ -207,4 +220,5 @@
 unsigned int job_slots = 1;
 unsigned int default_job_slots = 1;
+static unsigned int master_job_slots = 0;
 
 /* Value of job_slots that means no limit.  */
@@ -260,4 +274,13 @@
 
 int always_make_flag = 0;
+
+/* If nonzero, we're in the "try to rebuild makefiles" phase.  */
+
+int rebuilding_makefiles = 0;
+
+/* Remember the original value of the SHELL variable, from the environment.  */
+
+struct variable shell_var;
+
 
 
@@ -301,4 +324,6 @@
                               Don't start multiple jobs unless load is below N.\n"),
     N_("\
+  -L, --check-symlink-times   Use the latest mtime between symlinks and target.\n"),
+    N_("\
   -n, --just-print, --dry-run, --recon\n\
                               Don't actually run any commands; just print them.\n"),
@@ -348,36 +373,38 @@
 #endif
     { 'e', flag, (char *) &env_overrides, 1, 1, 0, 0, 0,
-        "environment-overrides", },
+      "environment-overrides", },
     { 'f', string, (char *) &makefiles, 0, 0, 0, 0, 0, "file" },
     { 'h', flag, (char *) &print_usage_flag, 0, 0, 0, 0, 0, "help" },
     { 'i', flag, (char *) &ignore_errors_flag, 1, 1, 0, 0, 0,
-        "ignore-errors" },
+      "ignore-errors" },
     { 'I', string, (char *) &include_directories, 1, 1, 0, 0, 0,
-        "include-dir" },
+      "include-dir" },
     { 'j', positive_int, (char *) &job_slots, 1, 1, 0, (char *) &inf_jobs,
-        (char *) &default_job_slots, "jobs" },
+      (char *) &default_job_slots, "jobs" },
     { CHAR_MAX+2, string, (char *) &jobserver_fds, 1, 1, 0, 0, 0,
-        "jobserver-fds" },
+      "jobserver-fds" },
     { 'k', flag, (char *) &keep_going_flag, 1, 1, 0, 0,
-        (char *) &default_keep_going_flag, "keep-going" },
+      (char *) &default_keep_going_flag, "keep-going" },
 #ifndef NO_FLOAT
     { 'l', floating, (char *) &max_load_average, 1, 1, 0,
-	(char *) &default_load_average, (char *) &default_load_average,
-	"load-average" },
+      (char *) &default_load_average, (char *) &default_load_average,
+      "load-average" },
 #else
     { 'l', positive_int, (char *) &max_load_average, 1, 1, 0,
-	(char *) &default_load_average, (char *) &default_load_average,
-	"load-average" },
-#endif
+      (char *) &default_load_average, (char *) &default_load_average,
+      "load-average" },
+#endif
+    { 'L', flag, (char *) &check_symlink_flag, 1, 1, 0, 0, 0,
+      "check-symlink-times" },
     { 'm', ignore, 0, 0, 0, 0, 0, 0, 0 },
     { 'n', flag, (char *) &just_print_flag, 1, 1, 1, 0, 0, "just-print" },
     { 'o', string, (char *) &old_files, 0, 0, 0, 0, 0, "old-file" },
     { 'p', flag, (char *) &print_data_base_flag, 1, 1, 0, 0, 0,
-        "print-data-base" },
+      "print-data-base" },
     { 'q', flag, (char *) &question_flag, 1, 1, 1, 0, 0, "question" },
     { 'r', flag, (char *) &no_builtin_rules_flag, 1, 1, 0, 0, 0,
       "no-builtin-rules" },
     { 'R', flag, (char *) &no_builtin_variables_flag, 1, 1, 0, 0, 0,
-	"no-builtin-variables" },
+      "no-builtin-variables" },
     { 's', flag, (char *) &silent_flag, 1, 1, 0, 0, 0, "silent" },
     { 'S', flag_off, (char *) &keep_going_flag, 1, 1, 0, 0,
@@ -386,10 +413,10 @@
     { 'v', flag, (char *) &print_version_flag, 1, 1, 0, 0, 0, "version" },
     { 'w', flag, (char *) &print_directory_flag, 1, 1, 0, 0, 0,
-        "print-directory" },
+      "print-directory" },
     { CHAR_MAX+3, flag, (char *) &inhibit_print_directory_flag, 1, 1, 0, 0, 0,
-	"no-print-directory" },
+      "no-print-directory" },
     { 'W', string, (char *) &new_files, 0, 0, 0, 0, 0, "what-if" },
     { CHAR_MAX+4, flag, (char *) &warn_undefined_variables_flag, 1, 1, 0, 0, 0,
-	"warn-undefined-variables" },
+      "warn-undefined-variables" },
     { 0 }
   };
@@ -446,4 +473,8 @@
 
 struct file *default_goal_file;
+
+/* Pointer to the value of the .DEFAULT_GOAL special
+   variable.  */
+char ** default_goal_name;
 
 /* Pointer to structure for the file .DEFAULT
@@ -549,4 +580,5 @@
 /* Toggle -d on receipt of SIGUSR1.  */
 
+#ifdef SIGUSR1
 static RETSIGTYPE
 debug_signal_handler (int sig UNUSED)
@@ -554,4 +586,5 @@
   db_level = db_level ? DB_NONE : DB_BASIC;
 }
+#endif
 
 static void
@@ -696,5 +729,6 @@
 {
   int sh_found = 0;
-  char* search_token;
+  char *search_token;
+  char *tokend;
   PATH_VAR(sh_path);
   extern char *default_shell;
@@ -705,6 +739,23 @@
     search_token = token;
 
-  if (!no_default_sh_exe &&
-      (token == NULL || !strcmp(search_token, default_shell))) {
+
+  /* If the user explicitly requests the DOS cmd shell, obey that request.
+     However, make sure that's what they really want by requiring the value
+     of SHELL either equal, or have a final path element of, "cmd" or
+     "cmd.exe" case-insensitive.  */
+  tokend = search_token + strlen (search_token) - 3;
+  if (((tokend == search_token
+        || (tokend > search_token
+            && (tokend[-1] == '/' || tokend[-1] == '\\')))
+       && !strcmpi (tokend, "cmd"))
+      || ((tokend - 4 == search_token
+           || (tokend - 4 > search_token
+               && (tokend[-5] == '/' || tokend[-5] == '\\')))
+          && !strcmpi (tokend - 4, "cmd.exe"))) {
+    batch_mode_shell = 1;
+    unixy_shell = 0;
+    sh_found = 0;
+  } else if (!no_default_sh_exe &&
+             (token == NULL || !strcmp (search_token, default_shell))) {
     /* no new information, path already set or known */
     sh_found = 1;
@@ -718,9 +769,7 @@
   } else {
     char *p;
-    struct variable *v = lookup_variable ("Path", 4);
-
-    /*
-     * Search Path for shell
-     */
+    struct variable *v = lookup_variable ("PATH", 4);
+
+    /* Search Path for shell */
     if (v && v->value) {
       char *ep;
@@ -841,4 +890,5 @@
   struct file *f;
   int i;
+  int makefile_status = MAKE_SUCCESS;
   char **p;
   struct dep *read_makefiles;
@@ -853,4 +903,18 @@
   unixy_shell = 0;
   no_default_sh_exe = 1;
+#endif
+
+#ifdef SET_STACK_SIZE
+ /* Get rid of any avoidable limit on stack size.  */
+  {
+    struct rlimit rlim;
+
+    /* Set the stack limit huge so that alloca does not fail.  */
+    if (getrlimit (RLIMIT_STACK, &rlim) == 0)
+      {
+        rlim.rlim_cur = rlim.rlim_max;
+        setrlimit (RLIMIT_STACK, &rlim);
+      }
+  }
 #endif
 
@@ -978,4 +1042,23 @@
 	program = argv[0] + 1;
 #endif
+#ifdef WINDOWS32
+      if (program == 0)
+        {
+          /* Extract program from full path */
+          int argv0_len;
+          char *p = strrchr (argv[0], '\\');
+          if (!p)
+            p = argv[0];
+          argv0_len = strlen(p);
+          if (argv0_len > 4
+              && streq (&p[argv0_len - 4], ".exe"))
+            {
+              /* Remove .exe extension */
+              p[argv0_len - 4] = '\0';
+              /* Increment past the initial '\' */
+              program = p + 1;
+            }
+        }
+#endif
       if (program == 0)
 	program = argv[0];
@@ -998,5 +1081,5 @@
     {
 #ifdef	HAVE_GETCWD
-      perror_with_name ("getcwd: ", "");
+      perror_with_name ("getcwd", "");
 #else
       error (NILF, "getwd: %s", current_directory);
@@ -1014,5 +1097,18 @@
   /* Initialize the special variables.  */
   define_variable (".VARIABLES", 10, "", o_default, 0)->special = 1;
-  /* define_variable (".TARGETS", 8, "", o_default, 0); */
+  /* define_variable (".TARGETS", 8, "", o_default, 0)->special = 1; */
+
+  /* Set up .FEATURES */
+  define_variable (".FEATURES", 9,
+                   "target-specific order-only second-expansion",
+                   o_default, 0);
+#ifdef MAKE_JOBSERVER
+  do_variable_definition (NILF, ".FEATURES", "jobserver",
+                          o_default, f_append, 0);
+#endif
+#ifdef MAKE_SYMLINKS
+  do_variable_definition (NILF, ".FEATURES", "check-symlink",
+                          o_default, f_append, 0);
+#endif
 
   /* Read in variables from the environment.  It is important that this be
@@ -1023,18 +1119,16 @@
   for (i = 0; envp[i] != 0; ++i)
     {
-      int do_not_define;
-      register char *ep = envp[i];
-
-      /* by default, everything gets defined and exported */
-      do_not_define = 0;
-
-      while (*ep != '=')
+      int do_not_define = 0;
+      char *ep = envp[i];
+
+      while (*ep != '\0' && *ep != '=')
         ++ep;
 #ifdef WINDOWS32
       if (!unix_path && strneq(envp[i], "PATH=", 5))
         unix_path = ep+1;
-      else if (!windows32_path && !strnicmp(envp[i], "Path=", 5)) {
+      else if (!strnicmp(envp[i], "Path=", 5)) {
         do_not_define = 1; /* it gets defined after loop exits */
-        windows32_path = ep+1;
+        if (!windows32_path)
+          windows32_path = ep+1;
       }
 #endif
@@ -1043,29 +1137,37 @@
 	 the same.  */
       if (!do_not_define)
-        define_variable (envp[i], (unsigned int) (ep - envp[i]),
-                         ep + 1, o_env, 1)
-	/* Force exportation of every variable culled from the environment.
-	   We used to rely on target_environment's v_default code to do this.
-	   But that does not work for the case where an environment variable
-	   is redefined in a makefile with `override'; it should then still
-	   be exported, because it was originally in the environment.  */
-	->export = v_export;
+        {
+          struct variable *v;
+
+          v = define_variable (envp[i], (unsigned int) (ep - envp[i]),
+                               ep + 1, o_env, 1);
+          /* Force exportation of every variable culled from the environment.
+             We used to rely on target_environment's v_default code to do this.
+             But that does not work for the case where an environment variable
+             is redefined in a makefile with `override'; it should then still
+             be exported, because it was originally in the environment.  */
+          v->export = v_export;
+
+          /* Another wrinkle is that POSIX says the value of SHELL set in the
+             makefile should not change the value of SHELL given to
+             subprocesses, which seems silly to me but...  */
+          if (strncmp (envp[i], "SHELL=", 6) == 0)
+            {
+#ifndef __MSDOS__
+              v->export = v_noexport;
+#endif
+              shell_var.name = "SHELL";
+              shell_var.value = xstrdup (ep + 1);
+            }
+        }
     }
 #ifdef WINDOWS32
-    /*
-     * Make sure that this particular spelling of 'Path' is available
+    /* If we didn't find a correctly spelled PATH we define PATH as
+     * either the first mispelled value or an empty string
      */
-    if (windows32_path)
-      define_variable("Path", 4, windows32_path, o_env, 1)->export = v_export;
-    else if (unix_path)
-      define_variable("Path", 4, unix_path, o_env, 1)->export = v_export;
-    else
-      define_variable("Path", 4, "", o_env, 1)->export = v_export;
-
-    /*
-     * PATH defaults to Path iff PATH not found and Path is found.
-     */
-    if (!unix_path && windows32_path)
-      define_variable("PATH", 4, windows32_path, o_env, 1)->export = v_export;
+    if (!unix_path)
+      define_variable("PATH", 4,
+                      windows32_path ? windows32_path : "",
+                      o_env, 1)->export = v_export;
 #endif
 #else /* For Amiga, read the ENV: device, ignoring all dirs */
@@ -1237,14 +1339,25 @@
       {
 	char *dir = directories->list[i];
+        char *expanded = 0;
 	if (dir[0] == '~')
 	  {
-	    char *expanded = tilde_expand (dir);
+            expanded = tilde_expand (dir);
 	    if (expanded != 0)
 	      dir = expanded;
 	  }
+#ifdef WINDOWS32
+        /* WINDOWS32 chdir() doesn't work if the directory has a trailing '/'
+           But allow -C/ just in case someone wants that.  */
+        {
+          char *p = dir + strlen (dir) - 1;
+          while (p > dir && (p[0] == '/' || p[0] == '\\'))
+            --p;
+          p[1] = '\0';
+        }
+#endif
 	if (chdir (dir) < 0)
 	  pfatal_with_name (dir);
-	if (dir != directories->list[i])
-	  free (dir);
+	if (expanded)
+	  free (expanded);
       }
 
@@ -1301,5 +1414,5 @@
 	{
 #ifdef	HAVE_GETCWD
-	  perror_with_name ("getcwd: ", "");
+	  perror_with_name ("getcwd", "");
 #else
 	  error (NILF, "getwd: %s", current_directory);
@@ -1368,5 +1481,5 @@
 	    if (outfile == 0)
 	      pfatal_with_name (_("fopen (temporary file)"));
-	    while (!feof (stdin))
+	    while (!feof (stdin) && ! ferror (stdin))
 	      {
 		char buf[2048];
@@ -1448,7 +1561,12 @@
   define_default_variables ();
 
+  default_file = enter_file (".DEFAULT");
+
+  {
+    struct variable *v = define_variable (".DEFAULT_GOAL", 13, "", o_file, 0);
+    default_goal_name = &v->value;
+  }
+
   /* Read all the makefiles.  */
-
-  default_file = enter_file (".DEFAULT");
 
   read_makefiles
@@ -1580,4 +1698,6 @@
          want job_slots to be 0 to indicate we're using the jobserver.  */
 
+      master_job_slots = job_slots;
+
       while (--job_slots)
         {
@@ -1599,4 +1719,12 @@
       jobserver_fds->idx = 1;
       jobserver_fds->max = 1;
+    }
+#endif
+
+#ifndef MAKE_SYMLINKS
+  if (check_symlink_flag)
+    {
+      error (NILF, _("Symbolic links not supported: disabling -L."));
+      check_symlink_flag = 0;
     }
 #endif
@@ -1668,4 +1796,5 @@
       int nargc = argc;
       int orig_db_level = db_level;
+      int status;
 
       if (! ISDB (DB_MAKEFILES))
@@ -1728,5 +1857,9 @@
       define_makeflags (1, 1);
 
-      switch (update_goal_chain (read_makefiles, 1))
+      rebuilding_makefiles = 1;
+      status = update_goal_chain (read_makefiles);
+      rebuilding_makefiles = 0;
+
+      switch (status)
 	{
 	case 1:
@@ -1777,4 +1910,5 @@
                         any_remade |= (mtime != NONEXISTENT_MTIME
                                        && mtime != makefile_mtimes[i]);
+                        makefile_status = MAKE_FAILURE;
                       }
                   }
@@ -1866,6 +2000,6 @@
 #ifndef _AMIGA
 	  for (p = environ; *p != 0; ++p)
-	    if ((*p)[MAKELEVEL_LENGTH] == '='
-		&& strneq (*p, MAKELEVEL_NAME, MAKELEVEL_LENGTH))
+	    if (strneq (*p, MAKELEVEL_NAME, MAKELEVEL_LENGTH)
+		&& (*p)[MAKELEVEL_LENGTH] == '=')
 	      {
 		/* The SGI compiler apparently can't understand
@@ -1922,12 +2056,12 @@
 	    int pid;
 	    int status;
-	    pid = child_execute_job(0, 1, nargv, environ);
+	    pid = child_execute_job (0, 1, nargv, environ);
 
 	    /* is this loop really necessary? */
 	    do {
-	      pid = wait(&status);
-	    } while(pid <= 0);
+	      pid = wait (&status);
+	    } while (pid <= 0);
 	    /* use the exit code of the child process */
-	    exit(WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE);
+	    exit (WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE);
 	  }
 #else
@@ -1943,4 +2077,8 @@
 
       db_level = orig_db_level;
+
+      /* Free the makefile mtimes (if we allocated any).  */
+      if (makefile_mtimes)
+        free ((char *) makefile_mtimes);
     }
 
@@ -1959,15 +2097,45 @@
     if (goals == 0)
       {
-	if (default_goal_file != 0)
-	  {
-	    goals = (struct dep *) xmalloc (sizeof (struct dep));
-	    goals->next = 0;
-	    goals->name = 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;
+
+                    ns = multi_glob (
+                      parse_file_seq (&p, '\0', sizeof (struct nameseq), 1),
+                      sizeof (struct nameseq));
+
+                    /* .DEFAULT_GOAL should contain one target. */
+                    if (ns->next != 0)
+                      fatal (NILF, _(".DEFAULT_GOAL contains more than one target"));
+
+                    default_goal_file = enter_file (ns->name);
+
+                    ns->name = 0; /* It was reused by enter_file(). */
+                    free_ns_chain (ns);
+                  }
+              }
+
+            goals = (struct dep *) xmalloc (sizeof (struct dep));
+            goals->next = 0;
+            goals->name = 0;
             goals->ignore_mtime = 0;
-	    goals->file = default_goal_file;
-	  }
+            goals->need_2nd_expansion = 0;
+            goals->file = default_goal_file;
+          }
       }
     else
       lastgoal->next = 0;
+
 
     if (!goals)
@@ -1983,5 +2151,5 @@
     DB (DB_BASIC, (_("Updating goal targets....\n")));
 
-    switch (update_goal_chain (goals, 0))
+    switch (update_goal_chain (goals))
     {
       case -1:
@@ -1989,5 +2157,5 @@
       case 0:
         /* Updated successfully.  */
-        status = MAKE_SUCCESS;
+        status = makefile_status;
         break;
       case 1:
@@ -2093,11 +2261,19 @@
   if (v != 0)
     {
-      /* It is indeed a variable definition.  Record a pointer to
-	 the variable for later use in define_makeflags.  */
-      struct command_variable *cv
-	= (struct command_variable *) xmalloc (sizeof (*cv));
-      cv->variable = v;
-      cv->next = command_variables;
-      command_variables = cv;
+      /* It is indeed a variable definition.  If we don't already have this
+	 one, record a pointer to the variable for later use in
+	 define_makeflags.  */
+      struct command_variable *cv;
+
+      for (cv = command_variables; cv != 0; cv = cv->next)
+        if (cv->variable == v)
+          break;
+
+      if (! cv) {
+        cv = (struct command_variable *) xmalloc (sizeof (*cv));
+        cv->variable = v;
+        cv->next = command_variables;
+        command_variables = cv;
+      }
     }
   else if (! env)
@@ -2122,4 +2298,5 @@
       lastgoal->file = f;
       lastgoal->ignore_mtime = 0;
+      lastgoal->need_2nd_expansion = 0;
 
       {
@@ -2770,4 +2947,5 @@
   if (!dying)
     {
+      char token = '+';
       int err;
 
@@ -2789,4 +2967,46 @@
       if (print_data_base_flag)
 	print_data_base ();
+
+      /* Sanity: have we written all our jobserver tokens back?  If our
+         exit status is 2 that means some kind of syntax error; we might not
+         have written all our tokens so do that now.  If tokens are left
+         after any other error code, that's bad.  */
+
+      if (job_fds[0] != -1 && jobserver_tokens)
+        {
+          if (status != 2)
+            error (NILF,
+                   "INTERNAL: Exiting with %u jobserver tokens (should be 0)!",
+                   jobserver_tokens);
+          else
+            while (jobserver_tokens--)
+              {
+                int r;
+
+                EINTRLOOP (r, write (job_fds[1], &token, 1));
+                if (r != 1)
+                  perror_with_name ("write", "");
+              }
+        }
+
+
+      /* Sanity: If we're the master, were all the tokens written back?  */
+
+      if (master_job_slots)
+        {
+          /* We didn't write one for ourself, so start at 1.  */
+          unsigned int tcnt = 1;
+
+          /* Close the write side, so the read() won't hang.  */
+          close (job_fds[1]);
+
+          while ((err = read (job_fds[0], &token, 1)) == 1)
+            ++tcnt;
+
+          if (tcnt != master_job_slots)
+            error (NILF,
+                   "INTERNAL: Exiting with %u jobserver tokens available; should be %u!",
+                   tcnt, master_job_slots);
+        }
 
       /* Try to move back to the original directory.  This is essential on
@@ -2854,3 +3074,6 @@
         printf (_("%s[%u]: Leaving directory `%s'\n"),
                 program, makelevel, starting_directory);
+
+  /* Flush stdout to be sure this comes before any stderr output.  */
+  fflush (stdout);
 }
Index: branches/GNU/src/gmake/maintMakefile
===================================================================
--- branches/GNU/src/gmake/maintMakefile	(revision 157)
+++ branches/GNU/src/gmake/maintMakefile	(revision 280)
@@ -2,8 +2,9 @@
 # only if you have the full copy of the GNU make sources from the CVS
 # tree, not a dist copy.
-#
+
+# We like mondo-warnings!
+AM_CFLAGS += -Wall -W
 
 # Find the glob source files... this might be dangerous, but we're maintainers!
-#
 globsrc := $(wildcard glob/*.c)
 globhdr := $(wildcard glob/*.h)
@@ -14,9 +15,4 @@
 
 all-am: $(TEMPLATES) $(MTEMPLATES) build.sh.in
-
-# We need this to ensure that README and build.sh.in are created on time to
-# avoid errors by automake.
-#
-#Makefile.in: README build.sh.in
 
 # General rule for turning a .template into a regular file.
@@ -56,5 +52,5 @@
 	rm -f $@
 	sed -e 's@%objs%@$(patsubst %.o,%.$${OBJEXT},$(filter-out remote-%,$(make_OBJECTS)))@g' \
-	    -e 's@%globobjs%@$(patsubst %.c,%.$${OBJEXT},$(globsrc)))@g' \
+	    -e 's@%globobjs%@$(patsubst %.c,%.$${OBJEXT},$(globsrc))@g' \
 	  $< > $@
 	chmod a-w+x $@
@@ -67,11 +63,16 @@
 # to do it ourselves.
 #
+DEP_FILES := $(wildcard $(DEPDIR)/*.Po)
 .dep_segment: Makefile.am maintMakefile $(DEP_FILES)
-	cat $(DEP_FILES) \
-	  | sed -e '/^[^:]*\.[ch] *:/d' \
-		-e 's, /usr/[^ ]*,,g' \
-		-e 's, $(srcdir)/, ,g' \
-		-e '/^ \\$$/d' \
-	  > $@
+	(for f in $(DEPDIR)/*.Po; do \
+	   echo ""; \
+	   echo "# $$f"; \
+	   cat $$f \
+	     | sed -e '/^[^:]*\.[ch] *:/d' \
+		   -e 's, /usr/[^ ]*,,g' \
+		   -e 's, $(srcdir)/, ,g' \
+		   -e '/^ *\\$$/d' \
+		   -e '/^ *$$/d'; \
+	 done) > $@
 
 # Get rid of everything "else".
@@ -80,18 +81,23 @@
 
 CVS-CLEAN-FILES +=	$(maintFILES) $(TEMPLATES) $(MTEMPLATES) NMakefile \
-			missing build.sh.in .dep_segment po-check-?
+			build.sh.in .deps .dep_segment ABOUT-NLS \
+			ansi2knr.*
 
 # This rule tries to clean the tree right down to how it looks when you do a
 # virgin CVS checkout.
 
+# This is potentially dangerous since it removes _ANY FILE_ that is not in
+# CVS.  Including files you might mean to add to CVS but haven't yet...
+# I only use this in subdirectories where it's unlikely we have any new
+# files.  Stil...
+cvsclean = perl -e '$$k{CVS} = 1; open(E,"< CVS/Entries") || die "CVS/Entries: $$!\n"; while (defined ($$_ = <E>)) { m%^/([^/]*)% or next; $$k{$$1} = 1; } close(E) || die "CVS/Entries: $$!\n"; opendir(D, ".") || die ".: $$!\n"; while (defined ($$_ = readdir(D))) { -f $$_ && ! exists $$k{$$_} && unlink($$_); } closedir(D) || die ".: $$!\n";'
+
 .PHONY: cvs-clean
 cvs-clean: maintainer-clean
-	-rm -f *~
-	-rm -f config/*~ config/Makefile.in config/[a-z]*
-	-rm -f po/*~ po/Makefile.in.in po/Rules-quot po/[a-z]*
-	-rm -f doc/*~ doc/Makefile.in doc/fdl.texi doc/make-stds.texi \
-		doc/texinfo.tex
-	-rm -f glob/*~ glob/Makefile.in
-	-rm -f ABOUT-NLS $(CVS-CLEAN-FILES)
+	-rm -rf *~ $(CVS-CLEAN-FILES)
+	-cd config && $(cvsclean)
+	-cd po     && $(cvsclean)
+	-cd doc    && $(cvsclean)
+	-cd glob   && $(cvsclean)
 
 
@@ -119,5 +125,5 @@
 # ------------------- #
 
-po_repo = http://www2.iro.umontreal.ca/%7Egnutra/po/maint/$(PACKAGE)
+po_repo = http://www.iro.umontreal.ca/translation/maint/$(PACKAGE)
 .PHONY: do-po-update po-update
 do-po-update:
@@ -136,5 +142,5 @@
 
 # -------------------------- #
-# Updating GNU build tools.  #
+# Updating GNU build files.  #
 # -------------------------- #
 
@@ -142,31 +148,9 @@
 # with each of the files that belongs to some other package and is
 # regularly updated from the specified URL.
-#              $(srcdir)/src/ansi2knr.c
-
-
-wget_files ?= $(srcdir)/doc/texinfo.tex $(srcdir)/doc/make-stds.texi \
-	      $(srcdir)/doc/fdl.texi
-
-wget-targets = $(patsubst %, get-%, $(wget_files))
-
-ansi2knr.c-url_prefix = ftp://ftp.cs.wisc.edu/ghost/
-
-texinfo.tex-url_prefix = $(ftp-gnu)/texinfo/
-
-standards.texi-url_prefix = $(ftp-gnu)/GNUinfo/
-make-stds.texi-url_prefix = $(ftp-gnu)/GNUinfo/
-fdl.texi-url_prefix = $(ftp-gnu)/GNUinfo/
-
+
+savannah-url = http://savannah.gnu.org/cgi-bin/viewcvs/~checkout~
 target = $(patsubst get-%,%,$@)
-url = $($(notdir $(target))-url_prefix)$(notdir $(target))
-
-.PHONY: $(wget-targets)
-$(wget-targets):
-	@echo $(WGET) $(url) -O $(target) \
-	  && $(WGET) $(url) -O $(target).t \
-	  && $(move_if_change)
-
-config-prefix = http://savannah.gnu.org/cgi-bin/viewcvs/config
-config-url = $(config-prefix)/$(patsubst get-%,%,$@)?rev=HEAD
+
+config-url = $(savannah-url)/config/config/$(patsubst get-config/%,%,$@)
 get-config/config.guess get-config/config.sub:
 	@echo $(WGET) $(config-url) -O $(target) \
@@ -174,23 +158,18 @@
 	  && $(move_if_change)
 
-
-.PHONY: wget-update
-wget-update: $(wget-targets)
-
-
-# Updating tools via CVS.
-cvs_files ?= depcomp missing
-# config/config.guess config/config.sub
-cvs-targets = $(patsubst %, get-%, $(cvs_files))
-
-automake_repo = :pserver:anoncvs@anoncvs.cygnus.com:/cvs/automake
-.PHONY: $(cvs-targets)
-$(cvs-targets):
-	$(CVS) -d $(automake_repo) co -p automake/lib/$(notdir $(target)) \
-	  >$(target).t \
-	    && $(move_if_change)
+gnulib-url = $(savannah-url)/gnulib/gnulib/build-aux/$(patsubst get-config/%,%,$@)
+get-config/texinfo.tex:
+	@echo $(WGET) $(gnulib-url) -O $(target) \
+	  && $(WGET) $(gnulib-url) -O $(target).t \
+	  && $(move_if_change)
+
+gnustandards-url = $(savannah-url)/gnustandards/gnustandards/$(patsubst get-doc/%,%,$@)
+get-doc/make-stds.texi get-doc/fdl.texi:
+	@echo $(WGET) $(gnustandards-url) -O $(target) \
+	  && $(WGET) $(gnustandards-url) -O $(target).t \
+	  && $(move_if_change)
 
 .PHONY: cvs-update
-cvs-update: $(cvs-targets) get-config/config.guess get-config/config.sub
+cvs-update: get-config/texinfo.tex get-config/config.guess get-config/config.sub get-doc/make-stds.texi get-doc/fdl.texi
 
 
@@ -200,7 +179,5 @@
 
 .PHONY: update
-update: wget-update po-update
-
-# cvs-update
+update: po-update cvs-update
 
 
@@ -232,2 +209,41 @@
 	  rm -f $@-1 $@-2; \
 	fi
+
+## ------------------------- ##
+## GNU FTP upload artifacts. ##
+## ------------------------- ##
+
+# This target creates the upload artifacts.
+# Sign it with my key.
+
+GPG = gpg
+GPGFLAGS = -u 6338B6D4
+
+DIST_ARCHIVES_SIG = $(addsuffix .sig,$(DIST_ARCHIVES))
+DIST_ARCHIVES_DIRECTIVE = $(addsuffix .directive.asc,$(DIST_ARCHIVES))
+
+.PHONY: distsign
+distsign: $(DIST_ARCHIVES_SIG) $(DIST_ARCHIVES_DIRECTIVE)
+
+$(DIST_ARCHIVES_DIRECTIVE): .directive.asc
+	cp $< $@
+
+%.sig : %
+	@echo "Signing file '$<':"
+	$(GPG) $(GPGFLAGS) -o $@ -b $<
+
+.directive.asc:
+	@echo "Creating directive file '$@':"
+	@echo 'directory: make' > .directive
+	$(GPG) $(GPGFLAGS) -o $@ --clearsign .directive
+	@rm -f .directive
+
+# Upload the artifacts
+
+FTPPUT = ncftpput
+gnu-url = ftp-upload.gnu.org /incoming
+
+UPLOADS = upload-alpha upload-ftp
+.PHONY: $(UPLOADS)
+$(UPLOADS): $(DIST_ARCHIVES) $(DIST_ARCHIVES_SIG) $(DIST_ARCHIVES_DIRECTIVE)
+	$(FTPPUT) $(gnu-url)/$(@:upload-%=%) $^
Index: branches/GNU/src/gmake/make.h
===================================================================
--- branches/GNU/src/gmake/make.h	(revision 157)
+++ branches/GNU/src/gmake/make.h	(revision 280)
@@ -367,5 +367,4 @@
 extern void sync_Path_environment(void);
 extern int kill(int pid, int sig);
-extern int safe_stat(char *file, struct stat *sb);
 extern char *end_of_token_w32(char *s, char stopchar);
 extern int find_and_set_default_shell(char *token);
@@ -422,9 +421,7 @@
 extern char *find_next_token PARAMS ((char **, unsigned int *));
 extern char *next_token PARAMS ((const char *));
-extern char *end_of_token PARAMS ((char *));
+extern char *end_of_token PARAMS ((const char *));
 extern void collapse_continuations PARAMS ((char *));
 extern void remove_comments PARAMS((char *));
-extern char *sindex PARAMS ((const char *, unsigned int, \
-                             const char *, unsigned int));
 extern char *lindex PARAMS ((const char *, const char *, int));
 extern int alpha_compare PARAMS ((const void *, const void *));
@@ -464,4 +461,8 @@
 extern void child_access PARAMS ((void));
 
+extern char *
+strip_whitespace PARAMS ((const char **begpp, const char **endpp));
+
+
 #ifdef  HAVE_VFORK_H
 # include <vfork.h>
@@ -496,7 +497,7 @@
 extern int print_data_base_flag, question_flag, touch_flag, always_make_flag;
 extern int env_overrides, no_builtin_rules_flag, no_builtin_variables_flag;
-extern int print_version_flag, print_directory_flag;
+extern int print_version_flag, print_directory_flag, check_symlink_flag;
 extern int warn_undefined_variables_flag, posix_pedantic, not_parallel;
-extern int clock_skew_detected;
+extern int clock_skew_detected, rebuilding_makefiles;
 
 /* can we run commands via 'sh -c xxx' or must we use batch files? */
Index: branches/GNU/src/gmake/makefile.vms
===================================================================
--- branches/GNU/src/gmake/makefile.vms	(revision 157)
+++ branches/GNU/src/gmake/makefile.vms	(revision 280)
@@ -6,4 +6,5 @@
 # Modified for version 3.78.1 by Hartmut.Becker@compaq.com.
 # Modified for version 3.80 by zinser@decus.de
+# Modified for version 3.81 by Hartmut Becker
 #
 # GNU Make is free software; you can redistribute it and/or modify
@@ -32,5 +33,5 @@
 
 ifeq ($(CC),cc)
-CFLAGS = $(defines) /include=([],[.glob])/prefix=all/standard=relaxed
+CFLAGS = $(defines) /include=([],[.glob])/prefix=(all,except=(glob,globfree))/standard=relaxed
 else
 CFLAGS = $(defines) /include=([],[.glob])
@@ -112,5 +113,4 @@
 	$$ purge [...]
 	-$(RM) make.exe;,*.obj;
-	-$(RM) *.opt;
 	-$(RM) [.glob]*.obj;
 
Index: branches/GNU/src/gmake/misc.c
===================================================================
--- branches/GNU/src/gmake/misc.c	(revision 157)
+++ branches/GNU/src/gmake/misc.c	(revision 280)
@@ -419,32 +419,4 @@
 
 
-/* Search string BIG (length BLEN) for an occurrence of
-   string SMALL (length SLEN).  Return a pointer to the
-   beginning of the first occurrence, or return nil if none found.  */
-
-char *
-sindex (const char *big, unsigned int blen,
-        const char *small, unsigned int slen)
-{
-  if (!blen)
-    blen = strlen (big);
-  if (!slen)
-    slen = strlen (small);
-
-  if (slen && blen >= slen)
-    {
-      register unsigned int b;
-
-      /* Quit when there's not enough room left for the small string.  */
-      --slen;
-      blen -= slen;
-
-      for (b = 0; b < blen; ++b, ++big)
-        if (*big == *small && strneq (big + 1, small + 1, slen))
-          return (char *)big;
-    }
-
-  return 0;
-}
 
 /* Limited INDEX:
@@ -468,9 +440,9 @@
 
 char *
-end_of_token (char *s)
+end_of_token (const char *s)
 {
   while (*s != '\0' && !isblank ((unsigned char)*s))
     ++s;
-  return s;
+  return (char *)s;
 }
 
@@ -563,4 +535,26 @@
 
 
+/* Free a chain of `struct nameseq'. Each nameseq->name is freed
+   as well.  Can be used on `struct dep' chains.*/
+
+void
+free_ns_chain (struct nameseq *n)
+{
+  register struct nameseq *tmp;
+
+  while (n != 0)
+  {
+    if (n->name != 0)
+      free (n->name);
+
+    tmp = n;
+
+    n = n->next;
+
+    free (tmp);
+  }
+
+}
+
 #ifdef	iAPX286
 /* The losing compiler on this machine can't handle this macro.  */
Index: branches/GNU/src/gmake/po/.cvsignore
===================================================================
--- branches/GNU/src/gmake/po/.cvsignore	(revision 157)
+++ branches/GNU/src/gmake/po/.cvsignore	(revision 280)
@@ -1,6 +1,6 @@
 *.gmo *.mo *.pot *.po
 
-Makefile Makefile.in Makefile.in.in
-Rules-quot
+Makefile Makefile.in Makefile.in.in Makevars.template
+Rules-quot stamp-po
 *.sed *.sin *.header
 POTFILES
Index: branches/GNU/src/gmake/po/ChangeLog
===================================================================
--- branches/GNU/src/gmake/po/ChangeLog	(revision 157)
+++ branches/GNU/src/gmake/po/ChangeLog	(revision 280)
@@ -1,2 +1,18 @@
+2005-05-09  Paul D. Smith  <psmith@gnu.org>
+
+	* POTFILES.in: Add new file vmsjobs.c.
+
+2005-04-06  Paul D. Smith  <psmith@gnu.org>
+
+	* LINGUAS: Added a new translation for Kinywarwanda (rw).
+
+2005-02-09  Paul D. Smith  <psmith@gnu.org>
+
+	* LINGUAS: Added a new translation for Irish (ga).
+
+2005-02-01  Paul D. Smith  <psmith@gnu.org>
+
+	* LINGUAS: Added a new translation for Finnish (fi).
+
 2003-10-18  Paul D. Smith  <psmith@gnu.org>
 
Index: branches/GNU/src/gmake/po/LINGUAS
===================================================================
--- branches/GNU/src/gmake/po/LINGUAS	(revision 157)
+++ branches/GNU/src/gmake/po/LINGUAS	(revision 280)
@@ -1,5 +1,5 @@
-# Set of available languages: 16 languages
+# Set of available languages: 20 languages
 
-be da de es fr gl he hr ja ko nl pl pt_BR sv ru tr uk zh_CN
+be da de es fi fr ga gl he hr ja ko nl pl pt_BR ru rw sv tr uk zh_CN
 
 # Can't seem to get en@quot and en@boldquot to build properly?
Index: branches/GNU/src/gmake/po/POTFILES.in
===================================================================
--- branches/GNU/src/gmake/po/POTFILES.in	(revision 157)
+++ branches/GNU/src/gmake/po/POTFILES.in	(revision 280)
@@ -23,3 +23,4 @@
 variable.h
 vmsfunctions.c
+vmsjobs.c
 vpath.c
Index: branches/GNU/src/gmake/read.c
===================================================================
--- branches/GNU/src/gmake/read.c	(revision 157)
+++ branches/GNU/src/gmake/read.c	(revision 280)
@@ -79,5 +79,7 @@
     unsigned int if_cmds;	/* Depth of conditional nesting.  */
     unsigned int allocated;	/* Elts allocated in following arrays.  */
-    char *ignoring;		/* Are we ignoring or interepreting?  */
+    char *ignoring;		/* Are we ignoring or interpreting?
+                                   0=interpreting, 1=not yet interpreted,
+                                   2=already interpreted */
     char *seen_else;		/* Have we already seen an `else'?  */
   };
@@ -131,10 +133,9 @@
                                enum variable_origin origin,
                                struct ebuffer *ebuf));
-static int conditional_line PARAMS ((char *line, const struct floc *flocp));
+static int conditional_line PARAMS ((char *line, int len, const struct floc *flocp));
 static void record_files PARAMS ((struct nameseq *filenames, char *pattern, char *pattern_percent,
 			struct dep *deps, unsigned int cmds_started, char *commands,
 			unsigned int commands_idx, int two_colon,
-			int have_sysv_atvar,
-                        const struct floc *flocp, int set_default));
+                        const struct floc *flocp));
 static void record_target_var PARAMS ((struct nameseq *filenames, char *defn,
                                        enum variable_origin origin,
@@ -256,4 +257,5 @@
 	      d->file->dontcare = 1;
               d->ignore_mtime = 0;
+              d->need_2nd_expansion = 0;
 	      /* 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.  */
@@ -371,9 +373,5 @@
   deps->file = lookup_file (filename);
   if (deps->file == 0)
-    {
-      deps->file = enter_file (xstrdup (filename));
-      if (flags & RM_DONTCARE)
-	deps->file->dontcare = 1;
-    }
+    deps->file = enter_file (xstrdup (filename));
   if (filename != ebuf.floc.filenm)
     free (filename);
@@ -381,4 +379,7 @@
   deps->changed = flags;
   deps->ignore_mtime = 0;
+  deps->need_2nd_expansion = 0;
+  if (flags & RM_DONTCARE)
+    deps->file->dontcare = 1;
 
   /* If the makefile can't be found at all, give up entirely.  */
@@ -412,4 +413,5 @@
 
   free (ebuf.bufstart);
+  alloca (0);
   return r;
 }
@@ -443,4 +445,5 @@
   reading_file = curfile;
 
+  alloca (0);
   return r;
 }
@@ -464,5 +467,4 @@
   int ignoring = 0, in_ignored_define = 0;
   int no_targets = 0;		/* Set when reading a rule without targets.  */
-  int have_sysv_atvar = 0;
   struct nameseq *filenames = 0;
   struct dep *deps = 0;
@@ -481,5 +483,5 @@
 	  record_files (filenames, pattern, pattern_percent, deps,            \
                         cmds_started, commands, commands_idx, two_colon,      \
-                        have_sysv_atvar, &fi, set_default);                   \
+                        &fi);                                                 \
         }                                                                     \
       filenames = 0;							      \
@@ -618,15 +620,15 @@
 	 following lines.  */
 
-      if (!in_ignored_define
-	  && (word1eq ("ifdef") || word1eq ("ifndef")
-	      || word1eq ("ifeq") || word1eq ("ifneq")
-	      || word1eq ("else") || word1eq ("endif")))
-	{
- 	  int i = conditional_line (p, fstart);
-	  if (i < 0)
-	    fatal (fstart, _("invalid syntax in conditional"));
-
-          ignoring = i;
-	  continue;
+      if (!in_ignored_define)
+	{
+ 	  int i = conditional_line (p, len, fstart);
+          if (i != -2)
+            {
+              if (i == -1)
+                fatal (fstart, _("invalid syntax in conditional"));
+
+              ignoring = i;
+              continue;
+            }
 	}
 
@@ -853,19 +855,9 @@
 	goto rule_complete;
 
+      /* This line starts with a tab but was not caught above because there
+         was no preceding target, and the line might have been usable as a
+         variable definition.  But now we know it is definitely lossage.  */
       if (line[0] == '\t')
-	{
-	  p = collapsed;	/* Ignore comments, etc.  */
-	  while (isblank ((unsigned char)*p))
-	    ++p;
-	  if (*p == '\0')
-	    /* The line is completely blank; that is harmless.  */
-	    continue;
-
-	  /* This line starts with a tab but was not caught above
-	     because there was no preceding target, and the line
-	     might have been usable as a variable definition.
-	     But now we know it is definitely lossage.  */
-	  fatal(fstart, _("commands commence before first target"));
-	}
+        fatal(fstart, _("commands commence before first target"));
 
       /* This line describes some target files.  This is complicated by
@@ -886,4 +878,5 @@
         unsigned int len, plen = 0;
         char *colonp;
+        const char *end, *beg; /* Helpers for whitespace stripping. */
 
         /* Record the previous rule.  */
@@ -934,4 +927,5 @@
 
         p2 = variable_expand_string(NULL, lb_next, len);
+
         while (1)
           {
@@ -1040,11 +1034,9 @@
         if (*lb_next != '\0')
           {
-            unsigned int l = p - variable_buffer;
-            unsigned int l2 = p2 - variable_buffer;
+            unsigned int l = p2 - variable_buffer;
             plen = strlen (p2);
             (void) variable_buffer_output (p2+plen,
                                            lb_next, strlen (lb_next)+1);
-            p = variable_buffer + l;
-            p2 = variable_buffer + l2;
+            p2 = variable_buffer + l;
           }
 
@@ -1112,14 +1104,4 @@
               }
           }
-
-        /* Do any of the prerequisites appear to have $@ etc.?  */
-        have_sysv_atvar = 0;
-        if (!posix_pedantic)
-          for (p = strchr (p2, '$'); p != 0; p = strchr (p+1, '$'))
-            if (p[1] == '@' || ((p[1] == '(' || p[1] == '{') && p[2] == '@'))
-              {
-                have_sysv_atvar = 1;
-                break;
-              }
 
         /* Is this a static pattern rule: `target: %targ: %dep; ...'?  */
@@ -1187,24 +1169,30 @@
           pattern = 0;
 
-        /* Parse the dependencies.  */
-        deps = (struct dep *)
-          multi_glob (parse_file_seq (&p2, '|', sizeof (struct dep), 1),
-                      sizeof (struct dep));
-        if (*p2)
+        /* Strip leading and trailing whitespaces. */
+        beg = p2;
+        end = beg + strlen (beg) - 1;
+        strip_whitespace (&beg, &end);
+
+        if (beg <= end && *beg != '\0')
           {
-            /* Files that follow '|' are special prerequisites that
-               need only exist in order to satisfy the dependency.
-               Their modification times are irrelevant.  */
-            struct dep **deps_ptr = &deps;
-            struct dep *d;
-            for (deps_ptr = &deps; *deps_ptr; deps_ptr = &(*deps_ptr)->next)
-              ;
-            ++p2;
-            *deps_ptr = (struct dep *)
-              multi_glob (parse_file_seq (&p2, '\0', sizeof (struct dep), 1),
-                          sizeof (struct dep));
-            for (d = *deps_ptr; d != 0; d = d->next)
-              d->ignore_mtime = 1;
+            char *top;
+            const char *fromp = beg;
+
+            /* Make a copy of the dependency string.  Note if we find '$'.  */
+            deps = (struct dep*) xmalloc (sizeof (struct dep));
+            deps->next = 0;
+            deps->name = top = (char *) xmalloc (end - beg + 2);
+            deps->need_2nd_expansion = 0;
+            while (fromp <= end)
+              {
+                if (*fromp == '$')
+                  deps->need_2nd_expansion = 1;
+                *(top++) = *(fromp++);
+              }
+            *top = '\0';
+            deps->file = 0;
           }
+        else
+          deps = 0;
 
         commands_idx = 0;
@@ -1225,4 +1213,80 @@
             commands_idx += len;
             commands[commands_idx++] = '\n';
+          }
+
+        /* Determine if this target should be made default. We used to do
+           this in record_files() but because of the delayed target recording
+           and because preprocessor directives are legal in target's commands
+           it is too late. Consider this fragment for example:
+
+           foo:
+
+           ifeq ($(.DEFAULT_GOAL),foo)
+              ...
+           endif
+
+           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)
+          {
+            char* name;
+            struct dep *d;
+            struct nameseq *t = filenames;
+
+            for (; t != 0; t = t->next)
+              {
+                int reject = 0;
+                name = t->name;
+
+                /* We have nothing to do if this is an implicit rule. */
+                if (strchr (name, '%') != 0)
+                  break;
+
+                /* See if this target's name does not start with a `.',
+                   unless it contains a slash.  */
+                if (*name == '.' && strchr (name, '/') == 0
+#ifdef HAVE_DOS_PATHS
+                    && strchr (name, '\\') == 0
+#endif
+                    )
+                  continue;
+
+
+                /* If this file is a suffix, don't let it be
+                   the default goal file.  */
+                for (d = suffix_file->deps; d != 0; d = d->next)
+                  {
+                    register struct dep *d2;
+                    if (*dep_name (d) != '.' && streq (name, dep_name (d)))
+                      {
+                        reject = 1;
+                        break;
+                      }
+                    for (d2 = suffix_file->deps; d2 != 0; d2 = d2->next)
+                      {
+                        register unsigned int len = strlen (dep_name (d2));
+                        if (!strneq (name, dep_name (d2), len))
+                          continue;
+                        if (streq (name + len, dep_name (d)))
+                          {
+                            reject = 1;
+                            break;
+                          }
+                      }
+
+                    if (reject)
+                      break;
+                  }
+
+                if (!reject)
+                  {
+                    define_variable_global (".DEFAULT_GOAL", 13, t->name,
+                                            o_file, 0, NILF);
+                    break;
+                  }
+              }
           }
 
@@ -1283,6 +1347,6 @@
       char *line;
 
+      nlines = readline (ebuf);
       ebuf->floc.lineno += nlines;
-      nlines = readline (ebuf);
 
       /* If there is nothing left to eval, we're done. */
@@ -1365,65 +1429,106 @@
    current makefile.  They are used for error messages.
 
-   Value is -1 if the line is invalid,
+   Value is -2 if the line is not a conditional at all,
+   -1 if the line is an invalid conditional,
    0 if following text should be interpreted,
    1 if following text should be ignored.  */
 
 static int
-conditional_line (char *line, const struct floc *flocp)
+conditional_line (char *line, int len, const struct floc *flocp)
 {
-  int notdef;
   char *cmdname;
-  register unsigned int i;
-
-  if (*line == 'i')
-    {
-      /* It's an "if..." command.  */
-      notdef = line[2] == 'n';
-      if (notdef)
-	{
-	  cmdname = line[3] == 'd' ? "ifndef" : "ifneq";
-	  line += cmdname[3] == 'd' ? 7 : 6;
-	}
-      else
-	{
-	  cmdname = line[2] == 'd' ? "ifdef" : "ifeq";
-	  line += cmdname[2] == 'd' ? 6 : 5;
-	}
-    }
+  enum { c_ifdef, c_ifndef, c_ifeq, c_ifneq, c_else, c_endif } cmdtype;
+  unsigned int i;
+  unsigned int o;
+
+  /* Compare a word, both length and contents. */
+#define	word1eq(s)      (len == sizeof(s)-1 && strneq (s, line, sizeof(s)-1))
+#define	chkword(s, t)   if (word1eq (s)) { cmdtype = (t); cmdname = (s); }
+
+  /* Make sure this line is a conditional.  */
+  chkword ("ifdef", c_ifdef)
+  else chkword ("ifndef", c_ifndef)
+  else chkword ("ifeq", c_ifeq)
+  else chkword ("ifneq", c_ifneq)
+  else chkword ("else", c_else)
+  else chkword ("endif", c_endif)
   else
-    {
-      /* It's an "else" or "endif" command.  */
-      notdef = line[1] == 'n';
-      cmdname = notdef ? "endif" : "else";
-      line += notdef ? 5 : 4;
-    }
-
-  line = next_token (line);
-
-  if (*cmdname == 'e')
+    return -2;
+
+  /* Found one: skip past it and any whitespace after it.  */
+  line = next_token (line + len);
+
+#define EXTRANEOUS() error (flocp, _("Extraneous text after `%s' directive"), cmdname)
+
+  /* An 'endif' cannot contain extra text, and reduces the if-depth by 1  */
+  if (cmdtype == c_endif)
     {
       if (*line != '\0')
-	error (flocp, _("Extraneous text after `%s' directive"), cmdname);
-      /* "Else" or "endif".  */
-      if (conditionals->if_cmds == 0)
+	EXTRANEOUS ();
+
+      if (!conditionals->if_cmds)
 	fatal (flocp, _("extraneous `%s'"), cmdname);
-      /* NOTDEF indicates an `endif' command.  */
-      if (notdef)
-	--conditionals->if_cmds;
-      else if (conditionals->seen_else[conditionals->if_cmds - 1])
-	fatal (flocp, _("only one `else' per conditional"));
+
+      --conditionals->if_cmds;
+
+      goto DONE;
+    }
+
+  /* An 'else' statement can either be simple, or it can have another
+     conditional after it.  */
+  if (cmdtype == c_else)
+    {
+      const char *p;
+
+      if (!conditionals->if_cmds)
+	fatal (flocp, _("extraneous `%s'"), cmdname);
+
+      o = conditionals->if_cmds - 1;
+
+      if (conditionals->seen_else[o])
+        fatal (flocp, _("only one `else' per conditional"));
+
+      /* Change the state of ignorance.  */
+      switch (conditionals->ignoring[o])
+        {
+          case 0:
+            /* We've just been interpreting.  Never do it again.  */
+            conditionals->ignoring[o] = 2;
+            break;
+          case 1:
+            /* We've never interpreted yet.  Maybe this time!  */
+            conditionals->ignoring[o] = 0;
+            break;
+        }
+
+      /* It's a simple 'else'.  */
+      if (*line == '\0')
+        {
+          conditionals->seen_else[o] = 1;
+          goto DONE;
+        }
+
+      /* The 'else' has extra text.  That text must be another conditional
+         and cannot be an 'else' or 'endif'.  */
+
+      /* Find the length of the next word.  */
+      for (p = line+1; *p != '\0' && !isspace ((unsigned char)*p); ++p)
+        ;
+      len = p - line;
+
+      /* If it's 'else' or 'endif' or an illegal conditional, fail.  */
+      if (word1eq("else") || word1eq("endif")
+          || conditional_line (line, len, flocp) < 0)
+	EXTRANEOUS ();
       else
-	{
-	  /* Toggle the state of ignorance.  */
-	  conditionals->ignoring[conditionals->if_cmds - 1]
-	    = !conditionals->ignoring[conditionals->if_cmds - 1];
-	  /* Record that we have seen an `else' in this conditional.
-	     A second `else' will be erroneous.  */
-	  conditionals->seen_else[conditionals->if_cmds - 1] = 1;
-	}
-      for (i = 0; i < conditionals->if_cmds; ++i)
-	if (conditionals->ignoring[i])
-	  return 1;
-      return 0;
+        {
+          /* conditional_line() created a new level of conditional.
+             Raise it back to this level.  */
+          if (conditionals->ignoring[o] < 2)
+            conditionals->ignoring[o] = conditionals->ignoring[o+1];
+          --conditionals->if_cmds;
+        }
+
+      goto DONE;
     }
 
@@ -1435,5 +1540,5 @@
     }
 
-  ++conditionals->if_cmds;
+  o = conditionals->if_cmds++;
   if (conditionals->if_cmds > conditionals->allocated)
     {
@@ -1446,23 +1551,22 @@
 
   /* Record that we have seen an `if...' but no `else' so far.  */
-  conditionals->seen_else[conditionals->if_cmds - 1] = 0;
+  conditionals->seen_else[o] = 0;
 
   /* Search through the stack to see if we're already ignoring.  */
-  for (i = 0; i < conditionals->if_cmds - 1; ++i)
+  for (i = 0; i < o; ++i)
     if (conditionals->ignoring[i])
       {
-	/* We are already ignoring, so just push a level
-	   to match the next "else" or "endif", and keep ignoring.
-	   We don't want to expand variables in the condition.  */
-	conditionals->ignoring[conditionals->if_cmds - 1] = 1;
+	/* We are already ignoring, so just push a level to match the next
+	   "else" or "endif", and keep ignoring.  We don't want to expand
+	   variables in the condition.  */
+	conditionals->ignoring[o] = 1;
 	return 1;
       }
 
-  if (cmdname[notdef ? 3 : 2] == 'd')
+  if (cmdtype == c_ifdef || cmdtype == c_ifndef)
     {
-      /* "Ifdef" or "ifndef".  */
       char *var;
       struct variable *v;
-      register char *p;
+      char *p;
 
       /* Expand the thing we're looking up, so we can use indirect and
@@ -1478,7 +1582,8 @@
 
       var[i] = '\0';
-      v = lookup_variable (var, strlen (var));
-      conditionals->ignoring[conditionals->if_cmds - 1]
-	= (v != 0 && *v->value != '\0') == notdef;
+      v = lookup_variable (var, i);
+
+      conditionals->ignoring[o] =
+        ((v != 0 && *v->value != '\0') == (cmdtype == c_ifndef));
 
       free (var);
@@ -1498,5 +1603,5 @@
       if (termin == ',')
 	{
-	  register int count = 0;
+	  int count = 0;
 	  for (; *line != '\0'; ++line)
 	    if (*line == '(')
@@ -1572,11 +1677,11 @@
       line = next_token (++line);
       if (*line != '\0')
-	error (flocp, _("Extraneous text after `%s' directive"), cmdname);
+	EXTRANEOUS ();
 
       s2 = variable_expand (s2);
-      conditionals->ignoring[conditionals->if_cmds - 1]
-	= streq (s1, s2) == notdef;
+      conditionals->ignoring[o] = (streq (s1, s2) == (cmdtype == c_ifneq));
     }
 
+ DONE:
   /* Search through the stack to see if we're ignoring.  */
   for (i = 0; i < conditionals->if_cmds; ++i)
@@ -1694,8 +1799,14 @@
           p = create_pattern_var (name, percent);
           p->variable.fileinfo = *flocp;
+          /* I don't think this can fail since we already determined it was a
+             variable definition.  */
           v = parse_variable_definition (&p->variable, defn);
-          v->value = xstrdup (v->value);
-          if (!v)
-            error (flocp, _("Malformed pattern-specific variable definition"));
+          assert (v != 0);
+
+          if (v->flavor == f_simple)
+            v->value = allocated_variable_expand (v->value);
+          else
+            v->value = xstrdup (v->value);
+
           fname = p->target;
         }
@@ -1771,5 +1882,5 @@
               struct dep *deps, unsigned int cmds_started, char *commands,
               unsigned int commands_idx, int two_colon,
-              int have_sysv_atvar, const struct floc *flocp, int set_default)
+              const struct floc *flocp)
 {
   struct nameseq *nextf;
@@ -1778,4 +1889,11 @@
   char **targets = 0, **target_percents = 0;
   struct commands *cmds;
+
+  /* If we've already snapped deps, that means we're in an eval being
+     resolved after the makefiles have been read in.  We can't add more rules
+     at this time, since they won't get snapped and we'll get core dumps.
+     See Savannah bug # 12124.  */
+  if (snapped_deps)
+    fatal (flocp, _("prerequisites cannot be defined in command scripts"));
 
   if (commands_idx > 0)
@@ -1843,5 +1961,5 @@
       /* 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 data base.  */
+	 to go in more than one place in the database.  */
       this = nextf != 0 ? copy_dep_chain (deps) : deps;
 
@@ -1860,127 +1978,19 @@
 	    }
 	  else
-	    {
-	      /* We use patsubst_expand to do the work of translating
-		 the target pattern, the target's name and the dependencies'
-		 patterns into plain dependency names.  */
-	      char *buffer = variable_expand ("");
-
-	      for (d = this; d != 0; d = d->next)
-		{
-		  char *o;
-		  char *percent = find_percent (d->name);
-		  if (percent == 0)
-		    continue;
-		  o = patsubst_expand (buffer, name, pattern, d->name,
-				       pattern_percent, percent);
-                  /* If the name expanded to the empty string, that's
-                     illegal.  */
-                  if (o == buffer)
-                    fatal (flocp,
-                           _("target `%s' leaves prerequisite pattern empty"),
-                           name);
-		  free (d->name);
-		  d->name = savestring (buffer, o - buffer);
-		}
-	    }
-	}
-
-      /* If at least one of the dependencies uses $$@ etc. deal with that.
-         It would be very nice and very simple to just expand everything, but
-         it would break a lot of backward compatibility.  Maybe that's OK
-         since we're just emulating a SysV function, and if we do that then
-         why not emulate it completely (that's what SysV make does: it
-         re-expands the entire prerequisite list, all the time, with $@
-         etc. in scope).  But, it would be a pain indeed to document this
-         ("iff you use $$@, your prerequisite lists is expanded twice...")
-         Ouch.  Maybe better to make the code more complex.  */
-
-      if (have_sysv_atvar)
-        {
-          char *p;
-          int tlen = strlen (name);
-          char *fnp = strrchr (name, '/');
-          int dlen;
-          int flen;
-
-          if (fnp)
-            {
-              dlen = fnp - name;
-              ++fnp;
-              flen = strlen (fnp);
-            }
-          else
-            {
-              dlen = 0;
-              fnp = name;
-              flen = tlen;
-            }
-
-
-          for (d = this; d != 0; d = d->next)
-            for (p = strchr (d->name, '$'); p != 0; p = strchr (p+1, '$'))
+            /* We use subst_expand to do the work of translating % to $* in
+               the dependency line.  */
+
+            if (this != 0 && find_percent (this->name) != 0)
               {
-                char *s = p;
-                char *at;
-                int atlen;
-
-                /* If it's '$@', '$(@', or '${@', it's escaped */
-                if ((++p)[0] == '$'
-                    && (p[1] == '@'
-                        || ((p[1] == '(' || p[1] == '{') && p[2] == '@')))
-                  {
-                    bcopy (p, s, strlen (p)+1);
-                    continue;
-                  }
-
-                /* Maybe found one.  We like anything of any form matching @,
-                   [({]@[}):], or [({]@[DF][}):].  */
-
-                if (! (p[0] == '@'
-                       || ((p[0] == '(' || p[0] == '{') && (++p)[0] == '@'
-                           && (((++p)[0] == ')' || p[0] == '}' || p[0] == ':')
-                               || ((p[1] == ')' || p[1] == '}' || p[1] == ':')
-                                   && (p[0] == 'D' || p[0] == 'F'))))))
-                  continue;
-
-                /* Found one.  Compute the length and string ptr.  Move p
-                   past the variable reference.  */
-                switch (p[0])
-                  {
-                  case 'D':
-                    atlen = dlen;
-                    at = name;
-                    p += 2;
-                    break;
-
-                  case 'F':
-                    atlen = flen;
-                    at = fnp;
-                    p += 2;
-                    break;
-
-                  default:
-                    atlen = tlen;
-                    at = name;
-                    ++p;
-                    break;
-                  }
-
-                /* Get more space.  */
-                {
-                  int soff = s - d->name;
-                  int poff = p - d->name;
-                  d->name = (char *) xrealloc (d->name,
-                                               strlen (d->name) + atlen + 1);
-                  s = d->name + soff;
-                  p = d->name + poff;
-                }
-
-                /* Copy the string over.  */
-                bcopy(p, s+atlen, strlen (p)+1);
-                bcopy(at, s, atlen);
-                p = s + atlen - 1;
+                char *o;
+                char *buffer = variable_expand ("");
+
+                o = subst_expand (buffer, this->name, "%", "$*", 1, 2, 0);
+
+                free (this->name);
+                this->name = savestring (buffer, o - buffer);
+                this->need_2nd_expansion = 1;
               }
-        }
+	}
 
       if (!two_colon)
@@ -2021,4 +2031,5 @@
 	  if (cmds != 0)
 	    f->cmds = cmds;
+
 	  /* Defining .SUFFIXES with no dependencies
 	     clears out the list of suffixes.  */
@@ -2035,39 +2046,61 @@
 	      f->deps = 0;
 	    }
-	  else if (f->deps != 0)
+          else if (this != 0)
 	    {
 	      /* Add the file's old deps and the new ones in THIS together.  */
 
-	      struct dep *firstdeps, *moredeps;
-	      if (cmds != 0)
-		{
-		  /* This is the rule with commands, so put its deps first.
-		     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.  */
-		  firstdeps = this;
-		  moredeps = f->deps;
-		}
-	      else
-		{
-		  /* Append the new deps to the old ones.  */
-		  firstdeps = f->deps;
-		  moredeps = this;
-		}
-
-	      if (firstdeps == 0)
-		firstdeps = moredeps;
-	      else
-		{
-		  d = firstdeps;
-		  while (d->next != 0)
-		    d = d->next;
-		  d->next = moredeps;
-		}
-
-	      f->deps = firstdeps;
+              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)
+                        {
+                          this->next = *d_ptr;
+                          *d_ptr = this;
+                        }
+                      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;
 	    }
-	  else
-	    f->deps = this;
 
 	  /* If this is a static pattern rule, set the file's stem to
@@ -2079,5 +2112,5 @@
 	      char *buffer = variable_expand ("");
 	      char *o = patsubst_expand (buffer, name, pattern, percent,
-					 pattern_percent, percent);
+					 pattern_percent+1, percent+1);
 	      f->stem = savestring (buffer, o - buffer);
 	    }
@@ -2115,44 +2148,9 @@
 	}
 
-      /* See if this is first target seen whose name does
-	 not start with a `.', unless it contains a slash.  */
-      if (default_goal_file == 0 && set_default
-	  && (*name != '.' || strchr (name, '/') != 0
-#ifdef HAVE_DOS_PATHS
-			   || strchr (name, '\\') != 0
-#endif
-	      ))
-	{
-	  int reject = 0;
-
-	  /* If this file is a suffix, don't
-	     let it be the default goal file.  */
-
-	  for (d = suffix_file->deps; d != 0; d = d->next)
-	    {
-	      register struct dep *d2;
-	      if (*dep_name (d) != '.' && streq (name, dep_name (d)))
-		{
-		  reject = 1;
-		  break;
-		}
-	      for (d2 = suffix_file->deps; d2 != 0; d2 = d2->next)
-		{
-		  register unsigned int len = strlen (dep_name (d2));
-		  if (!strneq (name, dep_name (d2), len))
-		    continue;
-		  if (streq (name + len, dep_name (d)))
-		    {
-		      reject = 1;
-		      break;
-		    }
-		}
-	      if (reject)
-		break;
-	    }
-
-	  if (!reject)
-	    default_goal_file = f;
-	}
+      /* If this target is a default target, update DEFAULT_GOAL_FILE.  */
+      if (strcmp (*default_goal_name, name) == 0
+          && (default_goal_file == 0
+              || strcmp (default_goal_file->name, name) != 0))
+        default_goal_file = f;
     }
 
@@ -2498,8 +2496,8 @@
 readstring (struct ebuffer *ebuf)
 {
-  char *p;
+  char *eol;
 
   /* If there is nothing left in this buffer, return 0.  */
-  if (ebuf->bufnext > ebuf->bufstart + ebuf->size)
+  if (ebuf->bufnext >= ebuf->bufstart + ebuf->size)
     return -1;
 
@@ -2507,24 +2505,31 @@
      next logical line (taking into account backslash/newline pairs).  */
 
-  p = ebuf->buffer = ebuf->bufnext;
+  eol = ebuf->buffer = ebuf->bufnext;
 
   while (1)
     {
       int backslash = 0;
-
-      /* Find the next newline.  Keep track of backslashes as we look.  */
-      for (; *p != '\n' && *p != '\0'; ++p)
-        if (*p == '\\')
-          backslash = !backslash;
-
-      /* If we got to the end of the string or a newline with no backslash,
-         we're done. */
-      if (*p == '\0' || !backslash)
+      char *bol = eol;
+      char *p;
+
+      /* Find the next newline.  At EOS, stop.  */
+      eol = p = strchr (eol , '\n');
+      if (!eol)
+        {
+          ebuf->bufnext = ebuf->bufstart + ebuf->size + 1;
+          return 0;
+        }
+
+      /* Found a newline; if it's escaped continue; else we're done.  */
+      while (p > bol && *(--p) == '\\')
+        backslash = !backslash;
+      if (!backslash)
         break;
+      ++eol;
     }
 
   /* Overwrite the newline char.  */
-  *p = '\0';
-  ebuf->bufnext = p+1;
+  *eol = '\0';
+  ebuf->bufnext = eol+1;
 
   return 0;
Index: branches/GNU/src/gmake/readme.vms
===================================================================
--- branches/GNU/src/gmake/readme.vms	(revision 157)
+++ branches/GNU/src/gmake/readme.vms	(revision 280)
@@ -1,2 +1,54 @@
+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.
+
+Build instructions
+Make a 1st version
+       $ @makefile.com
+       $ rena make.exe 1st-make.exe
+Use the 1st version to generate a 2nd version
+       $ mc sys$disk:[]1st-make clean
+       $ mc sys$disk:[]1st-make
+Verify your 2nd version
+       $ rena make.exe 2nd-make.exe
+       $ mc sys$disk:[]2nd-make clean
+       $ mc sys$disk:[]2nd-make
+
+Changes:
+
+. In default.c define variable ARCH as IA64 for VMS on Itanium systems.
+
+. In makefile.vms avoid name collision for glob and globfree.
+
+In newer version of the VMS CRTL there are glob and globfree implemented.
+Compiling and linking may result in
+
+  %ILINK-W-MULDEFLNKG, symbol DECC$GLOBFREE has subsequent linkage definition
+       in module DECC$SHR file SYS$COMMON:[SYSLIB]DECC$SHR.EXE;1
+  %ILINK-W-MULDEF, symbol DECC$GLOBFREE multiply defined
+       in module DECC$SHR file SYS$COMMON:[SYSLIB]DECC$SHR.EXE;1
+
+linker messages (and similar for DECC$GLOB). The messages just say, that
+globfree is a known CRTL whose name was mapped by the compiler to
+DECC$GLOBFREE.  This is done in glob.c as well, so this name is defined
+twice. One possible solution is to use the VMS versions of glob and
+globfree. However, then the build environment needs to figure out if
+there is a new CRTL supporting these or not. This adds complexity. Even
+more, these functions return VMS file specifications, which is not
+expected by the other make sources. There is a switch at run time (a VMS
+logical DECC$GLOB_UNIX_STYLE), which can be set to get Unix style
+names. This may conflict with other software. The recommended solution
+for this is to set this switch just prior to calling main: in an
+initialization routine. This adds more complexity and more VMS specific
+code. It is easier to tell the compiler NOT to map the routine names
+with a simple change in makefile.vms.
+
+
 This is the VMS port of GNU Make done by Hartmut.Becker@compaq.com.
 
Index: branches/GNU/src/gmake/remake.c
===================================================================
--- branches/GNU/src/gmake/remake.c	(revision 157)
+++ branches/GNU/src/gmake/remake.c	(revision 280)
@@ -75,11 +75,12 @@
 /* Remake all the goals in the `struct dep' chain GOALS.  Return -1 if nothing
    was done, 0 if all goals were updated successfully, or 1 if a goal failed.
-   If MAKEFILES is nonzero, these goals are makefiles, so -t, -q, and -n should
-   be disabled for them unless they were also command-line targets, and we
-   should only make one goal at a time and return as soon as one goal whose
-   `changed' member is nonzero is successfully made.  */
+
+   If rebuilding_makefiles is nonzero, these goals are makefiles, so -t, -q,
+   and -n should be disabled for them unless they were also command-line
+   targets, and we should only make one goal at a time and return as soon as
+   one goal whose `changed' member is nonzero is successfully made.  */
 
 int
-update_goal_chain (struct dep *goals, int makefiles)
+update_goal_chain (struct dep *goals)
 {
   int t = touch_flag, q = question_flag, n = just_print_flag;
@@ -87,5 +88,5 @@
   int status = -1;
 
-#define	MTIME(file) (makefiles ? file_mtime_no_search (file) \
+#define	MTIME(file) (rebuilding_makefiles ? file_mtime_no_search (file) \
 		     : file_mtime (file))
 
@@ -137,5 +138,5 @@
 	      int x;
 	      check_renamed (file);
-	      if (makefiles)
+	      if (rebuilding_makefiles)
 		{
 		  if (file->cmd_target)
@@ -154,5 +155,5 @@
 	      ocommands_started = commands_started;
 
-	      x = update_file (file, makefiles ? 1 : 0);
+	      x = update_file (file, rebuilding_makefiles ? 1 : 0);
 	      check_renamed (file);
 
@@ -177,6 +178,6 @@
                          matter how much more we run, since we already know
                          the answer to return.  */
-                      stop = (!keep_going_flag && !question_flag
-                              && !makefiles);
+                      stop = (question_flag && !keep_going_flag
+                              && !rebuilding_makefiles);
                     }
                   else
@@ -194,8 +195,8 @@
                              If STATUS is changed, we will get re-exec'd, and
                              enter an infinite loop.  */
-                          if (!makefiles
+                          if (!rebuilding_makefiles
                               || (!just_print_flag && !question_flag))
                             status = 0;
-                          if (makefiles && file->dontcare)
+                          if (rebuilding_makefiles && file->dontcare)
                             /* This is a default makefile; stop remaking.  */
                             stop = 1;
@@ -220,5 +221,5 @@
 		 print a message saying nothing needs doing.  */
 
-	      if (!makefiles
+	      if (!rebuilding_makefiles
 		  /* If the update_status is zero, we updated successfully
 		     or not at all.  G->changed will have been set above if
@@ -259,5 +260,5 @@
     }
 
-  if (makefiles)
+  if (rebuilding_makefiles)
     {
       touch_flag = t;
@@ -309,6 +310,7 @@
       check_renamed (f);
 
+      /* If we got an error, don't bother with double_colon etc.  */
       if (status != 0 && !keep_going_flag)
-	break;
+	return status;
 
       if (f->command_state == cs_running
@@ -324,17 +326,42 @@
   /* Process the remaining rules in the double colon chain so they're marked
      considered.  Start their prerequisites, too.  */
-  for (; f != 0 ; f = f->prev)
-    {
-      struct dep *d;
-
-      f->considered = considered;
-
-      for (d = f->deps; d != 0; d = d->next)
-        status |= update_file (d->file, depth + 1);
-    }
+  if (file->double_colon)
+    for (; f != 0 ; f = f->prev)
+      {
+        struct dep *d;
+
+        f->considered = considered;
+
+        for (d = f->deps; d != 0; d = d->next)
+          status |= update_file (d->file, depth + 1);
+      }
 
   return status;
 }
 
+
+/* Show a message stating the target failed to build.  */
+
+static void
+complain (const struct file *file)
+{
+  const char *msg_noparent
+    = _("%sNo rule to make target `%s'%s");
+  const char *msg_parent
+    = _("%sNo rule to make target `%s', needed by `%s'%s");
+
+  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, ".");
+}
 
 /* Consider a single `struct file' and update it as appropriate.  */
@@ -357,4 +384,15 @@
 	  DBF (DB_VERBOSE,
                _("Recently tried and failed to update file `%s'.\n"));
+
+          /* If the file we tried to make is marked dontcare 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;
+              complain (file);
+            }
+
 	  return file->update_status;
 	}
@@ -435,4 +473,5 @@
       FILE_TIMESTAMP mtime;
       int maybe_make;
+      int dontcare = 0;
 
       check_renamed (d->file);
@@ -458,5 +497,19 @@
       d->file->parent = file;
       maybe_make = must_make;
+
+      /* Inherit dontcare flag from our parent. */
+      if (rebuilding_makefiles)
+        {
+          dontcare = d->file->dontcare;
+          d->file->dontcare = file->dontcare;
+        }
+
+
       dep_status |= check_dep (d->file, depth, this_mtime, &maybe_make);
+
+      /* Restore original dontcare flag. */
+      if (rebuilding_makefiles)
+        d->file->dontcare = dontcare;
+
       if (! d->ignore_mtime)
         must_make = maybe_make;
@@ -495,8 +548,24 @@
 	if (d->file->intermediate)
 	  {
+            int dontcare = 0;
+
 	    FILE_TIMESTAMP mtime = file_mtime (d->file);
 	    check_renamed (d->file);
 	    d->file->parent = file;
+
+            /* Inherit dontcare flag from our parent. */
+            if (rebuilding_makefiles)
+              {
+                dontcare = d->file->dontcare;
+                d->file->dontcare = file->dontcare;
+              }
+
+
 	    dep_status |= update_file (d->file, depth);
+
+            /* Restore original dontcare flag. */
+            if (rebuilding_makefiles)
+              d->file->dontcare = dontcare;
+
 	    check_renamed (d->file);
 
@@ -846,8 +915,8 @@
   start_updating (file);
 
-  if (!file->intermediate)
-    /* If this is a non-intermediate file, update it and record
-       whether it is newer than THIS_MTIME.  */
-    {
+  if (file->phony || !file->intermediate)
+    {
+      /* If this is a non-intermediate file, update it and record
+         whether it is newer than THIS_MTIME.  */
       FILE_TIMESTAMP mtime;
       dep_status = update_file (file, depth);
@@ -1016,26 +1085,7 @@
       else
         {
-          const char *msg_noparent
-            = _("%sNo rule to make target `%s'%s");
-          const char *msg_parent
-            = _("%sNo rule to make target `%s', needed by `%s'%s");
-
           /* This is a dependency file we cannot remake.  Fail.  */
-          if (!keep_going_flag && !file->dontcare)
-            {
-              if (file->parent == 0)
-                fatal (NILF, msg_noparent, "", file->name, "");
-
-              fatal (NILF, msg_parent, "", file->name, file->parent->name, "");
-            }
-
-          if (!file->dontcare)
-            {
-              if (file->parent == 0)
-                error (NILF, msg_noparent, "*** ", file->name, ".");
-              else
-                error (NILF, msg_parent, "*** ",
-                       file->name, file->parent->name, ".");
-            }
+          if (!rebuilding_makefiles || !file->dontcare)
+            complain (file);
           file->update_status = 2;
         }
@@ -1273,7 +1323,14 @@
 /* Return the mtime of the file or archive-member reference NAME.  */
 
+/* First, we check with stat().  If the file does not exist, then we return
+   NONEXISTENT_MTIME.  If it does, and the symlink check flag is set, then
+   examine each indirection of the symlink and find the newest mtime.
+   This causes one duplicate stat() when -L is being used, but the code is
+   much cleaner.  */
+
 static FILE_TIMESTAMP
 name_mtime (char *name)
 {
+  FILE_TIMESTAMP mtime;
   struct stat st;
   int e;
@@ -1283,9 +1340,75 @@
     {
       if (errno != ENOENT && errno != ENOTDIR)
-        perror_with_name ("stat:", name);
+        perror_with_name ("stat: ", name);
       return NONEXISTENT_MTIME;
     }
-
-  return FILE_TIMESTAMP_STAT_MODTIME (name, st);
+  mtime = FILE_TIMESTAMP_STAT_MODTIME (name, st);
+
+#ifdef MAKE_SYMLINKS
+#ifndef S_ISLNK
+# define S_ISLNK(_m)     (((_m)&S_IFMT)==S_IFLNK)
+#endif
+  if (check_symlink_flag)
+    {
+      PATH_VAR (lpath);
+
+      /* Check each symbolic link segment (if any).  Find the latest mtime
+         amongst all of them (and the target file of course).
+         Note that we have already successfully dereferenced all the links
+         above.  So, if we run into any error trying to lstat(), or
+         readlink(), or whatever, something bizarre-o happened.  Just give up
+         and use whatever mtime we've already computed at that point.  */
+      strcpy (lpath, name);
+      while (1)
+        {
+          FILE_TIMESTAMP ltime;
+          PATH_VAR (lbuf);
+          long llen;
+          char *p;
+
+          EINTRLOOP (e, lstat (lpath, &st));
+          if (e)
+            {
+              /* Eh?  Just take what we have.  */
+              perror_with_name ("lstat: ", lpath);
+              break;
+            }
+
+          /* If this is not a symlink, we're done (we started with the real
+             file's mtime so we don't need to test it again).  */
+          if (!S_ISLNK (st.st_mode))
+            break;
+
+          /* If this mtime is newer than what we had, keep the new one.  */
+          ltime = FILE_TIMESTAMP_STAT_MODTIME (lpath, st);
+          if (ltime > mtime)
+            mtime = ltime;
+
+          /* Set up to check the file pointed to by this link.  */
+          EINTRLOOP (llen, readlink (lpath, lbuf, GET_PATH_MAX));
+          if (llen < 0)
+            {
+              /* Eh?  Just take what we have.  */
+              perror_with_name ("readlink: ", lpath);
+              break;
+            }
+          lbuf[llen] = '\0';
+
+          /* If the target is fully-qualified or the source is just a
+             filename, then the new path is the target.  Otherwise it's the
+             source directory plus the target.  */
+          if (lbuf[0] == '/' || (p = strrchr (lpath, '/')) == NULL)
+            strcpy (lpath, lbuf);
+          else if ((p - lpath) + llen + 2 > GET_PATH_MAX)
+            /* Eh?  Path too long!  Again, just go with what we have.  */
+            break;
+          else
+            /* Create the next step in the symlink chain.  */
+            strcpy (p+1, lbuf);
+        }
+    }
+#endif
+
+  return mtime;
 }
 
Index: branches/GNU/src/gmake/rule.c
===================================================================
--- branches/GNU/src/gmake/rule.c	(revision 157)
+++ branches/GNU/src/gmake/rule.c	(revision 280)
@@ -138,18 +138,4 @@
 
 	      dep->changed = !dir_file_exists_p (name, "");
-#ifdef VMS
-              if (dep->changed && strchr (name, ':') != 0)
-#else
-	      if (dep->changed && *name == '/')
-#endif
-		{
-		  /* The name is absolute and the directory does not exist.
-		     This rule can never possibly match, since this dependency
-		     can never possibly exist.  So just remove the rule from
-		     the list.  */
-		  freerule (rule, lastrule);
-		  --num_pattern_rules;
-		  goto end_main_loop;
-		}
 	    }
 	  else
@@ -162,5 +148,4 @@
 
       lastrule = rule;
-    end_main_loop:
       rule = next;
     }
@@ -225,4 +210,5 @@
       deps->name = depname;
       deps->ignore_mtime = 0;
+      deps->need_2nd_expansion = 0;
     }
 
Index: branches/GNU/src/gmake/signame.c
===================================================================
--- branches/GNU/src/gmake/signame.c	(revision 157)
+++ branches/GNU/src/gmake/signame.c	(revision 280)
@@ -28,5 +28,5 @@
  */
 
-#if !defined(SYS_SIGLIST_DECLARED)
+#if !defined(HAVE_DECL_SYS_SIGLIST)
 
 /* Some systems do not define NSIG in <signal.h>.  */
@@ -227,5 +227,5 @@
 }
 
-#endif  /* SYS_SIGLIST_DECLARED */
+#endif  /* HAVE_DECL_SYS_SIGLIST */
 
 
@@ -235,5 +235,5 @@
   static char buf[] = "Signal 12345678901234567890";
 
-#if !defined(SYS_SIGLIST_DECLARED)
+#if ! HAVE_DECL_SYS_SIGLIST
   static char sig_initted = 0;
 
Index: branches/GNU/src/gmake/tests/ChangeLog
===================================================================
--- branches/GNU/src/gmake/tests/ChangeLog	(revision 157)
+++ branches/GNU/src/gmake/tests/ChangeLog	(revision 280)
@@ -1,2 +1,174 @@
+2005-05-13  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/features/conditionals: Add tests for the new if... else
+	if... endif syntax.
+
+2005-05-03  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/variables/DEFAULT_GOAL: Rename DEFAULT_TARGET to
+	DEFAULT_GOAL.
+
+2005-05-02  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/features/parallelism: Add a test for exporting recursive
+	variables containing $(shell ) calls.  Rewrite this script to use
+	run_make_test() everywhere.
+
+2005-04-07  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/targets/SECONDARY: Add a test for Savannah bug #12331.
+
+2005-03-15  Boris Kolpackov  <boris@kolpackov.net>
+
+	* scripts/variables/automatic: Add a test for Savannah bug #12320.
+
+2005-03-10  Boris Kolpackov  <boris@kolpackov.net>
+
+	* scripts/features/patternrules: Add a test for Savannah bug #12267.
+
+2005-03-09  Boris Kolpackov  <boris@kolpackov.net>
+
+	* scripts/variables/DEFAULT_TARGET: Add a test for Savannah
+	bug #12266.
+
+2005-03-04  Boris Kolpackov  <boris@kolpackov.net>
+
+	* scripts/features/patternrules: Add a test for Savannah bug #12202.
+
+2005-03-03  Boris Kolpackov  <boris@kolpackov.net>
+
+	* scripts/features/se_implicit: Add a test for stem
+	termination bug. Add a test for stem triple-expansion bug.
+
+	* scripts/features/se_statpat: Add a test for stem
+	triple-expansion bug.
+
+	* scripts/features/statipattrules: Change test #4 to reflect
+	new way empty prerequisite list is handled.
+
+
+2005-03-01  Boris Kolpackov  <boris@kolpackov.net>
+
+	* scripts/features/statipattrules: Add a test for
+	Savannah bug #12180.
+
+2005-02-28  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/options/dash-q: Add a test for Savannah bug # 7144.
+
+	* scripts/options/symlinks: New file to test checking of symlink
+	timestamps.  Can't use filename dash-L because it conflicts with
+	dash-l on case-insensitive filesystems.
+
+	* scripts/variables/MAKEFILE_LIST, scripts/variables/MFILE_LIST:
+	Rename MAKEFILE_LIST test to MFILE_LIST, for systems that need 8.3
+	unique filenames.
+
+2005-02-28  Boris Kolpackov  <boris@kolpackov.net>
+
+	* scripts/variables/DEFAULT_TARGET: Test the .DEFAULT_TARGET
+	special variable.
+
+2005-02-27  Boris Kolpackov  <boris@kolpackov.net>
+
+	* scripts/features/se_explicit: Test the second expansion in
+	explicit rules.
+	* scripts/features/se_implicit: Test the second expansion in
+	implicit rules.
+	* scripts/features/se_statpat: Test the second expansion in
+	static pattern rules.
+	* scripts/variables/automatic: Fix to work with the second
+	expansion.
+
+	* scripts/misc/general4: Add a test for bug #12091.
+
+2005-02-27  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/functions/eval: Check that eval of targets within
+	command scripts fails.  See Savannah bug # 12124.
+
+2005-02-26  Paul D. Smith  <psmith@gnu.org>
+
+	* test_driver.pl (compare_output): If a basic comparison of the
+	log and answer doesn't match, try harder: change all backslashes
+	to slashes and all CRLF to LF.  This helps on DOS/Windows systems.
+
+2005-02-09  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/features/recursion: Test command line variable settings:
+	only one instance of a given variable should be provided.
+
+2004-11-30  Boris Kolpackov  <boris@kolpackov.net>
+
+	* tests/scripts/functions/abspath: New file: test `abspath'
+	built-in function.
+
+	* tests/scripts/functions/realpath: New file: test `realpath'
+	built-in function.
+
+2004-11-28  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/options/dash-C [WINDOWS32]: Add a test for bug #10252;
+	this doesn't really test anything useful in UNIX but...
+
+	* scripts/variables/SHELL: New file: test proper handling of SHELL
+	according to POSIX rules.  Fixes bug #1276.
+
+2004-10-21  Boris Kolpackov  <boris@kolpackov.net>
+
+	* scripts/functions/word: Test $(firstword ) and $(lastword ).
+
+2004-10-05  Boris Kolpackov  <boris@kolpackov.net>
+
+	* scripts/features/patspecific_vars: Test simple/recursive
+	variable expansion.
+
+2004-09-28  Boris Kolpackov  <boris@kolpackov.net>
+
+	* scripts/features/include: Test dontcare flag inheritance
+	when rebuilding makefiles.
+
+2004-09-27  Boris Kolpackov  <boris@kolpackov.net>
+
+	* scripts/features/patspecific_vars: Test exported variables.
+
+2004-09-22  Paul D. Smith  <psmith@gnu.org>
+
+	* run_make_tests.pl (run_make_test): Don't add newlines to the
+	makestring or answer if they are completely empty.
+
+	* scripts/features/patternrules: Rename from implicit_prereq_eval.
+
+	* scripts/test_template: Rework the template.
+
+2004-09-21  Boris Kolpackov  <boris@kolpackov.net>
+
+	* run_make_tests.pl: Change `#!/usr/local/bin/perl' to be
+	`#!/usr/bin/env perl'.
+
+	* scripts/features/implicit_prereq_eval: Test implicit rule
+	prerequisite evaluation code.
+
+2004-09-21  Paul D. Smith  <psmith@gnu.org>
+
+	* run_make_tests.pl (run_make_test): Enhance to allow the make
+	string to be undef: in that case it reuses the previous make
+	string.  Allows multiple tests on the same makefile.
+
+	* scripts/variables/flavors: Add some tests for prefix characters
+	interacting with define/endef variables.
+
+2004-09-20  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/functions/substitution: Rewrite to use run_make_test()
+	interface, and add test for substitution failures reported by
+	Markus Mauhart <qwe123@chello.at>.
+
+2004-03-22  Paul D. Smith  <psmith@gnu.org>
+
+	* test_driver.pl (run_each_test, toplevel, compare_output): Change
+	to track both the testing categories _AND_ the number of
+	individual tests, and report both sets of numbers.
+
 2004-02-21  Paul D. Smith  <psmith@gnu.org>
 
Index: branches/GNU/src/gmake/tests/run_make_tests.pl
===================================================================
--- branches/GNU/src/gmake/tests/run_make_tests.pl	(revision 157)
+++ branches/GNU/src/gmake/tests/run_make_tests.pl	(revision 280)
@@ -1,3 +1,3 @@
-#!/usr/local/bin/perl
+#!/usr/bin/env perl
 # -*-perl-*-
 
@@ -13,4 +13,5 @@
 
 $valgrind = 0;              # invoke make with valgrind
+$pure_log = undef;
 
 require "test_driver.pl";
@@ -38,5 +39,5 @@
    }
 
-# This doesn't work--it _should_!  Someone needs to fix this badly.
+# This doesn't work--it _should_!  Someone badly needs to fix this.
 #
 #   elsif ($option =~ /^-work([-_]?dir)?$/)
@@ -49,64 +50,121 @@
 }
 
-sub run_make_with_options
-{
-   local ($filename,$options,$logname,$expected_code) = @_;
-   local($code);
-   local($command) = $make_path;
-
-   $expected_code = 0 unless defined($expected_code);
-
-   if ($filename)
-   {
-      $command .= " -f $filename";
-   }
-
-   if ($options)
-   {
-      $command .= " $options";
-   }
-
-   if ($valgrind) {
-     print VALGRIND "\n\nExecuting: $command\n";
-   }
-
-   $code = &run_command_with_output($logname,$command);
-
-   # Check to see if we have Purify errors.  If so, keep the logfile.
-   # For this to work you need to build with the Purify flag -exit-status=yes
-
-   if ($pure_log && -f $pure_log) {
-     if ($code & 0x7000) {
-       $code &= ~0x7000;
-
-       # If we have a purify log, save it
-       $tn = $pure_testname . ($num_of_logfiles ? ".$num_of_logfiles" : "");
-       print("Renaming purify log file to $tn\n") if $debug;
-       rename($pure_log, "$tn")
-	 || die "Can't rename $log to $tn: $!\n";
-       ++$purify_errors;
-     }
-     else {
-       unlink($pure_log);
-     }
-   }
-
-   if ($code != $expected_code)
-   {
-      print "Error running $make_path ($code): $command\n";
-      $test_passed = 0;
-      # If it's a SIGINT, stop here
-      if ($code & 127) {
-        print STDERR "\nCaught signal ".($code & 127)."!\n";
-        exit($code);
-      }
-      return 0;
-   }
-
-   if ($profile & $vos)
-   {
-      system "add_profile $make_path";
-   }
-1;
+
+# This is an "all-in-one" function.  Arguments are as follows:
+#
+#  [0] (string):  The makefile to be tested.  undef means use the last one.
+#  [1] (string):  Arguments to pass to make.
+#  [2] (string):  Answer we should get back.
+#  [3] (integer): Exit code we expect.  A missing code means 0 (success)
+
+$old_makefile = undef;
+
+sub run_make_test
+{
+  local ($makestring, $options, $answer, $err_code) = @_;
+
+  # If the user specified a makefile string, create a new makefile to contain
+  # it.  If the first value is not defined, use the last one (if there is
+  # one).
+
+  if (! defined $makestring) {
+    defined $old_makefile
+      || die "run_make_test(undef) invoked before run_make_test('...')\n";
+    $makefile = $old_makefile;
+  } else {
+    if (! defined($makefile)) {
+      $makefile = &get_tmpfile();
+    }
+
+    # Make sure it ends in a newline.
+    $makestring && $makestring !~ /\n$/s and $makestring .= "\n";
+
+    # Replace @MAKEFILE@ with the makefile name and @MAKE@ with the path to
+    # make
+    $makestring =~ s/#MAKEFILE#/$makefile/g;
+    $makestring =~ s/#MAKEPATH#/$mkpath/g;
+    $makestring =~ s/#MAKE#/$make_name/g;
+    $makestring =~ s/#PWD#/$pwd/g;
+
+    # Populate the makefile!
+    open(MAKEFILE, "> $makefile") || die "Failed to open $makefile: $!\n";
+    print MAKEFILE $makestring;
+    close(MAKEFILE) || die "Failed to write $makefile: $!\n";
+  }
+
+  # Do the same processing on $answer as we did on $makestring.
+
+  $answer && $answer !~ /\n$/s and $answer .= "\n";
+  $answer =~ s/#MAKEFILE#/$makefile/g;
+  $answer =~ s/#MAKEPATH#/$mkpath/g;
+  $answer =~ s/#MAKE#/$make_name/g;
+  $answer =~ s/#PWD#/$pwd/g;
+
+  &run_make_with_options($makefile, $options, &get_logfile(0), $err_code);
+  &compare_output($answer, &get_logfile(1));
+
+  $old_makefile = $makefile;
+  $makefile = undef;
+}
+
+# The old-fashioned way...
+sub run_make_with_options {
+  local ($filename,$options,$logname,$expected_code) = @_;
+  local($code);
+  local($command) = $make_path;
+
+  $expected_code = 0 unless defined($expected_code);
+
+  # Reset to reflect this one test.
+  $test_passed = 1;
+
+  if ($filename) {
+    $command .= " -f $filename";
+  }
+
+  if ($options) {
+    $command .= " $options";
+  }
+
+  if ($valgrind) {
+    print VALGRIND "\n\nExecuting: $command\n";
+  }
+
+  $code = &run_command_with_output($logname,$command);
+
+  # Check to see if we have Purify errors.  If so, keep the logfile.
+  # For this to work you need to build with the Purify flag -exit-status=yes
+
+  if ($pure_log && -f $pure_log) {
+    if ($code & 0x7000) {
+      $code &= ~0x7000;
+
+      # If we have a purify log, save it
+      $tn = $pure_testname . ($num_of_logfiles ? ".$num_of_logfiles" : "");
+      print("Renaming purify log file to $tn\n") if $debug;
+      rename($pure_log, "$tn")
+        || die "Can't rename $log to $tn: $!\n";
+      ++$purify_errors;
+    } else {
+      unlink($pure_log);
+    }
+  }
+
+  if ($code != $expected_code) {
+    print "Error running $make_path (expected $expected_code; got $code): $command\n";
+    $test_passed = 0;
+    # If it's a SIGINT, stop here
+    if ($code & 127) {
+      print STDERR "\nCaught signal ".($code & 127)."!\n";
+      exit($code);
+    }
+    return 0;
+  }
+
+  if ($profile & $vos) {
+    system "add_profile $make_path";
+  }
+
+  1;
 }
 
@@ -159,5 +217,5 @@
    # This is probably not specific enough.
    #
-   if ($osname =~ /Windows/i) {
+   if ($osname =~ /Windows/i || $osname =~ /MINGW32/i) {
      $port_type = 'W32';
    }
@@ -184,10 +242,11 @@
    # timestamps with second granularity (!!).  Change the sleep time
    # needed to force a file to be considered "old".
-   #
    $wtime = $port_type eq 'UNIX' ? 1 : $port_type eq 'OS/2' ? 2 : 4;
+
+   print "Port type: $port_type\n" if $debug;
+   print "Make path: $make_path\n" if $debug;
 
    # Find the full pathname of Make.  For DOS systems this is more
    # complicated, so we ask make itself.
-
    $make_path = `sh -c 'echo "all:;\@echo \\\$(MAKE)" | $make_path -f-'`;
    chop $make_path;
@@ -227,8 +286,10 @@
    # Get Purify log info--if any.
 
-   $ENV{PURIFYOPTIONS} =~ /.*-logfile=([^ ]+)/;
-   $pure_log = $1 || '';
-   $pure_log =~ s/%v/$make_name/;
-   $purify_errors = 0;
+   if (exists $ENV{PURIFYOPTIONS}
+       && $ENV{PURIFYOPTIONS} =~ /.*-logfile=([^ ]+)/) {
+     $pure_log = $1 || '';
+     $pure_log =~ s/%v/$make_name/;
+     $purify_errors = 0;
+   }
 
    $string = `sh -c "$make_path -j 2 -f /dev/null 2>&1"`;
Index: branches/GNU/src/gmake/tests/scripts/features/conditionals
===================================================================
--- branches/GNU/src/gmake/tests/scripts/features/conditionals	(revision 157)
+++ branches/GNU/src/gmake/tests/scripts/features/conditionals	(revision 280)
@@ -4,10 +4,5 @@
 $details = "Attempt various different flavors of GNU make conditionals.";
 
-open(MAKEFILE,"> $makefile");
-
-# The Contents of the MAKEFILE ...
-
-print MAKEFILE <<'EOMAKE';
-objects = foo.obj
+run_make_test('
 arg1 = first
 arg2 = second
@@ -23,5 +18,5 @@
 endif
 
-ifeq '$(arg2)' "$(arg5)"
+ifeq \'$(arg2)\' "$(arg5)"
 	@echo arg2 equals arg5
 else
@@ -29,5 +24,5 @@
 endif
 
-ifneq '$(arg3)' '$(arg4)'
+ifneq \'$(arg3)\' \'$(arg4)\'
 	@echo arg3 NOT equal arg4
 else
@@ -44,30 +39,16 @@
 else
 	@echo arg4 is NOT defined
-endif
-
-EOMAKE
-
-close(MAKEFILE);
-
-&run_make_with_options($makefile,"",&get_logfile,0);
-
-$answer = "arg1 NOT equal arg2
+endif',
+              '',
+              'arg1 NOT equal arg2
 arg2 equals arg5
 arg3 NOT equal arg4
 variable is undefined
-arg4 is defined
-";
-
-&compare_output($answer,&get_logfile(1));
+arg4 is defined');
 
 
 # Test expansion of variables inside ifdef.
 
-$makefile2 = &get_tmpfile;
-
-open(MAKEFILE, "> $makefile2");
-
-print MAKEFILE <<'EOF';
-
+run_make_test('
 foo = 1
 
@@ -93,13 +74,71 @@
 endif
 
-all:; @echo DEF=$(DEF) DEF2=$(DEF2) DEF3=$(DEF3)
+all:; @echo DEF=$(DEF) DEF2=$(DEF2) DEF3=$(DEF3)',
+              '',
+              'DEF=yes DEF2=yes DEF3=yes');
 
-EOF
 
-close(MAKEFILE)
+# Test all the different "else if..." constructs
 
-&run_make_with_options($makefile2,"",&get_logfile,0);
-$answer = "DEF=yes DEF2=yes DEF3=yes\n";
-&compare_output($answer,&get_logfile(1));
+run_make_test('
+arg1 = first
+arg2 = second
+arg3 = third
+arg4 = cc
+arg5 = fifth
+
+result =
+
+ifeq ($(arg1),$(arg2))
+  result += arg1 equals arg2
+else ifeq \'$(arg2)\' "$(arg5)"
+  result += arg2 equals arg5
+else ifneq \'$(arg3)\' \'$(arg3)\'
+  result += arg3 NOT equal arg4
+else ifndef arg5
+  result += variable is undefined
+else ifdef undefined
+  result += arg4 is defined
+else
+  result += success
+endif
+
+
+all: ; @echo $(result)',
+              '',
+              'success');
+
+
+# Test some random "else if..." construct nesting
+
+run_make_test('
+arg1 = first
+arg2 = second
+arg3 = third
+arg4 = cc
+arg5 = second
+
+ifeq ($(arg1),$(arg2))
+  $(info failed 1)
+else ifeq \'$(arg2)\' "$(arg2)"
+  ifdef undefined
+    $(info failed 2)
+  else
+    $(info success)
+  endif
+else ifneq \'$(arg3)\' \'$(arg3)\'
+  $(info failed 3)
+else ifdef arg5
+  $(info failed 4)
+else ifdef undefined
+  $(info failed 5)
+else
+  $(info failed 6)
+endif
+
+.PHONY: all
+all: ; @:',
+              '',
+              'success');
 
 
Index: branches/GNU/src/gmake/tests/scripts/features/echoing
===================================================================
--- branches/GNU/src/gmake/tests/scripts/features/echoing	(revision 157)
+++ branches/GNU/src/gmake/tests/scripts/features/echoing	(revision 280)
@@ -55,11 +55,8 @@
 
 &run_make_with_options($makefile,"clean",&get_logfile,0);
-$answer = "";
-&compare_output($answer,&get_logfile(1));
-
-if (-f $example)
-{
-   $test_passed = 0;
+if (-f $example) {
+  $test_passed = 0;
 }
+&compare_output('',&get_logfile(1));
 
 # TEST #3
Index: branches/GNU/src/gmake/tests/scripts/features/errors
===================================================================
--- branches/GNU/src/gmake/tests/scripts/features/errors	(revision 157)
+++ branches/GNU/src/gmake/tests/scripts/features/errors	(revision 280)
@@ -53,4 +53,11 @@
 &run_make_with_options($makefile,"",&get_logfile);
 
+# If make acted as planned, it should ignore the error from the first
+# command in the target and execute the second which deletes the file "foo"
+# This file, therefore, should not exist if the test PASSES.
+if (-f "foo") {
+  $test_passed = 0;
+}
+
 # The output for this on VOS is too hard to replicate, so we only check it
 # on unix.
@@ -58,12 +65,4 @@
 {
    &compare_output($answer,&get_logfile(1));
-}
-
-# If make acted as planned, it should ignore the error from the first
-# command in the target and execute the second which deletes the file "foo"
-# This file, therefore, should not exist if the test PASSES.
-if (-f "foo")
-{
-   $test_passed = 0;
 }
 
@@ -81,13 +80,11 @@
 &run_make_with_options($makefile,"clean2 -i",&get_logfile);
 
-if (!$vos)
-{
+if (-f "foo") {
+  $test_passed = 0;
+}
+
+if (!$vos) {
    &compare_output($answer,&get_logfile(1));
 }
 
-if (-f "foo")
-{
-   $test_passed = 0;
-}
-
 1;
Index: branches/GNU/src/gmake/tests/scripts/test_template
===================================================================
--- branches/GNU/src/gmake/tests/scripts/test_template	(revision 157)
+++ branches/GNU/src/gmake/tests/scripts/test_template	(revision 280)
@@ -1,63 +1,22 @@
-$description = "The following test creates a makefile to ...
-                     <FILL IN DESCRIPTION HERE> ";
+#                                                                    -*-perl-*-
 
+$description = "<FILL IN SHORT DESCRIPTION HERE>";
 $details = "<FILL IN DETAILS OF HOW YOU TEST WHAT YOU SAY YOU ARE TESTING>";
 
-# IF YOU NEED >1 MAKEFILE FOR THIS TEST, USE &get_tmpfile; TO GET
-# THE NAME OF THE MAKEFILE.  THIS INSURES CONSISTENCY AND KEEPS TRACK OF
-# HOW MANY MAKEFILES EXIST FOR EASY DELETION AT THE END.
-# EXAMPLE: $makefile2 = &get_tmpfile;
+# Run a make test.  See the documentation of run_make_test() in
+# run_make_tests.pl, but briefly the first argument is a string with the
+# contents of a makefile to be tested, the second is a string containing the
+# arguments to be passed to the make invocation, the third is a string
+# containing the expected output.  The fourth is the expected exit code for
+# make.  If not specified, it's assumed that the make program should succeed
+# (exit with 0).
 
-open(MAKEFILE,"> $makefile");
+run_make_test('Your test makefile goes here',
+              'Arguments to pass to make go here',
+              'Expected output from the invocation goes here');
 
-# The Contents of the MAKEFILE ...
+# There are various special tokens, options, etc.  See the full documentation
+# in run_make_tests.pl.
 
-print MAKEFILE " <FILL IN THE CONTENTS OF THE MAKEFILE HERE>  \n";
-
-# END of Contents of MAKEFILE
-
-close(MAKEFILE);
-
-
-# Run make.  You may specify a makefile, but if you don't want to, just
-# insert "" where $make_filename is now.  You may also specify specific
-# options to run make with, but you also don't have to. (Insert "" where it 
-# says <FILL IN OPTIONS HERE>), The last field in this subroutine call
-# is the code which is returned from make.  If you think that make should
-# execute with no errors, you may OPTIONALLY put 0; Otherwise put the 
-# error code that you expect back from make for this test.
-
-# Every time you run make, you just need to say &get_logfile and that
-# subroutine will get a new logfile name for you in incrementing order
-# according to how many times you call it within ONE test.  It is 
-# reset to 0 at the beginning of every new test script.
-
-&run_make_with_options($makefile,
-                       "<FILL IN OPTIONS HERE>",
-                       &get_logfile,
-                       0);
-
-
-# THE REST OF THIS FILE DEPENDS HIGHLY ON WHAT KIND OF TEST YOU ARE
-# CREATING, SO IT WILL VARY.  BASICALLY, YOU MAY INSERT ANYTHING YOU 
-# WISH AT THIS POINT TO SEE IF THE TEST WORKED OK.  IF THERE ARE 
-# ADDITIONAL TESTS BESIDES &compare_output, AND IT FAILES, YOU
-# MUST *** SET $test_passed = 0 !!! ***
-
-# Create the answer to what should be produced by this Makefile
-$answer = "<INSERT ANSWER HERE>";
-
-# COMPARE RESULTS
-
-# In this call to compare output, you should use the call &get_logfile(1)
-# to send the name of the last logfile created.  You may also use
-# the special call &get_logfile(1) which returns the same as &get_logfile(1).
-
-&compare_output($answer,&get_logfile(1));
-
-# If you wish to &error ("abort
-") if the compare fails, then add a "|| &error ("abort
-")" to the
-# end of the previous line.
 
 # This tells the test driver that the perl test script executed properly.
Index: branches/GNU/src/gmake/tests/test_driver.pl
===================================================================
--- branches/GNU/src/gmake/tests/test_driver.pl	(revision 157)
+++ branches/GNU/src/gmake/tests/test_driver.pl	(revision 280)
@@ -1,3 +1,3 @@
-#!/usr/local/bin/perl
+#!/usr/bin/perl
 # -*-perl-*-
 
@@ -12,4 +12,24 @@
 # this routine controls the whole mess; each test suite sets up a few
 # variables and then calls &toplevel, which does all the real work.
+
+# $Id: test_driver.pl,v 1.14 2005/02/28 07:48:23 psmith Exp $
+
+
+# The number of test categories we've run
+$categories_run = 0;
+# The number of test categroies that have passed
+$categories_passed = 0;
+# The total number of individual tests that have been run
+$total_tests_run = 0;
+# The total number of individual tests that have passed
+$total_tests_passed = 0;
+# The number of tests in this category that have been run
+$tests_run = 0;
+# The number of tests in this category that have passed
+$tests_passed = 0;
+
+
+# Yeesh.  This whole test environment is such a hack!
+$test_passed = 1;
 
 sub toplevel
@@ -151,8 +171,13 @@
   $| = 1;
 
-  if ($num_failed)
-  {
-    print "\n$num_failed Test";
-    print "s" unless $num_failed == 1;
+  $categories_failed = $categories_run - $categories_passed;
+  $total_tests_failed = $total_tests_run - $total_tests_passed;
+
+  if ($total_tests_failed)
+  {
+    print "\n$total_tests_failed Test";
+    print "s" unless $total_tests_failed == 1;
+    print " in $categories_failed Categor";
+    print ($categories_failed == 1 ? "y" : "ies");
     print " Failed (See .$diffext files in $workdir dir for details) :-(\n\n";
     return 0;
@@ -160,6 +185,8 @@
   else
   {
-    print "\n$counter Test";
-    print "s" unless $counter == 1;
+    print "\n$total_tests_passed Test";
+    print "s" unless $total_tests_passed == 1;
+    print " in $categories_passed Categor";
+    print ($categories_passed == 1 ? "y" : "ies");
     print " Complete ... No Failures :-)\n\n";
     return 1;
@@ -349,14 +376,15 @@
 sub run_each_test
 {
-  $counter = 0;
+  $categories_run = 0;
 
   foreach $testname (sort @TESTS)
   {
-    $counter++;
-    $test_passed = 1;       # reset by test on failure
+    ++$categories_run;
+    $suite_passed = 1;       # reset by test on failure
     $num_of_logfiles = 0;
     $num_of_tmpfiles = 0;
     $description = "";
     $details = "";
+    $old_makefile = undef;
     $testname =~ s/^$scriptpath$pathsep//;
     $perl_testname = "$scriptpath$pathsep$testname";
@@ -391,9 +419,15 @@
 
     # Run the actual test!
-    #
+    $tests_run = 0;
+    $tests_passed = 0;
     $code = do $perl_testname;
+
+    $total_tests_run += $tests_run;
+    $total_tests_passed += $tests_passed;
+
+    # How did it go?
     if (!defined($code))
     {
-      $test_passed = 0;
+      $suite_passed = 0;
       if (length ($@))
       {
@@ -406,31 +440,31 @@
     }
     elsif ($code == -1) {
-      $test_passed = 0;
+      $suite_passed = 0;
     }
     elsif ($code != 1 && $code != -1) {
-      $test_passed = 0;
+      $suite_passed = 0;
       warn "\n*** Test returned $code\n";
     }
 
-    if ($test_passed) {
-      $status = "ok";
+    if ($suite_passed) {
+      ++$categories_passed;
+      $status = "ok     ($tests_passed passed)";
       for ($i = $num_of_tmpfiles; $i; $i--)
       {
-        &delete ($tmp_filename . &num_suffix ($i) );
+        &rmfiles ($tmp_filename . &num_suffix ($i) );
       }
 
       for ($i = $num_of_logfiles ? $num_of_logfiles : 1; $i; $i--)
       {
-        &delete ($log_filename . &num_suffix ($i) );
-        &delete ($base_filename . &num_suffix ($i) );
+        &rmfiles ($log_filename . &num_suffix ($i) );
+        &rmfiles ($base_filename . &num_suffix ($i) );
       }
     }
     elsif ($code > 0) {
-      $status = "FAILED";
-      $num_failed++;
+      $status = "FAILED ($tests_passed/$tests_run passed)";
     }
     elsif ($code < 0) {
       $status = "N/A";
-      --$counter;
+      --$categories_run;
     }
 
@@ -467,5 +501,5 @@
 # are sent to it.
 
-sub delete
+sub rmfiles
 {
   local(@files) = @_;
@@ -578,10 +612,7 @@
 {
   local($answer,$logfile) = @_;
-  local($slurp);
-
-  if ($debug)
-  {
-    print "Comparing Output ........ ";
-  }
+  local($slurp, $answer_matched) = ('', 0);
+
+  print "Comparing Output ........ " if $debug;
 
   $slurp = &read_file_into_string ($logfile);
@@ -592,31 +623,43 @@
   $slurp =~ s/^.*Clock skew detected.*\n//gm;
 
-  if ($slurp eq $answer)
-  {
-    if ($debug)
-    {
-      print "ok\n";
-    }
+  ++$tests_run;
+
+  if ($slurp eq $answer) {
+    $answer_matched = 1;
+  } else {
+    # See if it is a slash or CRLF problem
+    local ($answer_mod) = $answer;
+
+    $answer_mod =~ tr,\\,/,;
+    $answer_mod =~ s,\r\n,\n,gs;
+
+    $slurp =~ tr,\\,/,;
+    $slurp =~ s,\r\n,\n,gs;
+
+    $answer_matched = ($slurp eq $answer_mod);
+  }
+
+  if ($answer_matched && $test_passed)
+  {
+    print "ok\n" if $debug;
+    ++$tests_passed;
     return 1;
   }
-  else
-  {
-    if ($debug)
-    {
-      print "DIFFERENT OUTPUT\n";
-    }
-    $test_passed = 0;
+
+  if (! $answer_matched) {
+    print "DIFFERENT OUTPUT\n" if $debug;
+
     &create_file (&get_basefile, $answer);
 
-    if ($debug)
-    {
-      print "\nCreating Difference File ...\n";
-    }
+    print "\nCreating Difference File ...\n" if $debug;
+
     # Create the difference file
+
     local($command) = "diff -c " . &get_basefile . " " . $logfile;
     &run_command_with_output(&get_difffile,$command);
-
-    return 0;
-  }
+  }
+
+  $suite_passed = 0;
+  return 0;
 }
 
@@ -702,13 +745,9 @@
   local ($code);
 
-  if ($debug)
-  {
-    print "\nrun_command: @_\n";
-    $code = system @_;
-    print "run_command: \"@_\" returned $code.\n";
-    return $code;
-  }
-
-  return system @_;
+  print "\nrun_command: @_\n" if $debug;
+  $code = system @_;
+  print "run_command: \"@_\" returned $code.\n" if $debug;
+
+  return $code;
 }
 
@@ -726,8 +765,6 @@
   $code = system @_;
   &detach_default_output;
-  if ($debug)
-  {
-    print "run_command_with_output: \"@_\" returned $code.\n";
-  }
+
+  print "run_command_with_output: '@_' returned $code.\n" if $debug;
 
   return $code;
Index: branches/GNU/src/gmake/variable.c
===================================================================
--- branches/GNU/src/gmake/variable.c	(revision 157)
+++ branches/GNU/src/gmake/variable.c	(revision 280)
@@ -500,8 +500,30 @@
 
           do
-            /* We found one, so insert it into the set.  */
-            do_variable_definition (&p->variable.fileinfo, p->variable.name,
-                                    p->variable.value, p->variable.origin,
-                                    p->variable.flavor, 1);
+            {
+              /* We found one, so insert it into the set.  */
+
+              struct variable *v;
+
+              if (p->variable.flavor == f_simple)
+                {
+                  v = define_variable_loc (
+                    p->variable.name, strlen (p->variable.name),
+                    p->variable.value, p->variable.origin,
+                    0, &p->variable.fileinfo);
+
+                  v->flavor = f_simple;
+                }
+              else
+                {
+                  v = do_variable_definition (
+                    &p->variable.fileinfo, p->variable.name,
+                    p->variable.value, p->variable.origin,
+                    p->variable.flavor, 1);
+                }
+
+              /* Also mark it as a per-target and copy export status. */
+              v->per_target = p->variable.per_target;
+              v->export = p->variable.export;
+            }
           while ((p = lookup_pattern_var (p, file->name)) != 0);
 
@@ -727,14 +749,12 @@
 #endif
 
-  /* This won't override any definition, but it
-     will provide one if there isn't one there.  */
+  /* 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->export = v_export;		/* Always export SHELL.  */
-
-  /* On MSDOS we do use SHELL from environment, since
-     it isn't a standard environment variable on MSDOS,
-     so whoever sets it, does that on purpose.
-     On OS/2 we do not use SHELL from environment but
-     we have already handled that problem above. */
+
+  /* On MSDOS we do use SHELL from environment, since it isn't a standard
+     environment variable on MSDOS, so whoever sets it, does that on purpose.
+     On OS/2 we do not use SHELL from environment but we have already handled
+     that problem above. */
 #if !defined(__MSDOS__) && !defined(__EMX__)
   /* Don't let SHELL come from the environment.  */
@@ -854,5 +874,13 @@
 
 	      case v_noexport:
-		continue;
+                /* If this is the SHELL variable and it's not exported, then
+                   add the value from our original environment.  */
+                if (streq (v->name, "SHELL"))
+                  {
+                    extern struct variable shell_var;
+                    v = &shell_var;
+                    break;
+                  }
+                continue;
 
 	      case v_ifset:
@@ -969,4 +997,9 @@
             v = lookup_variable_in_set (varname, strlen (varname),
                                         current_variable_set_list->set);
+
+            /* Don't append from the global set if a previous non-appending
+               target-specific variable definition exists. */
+            if (v && !v->append)
+              append = 0;
           }
         else
@@ -1027,5 +1060,5 @@
       && strcmp (varname, "SHELL") == 0)
     {
-      char shellpath[PATH_MAX];
+      PATH_VAR (shellpath);
       extern char * __dosexec_find_on_path (const char *, char *[], char *);
 
@@ -1412,5 +1445,5 @@
 sync_Path_environment (void)
 {
-  char *path = allocated_variable_expand ("$(Path)");
+  char *path = allocated_variable_expand ("$(PATH)");
   static char *environ_path = NULL;
 
@@ -1429,5 +1462,5 @@
    */
   convert_Path_to_windows32 (path, ';');
-  environ_path = concat ("Path", "=", path);
+  environ_path = concat ("PATH", "=", path);
   putenv (environ_path);
   free (path);
Index: branches/GNU/src/gmake/variable.h
===================================================================
--- branches/GNU/src/gmake/variable.h	(revision 157)
+++ branches/GNU/src/gmake/variable.h	(revision 280)
@@ -113,4 +113,5 @@
 extern char *variable_buffer_output PARAMS ((char *ptr, char *string, unsigned int length));
 extern char *variable_expand PARAMS ((char *line));
+extern char *variable_expand_for_file PARAMS ((char *line, struct file *file));
 extern char *allocated_variable_expand_for_file PARAMS ((char *line, struct file *file));
 #define	allocated_variable_expand(line) \
@@ -126,5 +127,5 @@
 extern int pattern_matches PARAMS ((char *pattern, char *percent, char *str));
 extern char *subst_expand PARAMS ((char *o, char *text, char *subst, char *replace,
-		unsigned int slen, unsigned int rlen, int by_word, int suffix_only));
+		unsigned int slen, unsigned int rlen, int by_word));
 extern char *patsubst_expand PARAMS ((char *o, char *text, char *pattern, char *replace,
 		char *pattern_percent, char *replace_percent));
Index: branches/GNU/src/gmake/vmsfunctions.c
===================================================================
--- branches/GNU/src/gmake/vmsfunctions.c	(revision 157)
+++ branches/GNU/src/gmake/vmsfunctions.c	(revision 280)
@@ -3,4 +3,5 @@
 #include "make.h"
 #include "debug.h"
+#include "job.h"
 
 #ifdef __DECC
Index: branches/GNU/src/gmake/vmsjobs.c
===================================================================
--- branches/GNU/src/gmake/vmsjobs.c	(revision 280)
+++ branches/GNU/src/gmake/vmsjobs.c	(revision 280)
@@ -0,0 +1,668 @@
+
+
+
+/* --------------- Moved here from job.c ---------------
+   This file must be #included in job.c, as it accesses static functions.
+*/
+
+static int vms_jobsefnmask = 0;
+
+/* Wait for nchildren children to terminate */
+void
+vmsWaitForChildren(int *status)
+{
+  while (1)
+    {
+      if (!vms_jobsefnmask)
+	{
+	  *status = 0;
+	  return;
+	}
+
+      *status = sys$wflor (32, vms_jobsefnmask);
+    }
+  return;
+}
+
+/* Set up IO redirection.  */
+
+char *
+vms_redirect (struct dsc$descriptor_s *desc, char *fname, char *ibuf)
+{
+  char *fptr;
+
+  ibuf++;
+  while (isspace ((unsigned char)*ibuf))
+    ibuf++;
+  fptr = ibuf;
+  while (*ibuf && !isspace ((unsigned char)*ibuf))
+    ibuf++;
+  *ibuf = 0;
+  if (strcmp (fptr, "/dev/null") != 0)
+    {
+      strcpy (fname, vmsify (fptr, 0));
+      if (strchr (fname, '.') == 0)
+	strcat (fname, ".");
+    }
+  desc->dsc$w_length = strlen(fname);
+  desc->dsc$a_pointer = fname;
+  desc->dsc$b_dtype = DSC$K_DTYPE_T;
+  desc->dsc$b_class = DSC$K_CLASS_S;
+
+  if (*fname == 0)
+    printf (_("Warning: Empty redirection\n"));
+  return ibuf;
+}
+
+
+/* found apostrophe at (p-1)
+   inc p until after closing apostrophe.
+ */
+
+char *
+vms_handle_apos (char *p)
+{
+  int alast;
+
+#define SEPCHARS ",/()= "
+
+  alast = 0;
+
+  while (*p != 0)
+    {
+      if (*p == '"')
+	{
+          if (alast)
+            {
+              alast = 0;
+              p++;
+	    }
+	  else
+	    {
+	      p++;
+	      if (strchr (SEPCHARS, *p))
+		break;
+	      alast = 1;
+	    }
+	}
+      else
+	p++;
+    }
+
+  return p;
+}
+
+#include <descrip.h>
+#include <clidef.h>
+
+/* This is called as an AST when a child process dies (it won't get
+   interrupted by anything except a higher level AST).
+*/
+int
+vmsHandleChildTerm(struct child *child)
+{
+    int status;
+    register struct child *lastc, *c;
+    int child_failed;
+
+    vms_jobsefnmask &= ~(1 << (child->efn - 32));
+
+    lib$free_ef(&child->efn);
+
+    (void) sigblock (fatal_signal_mask);
+
+    child_failed = !(child->cstatus & 1 || ((child->cstatus & 7) == 0));
+
+    /* Search for a child matching the deceased one.  */
+    lastc = 0;
+#if defined(RECURSIVEJOBS) /* I've had problems with recursive stuff and process handling */
+    for (c = children; c != 0 && c != child; lastc = c, c = c->next)
+      ;
+#else
+    c = child;
+#endif
+
+    if (child_failed && !c->noerror && !ignore_errors_flag)
+      {
+	/* The commands failed.  Write an error message,
+	   delete non-precious targets, and abort.  */
+	child_error (c->file->name, c->cstatus, 0, 0, 0);
+	c->file->update_status = 1;
+	delete_child_targets (c);
+      }
+    else
+      {
+	if (child_failed)
+	  {
+	    /* The commands failed, but we don't care.  */
+	    child_error (c->file->name, c->cstatus, 0, 0, 1);
+	    child_failed = 0;
+	  }
+
+#if defined(RECURSIVEJOBS) /* I've had problems with recursive stuff and process handling */
+	/* If there are more commands to run, try to start them.  */
+	start_job (c);
+
+	switch (c->file->command_state)
+	  {
+	  case cs_running:
+	    /* Successfully started.  */
+	    break;
+
+	  case cs_finished:
+	    if (c->file->update_status != 0) {
+		/* We failed to start the commands.  */
+		delete_child_targets (c);
+	    }
+	    break;
+
+	  default:
+	    error (NILF, _("internal error: `%s' command_state"),
+                   c->file->name);
+	    abort ();
+	    break;
+	  }
+#endif /* RECURSIVEJOBS */
+      }
+
+    /* Set the state flag to say the commands have finished.  */
+    c->file->command_state = cs_finished;
+    notice_finished_file (c->file);
+
+#if defined(RECURSIVEJOBS) /* I've had problems with recursive stuff and process handling */
+    /* Remove the child from the chain and free it.  */
+    if (lastc == 0)
+      children = c->next;
+    else
+      lastc->next = c->next;
+    free_child (c);
+#endif /* RECURSIVEJOBS */
+
+    /* There is now another slot open.  */
+    if (job_slots_used > 0)
+      --job_slots_used;
+
+    /* If the job failed, and the -k flag was not given, die.  */
+    if (child_failed && !keep_going_flag)
+      die (EXIT_FAILURE);
+
+    (void) sigsetmask (sigblock (0) & ~(fatal_signal_mask));
+
+    return 1;
+}
+
+/* VMS:
+   Spawn a process executing the command in ARGV and return its pid. */
+
+#define MAXCMDLEN 200
+
+/* local helpers to make ctrl+c and ctrl+y working, see below */
+#include <libclidef.h>
+#include <ssdef.h>
+
+static int ctrlMask= LIB$M_CLI_CTRLY;
+static int oldCtrlMask;
+static int setupYAstTried= 0;
+static int pidToAbort= 0;
+static int chan= 0;
+
+static void
+reEnableAst(void)
+{
+	lib$enable_ctrl (&oldCtrlMask,0);
+}
+
+static void
+astHandler (void)
+{
+	if (pidToAbort) {
+		sys$forcex (&pidToAbort, 0, SS$_ABORT);
+		pidToAbort= 0;
+	}
+	kill (getpid(),SIGQUIT);
+}
+
+static void
+tryToSetupYAst(void)
+{
+	$DESCRIPTOR(inputDsc,"SYS$COMMAND");
+	int	status;
+	struct {
+		short int	status, count;
+		int	dvi;
+	} iosb;
+
+	setupYAstTried++;
+
+	if (!chan) {
+		status= sys$assign(&inputDsc,&chan,0,0);
+		if (!(status&SS$_NORMAL)) {
+			lib$signal(status);
+			return;
+		}
+	}
+	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);
+		return;
+	}
+
+	/* called from AST handler ? */
+	if (setupYAstTried>1)
+		return;
+	if (atexit(reEnableAst))
+		fprintf (stderr,
+                         _("-warning, you may have to re-enable CTRL-Y handling from DCL.\n"));
+	status= lib$disable_ctrl (&ctrlMask, &oldCtrlMask);
+	if (!(status&SS$_NORMAL)) {
+		lib$signal(status);
+		return;
+	}
+}
+
+int
+child_execute_job (char *argv, struct child *child)
+{
+  int i;
+  static struct dsc$descriptor_s cmddsc;
+  static struct dsc$descriptor_s pnamedsc;
+  static struct dsc$descriptor_s ifiledsc;
+  static struct dsc$descriptor_s ofiledsc;
+  static struct dsc$descriptor_s efiledsc;
+  int have_redirection = 0;
+  int have_newline = 0;
+
+  int spflags = CLI$M_NOWAIT;
+  int status;
+  char *cmd = alloca (strlen (argv) + 512), *p, *q;
+  char ifile[256], ofile[256], efile[256];
+  char *comname = 0;
+  char procname[100];
+  int in_string;
+
+  /* Parse IO redirection.  */
+
+  ifile[0] = 0;
+  ofile[0] = 0;
+  efile[0] = 0;
+
+  DB (DB_JOBS, ("child_execute_job (%s)\n", argv));
+
+  while (isspace ((unsigned char)*argv))
+    argv++;
+
+  if (*argv == 0)
+    return 0;
+
+  sprintf (procname, "GMAKE_%05x", getpid () & 0xfffff);
+  pnamedsc.dsc$w_length = strlen(procname);
+  pnamedsc.dsc$a_pointer = procname;
+  pnamedsc.dsc$b_dtype = DSC$K_DTYPE_T;
+  pnamedsc.dsc$b_class = DSC$K_CLASS_S;
+
+  in_string = 0;
+  /* Handle comments and redirection. */
+  for (p = argv, q = cmd; *p; p++, q++)
+    {
+      if (*p == '"')
+        in_string = !in_string;
+      if (in_string)
+        {
+          *q = *p;
+          continue;
+        }
+      switch (*p)
+	{
+	  case '#':
+	    *p-- = 0;
+	    *q-- = 0;
+	    break;
+	  case '\\':
+	    p++;
+	    if (*p == '\n')
+	      p++;
+	    if (isspace ((unsigned char)*p))
+	      {
+		do { p++; } while (isspace ((unsigned char)*p));
+		p--;
+	      }
+	    *q = *p;
+	    break;
+	  case '<':
+	    p = vms_redirect (&ifiledsc, ifile, p);
+	    *q = ' ';
+	    have_redirection = 1;
+	    break;
+	  case '>':
+	    have_redirection = 1;
+	    if (*(p-1) == '2')
+	      {
+		q--;
+		if (strncmp (p, ">&1", 3) == 0)
+		  {
+		    p += 3;
+		    strcpy (efile, "sys$output");
+		    efiledsc.dsc$w_length = strlen(efile);
+		    efiledsc.dsc$a_pointer = efile;
+		    efiledsc.dsc$b_dtype = DSC$K_DTYPE_T;
+		    efiledsc.dsc$b_class = DSC$K_CLASS_S;
+		  }
+		else
+		  {
+		    p = vms_redirect (&efiledsc, efile, p);
+		  }
+	      }
+	    else
+	      {
+		p = vms_redirect (&ofiledsc, ofile, p);
+	      }
+	    *q = ' ';
+	    break;
+	  case '\n':
+	    have_newline = 1;
+	  default:
+	    *q = *p;
+	    break;
+	}
+    }
+  *q = *p;
+  while (isspace ((unsigned char)*--q))
+    *q = '\0';
+
+  if (strncmp (cmd, "builtin_", 8) == 0)
+    {
+      child->pid = 270163;
+      child->efn = 0;
+      child->cstatus = 1;
+
+      DB (DB_JOBS, (_("BUILTIN [%s][%s]\n"), cmd, cmd+8));
+
+      p = cmd + 8;
+
+      if ((*(p) == 'c')
+	  && (*(p+1) == 'd')
+	  && ((*(p+2) == ' ') || (*(p+2) == '\t')))
+	{
+	  p += 3;
+	  while ((*p == ' ') || (*p == '\t'))
+	    p++;
+	  DB (DB_JOBS, (_("BUILTIN CD %s\n"), p));
+	  if (chdir (p))
+	    return 0;
+	  else
+	    return 1;
+	}
+      else if ((*(p) == 'r')
+	  && (*(p+1) == 'm')
+	  && ((*(p+2) == ' ') || (*(p+2) == '\t')))
+	{
+	  int in_arg;
+
+	  /* rm  */
+	  p += 3;
+	  while ((*p == ' ') || (*p == '\t'))
+	    p++;
+	  in_arg = 1;
+
+	  DB (DB_JOBS, (_("BUILTIN RM %s\n"), p));
+	  while (*p)
+	    {
+	      switch (*p)
+		{
+		  case ' ':
+		  case '\t':
+		    if (in_arg)
+		      {
+			*p++ = ';';
+			in_arg = 0;
+		      }
+		    break;
+		  default:
+		    break;
+		}
+	      p++;
+	    }
+	}
+      else
+	{
+	  printf(_("Unknown builtin command '%s'\n"), cmd);
+	  fflush(stdout);
+	  return 0;
+	}
+    }
+
+  /* Create a *.com file if either the command is too long for
+     lib$spawn, or the command contains a newline, or if redirection
+     is desired. Forcing commands with newlines into DCLs allows to
+     store search lists on user mode logicals.  */
+
+  if (strlen (cmd) > MAXCMDLEN
+      || (have_redirection != 0)
+      || (have_newline != 0))
+    {
+      FILE *outfile;
+      char c;
+      char *sep;
+      int alevel = 0;	/* apostrophe level */
+
+      if (strlen (cmd) == 0)
+	{
+	  printf (_("Error, empty command\n"));
+	  fflush (stdout);
+	  return 0;
+	}
+
+      outfile = open_tmpfile (&comname, "sys$scratch:CMDXXXXXX.COM");
+      if (outfile == 0)
+	pfatal_with_name (_("fopen (temporary file)"));
+
+      if (ifile[0])
+	{
+	  fprintf (outfile, "$ assign/user %s sys$input\n", ifile);
+          DB (DB_JOBS, (_("Redirected input from %s\n"), ifile));
+	  ifiledsc.dsc$w_length = 0;
+	}
+
+      if (efile[0])
+	{
+	  fprintf (outfile, "$ define sys$error %s\n", efile);
+          DB (DB_JOBS, (_("Redirected error to %s\n"), efile));
+	  efiledsc.dsc$w_length = 0;
+	}
+
+      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;
+	}
+
+      p = sep = q = cmd;
+      for (c = '\n'; c; c = *q++)
+	{
+	  switch (c)
+	    {
+            case '\n':
+              /* At a newline, skip any whitespace around a leading $
+                 from the command and issue exactly one $ into the DCL. */
+              while (isspace ((unsigned char)*p))
+                p++;
+              if (*p == '$')
+                p++;
+              while (isspace ((unsigned char)*p))
+                p++;
+              fwrite (p, 1, q - p, outfile);
+              fputc ('$', outfile);
+              fputc (' ', outfile);
+              /* Reset variables. */
+              p = sep = q;
+              break;
+
+	      /* Nice places for line breaks are after strings, after
+		 comma or space and before slash. */
+            case '"':
+              q = vms_handle_apos (q);
+              sep = q;
+              break;
+            case ',':
+            case ' ':
+              sep = q;
+              break;
+            case '/':
+            case '\0':
+              sep = q - 1;
+              break;
+            default:
+              break;
+	    }
+	  if (sep - p > 78)
+	    {
+	      /* Enough stuff for a line. */
+	      fwrite (p, 1, sep - p, outfile);
+	      p = sep;
+	      if (*sep)
+		{
+		  /* The command continues.  */
+		  fputc ('-', outfile);
+		}
+	      fputc ('\n', outfile);
+	    }
+  	}
+
+      fwrite (p, 1, q - p, outfile);
+      fputc ('\n', outfile);
+
+      fclose (outfile);
+
+      sprintf (cmd, "$ @%s", comname);
+
+      DB (DB_JOBS, (_("Executing %s instead\n"), cmd));
+    }
+
+  cmddsc.dsc$w_length = strlen(cmd);
+  cmddsc.dsc$a_pointer = cmd;
+  cmddsc.dsc$b_dtype = DSC$K_DTYPE_T;
+  cmddsc.dsc$b_class = DSC$K_CLASS_S;
+
+  child->efn = 0;
+  while (child->efn < 32 || child->efn > 63)
+    {
+      status = lib$get_ef ((unsigned long *)&child->efn);
+      if (!(status & 1))
+	return 0;
+    }
+
+  sys$clref (child->efn);
+
+  vms_jobsefnmask |= (1 << (child->efn - 32));
+
+/*
+             LIB$SPAWN  [command-string]
+			[,input-file]
+			[,output-file]
+			[,flags]
+			[,process-name]
+			[,process-id] [,completion-status-address] [,byte-integer-event-flag-num]
+			[,AST-address] [,varying-AST-argument]
+			[,prompt-string] [,cli] [,table]
+*/
+
+#ifndef DONTWAITFORCHILD
+/*
+ *	Code to make ctrl+c and ctrl+y working.
+ *	The problem starts with the synchronous case where after lib$spawn is
+ *	called any input will go to the child. But with input re-directed,
+ *	both control characters won't make it to any of the programs, neither
+ *	the spawning nor to the spawned one. Hence the caller needs to spawn
+ *	with CLI$M_NOWAIT to NOT give up the input focus. A sys$waitfr
+ *	has to follow to simulate the wanted synchronous behaviour.
+ *	The next problem is ctrl+y which isn't caught by the crtl and
+ *	therefore isn't converted to SIGQUIT (for a signal handler which is
+ *	already established). The only way to catch ctrl+y, is an AST
+ *	assigned to the input channel. But ctrl+y handling of DCL needs to be
+ *	disabled, otherwise it will handle it. Not to mention the previous
+ *	ctrl+y handling of DCL needs to be re-established before make exits.
+ *	One more: At the time of LIB$SPAWN signals are blocked. SIGQUIT will
+ *	make it to the signal handler after the child "normally" terminates.
+ *	This isn't enough. It seems reasonable for simple command lines like
+ *	a 'cc foobar.c' spawned in a subprocess but it is unacceptable for
+ *	spawning make. Therefore we need to abort the process in the AST.
+ *
+ *	Prior to the spawn it is checked if an AST is already set up for
+ *	ctrl+y, if not one is set up for a channel to SYS$COMMAND. In general
+ *	this will work except if make is run in a batch environment, but there
+ *	nobody can press ctrl+y. During the setup the DCL handling of ctrl+y
+ *	is disabled and an exit handler is established to re-enable it.
+ *	If the user interrupts with ctrl+y, the assigned AST will fire, force
+ *	an abort to the subprocess and signal SIGQUIT, which will be caught by
+ *	the already established handler and will bring us back to common code.
+ *	After the spawn (now /nowait) a sys$waitfr simulates the /wait and
+ *	enables the ctrl+y be delivered to this code. And the ctrl+c too,
+ *	which the crtl converts to SIGINT and which is caught by the common
+ *	signal handler. Because signals were blocked before entering this code
+ *	sys$waitfr will always complete and the SIGQUIT will be processed after
+ *	it (after termination of the current block, somewhere in common code).
+ *	And SIGINT too will be delayed. That is ctrl+c can only abort when the
+ *	current command completes. Anyway it's better than nothing :-)
+ */
+
+  if (!setupYAstTried)
+    tryToSetupYAst();
+  status = lib$spawn (&cmddsc,					/* cmd-string  */
+		      (ifiledsc.dsc$w_length == 0)?0:&ifiledsc, /* input-file  */
+		      (ofiledsc.dsc$w_length == 0)?0:&ofiledsc, /* output-file */
+		      &spflags,					/* flags  */
+		      &pnamedsc,				/* proc name  */
+		      &child->pid, &child->cstatus, &child->efn,
+		      0, 0,
+		      0, 0, 0);
+  if (status & 1)
+    {
+      pidToAbort= child->pid;
+      status= sys$waitfr (child->efn);
+      pidToAbort= 0;
+      vmsHandleChildTerm(child);
+    }
+#else
+  status = lib$spawn (&cmddsc,
+		      (ifiledsc.dsc$w_length == 0)?0:&ifiledsc,
+		      (ofiledsc.dsc$w_length == 0)?0:&ofiledsc,
+		      &spflags,
+		      &pnamedsc,
+		      &child->pid, &child->cstatus, &child->efn,
+		      vmsHandleChildTerm, child,
+		      0, 0, 0);
+#endif
+
+  if (!(status & 1))
+    {
+      printf (_("Error spawning, %d\n") ,status);
+      fflush (stdout);
+      switch (status)
+        {
+        case 0x1c:
+          errno = EPROCLIM;
+          break;
+        default:
+          errno = EFAIL;
+        }
+    }
+
+  if (comname && !ISDB (DB_JOBS))
+    unlink (comname);
+
+  return (status & 1);
+}
