DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T U

⟦f81b56a74⟧ TextFile

    Length: 121937 (0x1dc51)
    Types: TextFile
    Notes: Uncompressed file

Derivation

└─⟦a05ed705a⟧ Bits:30007078 DKUUG GNU 2/12/89
    └─⟦b7c781132⟧ »./make-3.54-3.55.diff.Z« 
        └─⟦this⟧ 

TextFile

This file contains context diffs between versions 3.54 and 3.55 of GNU Make.
There are two new files, README and make.man.  These are included as diffs
against /dev/null; recent versions of the `patch' program should handle this.

Differences in files generated by etags, ctags, tex, and makeinfo are not
included.

diff -rc make-3.54/CHANGES make-3.55/CHANGES
*** make-3.54/CHANGES	Mon Jun 12 01:41:30 1989
--- make-3.55/CHANGES	Sat Aug 26 16:59:28 1989
***************
*** 1,6 ****
--- 1,29 ----
  User-visible changes in GNU Make, excluding bug fixes, since version 3.05:
  ==========================================================================
  \f


+ Version 3.55
+ 
+ * There is now a Unix man page for GNU Make.  It is certainly not a replacement
+ for the Texinfo manual, but it documents the basic functionality and the
+ switches.  For full documentation, you should still read the Texinfo manual.
+ Thanks to Dennis Morse of Stanford University for contributing the initial
+ version of this.
+ 
+ * Variables which are defined by default (e.g., `CC') will no longer be put
+ into the environment for child processes.  (If these variables are reset by the
+ environment, makefiles, or the command line, they will still go into the
+ environment.)
+ 
+ * GNU Make will no longer go into an infinite loop when fed the horrid trash
+ that passes for makefiles that `imake' produces (so you can compile X, despite
+ the extreme stubbornness and irrationality of its maintainers).
+ 
+ * There is no longer a warning for using the `vpath' directive with an explicit
+ pathname (instead of a `%' pattern).
+ 
+ * Variables defined by default are no longer put into the environment.
+ This may help avoid E2BIG errors from execve.
+ \f


  Version 3.51
  
  * When removing intermediate files, only one `rm' command line is printed,
diff -rc make-3.54/ChangeLog make-3.55/ChangeLog
*** make-3.54/ChangeLog	Wed Jun 28 17:54:32 1989
--- make-3.55/ChangeLog	Sat Aug 26 16:25:53 1989
***************
*** 1,3 ****
--- 1,386 ----
+ Sat Aug 26 15:13:21 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+ 
+ 	* Version 3.55.
+ 
+ 	* make.texinfo (Rules: Multiple Targets): Make this node's `next'
+ 	pointer point to `Static Pattern'.
+ 
+ 	* make.texinfo (Makefiles: MAKEFILES Variable): Make this node's `prev'
+ 	pointer point to `Makefile Names'.
+ 
+ 	* make.1: Renamed to make.man.
+ 
+ 	* compatMakefile: Define `mandir' and `manext'.
+ 	(install): Depend on $(mandir)/make.$(manext).
+ 	($(mandir)/make.$(manext)): Depend on make.man and copy it to $@.
+ 	($(bindir)/make): Use `make' rather than $<; so Unix make can grok it.
+ 
+ Thu Aug 24 03:35:48 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+ 
+ 	* variable.c (target_environment): Allow variables that start with
+ 	underscores.
+ 
+ Wed Aug 23 22:50:32 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+ 
+ 	* variable.c (target_environment): Reject variables that don't start
+ 	with letters.
+ 
+ Tue Aug 22 04:14:29 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+ 
+ 	* GNUmakefile (make-$(version).tar.Z): Put make.1 in the tar file.
+ 
+ 	* make.texinfo (Commands: Recursion: Variables/Recursion): Document
+ 	that default variables are not put in the environment.
+ 
+ 	* variable.c (target_environment): Don't write variables with origin
+ 	o_default (i.e., ones from default.c).
+ 
+ 	* remake.c (update_file_1): Remake all targets with commands but no
+ 	deps.
+ 
+ Sat Aug 19 06:03:16 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+ 
+ 	* remake.c (update_file_1): In the final loop, set the deps'
+ 	`changed' members if they are newer than FILE.
+ 
+ 	* remake.c (update_goal_chain): Under -d, print a message if we decide
+ 	not to remake a makefile so as to avoid a possible infinite loop.
+ 
+ Fri Aug 18 20:30:14 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+ 
+ 	* remake.c (remake_file): Cleaned up.
+ 
+ 	* commands.c (execute_file_commands): If the commands are empty, set
+ 	FILE->update_status to zero before returning.
+ 
+ 	* remake.c (notice_finished_file): Set `last_mtime' fields to zero
+ 	instead of calling name_mtime; file_mtime will do that later if anybody
+ 	cares.
+ 
+ Thu Aug 17 10:01:11 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+ 
+ 	* make.texinfo (Rules: Wildcards: Wildcard Examples): Give this node a
+ 	`prev' pointer.
+ 
+ 	* Version 3.54.9 (alpha).
+ 
+ 	* make.texinfo: Fixed some @nodes.
+ 
+ 	* remake.c (check_dep): Don't set *MUST_MAKE_PTR if FILE doesn't exist
+ 	after running update_file.
+ 
+ 	* remake.c (notice_finished_file): If FILE has no commands, pretend its
+ 	modtime is now.
+ 
+ 	* remake.c (update_file_1): In the loops that call update_file on the
+ 	deps, compare modtimes before and after (unless deps are still being
+ 	made) and set the deps' `changed' members.  Do not set the `changed'
+ 	members in the loop that prints the newer/older debugging messages.
+ 
+ 	* remake.c (update_file_1): If no deps changed and FILE has no
+ 	commands, decide it doesn't need remaking.
+ 
+ 	* remake.c (update_file_1): Print a debugging message if we take
+ 	commands from default_file.
+ 
+ 	* make.texinfo (Makefiles: Remaking Makefiles): Document that makefiles
+ 	will not be remade if they are targets but have no dependencies.
+ 
+ 	* make.texinfo (Rules: Directory Search: Selective Search): Removed
+ 	note about warning for `vpath' with a constant pathname, since it isn't
+ 	warned about anymore.
+ 
+ 	* remake.c (update_goal_chain): If MAKEFILES, remove makefiles which
+ 	are targets and have no deps.
+ 
+ Tue Aug 15 00:00:08 1989  Roland McGrath  (roland at apple-gunkies.ai.mit.edu)
+ 
+ 	* remake.c (notice_finished_file): Increment files_remade for non-phony
+ 	files if they didn't exist before (even if they still don't).
+ 
+ 	* job.c: Include <errno.h> and declare errno.
+ 
+ 	* job.c (exec_command): If the execve fails with ENOEXEC (Exec format
+ 	error), return instead of exiting the child process.
+ 
+ 	* job.c (start_job): In the child side, if exec_command fails, try
+ 	using the shell.
+ 
+ 	* job.c (start_job): In the child side, call unblock_children instead
+ 	of sigsetmask.
+ 
+ 	* remake.c (notice_finished_file): Under -n or -q, always increment
+ 	files_remade for non-phony files.
+ 
+ 	* rule.c (intall_pattern_rule): Use find_percent.
+ 
+ 	* vpath.c (vpath_search): Pass the `percent' members to
+ 	pattern_matches.
+ 
+ Mon Aug 14 23:30:24 1989  Roland McGrath  (roland at apple-gunkies.ai.mit.edu)
+ 
+ 	* vpath.c (struct vpath): New member `percent', to hold a pointer into
+ 	the pattern where the % is.
+ 	(construct_vpath_list): Call find_percent on the pattern and set the
+ 	new `percent' member.
+ 
+ 	* rule.c (convert_to_pattern): Pass new arg to create_pattern_rule.
+ 	(create_pattern_rule): Take new arg TARGET_PERCENTS, nil or an array of
+ 	pointers into the corresponding elements of TARGETS, where the %s are.
+ 
+ 	* read.c (read_makefile): Don't run find_percent on `vpath' directive
+ 	patterns.
+ 
+ 	* read.c (record_files): Pass PATTERN_PERCENT to pattern_matches for
+ 	static pattern rules.  Save the percent pointer into implicit rule
+ 	targets, and pass them to create_pattern_rule.
+ 
+ 	* function.c (expand_function: `filter', `filter-out'): Pass new arg to
+ 	pattern_matches.
+ 
+ 	* funciton.c (pattern_matches): Take new arg PERCENT, a pointer into
+ 	PATTERN where the % is.  If PERCENT is nil, copy PATTERN into local
+ 	space and run find_percent on it.
+ 
+ Sun Aug 13 00:29:19 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+ 
+ 	* Version 3.54.8.
+ 
+ 	* README.templatate, README-doc.template: New files, turned into README
+ 	and README-doc to go into the two distribution tar files.
+ 	* GNUmakefile: Added a rule to edit the version number in
+ 	README.template and README-doc.template, producing README and
+ 	README-doc.
+ 
+ 	* remake.c (update_goal_chain): If -n or -q is in effect for a
+ 	makefile, and it got updated, don't change STATUS, so we can still
+ 	return -1 (meaning nothing was done).  This avoids an infinite loop on
+ 	"make -n Makefile".
+ 
+ Sat Aug 12 23:14:24 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+ 
+ 	* remake.c (notice_finished_file): Treat -q the same as -n.
+ 
+ 	* remake.c (update_goal_chain): Fixed handling of return from
+ 	update_file.  If -n or -q is in effect, ignore it.
+ 
+ 	* job.c (start_job): Don't test for -t.  We should never get called in
+ 	that case.
+ 
+ Fri Aug 11 04:09:14 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+ 
+ 	* function.c (expand_function): Removed unused variables.
+ 	(handle_function): Removed unused variable.
+ 
+ 	* main.c (main): Removed unused variable.
+ 
+ Wed Aug  9 09:37:10 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+ 
+ 	* Version 3.54.7.
+ 
+ 	* remake.c (notice_finished_file): If FILE's modtime actually changed,
+ 	increment files_remade.
+ 	(remake_file): Don't increment files_remade.
+ 
+ 	* remake.c (update_file): Don't print "up to date" messages for
+ 	phony files.
+ 
+ 	* job.c (child_handler): Don't set C->file->update_status to 1 if
+ 	start_job returns nonzero under -n or -t.
+ 
+ 	* expand.c (variable_expand): Count parens in $(foo:a=b) refs.
+ 
+ 	* main.c: Removed old declaration of `glob_tilde' (which hasn't existed
+ 	for a few months).
+ 
+ Tue Aug  8 23:53:43 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+ 
+ 	* job.c (exec_command): Fixed to not ignore the last path component and
+ 	to do the right thing with an empty path.
+ 
+ Fri Aug  4 15:58:19 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+ 
+ 	* remake.c (library_file_mtime): Look for libLIB.a, not /libLIB.a.
+ 	Do VPATH search on libLIB.a, not /usr/lib/libLIB.a
+ 
+ Thu Aug  3 20:42:00 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+ 
+ 	* job.c [HAVE_SYS_WAIT or not USG]: If WIFSIGNALED is not defined by
+ 	<sys/wait.h>, define it as (WTERMSIG != 0).
+ 
+ Tue Aug  1 19:25:34 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+ 
+ 	* remake.c (remake_file): If FILE has no commands and is a target,
+ 	don't set its time to now.  The time gets reset by notice_finished_file
+ 	anyway, and it isn't needed since check_dep checks for nonexistence.
+ 
+ 	* Version 3.54.6.
+ 
+ 	* read.c (read_makefile): Don't read off the end of the string after an
+ 	`include'.
+ 
+ 	* job.c (exec_command): New function to search the path for a file and
+ 	execute it.
+ 	(start_job): Use exec_command rather than execvp.
+ 
+ 	* read.c (read_makefile): Expand `include' directive args before
+ 	parsing them.  Allow trailing whitespace after filename.
+ 
+ 	* variable.c (target_environment): Put makelevel + 1, rather than
+ 	makelevel, in the `MAKELEVEL' envariable.
+ 
+ Sat Jul 29 10:27:04 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+ 
+ 	* remake.c (notice_finished_file): Don't get the new modtime of phony
+ 	files.
+ 
+ 	* remake.c (remake_file): Run commands instead of touching under -t if
+ 	FILE->cmds->any_recurse is set.
+ 
+ 	* commands.h (struct commands): Add new member `any_recurse', to be set
+ 	nonzero if any `lines_recurse' element is nonzero.
+ 	* commands.c (chop_commands): Set the `any_recurse' member.
+ 
+ 	* commands.c (execute_file_commands): Split chopping of commands into
+ 	lines into new function chop_commands.
+ 	* commands.h: Declare chop_commands.
+ 
+ 	* read.c (read_makefile): Test for a line beginning with a tab after
+ 	checking for conditional lines, but before all other checks.
+ 
+ Fri Jul 28 18:10:29 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+ 
+ 	* read.c (read_makefile): Match directives against collapsed line
+ 	and use that for their args.
+ 
+ 	* read.c (read_makefile): Warn about extra text after `include'.
+ 
+ Tue Jul 25 14:34:25 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+ 
+ 	* make.texinfo (Rules: Directory Search: Selective Search): Fixed
+ 	example to use correct `vpath' syntax.
+ 
+ Mon Jul 24 12:10:58 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+ 
+ 	* Version 3.54.5.
+ 
+ 	* job.c (start_job): In the child side, unblock SIGCHLD.
+ 
+ Fri Jul 21 18:25:59 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+ 
+ 	* make.h: Don't include <sys/types.h> #ifdef sun.
+ 
+ Mon Jul 17 14:29:10 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+ 
+ 	* implicit.c (pattern_search): If ar_name (FILENAME), don't check for
+ 	directory names.
+ 
+ 	* job.c (wait_for_children): Changed "waiting for children" message to
+ 	"waiting for unfinished jobs".
+ 
+ Fri Jul 14 13:17:13 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+ 
+ 	* load.c (load_average): Use an unsigned offset into kmem.
+ 
+ Thu Jul 13 18:44:49 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+ 
+ 	* variable.c (pop_variable_scope): Don't free the head of the chain of
+ 	variables in each bucket twice.
+ 
+ Tue Jul 11 06:45:24 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+ 
+ 	* GNUmakefile: Include COPYING in the doc tar file.
+ 
+ 	* variable.c, read.c, misc.c, job.c, function.c: Replace some identical
+ 	"for" loops with next_token or end_of_token calls.
+ 
+ Mon Jul 10 16:55:08 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+ 
+ 	* Version 3.54.4.
+ 
+ 	* compatMakefile: Documented new conditionals.
+ 
+ 	* job.c: Don't define sys_siglist if HAVE_SIGLIST is defined.
+ 	Don't define dup2 if HAVE_DUP2 is defined.
+ 
+ 	* job.c (child_handler): Interpret the return from start_job correctly.
+ 
+ 	* remake.c (update_file_1): Don't write "target not remade because of
+ 	errors" message under -n or -q.
+ 
+ 	* read.c: Declare getpwnam.
+ 
+ 	* glob.c: Use <dirent.h> if DIRENT is defined.
+ 	[USG]: Don't declare memcpy, since <memory.h> does.
+ 
+ Fri Jul  7 20:53:13 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+ 
+ 	* misc.c (collapse_line): Copy the line over in the right place.
+ 
+ Fri Jul  7 18:33:24 1989  Roland McGrath    (fsf at void.ai.mit.edu)
+ 
+ 	* remake.c: Conditionalize inclusion of <sys/file.h> on not
+ 	USG, since HP-UX defines a `struct file' there.
+ 
+ Fri Jul  7 12:11:30 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+ 
+ 	* job.c: If WTERMSIG is defined by <sys/wait.h>, define WAIT_T as int,
+ 	and don't define other macros; this covers HP-UX.
+ 	If WTERMSIG is not defined, use int or union wait based on USG and
+ 	HAVE_SYS_WAIT; this covers BSD and SysV.
+ 
+ 	* Version 3.54.3 (alpha).
+ 
+ 	* job.c [USG and not USGr3]: Include <errno.h> and declare errno.
+ 
+ 	* job.c (unblock_children [USG]): Declare child_handler.
+ 
+ 	* job.c: Renamed WRETCODE to WEXITSTATUS.
+ 	[HAVE_SYS_WAIT or not USG]: Undefine WTERMSIG, WCOREDUMP, and
+ 	WEXITSTATUS before defining them.  The HP-UX <sys/wait.h> defines them.
+ 
+ 	* main.c (main): If there are no goals, fatal AFTER printing the data
+ 	base under -p.
+ 
+ Thu Jul  6 22:43:33 1989  Roland McGrath  (roland at apple-gunkies.ai.mit.edu)
+ 
+ 	* glob.c [USG]: #define rindex as strrchr.
+ 
+ 	* job.c [USG]: Include <sys/param.h> and #define getdtablesize() as
+ 	NOFILE.
+ 
+ Wed Jul  5 09:36:00 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+ 
+ 	* Version 3.54.2 (alpha).
+ 
+ 	* expand.c (variable_expand): When expanding recursive variable
+ 	references (${${a}}), use the correct delimiters in the constructed
+ 	variable reference.
+ 
+ Mon Jul  3 18:29:26 1989  Roland McGrath  (roland at apple-gunkies.ai.mit.edu)
+ 
+ 	* compatMakefile: Clear out and redefine the .SUFFIXES list because
+ 	silly Sun 4 make defines .cps.h.
+ 
+ 	* compatMakefile: Fix comment about -DNO_MINUS_C_MINUS_O.
+ 
+ 	* remake.c: Include <sys/file.h> for O_* on 4.2.
+ 
+ 	* commands.c: Define sigmask if it's not defined.
+ 
+ Fri Jun 30 07:33:08 1989  Roland McGrath  (roland at apple-gunkies.ai.mit.edu)
+ 
+ 	* remake.c (remake_file): Don't always increment files_remade.
+ 
+ 	* variable.c (push_new_variable_scope): Zero the new variable hash
+ 	table.
+ 
+ Thu Jun 29 17:14:32 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+ 
+ 	* expand.c (variable_expand): When terminating the variable expansion
+ 	buffer, use variable_buffer_output instead of a simply zero store,
+ 	because the buffer may need to be enlarged.
+ 
  Wed Jun 28 16:53:47 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
  
  	* Version 3.54.
***************
*** 1905,1911 ****
  	* make.c (main): Use wait_for_children rather than child_handler.
  
  	* commands.c (wait_for_children): New function to block waiting for
! 	children, insuring th▶aa◀▶00◀▶04◀▶00◀▶05◀▶04◀▶02◀▶07◀▶01◀▶00◀X▶d6◀dler is not called recursively.
  	(execute_file_commands, kill_children): Use wait_for_children.
  
  	* commands.c (child_handler): Start up additional commands in a
--- 2288,2294 ----
  	* make.c (main): Use wait_for_children rather than child_handler.
  
  	* commands.c (wait_for_children): New function to block waiting for
! 	children, insuring th▶aa◀▶00◀▶00◀▶05◀▶02◀▶07◀▶01◀▶00◀X▶d6◀dler is not called recursively.
  	(execute_file_commands, kill_children): Use wait_for_children.
  
  	* commands.c (child_handler): Start up additional commands in a
diff -rc make-3.54/Makefile make-3.55/Makefile
*** make-3.54/Makefile	Wed Jun 28 18:17:44 1989
--- make-3.55/Makefile	Sat Aug 26 16:19:29 1989
***************
*** 25,32 ****
  # Define nothing for BSD, USG for System V,
  # and USGr3 (as well as USG) for SVR3.
  # If you have a USG hybrid with <sys/wait.h> and wait3, define HAVE_SYS_WAIT.
  # If your `cc' command doesn't grok -o options with -c (true for
! # many 4.2 BSD derivatives), define MINUS_C_MINUS_O.
  defines =
  
  # Define UMAX here to use Encore's inq_stats call.
--- 25,34 ----
  # Define nothing for BSD, USG for System V,
  # and USGr3 (as well as USG) for SVR3.
  # If you have a USG hybrid with <sys/wait.h> and wait3, define HAVE_SYS_WAIT.
+ # If you are USG but have sys_siglist, define HAVE_SIGLIST.
+ # If you are USG, and not USGr3, but have dup2, define HAVE_DUP2.
  # If your `cc' command doesn't grok -o options with -c (true for
! # many 4.2 BSD derivatives), define NO_MINUS_C_MINUS_O.
  defines =
  
  # Define UMAX here to use Encore's inq_stats call.
***************
*** 37,45 ****
  # If no load average determination can be done, define NO_LDAV.
  # `struct nlist' is an array that must be copied into, define NLIST_NAME_ARRAY.
  # Otherwise, define NO_LDAV.
- 
  LOAD_AVG =
  
  # If your system doesn't have alloca, or the one provided is bad,
  # get it from the Emacs distribution and define these.
  #ALLOCA = alloca.o
--- 39,50 ----
  # If no load average determination can be done, define NO_LDAV.
  # `struct nlist' is an array that must be copied into, define NLIST_NAME_ARRAY.
  # Otherwise, define NO_LDAV.
  LOAD_AVG =
  
+ # If your system needs extra libraries loaded in, define them here.
+ # System V probably need -lPW for alloca.
+ LOADLIBES =
+ 
  # If your system doesn't have alloca, or the one provided is bad,
  # get it from the Emacs distribution and define these.
  #ALLOCA = alloca.o
***************
*** 52,59 ****
  # Any extra object files your system needs.
  extras =
  
! # The directory to install Make in.
  bindir = $(prefix)/usr/local/bin
  
  objs = arscan.o glob.o ar.o commands.o job.o dir.o file.o load.o misc.o \
         main.o read.o remake.o remote.o rule.o implicit.o default.o variable.o \
--- 57,68 ----
  # Any extra object files your system needs.
  extras =
  
! # Directory to install `make' in.
  bindir = $(prefix)/usr/local/bin
+ # Directory to install the man page in.
+ mandir = $(prefix)/usr/local/man/man1
+ # Number to put on the man page filename.
+ manext = 1
  
  objs = arscan.o glob.o ar.o commands.o job.o dir.o file.o load.o misc.o \
         main.o read.o remake.o remote.o rule.o implicit.o default.o variable.o \
***************
*** 64,69 ****
--- 73,81 ----
         commands.h dep.h file.h job.h make.h rule.h variable.h
  
  
+ .SUFFIXES:
+ .SUFFIXES: .o .c .h .ps .dvi .texinfo
+ 
  .PHONY: all doc
  all: make
  doc: make-info make.dvi
***************
*** 100,110 ****
  	ctags -tw $(srcs)
  
  .PHONY: install
! install: $(bindir)/make
  
  $(bindir)/make: make
! 	cp $< $@.new
  	mv $@.new $@
  
  .PHONY: clean realclean
  clean:
--- 112,125 ----
  	ctags -tw $(srcs)
  
  .PHONY: install
! install: $(bindir)/make $(mandir)/make.$(manext)
  
  $(bindir)/make: make
! 	cp make $@.new
  	mv $@.new $@
+ 
+ $(mandir)/make.$(manext): make.man
+ 	cp make.man $@
  
  .PHONY: clean realclean
  clean:
diff -rc make-3.54/commands.c make-3.55/commands.c
*** make-3.54/commands.c	Sun Jun 11 23:41:32 1989
--- make-3.55/commands.c	Fri Aug 18 21:40:49 1989
***************
*** 23,29 ****
--- 23,105 ----
  #include "variable.h"
  #include "job.h"
  
+ #ifndef	sigmask
+ #define	sigmask(sig)	(1 << ((sig) - 1))
+ #endif
+ \f


+ /* Chop CMDS->commands up into lines in CMDS->command_lines.
+    Also set the corresponding CMDS->lines_recurse elements,
+    and the CMDS->any_recurse flag.  */
+ void
+ chop_commands (cmds)
+      register struct commands *cmds;
+ {
+   register char *p;
+   unsigned int nlines, idx;
+   char **lines;
+ 
+   nlines = 5;
+   lines = (char **) xmalloc (5 * sizeof (char *));
+   idx = 0;
+   p = cmds->commands;
+   while (*p != '\0')
+     {
+       char *end = p;
+     find_end:;
+       end = index (end, '\n');
+       if (end == 0)
+ 	end = p + strlen (p);
+       else if (end > p && end[-1] == '\\')
+ 	{
+ 	  int backslash = 1;
+ 	  register char *b;
+ 	  for (b = end - 2; b >= p && *b == '\\'; --b)
+ 	    backslash = !backslash;
+ 	  if (backslash)
+ 	    {
+ 	      ++end;
+ 	      goto find_end;
+ 	    }
+ 	}
  
+       if (idx == nlines - 1)
+ 	{
+ 	  nlines += 2;
+ 	  lines = (char **) xrealloc ((char *) lines,
+ 				      nlines * sizeof (char *));
+ 	}
+       lines[idx++] = savestring (p, end - p);
+       p = end;
+       if (*p != '\0')
+ 	++p;
+     }
+   lines[idx++] = 0;
+ 
+   if (idx != nlines)
+     {
+       nlines = idx;
+       lines = (char **) xrealloc ((char *) lines,
+ 				  nlines * sizeof (char *));
+     }
+ 
+   cmds->command_lines = lines;
+ 
+   cmds->any_recurse = 0;
+   --nlines;
+   cmds->lines_recurse = (char *) xmalloc (nlines);
+   for (idx = 0; idx < nlines; ++idx)
+     {
+       unsigned int len;
+       int recursive;
+       p = lines[idx];
+       len = strlen (p);
+       recursive = (sindex (p, len, "$(MAKE)", 7) != 0
+ 		   || sindex (p, len, "${MAKE}", 7) != 0);
+       cmds->lines_recurse[idx] = recursive;
+       cmds->any_recurse |= recursive;
+     }
+ }
+ \f


  /* Set FILE's automatic variables up.  */
  
  static void
***************
*** 251,256 ****
--- 327,333 ----
    if (*p == '\0')
      {
        file->command_state = cs_finished;
+       file->update_status = 0;
        return 0;
      }
  
***************
*** 260,329 ****
  
    set_file_variables (file);
  
!   /* Chop the commands up into lines.
!      Backslash-newlines do not end lines.  */
    if (cmds->command_lines == 0)
!     {
!       unsigned int nlines, idx;
!       char **lines;
! 
!       nlines = 5;
!       lines = (char **) xmalloc (5 * sizeof (char *));
!       idx = 0;
!       p = cmds->commands;
!       while (*p != '\0')
! 	{
! 	  char *end = p;
! 	find_end:;
! 	  end = index (end, '\n');
! 	  if (end == 0)
! 	    end = p + strlen (p);
! 	  else if (end > p && end[-1] == '\\')
! 	    {
! 	      int backslash = 1;
! 	      register char *b;
! 	      for (b = end - 2; b >= p && *b == '\\'; --b)
! 		backslash = !backslash;
! 	      if (backslash)
! 		{
! 		  ++end;
! 		  goto find_end;
! 		}
! 	    }
! 
! 	  if (idx == nlines - 1)
! 	    {
! 	      nlines += 2;
! 	      lines = (char **) xrealloc ((char *) lines,
! 					  nlines * sizeof (char *));
! 	    }
! 	  lines[idx++] = savestring (p, end - p);
! 	  p = end;
! 	  if (*p != '\0')
! 	    ++p;
! 	}
!       lines[idx++] = 0;
! 
!       if (idx != nlines)
! 	{
! 	  nlines = idx;
! 	  lines = (char **) xrealloc ((char *) lines,
! 				      nlines * sizeof (char *));
! 	}
! 
!       cmds->command_lines = lines;
! 
!       --nlines;
!       cmds->lines_recurse = (char *) xmalloc (nlines);
!       for (idx = 0; idx < nlines; ++idx)
! 	{
! 	  unsigned int len;
! 	  p = lines[idx];
! 	  len = strlen (p);
! 	  cmds->lines_recurse[idx] = (sindex (p, len, "$(MAKE)", 7) != 0
! 				      || sindex (p, len, "${MAKE}", 7) != 0);
! 	}
!     }
  
    if (job_slots > 0)
      /* Wait for a job slot to be freed up.  */
--- 337,345 ----
  
    set_file_variables (file);
  
!   /* Chop the commands up into lines.  */
    if (cmds->command_lines == 0)
!     chop_commands (cmds);
  
    if (job_slots > 0)
      /* Wait for a job slot to be freed up.  */
diff -rc make-3.54/commands.h make-3.55/commands.h
*** make-3.54/commands.h	Sun Jun 11 23:41:30 1989
--- make-3.55/commands.h	Sat Jul 29 21:02:50 1989
***************
*** 25,30 ****
--- 25,31 ----
      char *commands;		/* Commands text.  */
      char **command_lines;	/* Commands chopped up into lines.  */
      char *lines_recurse;	/* One flag for each line.  */
+     char any_recurse;		/* Nonzero if any `lines_recurse' elt is.  */
    };
  
  
***************
*** 31,33 ****
--- 32,36 ----
  extern int execute_file_commands ();
  extern void print_commands ();
  extern void delete_child_targets ();
+ 
+ extern void chop_commands ();
diff -rc make-3.54/dir.c make-3.55/dir.c
*** make-3.54/dir.c	Fri May 26 20:17:13 1989
--- make-3.55/dir.c	Mon Jul 10 18:03:11 1989
***************
*** 17,27 ****
  
  #include "make.h"
  
! #ifdef	USGr3
  #include <dirent.h>
  #define direct dirent
  #define	D_NAMLEN(d) strlen((d)->d_name)
! #else	/* Not USGr3.  */
  #define D_NAMLEN(d) ((d)->d_namlen)
  #	ifdef	USG
  #include "ndir.h"   /* Get ndir.h from the Emacs distribution.  */
--- 17,27 ----
  
  #include "make.h"
  
! #if	defined(USGr3) || defined(DIRENT)
  #include <dirent.h>
  #define direct dirent
  #define	D_NAMLEN(d) strlen((d)->d_name)
! #else	/* Not USGr3 and not DIRENT.  */
  #define D_NAMLEN(d) ((d)->d_namlen)
  #	ifdef	USG
  #include "ndir.h"   /* Get ndir.h from the Emacs distribution.  */
***************
*** 28,34 ****
  #	else	/* Not USG.  */
  #include <sys/dir.h>
  #	endif	/* USG.  */
! #endif	/* USGr3.  */
  
  
  /* Hash table of directories.  */
--- 28,34 ----
  #	else	/* Not USG.  */
  #include <sys/dir.h>
  #	endif	/* USG.  */
! #endif	/* USGr3 or DIRENT.  */
  
  
  /* Hash table of directories.  */
diff -rc make-3.54/expand.c make-3.55/expand.c
*** make-3.54/expand.c	Sun Jun 11 15:41:22 1989
--- make-3.55/expand.c	Wed Aug  9 16:08:46 1989
***************
*** 122,128 ****
  		if (count < 0)
  		  {
  		    char *name = expand_argument (beg, p);
! 		    p1 = concat ("$(", name, ")");
  		    free (name);
  		    name = allocated_variable_expand (p1);
  		    o = variable_buffer_output (o, name, strlen (name));
--- 122,131 ----
  		if (count < 0)
  		  {
  		    char *name = expand_argument (beg, p);
! 		    static char start[3] = { '$', }, end[2];
! 		    start[1] = openparen;
! 		    end[0] = closeparen;
! 		    p1 = concat (start, name, end);
  		    free (name);
  		    name = allocated_variable_expand (p1);
  		    o = variable_buffer_output (o, name, strlen (name));
***************
*** 133,165 ****
  
  	    /* This is not a reference to a built-in function and
  	       it does not contain any variable references inside.
! 	       There are several things it could be.  In any case,
! 	       find the end of it, which is the first close-paren
! 	       of the appropriate type.  (We do not count them.)  */
  
! 	    end = index (beg, closeparen);
! 	    if (end == 0)
! 	      /* There was no ending ) or } !!
! 		 Swallow the line (and screw the hook and sinker).  */
! 	      return initialize_variable_output ();
! 
! 	    /* This is not a reference to a built-in function.  Is it
! 	       an old-fashioned substitution spec, $(FOO:BAR=UGH)?  */
! 
! 	    if ((p = lindex (beg, end, ':')) != 0
! 		&& (p1 = lindex (p, end, '=')) != 0)
  	      {
! 		unsigned int slen = p1 - p - 1;
! 		unsigned int rlen = end - p1 - 1;
  		v = lookup_variable (beg, p - beg);
  		if (v != 0 && *v->value != '\0')
  		  {
  		    char *value = (v->recursive ? recursively_expand (v)
  				   : v->value);
! 		    if (lindex (p + 1, p1 - 1, '%') != 0)
  		      {
! 			p = savestring (p + 1, slen);
! 			p1 = savestring (p1 + 1, rlen);
  			o = patsubst_expand (o, value, p, p1,
  					     index (p, '%'), index (p1, '%'));
  			free (p);
--- 136,192 ----
  
  	    /* This is not a reference to a built-in function and
  	       it does not contain any variable references inside.
! 	       There are several things it could be.  */
  
! 	    p = index (beg, ':');
! 	    if (p != 0 && lindex (beg, p, closeparen) == 0)
  	      {
! 		/* This is a substitution reference: $(FOO:A=B).  */
! 		int count;
! 		char *subst_beg, *replace_beg;
! 		unsigned int subst_len, replace_len;
! 
  		v = lookup_variable (beg, p - beg);
+ 
+ 		subst_beg = p + 1;
+ 		count = 0;
+ 		for (p = subst_beg; *p != '\0'; ++p)
+ 		  {
+ 		    if (*p == openparen)
+ 		      ++count;
+ 		    else if (*p == closeparen)
+ 		      --count;
+ 		    else if (*p == '=' && count <= 0)
+ 		      break;
+ 		  }
+ 		if (count > 0)
+ 		  /* There were unmatched opening parens.  */
+ 		  return initialize_variable_output ();
+ 		subst_len = p - subst_beg;
+ 
+ 		replace_beg = p + 1;
+ 		count = 0;
+ 		for (p = replace_beg; *p != '\0'; ++p)
+ 		  {
+ 		    if (*p == openparen)
+ 		      ++count;
+ 		    else if (*p == closeparen && --count < 0)
+ 		      break;
+ 		  }
+ 		if (count > 0)
+ 		  /* There were unmatched opening parens.  */
+ 		  return initialize_variable_output ();
+ 		end = p;
+ 		replace_len = p - replace_beg;
+ 
  		if (v != 0 && *v->value != '\0')
  		  {
  		    char *value = (v->recursive ? recursively_expand (v)
  				   : v->value);
! 		    if (lindex (subst_beg, subst_beg + subst_len, '%') != 0)
  		      {
! 			p = savestring (subst_beg, subst_len);
! 			p1 = savestring (replace_beg, replace_len);
  			o = patsubst_expand (o, value, p, p1,
  					     index (p, '%'), index (p1, '%'));
  			free (p);
***************
*** 166,173 ****
  			free (p1);
  		      }
  		    else
! 		      o = subst_expand (o, value, p + 1, p1 + 1,
! 					slen, rlen, 0, 1);
  		    if (v->recursive)
  		      free (value);
  		  }
--- 193,200 ----
  			free (p1);
  		      }
  		    else
! 		      o = subst_expand (o, value, subst_beg, replace_beg,
! 					subst_len, replace_len, 0, 1);
  		    if (v->recursive)
  		      free (value);
  		  }
***************
*** 177,182 ****
--- 204,212 ----
  	    else
  	      {
  		/* Look up the value of the variable.  */
+ 		end = index (beg, closeparen);
+ 		if (end == 0)
+ 		  return initialize_variable_output ();
  		v = lookup_variable (beg, end - beg);
  
  		if (v != 0 && *v->value != '\0')
***************
*** 225,232 ****
  	++p;
      }
  
!   *o = '\0';
! 
    return initialize_variable_output ();
  }
  \f


--- 255,261 ----
  	++p;
      }
  
!   (void) variable_buffer_output (o, "", 1);
    return initialize_variable_output ();
  }
  \f


diff -rc make-3.54/function.c make-3.55/function.c
*** make-3.54/function.c	Mon Jun 19 17:59:06 1989
--- make-3.55/function.c	Tue Aug 15 00:03:36 1989
***************
*** 270,283 ****
  /* Return 1 if PATTERN matches WORD, 0 if not.  */
  
  int
! pattern_matches (pattern, word)
!      register char *pattern, *word;
  {
-   char *percent = index (pattern, '%');
    unsigned int len;
  
    if (percent == 0)
!     return !strcmp (pattern, word);
  
    len = strlen (percent + 1);
  
--- 270,290 ----
  /* Return 1 if PATTERN matches WORD, 0 if not.  */
  
  int
! pattern_matches (pattern, percent, word)
!      register char *pattern, *percent, *word;
  {
    unsigned int len;
  
    if (percent == 0)
!     {
!       unsigned int len = strlen (pattern) + 1;
!       char *new = (char *) alloca (len);
!       bcopy (pattern, new, len);
!       pattern = new;
!       percent = find_percent (pattern);
!       if (percent == 0)
! 	return streq (pattern, word);
!     }
  
    len = strlen (percent + 1);
  
***************
*** 541,548 ****
  	   expand only the first two.  */
  	char *var, *list;
  	register struct variable *v;
- 	char *saved_value;
- 	int saved_recursive;
  
  	count = 0;
  	for (p = text; p < end; ++p)
--- 548,553 ----
***************
*** 652,666 ****
  	p3 = p2;
  	while ((p = find_next_token (&p3, &len)) != 0)
  	  {
! 	    int is_pattern;
  	    char save = p[len];
  	    p[len] = '\0';
  
! 	    is_pattern = find_percent (p) != 0;
  	    for (i = 0; i < wordi; ++i)
  	      if (words[i] != 0 &&
! 		  (is_pattern ? pattern_matches (p, words[i])
! 		   : streq (p, words[i]))
  		  == (function == function_filter_out))
  		words[i] = 0;
  	    p[len] = save;
--- 657,671 ----
  	p3 = p2;
  	while ((p = find_next_token (&p3, &len)) != 0)
  	  {
! 	    char *percent;
  	    char save = p[len];
  	    p[len] = '\0';
  
! 	    percent = find_percent (p);
  	    for (i = 0; i < wordi; ++i)
  	      if (words[i] != 0 &&
! 		  (percent == 0 ? streq (p, words[i])
! 		   : pattern_matches (p, percent, words[i]))
  		  == (function == function_filter_out))
  		words[i] = 0;
  	    p[len] = save;
***************
*** 1055,1062 ****
  handle_function (op, stringp)
       char **op;
       char **stringp;
  {
-   char *end;
    register unsigned int code;
    unsigned int maxlen;
    char *beg = *stringp + 1;
--- 1060,1067 ----
  handle_function (op, stringp)
       char **op;
       char **stringp;
+ 
  {
    register unsigned int code;
    unsigned int maxlen;
    char *beg = *stringp + 1;
***************
*** 1086,1094 ****
        register char *p;
  
        /* Space after function name isn't part of the args.  */
!       p = endref;
!       while (*p == ' ' || *p == '\t')
! 	++p;
        argbeg = p;
  
        /* Count nested use of whichever kind of parens we use,
--- 1091,1097 ----
        register char *p;
  
        /* Space after function name isn't part of the args.  */
!       p = next_token (endref);
        argbeg = p;
  
        /* Count nested use of whichever kind of parens we use,
diff -rc make-3.54/glob.c make-3.55/glob.c
*** make-3.54/glob.c	Fri May 26 21:52:00 1989
--- make-3.55/glob.c	Mon Jul 10 18:03:16 1989
***************
*** 21,45 ****
  
  #include <sys/types.h>
  
! #ifdef	USGr3
  #include <dirent.h>
  #define direct dirent
  #define	D_NAMLEN(d) strlen((d)->d_name)
! #else	/* not USGr3	*/
  #define D_NAMLEN(d) ((d)->d_namlen)
  #	ifdef	USG
  #include "ndir.h"   /* Get ndir.h from the Emacs distribution.  */
! #	else	/* not USG	*/
  #include <sys/dir.h>
! #	endif	/* USG		*/
! #endif	/* USGr3	*/
  
  #ifdef USG
  #include <memory.h>
  #include <string.h>
  #define bcopy(s, d, n) ((void) memcpy ((d), (s), (n)))
  
- extern char *memcpy ();
  #else /* not USG */
  #include <strings.h>
  
--- 21,45 ----
  
  #include <sys/types.h>
  
! #if	defined(USGr3) || defined(DIRENT)
  #include <dirent.h>
  #define direct dirent
  #define	D_NAMLEN(d) strlen((d)->d_name)
! #else	/* Not USGr3 and not DIRENT.  */
  #define D_NAMLEN(d) ((d)->d_namlen)
  #	ifdef	USG
  #include "ndir.h"   /* Get ndir.h from the Emacs distribution.  */
! #	else	/* Not USG.  */
  #include <sys/dir.h>
! #	endif	/* USG.  */
! #endif	/* USGr3 or DIRENT.  */
  
  #ifdef USG
  #include <memory.h>
  #include <string.h>
  #define bcopy(s, d, n) ((void) memcpy ((d), (s), (n)))
+ #define rindex	strrchr
  
  #else /* not USG */
  #include <strings.h>
  
diff -rc make-3.54/implicit.c make-3.55/implicit.c
*** make-3.54/implicit.c	Mon Jun 12 00:09:49 1989
--- make-3.55/implicit.c	Sat Aug 19 11:21:43 1989
***************
*** 135,147 ****
  
    char *p;
  
!   /* Set LASTSLASH to point at the last slash in FILENAME
!      but not counting any slash at the end.  (foo/bar/ counts as
!      bar/ in directory foo/, not empty in directory foo/bar/.)  */
! 
!   lastslash = rindex (filename, '/');
!   if (lastslash != 0 && lastslash[1] == '\0')
      lastslash = 0;
  
    /* First see which pattern rules match this target
       and may be considered.  Put them in TRYRULES.  */
--- 135,151 ----
  
    char *p;
  
!   if (ar_name (filename))
      lastslash = 0;
+   else
+     {
+       /* Set LASTSLASH to point at the last slash in FILENAME
+ 	 but not counting any slash at the end.  (foo/bar/ counts as
+ 	 bar/ in directory foo/, not empty in directory foo/bar/.)  */
+       lastslash = rindex (filename, '/');
+       if (lastslash != 0 && lastslash[1] == '\0')
+ 	lastslash = 0;
+     }
  
    /* First see which pattern rules match this target
       and may be considered.  Put them in TRYRULES.  */
***************
*** 175,189 ****
  	     intermediate files.  */
  	  if (recursions > 0 && target[1] == '\0' && !rule->terminal)
  	    continue;
! 	  
  	  /* From the lengths of the filename and the pattern parts,
  	     find the stem: the part of the filename that matches the %.  */
  	  stem = filename + (suffix - target - 1);
  	  stemlen = namelen - rule->lens[i] + 1;
! 	  
  	  /* Set CHECK_LASTSLASH if FILENAME contains a directory
  	     prefix and the target pattern does not contain a slash.  */
! 	  
  	  check_lastslash = lastslash != 0 && index (target, '/') == 0;
  	  if (check_lastslash)
  	    {
--- 179,193 ----
  	     intermediate files.  */
  	  if (recursions > 0 && target[1] == '\0' && !rule->terminal)
  	    continue;
! 
  	  /* From the lengths of the filename and the pattern parts,
  	     find the stem: the part of the filename that matches the %.  */
  	  stem = filename + (suffix - target - 1);
  	  stemlen = namelen - rule->lens[i] + 1;
! 
  	  /* Set CHECK_LASTSLASH if FILENAME contains a directory
  	     prefix and the target pattern does not contain a slash.  */
! 
  	  check_lastslash = lastslash != 0 && index (target, '/') == 0;
  	  if (check_lastslash)
  	    {
***************
*** 192,202 ****
  	      stem += lastslash - filename + 1;
  	      stemlen -= (lastslash - filename) + 1;
  	    }
! 	  
  	  /* Check that filename is long enough to match the whole pattern.  */
  	  if (stemlen <= 0)
  	    continue;
! 	  
  	  /* Check that the rule pattern matches the text before the stem.  */
  	  if (check_lastslash)
  	    {
--- 196,206 ----
  	      stem += lastslash - filename + 1;
  	      stemlen -= (lastslash - filename) + 1;
  	    }
! 
  	  /* Check that filename is long enough to match the whole pattern.  */
  	  if (stemlen <= 0)
  	    continue;
! 
  	  /* Check that the rule pattern matches the text before the stem.  */
  	  if (check_lastslash)
  	    {
***************
*** 207,213 ****
  	  else if (stem > filename
  		   && strncmp (target, filename, stem - filename))
  	    continue;
! 	  
  	  /* Check that the rule pattern matches the text after the stem.
  	     We could test simply use streq, but this way we compare the
  	     first two characters immediately.  This saves time in the very
--- 211,217 ----
  	  else if (stem > filename
  		   && strncmp (target, filename, stem - filename))
  	    continue;
! 
  	  /* Check that the rule pattern matches the text after the stem.
  	     We could test simply use streq, but this way we compare the
  	     first two characters immediately.  This saves time in the very
***************
*** 216,222 ****
  	  if (*suffix != stem[stemlen]
  	      || (*suffix != '\0' && !streq (&suffix[1], &stem[stemlen + 1])))
  	    continue;
! 	  
  	  /* Record if we match a rule that not all filenames will match.  */
  	  if (target[1] != '\0')
  	    specific_rule_may_have_matched = 1;
--- 220,226 ----
  	  if (*suffix != stem[stemlen]
  	      || (*suffix != '\0' && !streq (&suffix[1], &stem[stemlen + 1])))
  	    continue;
! 
  	  /* Record if we match a rule that not all filenames will match.  */
  	  if (target[1] != '\0')
  	    specific_rule_may_have_matched = 1;
***************
*** 230,236 ****
  	continue;
  
        specific_rule_matched |= specific_rule_may_have_matched;
! 	  
        /* A rule with no dependencies and no commands exists solely to set
  	 specific_rule_matched when it matches.  Don't try to use it.  */
        if (rule->deps == 0 && rule->cmds == 0)
--- 234,240 ----
  	continue;
  
        specific_rule_matched |= specific_rule_may_have_matched;
! 
        /* A rule with no dependencies and no commands exists solely to set
  	 specific_rule_matched when it matches.  Don't try to use it.  */
        if (rule->deps == 0 && rule->cmds == 0)
***************
*** 326,334 ****
  		}
  	      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
--- 330,338 ----
  		}
  	      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
***************
*** 340,346 ****
  		  tryrules[i] = 0;
  		  break;
  		}
! 	      
  	      intermediate_files[deps_found] = 0;
  
  	      DEBUGP2 ("Trying %s dependency `%s'.\n",
--- 344,350 ----
  		  tryrules[i] = 0;
  		  break;
  		}
! 
  	      intermediate_files[deps_found] = 0;
  
  	      DEBUGP2 ("Trying %s dependency `%s'.\n",
***************
*** 358,377 ****
  		  found_files[deps_found++] = p;
  		  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 && p == depname)
  		{
  		  if (intermediate_file == 0)
  		    intermediate_file
  		      = (struct file *) alloca (sizeof (struct file));
! 		  
  		  DEBUGP2 ("Looking for a rule with intermediate file `%s'.\n",
  			   p, 0);
! 		  
  		  bzero ((char *) intermediate_file, sizeof (struct file));
  		  intermediate_file->name = p;
  		  if (pattern_search (intermediate_file, (char *) 0,
--- 362,381 ----
  		  found_files[deps_found++] = p;
  		  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 && p == depname)
  		{
  		  if (intermediate_file == 0)
  		    intermediate_file
  		      = (struct file *) alloca (sizeof (struct file));
! 
  		  DEBUGP2 ("Looking for a rule with intermediate file `%s'.\n",
  			   p, 0);
! 
  		  bzero ((char *) intermediate_file, sizeof (struct file));
  		  intermediate_file->name = p;
  		  if (pattern_search (intermediate_file, (char *) 0,
***************
*** 387,407 ****
  		      ++deps_found;
  		      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.  */
  	  rule->in_use = 0;
! 	  
  	  if (dep != 0)
  	    {
  	      /* This pattern rule does not apply.
--- 391,411 ----
  		      ++deps_found;
  		      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.  */
  	  rule->in_use = 0;
! 
  	  if (dep != 0)
  	    {
  	      /* This pattern rule does not apply.
***************
*** 421,432 ****
  	    /* This pattern rule does apply.  Stop looking for one.  */
  	    break;
  	}
!       
        /* If we found an applicable rule without
  	 intermediate files, don't try with them.  */
        if (i < nrules)
  	break;
! 	  
        rule = 0;
      }
  
--- 425,436 ----
  	    /* This pattern rule does apply.  Stop looking for one.  */
  	    break;
  	}
! 
        /* If we found an applicable rule without
  	 intermediate files, don't try with them.  */
        if (i < nrules)
  	break;
! 
        rule = 0;
      }
  
***************
*** 443,449 ****
    if (recursions > 0)
      /* Kludge-o-matic */
      file->name = rule->targets[matches[foundrule]];
!   
    /* FOUND_FILES lists the dependencies for the rule we found.
       This includes the intermediate files, if any.
       Convert them into entries on the deps-chain of FILE.  */
--- 447,453 ----
    if (recursions > 0)
      /* Kludge-o-matic */
      file->name = rule->targets[matches[foundrule]];
! 
    /* FOUND_FILES lists the dependencies for the rule we found.
       This includes the intermediate files, if any.
       Convert them into entries on the deps-chain of FILE.  */
***************
*** 451,457 ****
    while (deps_found-- > 0)
      {
        register char *s;
!       
        if (intermediate_files[deps_found] != 0)
  	{
  	  /* If we need to use an intermediate file,
--- 455,461 ----
    while (deps_found-- > 0)
      {
        register char *s;
! 
        if (intermediate_files[deps_found] != 0)
  	{
  	  /* If we need to use an intermediate file,
***************
*** 460,466 ****
  	     We know that the intermediate file did not already exist as
  	     a target; therefore we can assume that the deps and cmds
  	     of F below are null before we change them.  */
! 	  
  	  struct file *imf = intermediate_files[deps_found];
  	  register struct file *f = enter_file (imf->name);
  	  f->deps = imf->deps;
--- 464,470 ----
  	     We know that the intermediate file did not already exist as
  	     a target; therefore we can assume that the deps and cmds
  	     of F below are null before we change them.  */
! 
  	  struct file *imf = intermediate_files[deps_found];
  	  register struct file *f = enter_file (imf->name);
  	  f->deps = imf->deps;
***************
*** 479,485 ****
  	    }
  	  num_intermediates++;
  	}
!       
        dep = (struct dep *) xmalloc (sizeof (struct dep));
        s = found_files[deps_found];
        if (recursions == 0)
--- 483,489 ----
  	    }
  	  num_intermediates++;
  	}
! 
        dep = (struct dep *) xmalloc (sizeof (struct dep));
        s = found_files[deps_found];
        if (recursions == 0)
***************
*** 507,513 ****
  	}
        dep->next = file->deps;
        file->deps = dep;
!       
        /* If the new dependency duplicates an old one, delete the old one.  */
        while (dep != 0)
  	{
--- 511,517 ----
  	}
        dep->next = file->deps;
        file->deps = dep;
! 
        /* If the new dependency duplicates an old one, delete the old one.  */
        while (dep != 0)
  	{
***************
*** 529,537 ****
      {
        unsigned int max_targets = 2;
        register unsigned int idx;
!       
        file->also_make = (char **) xmalloc (2 * sizeof (char *));
!       
        idx = 0;
        for (i = 0; rule->targets[i] != 0; ++i)
  	if (i == matches[foundrule])
--- 533,541 ----
      {
        unsigned int max_targets = 2;
        register unsigned int idx;
! 
        file->also_make = (char **) xmalloc (2 * sizeof (char *));
! 
        idx = 0;
        for (i = 0; rule->targets[i] != 0; ++i)
  	if (i == matches[foundrule])
diff -rc make-3.54/job.c make-3.55/job.c
*** make-3.54/job.c	Thu Jun 22 21:50:03 1989
--- make-3.55/job.c	Tue Aug 15 00:52:16 1989
***************
*** 21,27 ****
--- 21,30 ----
  #include "job.h"
  #include "file.h"
  #include "variable.h"
+ #include <errno.h>
  
+ extern int errno;
+ 
  extern char **construct_command_argv ();
  
  #ifdef	USG
***************
*** 31,75 ****
  #define	VFORK_NAME	"vfork"
  #endif	/* USG.  */
  
  #if	defined(USG) && !defined(HAVE_SYS_WAIT)
  
  #define WAIT_T int
  #define WTERMSIG(x) ((x) & 0x7f)
  #define WCOREDUMP(x) ((x) & 0x80)
! #define WRETCODE(x) (((x) >> 8) & 0xff)
  #define WIFSIGNALED(x) (WTERMSIG (x) != 0)
  #define WIFEXITED(x) (WTERMSIG (x) == 0)
  
  #else	/* Have <sys/wait.h> or not USG.  */
  
- #include <sys/wait.h>
  #define WAIT_T union wait
  #define WTERMSIG(x) ((x).w_termsig)
  #define WCOREDUMP(x) ((x).w_coredump)
! #define WRETCODE(x) ((x).w_retcode)
! 
! #include <sys/time.h>
! #include <sys/resource.h>
! #include <signal.h>
! 
! #ifndef sigmask
! #define sigmask(sig) (1 << ((sig) - 1))
  #endif
  
  #endif	/* USG and don't have <sys/wait.h>.  */
  
  
  extern int fork (), wait (), kill (), getpid ();
  extern void _exit ();
  
- #if	!defined(USG) || defined(HAVE_SYS_WAIT)
- extern int wait3 ();
- #endif
- 
  #ifndef	USG
  extern int sigsetmask ();
  #endif
  
  extern void block_remote_children (), unblock_remote_children ();
  extern double load_average ();
  extern int start_remote_job_p ();
--- 34,90 ----
  #define	VFORK_NAME	"vfork"
  #endif	/* USG.  */
  
+ #if	defined(HAVE_SYS_WAIT) || !defined(USG)
+ #include <sys/wait.h>
+ #include <sys/time.h>
+ #include <sys/resource.h>
+ #include <signal.h>
+ extern int wait3 ();
+ #endif
+ 
+ #ifdef	WTERMSIG
+ #define	WAIT_T int
+ #else
+ 
  #if	defined(USG) && !defined(HAVE_SYS_WAIT)
  
  #define WAIT_T int
  #define WTERMSIG(x) ((x) & 0x7f)
  #define WCOREDUMP(x) ((x) & 0x80)
! #define WEXITSTATUS(x) (((x) >> 8) & 0xff)
  #define WIFSIGNALED(x) (WTERMSIG (x) != 0)
  #define WIFEXITED(x) (WTERMSIG (x) == 0)
  
  #else	/* Have <sys/wait.h> or not USG.  */
  
  #define WAIT_T union wait
  #define WTERMSIG(x) ((x).w_termsig)
  #define WCOREDUMP(x) ((x).w_coredump)
! #define WEXITSTATUS(x) ((x).w_retcode)
! #ifndef	WIFSIGNALED
! #define	WIFSIGNALED(x)	(WTERMSIG(x) != 0)
  #endif
  
  #endif	/* USG and don't have <sys/wait.h>.  */
  
+ #endif	/* WTERMSIG.  */
  
+ 
  extern int fork (), wait (), kill (), getpid ();
  extern void _exit ();
  
  #ifndef	USG
+ #ifndef sigmask
+ #define sigmask(sig) (1 << ((sig) - 1))
+ #endif
  extern int sigsetmask ();
  #endif
  
+ #ifdef USG
+ #include <sys/param.h>
+ #define getdtablesize() NOFILE
+ #endif
+ 
  extern void block_remote_children (), unblock_remote_children ();
  extern double load_average ();
  extern int start_remote_job_p ();
***************
*** 76,87 ****
  extern int start_remote_job (), remote_status ();
  
  
! #ifdef USG
  static char *sys_siglist[NSIG];
  void init_siglist ();
! #else	/* Not USG.  */
  extern char *sys_siglist[];
! #endif	/* USG.  */
  \f


  /* Chain of all children.  */
  
--- 91,104 ----
  extern int start_remote_job (), remote_status ();
  
  
! #if	defined(USG) && !defined(HAVE_SIGLIST)
  static char *sys_siglist[NSIG];
  void init_siglist ();
! #else	/* Not USG and or HAVE_SIGLIST.  */
  extern char *sys_siglist[];
! #endif	/* USG and not HAVE_SIGLIST.  */
! 
! int child_handler ();
  \f


  /* Chain of all children.  */
  
***************
*** 206,212 ****
  	  else
  	    {
  	      /* Chop the status word up.  */
! 	      exit_code = WRETCODE (status);
  	      exit_sig = WIFSIGNALED (status) ? WTERMSIG (status) : 0;
  	      coredump = WCOREDUMP (status);
  	    }
--- 223,229 ----
  	  else
  	    {
  	      /* Chop the status word up.  */
! 	      exit_code = WEXITSTATUS (status);
  	      exit_sig = WIFSIGNALED (status) ? WTERMSIG (status) : 0;
  	      coredump = WCOREDUMP (status);
  	    }
***************
*** 281,287 ****
  		}
  
  	      /* If there are more commands to run, try to start them.  */
! 	      if (!start_job (c))
  		if (c->file->command_state == cs_running)
  		  /* Successfully started.  Loop to reap more children.  */
  		  continue;
--- 298,311 ----
  		}
  
  	      /* If there are more commands to run, try to start them.  */
! 	      if (start_job (c))
! 		{
! 		  /* We failed to start the commands.  */
! 		  c->file->update_status
! 		    = (just_print_flag || touch_flag) ? 0 : 1;
! 		  delete_child_targets (c);
! 		}
! 	      else
  		if (c->file->command_state == cs_running)
  		  /* Successfully started.  Loop to reap more children.  */
  		  continue;
***************
*** 288,299 ****
  		else
  		  /* There were no more commands.  */
  		  c->file->update_status = 0;
- 	      else
- 		{
- 		  /* We failed to start the commands.  */
- 		  c->file->update_status = 1;
- 		  delete_child_targets (c);
- 		}
  	    }
  
  	  /* Set the state flag to say the commands have finished.  */
--- 312,317 ----
***************
*** 352,358 ****
    if (err && (children != 0 || shell_function_pid != 0))
      {
        fflush (stdout);
!       error ("*** Waiting for children....");
      }
  
    /* Call child_handler to do the work.  */
--- 370,376 ----
    if (err && (children != 0 || shell_function_pid != 0))
      {
        fflush (stdout);
!       error ("*** Waiting for unfinished jobs....");
      }
  
    /* Call child_handler to do the work.  */
***************
*** 361,366 ****
--- 379,386 ----
    unblock_children ();
  }
  \f


+ static void exec_command ();
+ 
  /* Start a job to run the commands specified in CHILD.
     CHILD is updated to reflect the commands and ID of the child process.  */
  
***************
*** 450,463 ****
        ++p;
      }
  
!   /* If -q or -t was given, just say that updating `failed'.  */
!   if ((question_flag || touch_flag) && !recursive)
      return 1;
  
    /* There may be some preceding whitespace left if there
       was nothing but a backslash on the first line.  */
!   while (*p == ' ' || *p == '\t')
!     ++p;
  
    if (*p == '\0')
      /* There were no commands on this line.  Go to the next.  */
--- 470,482 ----
        ++p;
      }
  
!   /* If -q was given, just say that updating `failed'.  */
!   if (question_flag && !recursive)
      return 1;
  
    /* There may be some preceding whitespace left if there
       was nothing but a backslash on the first line.  */
!   p = next_token (p);
  
    if (*p == '\0')
      /* There were no commands on this line.  Go to the next.  */
***************
*** 547,552 ****
--- 566,572 ----
  	{
  	  /* We are the child side.  */
  	  extern char **environ;
+ 	  char *path;
  
  	  if (!child->good_stdin)
  	    /* We get the `bad' standard input.  */
***************
*** 560,570 ****
  	      (void) close (d);
  	  }
  
  	  /* Run the command.  */
! 	  environ = child->environment;
! 	  (void) execvp (argv[0], argv);
! 	  perror_with_name ("execvp: ", argv[0]);
! 	  _exit (127);
  	}
        else if (child->pid < 0)
  	{
--- 580,605 ----
  	      (void) close (d);
  	  }
  
+ 	  /* Don't block children for our child.  */
+ 	  unblock_children ();
+ 
+ 	  path = allocated_variable_expand_for_file ("$(PATH)", child->file);
+ 
  	  /* Run the command.  */
! 	  exec_command (argv, child->environment, path);
! 
! 	  /* If exec_command returned, then we should use the shell.  */
! 	  {
! 	    argv = (char **) alloca (4 * sizeof (char *));
! 	    argv[0] = variable_expand_for_file ("$(SHELL)", child->file);
! 	    argv[1] = "-c";
! 	    argv[2] = p;
! 	    argv[3] = 0;
! 	    exec_command (argv, child->environment, path);
! 
! 	    /* If that returned, die.  */
! 	    _exit (127);
! 	  }
  	}
        else if (child->pid < 0)
  	{
***************
*** 580,585 ****
--- 615,708 ----
    child->file->command_state = cs_running;
    return 0;
  }
+ 
+ /* Replace the current process with one running the command
+    in ARGV, with environment ENVP.  The program named in ARGV[0]
+    is searched for in PATH.  This function does not return.  */
+ 
+ static void
+ exec_command (argv, envp, path)
+      char **argv, **envp;
+      char *path;
+ {
+   char *program;
+ 
+   if (*path == '\0' || index (argv[0], '/') != 0)
+     program = argv[0];
+   else
+     {
+       unsigned int len;
+ 
+ #ifndef	USG
+       extern int getgroups ();
+       static int groups[NGROUPS];
+       static int ngroups = -1;
+       if (ngroups == -1)
+ 	ngroups = getgroups (NGROUPS, groups);
+ #endif	/* Not USG.  */
+ 
+       len = strlen (argv[0]) + 1;
+       program = (char *) alloca (strlen (path) + 1 + len);
+       do
+ 	{
+ 	  struct stat st;
+ 	  int perm;
+ 	  char *p;
+ 
+ 	  p = index (path, ':');
+ 	  if (p == 0)
+ 	    p = path + strlen (path);
+ 
+ 	  if (p == path)
+ 	    bcopy (argv[0], program, len);
+ 	  else
+ 	    {
+ 	      bcopy (path, program, p - path);
+ 	      program[p - path] = '/';
+ 	      bcopy (argv[0], program + (p - path) + 1, len);
+ 	    }
+ 
+ 	  if (stat (program, &st) == 0
+ 	      && (st.st_mode & S_IFMT) == S_IFREG)
+ 	    {
+ 	      if (st.st_uid == geteuid ())
+ 		perm = st.st_mode & 07;
+ 	      else if (st.st_gid == getegid ())
+ 		perm = (st.st_mode & 070) >> 3;
+ 	      else
+ 		{
+ #ifndef	USG
+ 		  register int i;
+ 		  for (i = 0; i < ngroups; ++i)
+ 		    if (groups[i] == st.st_gid)
+ 		      break;
+ 		  if (i < ngroups)
+ 		    perm = (st.st_mode & 070) >> 3;
+ 		  else
+ #endif	/* Not USG.  */
+ 		    perm = (st.st_mode & 0700) >> 6;
+ 		}
+ 
+ 	      if (perm & 1)
+ 		goto run;
+ 	    }
+ 
+ 	  path = p + 1;
+ 	} while (*path != '\0');
+ 
+       error ("%s: Command not found", argv[0]);
+       _exit (127);
+     }
+ 
+  run:;
+   execve (program, argv, envp);
+ 
+   if (errno != ENOEXEC)
+     {
+       perror_with_name ("execve: ", program);
+       _exit (127);
+     }
+ }
  \f


  /* Figure out the argument list necessary to run LINE as a command.
     Try to avoid using a shell.  This routine handles only ' quoting.
***************
*** 677,684 ****
  	      }
  
  	    /* Ignore multiple whitespace chars.  */
! 	    while (*p == ' ' || *p == '\t')
! 	      ++p;
  	    /* Next iteration should examine the first nonwhite char.  */
  	    --p;
  	    break;
--- 800,806 ----
  	      }
  
  	    /* Ignore multiple whitespace chars.  */
! 	    p = next_token (p);
  	    /* Next iteration should examine the first nonwhite char.  */
  	    --p;
  	    break;
***************
*** 714,720 ****
    return new_argv;
  }
  \f


! #ifdef	USG
  /* Initialize sys_siglist.  */
  
  void
--- 836,842 ----
    return new_argv;
  }
  \f


! #if	defined(USG) && !defined(HAVE_SIGLIST)
  /* Initialize sys_siglist.  */
  
  void
***************
*** 863,870 ****
  #endif
        }
  }
  
- #ifndef	USGr3
  int
  dup2 (old, new)
       int old, new;
--- 985,997 ----
  #endif
        }
  }
+ #endif	/* USG and not HAVE_SIGLIST.  */
+ 
+ #if	defined(USG) && !defined(USGr3) && !defined(HAVE_DUP2)
+ 
+ #include <errno.h>
+ extern int errno;
  
  int
  dup2 (old, new)
       int old, new;
***************
*** 882,887 ****
  
    return fd;
  }
! #endif	/* Not USGr3.  */
! 
! #endif	/* USG.  */
--- 1009,1012 ----
  
    return fd;
  }
! #endif	/* USG and not USGr3 and not HAVE_DUP2.  */
diff -rc make-3.54/load.c make-3.55/load.c
*** make-3.54/load.c	Sun Jun 11 23:23:30 1989
--- make-3.55/load.c	Fri Jul 14 14:21:41 1989
***************
*** 137,143 ****
  {
    LDAV_TYPE load;
    static int kmem = -1;
!   static long int offset = -1;
  
    if (kmem < 0)
      {
--- 137,143 ----
  {
    LDAV_TYPE load;
    static int kmem = -1;
!   static unsigned long int offset = 0;
  
    if (kmem < 0)
      {
***************
*** 146,152 ****
  	return 0.0;
      }
  
!   if (offset < 0)
      {
        struct nlist nl[2];
  
--- 146,152 ----
  	return 0.0;
      }
  
!   if (offset == 0)
      {
        struct nlist nl[2];
  
***************
*** 160,166 ****
  
        if (nlist (KERNEL_FILE, nl) < 0 || nl[0].n_type == 0)
  	return 0.0;
!       offset = (long int) nl[0].n_value;
      }
  
    if (lseek (kmem, offset, 0) < 0L)
--- 160,166 ----
  
        if (nlist (KERNEL_FILE, nl) < 0 || nl[0].n_type == 0)
  	return 0.0;
!       offset = nl[0].n_value;
      }
  
    if (lseek (kmem, offset, 0) < 0L)
diff -rc make-3.54/main.c make-3.55/main.c
*** make-3.54/main.c	Sun Jun 11 23:23:29 1989
--- make-3.55/main.c	Fri Aug 11 05:13:41 1989
***************
*** 261,268 ****
  
  struct file *default_file;
  \f


- extern int glob_tilde;
- 
  extern char **environ;
  
  int
--- 261,266 ----
***************
*** 506,512 ****
  	       and thus re-read the makefiles, we read standard input
  	       into a temporary file and read from that.  */
  	    static char name[] = "/tmp/GmXXXXXX";
- 	    unsigned int len;
  	    FILE *outfile;
  
  	    /* Free the storage allocated for "-".  */
--- 504,509 ----
***************
*** 744,790 ****
  	}
      }
  
-   /* If there were no command-line goals, use the default.  */
- 
-   if (goals == 0)
-     {
-       if (default_goal_file == 0)
- 	fatal ("no goal target");
-       goals = (struct dep *) xmalloc (sizeof (struct dep));
-       goals->next = 0;
-       goals->name = 0;
-       goals->file = default_goal_file;
-     }
-   else
-     lastgoal->next = 0;
- 
-   /* Update the goals.  */
- 
    {
      int status;
  
!     if (debug_flag)
!       puts ("Updating goal targets....");
  
!     switch (update_goal_chain (goals, 0))
        {
!       case -1:
! 	/* Nothing happened.  */
!       case 0:
! 	/* Updated successfully.  */
! 	status = 0;
! 	break;
!       case 1:
! 	/* Updating failed.  */
! 	status = 1;
! 	break;
!       default:
! 	abort ();
        }
  
      /* Print the data base under -p.  */
      if (print_data_base_flag)
        print_data_base ();
  
      /* Exit.  */
      die (status);
--- 741,793 ----
  	}
      }
  
    {
      int status;
  
!     /* If there were no command-line goals, use the default.  */
!     if (goals == 0)
!       {
! 	if (default_goal_file != 0)
! 	  {
! 	    goals = (struct dep *) xmalloc (sizeof (struct dep));
! 	    goals->next = 0;
! 	    goals->name = 0;
! 	    goals->file = default_goal_file;
! 	  }
!       }
!     else
!       lastgoal->next = 0;
  
!     if (goals != 0)
        {
! 	/* Update the goals.  */
! 
! 	if (debug_flag)
! 	  puts ("Updating goal targets....");
! 
! 	switch (update_goal_chain (goals, 0))
! 	  {
! 	  case -1:
! 	    /* Nothing happened.  */
! 	  case 0:
! 	    /* Updated successfully.  */
! 	    status = 0;
! 	    break;
! 	  case 1:
! 	    /* Updating failed.  */
! 	    status = 1;
! 	    break;
! 	  default:
! 	    abort ();
! 	  }
        }
  
      /* Print the data base under -p.  */
      if (print_data_base_flag)
        print_data_base ();
+ 
+     if (goals == 0)
+       fatal ("No targets");
  
      /* Exit.  */
      die (status);
diff -rc make-3.54/make.h make-3.55/make.h
*** make-3.54/make.h	Sun Jun 11 22:08:02 1989
--- make-3.55/make.h	Fri Jul 21 19:26:20 1989
***************
*** 17,23 ****
--- 17,32 ----
  
  #include <signal.h>
  #include <stdio.h>
+ 
+ #ifndef	sun
  #include <sys/types.h>
+ #endif
+ 
+ #include <sys/param.h>
+ #ifndef MAXPATHLEN
+ #define MAXPATHLEN 1024
+ #endif	/* No MAXPATHLEN.  */
+ 
  #include <sys/stat.h>
  
  #ifdef	USG
***************
*** 47,57 ****
  extern char *alloca ();
  #endif	/* sparc.  */
  #endif	/* GCC.  */
- 
- #include <sys/param.h>
- #ifndef MAXPATHLEN
- #define MAXPATHLEN 1024
- #endif	/* No MAXPATHLEN.  */
  
  #ifndef	iAPX286
  #define streq(a, b) \
--- 56,61 ----
diff -rc make-3.54/make.texinfo make-3.55/make.texinfo
*** make-3.54/make.texinfo	Mon Jun 19 20:15:35 1989
--- make-3.55/make.texinfo	Sat Aug 26 16:25:57 1989
***************
*** 50,60 ****
  @sp 2
  @center by Richard M. Stallman and Roland McGrath
  @sp 3
! @center Edition 0.22 Beta,
  @sp 1
! @center last updated 11 June 1989,
  @sp 1
! @center for @code{make}, Version 3.51 Beta.
  @page
  @vskip 0pt plus 1filll
  Copyright @copyright{} 1988, 1989 Free Software Foundation, Inc.
--- 50,60 ----
  @sp 2
  @center by Richard M. Stallman and Roland McGrath
  @sp 3
! @center Edition 0.23 Beta,
  @sp 1
! @center last updated 26 August 1989,
  @sp 1
! @center for @code{make}, Version 3.55 Beta.
  @page
  @vskip 0pt plus 1filll
  Copyright @copyright{} 1988, 1989 Free Software Foundation, Inc.
***************
*** 61,68 ****
  @sp 2
  
  This is Edition 0.22 Beta of the @cite{GNU Make Manual}, @*
! last updated 11 June 1989, @*
! for @code{make} Version 3.51 Beta.
  
  @sp 2
  Published by the Free Software Foundation @*
--- 61,68 ----
  @sp 2
  
  This is Edition 0.22 Beta of the @cite{GNU Make Manual}, @*
! last updated 26 August 1989, @*
! for @code{make} Version 3.55 Beta.
  
  @sp 2
  Published by the Free Software Foundation @*
***************
*** 873,879 ****
  warning message is generated, but it is not a fatal error; processing
  of the makefile containing the @code{include} continues.@refill
  
! @node MAKEFILES Variable, Remaking Makefiles, Include, Makefiles
  @section The Variable @code{MAKEFILES}
  
  @vindex MAKEFILES
--- 873,879 ----
  warning message is generated, but it is not a fatal error; processing
  of the makefile containing the @code{include} continues.@refill
  
! @node MAKEFILES Variable, Remaking Makefiles, Makefile Names, Makefiles
  @section The Variable @code{MAKEFILES}
  
  @vindex MAKEFILES
***************
*** 919,924 ****
--- 919,933 ----
  each of them over again, but normally this will not change them again,
  since they are already up to date.)@refill
  
+ If the makefiles specify commands to remake a file but no dependencies,
+ the file will always be remade.  In the case of makefiles, a makefile
+ that has commands but no dependencies will be remade every time
+ @code{make} is run, and then again after @code{make} starts over and
+ reads the makefiles in again.  This would cause an infinite loop;
+ @code{make} would constantly remake the makefile, and never do anything
+ else.  So, to avoid this, @code{make} will @emph{not} attempt to remake
+ makefiles which are specified as targets but have no dependencies.@refill
+ 
  If you do not specify any makefiles to be read with @samp{-f} options,
  @code{make} will try the default makefile names; @pxref{Makefile Names}.
  Unlike makefiles explicitly requested with @samp{-f} options,
***************
*** 1162,1168 ****
         using the function @code{wildcard}.
  @end menu
  
! @node Wildcard Examples, Wildcard Pitfall,  , Wildcards
  @subsection Wildcard Examples
  
  Wildcards can be used in the commands of a rule.  For example, here is a
--- 1171,1177 ----
         using the function @code{wildcard}.
  @end menu
  
! @node Wildcard Examples, Wildcard Pitfall, Wildcards, Wildcards
  @subsection Wildcard Examples
  
  Wildcards can be used in the commands of a rule.  For example, here is a
***************
*** 1381,1389 ****
  string must match the filename of a dependency that is being searched for,
  the @samp{%} character matching any sequence of zero or more characters (as
  in pattern rules; @pxref{Pattern Rules}).  (If there is no @samp{%}, the
! pattern must match the dependency, which is not really useful.  Since
! this is probably not what you want, @code{make} will give you a warning
! if there is no @samp{%} in a @code{vpath} directive's pattern.)
  
  @samp{%} characters in a @code{vpath} directive's pattern can be quoted
  with preceding backslashes (@samp{\}).  Backslashes that would otherwise
--- 1390,1396 ----
  string must match the filename of a dependency that is being searched for,
  the @samp{%} character matching any sequence of zero or more characters (as
  in pattern rules; @pxref{Pattern Rules}).  (If there is no @samp{%}, the
! pattern must match the dependency, which is not useful very often.)
  
  @samp{%} characters in a @code{vpath} directive's pattern can be quoted
  with preceding backslashes (@samp{\}).  Backslashes that would otherwise
***************
*** 1399,1405 ****
  example,
  
  @example
! vpath *.h ../headers
  @end example
  
  @noindent
--- 1406,1412 ----
  example,
  
  @example
! vpath %.h ../headers
  @end example
  
  @noindent
***************
*** 1705,1711 ****
  @samp{.}, so these special target names also begin with @samp{.}.
  @xref{Suffix Rules}.
  
! @node Multiple Targets, Multiple Rules, Special Targets, Rules
  @section Multiple Targets in a Rule
  
  A rule with multiple targets is equivalent to writing many rules, each with
--- 1712,1718 ----
  @samp{.}, so these special target names also begin with @samp{.}.
  @xref{Suffix Rules}.
  
! @node Multiple Targets, Static Pattern, Special Targets, Rules
  @section Multiple Targets in a Rule
  
  A rule with multiple targets is equivalent to writing many rules, each with
***************
*** 2327,2339 ****
  
  Most variable values of the top-level @code{make} are passed to the
  sub-@code{make} through the environment.  These variables are defined in
! the sub-@code{make} as defaults, but do not override what is specified in
! the sub-@code{make}'s makefile.  (Variables are passed down if their names
! consist of letters, numbers and underscores.)
  
! The way this works is that @code{make} adds each variable and its value to
! the environment for running each command.  (Variables whose names start
! with non-alphanumeric characters are left out.)  The sub-@code{make}, in
  turn, uses the environment to initialize its table of variable values.
  @xref{Environment}.
  
--- 2334,2353 ----
  
  Most variable values of the top-level @code{make} are passed to the
  sub-@code{make} through the environment.  These variables are defined in
! the sub-@code{make} as defaults, but do not override what is specified
! in the sub-@code{make}'s makefile.
! 
! Variables are passed down if their names consist only of letters,
! numbers and underscores.  Some shells cannot cope with environment
! variable names consisting of characters other than letters, numbers,
! and underscores.
! 
! Variable are @emph{not} passed down if they were created by default by
! @code{make} (@pxref{Implicit Variables}).  The sub-@code{make} will
! define these for itself.@refill
  
! The way this works is that @code{make} adds each variable and its value
! to the environment for running each command.  The sub-@code{make}, in
  turn, uses the environment to initialize its table of variable values.
  @xref{Environment}.
  
***************
*** 4512,4517 ****
--- 4526,4535 ----
  
  * Pattern Rules::        Defining new implicit rules.
  
+ * Last Resort::          Defining commands for rules which can't find any.
+ 
+ * Suffix Rules::         The old-fashioned style of implicit rule.
+ 
  * Search Algorithm::     Precise algorithm for applying implicit rules.
  @end menu
  
***************
*** 5257,5265 ****
  
  @item $(%D)
  @itemx $(%F)
! The directory part and the file-within-directory
! part of the target archive member name.  This is meaningful only for
! archive member targets of the form @file{@var{archive}(@var{member})}
  and useful only when @var{member} may contain a directory name.
  (@xref{Archive Members}.)
  
--- 5275,5283 ----
  
  @item $(%D)
  @itemx $(%F)
! The directory part and the file-within-directory part of the target
! archive member name.  This makes sense only for archive member
! targets of the form @file{@var{archive}(@var{member})}
  and useful only when @var{member} may contain a directory name.
  (@xref{Archive Members}.)
  
***************
*** 5656,5661 ****
--- 5674,5680 ----
                                  as a target or dependency.
  * Update: Archive Update.      An implicit rule can update
                                  most archive member targets just right.
+ * Symbols: Archive Symbols.    Special things to do for library archives.
  @end menu
  
  @node Archive Members, Archive Update, Archives, Archives
diff -rc make-3.54/misc.c make-3.55/misc.c
*** make-3.54/misc.c	Sun Jun 11 17:29:42 1989
--- make-3.55/misc.c	Tue Jul 11 07:45:39 1989
***************
*** 83,90 ****
  	 and any preceding whitespace; leave just one space.  */
        if (backslash)
  	{
! 	  while (*in == ' ' || *in == '\t')
! 	    ++in;
  	  while (out > line && (out[-1] == ' ' || out[-1] == '\t'))
  	    --out;
  	  *out++ = ' ';
--- 83,89 ----
  	 and any preceding whitespace; leave just one space.  */
        if (backslash)
  	{
! 	  in = next_token (in);
  	  while (out > line && (out[-1] == ' ' || out[-1] == '\t'))
  	    --out;
  	  *out++ = ' ';
***************
*** 155,161 ****
  	}
  
        /* strcpy better copy left to right.  */
!       line = p + 1;
        strcpy (p2 + 1 + bs_write, line);
      }
  }
--- 154,160 ----
  	}
  
        /* strcpy better copy left to right.  */
!       line = p;
        strcpy (p2 + 1 + bs_write, line);
      }
  }
diff -rc make-3.54/read.c make-3.55/read.c
*** make-3.54/read.c	Tue Jun 20 21:38:11 1989
--- make-3.55/read.c	Tue Aug 15 00:03:25 1989
***************
*** 22,27 ****
--- 22,28 ----
  #include "variable.h"
  
  #include <pwd.h>
+ struct passwd *getpwnam ();
  
  
  static void read_makefile ();
***************
*** 295,311 ****
  	}
        strcpy (collapsed, lb.buffer);
        collapse_line (collapsed);
!       
!       p = collapsed;
!       while (*p == ' ' || *p == '\t' || *p == '\f')
! 	++p;
        if (*p == '\0')
  	continue;
  
-       p = lb.buffer;
-       while (*p == ' ' || *p == '\f')
- 	++p;
- 
  #define	word1eq(s, l) 	((p[l] == '\0' || p[l] == ' ' || p[l] == '\t') && \
  			 !strncmp (s, p, l))
        if (word1eq ("ifdef", 5) || word1eq ("ifndef", 6)
--- 296,306 ----
  	}
        strcpy (collapsed, lb.buffer);
        collapse_line (collapsed);
! 
!       p = next_token (collapsed);
        if (*p == '\0')
  	continue;
  
  #define	word1eq(s, l) 	((p[l] == '\0' || p[l] == ' ' || p[l] == '\t') && \
  			 !strncmp (s, p, l))
        if (word1eq ("ifdef", 5) || word1eq ("ifndef", 6)
***************
*** 312,318 ****
  	  || word1eq ("ifeq", 4) || word1eq ("ifneq", 5)
  	  || word1eq ("else", 4) || word1eq ("endif", 5))
  	{
! 	  int i = conditional_line (collapsed, filename, lineno);
  	  if (i >= 0)
  	    {
  	      ignoring = i;
--- 307,313 ----
  	  || word1eq ("ifeq", 4) || word1eq ("ifneq", 5)
  	  || word1eq ("else", 4) || word1eq ("endif", 5))
  	{
! 	  int i = conditional_line (p, filename, lineno);
  	  if (i >= 0)
  	    {
  	      ignoring = i;
***************
*** 323,333 ****
  	}
        if (ignoring)
  	continue;
        else if (word1eq ("define", 6))
  	{
! 	  p = collapsed;
! 	  p += 6;
! 	  p2 = next_token (p);
  	  p = end_of_token (p2);
  	  lineno = do_define (p2, p - p2, o_file, lineno, infile, filename);
  	  continue;
--- 318,349 ----
  	}
        if (ignoring)
  	continue;
+       else if (lb.buffer[0] == '\t')
+ 	{
+ 	  /* This line is a shell command.  */
+ 	  unsigned int len;
+ 
+ 	  if (filenames == 0)
+ 	    fatal ("%s:%u: commands commence before first target",
+ 	           filename, lineno);
+ 
+ 	  /* Add this command line to end of the line being accumulated.  */
+ 	  p = lb.buffer;
+ 	  if (commands_idx == 0)
+ 	    commands_started = lineno;
+ 	  len = strlen (p);
+ 	  if (len + 1 + commands_idx > commands_len)
+ 	    {
+ 	      commands_len = (len + 1 + commands_idx) * 2;
+ 	      commands = (char *) xrealloc (commands, commands_len);
+ 	    }
+ 	  bcopy (p, &commands[commands_idx], len);
+ 	  commands_idx += len;
+ 	  commands[commands_idx++] = '\n';
+ 	}
        else if (word1eq ("define", 6))
  	{
! 	  p2 = next_token (p + 6);
  	  p = end_of_token (p2);
  	  lineno = do_define (p2, p - p2, o_file, lineno, infile, filename);
  	  continue;
***************
*** 336,351 ****
  	fatal ("%s:%u: extraneous `endef'", filename, lineno);
        else if (word1eq ("override", 8))
  	{
! 	  p = collapsed;
! 	  p += 8;
! 	  p2 = next_token (p);
  	  if (p2 == 0)
! 	    error ("%s:%u: Empty `override' directive", filename, lineno);
  	  if (!strncmp (p2, "define", 6))
  	    {
! 	      p = next_token (p2);
! 	      p2 = end_of_token (p);
! 	      lineno = do_define (p, p2 - p, o_override,
  				  lineno, infile, filename);
  	    }
  	  else if (!try_variable_definition (p2, o_override))
--- 352,365 ----
  	fatal ("%s:%u: extraneous `endef'", filename, lineno);
        else if (word1eq ("override", 8))
  	{
! 	  p2 = next_token (p + 8);
  	  if (p2 == 0)
! 	    error ("%s:%u: empty `override' directive", filename, lineno);
  	  if (!strncmp (p2, "define", 6))
  	    {
! 	      unsigned int len;
! 	      p = find_next_token (&p2, &len);
! 	      lineno = do_define (p, len, o_override,
  				  lineno, infile, filename);
  	    }
  	  else if (!try_variable_definition (p2, o_override))
***************
*** 358,376 ****
  	     makefile to be read at this point.  */
  	  struct conditionals *save = conditionals;
  	  struct conditionals new_conditionals;
! 	  p = collapsed;
! 	  p += 8;
! 	  p2 = p;
! 	  p = find_next_token (&p2, (unsigned int *) 0);
! 	  if (p == 0)
  	    {
  	      error ("%s:%u: no filename for `include'", filename, lineno);
  	      continue;
  	    }
! 	  p = allocated_variable_expand (p);
  	  bzero ((char *) &new_conditionals, sizeof new_conditionals);
  	  conditionals = &new_conditionals;
! 	  /* Record the rules that are waiting so will determine
  	     the default goal before those in the included makefile.  */
  	  record_waiting_files ();
  	  read_makefile (p, 2);
--- 372,394 ----
  	     makefile to be read at this point.  */
  	  struct conditionals *save = conditionals;
  	  struct conditionals new_conditionals;
! 	  p = allocated_variable_expand (next_token (p + 8));
! 	  if (*p == '\0')
  	    {
  	      error ("%s:%u: no filename for `include'", filename, lineno);
  	      continue;
  	    }
! 	  p2 = end_of_token (p);
! 	  if (*p2 != '\0')
! 	    {
! 	      *p2++ = '\0';
! 	      if (*next_token (p2) != '\0')
! 		error ("%s:%u: extraneous text after `include'",
! 		       filename, lineno);
! 	    }
  	  bzero ((char *) &new_conditionals, sizeof new_conditionals);
  	  conditionals = &new_conditionals;
! 	  /* Record the rules that are waiting so they will determine
  	     the default goal before those in the included makefile.  */
  	  record_waiting_files ();
  	  read_makefile (p, 2);
***************
*** 384,405 ****
  	{
  	  char *pattern;
  	  unsigned int len;
! 	  p = collapsed;
! 	  p += 5;
! 	  p2 = variable_expand (p);
  	  p = find_next_token (&p2, &len);
  	  if (p != 0)
  	    {
  	      pattern = savestring (p, len);
- 	      if (find_percent (pattern) == 0)
- 		error ("%s:%u: `vpath' directive for explicit file name",
- 		       filename, lineno);
  	      p = find_next_token (&p2, &len);
  	      if (p != 0)
  		{
  		  p = savestring (p, len);
  		  if (find_next_token (&p2, (unsigned int *) 0) != 0)
! 		    error ("%s:%u: Extraneous text after `vpath' directive",
  			   filename, lineno);
  		}
  	      /* No searchpath means remove all previous
--- 402,418 ----
  	{
  	  char *pattern;
  	  unsigned int len;
! 	  p2 = variable_expand (p + 5);
  	  p = find_next_token (&p2, &len);
  	  if (p != 0)
  	    {
  	      pattern = savestring (p, len);
  	      p = find_next_token (&p2, &len);
  	      if (p != 0)
  		{
  		  p = savestring (p, len);
  		  if (find_next_token (&p2, (unsigned int *) 0) != 0)
! 		    error ("%s:%u: extraneous text after `vpath' directive",
  			   filename, lineno);
  		}
  	      /* No searchpath means remove all previous
***************
*** 416,445 ****
  	  continue;
  	}
  #undef	word1eq
!       else if (try_variable_definition (collapsed, o_file))
  	continue;
-       else if (*p == '\t')
- 	{
- 	  /* This line is a shell command.  */
- 	  unsigned int len;
- 
- 	  if (filenames == 0)
- 	    fatal ("%s:%u: commands commence before first target",
- 	           filename, lineno);
- 
- 	  /* Add this command line to end of the line being accumulated.  */
- 	  if (commands_idx == 0)
- 	    commands_started = lineno;
- 	  len = strlen (p);
- 	  if (len + 1 + commands_idx > commands_len)
- 	    {
- 	      commands_len = (len + 1 + commands_idx) * 2;
- 	      commands = (char *) xrealloc (commands, commands_len);
- 	    }
- 	  bcopy (p, &commands[commands_idx], len);
- 	  commands_idx += len;
- 	  commands[commands_idx++] = '\n';
- 	}
        else
  	{
  	  /* This line describes some target files.
--- 429,436 ----
  	  continue;
  	}
  #undef	word1eq
!       else if (try_variable_definition (p, o_file))
  	continue;
        else
  	{
  	  /* This line describes some target files.
***************
*** 719,728 ****
      {
        /* "Ifdef" or "ifndef".  */
        struct variable *v;
!       register char *p = line;
! 
!       while (*p != '\0' && *p != ' ' && *p != '\t')
! 	++p;
        i = p - line;
        p = next_token (p);
        if (*p != '\0')
--- 710,716 ----
      {
        /* "Ifdef" or "ifndef".  */
        struct variable *v;
!       register char *p = end_of_token (line);
        i = p - line;
        p = next_token (p);
        if (*p != '\0')
***************
*** 851,857 ****
    struct nameseq *nextf;
    int implicit = 0;
    unsigned int max_targets, target_idx;
!   char **targets = 0;
    struct commands *cmds;
  
    if (commands_idx > 0)
--- 839,845 ----
    struct nameseq *nextf;
    int implicit = 0;
    unsigned int max_targets, target_idx;
!   char **targets = 0, **target_percents = 0;
    struct commands *cmds;
  
    if (commands_idx > 0)
***************
*** 872,890 ****
        register struct file *f;
        register struct dep *d;
        struct dep *this;
!       int this_implicit;
  
        nextf = filenames->next;
        free ((char *) filenames);
  
!       this_implicit = find_percent (name) != 0;
!       implicit |= this_implicit;
  
        if (implicit && pattern != 0)
  	fatal ("%s:%u: mixed implicit and static pattern rules",
  	       filename, lineno);
  
!       if (implicit && !this_implicit)
  	fatal ("%s:%u: mixed implicit and normal rules", filename, lineno);
  
        if (implicit)
--- 860,878 ----
        register struct file *f;
        register struct dep *d;
        struct dep *this;
!       char *implicit_percent;
  
        nextf = filenames->next;
        free ((char *) filenames);
  
!       implicit_percent = find_percent (name);
!       implicit |= implicit_percent != 0;
  
        if (implicit && pattern != 0)
  	fatal ("%s:%u: mixed implicit and static pattern rules",
  	       filename, lineno);
  
!       if (implicit && implicit_percent == 0)
  	fatal ("%s:%u: mixed implicit and normal rules", filename, lineno);
  
        if (implicit)
***************
*** 893,898 ****
--- 881,887 ----
  	    {
  	      max_targets = 5;
  	      targets = (char **) xmalloc (5 * sizeof (char *));
+ 	      target_percents = (char **) xmalloc (5 * sizeof (char *));
  	      target_idx = 0;
  	    }
  	  else if (target_idx == max_targets - 1)
***************
*** 900,907 ****
  	      max_targets += 5;
  	      targets = (char **) xrealloc ((char *) targets,
  					    max_targets * sizeof (char *));
  	    }
! 	  targets[target_idx++] = name;
  	  continue;
  	}
  
--- 889,901 ----
  	      max_targets += 5;
  	      targets = (char **) xrealloc ((char *) targets,
  					    max_targets * sizeof (char *));
+ 	      target_percents
+ 		= (char **) xrealloc ((char *) target_percents,
+ 				      max_targets * sizeof (char *));
  	    }
! 	  targets[target_idx] = name;
! 	  target_percents[target_idx] = implicit_percent;
! 	  ++target_idx;
  	  continue;
  	}
  
***************
*** 915,921 ****
  	   `targets: target%pattern: dep%pattern; cmds',
  	   translate each dependency pattern into a plain filename
  	   using the target pattern and this target's name.  */
! 	if (!pattern_matches (pattern, name))
  	  {
  	    /* Give a warning if the rule is meaningless.  */
  	    error ("%s:%u: target `%s' doesn't match the target pattern",
--- 909,915 ----
  	   `targets: target%pattern: dep%pattern; cmds',
  	   translate each dependency pattern into a plain filename
  	   using the target pattern and this target's name.  */
! 	if (!pattern_matches (pattern, pattern_percent, name))
  	  {
  	    /* Give a warning if the rule is meaningless.  */
  	    error ("%s:%u: target `%s' doesn't match the target pattern",
***************
*** 1085,1091 ****
    if (implicit)
      {
        targets[target_idx] = 0;
!       create_pattern_rule (targets, two_colon, deps, cmds, 1);
      }
  }
  \f


--- 1079,1087 ----
    if (implicit)
      {
        targets[target_idx] = 0;
!       target_percents[target_idx] = 0;
!       create_pattern_rule (targets, target_percents, two_colon, deps, cmds, 1);
!       free ((char *) target_percents);
      }
  }
  \f


diff -rc make-3.54/remake.c make-3.55/remake.c
*** make-3.54/remake.c	Mon Jun 12 21:41:40 1989
--- make-3.55/remake.c	Tue Aug 22 05:20:58 1989
***************
*** 21,27 ****
--- 21,31 ----
  #include "file.h"
  #include <fcntl.h>
  
+ #ifndef USG
+ #include <sys/file.h>
+ #endif
  
+ 
  extern int open (), fstat (), read (), lseek (), write (), close ();
  extern time_t time ();
  
***************
*** 59,66 ****
--- 63,109 ----
    goals = copy_dep_chain (goals);
  
    if (makefiles)
+     /* Only run one job at a time.  */
      job_slots = 1;
  
+   if (makefiles)
+     {
+       register struct dep *g, *lastgoal;
+       lastgoal = 0;
+       g = goals;
+       while (g != 0)
+ 	{
+ 	  register struct file *f = g->file;
+ 	  if (f->is_target && f->deps == 0)
+ 	    {
+ 	      /* This makefile is a target, but has no dependencies.
+ 		 So, it will always be remade.  This might well cause
+ 		 an infinite loop, so don't try to remake it.
+ 		 (This will only happen if your makefiles are written
+ 		 exceptionally stupidly; but if you work for Athena,
+ 		 that is how you write makefiles.)  */
+ 
+ 	      if (debug_flag)
+ 		printf ("Makefile `%s' might loop; not remaking it.", f->name);
+ 
+ 	      if (lastgoal == 0)
+ 		goals = g->next;
+ 	      else
+ 		lastgoal->next = g->next;
+ 
+ 	      /* Free the storage.  */
+ 	      free ((char *) g);
+ 
+ 	      g = lastgoal == 0 ? 0 : lastgoal->next;
+ 	    }
+ 	  else
+ 	    {
+ 	      lastgoal = g;
+ 	      g = g->next;
+ 	    }
+ 	}
+     }	
+ 
    /* Update all the goals until they are all finished.  */
  
    while (goals != 0)
***************
*** 92,109 ****
  	  if (update_file (g->file, makefiles ? 1 : 0) != 0
  	      || g->file->updated)
  	    {
! 	      int stop;
  	      /* If STATUS was not already 1, set it to 1 if
  		 updating failed, or to 0 if updating succeeded.
  		 Leave STATUS as it is if no updating was done.  */
  	      if (status < 1)
! 		status = ((g->file->update_status != 0 && !makefiles) ? 1
! 			  : file_mtime (g->file) == mtime ? status : 0);
! 
! 	      /* Stop if this is a default makefile and was remade.  */
! 	      stop = (makefiles && g->file->dontcare
! 		      && g->file->update_status == 0
! 		      && file_mtime (g->file) != mtime);
  
  	      /* This goal is finished.  Remove it from the chain.  */
  	      if (lastgoal == 0)
--- 135,164 ----
  	  if (update_file (g->file, makefiles ? 1 : 0) != 0
  	      || g->file->updated)
  	    {
! 	      int stop = 0;
  	      /* If STATUS was not already 1, set it to 1 if
  		 updating failed, or to 0 if updating succeeded.
  		 Leave STATUS as it is if no updating was done.  */
  	      if (status < 1)
! 		{
! 		  if (g->file->update_status != 0 && !makefiles)
! 		    /* Updating failed on a regular target.  */
! 		    status = 1;
! 		  else if (file_mtime (g->file) != mtime)
! 		    {
! 		      /* Updating was done.
! 			 If this is a makefile and just_print_flag or
! 			 question_flag is set (meaning -n or -q was given
! 			 and this file was specified as a command-line target),
! 			 don't change STATUS.  If STATUS is changed, we will
! 			 get re-exec'd, and fall into an infinite loop.  */
! 		      if (!makefiles || (!just_print_flag && !question_flag))
! 			status = 0;
! 		      if (makefiles && g->file->dontcare)
! 			/* This is a default makefile.  Stop remaking.  */
! 			stop = 1;
! 		    }
! 		}
  
  	      /* This goal is finished.  Remove it from the chain.  */
  	      if (lastgoal == 0)
***************
*** 126,132 ****
  	    }
  	}
  
!       if ((status == 1 && !keep_going_flag) || (makefiles && status >= 0))
  	break;
      }
  
--- 181,187 ----
  	    }
  	}
  
!       if ((status > 0 && !keep_going_flag) || (makefiles && status >= 0))
  	break;
      }
  
***************
*** 175,182 ****
    /* For a top level target, if we have found nothing whatever to do for it,
       print a message saying nothing needs doing.  */
  
!   if (status == 0 && files_remade == ofiles_remade && commands_finished
!       && depth == 0 && !silent_flag && !question_flag)
      {
        printf ("%s: `%s' is up to date.\n", program, file->name);
        fflush (stdout);
--- 230,237 ----
    /* For a top level target, if we have found nothing whatever to do for it,
       print a message saying nothing needs doing.  */
  
!   if (status == 0 && !file->phony && files_remade == ofiles_remade
!       && commands_finished && depth == 0 && !silent_flag && !question_flag)
      {
        printf ("%s: `%s' is up to date.\n", program, file->name);
        fflush (stdout);
***************
*** 193,199 ****
       unsigned int depth;
  {
    register time_t this_mtime;
!   int must_make;
    int dep_status = 0;
    register struct dep *d, *lastd;
    char running = 0;
--- 248,254 ----
       unsigned int depth;
  {
    register time_t this_mtime;
!   int noexist, must_make, deps_changed;
    int dep_status = 0;
    register struct dep *d, *lastd;
    char running = 0;
***************
*** 233,253 ****
  
    /* Notice recursive update of the same file.  */
    file->updating = 1;
!   
    /* Looking at the file's modtime beforehand allows the possibility
       that its name may be changed by a VPATH search, and thus it may
       not need an implicit rule.  If this were not done, the file
       might get implicit commands that apply to its initial name, only
       to have that name replaced with another found by VPATH search.  */
!   
    this_mtime = file_mtime (file);
!   must_make = this_mtime == (time_t) -1;
!   if (must_make)
      DEBUGPR ("File `%s' does not exist.\n");
!   
    /* If file was specified as a target with no commands,
       come up with some default commands.  */
!   
    if (!file->phony && file->cmds == 0 && !file->tried_implicit)
      {
        if (try_implicit_rule (file, depth))
--- 288,310 ----
  
    /* Notice recursive update of the same file.  */
    file->updating = 1;
! 
    /* Looking at the file's modtime beforehand allows the possibility
       that its name may be changed by a VPATH search, and thus it may
       not need an implicit rule.  If this were not done, the file
       might get implicit commands that apply to its initial name, only
       to have that name replaced with another found by VPATH search.  */
! 
    this_mtime = file_mtime (file);
!   noexist = this_mtime == (time_t) -1;
!   if (noexist)
      DEBUGPR ("File `%s' does not exist.\n");
! 
!   must_make = noexist;
! 
    /* If file was specified as a target with no commands,
       come up with some default commands.  */
! 
    if (!file->phony && file->cmds == 0 && !file->tried_implicit)
      {
        if (try_implicit_rule (file, depth))
***************
*** 256,274 ****
  	{
  	  DEBUGPR ("No implicit rule found for `%s'.\n");
  	  if (default_file != 0 && default_file->cmds != 0)
! 	    file->cmds = default_file->cmds;
  	  file->also_make = 0;
  	}
        file->tried_implicit = 1;
      }
!   
    /* Update all non-intermediate files we depend on, if necessary,
       and see whether any of them is more recent than this file.  */
!   
    lastd = 0;
    d = file->deps;
    while (d != 0)
      {
        if (d->file->updating)
  	{
  	  error ("Circular %s <- %s dependency dropped.",
--- 313,336 ----
  	{
  	  DEBUGPR ("No implicit rule found for `%s'.\n");
  	  if (default_file != 0 && default_file->cmds != 0)
! 	    {
! 	      DEBUGPR ("Using default commands for `%s'.\n");
! 	      file->cmds = default_file->cmds;
! 	    }
  	  file->also_make = 0;
  	}
        file->tried_implicit = 1;
      }
! 
    /* Update all non-intermediate files we depend on, if necessary,
       and see whether any of them is more recent than this file.  */
! 
    lastd = 0;
    d = file->deps;
    while (d != 0)
      {
+       time_t mtime;
+ 
        if (d->file->updating)
  	{
  	  error ("Circular %s <- %s dependency dropped.",
***************
*** 288,293 ****
--- 350,356 ----
  	  continue;
  	}
  
+       mtime = file_mtime (d->file);
        d->file->parent = file;
        dep_status |= check_dep (d->file, depth, this_mtime, &must_make);
  
***************
*** 297,314 ****
        if (dep_status != 0 && !keep_going_flag)
  	break;
  
        lastd = d;
        d = d->next;
      }
!   
    /* Now we know whether this target needs updating.
       If it does, update all the intermediate files we depend on.  */
!   
    if (must_make)
      {
        for (d = file->deps; d != 0; d = d->next)
  	if (d->file->intermediate)
  	  {
  	    d->file->parent = file;
  	    dep_status |= update_file (d->file, depth);
  
--- 360,381 ----
        if (dep_status != 0 && !keep_going_flag)
  	break;
  
+       if (!running)
+ 	d->changed = file_mtime (d->file) != mtime;
+ 
        lastd = d;
        d = d->next;
      }
! 
    /* Now we know whether this target needs updating.
       If it does, update all the intermediate files we depend on.  */
! 
    if (must_make)
      {
        for (d = file->deps; d != 0; d = d->next)
  	if (d->file->intermediate)
  	  {
+ 	    time_t mtime = file_mtime (d->file);
  	    d->file->parent = file;
  	    dep_status |= update_file (d->file, depth);
  
***************
*** 317,331 ****
  
  	    if (dep_status != 0 && !keep_going_flag)
  	      break;
  	  }
      }
!   
    file->updating = 0;
!   
    DEBUGPR ("Finished dependencies of target file `%s'.\n");
!   
    /* If any dependency failed, give up now.  */
!   
    if (dep_status != 0)
      {
        file->command_state = cs_finished;
--- 384,401 ----
  
  	    if (dep_status != 0 && !keep_going_flag)
  	      break;
+ 
+ 	    if (!running)
+ 	      d->changed = file_mtime (d->file) != mtime;
  	  }
      }
! 
    file->updating = 0;
! 
    DEBUGPR ("Finished dependencies of target file `%s'.\n");
! 
    /* If any dependency failed, give up now.  */
! 
    if (dep_status != 0)
      {
        file->command_state = cs_finished;
***************
*** 336,347 ****
  
        DEBUGPR ("Giving up on target file `%s'.\n");
  
!       if (depth == 0 && keep_going_flag)
  	error ("Target `%s' not remade because of errors.", file->name);
  
        return dep_status;
      }
!   
    if (running)
      {
        file->command_state = cs_deps_running;
--- 406,418 ----
  
        DEBUGPR ("Giving up on target file `%s'.\n");
  
!       if (depth == 0 && keep_going_flag
! 	  && !just_print_flag && !question_flag)
  	error ("Target `%s' not remade because of errors.", file->name);
  
        return dep_status;
      }
! 
    if (running)
      {
        file->command_state = cs_deps_running;
***************
*** 354,366 ****
  
    /* Now record which dependencies are more
       recent than this file, so we can define $?.  */
!   
    for (d = file->deps; d != 0; d = d->next)
      {
!       d->changed
! 	= this_mtime == (time_t) -1 || file_mtime (d->file) > this_mtime;
!       
!       if (debug_flag && this_mtime != (time_t) -1)
  	{
  	  print_spaces (depth);
  	  printf ("Dependency `%s' is %s than dependent `%s'.\n",
--- 425,442 ----
  
    /* Now record which dependencies are more
       recent than this file, so we can define $?.  */
! 
!   deps_changed = 0;
    for (d = file->deps; d != 0; d = d->next)
      {
!       /* Set DEPS_CHANGED if this dep actually changed.  */
!       deps_changed |= d->changed;
! 
!       /* Set D->changed if either this dep actually changed,
! 	 or its dependent, FILE, is older or does not exist.  */
!       d->changed |= noexist || file_mtime (d->file) > this_mtime;
! 
!       if (debug_flag && !noexist)
  	{
  	  print_spaces (depth);
  	  printf ("Dependency `%s' is %s than dependent `%s'.\n",
***************
*** 369,387 ****
  	  fflush (stdout);
  	}
      }
!   
    /* Here depth returns to the value it had when we were called.  */
    depth--;
  
!   if (file->deps == 0 && file->double_colon)
      {
        must_make = 1;
!       DEBUGPR ("Target `%s' is double-colon and has no dependencies.\n");
      }
  
    if (!must_make)
      {
!       DEBUGPR ("No need to remake target file `%s'.\n");
        file->command_state = cs_finished;
        file->update_status = 0;
        file->updated = 1;
--- 445,468 ----
  	  fflush (stdout);
  	}
      }
! 
    /* Here depth returns to the value it had when we were called.  */
    depth--;
  
!   if (file->deps == 0 && file->cmds != 0)
      {
        must_make = 1;
!       DEBUGPR ("Target `%s' has commands but no dependencies.\n");
!     }
!   else if (!deps_changed && file->cmds == 0)
!     {
!       must_make = 0;
!       DEBUGPR ("No commands for `%s' and no dependencies actually changed.\n");
      }
  
    if (!must_make)
      {
!       DEBUGPR ("No need to remake target `%s'.\n");
        file->command_state = cs_finished;
        file->update_status = 0;
        file->updated = 1;
***************
*** 388,394 ****
        return 0;
      }
  
!   DEBUGPR ("Must remake target file `%s'.\n");
  
    /* Now, take appropriate actions to remake the file.  */
    file->update_status = remake_file (file);
--- 469,475 ----
        return 0;
      }
  
!   DEBUGPR ("Must remake target `%s'.\n");
  
    /* Now, take appropriate actions to remake the file.  */
    file->update_status = remake_file (file);
***************
*** 414,423 ****
       register struct file *file;
  {
    file->updated = 1;
!   if (just_print_flag)
!     file->last_mtime = time ((time_t *) 0);
!   else
!     file->last_mtime = name_mtime (file->name);
  
    if (file->also_make != 0)
      {
--- 495,515 ----
       register struct file *file;
  {
    file->updated = 1;
! 
!   if (!file->phony)
!     {
!       if (just_print_flag || question_flag || file->cmds == 0)
! 	{
! 	  file->last_mtime = time ((time_t *) 0);
! 	  ++files_remade;
! 	}
!       else
! 	{
! 	  file->last_mtime = 0;
! 	  if (file->update_status != -1)
! 	    ++files_remade;
! 	}
!     }
  
    if (file->also_make != 0)
      {
***************
*** 427,436 ****
  	  register struct file *f = enter_file (file->also_make[i]);
  	  f->updated = 1;
  	  f->update_status = file->update_status;
! 	  if (just_print_flag)
  	    f->last_mtime = file->last_mtime;
  	  else
! 	    f->last_mtime = name_mtime (f->name);
  	}
      }
  
--- 519,528 ----
  	  register struct file *f = enter_file (file->also_make[i]);
  	  f->updated = 1;
  	  f->update_status = file->update_status;
! 	  if (just_print_flag || question_flag)
  	    f->last_mtime = file->last_mtime;
  	  else
! 	    f->last_mtime = 0;
  	}
      }
  
***************
*** 459,470 ****
  
    if (!file->intermediate)
      /* If this is a non-intermediate file, update it and record
!        whether it is newer than THIS_MTIME or doesn't exist.  */
      {
        time_t mtime;
        dep_status = update_file (file, depth);
        mtime = file_mtime (file);
!       if (mtime == (time_t) -1 || mtime > this_mtime)
  	*must_make_ptr = 1;
      }
    else
--- 551,562 ----
  
    if (!file->intermediate)
      /* If this is a non-intermediate file, update it and record
!        whether it is newer than THIS_MTIME.  */
      {
        time_t mtime;
        dep_status = update_file (file, depth);
        mtime = file_mtime (file);
!       if (mtime != (time_t) -1 && mtime > this_mtime)
  	*must_make_ptr = 1;
      }
    else
***************
*** 571,630 ****
  remake_file (file)
       struct file *file;
  {
-   int status;
- 
-   files_remade++;
- 
    if (file->cmds == 0 && !(touch_flag && !file->is_target))
      {
        if (file->phony)
! 	{
! 	  /* Phony target.  Pretend it succeeded.  */
! 	  status = 0;
! 	  file->command_state = cs_finished;
! 	}
        else if (file->is_target)
! 	{
! 	  /* This is a nonexistent target file we cannot make.
! 	     Pretend it was successfully remade.  */
! 	  file->last_mtime = time ((time_t *) 0);
! 	  status = 0;
! 	  file->command_state = cs_finished;
! 	}
        else
  	{
  	  /* This is a dependency file we cannot remake.  Fail.  */
! 	  static char nospec[] = "*** No way to make target";
  	  if (keep_going_flag || file->dontcare)
  	    {
  	      if (!file->dontcare)
! 		error ("%s `%s'.", nospec, file->name);
!  	      status = 1;
! 	      file->command_state = cs_finished;
  	    }
  	  else
! 	    fatal ("%s `%s'", nospec, file->name);
  	}
      }
    else
      {
!       if (touch_flag && file->cmds != 0 && !file->phony)
! 	/* Should set file's modification date and do nothing else.  */
! 	status = touch_file (file);
        else
! 	status = 0;
! 
!       if (!status)
! 	status = execute_file_commands (file);
      }
  
!   if (file->command_state == cs_finished)
!     {
!       file->update_status = status;
!       return notice_finished_file (file);
!     }
!   else
!     return 0;
  }
  \f


  /* Return the mtime of a file, given a struct file.
--- 663,707 ----
  remake_file (file)
       struct file *file;
  {
    if (file->cmds == 0 && !(touch_flag && !file->is_target))
      {
        if (file->phony)
! 	/* Phony target.  Pretend it succeeded.  */
! 	file->update_status = 0;
        else if (file->is_target)
! 	/* This is a nonexistent target file we cannot make.
! 	   Pretend it was successfully remade.  */
! 	file->update_status = 0;
        else
  	{
  	  /* This is a dependency file we cannot remake.  Fail.  */
! 	  static char noway[] = "*** No way to make target";
  	  if (keep_going_flag || file->dontcare)
  	    {
  	      if (!file->dontcare)
! 		error ("%s `%s'.", noway, file->name);
!  	      file->update_status = 1;
  	    }
  	  else
! 	    fatal ("%s `%s'", noway, file->name);
  	}
      }
    else
      {
!       if (touch_flag && !file->cmds->any_recurse)
! 	{
! 	  if (file->phony)
! 	    file->update_status = 0;
! 	  else
! 	    /* Should set file's modification date and do nothing else.  */
! 	    file->update_status = touch_file (file);
! 	}
        else
! 	return execute_file_commands (file);
      }
  
!   file->command_state = cs_finished;
!   return notice_finished_file (file);
  }
  \f


  /* Return the mtime of a file, given a struct file.
***************
*** 704,713 ****
    if (mtime == (time_t) -1)
      mtime = name_mtime (name + 4);
    if (mtime == (time_t) -1)
!     mtime = name_mtime (name + 8);
    if (mtime == (time_t) -1)
      {
!       char *newname = name;
        if (vpath_search (&newname))
  	{
  	  mtime = name_mtime (newname);
--- 781,790 ----
    if (mtime == (time_t) -1)
      mtime = name_mtime (name + 4);
    if (mtime == (time_t) -1)
!     mtime = name_mtime (name + 9);
    if (mtime == (time_t) -1)
      {
!       char *newname = name + 9;
        if (vpath_search (&newname))
  	{
  	  mtime = name_mtime (newname);
diff -rc make-3.54/rule.c make-3.55/rule.c
*** make-3.54/rule.c	Sun Jun 11 22:51:34 1989
--- make-3.55/rule.c	Tue Aug 15 00:10:06 1989
***************
*** 157,163 ****
        names = (char **) xmalloc (2 * sizeof (char *));
        names[0] = name;
        names[1] = 0;
!       create_pattern_rule (names, 0, (struct dep *) 0,
  			   (struct commands *) 0, 0);
  
        f = d->file;
--- 157,163 ----
        names = (char **) xmalloc (2 * sizeof (char *));
        names[0] = name;
        names[1] = 0;
!       create_pattern_rule (names, (char **) 0, 0, (struct dep *) 0,
  			   (struct commands *) 0, 0);
  
        f = d->file;
***************
*** 170,176 ****
  	  names = (char **) xmalloc (2 * sizeof (char *));
  	  names[0] = savestring ("%", 1);
  	  names[1] = 0;
! 	  create_pattern_rule (names, 0, newd, f->cmds, 0);
  	}
  
        /* Record a pattern for each of this suffix's two-suffix rules.  */
--- 170,176 ----
  	  names = (char **) xmalloc (2 * sizeof (char *));
  	  names[0] = savestring ("%", 1);
  	  names[1] = 0;
! 	  create_pattern_rule (names, (char **) 0, 0, newd, f->cmds, 0);
  	}
  
        /* Record a pattern for each of this suffix's two-suffix rules.  */
***************
*** 207,213 ****
  	  newd->name = (char *) xmalloc (1 + slen + 1);
  	  newd->name[0] = '%';
  	  bcopy (dep_name (d), newd->name + 1, slen + 1);
! 	  create_pattern_rule (names, 0, newd, f->cmds, 0);
  	}
      }
  }
--- 207,213 ----
  	  newd->name = (char *) xmalloc (1 + slen + 1);
  	  newd->name[0] = '%';
  	  bcopy (dep_name (d), newd->name + 1, slen + 1);
! 	  create_pattern_rule (names, (char **) 0, 0, newd, f->cmds, 0);
  	}
      }
  }
***************
*** 312,318 ****
    /* These will all be string literals, but we malloc space for
       them anyway because somebody might want to free them later on.  */
    r->targets[0] = savestring (p->target, r->lens[0]);
!   r->suffixes[0] = index (r->targets[0], '%') + 1;
  
    ptr = p->dep;
    r->deps = (struct dep *) multi_glob (parse_file_seq (&ptr, '\0',
--- 312,323 ----
    /* These will all be string literals, but we malloc space for
       them anyway because somebody might want to free them later on.  */
    r->targets[0] = savestring (p->target, r->lens[0]);
!   r->suffixes[0] = find_percent (r->targets[0]);
!   if (r->suffixes[0] == 0)
!     /* Programmer-out-to-lunch error.  */
!     abort ();
!   else
!     ++r->suffixes[0];
  
    ptr = p->dep;
    r->deps = (struct dep *) multi_glob (parse_file_seq (&ptr, '\0',
***************
*** 378,391 ****
  }
  \f


  /* Create a new pattern rule with the targets in the nil-terminated
!    array TARGETS.  The new rule has dependencies DEPS and commands
!    from COMMANDS.  It is a terminal rule if TERMINAL is nonzero.
!    This rule overrides identical rules with different commands if
!    OVERRIDE is nonzero.  */
  
  void
! create_pattern_rule (targets, terminal, deps, commands, override)
!      char **targets;
       int terminal;
       struct dep *deps;
       struct commands *commands;
--- 383,402 ----
  }
  \f


  /* Create a new pattern rule with the targets in the nil-terminated
!    array TARGETS.  If TARGET_PERCENTS is not nil, it is an array of
!    pointers into the elements of TARGETS, where the `%'s are.
!    The new rule has dependencies DEPS and commands from COMMANDS.
!    It is a terminal rule if TERMINAL is nonzero.  This rule overrides
!    identical rules with different commands if OVERRIDE is nonzero.
! 
!    The storage for TARGETS and its elements is used and must not be freed
!    until the rule is destroyed.  The storage for TARGET_PERCENTS is not used;
!    it may be freed.  */
  
  void
! create_pattern_rule (targets, target_percents,
! 		     terminal, deps, commands, override)
!      char **targets, **target_percents;
       int terminal;
       struct dep *deps;
       struct commands *commands;
***************
*** 412,418 ****
  	    xrealloc ((char *) r->suffixes, max_targets * sizeof (char *));
  	}
        r->lens[i] = strlen (targets[i]);
!       r->suffixes[i] = index (targets[i], '%') + 1;
      }
  
    if (i < max_targets - 1)
--- 423,432 ----
  	    xrealloc ((char *) r->suffixes, max_targets * sizeof (char *));
  	}
        r->lens[i] = strlen (targets[i]);
!       r->suffixes[i] = (target_percents == 0 ? find_percent (targets[i])
! 			: target_percents[i]) + 1;
!       if (r->suffixes[i] == 0)
! 	abort ();
      }
  
    if (i < max_targets - 1)
diff -rc make-3.54/variable.c make-3.55/variable.c
*** make-3.54/variable.c	Sun Jun 11 15:25:37 1989
--- make-3.55/variable.c	Thu Aug 24 15:08:01 1989
***************
*** 236,242 ****
  	  free (v->name);
  	  free ((char *) v);
  	}
-       free ((char *) set->table[i]);
      }
    free ((char *) set->table);
    free ((char *) set);
--- 236,241 ----
***************
*** 254,259 ****
--- 253,259 ----
    set->buckets = SMALL_SCOPE_VARIABLE_BUCKETS;
    set->table = (struct variable **)
      xmalloc (set->buckets * sizeof (struct variable *));
+   bzero ((char *) set->table, set->buckets * sizeof (struct variable *));
  
    setlist = (struct variable_set_list *)
      xmalloc (sizeof (struct variable_set_list));
***************
*** 374,385 ****
  	    {
  	      unsigned int j = i % buckets;
  	      register struct variable_bucket *ov;
! 	      register char *p;
  
! 	      if (streq (v->name, "MAKELEVEL"))
  		continue;
  
! 	      for (p = v->name; *p != '\0'; ++p)
  		if (*p != '_' && (*p < 'a' || *p > 'z')
  		    && (*p < 'A' || *p > 'Z') && (*p < '0' || *p > '9'))
  		  break;
--- 374,389 ----
  	    {
  	      unsigned int j = i % buckets;
  	      register struct variable_bucket *ov;
! 	      register char *p = v->name;
  
! 	      if (v->origin == o_default
! 		  || streq (p, "MAKELEVEL"))
  		continue;
  
! 	      if (*p != '_' && (*p < 'A' || *p > 'Z')
! 		  && (*p < 'a' || *p > 'z'))
! 		continue;
! 	      for (++p; *p != '\0'; ++p)
  		if (*p != '_' && (*p < 'a' || *p > 'z')
  		    && (*p < 'A' || *p > 'Z') && (*p < '0' || *p > '9'))
  		  break;
***************
*** 415,421 ****
  	}
      }
    result[nvariables] = (char *) xmalloc (100);
!   (void) sprintf (result[nvariables], "MAKELEVEL=%u", makelevel);
    result[++nvariables] = 0;
  
    return result;
--- 419,425 ----
  	}
      }
    result[nvariables] = (char *) xmalloc (100);
!   (void) sprintf (result[nvariables], "MAKELEVEL=%u", makelevel + 1);
    result[++nvariables] = 0;
  
    return result;
***************
*** 535,543 ****
        printf ("%s %s= ", v->name, v->recursive ? "" : ":");
  
        /* Check if the value is just whitespace.  */
!       p = v->value;
!       while (*p == ' ' || *p == '\t')
! 	++p;
        if (p != v->value && *p == '\0')
  	/* All whitespace.  */
  	printf ("$(subst ,,%s)", v->value);
--- 539,545 ----
        printf ("%s %s= ", v->name, v->recursive ? "" : ":");
  
        /* Check if the value is just whitespace.  */
!       p = next_token (v->value);
        if (p != v->value && *p == '\0')
  	/* All whitespace.  */
  	printf ("$(subst ,,%s)", v->value);
diff -rc make-3.54/version.c make-3.55/version.c
*** make-3.54/version.c	Sat Jun 24 15:27:31 1989
--- make-3.55/version.c	Sat Aug 26 16:18:09 1989
***************
*** 1,4 ****
! char *version_string = "3.54";
  \f


  /*
    Local variables:
--- 1,4 ----
! char *version_string = "3.55";
  \f


  /*
    Local variables:
diff -rc make-3.54/vpath.c make-3.55/vpath.c
*** make-3.54/vpath.c	Fri May 26 19:05:00 1989
--- make-3.55/vpath.c	Tue Aug 15 00:03:29 1989
***************
*** 26,31 ****
--- 26,32 ----
    {
      struct vpath *next;	/* Pointer to next struct in the linked list.  */
      char *pattern;	/* The pattern to match.  */
+     char *percent;	/* Pointer into `pattern' where the `%' is.  */
      unsigned int patlen;/* Length of the pattern.  */
      char **searchpath;	/* Null-terminated list of directories.  */
      unsigned int maxlen;/* Maximum length of any entry in the list.  */
***************
*** 110,116 ****
--- 111,124 ----
    register char **vpath;
    register unsigned int maxvpath;
    unsigned int maxelem;
+   char *percent;
  
+   if (pattern != 0)
+     {
+       pattern = savestring (pattern, strlen (pattern));
+       percent = find_percent (pattern);
+     }
+ 
    if (dirpath == 0)
      {
        /* Remove matching listings.  */
***************
*** 118,124 ****
  
        lastpath = vpaths;
        for (path = vpaths; path != 0; lastpath = path, path = path->next)
! 	if (pattern == 0 || streq (pattern, path->pattern))
  	  {
  	    /* Remove it from the linked list.  */
  	    if (lastpath == vpaths)
--- 126,135 ----
  
        lastpath = vpaths;
        for (path = vpaths; path != 0; lastpath = path, path = path->next)
! 	if (pattern == 0
! 	    || (((percent == 0 && path->percent == 0)
! 		 || (percent - pattern == path->percent - path->pattern))
! 		&& streq (pattern, path->pattern)))
  	  {
  	    /* Remove it from the linked list.  */
  	    if (lastpath == vpaths)
***************
*** 131,136 ****
--- 142,149 ----
  	    free ((char *) path->searchpath);
  	    free ((char *) path);
  	  }
+       if (pattern != 0)
+ 	free (pattern);
        return;
      }
  
***************
*** 211,218 ****
        vpaths = path;
  
        /* Set up the members.  */
        path->patlen = strlen (pattern);
-       path->pattern = savestring (pattern, path->patlen);
      }
    else
      /* There were no entries, so free whatever space we allocated.  */
--- 224,232 ----
        vpaths = path;
  
        /* Set up the members.  */
+       path->pattern = pattern;
+       path->percent = percent;
        path->patlen = strlen (pattern);
      }
    else
      /* There were no entries, so free whatever space we allocated.  */
***************
*** 237,243 ****
      return 0;
  
    for (v = vpaths; v != 0; v = v->next)
!     if (pattern_matches (v->pattern, *file))
        {
  	if (selective_vpath_search (v, file))
  	  return 1;
--- 251,257 ----
      return 0;
  
    for (v = vpaths; v != 0; v = v->next)
!     if (pattern_matches (v->pattern, v->percent, *file))
        {
  	if (selective_vpath_search (v, file))
  	  return 1;
*** /dev/null	Sat Aug 26 15:28:08 1989
--- make-3.55/README	Sat Aug 26 16:59:32 1989
***************
*** 0 ****
--- 1,11 ----
+ This directory contains the 3.55 test release of GNU Make.
+ All bugs reported for previous test releases have been fixed.
+ Some bugs probably remain.
+ 
+ To install, edit the file Makefile as directed in the comments,
+ and run `make install'.
+ 
+ GNU Make is fully documented in make.texinfo.  See the section entitled `Bugs'
+ for information on submitting bug reports.
+ 
+ GNU Make is free software.  See the file COPYING for copying conditions.
*** /dev/null	Sat Aug 26 15:28:08 1989
--- make-3.55/make.man	Tue Aug 22 19:00:11 1989
***************
*** 0 ****
--- 1,297 ----
+ .TH MAKE 1L "22 August 1989" "GNU" "LOCAL USER COMMANDS"
+ .SH NAME
+ make \- GNU make utility to maintain groups of programs
+ .SH SYNOPSIS
+ .B "make "
+ [
+ .B \-f
+ makefile ] [ option ] ...
+ target ...
+ .SH WARNING
+ This man paage is an extract of the documentation of
+ .I GNU make .
+ It is updated only occasionally, because the GNU project does not use nroff.
+ For complete, current documentation, refer to the Info file
+ .B make
+ or the DVI file
+ .B make.dvi
+ which are made from the Texinfo source file
+ .BR make.texinfo .
+ .SH DESCRIPTION
+ .LP
+ The purpose of the
+ .I make
+ utility is to determine automatically which
+ pieces of a large program need to be recompiled, and issue the commands to
+ recompile them.
+ This manual describes the GNU implementation of
+ .IR make ,
+ which was written by Richard Stallman and Roland McGrath.
+ Our examples show C programs, since they are most common, but you can use
+ .I make
+ with any programming language whose compiler can be run with a
+ shell command.
+ In fact,
+ .I make
+ is not limited to programs.
+ You can use it to describe any task where some files must be
+ updated automatically from others whenever the others change.
+ .LP
+ To prepare to use
+ .IR make ,
+ you must write a file called the
+ .I makefile
+ that describes the relationships among files in your program, and the
+ states the commands for updating each file.
+ In a program, typically the executable file is updated from object
+ files, which are in turn made by compiling source files.
+ .LP
+ Once a suitable makefile exists, each time you change some source files,
+ this simple shell command:
+ .sp 1
+ .RS
+ .B make
+ .RE
+ .sp 1
+ suffices to perform all necessary recompilations.
+ The
+ .I make
+ program uses the makefile data base and the last-modification times
+ of the files to decide which of the files need to be updated.
+ For each of those files, it issues the commands recorded in the data base.
+ .LP
+ .I make
+ executes commands in the
+ .I makefile
+ to update
+ one or more target
+ .IR names ,
+ where
+ .I name
+ is typically a program.
+ If no
+ .B \-f
+ option is present,
+ .I make
+ will look for the makefiles
+ .IR GNUmakefile ,
+ .IR makefile ,
+ and
+ .IR Makefile ,
+ in that order.
+ .LP
+ Normally you should call your makefile either
+ .I makefile
+ or
+ .IR Makefile .
+ (We recommend
+ .I Makefile
+ because it appears prominently near the beginning of a directory
+ listing, right near other important files such as
+ .IR  README .)
+ The first name checked,
+ .IR GNUmakefile ,
+ is not recommended for most makefiles.
+ You should use this name if you have a makefile that is specific to GNU
+ .IR make ,
+ and will not be understood by other versions of
+ .IR make .
+ If
+ .I makefile
+ is `\-', the standard input is read.
+ .LP
+ .I make
+ updates a target if it depends on prerequisite files
+ that have been modified since the target was last modified,
+ or if the target does not exist.
+ .SH OPTIONS
+ .sp 1
+ .TP 0.5i
+ .B \-b
+ .TP 0.5i
+ .B \-m
+ These options are ignored for compatibility with other versions of 
+ .IR make .
+ .TP 0.5i
+ .BI "\-C " dir
+ Change to directory
+ .I dir
+ before reading the makefiles or doing anything else.
+ If multiple
+ .B \-C
+ options are specified, each is interpreted relative to the
+ previous one:
+ .BR "\-C " /
+ .BR "\-C " etc
+ is equivalent to
+ .BR "\-C " /etc.
+ This is typically used with recursive invocations of
+ .IR make .
+ .TP 0.5i
+ .B \-d
+ Print debugging information in addition to normal processing.
+ The debugging information says which files are being considered for
+ remaking, which file-times are being compared and with what results,
+ which files actually need to be remade, which implicit rules are
+ considered and which are applied---everything interesting about how
+ .I make
+ decides what to do.
+ .TP 0.5i
+ .BI "\-f " file
+ Use file
+ .I file as a makefile.
+ .TP 0.5i
+ .B \-i
+ Ignore all errors in commands executed to remake files.
+ .TP 0.5i
+ .BI "\-I " dir
+ Specifies a directory
+ .I dir
+ to search for included makefiles.
+ If several
+ .B \-I
+ options are used to specify several directories, the directories are
+ searched in the order specified.
+ Unlike the arguments to other flags of 
+ .IR make ,
+ directories given with
+ . \-I
+ flags may come directly after the flag:
+ .BI \-I dir
+ is allowed, as well as
+ .BI "\-I " dir.
+ This syntax is allowed for compatibility with the C
+ preprocessor's
+ .B \-I
+ flag.
+ .TP 0.5i
+ .BI "\-j " jobs
+ Specifies the number of jobs (commands) to run simultaneously.
+ If there is more than one
+ .B \-j
+ option, the last one is effective.
+ If the
+ .B \-j
+ option is given without an argument,
+ .IR make
+ will not limit the number of jobs that can run simultaneously.
+ .TP 0.5i
+ .B \-k
+ Continue as much as possible after an error.
+ While the target that failed, and those that depend on it, cannot
+ be remade, the other dependencies of these targets can be processed
+ all the same.
+ .TP 0.5i
+ .B \-l
+ .TP 0.5i
+ .BI "\-l " load
+ Specifies that no new jobs (commands) should be started if there are
+ others jobs running and the load average is at least
+ .I load
+ (a floating-point number).
+ With no argument, removes a previous load limit.
+ .TP 0.5i
+ .B \-n
+ Print the commands that would be executed, but do not execute them.
+ .TP 0.5i
+ .BI "\-o " file
+ Do not remake the file
+ .I file
+ even if it is older than its dependencies, and do not remake anything
+ on account of changes in
+ .IR file .
+ Essentially the file is treated as very old and its rules are ignored.
+ .TP 0.5i
+ .B \-p
+ Print the data base (rules and variable values) that results from
+ reading the makefiles; then execute as usual or as otherwise
+ specified.
+ This also prints the version information given by the
+ .B \-v
+ switch (see below).
+ To print the data base without trying to remake any files, use
+ .B make
+ .B \-p
+ .BI \-f /dev/null.
+ .TP 0.5i
+ .B \-q
+ ``Question mode''.
+ Do not run any commands, or print anything; just return an exit status
+ that is zero if the specified targets are already up to date, nonzero
+ otherwise.
+ .TP 0.5i
+ .B \-r
+ Eliminate use of the built-in implicit rules.
+ Also clear out the default list of suffixes for suffix rules.
+ .TP 0.5i
+ .B \-s
+ Silent operation; do not print the commands as they are executed.
+ .TP 0.5i
+ .B \-S
+ Cancel the effect of the
+ .B \-k
+ option.
+ This is never necessary except in a recursive 
+ .I make
+ where
+ .B \-k
+ might be inherited from the top-level 
+ .I make
+ via MAKEFLAGS or if you set
+ .B \-k
+ in MAKEFLAGS in your environment.
+ .TP 0.5i
+ .B \-t
+ Touch files (mark them up to date without really changing them)
+ instead of running their commands.
+ This is used to pretend that the commands were done, in order to fool
+ future invocations of
+ .IR make .
+ .TP 0.5i
+ .B \-v
+ Print the version of the 
+ .I make
+ program plus a copyright, a list of authors and a notice that there
+ is no warranty.
+ After this information is printed, processing continues normally.
+ To get this information without doing anything else, use
+ .B make
+ .B \-v
+ .BI \-f /dev/null.
+ .TP 0.5i
+ .B \-w
+ Print a message containing the working directory before and after
+ before and after other processing.
+ This may be useful for tracking down errors from complicated nests of
+ recursive
+ .I make
+ commands.
+ .TP 0.5i
+ .BI "\-W " file
+ Pretend that the target
+ .I file
+ has just been modified.
+ When used with the
+ .B \-n
+ flag, this shows you what would happen if you were to modify that file.
+ Without
+ .BR \-n ,
+ it is almost the same as running a
+ .I touch
+ command on the given file before running
+ .IR make ,
+ except that the modification time is changed only in the imagination of 
+ .IR make .
+ .SH "SEE ALSO"
+ .PD 0
+ .TP 2.0i
+ /usr/local/doc/gnumake.dvi
+ .I
+ The GNU Make Manual
+ .PD
+ .SH BUGS
+ See the chapter `Problems and Bugs' in
+ .I "The GNU Make Manual" .
+ .SH AUTHOR
+ This manual page contributed by Dennis Morse of Stanford University.
+ It has been reworked by Roland McGrath.