dmake Version 3.7
=================

FULL RELEASE OF DMAKE, REPLACES VERSION 3.6

Nature:  It is highly recommended that this version replace all versions of 3.6
-------  that are in current use.  Version 3.7 fixes numerous memory bugs that
	 were present in Version 3.6.  These often caused spurious behaviour
	 especially on MSDOS machines when complex makefiles were used.

	 This release addresses the following issues:

	     1. Modifications to the inference algorithm.
	     2. Memory bug fixes.
	     3. Enhancements to the macro expansion facilities.
	     4. Addition of .KEEP_STATE functionality.
	     5. Many other tweaks and tunes

	  This distribution advances dmake to Version 3.7, patch level 0.


Availability:
-------------
	  dmake is available via anonymous ftp from watmsg.uwaterloo.edu
	  (129.97.129.9) as:

	      pub/dmake/dmake37.tar.Z		- compressed tar archive
	      pub/dmake/dmake37.zoo		- zoo archive
	      pub/dmake/dmake37-msdos-exe.zoo	- MSDOS executable zoo archive
	      pub/dmake/dmake37-msdos-exe.zip	- MSDOS executable zip archive
	      pub/dmake/dmake37.shar01		- xx part shar archive
	      ...				  (get all parts)
	      pub/dmake/dmake37.sharxx

	  and comes in several archive formats.  Choose the one that best
	  suits your needs.

Acknowledgements:
-----------------
	  Thanks to all who submitted code for new features, suggestions for
	  improvements, and bug fixes.  I have tried to make sure no gotchas
	  remain, if you encounter problems installing or running dmake please
	  let me know.  As always, I am always happy to receive e-mail.


DETAILS OF ENHANCEMENTS/TWEAKS:
===============================
- Ran the whole thing with a DEBUGING malloc library on.  Found one memory
  bug in expand.c, one in BSD 4.3's version of getwd.  I am now fairly
  confident that no more obscure memory allocation bugs remain in dmake.

- Addition of the malloc dbug code made me move all debug code into the
  dbug directory and I changed the config.mk files around to reflect the
  changes.  Setting DEBUG=1 on the command line gives you DB_ macros, and
  DEBUG=1 DBMALLOC=1 gives you DB_ macros and debuging malloc library.

- Added sysvr4 directory and targets

- Disallowed %.o :: %.c rules.  They make no sense and the implementation
  was completely wrong.  That is, the difference between

	%.o : %.c; ...
	%.o : %.f; ...
  and
	%.o :: %.c; ...
	%.o :: %.f; ...

  is less than clear, and the efficacy of the latter is even muddier.  From
  now on :: rules are not allowed in %-meta rules.  This simplifies the
  description of what is going on and makes the code in infer.c significantly
  more correct.  When %-meta rules are now replaced by other rules, the
  .SETDIR attribute (if specified) is taken into consideration and only rules
  whose target, prerequisite, and .SETDIR value match are considered for
  replacement, otherwise the new rule is added.

- Modified the setting of external file name for targets that have been made
  and that had a .SETDIR= attribute as follows:

	.SETDIR=fred : test

	target : test ; ...

  then the name of test in any $< expansions is fred/test if the change of
  directory was successful, if however the rules for making test are:

	test .SETDIR=a :: ...
	test .SETDIR=b :: ...

  then the external file name for 'test' is simply 'test'.  We don't know
  which recipes will be used to bring it up to date in which directories
  hence we will not attempt to modify the name of test.   The same holds for
  the .SOURCE search rules in this case.

  You are now able to provide different .SETDIR=dir attributes to each
  new :: rule associated with a target, see above for what name is deduced
  for such targets after they are made.

- Went to a Breadth-first search inference algorithm.  Major change and two
  days of hacking, but it seems to work.  It is much nicer now and I can
  describe with definite determinism what the algorithm will not infer.
  All ambiguities are reported rather than choosing an arbitrary inference
  chain.  This is considerably less error prone, but may break some existing
  makefiles.  Modified -v display to show exactly what inference chain is
  used.

- Fixed the recipe handling of +,-,%,@ at the start of a recipe line.  The
  attributes are now recognized even if they appear in a macro at the start
  of the recipe line.  ie;

	all:
	    $(SH) do the right thing

  will use the shell if SH=+ is defined somewhere.

- Modified string{token_list} expansions to better co-exist with /bin/sh.
  /bin/sh treats the following as valid syntax:

  	{ echo hello;}

  under version 3.6 of dmake it would strip the {} characters or worse.
  This version of dmake has been modified to apply the {} only of the
  first token in token_list follows the opening { with no intervening
  white space.  Thus the above line will NOT BE Expanded, while

        {foo fee}.c

  will result in foo.c and fee.c as the result of the expansion.

- If using Augmake (-A) flag then directories are always made, even if they
  are up to date.

- Added .PHONY attribute.  Any target with this attribute will have it's
  recipe made each time it is made even if a file with the name of the target
  exists and can be found by dmake.  Targets that have as a prerequisite a
  target with the .PHONY attribute set will also get made since the time stamp
  of the prerequisite will be made current and it will appear older than the
  target thereby forcing it to be made as well.

- Added .ELIF <condition> construct, and allowed .ENDIF as a synnonym for
  .END.  Made the parsing of .IF....ELIF....ELSE....END constructs a little
  more robust.

- Changed behaviour of .SETDIR= attribute when used without prerequisites or
  a target.

	.SETDIR=somedir :

  is no longer supported you should instead use the macro form of the
  attribute:

	.SETDIR := somedir

  The reasoning behind the switch goes as follows.  If you wrote the line

	.SETDIR=somedir : $(SOURCE_FILES)

  and $(SOURCE_FILES) was null this would cause dmake to CD to somedir prior
  to making any targets.  This situation is undesirable at best as it caused
  some weird error messages.  The new modified behaviour is more consistent
  and allows the attribute to be set on the command line.

- Modified inference to assume targets that have no .suffix can be made from
  files that contain at least one .suffix.  This prevents early termination of
  the inference algorithm.

- Added -v{dfimt} flag so that you can now control
  how much junk -v actually prints.  This means that
  -v is now a seperate flag and cannot be catenated
  with the rest... oh well.

- Added DOS tee function to copy the contents of output to stdout and stderr
  to a file specified using -C option.  patches were supplied by Len Reed.

- Added KEEPSTATE functionality based on Dean Hoovers stuff.
    BEWARE:  If you make a target and the recipe has a default set of rules
	     when things are updated, but a slightly different set when it
	     updates then using KEEPSTATE will fail.  In particular:

	     Suppose you infer a recipe % --> %.o --> %.c, and the first time
	     you make a target the .o is in the '.' directory, but by default
	     you tell dmake to look in objects, then when you run dmake the
	     next time the recipe will be different as the .o will now be
	     objects/foo.o and the KEEPSTATE value will be outdated and hence
	     the target will look as if it needs making.
  .NOSTATE attribute to disable keeping of state for any target with this
  attribute set.  no state is kept for .PHONY targets either.

- Added some more GNU style macro expansions:

	$(null,text true false)
	$(!null,text true false)
	$(eq,lhs,rhs true false)
	$(!eq,lhs,rhs true false)

  The first returns Expand(true) if Expand(text) is null, and Expand(false) if
  Expand(text) is not null.  The second is the negation of the first.

  The equality macros are similar but test
     Expand(lhs) == Expand(rhs)
  rather than against null.

- Modified the running of normal recipes to perform the following expansion
  prior to doing the command:

	set CNMDNAME := name of command to execute (first whitespace ending
			token in command line)
	set CMNDARGS := remainder of the line

  Expand $(COMMAND) to form the the command line to pass to be executed.  By
  default COMMAND is set to:

	COMMAND = $(CMNDNAME) $(CMNDARGS)

  If however you wish to use a different interface (esp under DOS) for passing
  long command line arguments then you can easily do so, for example:

	COMMAND = $(CMNDNAME) @(mktmp $(CMNDARGS))

  assigns a temporary file that holds the arguments and executest the comand

	$(CMNDNAME) @/tmp/ASAD38479217

  or whatever, the temporary file is removed upon completion of the command
  unless the -vt flag is given.

- Added $(shell command) macro, which passes the commands specified as data to
  a shell using the usual interface and returns the result of the output from
  the command catenated together into a single string separated by spaces.

  For example:

  	$(shell ls *.c)

  returns the list of *.c files from the current directory.

- Added $(sort data) macro which sorts the list of space separated tokens in
  data.

- Added $(strip data) macro which makes sure that data contains a list
  of tokens separated by a single space.

- Added $(subst,pat,replacement data)



DETAILS OF BUG FIXES:
=====================

MAN PAGE TWEAKS:
----------------
- Made all "it's" in the document to "its" -- oops.

- Documented '.IMPORT : .EVERYTHING' functionality and ensured that global
  attributes are not affected by it.

- Documented '.NOINFER:' functionality.

- Documented new features


UNIX RELATED BUG FIXES:
-----------------------
- Changed unix/arlib.c to use binary time headers if M_XENIX.  You can fix
  this by changing the definition of ASCARCH in unix/sysvr3/config.h when
  M_XENIX is defined.  I don't know which is the true case so if anyone knows
  can you let me know and I'll make sure it gets set right.

- Updated unix/arlib.c to handle RS6000/AIX 3.0 archive headers.  This is
  a bit of a pain as #ifdef _AIX had to be spattered throughout arlib.c
  and in a number of other places.  It was the lesser of two evils.  Will
  IBM ever get stuff like __STDC__ right?


MSDOS RELATED BUG FIXES:
------------------------
- Applied fix supplied by few@gupta.com (Frank Whaley) to msdos/spawn.c for
  building and handling path names during the search for an executable.
  It could have hung the machine the way it was due to lack of a NULL
  pointer.

- Fixed another bug in msdos/spawn.c.  If you tried to run a program that had
  a full path including extension then the current spawn.c did not find it
  in some instances.  Whether it did or not depended on what the contents of
  the NULL pointer happened to be :-).

- Fixed a HUGE bug in msdos/spawn.c.  There was an off by one error in
  _get_path that caused serious memory stomps, and eventual hangs of the
  machine.

- Fixed bug in msdos/switchar.c, it now correctly selects the code to
  get the switchar if it's an MSDOS compile.


OS/2 RELATED FIXES:
-------------------
- Applied patch for OS/2 supplied by "Kai Uwe Rommel".  Details (from Kai) of
  patch:
     o in os2/_chdir.c, there was a transmission error or typo, Ox20 instead of
       0x20
     o in os2/dmake.cs I corrected the options; my compiler shell maintains a
       global ("system-wide") set of default options, so there is no need to
       use -G2 etc. there. Also, -WX seems to be unnessecary.
     o in os2/dmake.def, I commented out the IMPORT statement (see below).
     o in os2/ruletab.c, MAXPROCESS *MUST* me removed, otherwise the argument
       of the -Pn option seems to be ignored.
     o in os2/runargv.c, I moved the session title code (with a call to an
       undocumented system call) into "#ifdef SESSTITTLE" because it also
       prevents BIND to make a family mode application that also runs under DOS
       or in the DOS box; this may be of interest to people who use both DOS
       and OS/2 on their machines, to prevent them from having two binaries of
       dmake on their hard disk. This also requires to remove the import
       statement  for the undoc. system call from the dmake.def file.
     o in os2/startup.h I added a / into the MAKESTARTUP definition.


GENERAL FIXES:
--------------
- Fixed the # comment handling inside recipes to mirror what standard makes
  do.  This turned out to be trivial to do so I stuck it in.

- Fixed bug reported by bill@twwells.com, If dmake was run in a /bin/sh with
  makefile text comming via a pipe from stdin then when dmake executed the
  makefile it would see an extra child termination comming from the source
  of the pipe.  dmake now ignores returned pid's from child processes that it
  did not spawn.  An example, under /bin/sh, do:

	cat <<\+ | dmake -vf - verify
	verify : make
		echo verify
	make :
		echo make
	+

  The cat could finish before the first real dmake child finished and would
  cause a core dump.

- Inserted definitions of FP_OFF and FP_SEG into spawn.c and find.c under
  msdos directory as Turbo C++ was having troubles finding them.  As reported
  by Nino Margetic (nino@uk.ac.ucl.sm.mph).

- Changed Fatal error message for multiple .SETDIR= attribute specifications
  into a Warning.

- Fixed a nasty bug in Parallel Make.  It would get the names of .SETDIR'ed
  prerequisites wrong.  Specifically it lost the .SETDIR value when setting
  the $< etc macro values for the final target.

- Fixed bug reported by Len Reed.  When removing prerequisites using .REMOVE
  I now set their flags as no longer existing.  This way if we happen to
  walk this part of the graph again from some other place we know enough
  to remake them.  This is really a simpler case of the general go to the
  same spot from a different .SETDIR location problem.

  NOTE:  The following makefile is an example of what this fixes, but that
  it may not work correctly with -Pn where n>1 since .REMOVES are run and
  they happen in parallel along with the rest of the processing.  There is
  a race in getting the .REMOVE done and walking the graph from
  the large.target side.  Don't build graphs like this.  If you want to
  do it in parallel then put each of large and small in a different
  directory.

      all .SEQUENTIAL : small.target large.target

      small.target : one.sml two.sml
	      echo Building $@ from $&

      large.target : one.lrg two.lrg; echo Building $@ from $&

      %.sml : %.c; echo $(CC) $(CFLAGS) -c -Fo$<; touch $@

      %.lrg : %.c; echo $(CC) $(CFLAGS) -AL -c -Fo$<; touch $@

      CO = co -u
      CC = cc
      V = ,v

	 % : $$(@:d)RCS/$$(@:f)$V;- $(CO) $(COFLAGS) $@
	    .NOINFER : %$V $$(@:d)RCS/$$(@:f)$V

      :REMOVE :; /bin/rm -f $&

- Fixed core dump on circularity test for targets that contain a .LIBRARY
  beats me why I put the explicit test in to ignore the libraries if found
  to be circular.  Someone will complain if this is broken now but I don't
  think it is.

- Cleaned up the .h files, they are much cleaner and more
  organized now.
     o Added define of _POSIX_SOURCE for RS/6000
     o Moved the definition of size_t from all over the place to alloc.h
     o Cleaned up the definition of POSTAR for XENIX, You shouldn't need it.

- Fixed a bug with setting macro variables from the command line.
  It now recognizes a + only if it preceeds an '='.

- WARNING if you use the vfprintf code supplied with dmake then you might get
  a warning indicating that an illegal pointer assignment is taking place,
  ignore it.

- Fixed handling of attributes for recipes and :: rules.  The following is now
  true:

	.MKSARGS : list_of_targets

  Will set .MKSARGS for any target appearing in list_of_targets irrespective
  of whether it appears as a target in :: or : recipe lines.  Conversely
  the construct:

	target1 :: ; recipe 1
	target1 .MKSARGS :: ; recipe 2

  will set .MKSARGS when making target1 using recipe 2 only.

- Fixed a nasty bug in string.c.  Forgot to check for NIL(char) in second
  argument to _strspn and _strpbrk, sheesh!.

- Propagate parent timestamp for infered prerequisites if it is >= not just >.
  This fixes a small bug with directories that were prerequisites of a target.
  If the directory was modified when the target was made it is quite possible
  they may have the same time-stamp.  This in general is not a good thing to
  do anyway.

- Modified $(mktmp ...) macro so that you can specify a file name.

	$(mktmp[,[FILE][,TEXT]] data);

  will put data into a file called Expand(FILE), if FILE contains
  $(TMPFILE) then a suitable temporary file name is generated and
  substituted.  The result value of the macro is the name of the tempfile
  or if TEXT is defined, is the result of Expand(TEXT).

  Some examples are:

	$(mktmp data)			==> normal tmpfile
	$(mktmp,$(TMPFILE) data)	==> normal tmpfile
	$(mktmp,, data)			==> normal tmpfile
	$(mktmp,turboc.cfg $(CFLAGS))	==> tmpfile named turboc.cfg
	$(mktmp,,$(TMPSHELL) data)	==> normal tmpfile, named Expand(...)
	$(mktmp,,$(NULL) data)		==> normal tmpfile, null result

- Modified making of .MAKEFILES special targets to make certain that
  it does not make a prerequisite of that target if the -n flag is specified.

- Changed statting of targets to match the functionality of .SETDIR a bit
  better.  When looking into a library and we have used .SETDIR to change
  directories, dmake will look into a relative current path, and if it
  does not find it, it will search a library found by prepending the value
  of the TMD macro to the path of the library file.

- Fixed the handling of :: and %-meta targets by ripping out the HOW internal
  data-structure, and by doing some interesting things with the cell dag.
  .UPDATEALL is now more comprehensive in its behaviour (might even be
  correct).  Sets of :: rules for a target return the timestamp for the target
  that resulted in it's being made.
