GNU make release 3.77.
authorPaul Smith <psmith@gnu.org>
Thu, 30 Jul 1998 20:54:47 +0000 (20:54 +0000)
committerPaul Smith <psmith@gnu.org>
Thu, 30 Jul 1998 20:54:47 +0000 (20:54 +0000)
61 files changed:
AUTHORS
ChangeLog
GNUmakefile
INSTALL
Makefile.DOS.template
Makefile.am
NEWS
NMakefile.template
README.DOS.template
README.W32
README.customs [new file with mode: 0644]
README.template
SMakefile.template
acinclude.m4 [new file with mode: 0644]
arscan.c
config.ami.template
config.h.W32.template
configure.in
default.c
dir.c
dosbuild.bat
expand.c
file.c
filedef.h
function.c
getloadavg.c
glob/ChangeLog
glob/Makefile.am
glob/Makefile.ami
glob/SMakefile
glob/configure.in
glob/fnmatch.c
glob/fnmatch.h
glob/glob.c
glob/glob.h
implicit.c
job.c
job.h
main.c
maintMakefile
make.1
make.h
make.texinfo
makefile.com
misc.c
read.c
readme.vms
remake.c
remote-cstms.c
remote-stub.c
rule.c
rule.h
subproc.bat
variable.c
variable.h
vmsfunctions.c
vmsify.c
vpath.c
w32/subproc/NMakefile
w32/subproc/build.bat
w32/subproc/sub_proc.c

diff --git a/AUTHORS b/AUTHORS
index b66bb8f..489c8cd 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,29 +1,30 @@
 -----------------------------------
 
 GNU make development up to version 3.75 by:
-    Roland McGrath <roland@gnu.ai.mit.edu>
+    Roland McGrath <roland@gnu.org>
 
 
-GNU Make User's Manual written by:
-    Richard M. Stallman <rms@gnu.ai.mit.edu>
-
-  User's Manual edited by:
-    Roland McGrath <roland@gnu.ai.mit.edu>
-    Bob Chassell <bob@gnu.ai.mit.edu>
-    Melissa Weisshaus <melissa@gnu.ai.mit.edu>
+Development starting with GNU make 3.76 by:
+    Paul D. Smith <psmith@gnu.org>
 
 
-Development and maintenance starting with GNU make 3.76 by:
-    Paul D. Smith <psmith@gnu.ai.mit.edu>
+GNU Make User's Manual written by:
+    Richard M. Stallman <rms@gnu.org>
 
+  User's Manual edited by:
+    Roland McGrath <roland@gnu.org>
+    Bob Chassell <bob@gnu.org>
+    Melissa Weisshaus <melissa@gnu.org>
+    Paul D. Smith <psmith@gnu.org>
 
 -----------------------------------
-GNU Make porting efforts:
+GNU make porting efforts:
 
   Port to VMS by:
       Klaus Kaempf <kkaempf@progis.de>
       Archive support/Bug fixes by John W. Eaton <jwe@bevo.che.wisc.edu>
 
+
   Port to Amiga by:
       Aaron Digulla <digulla@fh-konstanz.de>
 
index f773f3c..c3ffc61 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,450 @@
+1998-07-28  Paul D. Smith  <psmith@gnu.org>
+
+       * Version 3.77 released.
+
+       * dosbuild.bat: Change to DOS CRLF line terminators.
+
+       * make-stds.texi: Update from latest version.
+
+       * make.texinfo (Options Summary): Clarify that the -r option
+       affects only rules, not builtin variables.
+
+1998-07-27  Paul D. Smith  <psmith@gnu.org>
+
+       * make.h: Make __attribute__ resolve to empty for non-GCC _and_
+       for GCC pre-2.5.x.
+
+       * misc.c (log_access): Print UID/GID's as unsigned long int for
+       maximum portability.
+
+       * job.c (reap_children): Print PIDs as long int for maximum
+       portability.
+
+1998-07-24  Eli Zaretskii  <eliz@is.elta.co.il>
+
+       * Makefile.DOS (*_INSTALL, *_UNINSTALL): Replace `true' with `:'.
+
+1998-07-25  Paul D. Smith  <psmith@gnu.org>
+
+       * Version 3.76.94 released.
+
+1998-07-23  Paul D. Smith  <psmith@gnu.org>
+
+       * config.h.W32.template: Make sure all the #defines of macros here
+       have a value (e.g., use ``#define HAVE_STRING_H 1'' instead of
+       just ``#define HAVE_STRING_H''.  Keeps the preprocessor happy in
+       some contexts.
+
+       * make.h: Remove __attribute__((format...)) stuff; using it with
+       un-prototyped functions causes older GCC's to fail.
+
+       * Version 3.76.93 released.
+
+1998-07-22  Paul D. Smith  <psmith@gnu.org>
+
+       * file.c (print_file_data_base): Fix average calculation.
+
+1998-07-20  Paul D. Smith  <psmith@gnu.org>
+
+       * main.c (die): Postpone the chdir() until after
+       remove_intermediates() so that intermediate targets with relative
+       pathnames are removed properly.
+
+1998-07-17  Paul D. Smith  <psmith@gnu.org>
+
+       * filedef.h (struct file): New flag: did we print an error or not?
+
+       * remake.c (no_rule_error): New function to print error messages,
+       extraced from remake_file().
+
+       * remake.c (remake_file): Invoke the new error print function.
+       (update_file_1): Invoke the error print function if we see that we
+       already tried this target and it failed, but that an error wasn't
+       printed for it.  This can happen if a file is included with
+       -include or sinclude and couldn't be built, then later is also
+       the dependency of another target.  Without this change, make just
+       silently stops :-/.
+
+1998-07-16  Paul D. Smith  <psmith@gnu.org>
+
+       * make.texinfo: Removed "beta" version designator.
+       Updated ISBN for the next printing.
+
+1998-07-13  Paul Eggert  <eggert@twinsun.com>
+
+       * acinclude.m4: New AC_LFS macro to determine if special compiler
+       flags are needed to allow access to large files (e.g., Solaris 2.6).
+       * configure.in: Invoke it.
+
+1998-07-08  Eli Zaretskii  <eliz@is.elta.co.il>
+
+       * Makefile.DOS: track changes in Makefile.in.
+
+1998-07-07  Paul D. Smith  <psmith@gnu.org>
+
+       * remote-cstms.c (start_remote_job): Move gethostbyaddr() to the
+       top so host is initialized early enough.
+
+       * acinclude.m4: New file.  Need some special autoconf macros to
+       check for network libraries (-lsocket, -lnsl, etc.) when
+       configuring Customs.
+
+       * configure.in (make_try_customs): Invoke new network libs macro.
+
+1998-07-06  Paul D. Smith  <psmith@gnu.org>
+
+       * Version 3.76.92 released.
+
+       * README.customs: Added to the distribution.
+
+       * configure.in (make_try_customs): Rewrite to require an installed
+       Customs library, rather than looking at the build directory.
+
+       * Makefile.am (man_MANS): Install make.1.
+       * make.1: Renamed from make.man.
+
+       * make.texinfo (Bugs): New mailing list address for GNU make bug
+       reports.
+
+1998-07-02  Paul D. Smith  <psmith@gnu.org>
+
+       * Version 3.76.91 released.
+
+       * default.c: Added default rule for new-style RCS master file
+       storage; ``% :: RCS/%''.
+       Added default rules for DOS-style C++ files with suffix ".cpp".
+       They use the new LINK.cpp and COMPILE.cpp macros, which are set by
+       default to be equal to LINK.cc and COMPILE.cc.
+
+1998-06-19  Eli Zaretskii  <eliz@is.elta.co.il>
+
+        * job.c (start_job_command): Reset execute_by_shell after an empty
+        command was skipped.
+
+1998-06-09  Paul D. Smith  <psmith@gnu.org>
+
+       * main.c (main): Keep track of the temporary filename created when
+       reading a makefile from stdin (-f-) and attempt to remove it
+       as soon as we know we're not going to re-exec.  If we are, add it
+       to the exec'd make's cmd line with "-o" so the exec'd make doesn't
+       try to rebuild it.  We still have a hole: if make re-execs then
+       the temporary file will never be removed.  To fix this we'd need
+       a brand new option that meant "really delete this".
+       * AUTHORS, getopt.c, getopt1.c, getopt.h, main.c (print_version):
+       Updated mailing addresses.
+
+1998-06-08  Paul D. Smith  <psmith@gnu.org>
+
+       * main.c (main): Andreas Luik <luik@isa.de> points out that the
+       check for makefile :: rules with commands but no dependencies
+       causing a loop terminates incorrectly.
+
+       * maintMakefile: Make a template for README.DOS to update version
+       numbers.
+
+1998-05-30  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+       * remake.c (update_file_1): Don't free the memory for the
+       dependency structure when dropping a circular dependency.
+
+1998-05-30  Eli Zaretskii  <eliz@is.elta.co.il>
+
+       * dir.c (file_exists_p, file_impossible_p, file_impossible)
+       [__MSDOS__, WINDOWS32]: Retain trailing slash in "d:/", and make
+       dirname of "d:foo" be "d:".
+
+1998-05-26  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+       * read.c (read_makefile): Avoid running past EOS when scanning
+       file name after `include'.
+
+1998-05-26  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+       * make.texinfo (Flavors): Correct description of conditional
+       assignment, which is not equivalent to ifndef.
+       (Setting): Likewise.
+
+1998-05-24  Paul D. Smith  <psmith@gnu.org>
+
+       * arscan.c (ar_name_equal): strncmp() might be implemented as a
+       macro, so don't put preprocessor conditions inside the arguments
+       list.
+
+1998-05-23  Eli Zaretskii  <eliz@is.elta.co.il>
+
+       * read.c (read_makefile) [__MSDOS__, WINDOWS32]: Skip colons in
+       drive specs when parsing targets, target-specific variables and
+       static pattern rules.  A colon can only be part of drive spec if
+       it is after the first letter in a token.
+
+1998-05-22  Eli Zaretskii  <eliz@is.elta.co.il>
+
+       * remake.c (f_mtime) [__MSDOS__]: Allow up to 3 sec of skew before
+       yelling bloody murder.
+
+       * dosbuild.bat: Use -DINCLUDEDIR= and -DLIBDIR= where appropriate.
+
+       * read.c (parse_file_seq): Combine the special file-handling code
+       for WINDOWS32 and __MSDOS__ into a single snippet.
+       (get_next_mword) [__MSDOS__, WINDOWS32]: Allow a word to include a
+       colon as part of a drive spec.
+
+       * job.c (batch_mode_shell) [__MSDOS__]: Declare.
+
+1998-05-20  Paul D. Smith  <psmith@gnu.org>
+
+       * Version 3.76.90 released.
+
+1998-05-19  Paul D. Smith  <psmith@gnu.org>
+
+       * make.texinfo (Make Errors): Added a new appendix describing
+       common errors make might generate and how to resolve them (or at
+       least more information on what they mean).
+
+       * maintMakefile (NMAKEFILES): Use the new automake 1.3 feature
+       to create a dependency file to construct Makefile.DOS, SMakefile,
+       and NMakefile.
+       (.dep_segment): Generate the dependency fragment file.
+
+1998-05-14  Paul D. Smith  <psmith@gnu.org>
+
+       * make.man: Minor changes.
+
+1998-05-13  Paul D. Smith  <psmith@gnu.org>
+
+       * function.c (pattern_matches,expand_function): Change variables
+       and types named "word" to something else, to avoid compilation
+       problems on Cray C90 Unicos.
+       * variable.h: Modify the function prototype.
+
+1998-05-11  Rob Tulloh  <rob_tulloh@tivoli.com>
+
+       * job.c (construct_command_argv_internal): [WINDOWS32] Turn off
+       echo when using a batch file, and make sure the command ends in a
+       newline.
+
+1998-05-03  Paul D. Smith  <psmith@gnu.org>
+
+       * configure.in (make_try_customs): Add some customs flags if the
+       user configures custom support.
+
+       * job.c, remote-cstms.c: Merge in changes for custom library.
+
+       * remote-stub.c: Add option to stub start_remote_job_p().
+
+1998-05-01  Paul D. Smith  <psmith@gnu.org>
+
+       * remake.c (f_mtime): Install VPATH+ handling for archives; use
+       the hname field instead of the name field, and rehash when
+       appropriate.
+
+1998-04-30  Paul D. Smith  <psmith@gnu.org>
+
+       * rule.c (print_rule_data_base): Print out any pattern-specific
+       variable values into the rules database.
+
+       * variable.c (print_variable_set): Make this variable extern, to
+       be called by print_rule_data_base() for pattern-specific variables.
+
+       * make.texinfo (Pattern-specific): Document pattern-specific
+       variables.
+
+1998-04-29  Paul D. Smith  <psmith@gnu.org>
+
+       * expand.c (variable_expand_for_file): Make static; its only
+       called internally.  Look up this target in the list of
+       pattern-specific variables and insert the variable set into the
+       queue to be searched.
+
+       * filedef.h (struct file): Add a new field to hold the
+       previously-found pattern-specific variable reference.  Add a new
+       flag to remember whether we already searched for this file.
+
+       * rule.h (struct pattern_var): New structure for storing
+       pattern-specific variable values.  Define new function prototypes.
+
+       * rule.c: New variables pattern_vars and last_pattern_var for
+       storage and handling of pattern-specific variable values.
+       (create_pattern_var): Create a new pattern-specific variable value
+       structure.
+       (lookup_pattern_var): Try to match a target to one of the
+       pattern-specific variable values.
+
+1998-04-22  Paul D. Smith  <psmith@gnu.org>
+
+       * make.texinfo (Target-specific): Document target-specific
+       variables.
+
+1998-04-21  Paul D. Smith  <psmith@gnu.org>
+
+       * variable.c (define_variable_in_set): Made globally visible.
+       (lookup_variable_in_set): New function: like lookup_variable but
+       look only in a specific variable set.
+       (target_environment): Use lookup_variable_in_set() to get the
+       correct export rules for a target-specific variable.
+       (create_new_variable_set): Create a new variable set, and just
+       return it without installing it anywhere.
+       (push_new_variable_scope): Reimplement in terms of
+       create_new_variable_set.
+
+       * read.c (record_target_var): Like record_files, but instead of
+       files create a target-specific variable value for each of the
+       listed targets.  Invoked from read_makefile() when the target line
+       turns out to be a target-specific variable assignment.
+
+1998-04-19  Paul D. Smith <psmith@gnu.org>
+
+       * read.c (read_makefile): Rewrite the entire target parsing
+       section to implement target-specific variables.  In particular, we
+       cannot expand the entire line as soon as it's read in, since we
+       may want to evaluate parts of it with different variable contexts
+       active.  Instead, start expanding from the beginning until we find
+       the `:' (or `::'), then determine what kind of line this is and
+       continue appropriately.
+
+       * read.c (get_next_mword): New function to parse a makefile line
+       by "words", considering an entire variable or function as one
+       word.  Return the type read in, along with its starting position
+       and length.
+       (enum make_word_type): The types of words that are recognized by
+       get_next_mword().
+
+       * variable.h (struct variable): Add a flag to specify a per-target
+       variable.
+
+       * expand.c: Make variable_buffer global.  We need this during the
+       new parsing of the makefile.
+       (variable_expand_string): New function.  Like variable_expand(),
+       but start at a specific point in the buffer, not the beginning.
+       (variable_expand): Rewrite to simply call variable_expand_string().
+
+1998-04-13  Paul D. Smith  <psmith@gnu.org>
+
+       * remake.c (update_goal_chain): Allow the rebuilding makefiles
+       step to use parallel jobs.  Not sure why this was disabled:
+       hopefully we won't find out :-/.
+
+1998-04-11  Paul D. Smith  <psmith@gnu.org>
+
+       * main.c (main): Set the CURDIR makefile variable.
+       * make.texinfo (Recursion): Document it.
+
+1998-03-17  Paul D. Smith  <psmith@gnu.org>
+
+       * misc.c (makefile_fatal): If FILE is nil, invoke plain fatal().
+       * variable.c (try_variable_definition): Use new feature.
+
+1998-03-10  Paul D. Smith  <psmith@gnu.org>
+
+       * main.c (main): Don't pass included, rebuilt makefiles to
+       re-exec'd makes with -o.  Reopens a possible loop, but it caused
+       too many problems.
+
+1998-03-02  Paul D. Smith  <psmith@gnu.org>
+
+       * variable.c (try_variable_definition): Implement ?=.
+       * make.texinfo (Setting): Document it.
+
+1998-02-28  Eli Zaretskii  <eliz@is.elta.co.il>
+
+       * job.c (start_job_command): Reset execute_by_shell after an empty
+        command, like ":", has been seen.
+
+Tue Oct 07 15:00:00 1997  Phil Brooks <phillip_brooks@hp.com>
+
+       * make.h: [WINDOWS32] make case sensitivity configurable
+       * dir.c: [WINDOWS32] make case sensitivity configurable
+       * README.W32: Document case sensitivity
+       * config.ami: Share case warping code with Windows
+
+Mon Oct  6 18:48:45 CDT 1997 Rob Tulloh <rob_tulloh@dev.tivoli.com>
+
+       * w32/subproc/sub_proc.c: Added support for MKS toolkit shell
+       (turn on HAVE_MKS_SHELL).
+       * read.c: [WINDOWS32] Fixed a problem with multiple target rules
+       reported by Gilbert Catipon (gcatipon@tibco.com).  If multiple
+       path tokens in a rule did not have drive letters, make would
+       incorrectly concatenate the 2 tokens together.
+       * main.c/variable.c: [WINDOWS32] changed SHELL detection code to
+       follow what MSDOS did. In addition to watching for SHELL variable
+       updates, make's main will attempt to default the value of SHELL
+       before and after makefiles are parsed.
+       * job.c/job.h: [WINDOWS32] The latest changes made to enable use
+       of the GNUWIN32 shell from make could cause make to fail due to a
+       concurrency condition between parent and child processes.  Make
+       now creates a batch file per job instead of trying to reuse the
+       same singleton batch file.
+       * job.c/job.h/function.c/config.h.W32: [WINDOWS32] Renamed macro
+       from HAVE_CYGNUS_GNUWIN32_TOOLS to BATCH_MODE_ONLY_SHELL. Reworked
+       logic to reduce complexity. WINDOWS32 now uses the unixy_shell
+       variable to detect Bourne-shell compatible environments. There is
+       also a batch_mode_shell variable that determines whether not
+       command lines should be executed via script files. A WINDOWS32
+       system with no sh.exe installed would have unixy_shell set to
+       FALSE and batch_mode_shell set to TRUE. If you have a unixy shell
+       that does not behave well when invoking things via 'sh -c xxx',
+       you may want to turn on BATCH_MODE_ONLY_SHELL and see if things
+       improve.
+       * NMakefile: Added /D DEBUG to debug build flags so that unhandled
+       exceptions could be debugged.
+
+Mon Oct  6 00:04:25 1997  Rob Tulloh <rob_tulloh@dev.tivoli.com>
+
+       * main.c: [WINDOWS32] The function define_variable() does not
+       handle NULL. Test before calling it to set Path.
+       * main.c: [WINDOWS32] Search Path again after makefiles have been
+       parsed to detect sh.exe.
+       * job.c: [WINDOWS32] Added support for Cygnus GNU WIN32 tools.
+       To use, turn on HAVE_CYGNUS_GNUWIN32_TOOLS in config.h.W32.
+       * config.h.W32: Added HAVE_CYGNUS_GNUWIN32_TOOLS macro.
+
+Sun Oct  5 22:43:59 1997  John W. Eaton <jwe@bevo.che.wisc.edu>
+
+       * glob/glob.c (glob_in_dir): [VMS] Globbing shouldn't be
+       case-sensitive.
+       * job.c (child_execute_job): [VMS] Use a VMS .com file if the
+       command contains a newline (e.g. from a define/enddef block).
+       * vmsify.c (vmsify): Return relative pathnames wherever possible.
+       * vmsify.c (vmsify): An input string like "../.." returns "[--]".
+
+Wed Oct  1 15:45:09 1997  Rob Tulloh <rob_tulloh@tivoli.com>
+
+       * NMakefile: Changed nmake to $(MAKE).
+       * subproc.bat: Take the make command name from the command
+       line. If no command name was given, default to nmake.
+       * job.c: [WINDOWS32/MSDOS] Fix memory stomp: temporary file names
+       are now always created in heap memory.
+       * w32/subproc/sub_proc.c: New implementation of make_command_line()
+       which is more compatible with different Bourne shell implementations.
+       Deleted the now obsolete fix_command_line() function.
+       * main.c: [WINDOWS32] Any arbitrary spelling of Path can be
+       detected. Make will ensure that the special spelling `Path' is
+       inserted into the environment when the path variable is propagated
+       within itself and to make's children.
+       * main.c: [WINDOWS32] Detection of sh.exe was occurring too
+       soon. The 2nd check for the existence of sh.exe must come after
+       the call to read_all_makefiles().
+
+Fri Sep 26 01:14:18 1997  <zinser@axp602.gsi.de>
+
+       * makefile.com: [VMS] Fixed definition of sys.
+       * readme.vms: Comments on what's changed lately.
+
+Fri Sep 26 01:14:18 1997  John W. Eaton <jwe@bevo.che.wisc.edu>
+
+       * read.c (read_all_makefiles): Allow make to find files named
+       "MAKEFILE" with no extension on VMS.
+       * file.c (lookup_file): Lowercase filenames on VMS.
+
+1997-09-29  Paul D. Smith  <psmith@baynetworks.com>
+
+       * read.c (read_makefile): Reworked target detection again; the old
+       version had an obscure quirk.
+
 Fri Sep 19 09:20:49 1997  Paul D. Smith  <psmith@baynetworks.com>
 
+       * Version 3.76.1 released.
+
        * Makefile.am: Add loadavg files to clean rules.
 
        * configure.in (AC_OUTPUT): Remove stamp-config; no longer needed.
@@ -37,7 +482,7 @@ Thu Aug 28 19:39:06 1997  Rob Tulloh  <rob_tulloh@tivoli.com>
        from main() to re-exec make, the call to execvp() would
        incorrectly return control to parent shell before the exec'ed
        command could run to completion. I believe this is a feature of
-       the way that execvp() is implemented on top of WIN32 APIs. To
+       the way that execvp() is implemented on top of WINDOWS32 APIs. To
        alleviate the problem, use the supplied process launch function in
        the sub_proc library and suspend the parent process until the
        child process has run.  When the child exits, exit the parent make
index aedde59..15067c6 100644 (file)
@@ -7,7 +7,7 @@
 
 NORECURSE = true
 
-# If the user asked for a specific target, invoke the Mkaefile instead.
+# If the user asked for a specific target, invoke the Makefile instead.
 #
 .DEFAULT:
        @[ -f Makefile.in -a -f configure -a -f aclocal.m4 -a -f config.h.in ] \
@@ -16,7 +16,7 @@ NORECURSE = true
          || ./configure
        $(MAKE) -f Makefile $@
 
-.PHONY: __cfg __cfg_basic TAGS
+.PHONY: __cfg __cfg_basic
 
 # This is variable since the glob subdirectory doesn't use it.
 #
@@ -36,7 +36,7 @@ endif
 
 __cfg_basic: aclocal.m4 stamp-h.in configure Makefile.in
 
-aclocal.m4: configure.in
+aclocal.m4: configure.in $(wildcard acinclude.m4)
        aclocal
 
 config.h.in: stamp-h.in
diff --git a/INSTALL b/INSTALL
index 50dbe43..bca44d0 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -1,8 +1,6 @@
 Basic Installation
 ==================
 
-   These are generic installation instructions.
-
    The `configure' shell script attempts to guess correct values for
 various system-dependent variables used during compilation.  It uses
 those values to create a `Makefile' in each directory of the package.
@@ -36,7 +34,13 @@ The simplest way to compile this package is:
 
   2. Type `make' to compile the package.
 
-  3. Optionally, type `make check' to run any self-tests that come with
+     If you're building GNU make on a system which does not already have
+     a `make', you can use the build.sh shell script to compile.  Run
+     `sh ./build.sh'.  This should compile the program in the current
+     directory.  Then you will have a Make program that you can use for
+     `make install', or whatever else.
+
+  3. Optionally, type `./make check' to run any self-tests that come with
      the package.
 
   4. Type `make install' to install the programs and any data files and
index 856cdc2..b8d44ee 100644 (file)
@@ -41,12 +41,12 @@ transform = s,x,x,
 # get "Error -1" instead of "Error 1".
 EXIT_FAIL = false
 
-NORMAL_INSTALL = true
-PRE_INSTALL = true
-POST_INSTALL = true
-NORMAL_UNINSTALL = true
-PRE_UNINSTALL = true
-POST_UNINSTALL = true
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
 AR = ar
 CC = gcc
 CPP = gcc -E
@@ -67,12 +67,13 @@ libglob_a_SOURCES = %GLOB_SOURCES%
 make_LDADD =     glob/libglob.a
 
 info_TEXINFOS =        make.texinfo
+man_MANS =     make.1
 
 INCLUDES =     -I$(srcdir)/glob -DLIBDIR=\"c:/djgpp/lib\" -DINCLUDEDIR=\"c:/djgpp/include\"
 
 BUILT_SOURCES =        README build.sh.in
 
-EXTRA_DIST =   make.man $(BUILT_SOURCES) remote-cstms.c  make-stds.texi texinfo.tex SCOPTIONS SMakefile  Makefile.ami README.Amiga config.ami amiga.c amiga.h  NMakefile README.DOS configh.dos configure.bat makefile.com  README.W32 build_w32.bat config.h.W32 subproc.bat make.lnk  config.h-vms makefile.vms readme.vms vmsdir.h vmsfunctions.c  vmsify.c
+EXTRA_DIST =   $(BUILT_SOURCES) $(man_MANS) README.customs remote-cstms.c  make-stds.texi texinfo.tex SCOPTIONS SMakefile  Makefile.ami README.Amiga config.ami amiga.c amiga.h  NMakefile README.DOS configh.dos configure.bat makefile.com  README.W32 build_w32.bat config.h.W32 subproc.bat make.lnk  config.h-vms makefile.vms readme.vms vmsdir.h vmsfunctions.c  vmsify.c
 
 SUBDIRS =      glob
 mkinstalldirs = ${bindir}/gmkdir -p
@@ -99,6 +100,10 @@ TEXINFO_TEX = $(srcdir)/texinfo.tex
 INFO_DEPS = make.info
 DVIS = make.dvi
 TEXINFOS = make.texinfo
+man1dir = $(mandir)/man1
+MANS = $(man_MANS)
+
+NROFF = nroff
 DIST_COMMON =  README AUTHORS COPYING ChangeLog INSTALL Makefile.am  Makefile.in NEWS acconfig.h aclocal.m4 alloca.c build.sh.in config.h.in  configure configure.in getloadavg.c install-sh missing mkinstalldirs  stamp-h.in texinfo.tex
 
 
@@ -116,14 +121,14 @@ default: all
 .SUFFIXES: .c .dvi .info .o .ps .texi .texinfo
 
 distclean-hdr:
-       rm -f config.h
+       -rm -f config.h
 
 maintainer-clean-hdr:
 
 mostlyclean-binPROGRAMS:
 
 clean-binPROGRAMS:
-       test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+       -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
 
 distclean-binPROGRAMS:
 
@@ -131,7 +136,7 @@ maintainer-clean-binPROGRAMS:
 
 install-binPROGRAMS: $(bin_PROGRAMS)
        @$(NORMAL_INSTALL)
-       $(mkinstalldirs) $(bindir)
+       $(mkinstalldirs) $(DESTDIR)$(bindir)
        @list='$(bin_PROGRAMS)'; for p in $$list; do    if test -f $$p; then      echo "  $(INSTALL_PROGRAM) $$p $(bindir)/`echo $$p | sed '$(transform)'`";       $(INSTALL_PROGRAM) $$p $(bindir)/`echo $$p | sed '$(transform)'`;    else :; fi;  done
 
 uninstall-binPROGRAMS:
@@ -142,15 +147,15 @@ uninstall-binPROGRAMS:
        $(COMPILE) -c $<
 
 clean-noinstLIBRARIES:
-       test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+       -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
 
 mostlyclean-compile:
-       rm -f *.o *.exe make.new core
+       -rm -f *.o *.exe make.new core
 
 clean-compile:
 
 distclean-compile:
-       rm -f *.tab.c
+       -rm -f *.tab.c
 
 maintainer-clean-compile:
 
@@ -188,22 +193,22 @@ DVIPS = dvips
 
 install-info-am: $(INFO_DEPS)
        @$(NORMAL_INSTALL)
-       $(mkinstalldirs) $(infodir)
-       @for file in $(INFO_DEPS) make.i; do    d=$(srcdir);    for ifile in `cd $$d && echo $$file $$file-[0-9] $$file-[0-9][0-9] $$file[0-9] $$file[0-9][0-9]`; do      if test -f $$d/$$ifile; then        echo " $(INSTALL_DATA) $$d/$$ifile $(infodir)/$$ifile"; $(INSTALL_DATA) $$d/$$ifile $(infodir)/$$ifile; else : ; fi;    done;  done
+       $(mkinstalldirs) $(DESTDIR)$(infodir)
+       @for file in $(INFO_DEPS) make.i; do    d=$(srcdir);    for ifile in `cd $$d && echo $$file $$file-[0-9] $$file-[0-9][0-9] $$file[0-9] $$file[0-9][0-9]`; do      if test -f $$d/$$ifile; then        echo " $(INSTALL_DATA) $$d/$$ifile $(DESTDIR)$(infodir)/$$ifile"; $(INSTALL_DATA) $$d/$$ifile $(DESTDIR)$(infodir)/$$ifile; else : ; fi;    done;  done
        @$(POST_INSTALL)
-       @if $(SHELL) -c 'install-info --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then    for file in $(INFO_DEPS); do      echo " install-info --info-dir=$(infodir) $(infodir)/$$file";     install-info --info-dir=$(infodir) $(infodir)/$$file || :;   done;  else : ; fi
+       @if $(SHELL) -c 'install-info --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then    for file in $(INFO_DEPS); do      echo " install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$file";     install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$file || :;   done;  else : ; fi
 
 uninstall-info:
        $(PRE_UNINSTALL)
-       @if $(SHELL) -c 'install-info --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then    ii=yes;  else ii=; fi;  for file in $(INFO_DEPS); do    test -z $ii || install-info --info-dir=$(infodir) --remove $$file;  done
+       @if $(SHELL) -c 'install-info --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then    ii=yes;  else ii=; fi;  for file in $(INFO_DEPS); do    test -z $ii || install-info --info-dir=$(DESTDIR)$(infodir) --remove $$file;  done
        $(NORMAL_UNINSTALL)
-       for file in $(INFO_DEPS) make.i; do    (cd $(infodir) && rm -f $$file $$file-[0-9] $$file-[0-9][0-9] $$file[0-9] $$file[0-9][0-9]);  done
+       for file in $(INFO_DEPS) make.i; do    (cd $(DESTDIR)$(infodir) && rm -f $$file $$file-[0-9] $$file-[0-9][0-9] $$file[0-9] $$file[0-9][0-9]);  done
 
 dist-info: $(INFO_DEPS)
        for base in $(INFO_DEPS); do    d=$(srcdir);    for file in `cd $$d && eval echo $$base*`; do      test -f $(distdir)/$$file      || ln $$d/$$file $(distdir)/$$file 2> /dev/null      || cp -p $$d/$$file $(distdir)/$$file;    done;  done
 
 mostlyclean-aminfo:
-       rm -f make.aux make.cp make.cps make.dvi make.fn make.fns make.ky    make.log make.pg make.toc make.tp make.tps make.vr make.vrs    make.op make.tr make.cv
+       rm -f make.aux make.cp make.cps make.dvi make.fn make.fns make.ky    make.kys make.ps make.log make.pg make.toc make.tp make.tps make.vr make.vrs    make.op make.tr make.cv make.cn
 
 clean-aminfo:
 
@@ -212,6 +217,45 @@ distclean-aminfo:
 maintainer-clean-aminfo:
        for i in $(INFO_DEPS) make.i; do rm -f `eval echo $$i*`; done
 
+install-man1:
+       $(mkinstalldirs) $(DESTDIR)$(man1dir)
+       @list='$(man1_MANS)'; \
+       l2='$(man_MANS)'; for i in $$l2; do \
+         case "$$i" in \
+           *.1*) list="$$list $$i" ;; \
+         esac; \
+       done; \
+       for i in $$list; do \
+         if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+         else file=$$i; fi; \
+         ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+         inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+         inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+         echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst"; \
+         $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst; \
+       done
+
+uninstall-man1:
+       @list='$(man1_MANS)'; \
+       l2='$(man_MANS)'; for i in $$l2; do \
+         case "$$i" in \
+           *.1*) list="$$list $$i" ;; \
+         esac; \
+       done; \
+       for i in $$list; do \
+         ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+         inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+         inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+         echo " rm -f $(DESTDIR)$(man1dir)/$$inst"; \
+         rm -f $(DESTDIR)$(man1dir)/$$inst; \
+       done
+install-man: $(MANS)
+       @$(NORMAL_INSTALL)
+       $(MAKE) install-man1
+uninstall-man:
+       @$(NORMAL_UNINSTALL)
+       $(MAKE) uninstall-man1
+
 # Assume that the only thing to do in glob is to build libglob.a,
 # but do a sanity check: if $SUBDIRS will ever have more than
 # a single directory, yell bloody murder.
@@ -266,7 +310,7 @@ mostlyclean-tags:
 clean-tags:
 
 distclean-tags:
-       rm -f TAGS ID
+       -rm -f TAGS ID
 
 maintainer-clean-tags:
 
@@ -299,32 +343,6 @@ distdir: $(DISTFILES)
        @for file in $(DISTFILES); do d=$(srcdir); test -f $(distdir)/$$file || ln $$d/$$file $(distdir)/$$file 2> /dev/null || cp -p $$d/$$file $(distdir)/$$file; done; for subdir in $(SUBDIRS); do test -d $(distdir)/$$subdir || mkdir $(distdir)/$$subdir || exit 1; chmod 777 $(distdir)/$$subdir; (cd $$subdir && $(MAKE) top_distdir=../$(top_distdir)/$$subdir distdir=../$(distdir)/$$subdir distdir) || exit 1; done
        $(MAKE) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-info
        $(MAKE) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-hook
-alloca.o alloca.lo: alloca.c config.h
-ar.o ar.lo: ar.c make.h config.h filedef.h dep.h glob/fnmatch.h
-arscan.o arscan.lo: arscan.c make.h config.h
-commands.o commands.lo: commands.c make.h config.h dep.h filedef.h  variable.h job.h commands.h
-default.o default.lo: default.c make.h config.h rule.h dep.h filedef.h  job.h commands.h variable.h
-dir.o dir.lo: dir.c make.h config.h glob/glob.h
-expand.o expand.lo: expand.c make.h config.h filedef.h job.h commands.h  variable.h
-file.o file.lo: file.c make.h config.h dep.h filedef.h job.h commands.h  variable.h
-function.o function.lo: function.c make.h config.h filedef.h variable.h  dep.h job.h commands.h
-getloadavg.o getloadavg.lo: getloadavg.c config.h
-getopt.o getopt.lo: getopt.c config.h getopt.h
-getopt1.o getopt1.lo: getopt1.c config.h getopt.h
-implicit.o implicit.lo: implicit.c make.h config.h rule.h dep.h  filedef.h
-job.o job.lo: job.c make.h config.h job.h filedef.h commands.h  variable.h
-main.o main.lo: main.c make.h config.h dep.h filedef.h variable.h job.h  commands.h getopt.h
-misc.o misc.lo: misc.c make.h config.h dep.h
-read.o read.lo: read.c make.h config.h dep.h filedef.h job.h commands.h  variable.h glob/glob.h
-remake.o remake.lo: remake.c make.h config.h filedef.h job.h commands.h  dep.h
-remote-stub.o remote-stub.lo: remote-stub.c make.h config.h filedef.h  job.h commands.h
-rule.o rule.lo: rule.c make.h config.h dep.h filedef.h job.h commands.h  variable.h rule.h
-signame.o signame.lo: signame.c config.h signame.h
-variable.o variable.lo: variable.c make.h config.h dep.h filedef.h job.h  commands.h variable.h
-version.o version.lo: version.c config.h
-vpath.o vpath.lo: vpath.c make.h config.h filedef.h variable.h
-fnmatch.o fnmatch.lo: fnmatch.c fnmatch.h ../config.h
-glob.o glob.lo: glob.c fnmatch.h glob.h ../config.h
 
 info: $(INFO_DEPS) info-recursive
 dvi: $(DVIS) dvi-recursive
@@ -362,19 +380,19 @@ installdirs: installdirs-recursive
 
 
 mostlyclean-generic:
-       test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
+       -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
 
 clean-generic:
-       test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+       -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
 
 distclean-generic:
-       rm -f Makefile $(DISTCLEANFILES)
-       rm -f config.cache config.log stamp-h stamp-h[0-9]*
-       test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -rm -f Makefile $(DISTCLEANFILES)
+       -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
 
 maintainer-clean-generic:
-       test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
-       test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+       -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+       -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
 mostlyclean-am:  mostlyclean-hdr mostlyclean-binPROGRAMS  mostlyclean-compile mostlyclean-aminfo mostlyclean-tags  mostlyclean-generic
 
 clean-am:  clean-hdr clean-binPROGRAMS clean-compile clean-aminfo  clean-tags clean-generic mostlyclean-am
index 5463428..ab1c1f1 100644 (file)
@@ -1,6 +1,6 @@
 # -*-Makefile-*-, or close enough
 
-AUTOMAKE_OPTIONS = 1.2
+AUTOMAKE_OPTIONS = 1.3
 
 bin_PROGRAMS = make
 
@@ -13,12 +13,13 @@ make_SOURCES =      main.c commands.c job.c dir.c file.c misc.c read.c remake.c \
 make_LDADD =   @LIBOBJS@ @ALLOCA@ glob/libglob.a
 
 info_TEXINFOS =        make.texinfo
+man_MANS =     make.1
 
 INCLUDES =     -I$(srcdir)/glob -DLIBDIR=\"$(libdir)\" -DINCLUDEDIR=\"$(includedir)\"
 
 BUILT_SOURCES =        README build.sh.in
 
-EXTRA_DIST =   make.man $(BUILT_SOURCES) remote-cstms.c\
+EXTRA_DIST =   $(BUILT_SOURCES) $(man_MANS) README.customs remote-cstms.c\
                make-stds.texi texinfo.tex SCOPTIONS SMakefile\
                README.Amiga Makefile.ami config.ami make.lnk amiga.c amiga.h\
                README.DOS Makefile.DOS configure.bat dosbuild.bat configh.dos\
@@ -31,13 +32,43 @@ SUBDIRS =   glob
 MOSTLYCLEANFILES = loadavg.c
 CLEANFILES =   loadavg
 
+
+# --------------- Local INSTALL Section
+
+# If necessary, change the gid of the app and turn on the setgid flag.
+#
+
+# Whether or not make needs to be installed setgid.
+# The value should be either `true' or `false'.
+# On many systems, the getloadavg function (used to implement the `-l'
+# switch) will not work unless make is installed setgid kmem.
+#
+inst_setgid = @NEED_SETGID@
+
+# Install make setgid to this group so it can get the load average.
+#
+inst_group = @KMEM_GROUP@
+
+install-exec-local:
+       @if $(inst_setgid); then \
+          app=$(DESTDIR)$(bindir)/`echo $(bin_PROGRAMS)|sed '$(transform)'`; \
+          if chgrp $(inst_group) $$app && chmod g+s $$app; then \
+            echo "chgrp $(inst_group) $$app && chmod g+s $$app"; \
+          else \
+            echo "$$app needs to be owned by group $(inst_group) and setgid;"; \
+            echo "otherwise the \`-l' option will probably not work."; \
+            echo "You may need special privileges to complete the installation"; \
+            echo "of $$app."; \
+          fi; \
+        else true; fi
+
 # --------------- Local DIST Section
 
 # Install the w32 subdirectory
 #
 dist-hook:
        (cd $(srcdir); \
-        w32=`find w32 -follow \( -name CVS -prune \) -o -type f -print`; \
+        w32=`find w32 -follow \( -name CVS -prune \) -o \( -name \*.orig -o -name \*.rej -o -name \*~ -prune \) -o -type f -print`; \
         tar chf - $$w32) \
        | (cd $(distdir); tar xfBp -)
 
@@ -52,11 +83,14 @@ check-local: check-loadavg check-regression
 loadavg: loadavg.c config.h
        @rm -f loadavg
        $(LINK) -I. -I$(srcdir) -DHAVE_CONFIG_H -DTEST $(make_LDFLAGS) loadavg.c $(LIBS)
+
 # We copy getloadavg.c into a different file rather than compiling it
 # directly because some compilers clobber getloadavg.o in the process.
+#
 loadavg.c: getloadavg.c
        ln $(srcdir)/getloadavg.c loadavg.c || \
-       cp $(srcdir)/getloadavg.c loadavg.c
+         cp $(srcdir)/getloadavg.c loadavg.c
+
 check-loadavg: loadavg
        @echo The system uptime program believes the load average to be:
        -uptime
@@ -69,8 +103,10 @@ check-loadavg: loadavg
 # specified, or else in the srcdir or the distdir, their parents, and _their_
 # parents.
 #
+MAKETESTFLAGS =
+
 check-regression: all
-       here=`pwd`; testdir=""; \
+       @here=`pwd`; testdir=""; \
          case "$(MAKE_TEST)" in "") \
            for d1 in $$here $(srcdir); do \
              for d2 in ../.. .. .; do \
@@ -83,10 +119,10 @@ check-regression: all
            *) testdir="$(MAKE_TEST)" ;; \
          esac; \
          case "$$testdir" in \
-           "") echo "Couldn't find make-test-* test suite."; exit 0;; \
+           "") echo "Couldn't find make-test-* regression test suite."; exit 0;; \
          esac; \
-         echo "cd $$testdir && ./run_make_tests -make_path $$here/make"; \
-         cd $$testdir && ./run_make_tests -make_path $$here/make
+         echo "cd $$testdir && ./run_make_tests -make $$here/make $(MAKETESTFLAGS)"; \
+         cd $$testdir && ./run_make_tests -make $$here/make $(MAKETESTFLAGS)
 
 
 # --------------- Maintainer's Section
diff --git a/NEWS b/NEWS
index 70cdc62..5bc2974 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,11 +1,57 @@
 GNU make NEWS                                               -*-indented-text-*-
   History of user-visible changes.
-  19 Sep 1997
+  19 May 1998
 
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
+Copyright (C) 1992,1993,1994,1995,1996,1997,1998 Free Software Foundation, Inc.
 See the end for copying conditions.
 
-Please send GNU make bug reports to bug-gnu-utils@prep.ai.mit.edu.
+Please send GNU make bug reports to bug-make@gnu.org.
+\f
+Version 3.77
+
+* Implement BSD make's "?=" variable assignment operator.  The variable
+  is assigned the specified value only if that variable is not already
+  defined.
+
+* Make defines a new variable, "CURDIR", to contain the current working
+  directory (after the -C option, if any, has been processed).
+  Modifying this variable has no effect on the operation of make.
+
+* Make defines a new default RCS rule, for new-style master file
+  storage: ``% :: RCS/%'' (note no ``,v'' suffix).
+
+  Make defines new default rules for DOS-style C++ file naming
+  conventions, with ``.cpp'' suffixes.  All the same rules as for
+  ``.cc'' and ``.C'' suffixes are provided, along with LINK.cpp and
+  COMPILE.cpp macros (which default to the same value as LINK.cc and
+  COMPILE.cc).  Note CPPFLAGS is still C preprocessor flags!  You should
+  use CXXFLAGS to change C++ compiler flags.
+
+* A new feature, "target-specific variable values", has been added.
+  This is a large change so please see the appropriate sections of the
+  manual for full details.  Briefly, syntax like this:
+
+    TARGET: VARIABLE = VALUE
+
+  defines VARIABLE as VALUE within the context of TARGET.  This is
+  similar to SunOS make's "TARGET := VARIABLE = VALUE" feature.  Note
+  that the assignment may be of any type, not just recursive, and that
+  the override keyword is available.
+
+  COMPATIBILITY: This new syntax means that if you have any rules where
+  the first or second dependency has an equal sign (=) in its name,
+  you'll have to escape them with a backslash: "foo : bar\=baz".
+  Further, if you have any dependencies which already contain "\=",
+  you'll have to escape both of them: "foo : bar\\\=baz".
+
+* A new appendix listing the most common error and warning messages
+  generated by GNU make, with some explanation, has been added to the
+  GNU make User's Manual.
+
+* Updates to the GNU make Customs library support (see README.customs).
+
+* Updates to the Windows 95/NT port from Rob Tulloh (see README.W32),
+  and to the DOS port from Eli Zaretski (see README.DOS).
 \f
 Version 3.76.1
 
index d82dbce..8f2b3f3 100644 (file)
-# NOTE: If you have no `make' program at all to process this makefile, run\r
-# `build_w32.bat' instead.\r
-#\r
-# Copyright (C) 1988,89,91,92,93,94,95,96,97 Free Software Foundation, Inc.\r
-# This file is part of GNU Make.\r
-#\r
-# GNU Make is free software; you can redistribute it and/or modify\r
-# it under the terms of the GNU General Public License as published by\r
-# the Free Software Foundation; either version 2, or (at your option)\r
-# any later version.\r
-#\r
-# GNU Make is distributed in the hope that it will be useful,\r
-# but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-# GNU General Public License for more details.\r
-#\r
-# You should have received a copy of the GNU General Public License\r
-# along with GNU Make; see the file COPYING.  If not, write to\r
-# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\r
-\r
-#\r
-#       NMakefile for GNU Make\r
-#\r
-\r
-LINK = link\r
-CC = cl\r
-\r
-OUTDIR=.\r
-MAKEFILE=NMakefile\r
-SUBPROC_MAKEFILE=NMakefile\r
-\r
-CFLAGS_any = /nologo /MT /W3 /GX /Zi /YX /I . /I glob /I w32/include /D WIN32 /D WINDOWS32 /D _CONSOLE /D HAVE_CONFIG_H /D NO_ARCHIVES\r
-CFLAGS_debug = $(CFLAGS_any) /Od /D _DEBUG /FR.\WinDebug/ /Fp.\WinDebug/make.pch /Fo.\WinDebug/ /Fd.\WinDebug/make.pdb\r
-CFLAGS_release = $(CFLAGS_any) /O2 /D NDEBUG /FR.\WinRel/ /Fp.\WinRel/make.pch /Fo.\WinRel/\r
-\r
-LDFLAGS_debug = w32\subproc\WinDebug\subproc.lib /NOLOGO /SUBSYSTEM:console\\r
-       /INCREMENTAL:no /PDB:WinDebug/make.pdb /MACHINE:I386 \\r
-       /OUT:WinDebug/make.exe /DEBUG\r
-LDFLAGS_release = w32\subproc\WinRel\subproc.lib /NOLOGO /SUBSYSTEM:console\\r
-       /INCREMENTAL:no /MACHINE:I386 /OUT:WinRel/make.exe\r
-\r
-all: config.h subproc Release Debug\r
-\r
-#\r
-# Make sure we build the subproc library first. It has it's own\r
-# makefile. To be portable to Windows 95, we put the instructions\r
-# on how to build the library into a batch file. On NT, we could\r
-# simply have done foo && bar && dog, but this doesn't port.\r
-#\r
-subproc: w32/subproc/WinDebug/subproc.lib w32/subproc/WinRel/subproc.lib\r
-\r
-w32/subproc/WinDebug/subproc.lib w32/subproc/WinRel/subproc.lib:\r
-       subproc.bat $(SUBPROC_MAKEFILE)\r
-\r
-config.h: config.h.W32\r
-       copy $? $@\r
-\r
-Release:\r
-       nmake /f $(MAKEFILE) LDFLAGS="$(LDFLAGS_release)" CFLAGS="$(CFLAGS_release)" OUTDIR=WinRel WinRel/make.exe\r
-Debug:\r
-       nmake /f $(MAKEFILE) LDFLAGS="$(LDFLAGS_debug)" CFLAGS="$(CFLAGS_debug)" OUTDIR=WinDebug WinDebug/make.exe\r
-\r
-clean:\r
-       rmdir /s /q WinDebug WinRel\r
-       rmdir /s /q w32\subproc\WinDebug w32\subproc\WinRel\r
-       erase config.h\r
-\r
-$(OUTDIR):\r
-       if not exist .\$@\nul mkdir .\$@\r
-\r
-LIBS = kernel32.lib user32.lib advapi32.lib\r
-\r
-OBJS = \\r
-       $(OUTDIR)/ar.obj \\r
-       $(OUTDIR)/arscan.obj \\r
-       $(OUTDIR)/commands.obj \\r
-       $(OUTDIR)/default.obj \\r
-       $(OUTDIR)/dir.obj \\r
-       $(OUTDIR)/expand.obj \\r
-       $(OUTDIR)/file.obj \\r
-       $(OUTDIR)/function.obj \\r
-       $(OUTDIR)/getloadavg.obj \\r
-       $(OUTDIR)/getopt.obj \\r
-       $(OUTDIR)/getopt1.obj \\r
-       $(OUTDIR)/implicit.obj \\r
-       $(OUTDIR)/job.obj \\r
-       $(OUTDIR)/main.obj \\r
-       $(OUTDIR)/misc.obj \\r
-       $(OUTDIR)/read.obj \\r
-       $(OUTDIR)/remake.obj \\r
-       $(OUTDIR)/remote-stub.obj \\r
-       $(OUTDIR)/rule.obj \\r
-       $(OUTDIR)/signame.obj \\r
-       $(OUTDIR)/variable.obj \\r
-       $(OUTDIR)/version.obj \\r
-       $(OUTDIR)/vpath.obj \\r
-       $(OUTDIR)/glob.obj \\r
-       $(OUTDIR)/fnmatch.obj \\r
-       $(OUTDIR)/dirent.obj \\r
-       $(OUTDIR)/pathstuff.obj\r
-\r
-$(OUTDIR)/make.exe: $(OUTDIR) $(OBJS)\r
-       $(LINK) @<<\r
-               $(LDFLAGS) $(LIBS) $(OBJS)\r
-<<\r
-\r
-.c{$(OUTDIR)}.obj:\r
-       $(CC) $(CFLAGS) /c $<\r
-       \r
-$(OUTDIR)/ar.obj : ar.c make.h filedef.h dep.h\r
-$(OUTDIR)/arscan.obj : arscan.c make.h\r
-$(OUTDIR)/commands.obj : commands.c\r
-$(OUTDIR)/default.obj : default.c make.h rule.h dep.h filedef.h job.h commands.h variable.h\r
-$(OUTDIR)/dir.obj :  dir.c make.h\r
-$(OUTDIR)/expand.obj : expand.c make.h filedef.h job.h commands.h variable.h\r
-$(OUTDIR)/file.obj : file.c make.h dep.h filedef.h job.h commands.h variable.h\r
-$(OUTDIR)/function.obj : function.c make.h filedef.h variable.h dep.h job.h commands.h\r
-$(OUTDIR)/getloadavg.obj : getloadavg.c\r
-$(OUTDIR)/getopt.obj : getopt.c\r
-$(OUTDIR)/getopt1.obj : getopt1.c getopt.h\r
-$(OUTDIR)/implicit.obj : implicit.c make.h rule.h dep.h filedef.h\r
-$(OUTDIR)/job.obj : job.c make.h job.h filedef.h commands.h variable.h\r
-$(OUTDIR)/main.obj : main.c make.h dep.h filedef.h variable.h job.h commands.h getopt.h\r
-$(OUTDIR)/misc.obj : misc.c make.h dep.h\r
-$(OUTDIR)/read.obj : read.c make.h dep.h filedef.h job.h commands.h variable.h glob/glob.h\r
-$(OUTDIR)/remake.obj : remake.c make.h filedef.h job.h commands.h dep.h\r
-$(OUTDIR)/remote-stub.obj : remote-stub.c make.h filedef.h job.h commands.h\r
-$(OUTDIR)/rule.obj : rule.c make.h dep.h filedef.h job.h commands.h variable.h rule.h\r
-$(OUTDIR)/signame.obj : signame.c signame.h\r
-$(OUTDIR)/variable.obj : variable.c make.h dep.h filedef.h job.h commands.h variable.h\r
-$(OUTDIR)/version.obj : version.c\r
-$(OUTDIR)/vpath.obj : vpath.c make.h filedef.h variable.h\r
-$(OUTDIR)/glob.obj : glob/glob.c\r
-       $(CC) $(CFLAGS) /c $?\r
-$(OUTDIR)/fnmatch.obj : glob/fnmatch.c\r
-       $(CC) $(CFLAGS) /c $?\r
-$(OUTDIR)/dirent.obj : w32/compat/dirent.c\r
-       $(CC) $(CFLAGS) /c $?\r
-$(OUTDIR)/pathstuff.obj : w32/pathstuff.c\r
-       $(CC) $(CFLAGS) /c $?\r
-\r
+# NOTE: If you have no `make' program at all to process this makefile, run
+# `build_w32.bat' instead.
+#
+# Copyright (C) 1988,89,91,92,93,94,95,96,97 Free Software Foundation, Inc.
+# This file is part of GNU Make.
+#
+# GNU Make is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# GNU Make is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Make; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+#
+#       NMakefile for GNU Make
+#
+
+LINK = link
+CC = cl
+
+OUTDIR=.
+MAKEFILE=NMakefile
+SUBPROC_MAKEFILE=NMakefile
+
+CFLAGS_any = /nologo /MT /W3 /GX /Zi /YX /I . /I glob /I w32/include /D WIN32 /D WINDOWS32 /D _CONSOLE /D HAVE_CONFIG_H /D NO_ARCHIVES
+CFLAGS_debug = $(CFLAGS_any) /Od /D DEBUG /D _DEBUG /FR.\WinDebug/ /Fp.\WinDebug/make.pch /Fo.\WinDebug/ /Fd.\WinDebug/make.pdb
+CFLAGS_release = $(CFLAGS_any) /O2 /D NDEBUG /FR.\WinRel/ /Fp.\WinRel/make.pch /Fo.\WinRel/
+
+LDFLAGS_debug = w32\subproc\WinDebug\subproc.lib /NOLOGO /SUBSYSTEM:console\
+       /INCREMENTAL:no /PDB:WinDebug/make.pdb /MACHINE:I386 \
+       /OUT:WinDebug/make.exe /DEBUG
+LDFLAGS_release = w32\subproc\WinRel\subproc.lib /NOLOGO /SUBSYSTEM:console\
+       /INCREMENTAL:no /MACHINE:I386 /OUT:WinRel/make.exe
+
+all: config.h subproc Release Debug
+
+#
+# Make sure we build the subproc library first. It has it's own
+# makefile. To be portable to Windows 95, we put the instructions
+# on how to build the library into a batch file. On NT, we could
+# simply have done foo && bar && dog, but this doesn't port.
+#
+subproc: w32/subproc/WinDebug/subproc.lib w32/subproc/WinRel/subproc.lib
+
+w32/subproc/WinDebug/subproc.lib w32/subproc/WinRel/subproc.lib:
+       subproc.bat $(SUBPROC_MAKEFILE) $(MAKE)
+
+config.h: config.h.W32
+       copy $? $@
+
+Release:
+       $(MAKE) /f $(MAKEFILE) LDFLAGS="$(LDFLAGS_release)" CFLAGS="$(CFLAGS_release)" OUTDIR=WinRel WinRel/make.exe
+Debug:
+       $(MAKE) /f $(MAKEFILE) LDFLAGS="$(LDFLAGS_debug)" CFLAGS="$(CFLAGS_debug)" OUTDIR=WinDebug WinDebug/make.exe
+
+clean:
+       rmdir /s /q WinDebug WinRel
+       rmdir /s /q w32\subproc\WinDebug w32\subproc\WinRel
+       erase config.h
+       erase *.pdb
+
+$(OUTDIR):
+       if not exist .\$@\nul mkdir .\$@
+
+LIBS = kernel32.lib user32.lib advapi32.lib
+
+OBJS = \
+       $(OUTDIR)/ar.obj \
+       $(OUTDIR)/arscan.obj \
+       $(OUTDIR)/commands.obj \
+       $(OUTDIR)/default.obj \
+       $(OUTDIR)/dir.obj \
+       $(OUTDIR)/expand.obj \
+       $(OUTDIR)/file.obj \
+       $(OUTDIR)/function.obj \
+       $(OUTDIR)/getloadavg.obj \
+       $(OUTDIR)/getopt.obj \
+       $(OUTDIR)/getopt1.obj \
+       $(OUTDIR)/implicit.obj \
+       $(OUTDIR)/job.obj \
+       $(OUTDIR)/main.obj \
+       $(OUTDIR)/misc.obj \
+       $(OUTDIR)/read.obj \
+       $(OUTDIR)/remake.obj \
+       $(OUTDIR)/remote-stub.obj \
+       $(OUTDIR)/rule.obj \
+       $(OUTDIR)/signame.obj \
+       $(OUTDIR)/variable.obj \
+       $(OUTDIR)/version.obj \
+       $(OUTDIR)/vpath.obj \
+       $(OUTDIR)/glob.obj \
+       $(OUTDIR)/fnmatch.obj \
+       $(OUTDIR)/dirent.obj \
+       $(OUTDIR)/pathstuff.obj
+
+$(OUTDIR)/make.exe: $(OUTDIR) $(OBJS)
+       $(LINK) @<<
+               $(LDFLAGS) $(LIBS) $(OBJS)
+<<
+
+.c{$(OUTDIR)}.obj:
+       $(CC) $(CFLAGS) /c $<
+
+$(OUTDIR)/glob.obj : glob/glob.c
+       $(CC) $(CFLAGS) /c $?
+$(OUTDIR)/fnmatch.obj : glob/fnmatch.c
+       $(CC) $(CFLAGS) /c $?
+$(OUTDIR)/dirent.obj : w32/compat/dirent.c
+       $(CC) $(CFLAGS) /c $?
+$(OUTDIR)/pathstuff.obj : w32/pathstuff.c
+       $(CC) $(CFLAGS) /c $?
index 065c239..6372437 100644 (file)
@@ -37,6 +37,10 @@ To build:
       if you use PKUNZIP).  If you build Make on Windows 95, use an
       unzip program that supports long filenames in zip files.
 
+      If you are unpacking an official GNU source distribution, use
+      either DJTAR (which is part of the DJGPP development
+      environment), or the DJGPP port of GNU Tar.
+
    2. Invoke the `configure.bat' batch file.
 
       If you are building Make in-place, i.e. in the same directory
@@ -44,7 +48,7 @@ To build:
       [Enter].  Otherwise, you need to supply the path to the source
       directory as an argument to the batch file, like this:
 
-               configure.bat c:/djgpp/gnu/make-3.76
+               configure.bat c:/djgpp/gnu/make-%VERSION%
 
       Note the forward slashes: you MUST use them here.
 
@@ -65,7 +69,7 @@ To build:
       If you are building from outside of the source directory, you
       need to tell Make where the sources are, like this:
 
-               make srcdir=c:/djgpp/gnu/make-3.76
+               make srcdir=c:/djgpp/gnu/make-%VERSION%
 
       (configure.bat will tell you this when it finishes).  You MUST
       use a full, not relative, name of the source directory here, or
@@ -73,8 +77,8 @@ To build:
 
    6. After Make finishes, if you have a Unix-style shell installed,
       you can use the `install' target to install the package.  You
-      will also need GNU Fileutils and GNU Sh-utils for this (they
-      should be available from the DJGPP sites).
+      will also need GNU Fileutils and GNU Sed for this (they should
+      be available from the DJGPP sites).
 
       Without a Unix-style shell, you will have to install programs
       and the docs manually.  Copy make.exe to a directory on your
@@ -82,7 +86,7 @@ To build:
       file `dir' in your Info directory by adding the following item
       to the main menu:
 
-       * GNU make: (make.info).           The GNU make utility.
+       * Make: (make.info).           The GNU make utility.
 
       If you have the `install-info' program (from the GNU Texinfo
       package), it will do that for you if you invoke it like this:
@@ -92,8 +96,8 @@ To build:
       (If your Info directory is other than C:\DJGPP\INFO, change this
       command accordingly.)
 
-   7. The `clean' targets also require Unix-style shell and `test' and
-      `rm' programs (from Fileutils and Sh-utils, accordingly). 
+   7. The `clean' targets also require Unix-style shell, and GNU Sed
+      and `rm' programs (the latter from Fileutils).
 
 
 
@@ -240,8 +244,7 @@ Notes:
       doesn't include characters illegal on MSDOS FAT filesystems,
       will be automatically down-cased.)  User reports that I have
       indicate that this default behavior is generally what you'd
-      expect; however, since support for long filenames in the DJGPP
-      port of GNU Make is relatively new, your input is most welcome.
+      expect; however, your input is most welcome.
 
       In any case, if you hit a situation where you must force Make to
       get the 8+3 DOS filenames in upper case, set FNCASE=y in the
@@ -283,8 +286,8 @@ Bug reports:
    reported first on the comp.os.msdos.djgpp news group (if you cannot
    post to Usenet groups, write to the DJGPP mailing list,
    <djgpp@delorie.com>, which is an email gateway into the above news
-   group).  For other bugs, please follow the the procedure explained
-   in the "Bugs" chapter of the Info docs.  If you don't have an Info
+   group).  For other bugs, please follow the procedure explained in
+   the "Bugs" chapter of the Info docs.  If you don't have an Info
    reader, look up that chapter in the `make.i1' file with any text
    browser/editor.
 
index ac5001d..ca7f32c 100644 (file)
@@ -46,6 +46,35 @@ GNU make and sh.exe:
        freely available. It may be available someday, but I am not in control
        of this decision nor do I influence it. Sorry!
 
+GNU make and Cygnus GNU WIN32 tools (BATCH_MODE_ONLY_SHELL)
+
+       GNU make now has support for the Cygnus GNU WIN32 toolset. The
+       GNU WIN32 version of Bourne shell does not behave well when
+       invoked as 'sh -c' from CreateProcess().  The main problem is it
+       seems to have a hard time handling quoted strings correctly. This
+       problem goes away when invoking the Cygnus shell on a shell script.
+
+       To work around this difficulty, this version of make supports
+       a new batch mode.  When BATCH_MODE_ONLY_SHELL is defined at compile
+       time, make forces all command lines to be executed via script
+       files instead of by command line.
+
+       A native WIN32 system with no Bourne shell will also run
+       in batch mode.  All command lines will be put into batch files
+       and executed via $(COMSPEC) (%COMSPEC%).
+
+       If you wish to use Cygnus' GNUWIN32 shell, be sure you define
+       BATCH_MODE_ONLY_SHELL in the config.h.W32 prior to building make.
+       The new feataure was tested with the b18 version of the Cygnus
+       user tools.
+
+GNU make and MKS shell
+
+       There is now semi-official support for the MKS shell. To turn this
+       support on, define HAVE_MKS_SHELL in the config.h.W32 before you
+       build make.  Do not define BATCH_MODE_ONLY_SHELL if you turn
+       on HAVE_MKS_SHELL.
+
 GNU make handling of drive letters in pathnames (PATH, vpath, VPATH):
 
        There is a caveat that should be noted with respect to handling
@@ -127,6 +156,38 @@ Pathnames and white space:
        and you are free to take a crack at making this work. The code
        in w32/pathstuff.c and vpath.c would be the places to start.
 
+Pathnames and Case insensitivity:
+
+       Unlike Unix, Windows 95/NT systems are case insensitive but case
+       preserving.  For example if you tell the file system to create a
+       file named "Target", it will preserve the case.  Subsequent access to
+       the file with other case permutations will succeed (i.e. opening a
+       file named "target" or "TARGET" will open the file "Target").
+
+       By default, GNU make retains its case sensitivity when comparing
+       target names and existing files or directories.  It can be
+       configured, however, into a case preserving and case insensitive
+       mode by adding a define for HAVE_CASE_INSENSITIVE_FS to
+       config.h.W32.
+
+       For example, the following makefile will create a file named
+       Target in the directory subdir which will subsequently be used
+       to satisfy the dependency of SUBDIR/DepTarget on SubDir/TARGET.
+       Without HAVE_CASE_INSENSITIVE_FS configured, the dependency link
+       will not be made:
+
+       subdir/Target:
+               touch $@
+
+       SUBDIR/DepTarget: SubDir/TARGET
+               cp $^ $@
+
+       Reliance on this behavior also eliminates the ability of GNU make
+       to use case in comparison of matching rules.  For example, it is
+       not possible to set up a C++ rule using %.C that is different
+       than a C rule using %.c.  GNU make will consider these to be the
+       same rule and will issue a warning.
+
 SAMBA/NTFS/VFAT:
 
        I have not had any success building the debug version of this
diff --git a/README.customs b/README.customs
new file mode 100644 (file)
index 0000000..9ad21f6
--- /dev/null
@@ -0,0 +1,73 @@
+                                                            -*-indented-text-*-
+
+GNU make can utilize the Customs library, distributed with Pmake, to
+provide builds distributed across multiple hosts.
+
+In order to utilize this capability, you must first download and build
+the Customs library.  It is contained in the Pmake distribution, which
+can be obtained at:
+
+  ftp://ftp.icsi.berkeley.edu/pub/ai/stolcke/software/
+
+This integration was tested (superficially) with Pmake 2.1.33.
+
+
+BUILDING CUSTOMS
+----------------
+
+First, build pmake and Customs.  You need to build pmake first, because
+Customs require pmake to build.  Unfortunately, this is not trivial;
+please see the pmake and Customs documentation for details.  The best
+place to look for instructions is in the pmake-2.1.33/INSTALL file.
+
+Note that the 2.1.33 Pmake distribution comes with a set of patches to
+GNU make, distributed in the pmake-2.1.33/etc/gnumake/ directory.  These
+patches are based on GNU make 3.75 (there are patches for earlier
+versions of GNU make, also).  The parts of this patchfile which relate
+directly to Customs support have already been incorporated into this
+version of GNU make, so you should _NOT_ apply the patch file.
+
+However, there are a few non-Customs specific (as far as I could tell)
+changes here which are not incorporated (for example, the modification
+to try expanding -lfoo to libfoo.so).  If you rely on these changes
+you'll need to re-apply them by hand.
+
+Install the Customs library and header files according to the
+documentation.  You should also install the man pages (contrary to
+comments in the documentation, they weren't installed automatically for
+me; I had to cd to the ``pmake-2.1.33/doc'' directory and run ``pmake
+install'' there directly).
+
+
+BUILDING GNU MAKE
+-----------------
+
+Once you've installed Customs, you can build GNU make to use it.  When
+configuring GNU make, merely use the ``--with-customs=DIR'' option.
+Provide the directory containing the ``lib'' and ``include/customs''
+subdirectories as DIR.  For example, if you installed the customs
+library in /usr/local/lib and the headers in /usr/local/include/customs,
+then you'd pass ``--with-customs=/usr/local'' as an option to configure.
+
+Run make (or use build.sh) normally to build GNU make as described in
+the INSTALL file.
+
+See the documentation for Customs for information on starting and
+configuring Customs.
+
+
+PROBLEMS
+--------
+
+SunOS 4.1.x:
+  The customs/sprite.h header file #includes the <malloc.h> header
+  files; this conflicts with GNU make's configuration so you'll get a
+  compile error if you use GCC (or any other ANSI-capable C compiler).
+
+  I commented out the #include in sprite.h:107:
+
+    #if defined(sun) || defined(ultrix) || defined(hpux) || defined(sgi)
+    /* #include <malloc.h> */
+    #else
+
+  YMMV.
index 0b1736b..e011f99 100644 (file)
@@ -14,6 +14,9 @@ Some systems' Make programs are broken and cannot process the Makefile for
 GNU Make.  If you get errors from your system's Make when building GNU
 Make, try using `build.sh' instead.
 
+  - See README.customs for details on integrating GNU make with the
+    Customs distributed build environment from the Pmake distribution.
+
   - See README.W32 for details about GNU Make on Windows NT or 95.
 
   - See README.Amiga for details about GNU Make on AmigaDOS.
index 4705713..2caa82e 100644 (file)
@@ -210,67 +210,3 @@ glob-clean glob-realclean:
        cd glob
        smake $@
 <
-
-# The automatically generated dependencies below may omit config.h
-# because it is included with ``#include <config.h>'' rather than
-# ``#include "config.h"''.  So we add the explicit dependency to make sure.
-$(objs): config.h
-
-# Automatically generated dependencies will be put at the end of the file.
-
-# Automatically generated dependencies.
-commands.o: commands.c make.h dep.h filedef.h variable.h job.h \
- commands.h
-
-job.o: job.c make.h job.h filedef.h commands.h variable.h
-
-dir.o: dir.c make.h
-
-file.o: file.c make.h dep.h filedef.h job.h commands.h variable.h
-
-misc.o: misc.c make.h dep.h
-
-main.o: main.c make.h dep.h filedef.h variable.h job.h commands.h \
- getopt.h
-
-read.o: read.c make.h dep.h filedef.h job.h commands.h variable.h \
- glob/glob.h
-
-remake.o: remake.c make.h filedef.h job.h commands.h dep.h
-
-rule.o: rule.c make.h dep.h filedef.h job.h commands.h variable.h \
- rule.h
-
-implicit.o: implicit.c make.h rule.h dep.h filedef.h
-
-default.o: default.c make.h rule.h dep.h filedef.h job.h commands.h \
- variable.h
-
-variable.o: variable.c make.h dep.h filedef.h job.h commands.h \
- variable.h
-
-expand.o: expand.c make.h filedef.h job.h commands.h variable.h
-
-function.o: function.c make.h filedef.h variable.h dep.h job.h \
- commands.h amiga.h
-
-vpath.o: vpath.c make.h filedef.h variable.h
-
-version.o: version.c
-
-ar.o: ar.c make.h filedef.h dep.h
-
-arscan.o: arscan.c make.h
-
-signame.o: signame.c signame.h
-
-remote-stub.o: remote-stub.c make.h filedef.h job.h commands.h
-
-getopt.o: getopt.c
-
-getopt1.o : getopt1.c getopt.h
-
-getloadavg.o: getloadavg.c
-
-amiga.o: amiga.c make.h variable.h amiga.h
-
diff --git a/acinclude.m4 b/acinclude.m4
new file mode 100644 (file)
index 0000000..343c333
--- /dev/null
@@ -0,0 +1,131 @@
+dnl acinclude.m4 -- Extra macros needed for GNU make.
+dnl
+dnl Automake will incorporate this into its generated aclocal.m4.
+
+dnl ---------------------------------------------------------------------------
+dnl Got this from the lynx 2.8 distribution.
+dnl by T.E.Dickey <dickey@clark.net>
+dnl and Jim Spath <jspath@mail.bcpl.lib.md.us>
+dnl and Philippe De Muyter <phdm@macqel.be>
+dnl
+dnl Created: 1997/1/28
+dnl Updated: 1997/12/23
+dnl ---------------------------------------------------------------------------
+dnl After checking for functions in the default $LIBS, make a further check
+dnl for the functions that are netlib-related (these aren't always in the
+dnl libc, etc., and have to be handled specially because there are conflicting
+dnl and broken implementations.
+dnl Common library requirements (in order):
+dnl    -lresolv -lsocket -lnsl
+dnl    -lnsl -lsocket
+dnl    -lsocket
+dnl    -lbsd
+AC_DEFUN([CF_NETLIBS],[
+cf_test_netlibs=no
+AC_MSG_CHECKING(for network libraries)
+AC_CACHE_VAL(cf_cv_netlibs,[
+AC_MSG_RESULT(working...)
+cf_cv_netlibs=""
+cf_test_netlibs=yes
+AC_CHECK_FUNCS(gethostname,,[
+       CF_RECHECK_FUNC(gethostname,nsl,cf_cv_netlibs,[
+               CF_RECHECK_FUNC(gethostname,socket,cf_cv_netlibs)])])
+#
+# FIXME:  sequent needs this library (i.e., -lsocket -linet -lnsl), but
+# I don't know the entrypoints - 97/7/22 TD
+AC_CHECK_LIB(inet,main,cf_cv_netlibs="-linet $cf_cv_netlibs")
+#
+if test "$ac_cv_func_lsocket" != no ; then
+AC_CHECK_FUNCS(socket,,[
+       CF_RECHECK_FUNC(socket,socket,cf_cv_netlibs,[
+               CF_RECHECK_FUNC(socket,bsd,cf_cv_netlibs)])])
+fi
+#
+AC_CHECK_FUNCS(gethostbyname,,[
+       CF_RECHECK_FUNC(gethostbyname,nsl,cf_cv_netlibs)])
+#
+AC_CHECK_FUNCS(strcasecmp,,[
+       CF_RECHECK_FUNC(strcasecmp,resolv,cf_cv_netlibs)])
+])
+LIBS="$LIBS $cf_cv_netlibs"
+test $cf_test_netlibs = no && echo "$cf_cv_netlibs" >&AC_FD_MSG
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Re-check on a function to see if we can pick it up by adding a library.
+dnl    $1 = function to check
+dnl    $2 = library to check in
+dnl    $3 = environment to update (e.g., $LIBS)
+dnl    $4 = what to do if this fails
+dnl
+dnl This uses 'unset' if the shell happens to support it, but leaves the
+dnl configuration variable set to 'unknown' if not.  This is a little better
+dnl than the normal autoconf test, which gives misleading results if a test
+dnl for the function is made (e.g., with AC_CHECK_FUNC) after this macro is
+dnl used (autoconf does not distinguish between a null token and one that is
+dnl set to 'no').
+AC_DEFUN([CF_RECHECK_FUNC],[
+AC_CHECK_LIB($2,$1,[
+       CF_UPPER(cf_tr_func,$1)
+       AC_DEFINE_UNQUOTED(HAVE_$cf_tr_func)
+       ac_cv_func_$1=yes
+       $3="-l$2 [$]$3"],[
+       ac_cv_func_$1=unknown
+       unset ac_cv_func_$1 2>/dev/null
+       $4],
+       [[$]$3])
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Make an uppercase version of a variable
+dnl $1=uppercase($2)
+AC_DEFUN([CF_UPPER],
+[
+changequote(,)dnl
+$1=`echo $2 | tr '[a-z]' '[A-Z]'`
+changequote([,])dnl
+])dnl
+
+dnl ---------------------------------------------------------------------------
+dnl Got this from the GNU fileutils 3.16r distribution
+dnl by Paul Eggert <egger@twinsun.com>
+dnl ---------------------------------------------------------------------------
+
+dnl The problem is that the default compilation flags in Solaris 2.6 won't
+dnl let programs access large files;  you need to tell the compiler that
+dnl you actually want your programs to work on large files.  For more
+dnl details about this brain damage please see:
+dnl http://www.sas.com/standards/large.file/x_open.20Mar96.html
+
+AC_DEFUN(AC_LFS,
+[dnl
+  # If available, prefer support for large files unless the user specified
+  # one of the CPPFLAGS, LDFLAGS, or LIBS variables.
+  AC_MSG_CHECKING(whether large file support needs explicit enabling)
+  ac_getconfs=''
+  ac_result=yes
+  ac_set=''
+  ac_shellvars='CPPFLAGS LDFLAGS LIBS'
+  for ac_shellvar in $ac_shellvars; do
+    case $ac_shellvar in
+      CPPFLAGS) ac_lfsvar=LFS_CFLAGS ;;
+      *) ac_lfsvar=LFS_$ac_shellvar ;;
+    esac
+    eval test '"${'$ac_shellvar'+set}"' = set && ac_set=$ac_shellvar
+    (getconf $ac_lfsvar) >/dev/null 2>&1 || { ac_result=no; break; }
+    ac_getconf=`getconf $ac_lfsvar`
+    ac_getconfs=$ac_getconfs$ac_getconf
+    eval ac_test_$ac_shellvar=\$ac_getconf
+  done
+  case "$ac_result$ac_getconfs" in
+    yes) ac_result=no ;;
+  esac
+  case "$ac_result$ac_set" in
+    yes?*) ac_result="yes, but $ac_set is already set, so use its settings"
+  esac
+  AC_MSG_RESULT($ac_result)
+  case $ac_result in
+    yes)
+      for ac_shellvar in $ac_shellvars; do
+       eval $ac_shellvar=\$ac_test_$ac_shellvar
+      done ;;
+  esac
+])
index 9cf746b..13ae45b 100644 (file)
--- a/arscan.c
+++ b/arscan.c
@@ -600,15 +600,12 @@ ar_name_equal (name, mem, truncated)
       abort ();
 #else
       struct ar_hdr hdr;
-      return !strncmp (name, mem,
-                      sizeof (hdr.ar_name) -
 #if !defined (__hpux) && !defined (cray)
-                      1
+      return !strncmp (name, mem, sizeof(hdr.ar_name) - 1);
 #else
-                      2
+      return !strncmp (name, mem, sizeof(hdr.ar_name) - 2);
 #endif /* !__hpux && !cray */
-                      );
-#endif
+#endif /* !AIAMAG */
     }
 #endif /* !VMS */
 
index 1be0ccb..b7103ed 100644 (file)
 
 /* Define if you have the sun library (-lsun).  */
 #undef HAVE_LIBSUN
+
+/* Define for Case Insensitve behavior */
+#define HAVE_CASE_INSENSITIVE_FS
index cf8a888..aa5a027 100644 (file)
@@ -29,7 +29,7 @@
 
 /* Define if you have alloca, as a function or macro.  */
 #undef HAVE_ALLOCA
-#define HAVE_ALLOCA
+#define HAVE_ALLOCA 1
 
 /* Define if you have <alloca.h> and it should be used (not on Ultrix).  */
 #undef HAVE_ALLOCA_H
@@ -52,7 +52,7 @@
 
 /* Define if you support file names longer than 14 characters.  */
 #undef HAVE_LONG_FILE_NAMES
-#define HAVE_LONG_FILE_NAMES
+#define HAVE_LONG_FILE_NAMES 1
 
 /* Define if you have a working `mmap' system call.  */
 #undef HAVE_MMAP
 
 /* Define if you have the strcoll function and it is properly defined.  */
 #undef HAVE_STRCOLL
-#define HAVE_STRCOLL
+#define HAVE_STRCOLL 1
 
 /* Define if your struct stat has st_rdev.  */
 #undef HAVE_ST_RDEV
-#define HAVE_ST_RDEV
+#define HAVE_ST_RDEV 1
 
 /* Define if you have the strftime function.  */
 #undef HAVE_STRFTIME
-#define HAVE_STRFTIME
+#define HAVE_STRFTIME 1
 
 /* Define if you have <sys/wait.h> that is POSIX.1 compatible.  */
 #undef HAVE_SYS_WAIT_H
 /* Define if you don't have tm_zone but do have the external array
    tzname.  */
 #undef HAVE_TZNAME
-#define HAVE_TZNAME
+#define HAVE_TZNAME 1
 
 /* Define if you have <unistd.h>.  */
 #undef HAVE_UNISTD_H
 
 /* Define if utime(file, NULL) sets file's timestamp to the present.  */
 #undef HAVE_UTIME_NULL
-#define HAVE_UTIME_NULL
+#define HAVE_UTIME_NULL 1
 
 /* Define if you have <vfork.h>.  */
 #undef HAVE_VFORK_H
 
 /* Define if you have the vprintf function.  */
 #undef HAVE_VPRINTF
-#define HAVE_VPRINTF
+#define HAVE_VPRINTF 1
 
 /* Define if you have the wait3 system call.  */
 #undef HAVE_WAIT3
 
 /* Define if you need to in order for stat and other things to work.  */
 #undef _POSIX_SOURCE
-#define _POSIX_SOURCE
+#define _POSIX_SOURCE 1
 
 /* Define as the return type of signal handlers (int or void).  */
 #undef RETSIGTYPE
 
 /* Define if you have the ANSI C header files.  */
 #undef STDC_HEADERS
-#define STDC_HEADERS
+#define STDC_HEADERS 1
 
 /* Define on System V Release 4.  */
 #undef SVR4
 
 /* Define if you have the dup2 function.  */
 #undef HAVE_DUP2
-#define HAVE_DUP2
+#define HAVE_DUP2 1
 
 /* Define if you have the getcwd function.  */
 #undef HAVE_GETCWD
-#define HAVE_GETCWD
+#define HAVE_GETCWD 1
 
 /* Define if you have the getgroups function.  */
 #undef HAVE_GETGROUPS
 
 /* Define if you have the mktemp function.  */
 #undef HAVE_MKTEMP
-#define HAVE_MKTEMP
+#define HAVE_MKTEMP 1
 
 /* Define if you have the psignal function.  */
 #undef HAVE_PSIGNAL
 
 /* Define if you have the strerror function.  */
 #undef HAVE_STRERROR
-#define HAVE_STRERROR
+#define HAVE_STRERROR 1
 
 /* Define if you have the strsignal function.  */
 #undef HAVE_STRSIGNAL
 
 /* Define if you have the <dirent.h> header file.  */
 #undef HAVE_DIRENT_H
-#define HAVE_DIRENT_H
+#define HAVE_DIRENT_H 1
 
 /* Define if you have the <fcntl.h> header file.  */
 #undef HAVE_FCNTL_H
-#define HAVE_FCNTL_H
+#define HAVE_FCNTL_H 1
 
 /* Define if you have the <limits.h> header file.  */
 #undef HAVE_LIMITS_H
-#define HAVE_LIMITS_H
+#define HAVE_LIMITS_H 1
 
 /* Define if you have the <mach/mach.h> header file.  */
 #undef HAVE_MACH_MACH_H
 
 /* Define if you have the <memory.h> header file.  */
 #undef HAVE_MEMORY_H
-#define HAVE_MEMORY_H
+#define HAVE_MEMORY_H 1
 
 /* Define if you have the <ndir.h> header file.  */
 #undef HAVE_NDIR_H
 
 /* Define if you have the <string.h> header file.  */
 #undef HAVE_STRING_H
-#define HAVE_STRING_H
+#define HAVE_STRING_H 1
 
 /* Define if you have the <sys/dir.h> header file.  */
 #undef HAVE_SYS_DIR_H
 
 /* Define if you have the <sys/timeb.h> header file.  */
 #undef HAVE_SYS_TIMEB_H
-#define HAVE_SYS_TIMEB_H
+#define HAVE_SYS_TIMEB_H 1
 
 /* Define if you have the <sys/wait.h> header file.  */
 #undef HAVE_SYS_WAIT_H
 
 /* Define if you have the sun library (-lsun).  */
 #undef HAVE_LIBSUN
+
+/*
+ * Refer to README.W32 for info on the following settings
+ */
+
+/*
+   Define if you have the Cygnus GNU WIN32 tool set or a shell
+   that does not grok 'sh -c quoted-command-line' correctly.
+ */
+#undef BATCH_MODE_ONLY_SHELL
+
+/*
+   Define if you have the MKS tool set or shell. Do NOT define
+   BATCH_MODE_ONLY_SHELL if you define HAVE_MKS_SHELL
+ */
+#undef HAVE_MKS_SHELL
+
+/* Define if you prefer Case Insensitve behavior */
+#undef HAVE_CASE_INSENSITIVE_FS
index 655ee7e..8fb99f7 100644 (file)
@@ -3,7 +3,7 @@ AC_REVISION([$Id$])
 AC_PREREQ(2.12)dnl             dnl Minimum Autoconf version required.
 AC_INIT(vpath.c)dnl            dnl A distinctive file to look for in srcdir.
 
-AM_INIT_AUTOMAKE(make, 3.76.1)
+AM_INIT_AUTOMAKE(make, 3.77)
 AM_CONFIG_HEADER(config.h)
 AC_CONFIG_SUBDIRS(glob)
 
@@ -15,10 +15,16 @@ AC_PROG_MAKE_SET
 AC_PROG_CC
 AC_PROG_INSTALL
 AC_PROG_CPP                    dnl Later checks need this.
-AC_ARG_PROGRAM
+dnl AC_ARG_PROGRAM -- implied by AM_INIT_AUTOMAKE; gives errors if run twice.
 AC_AIX
 AC_ISC_POSIX
 AC_MINIX
+
+dnl This test must come as early as possible after the compiler configuration
+dnl tests, because the choice of the file model can (in principle) affect
+dnl whether functions and headers are available, whether they work, etc.
+AC_LFS
+
 AC_HEADER_STDC
 AC_HEADER_DIRENT
 AC_TYPE_UID_T                  dnl Also does gid_t.
@@ -91,8 +97,25 @@ AC_DECL_SYS_SIGLIST
 AC_CHECK_LIB(sun, getpwnam)
 
 AC_SUBST(REMOTE) REMOTE=stub
-AC_ARG_WITH(customs, [export jobs with the Customs daemon (NOT SUPPORTED)],
-[REMOTE=cstms LIBS="$LIBS libcustoms.a"])
+make_try_customs=no
+AC_ARG_WITH(customs,
+[  --with-customs=DIR      Enable remote jobs via Customs--see README.customs],
+[case "$withval" in
+  n|no) ;;
+  *) make_cppflags="$CPPFLAGS"
+     case "$withval" in
+       y|ye|yes) ;;
+       *) CPPFLAGS="$CPPFLAGS -I$with_customs/include/customs"
+         make_ldflags="$LDFLAGS -L$with_customs/lib" ;;
+     esac
+     CF_NETLIBS
+     AC_CHECK_HEADER(customs.h,
+                    REMOTE=cstms
+                       LIBS="$LIBS -lcustoms" LDFLAGS="$make_ldflags",
+                    with_customs=no
+                       CPPFLAGS="$make_cppflags" make_badcust=yes)
+     ;;
+esac])
 
 echo checking for location of SCCS get command
 if test -f /usr/sccs/get; then
@@ -116,6 +139,26 @@ rm -f s.conftest conftoast
 
 AC_OUTPUT(Makefile build.sh)
 
+case "$make_badcust" in
+  yes) echo
+       echo "WARNING: --with-customs specified but no customs.h could be found;"
+       echo "         disabling Customs support."
+       echo ;;
+esac
+
+case "$with_customs" in
+  ""|n|no|y|ye|yes) ;;
+  *) if test -f "$with_customs/lib/libcustoms.a"; then
+       :
+     else
+       echo
+       echo "WARNING: \`$with_customs/lib' does not appear to contain the"
+       echo "         Customs library.  You must build and install Customs"
+       echo "         before compiling GNU make."
+       echo
+     fi ;;
+esac
+
 dnl Local Variables:
 dnl comment-start: "dnl "
 dnl comment-end: ""
index 5f5d2b5..653bc81 100644 (file)
--- a/default.c
+++ b/default.c
@@ -41,7 +41,7 @@ static char default_suffixes[]
 .mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo \
 .w .ch .cweb .web .com .sh .elc .el";
 #else
-  = ".out .a .ln .o .c .cc .C .p .f .F .r .y .l .s .S \
+  = ".out .a .ln .o .c .cc .C .cpp .p .f .F .r .y .l .s .S \
 .mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo \
 .w .ch .web .sh .elc .el";
 #endif
@@ -91,6 +91,8 @@ static struct pspec default_terminal_rules[] =
        "$(CHECKOUT,v)" },
     { "%", "RCS/%,v",
        "$(CHECKOUT,v)" },
+    { "%", "RCS/%",
+       "$(CHECKOUT,v)" },
 
     /* SCCS.  */
     { "%", "s.%",
@@ -156,6 +158,8 @@ static char *default_suffix_rules[] =
     "$(LINK.cc) $^ $(LOADLIBES) $(LDLIBS) -o $@",
     ".C",
     "$(LINK.C) $^ $(LOADLIBES) $(LDLIBS) -o $@",
+    ".cpp",
+    "$(LINK.cpp) $^ $(LOADLIBES) $(LDLIBS) -o $@",
     ".f",
     "$(LINK.f) $^ $(LOADLIBES) $(LDLIBS) -o $@",
     ".p",
@@ -183,6 +187,8 @@ static char *default_suffix_rules[] =
     "$(COMPILE.cc) $< $(OUTPUT_OPTION)",
     ".C.o",
     "$(COMPILE.C) $< $(OUTPUT_OPTION)",
+    ".cpp.o",
+    "$(COMPILE.cpp) $< $(OUTPUT_OPTION)",
     ".f.o",
     "$(COMPILE.f) $< $(OUTPUT_OPTION)",
     ".p.o",
@@ -386,8 +392,10 @@ static char *default_variables[] =
     "LINK.c", "$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)",
     "COMPILE.cc", "$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c",
     "COMPILE.C", "$(COMPILE.cc)",
+    "COMPILE.cpp", "$(COMPILE.cc)",
     "LINK.cc", "$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)",
     "LINK.C", "$(LINK.cc)",
+    "LINK.cpp", "$(LINK.cc)",
     "YACC.y", "$(YACC) $(YFLAGS)",
     "LEX.l", "$(LEX) $(LFLAGS) -t",
     "COMPILE.f", "$(FC) $(FFLAGS) $(TARGET_ARCH) -c",
diff --git a/dir.c b/dir.c
index d187c03..9e1cf7a 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -111,19 +111,25 @@ dosify (filename)
 
 #ifdef _AMIGA
 #include <ctype.h>
+#endif
 
+#ifdef HAVE_CASE_INSENSITIVE_FS
 static char *
-amigafy (filename)
+downcase (filename)
      char *filename;
 {
-  static char amiga_filename[136];
+#ifdef _AMIGA
+  static char new_filename[136];
+#else
+  static char new_filename[PATH_MAX];
+#endif
   char *df;
   int i;
 
   if (filename == 0)
     return 0;
 
-  df = amiga_filename;
+  df = new_filename;
 
   /* First, transform the name part.  */
   for (i = 0; *filename != '\0'; ++i)
@@ -134,9 +140,9 @@ amigafy (filename)
 
   *df = 0;
 
-  return amiga_filename;
+  return new_filename;
 }
-#endif /* _AMIGA */
+#endif /* HAVE_CASE_INSENSITIVE_FS */
 
 #ifdef VMS
 
@@ -355,7 +361,7 @@ find_directory (name)
 
          for (dc = directories_contents[hash]; dc != 0; dc = dc->next)
 #ifdef WINDOWS32
-            if (!strcmp(dc->path_key, w32_path))
+            if (strieq(dc->path_key, w32_path))
 #else
            if (dc->dev == st.st_dev
 #ifdef VMS
@@ -468,8 +474,8 @@ dir_contents_file_exists_p (dir, filename)
   filename = dosify (filename);
 #endif
 
-#ifdef _AMIGA
-  filename = amigafy (filename);
+#ifdef HAVE_CASE_INSENSITIVE_FS
+  filename = downcase (filename);
 #endif
 
 #ifdef VMS
@@ -613,6 +619,7 @@ file_exists_p (name)
 {
   char *dirend;
   char *dirname;
+  char *slash;
 
 #ifndef        NO_ARCHIVES
   if (ar_name (name))
@@ -632,8 +639,9 @@ file_exists_p (name)
     char *bslash = rindex(name, '\\');
     if (!dirend || bslash > dirend)
       dirend = bslash;
-    /* The case of "d:file" is unhandled.  But I don't think
-       such names can happen here.  */
+    /* The case of "d:file".  */
+    if (!dirend && name[0] && name[1] == ':')
+      dirend = name + 1;
   }
 #endif /* WINDOWS32 || __MSDOS__ */
   if (dirend == 0)
@@ -644,15 +652,22 @@ file_exists_p (name)
 #endif /* AMIGA */
 #endif /* VMS */
 
+  slash = dirend;
   if (dirend == name)
     dirname = "/";
   else
     {
+#if defined (WINDOWS32) || defined (__MSDOS__)
+  /* d:/ and d: are *very* different...  */
+      if (dirend < name + 3 && name[1] == ':' &&
+         (*dirend == '/' || *dirend == '\\' || *dirend == ':'))
+       dirend++;
+#endif
       dirname = (char *) alloca (dirend - name + 1);
       bcopy (name, dirname, dirend - name);
       dirname[dirend - name] = '\0';
     }
-  return dir_file_exists_p (dirname, dirend + 1);
+  return dir_file_exists_p (dirname, slash + 1);
 }
 \f
 /* Mark FILENAME as `impossible' for `file_impossible_p'.
@@ -682,8 +697,9 @@ file_impossible (filename)
     char *bslash = rindex(p, '\\');
     if (!dirend || bslash > dirend)
       dirend = bslash;
-    /* The case of "d:file" is unhandled.  But I don't think
-       such names can happen here.  */
+    /* The case of "d:file".  */
+    if (!dirend && p[0] && p[1] == ':')
+      dirend = p + 1;
   }
 #endif /* WINDOWS32 or __MSDOS__ */
   if (dirend == 0)
@@ -696,16 +712,23 @@ file_impossible (filename)
   else
     {
       char *dirname;
+      char *slash = dirend;
       if (dirend == p)
        dirname = "/";
       else
        {
+#if defined (WINDOWS32) || defined (__MSDOS__)
+         /* d:/ and d: are *very* different...  */
+         if (dirend < p + 3 && p[1] == ':' &&
+             (*dirend == '/' || *dirend == '\\' || *dirend == ':'))
+           dirend++;
+#endif
          dirname = (char *) alloca (dirend - p + 1);
          bcopy (p, dirname, dirend - p);
          dirname[dirend - p] = '\0';
        }
       dir = find_directory (dirname);
-      filename = p = dirend + 1;
+      filename = p = slash + 1;
     }
 
   for (hash = 0; *p != '\0'; ++p)
@@ -776,8 +799,9 @@ file_impossible_p (filename)
     char *bslash = rindex(filename, '\\');
     if (!dirend || bslash > dirend)
       dirend = bslash;
-    /* The case of "d:file" is unhandled.  But I don't think
-       such names can happen here.  */
+    /* The case of "d:file".  */
+    if (!dirend && filename[0] && filename[1] == ':')
+      dirend = filename + 1;
   }
 #endif /* WINDOWS32 || __MSDOS__ */
   if (dirend == 0)
@@ -790,16 +814,23 @@ file_impossible_p (filename)
   else
     {
       char *dirname;
+      char *slash = dirend;
       if (dirend == filename)
        dirname = "/";
       else
        {
+#if defined (WINDOWS32) || defined (__MSDOS__)
+         /* d:/ and d: are *very* different...  */
+         if (dirend < filename + 3 && filename[1] == ':' &&
+             (*dirend == '/' || *dirend == '\\' || *dirend == ':'))
+           dirend++;
+#endif
          dirname = (char *) alloca (dirend - filename + 1);
          bcopy (p, dirname, dirend - p);
          dirname[dirend - p] = '\0';
        }
       dir = find_directory (dirname)->contents;
-      p = filename = dirend + 1;
+      p = filename = slash + 1;
     }
 
   if (dir == 0 || dir->files == 0)
@@ -809,8 +840,8 @@ file_impossible_p (filename)
 #ifdef __MSDOS__
   p = filename = dosify (p);
 #endif
-#ifdef _AMIGA
-  p = filename = amigafy (p);
+#ifdef HAVE_CASE_INSENSITIVE_FS
+  p = filename = downcase (p);
 #endif
 #ifdef VMS
   p = filename = vmsify (p, 1);
@@ -891,8 +922,9 @@ print_dir_data_base ()
                        dir->contents->ino[0], dir->contents->ino[1],
                        dir->contents->ino[2]);
 #else
-           printf ("# %s (device %d, inode %d): ",
-                   dir->name, dir->contents->dev, dir->contents->ino);
+           printf ("# %s (device %ld, inode %ld): ",
+                   dir->name,
+                    (long)dir->contents->dev, (long)dir->contents->ino);
 #endif
 #endif /* WINDOWS32 */
            if (f == 0)
@@ -1016,6 +1048,14 @@ read_dirstream (stream)
   return 0;
 }
 
+static void
+ansi_free(p)
+  void *p;
+{
+    if (p)
+      free(p);
+}
+
 void
 dir_setup_glob (gl)
      glob_t *gl;
@@ -1025,7 +1065,7 @@ dir_setup_glob (gl)
   /* Bogus sunos4 compiler complains (!) about & before functions.  */
   gl->gl_opendir = open_dirstream;
   gl->gl_readdir = read_dirstream;
-  gl->gl_closedir = free;
+  gl->gl_closedir = ansi_free;
   gl->gl_stat = stat;
   /* We don't bother setting gl_lstat, since glob never calls it.
      The slot is only there for compatibility with 4.4 BSD.  */
index 8ba6850..ac1e6cd 100644 (file)
@@ -7,8 +7,8 @@ gcc  -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g dir.c -o dir.o
 gcc  -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g file.c -o file.o\r
 gcc  -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g misc.c -o misc.o\r
 gcc  -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g main.c -o main.o\r
-gcc  -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g read.c -o read.o\r
-gcc  -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g remake.c -o remake.o\r
+gcc  -c -I. -I./glob -DHAVE_CONFIG_H -DINCLUDEDIR=\"c:/djgpp/include\" -O2 -g read.c -o read.o\r
+gcc  -c -I. -I./glob -DHAVE_CONFIG_H -DLIBDIR=\"c:/djgpp/lib\" -O2 -g remake.c -o remake.o\r
 gcc  -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g rule.c -o rule.o\r
 gcc  -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g implicit.c -o implicit.o\r
 gcc  -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g default.c -o default.o\r
index 5f46ac2..3f4bcfc 100644 (file)
--- a/expand.c
+++ b/expand.c
@@ -21,15 +21,24 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "job.h"
 #include "commands.h"
 #include "variable.h"
+#include "rule.h"
 
 /* The next two describe the variable output buffer.
    This buffer is used to hold the variable-expansion of a line of the
    makefile.  It is made bigger with realloc whenever it is too small.
    variable_buffer_length is the size currently allocated.
-   variable_buffer is the address of the buffer.  */
+   variable_buffer is the address of the buffer.
+
+   For efficiency, it's guaranteed that the buffer will always have
+   VARIABLE_BUFFER_ZONE extra bytes allocated.  This allows you to add a few
+   extra chars without having to call a function.  Note you should never use
+   these bytes unless you're _sure_ you have room (you know when the buffer
+   length was last checked.  */
+
+#define VARIABLE_BUFFER_ZONE    5
 
 static unsigned int variable_buffer_length;
-static char *variable_buffer;
+char *variable_buffer;
 
 /* Subroutine of variable_expand and friends:
    The text to add is LENGTH chars starting at STRING to the variable_buffer.
@@ -45,7 +54,7 @@ variable_buffer_output (ptr, string, length)
 {
   register unsigned int newlen = length + (ptr - variable_buffer);
 
-  if (newlen > variable_buffer_length)
+  if ((newlen + VARIABLE_BUFFER_ZONE) > variable_buffer_length)
     {
       unsigned int offset = ptr - variable_buffer;
       variable_buffer_length = (newlen + 100 > 2 * variable_buffer_length
@@ -93,7 +102,7 @@ recursively_expand (v)
               v->name);
       else
        makefile_fatal
-         (reading_filename, *reading_lineno_ptr, 
+         (reading_filename, *reading_lineno_ptr,
           "Recursive variable `%s' references itself (eventually)",
           v->name);
     }
@@ -153,20 +162,38 @@ reference_variable (o, name, length)
   return o;
 }
 \f
-/* Scan LINE for variable references and expansion-function calls.
-   Build in `variable_buffer' the result of expanding the references and calls.
-   Return the address of the resulting string, which is null-terminated
-   and is valid only until the next time this function is called.  */
+/* Scan STRING for variable references and expansion-function calls.  Only
+   LENGTH bytes of STRING are actually scanned.  If LENGTH is -1, scan until
+   a null byte is found.
+
+   Write the results to LINE, which must point into `variable_buffer'.  If
+   LINE is NULL, start at the beginning of the buffer.
+   Return a pointer to LINE, or to the beginning of the buffer if LINE is
+   NULL.  */
 
 char *
-variable_expand (line)
+variable_expand_string (line, string, length)
      register char *line;
+     char *string;
+     long length;
 {
   register struct variable *v;
   register char *p, *o, *p1;
+  char save_char = '\0';
+  unsigned int line_offset;
 
-  p = line;
-  o = initialize_variable_output ();
+  if (!line)
+    line = initialize_variable_output();
+
+  p = string;
+  o = line;
+  line_offset = line - variable_buffer;
+
+  if (length >= 0)
+    {
+      save_char = string[length];
+      string[length] = '\0';
+    }
 
   while (1)
     {
@@ -316,7 +343,7 @@ variable_expand (line)
                                       replace_end - replace_beg);
                                replace[replace_end - replace_beg] = '\0';
                              }
-                           
+
                            o = patsubst_expand (o, value, pattern, replace,
                                                 percent, (char *) 0);
                          }
@@ -366,7 +393,7 @@ variable_expand (line)
          }
 
          break;
-       }      
+       }
 
       if (*p == '\0')
        break;
@@ -374,8 +401,23 @@ variable_expand (line)
        ++p;
     }
 
-  (void) variable_buffer_output (o, "", 1);
-  return initialize_variable_output ();
+  if (save_char)
+    string[length] = save_char;
+
+  (void)variable_buffer_output (o, "", 1);
+  return (variable_buffer + line_offset);
+}
+\f
+/* Scan LINE for variable references and expansion-function calls.
+   Build in `variable_buffer' the result of expanding the references and calls.
+   Return the address of the resulting string, which is null-terminated
+   and is valid only until the next time this function is called.  */
+
+char *
+variable_expand (line)
+     char *line;
+{
+  return variable_expand_string(NULL, line, -1);
 }
 \f
 /* Expand an argument for an expansion function.
@@ -405,13 +447,13 @@ expand_argument (str, end)
 /* Expand LINE for FILE.  Error messages refer to the file and line where
    FILE's commands were found.  Expansion uses FILE's variable set list.  */
 
-char *
+static char *
 variable_expand_for_file (line, file)
      char *line;
      register struct file *file;
 {
   char *result;
-  struct variable_set_list *save;
+  struct variable_set_list *save, *fnext;
 
   if (file == 0)
     return variable_expand (line);
@@ -420,10 +462,23 @@ variable_expand_for_file (line, file)
   current_variable_set_list = file->variables;
   reading_filename = file->cmds->filename;
   reading_lineno_ptr = &file->cmds->lineno;
+  fnext = file->variables->next;
+  /* See if there's a pattern-specific variable struct for this target.  */
+  if (!file->pat_searched)
+    {
+      file->patvar = lookup_pattern_var(file->name);
+      file->pat_searched = 1;
+    }
+  if (file->patvar != 0)
+    {
+      file->patvar->vars->next = fnext;
+      file->variables->next = file->patvar->vars;
+    }
   result = variable_expand (line);
   current_variable_set_list = save;
   reading_filename = 0;
   reading_lineno_ptr = 0;
+  file->variables->next = fnext;
 
   return result;
 }
diff --git a/file.c b/file.c
index e4ea0bd..a60e70f 100644 (file)
--- a/file.c
+++ b/file.c
@@ -49,6 +49,9 @@ lookup_file (name)
   register struct file *f;
   register char *n;
   register unsigned int hashval;
+#ifdef VMS
+  register char *lname, *ln;
+#endif
 
   if (*name == '\0')
     abort ();
@@ -57,6 +60,12 @@ lookup_file (name)
      for names read from makefiles.  It is here for names passed
      on the command line.  */
 #ifdef VMS
+  lname = (char *)malloc(strlen(name) + 1);
+  for (n=name, ln=lname; *n != '\0'; ++n, ++ln)
+    *ln = isupper(*n) ? tolower(*n) : *n;
+  *ln = '\0';
+  name = lname;
+
   while (name[0] == '[' && name[1] == ']' && name[2] != '\0')
       name += 2;
 #endif
@@ -89,9 +98,15 @@ lookup_file (name)
     {
       if (strieq (f->hname, name))
        {
+#ifdef VMS
+         free (lname);
+#endif
          return f;
        }
     }
+#ifdef VMS
+  free (lname);
+#endif
   return 0;
 }
 
@@ -374,9 +389,9 @@ remove_intermediates (sig)
          if (f->update_status == -1)
            /* If nothing would have created this file yet,
               don't print an "rm" command for it.  */
-           continue;
-         else if (just_print_flag)
-           status = 0;
+            continue;
+         else if (just_print_flag)
+           status = 0;
          else
            {
              status = unlink (f->name);
@@ -660,8 +675,8 @@ print_file_data_base ()
     {
       printf ("\n# %u files in %u hash buckets.\n", nfiles, FILE_BUCKETS);
 #ifndef        NO_FLOAT
-      printf ("# average %.1f files per bucket, max %u files in one bucket.\n",
-             ((double) nfiles) / ((double) FILE_BUCKETS) * 100.0, per_bucket);
+      printf ("# average %.3f files per bucket, max %u files in one bucket.\n",
+             ((double) nfiles) / ((double) FILE_BUCKETS), per_bucket);
 #endif
     }
 }
index b1e6d31..a5de0a1 100644 (file)
--- a/filedef.h
+++ b/filedef.h
@@ -52,6 +52,10 @@ struct file
        the same file.  Otherwise this is null.  */
     struct file *double_colon;
 
+    /* Pattern-specific variable reference for this target, or null if there
+       isn't one.  Also see the pat_searched flag, below.  */
+    struct pattern_var *patvar;
+
     short int update_status;   /* Status of the last attempt to update,
                                   or -1 if none has been made.  */
 
@@ -79,7 +83,10 @@ struct file
     unsigned int secondary:1;
     unsigned int dontcare:1;   /* Nonzero if no complaint is to be made if
                                   this target cannot be remade.  */
+    unsigned int shownerror:1;  /* Nonzero if we printed an error */
     unsigned int ignore_vpath:1;/* Nonzero if we threw out VPATH name */
+    unsigned int pat_searched:1;/* Nonzero if we already searched for
+                                   pattern-specific variables */
   };
 
 /* Number of intermediate files entered.  */
index e115522..198ab44 100644 (file)
@@ -119,7 +119,7 @@ patsubst_expand (o, text, pattern, replace, pattern_percent, replace_percent)
      register char *pattern_percent, *replace_percent;
 {
   unsigned int pattern_prepercent_len, pattern_postpercent_len;
-  unsigned int replace_prepercent_len, replace_postpercent_len;
+  unsigned int replace_prepercent_len, replace_postpercent_len = 0;
   char *t;
   unsigned int len;
   int doneany = 0;
@@ -282,13 +282,13 @@ static struct
     { 0, 0, function_invalid }
   };
 \f
-/* Return 1 if PATTERN matches WORD, 0 if not.  */
+/* Return 1 if PATTERN matches STR, 0 if not.  */
 
 int
-pattern_matches (pattern, percent, word)
-     register char *pattern, *percent, *word;
+pattern_matches (pattern, percent, str)
+     register char *pattern, *percent, *str;
 {
-  unsigned int sfxlen, wordlen;
+  unsigned int sfxlen, strlength;
 
   if (percent == 0)
     {
@@ -298,17 +298,17 @@ pattern_matches (pattern, percent, word)
       pattern = new;
       percent = find_percent (pattern);
       if (percent == 0)
-       return streq (pattern, word);
+       return streq (pattern, str);
     }
 
   sfxlen = strlen (percent + 1);
-  wordlen = strlen (word);
+  strlength = strlen (str);
 
-  if (wordlen < (percent - pattern) + sfxlen
-      || strncmp (pattern, word, percent - pattern))
+  if (strlength < (percent - pattern) + sfxlen
+      || strncmp (pattern, str, percent - pattern))
     return 0;
 
-  return !strcmp (percent + 1, word + (wordlen - sfxlen));
+  return !strcmp (percent + 1, str + (strlength - sfxlen));
 }
 \f
 int shell_function_pid = 0, shell_function_completed;
@@ -318,13 +318,13 @@ int shell_function_pid = 0, shell_function_completed;
    The output is written into VARIABLE_BUFFER starting at O.  */
 
 /* Note this absorbs a semicolon and is safe to use in conditionals.  */
-#define BADARGS(func)                                                         \
+#define BADARGS(func)  do {                                                   \
   if (reading_filename != 0)                                                  \
     makefile_fatal (reading_filename, *reading_lineno_ptr,                    \
                    "insufficient arguments to function `%s'",                \
                    func);                                                    \
   else                                                                        \
-    fatal ("insufficient arguments to function `%s'", func)
+    fatal ("insufficient arguments to function `%s'", func); } while (0)
 
 static char *
 expand_function (o, function, text, end)
@@ -348,6 +348,7 @@ expand_function (o, function, text, end)
 #ifndef VMS /* not supported for vms yet */
     case function_shell:
       {
+       char* batch_filename = NULL;
 #ifdef WINDOWS32
        SECURITY_ATTRIBUTES saAttr;
        HANDLE hIn;
@@ -373,7 +374,7 @@ expand_function (o, function, text, end)
 #ifndef __MSDOS__
        /* Construct the argument list.  */
        argv = construct_command_argv (text,
-                                      (char **) NULL, (struct file *) 0);
+                                      (char **) NULL, (struct file *) 0, &batch_filename);
        if (argv == 0)
          break;
 #endif
@@ -584,6 +585,12 @@ expand_function (o, function, text, end)
            while (shell_function_completed == 0)
              reap_children (1, 0);
 
+            if (batch_filename) {
+              if (debug_flag)
+                printf("Cleaning up temporary batch file %s\n", batch_filename);
+              remove(batch_filename);
+              free(batch_filename);
+            }
            shell_function_pid = 0;
 
            /* The child_handler function will set shell_function_completed
@@ -852,6 +859,8 @@ expand_function (o, function, text, end)
 
        push_new_variable_scope ();
        v = define_variable (var, strlen (var), "", o_automatic, 0);
+        free (v->value);
+        v->value = 0;
        p3 = list;
        while ((p = find_next_token (&p3, &len)) != 0)
          {
@@ -882,10 +891,10 @@ expand_function (o, function, text, end)
     case function_filter:
     case function_filter_out:
       {
-       struct word
+       struct a_word
          {
-           struct word *next;
-           char *word;
+           struct a_word *next;
+           char *str;
            int matched;
          } *words, *wordtail, *wp;
 
@@ -911,7 +920,7 @@ expand_function (o, function, text, end)
        p3 = text;
        while ((p = find_next_token (&p3, &len)) != 0)
          {
-           struct word *w = (struct word *) alloca (sizeof (struct word));
+           struct a_word *w = (struct a_word *)alloca(sizeof(struct a_word));
            if (words == 0)
              words = w;
            else
@@ -921,7 +930,7 @@ expand_function (o, function, text, end)
            if (*p3 != '\0')
              ++p3;
            p[len] = '\0';
-           w->word = p;
+           w->str = p;
            w->matched = 0;
          }
 
@@ -939,8 +948,8 @@ expand_function (o, function, text, end)
 
                percent = find_percent (p);
                for (wp = words; wp != 0; wp = wp->next)
-                 wp->matched |= (percent == 0 ? streq (p, wp->word)
-                                 : pattern_matches (p, percent, wp->word));
+                 wp->matched |= (percent == 0 ? streq (p, wp->str)
+                                 : pattern_matches (p, percent, wp->str));
 
                p[len] = save;
              }
@@ -949,7 +958,7 @@ expand_function (o, function, text, end)
            for (wp = words; wp != 0; wp = wp->next)
              if (function == function_filter ? wp->matched : !wp->matched)
                {
-                 o = variable_buffer_output (o, wp->word, strlen (wp->word));
+                 o = variable_buffer_output (o, wp->str, strlen (wp->str));
                  o = variable_buffer_output (o, " ", 1);
                  doneany = 1;
                }
index adc4bef..154f18d 100644 (file)
@@ -35,6 +35,7 @@
    LOAD_AVE_TYPE               Type of the load average array in the kernel.
                                Must be defined unless one of
                                apollo, DGUX, NeXT, or UMAX is defined;
+                                or we have libkstat;
                                otherwise, no load average is available.
    NLIST_STRUCT                        Include nlist.h, not a.out.h, and
                                the nlist n_name element is a pointer,
@@ -500,6 +501,7 @@ extern int errno;
 #  include <sys/file.h>
 # endif
 \f
+
 /* Avoid static vars inside a function since in HPUX they dump as pure.  */
 
 # ifdef NeXT
@@ -516,7 +518,7 @@ static unsigned int samples;
 static struct dg_sys_info_load_info load_info; /* what-a-mouthful! */
 # endif /* DGUX */
 
-# ifdef LOAD_AVE_TYPE
+#if !defined(HAVE_LIBKSTAT) && defined(LOAD_AVE_TYPE)
 /* File descriptor open to /dev/kmem or VMS load ave driver.  */
 static int channel;
 /* Nonzero iff channel is valid.  */
@@ -524,15 +526,15 @@ static int getloadavg_initialized;
 /* Offset in kmem to seek to read load average, or 0 means invalid.  */
 static long offset;
 
-#  if !defined(VMS) && !defined(sgi) && !defined(__linux__)
+#if !defined(VMS) && !defined(sgi) && !defined(__linux__)
 static struct nlist nl[2];
-#  endif /* Not VMS or sgi */
+#endif
 
-#  ifdef SUNOS_5
+#ifdef SUNOS_5
 static kvm_t *kd;
-#  endif /* SUNOS_5 */
+#endif /* SUNOS_5 */
 
-# endif /* LOAD_AVE_TYPE */
+# endif /* LOAD_AVE_TYPE && !HAVE_LIBKSTAT */
 \f
 /* Put the 1 minute, 5 minute and 15 minute load averages
    into the first NELEM elements of LOADAVG.
index 92c5e7c..e3854a5 100644 (file)
@@ -1,3 +1,51 @@
+1998-07-29  Paul D. Smith  <psmith@gnu.org>
+
+       * glob.c, fnmatch.c: New versions from the GLIBC folks (Ulrich
+       Drepper).  Fixes a bug reported by Eli Zaretski.  Integrates
+       DOS/Windows32 support.
+
+1998-07-27  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
+
+       * glob.c (glob): Cast away const on assignment of pattern to dirname.
+       Cast the return type of __alloca() for traditional C compilers.
+
+1998-07-23  Paul D. Smith  <psmith@gnu.org>
+
+       * glob.c, fnmatch.c: New versions of these files from the GLIBC
+       folks (Ulrich Drepper).  Had to re-integrate some DOS/Windows
+       code.
+
+1998-07-10  Paul D. Smith  <psmith@gnu.org>
+
+       * glob.c (glob_in_dir): If no meta chars exist in PATTERN and
+       GLOB_NOCHECK is present, don't look for the file--whether it's
+       found or not, we'll always return it, so why bother searching?
+
+       Also, if we are searching and there are no meta chars, don't
+       bother trying fnmatch() if the strcmp() fails.
+
+1998-05-30  Eli Zaretskii  <eliz@is.elta.co.il>
+
+       * glob.c (glob) [__MSDOS__, WINDOWS32]: Compute the directory and
+       filename parts of the pattern correctly when it includes a drive
+       spec.  Disallow wildcards in the drive spec.  Prevent recursion
+       when dirname is of the form "d:/" or "d:".
+       (prefix_array) [__MSDOS__, WINDOWS32]: Don't append a slash to
+       "d:/" and "d:".
+
+1998-05-13  Paul D. Smith  <psmith@gnu.org>
+
+       * SMakefile, Makefile.ami, glob.c, glob.h, fnmatch.c: Updated from
+       the latest glibc version.
+
+1998-04-17  Paul D. Smith  <psmith@gnu.org>
+
+       * configure.in: Create a config.h file instead of setting things
+       on the compile line.  This is because when build.sh runs it merely
+       passes -DHAVE_CONFIG_H to the glob files, just as it does to the
+       make files.
+       * config.h.in: Created by autoheader.
+
 Tue Aug 12 10:52:34 1997  Paul D. Smith  <psmith@baynetworks.com>
 
        * configure.in: Require autoconf 2.12.
index 3c4ab7a..964ac19 100644 (file)
@@ -1,6 +1,6 @@
 # -*-Makefile-*-, or close enough
 
-AUTOMAKE_OPTIONS =     1.2 foreign
+AUTOMAKE_OPTIONS =     1.3 foreign
 
 noinst_LIBRARIES =     libglob.a
 
index 3666d3e..d3e3d40 100644 (file)
@@ -1,6 +1,6 @@
 # Makefile for standalone distribution of libglob.a (fnmatch, glob).
 
-# Copyright (C) 1991, 92, 93, 94, 95 Free Software Foundation, Inc.
+# Copyright (C) 1991, 92, 93, 94, 95, 97, 98 Free Software Foundation, Inc.
 # This file is part of the GNU C Library.
 
 # This library is free software; you can redistribute it and/or
@@ -15,8 +15,8 @@
 
 # You should have received a copy of the GNU Library General Public
 # License along with this library; see the file COPYING.LIB.  If
-# not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-# Cambridge, MA 02139, USA.
+# not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 # Ultrix 2.2 make doesn't expand the value of VPATH.
 VPATH = /glob/
index 1c82e0a..9dcb90b 100644 (file)
@@ -1,6 +1,6 @@
 # Makefile for standalone distribution of libglob.a (fnmatch, glob).
 
-# Copyright (C) 1991, 92, 93, 94, 95 Free Software Foundation, Inc.
+# Copyright (C) 1991, 92, 93, 94, 95, 97, 98 Free Software Foundation, Inc.
 # This file is part of the GNU C Library.
 
 # This library is free software; you can redistribute it and/or
@@ -15,8 +15,8 @@
 
 # You should have received a copy of the GNU Library General Public
 # License along with this library; see the file COPYING.LIB.  If
-# not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-# Cambridge, MA 02139, USA.
+# not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 # Ultrix 2.2 make doesn't expand the value of VPATH.
 VPATH = /glob/
index cf0a408..e948bc1 100644 (file)
@@ -3,6 +3,7 @@ AC_INIT(fnmatch.c)              dnl A distinctive file to look for in srcdir.
 AC_PREREQ(2.12)                        dnl Minimum Autoconf version required.
 
 AM_INIT_AUTOMAKE(glob, 0.0, nodefs)
+AM_CONFIG_HEADER(config.h)
 
 AC_PROG_CC
 AC_CHECK_PROG(AR, ar, ar, ar)
index e143743..2d6f6af 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1992, 1993, 1996, 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 92, 93, 96, 97, 98 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    This library is free software; you can redistribute it and/or
 #include <fnmatch.h>
 #include <ctype.h>
 
+#if HAVE_STRING_H
+# include <string.h>
+#else
+# include <strings.h>
+#endif
+
+#if defined STDC_HEADERS || defined _LIBC
+# include <stdlib.h>
+#endif
+
+/* For platform which support the ISO C amendement 1 functionality we
+   support user defined character classes.  */
+#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>.  */
+# include <wchar.h>
+# include <wctype.h>
+#endif
 
 /* Comment out all this code if we are using the GNU C Library, and are not
    actually compiling the library itself.  This code is part of the GNU C
 #  define ISASCII(c) isascii(c)
 # endif
 
-# define ISUPPER(c) (ISASCII (c) && isupper (c))
+#ifdef isblank
+# define ISBLANK(c) (ISASCII (c) && isblank (c))
+#else
+# define ISBLANK(c) ((c) == ' ' || (c) == '\t')
+#endif
+#ifdef isgraph
+# define ISGRAPH(c) (ISASCII (c) && isgraph (c))
+#else
+# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
+#endif
+
+#define ISPRINT(c) (ISASCII (c) && isprint (c))
+#define ISDIGIT(c) (ISASCII (c) && isdigit (c))
+#define ISALNUM(c) (ISASCII (c) && isalnum (c))
+#define ISALPHA(c) (ISASCII (c) && isalpha (c))
+#define ISCNTRL(c) (ISASCII (c) && iscntrl (c))
+#define ISLOWER(c) (ISASCII (c) && islower (c))
+#define ISPUNCT(c) (ISASCII (c) && ispunct (c))
+#define ISSPACE(c) (ISASCII (c) && isspace (c))
+#define ISUPPER(c) (ISASCII (c) && isupper (c))
+#define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))
+
+# define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
+
+# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+/* The GNU C library provides support for user-defined character classes
+   and the functions from ISO C amendement 1.  */
+#  ifdef CHARCLASS_NAME_MAX
+#   define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
+#  else
+/* This shouldn't happen but some implementation might still have this
+   problem.  Use a reasonable default value.  */
+#   define CHAR_CLASS_MAX_LENGTH 256
+#  endif
+
+#  ifdef _LIBC
+#   define IS_CHAR_CLASS(string) __wctype (string)
+#  else
+#   define IS_CHAR_CLASS(string) wctype (string)
+#  endif
+# else
+#  define CHAR_CLASS_MAX_LENGTH  6 /* Namely, `xdigit'.  */
+
+#  define IS_CHAR_CLASS(string)                                                      \
+   (STREQ (string, "alpha") || STREQ (string, "upper")                       \
+    || STREQ (string, "lower") || STREQ (string, "digit")                    \
+    || STREQ (string, "alnum") || STREQ (string, "xdigit")                   \
+    || STREQ (string, "space") || STREQ (string, "print")                    \
+    || STREQ (string, "punct") || STREQ (string, "graph")                    \
+    || STREQ (string, "cntrl") || STREQ (string, "blank"))
+# endif
+
+/* Avoid depending on library functions or files
+   whose names are inconsistent.  */
 
+# if !defined _LIBC && !defined getenv
+extern char *getenv ();
+# endif
 
 # ifndef errno
 extern int errno;
@@ -66,7 +139,11 @@ fnmatch (pattern, string, flags)
   register char c;
 
 /* Note that this evaluates C many times.  */
-# define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
+# ifdef _LIBC
+#  define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
+# else
+#  define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
+# endif
 
   while ((c = *p++) != '\0')
     {
@@ -137,67 +214,124 @@ fnmatch (pattern, string, flags)
        case '[':
          {
            /* Nonzero if the sense of the character class is inverted.  */
+           static int posixly_correct;
            register int not;
+           char cold;
+
+           if (posixly_correct == 0)
+             posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
 
            if (*n == '\0')
              return FNM_NOMATCH;
 
-           if ((flags & FNM_PERIOD) && *n == '.' &&
+           if (*n == '.' && (flags & FNM_PERIOD) &&
                (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
              return FNM_NOMATCH;
 
-           not = (*p == '!' || *p == '^');
+           if (*n == '/' && (flags & FNM_FILE_NAME))
+             /* `/' cannot be matched.  */
+             return FNM_NOMATCH;
+
+           not = (*p == '!' || (posixly_correct < 0 && *p == '^'));
            if (not)
              ++p;
 
            c = *p++;
            for (;;)
              {
-               register char cstart = c, cend = c;
+               int fn = FOLD (*n);
 
                if (!(flags & FNM_NOESCAPE) && c == '\\')
                  {
                    if (*p == '\0')
                      return FNM_NOMATCH;
-                   cstart = cend = *p++;
+                   c = FOLD (*p++);
+
+                   if (c == fn)
+                     goto matched;
                  }
+               else if (c == '[' && *p == ':')
+                 {
+                   /* Leave room for the null.  */
+                   char str[CHAR_CLASS_MAX_LENGTH + 1];
+                   size_t c1 = 0;
+# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+                   wctype_t wt;
+# endif
 
-               cstart = cend = FOLD (cstart);
+                   for (;;)
+                     {
+                       if (c1 == CHAR_CLASS_MAX_LENGTH)
+                         /* The name is too long and therefore the pattern
+                            is ill-formed.  */
+                         return FNM_NOMATCH;
+
+                       c = *++p;
+                       if (c == ':' && p[1] == ']')
+                         {
+                           p += 2;
+                           break;
+                         }
+                       str[c1++] = 'c';
+                     }
+                   str[c1] = '\0';
+
+# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+                   wt = IS_CHAR_CLASS (str);
+                   if (wt == 0)
+                     /* Invalid character class name.  */
+                     return FNM_NOMATCH;
 
-               if (c == '\0')
+                   if (__iswctype (__btowc (*n), wt))
+                     goto matched;
+# else
+                   if ((STREQ (str, "alnum") && ISALNUM (*n))
+                       || (STREQ (str, "alpha") && ISALPHA (*n))
+                       || (STREQ (str, "blank") && ISBLANK (*n))
+                       || (STREQ (str, "cntrl") && ISCNTRL (*n))
+                       || (STREQ (str, "digit") && ISDIGIT (*n))
+                       || (STREQ (str, "graph") && ISGRAPH (*n))
+                       || (STREQ (str, "lower") && ISLOWER (*n))
+                       || (STREQ (str, "print") && ISPRINT (*n))
+                       || (STREQ (str, "punct") && ISPUNCT (*n))
+                       || (STREQ (str, "space") && ISSPACE (*n))
+                       || (STREQ (str, "upper") && ISUPPER (*n))
+                       || (STREQ (str, "xdigit") && ISXDIGIT (*n)))
+                     goto matched;
+# endif
+                 }
+               else if (c == '\0')
                  /* [ (unterminated) loses.  */
                  return FNM_NOMATCH;
+               else if (FOLD (c) == fn)
+                 goto matched;
 
+               cold = c;
                c = *p++;
-               c = FOLD (c);
-
-               if ((flags & FNM_FILE_NAME) && c == '/')
-                 /* [/] can never match.  */
-                 return FNM_NOMATCH;
 
                if (c == '-' && *p != ']')
                  {
-                   cend = *p++;
+                   /* It is a range.  */
+                   char cend = *p++;
                    if (!(flags & FNM_NOESCAPE) && cend == '\\')
                      cend = *p++;
                    if (cend == '\0')
                      return FNM_NOMATCH;
-                   cend = FOLD (cend);
+
+                   if (cold <= fn && fn <= FOLD (cend))
+                     goto matched;
 
                    c = *p++;
                  }
-
-               if (FOLD (*n) >= cstart && FOLD (*n) <= cend)
-                 goto matched;
-
                if (c == ']')
                  break;
              }
+
            if (!not)
              return FNM_NOMATCH;
            break;
 
-         matched:;
+         matched:
            /* Skip the rest of the [...] that already matched.  */
            while (c != ']')
              {
@@ -213,6 +347,15 @@ fnmatch (pattern, string, flags)
                    /* XXX 1003.2d11 is unclear if this is right.  */
                    ++p;
                  }
+               else if (c == '[' && *p == ':')
+                 {
+                   do
+                     if (*++p == '\0')
+                       return FNM_NOMATCH;
+                   while (*p != ':' || p[1] == ']');
+                   p += 2;
+                   c = *p;
+                 }
              }
            if (not)
              return FNM_NOMATCH;
index 38b7255..4d1eb3e 100644 (file)
 extern "C" {
 #endif
 
-#if (defined (__cplusplus) || (defined (__STDC__) && __STDC__) \
-     || defined (WINDOWS32))
-#undef __P
-#define        __P(protos)     protos
+#if defined __cplusplus || (defined __STDC__ && __STDC__) || defined WINDOWS32
+# undef        __P
+# define __P(protos)   protos
 #else /* Not C++ or ANSI C.  */
-#undef __P
-#define        __P(protos)     ()
+# undef        __P
+# define __P(protos)   ()
 /* We can get away without defining `const' here only because in this file
    it is used only inside the prototype for `fnmatch', which is elided in
    non-ANSI C where `const' is problematical.  */
 #endif /* C++ or ANSI C.  */
 
+#ifndef const
+# if (defined __STDC__ && __STDC__) || defined __cplusplus
+#  define __const      const
+# else
+#  define __const
+# endif
+#endif
 
 /* We #undef these before defining them because some losing systems
    (HP-UX A.08.07 for example) define these in <unistd.h>.  */
@@ -47,18 +53,26 @@ extern "C" {
 #define        FNM_NOESCAPE    (1 << 1) /* Backslashes don't quote special chars.  */
 #define        FNM_PERIOD      (1 << 2) /* Leading `.' is matched only explicitly.  */
 
-#if !defined (_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 2 || defined (_GNU_SOURCE)
-#define        FNM_FILE_NAME   FNM_PATHNAME /* Preferred GNU name.  */
-#define        FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match.  */
-#define        FNM_CASEFOLD    (1 << 4) /* Compare without regard to case.  */
+#if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _GNU_SOURCE
+# define FNM_FILE_NAME  FNM_PATHNAME   /* Preferred GNU name.  */
+# define FNM_LEADING_DIR (1 << 3)      /* Ignore `/...' after a match.  */
+# define FNM_CASEFOLD   (1 << 4)       /* Compare without regard to case.  */
 #endif
 
 /* Value returned by `fnmatch' if STRING does not match PATTERN.  */
 #define        FNM_NOMATCH     1
 
+/* This value is returned if the implementation does not support
+   `fnmatch'.  Since this is not the case here it will never be
+   returned but the conformance test suites still require the symbol
+   to be defined.  */
+#if (_XOPEN_SOURCE - 0) == 500
+# define FNM_NOSYS     (-1)
+#endif
+
 /* Match STRING against the filename pattern PATTERN,
    returning zero if it matches, FNM_NOMATCH if not.  */
-extern int fnmatch __P ((const char *__pattern, const char *__string,
+extern int fnmatch __P ((__const char *__pattern, __const char *__string,
                         int __flags));
 
 #ifdef __cplusplus
index 6a82fe0..eab7919 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc.
+/* Copyright (C) 1991,92,93,94,95,96,97,98 Free Software Foundation, Inc.
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public License as
    Boston, MA 02111-1307, USA.  */
 
 /* AIX requires this to be the first thing in the file.  */
-#if defined (_AIX) && !defined (__GNUC__)
+#if defined _AIX && !defined __GNUC__
  #pragma alloca
 #endif
 
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
 #endif
 
 /* Enable GNU extensions in glob.h.  */
 #ifndef _GNU_SOURCE
-#define        _GNU_SOURCE     1
+# define _GNU_SOURCE   1
 #endif
 
 #include <errno.h>
    it is simpler to just do this in the source for each such file.  */
 
 #define GLOB_INTERFACE_VERSION 1
-#if !defined (_LIBC) && defined (__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1
-#include <gnu-versions.h>
-#if _GNU_GLOB_INTERFACE_VERSION == GLOB_INTERFACE_VERSION
-#define ELIDE_CODE
-#endif
+#if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
+# include <gnu-versions.h>
+# if _GNU_GLOB_INTERFACE_VERSION == GLOB_INTERFACE_VERSION
+#  define ELIDE_CODE
+# endif
 #endif
 
 #ifndef ELIDE_CODE
 
-#if defined(STDC_HEADERS) || defined(__GNU_LIBRARY__)
-#include <stddef.h>
+#if defined STDC_HEADERS || defined __GNU_LIBRARY__
+# include <stddef.h>
 #endif
 
 #if defined HAVE_UNISTD_H || defined _LIBC
-#include <unistd.h>
-#ifndef POSIX
-#ifdef _POSIX_VERSION
-#define        POSIX
-#endif
-#endif
+# include <unistd.h>
+# ifndef POSIX
+#  ifdef _POSIX_VERSION
+#   define POSIX
+#  endif
+# endif
 #endif
 
-#if !defined (_AMIGA) && !defined (VMS) && !defined(WINDOWS32)
-#include <pwd.h>
+#if !defined _AMIGA && !defined VMS && !defined WINDOWS32
+# include <pwd.h>
 #endif
 
-#if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
+#if !defined __GNU_LIBRARY__ && !defined STDC_HEADERS
 extern int errno;
 #endif
 #ifndef __set_errno
-#define __set_errno(val) errno = (val)
+# define __set_errno(val) errno = (val)
 #endif
 
 #ifndef        NULL
-#define        NULL    0
+# define NULL  0
 #endif
 
 
-#if defined (HAVE_DIRENT_H) || defined (__GNU_LIBRARY__)
+#if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__
 # include <dirent.h>
 # define NAMLEN(dirent) strlen((dirent)->d_name)
 #else
@@ -110,36 +110,42 @@ extern int errno;
 
 /* In GNU systems, <dirent.h> defines this macro for us.  */
 #ifdef _D_NAMLEN
-#undef NAMLEN
-#define NAMLEN(d) _D_NAMLEN(d)
+# undef NAMLEN
+# define NAMLEN(d) _D_NAMLEN(d)
+#endif
+
+/* When used in the GNU libc the symbol _DIRENT_HAVE_D_TYPE is available
+   if the `d_type' member for `struct dirent' is available.  */
+#ifdef _DIRENT_HAVE_D_TYPE
+# define HAVE_D_TYPE   1
 #endif
 
 
-#if (defined (POSIX) || defined (WINDOWS32)) && !defined (__GNU_LIBRARY__)
+#if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
 /* Posix does not require that the d_ino field be present, and some
    systems do not provide it. */
-#define REAL_DIR_ENTRY(dp) 1
+# define REAL_DIR_ENTRY(dp) 1
 #else
-#define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
+# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
 #endif /* POSIX */
 
-#if    (defined (STDC_HEADERS) || defined (__GNU_LIBRARY__))
-#include <stdlib.h>
-#include <string.h>
-#define        ANSI_STRING
+#if defined STDC_HEADERS || defined __GNU_LIBRARY__
+# include <stdlib.h>
+# include <string.h>
+# define       ANSI_STRING
 #else  /* No standard headers.  */
 
 extern char *getenv ();
 
-#ifdef HAVE_STRING_H
-#include <string.h>
-#define        ANSI_STRING
-#else
-#include <strings.h>
-#endif
-#ifdef HAVE_MEMORY_H
-#include <memory.h>
-#endif
+# ifdef HAVE_STRING_H
+#  include <string.h>
+#  define ANSI_STRING
+# else
+#  include <strings.h>
+# endif
+# ifdef        HAVE_MEMORY_H
+#  include <memory.h>
+# endif
 
 extern char *malloc (), *realloc ();
 extern void free ();
@@ -151,35 +157,40 @@ extern void abort (), exit ();
 
 #ifndef        ANSI_STRING
 
-#ifndef        bzero
+# ifndef bzero
 extern void bzero ();
-#endif
-#ifndef        bcopy
+# endif
+# ifndef bcopy
 extern void bcopy ();
-#endif
+# endif
 
-#define        memcpy(d, s, n) bcopy ((s), (d), (n))
-#define        strrchr rindex
+# define memcpy(d, s, n)       bcopy ((s), (d), (n))
+# define strrchr       rindex
 /* memset is only used for zero here, but let's be paranoid.  */
-#define        memset(s, better_be_zero, n) \
+# define memset(s, better_be_zero, n) \
   ((void) ((better_be_zero) == 0 ? (bzero((s), (n)), 0) : (abort(), 0)))
 #endif /* Not ANSI_STRING.  */
 
 #if !defined HAVE_STRCOLL && !defined _LIBC
-#define        strcoll strcmp
+# define strcoll       strcmp
+#endif
+
+#if !defined HAVE_MEMPCPY && __GLIBC__ - 0 == 2 && __GLIBC_MINOR__ >= 1
+# define HAVE_MEMPCPY  1
+# define mempcpy(Dest, Src, Len) __mempcpy (Dest, Src, Len)
 #endif
 
 
 #ifndef        __GNU_LIBRARY__
-#ifdef __GNUC__
+# ifdef        __GNUC__
 __inline
-#endif
-#ifndef __SASC
-#ifdef WINDOWS32
+# endif
+# ifndef __SASC
+#  ifdef WINDOWS32
 static void *
-#else
+#  else
 static char *
-#endif
+# endif
 my_realloc (p, n)
      char *p;
      unsigned int n;
@@ -190,68 +201,85 @@ my_realloc (p, n)
     return (char *) malloc (n);
   return (char *) realloc (p, n);
 }
-#define        realloc my_realloc
-#endif /* __SASC */
+# define       realloc my_realloc
+# endif /* __SASC */
 #endif /* __GNU_LIBRARY__ */
 
 
-#if    !defined(__alloca) && !defined(__GNU_LIBRARY__)
+#if !defined __alloca && !defined __GNU_LIBRARY__
 
-#ifdef __GNUC__
-#undef alloca
-#define        alloca(n)       __builtin_alloca (n)
-#else  /* Not GCC.  */
-#ifdef HAVE_ALLOCA_H
-#include <alloca.h>
-#else  /* Not HAVE_ALLOCA_H.  */
-#ifndef        _AIX
-#ifdef WINDOWS32
-#include <malloc.h>
-#else
+# ifdef        __GNUC__
+#  undef alloca
+#  define alloca(n)    __builtin_alloca (n)
+# else /* Not GCC.  */
+#  ifdef HAVE_ALLOCA_H
+#   include <alloca.h>
+#  else        /* Not HAVE_ALLOCA_H.  */
+#   ifndef _AIX
+#    ifdef WINDOWS32
+#     include <malloc.h>
+#    else
 extern char *alloca ();
-#endif /* WINDOWS32 */
-#endif /* Not _AIX.  */
-#endif /* sparc or HAVE_ALLOCA_H.  */
-#endif /* GCC.  */
+#    endif /* WINDOWS32 */
+#   endif /* Not _AIX.  */
+#  endif /* sparc or HAVE_ALLOCA_H.  */
+# endif        /* GCC.  */
 
-#define        __alloca        alloca
+# define __alloca      alloca
 
 #endif
 
 #ifndef __GNU_LIBRARY__
-#define __stat stat
-#ifdef STAT_MACROS_BROKEN
-#undef S_ISDIR
-#endif
-#ifndef S_ISDIR
-#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
+# define __stat stat
+# ifdef STAT_MACROS_BROKEN
+#  undef S_ISDIR
+# endif
+# ifndef S_ISDIR
+#  define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
+# endif
 #endif
+
+#ifdef _LIBC
+# define strdup(str) __strdup (str)
+# define sysconf(id) __sysconf (id)
+# define closedir(dir) __closedir (dir)
+# define opendir(name) __opendir (name)
+# define readdir(str) __readdir (str)
 #endif
 
-#if !(defined (STDC_HEADERS) || defined (__GNU_LIBRARY__))
-#undef size_t
-#define        size_t  unsigned int
+#if !(defined STDC_HEADERS || defined __GNU_LIBRARY__)
+# undef        size_t
+# define size_t        unsigned int
 #endif
 
 /* Some system header files erroneously define these.
    We want our own definitions from <fnmatch.h> to take precedence.  */
-#undef FNM_PATHNAME
-#undef FNM_NOESCAPE
-#undef FNM_PERIOD
+#ifndef __GNU_LIBRARY__
+# undef        FNM_PATHNAME
+# undef        FNM_NOESCAPE
+# undef        FNM_PERIOD
+#endif
 #include <fnmatch.h>
 
 /* Some system header files erroneously define these.
    We want our own definitions from <glob.h> to take precedence.  */
-#undef GLOB_ERR
-#undef GLOB_MARK
-#undef GLOB_NOSORT
-#undef GLOB_DOOFFS
-#undef GLOB_NOCHECK
-#undef GLOB_APPEND
-#undef GLOB_NOESCAPE
-#undef GLOB_PERIOD
+#ifndef __GNU_LIBRARY__
+# undef        GLOB_ERR
+# undef        GLOB_MARK
+# undef        GLOB_NOSORT
+# undef        GLOB_DOOFFS
+# undef        GLOB_NOCHECK
+# undef        GLOB_APPEND
+# undef        GLOB_NOESCAPE
+# undef        GLOB_PERIOD
+#endif
 #include <glob.h>
 \f
+static
+#if __GNUC__ - 0 >= 2
+inline
+#endif
+const char *next_brace_sub __P ((const char *begin));
 static int glob_in_dir __P ((const char *pattern, const char *directory,
                             int flags,
                             int (*errfunc) __P ((const char *, int)),
@@ -358,8 +386,12 @@ glob (pattern, flags, errfunc, pglob)
 #endif
 
          /* We know the prefix for all sub-patterns.  */
+#ifdef HAVE_MEMPCPY
+         alt_start = mempcpy (onealt, pattern, begin - pattern);
+#else
          memcpy (onealt, pattern, begin - pattern);
          alt_start = &onealt[begin - pattern];
+#endif
 
          /* Find the first sub-pattern and at the same time find the
             rest after the closing brace.  */
@@ -412,8 +444,12 @@ glob (pattern, flags, errfunc, pglob)
              int result;
 
              /* Construct the new glob expression.  */
+#ifdef HAVE_MEMPCPY
+             mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len);
+#else
              memcpy (alt_start, p, next - p);
              memcpy (&alt_start[next - p], rest, rest_len);
+#endif
 
              result = glob (onealt,
                             ((flags & ~(GLOB_NOCHECK|GLOB_NOMAGIC))
@@ -453,15 +489,38 @@ glob (pattern, flags, errfunc, pglob)
 
   /* Find the filename.  */
   filename = strrchr (pattern, '/');
+#if defined __MSDOS__ || defined WINDOWS32
+  /* The case of "d:pattern".  Since `:' is not allowed in
+     file names, we can safely assume that wherever it
+     happens in pattern, it signals the filename part.  This
+     is so we could some day support patterns like "[a-z]:foo".  */
+  if (filename == NULL)
+    filename = strchr (pattern, ':');
+#endif /* __MSDOS__ || WINDOWS32 */
   if (filename == NULL)
     {
-      filename = pattern;
+      /* This can mean two things: a simple name or "~name".  The later
+        case is nothing but a notation for a directory.  */
+      if ((flags & GLOB_TILDE) && pattern[0] == '~')
+       {
+         dirname = (char *) pattern;
+         dirlen = strlen (pattern);
+
+          /* Set FILENAME to NULL as a special flag.  This is ugly but
+             other solutions would require much more code.  We test for
+             this special case below.  */
+          filename = NULL;
+       }
+      else
+       {
+          filename = pattern;
 #ifdef _AMIGA
-      dirname = (char *) "";
+          dirname = (char *) "";
 #else
-      dirname = (char *) ".";
+          dirname = (char *) ".";
 #endif
-      dirlen = 0;
+          dirlen = 0;
+        }
     }
   else if (filename == pattern)
     {
@@ -473,19 +532,53 @@ glob (pattern, flags, errfunc, pglob)
   else
     {
       dirlen = filename - pattern;
+#if defined __MSDOS__ || defined WINDOWS32
+      if ((*filename == ':')
+         || (filename > pattern + 1 && filename[-1] == ':'))
+       {
+         char *drive_spec;
+
+         ++dirlen;
+         drive_spec = (char *) __alloca (dirlen + 1);
+#ifdef HAVE_MEMPCPY
+         *((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0';
+#else
+         memcpy (drive_spec, pattern, dirlen);
+         drive_spec[dirlen] = '\0';
+#endif
+         /* For now, disallow wildcards in the drive spec, to
+            prevent infinite recursion in glob.  */
+         if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE)))
+           return GLOB_NOMATCH;
+         /* If this is "d:pattern", we need to copy `:' to DIRNAME
+            as well.  If it's "d:/pattern", don't remove the slash
+            from "d:/", since "d:" and "d:/" are not the same.*/
+       }
+#endif
       dirname = (char *) __alloca (dirlen + 1);
+#ifdef HAVE_MEMPCPY
+      *((char *) mempcpy (dirname, pattern, dirlen)) = '\0';
+#else
       memcpy (dirname, pattern, dirlen);
       dirname[dirlen] = '\0';
+#endif
       ++filename;
-    }
 
-  if (filename[0] == '\0' && dirlen > 1)
-    /* "pattern/".  Expand "pattern", appending slashes.  */
-    {
-      int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob);
-      if (val == 0)
-       pglob->gl_flags = (pglob->gl_flags & ~GLOB_MARK) | (flags & GLOB_MARK);
-      return val;
+      if (filename[0] == '\0'
+#if defined __MSDOS__ || defined WINDOWS32
+          && dirname[dirlen-1] != ':'
+          && (dirlen < 3 || dirname[dirlen-2] != ':'
+             || dirname[dirlen-1] != '/')
+#endif
+          && dirlen > 1)
+      /* "pattern/".  Expand "pattern", appending slashes.  */
+      {
+        int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob);
+        if (val == 0)
+          pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK)
+                             | (flags & GLOB_MARK));
+        return val;
+      }
     }
 
   if (!(flags & GLOB_APPEND))
@@ -503,18 +596,18 @@ glob (pattern, flags, errfunc, pglob)
        {
          /* Look up home directory.  */
          char *home_dir = getenv ("HOME");
-#ifdef _AMIGA
+# ifdef _AMIGA
          if (home_dir == NULL || home_dir[0] == '\0')
            home_dir = "SYS:";
-#else
-#ifdef WINDOWS32
+# else
+#  ifdef WINDOWS32
          if (home_dir == NULL || home_dir[0] == '\0')
             home_dir = "c:/users/default"; /* poor default */
-#else
+#  else
          if (home_dir == NULL || home_dir[0] == '\0')
            {
              int success;
-#if defined HAVE_GETLOGIN_R || defined _LIBC
+#   if defined HAVE_GETLOGIN_R || defined _LIBC
              extern int getlogin_r __P ((char *, size_t));
              size_t buflen = sysconf (_SC_LOGIN_NAME_MAX) + 1;
              char *name;
@@ -526,15 +619,15 @@ glob (pattern, flags, errfunc, pglob)
              name = (char *) __alloca (buflen);
 
              success = getlogin_r (name, buflen) >= 0;
-#else
+#   else
              extern char *getlogin __P ((void));
              char *name;
 
              success = (name = getlogin ()) != NULL;
-#endif
+#   endif
              if (success)
                {
-#if defined HAVE_GETPWNAM_R || defined _LIBC
+#   if defined HAVE_GETPWNAM_R || defined _LIBC
                  size_t pwbuflen = sysconf (_SC_GETPW_R_SIZE_MAX);
                  char *pwtmpbuf;
                  struct passwd pwbuf, *p;
@@ -543,18 +636,18 @@ glob (pattern, flags, errfunc, pglob)
 
                  success = (__getpwnam_r (name, &pwbuf, pwtmpbuf,
                                           pwbuflen, &p) >= 0);
-#else
+#   else
                  struct passwd *p = getpwnam (name);
                  success = p != NULL;
-#endif
+#   endif
                  if (success)
                    home_dir = p->pw_dir;
                }
            }
          if (home_dir == NULL || home_dir[0] == '\0')
            home_dir = (char *) "~"; /* No luck.  */
-#endif /* WINDOWS32 */
-#endif
+#  endif /* WINDOWS32 */
+# endif
          /* Now construct the full directory.  */
          if (dirname[1] == '\0')
            dirname = home_dir;
@@ -563,12 +656,17 @@ glob (pattern, flags, errfunc, pglob)
              char *newp;
              size_t home_len = strlen (home_dir);
              newp = (char *) __alloca (home_len + dirlen);
+# ifdef HAVE_MEMPCPY
+             mempcpy (mempcpy (newp, home_dir, home_len),
+                      &dirname[1], dirlen);
+# else
              memcpy (newp, home_dir, home_len);
              memcpy (&newp[home_len], &dirname[1], dirlen);
+# endif
              dirname = newp;
            }
        }
-#if !defined _AMIGA && !defined WINDOWS32
+# if !defined _AMIGA && !defined WINDOWS32
       else
        {
          char *end_name = strchr (dirname, '/');
@@ -580,13 +678,18 @@ glob (pattern, flags, errfunc, pglob)
          else
            {
              user_name = (char *) __alloca (end_name - dirname);
+# ifdef HAVE_MEMPCPY
+             *((char *) mempcpy (user_name, dirname + 1, end_name - dirname))
+               = '\0';
+# else
              memcpy (user_name, dirname + 1, end_name - dirname);
              user_name[end_name - dirname - 1] = '\0';
+# endif
            }
 
          /* Look up specific user's home directory.  */
          {
-#if defined HAVE_GETPWNAM_R || defined _LIBC
+#  if defined HAVE_GETPWNAM_R || defined _LIBC
            size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
            char *pwtmpbuf = (char *) __alloca (buflen);
            struct passwd pwbuf, *p;
@@ -594,13 +697,13 @@ glob (pattern, flags, errfunc, pglob)
              home_dir = p->pw_dir;
            else
              home_dir = NULL;
-#else
+#  else
            struct passwd *p = getpwnam (user_name);
            if (p != NULL)
              home_dir = p->pw_dir;
            else
              home_dir = NULL;
-#endif
+#  endif
          }
          /* If we found a home directory use this.  */
          if (home_dir != NULL)
@@ -609,16 +712,74 @@ glob (pattern, flags, errfunc, pglob)
              size_t home_len = strlen (home_dir);
              size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
              newp = (char *) __alloca (home_len + rest_len + 1);
+#  ifdef HAVE_MEMPCPY
+             *((char *) mempcpy (mempcpy (newp, home_dir, home_len),
+                                 end_name, rest_len)) = '\0';
+#  else
              memcpy (newp, home_dir, home_len);
              memcpy (&newp[home_len], end_name, rest_len);
              newp[home_len + rest_len] = '\0';
+#  endif
              dirname = newp;
            }
        }
-#endif /* Not Amiga && not WINDOWS32.  */
+# endif        /* Not Amiga && not WINDOWS32.  */
     }
 #endif /* Not VMS.  */
 
+  /* Now test whether we looked for "~" or "~NAME".  In this case we
+     can give the answer now.  */
+  if (filename == NULL)
+    {
+      struct stat st;
+
+      /* Return the directory if we don't check for error or if it exists.  */
+      if ((flags & GLOB_NOCHECK)
+         || (((flags & GLOB_ALTDIRFUNC)
+              ? (*pglob->gl_stat) (dirname, &st)
+              : __stat (dirname, &st)) == 0
+             && S_ISDIR (st.st_mode)))
+       {
+         pglob->gl_pathv
+           = (char **) realloc (pglob->gl_pathv,
+                                (pglob->gl_pathc +
+                                 ((flags & GLOB_DOOFFS) ?
+                                  pglob->gl_offs : 0) +
+                                 1 + 1) *
+                                sizeof (char *));
+         if (pglob->gl_pathv == NULL)
+           return GLOB_NOSPACE;
+
+         if (flags & GLOB_DOOFFS)
+           while (pglob->gl_pathc < pglob->gl_offs)
+             pglob->gl_pathv[pglob->gl_pathc++] = NULL;
+
+#if defined HAVE_STRDUP || defined _LIBC
+         pglob->gl_pathv[pglob->gl_pathc] = strdup (dirname);
+#else
+         {
+           size_t len = strlen (dirname) + 1;
+           char *dircopy = malloc (len);
+           if (dircopy != NULL)
+             pglob->gl_pathv[pglob->gl_pathc] = memcpy (dircopy, dirname,
+                                                        len);
+         }
+#endif
+         if (pglob->gl_pathv[pglob->gl_pathc] == NULL)
+           {
+             free (pglob->gl_pathv);
+             return GLOB_NOSPACE;
+           }
+         pglob->gl_pathv[++pglob->gl_pathc] = NULL;
+         pglob->gl_flags = flags;
+
+         return 0;
+       }
+
+      /* Not found.  */
+      return GLOB_NOMATCH;
+    }
+
   if (__glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE)))
     {
       /* The directory name contains metacharacters, so we
@@ -628,8 +789,8 @@ glob (pattern, flags, errfunc, pglob)
       register int i;
 
       status = glob (dirname,
-                    ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE)) |
-                     GLOB_NOSORT),
+                    ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE))
+                     | GLOB_NOSORT | GLOB_ONLYDIR),
                     errfunc, &dirs);
       if (status != 0)
        return status;
@@ -639,7 +800,7 @@ glob (pattern, flags, errfunc, pglob)
         appending the results to PGLOB.  */
       for (i = 0; i < dirs.gl_pathc; ++i)
        {
-         int oldcount;
+         int old_pathc;
 
 #ifdef SHELL
          {
@@ -655,9 +816,10 @@ glob (pattern, flags, errfunc, pglob)
          }
 #endif /* SHELL.  */
 
-         oldcount = pglob->gl_pathc;
+         old_pathc = pglob->gl_pathc;
          status = glob_in_dir (filename, dirs.gl_pathv[i],
-                               (flags | GLOB_APPEND) & ~GLOB_NOCHECK,
+                               ((flags | GLOB_APPEND)
+                                & ~(GLOB_NOCHECK | GLOB_ERR)),
                                errfunc, pglob);
          if (status == GLOB_NOMATCH)
            /* No matches in this directory.  Try the next.  */
@@ -672,8 +834,8 @@ glob (pattern, flags, errfunc, pglob)
 
          /* Stick the directory on the front of each name.  */
          if (prefix_array (dirs.gl_pathv[i],
-                           &pglob->gl_pathv[oldcount],
-                           pglob->gl_pathc - oldcount))
+                           &pglob->gl_pathv[old_pathc],
+                           pglob->gl_pathc - old_pathc))
            {
              globfree (&dirs);
              globfree (pglob);
@@ -683,26 +845,29 @@ glob (pattern, flags, errfunc, pglob)
 
       flags |= GLOB_MAGCHAR;
 
+      /* We have ignored the GLOB_NOCHECK flag in the `glob_in_dir' calls.
+        But if we have not found any matching entry and thie GLOB_NOCHECK
+        flag was set we must return the list consisting of the disrectory
+        names followed by the filename.  */
       if (pglob->gl_pathc == oldcount)
        /* No matches.  */
        if (flags & GLOB_NOCHECK)
          {
-           size_t len = strlen (pattern) + 1;
-           char *patcopy = (char *) malloc (len);
-           if (patcopy == NULL)
-             return GLOB_NOSPACE;
-           memcpy (patcopy, pattern, len);
+           size_t filename_len = strlen (filename) + 1;
+           char **new_pathv;
+           struct stat st;
 
+           /* This is an pessimistic guess about the size.  */
            pglob->gl_pathv
              = (char **) realloc (pglob->gl_pathv,
                                   (pglob->gl_pathc +
                                    ((flags & GLOB_DOOFFS) ?
                                     pglob->gl_offs : 0) +
-                                   1 + 1) *
+                                   dirs.gl_pathc + 1) *
                                   sizeof (char *));
            if (pglob->gl_pathv == NULL)
              {
-               free (patcopy);
+               globfree (&dirs);
                return GLOB_NOSPACE;
              }
 
@@ -710,12 +875,55 @@ glob (pattern, flags, errfunc, pglob)
              while (pglob->gl_pathc < pglob->gl_offs)
                pglob->gl_pathv[pglob->gl_pathc++] = NULL;
 
-           pglob->gl_pathv[pglob->gl_pathc++] = patcopy;
+           for (i = 0; i < dirs.gl_pathc; ++i)
+             {
+               const char *dir = dirs.gl_pathv[i];
+               size_t dir_len = strlen (dir);
+
+               /* First check whether this really is a directory.  */
+               if (((flags & GLOB_ALTDIRFUNC)
+                    ? (*pglob->gl_stat) (dir, &st) : __stat (dir, &st)) != 0
+                   || !S_ISDIR (st.st_mode))
+                 /* No directory, ignore this entry.  */
+                 continue;
+
+               pglob->gl_pathv[pglob->gl_pathc] = malloc (dir_len + 1
+                                                          + filename_len);
+               if (pglob->gl_pathv[pglob->gl_pathc] == NULL)
+                 {
+                   globfree (&dirs);
+                   globfree (pglob);
+                   return GLOB_NOSPACE;
+                 }
+
+#ifdef HAVE_MEMPCPY
+               mempcpy (mempcpy (mempcpy (pglob->gl_pathv[pglob->gl_pathc],
+                                          dir, dir_len),
+                                 "/", 1),
+                        filename, filename_len);
+#else
+               memcpy (pglob->gl_pathv[pglob->gl_pathc], dir, dir_len);
+               pglob->gl_pathv[pglob->gl_pathc][dir_len] = '/';
+               memcpy (&pglob->gl_pathv[pglob->gl_pathc][dir_len + 1],
+                       filename, filename_len);
+#endif
+               ++pglob->gl_pathc;
+             }
+
            pglob->gl_pathv[pglob->gl_pathc] = NULL;
            pglob->gl_flags = flags;
+
+           /* Now we know how large the gl_pathv vector must be.  */
+           new_pathv = (char **) realloc (pglob->gl_pathv,
+                                           ((pglob->gl_pathc + 1)
+                                            * sizeof (char *)));
+           if (new_pathv != NULL)
+             pglob->gl_pathv = new_pathv;
          }
        else
          return GLOB_NOMATCH;
+
+      globfree (&dirs);
     }
   else
     {
@@ -726,9 +934,14 @@ glob (pattern, flags, errfunc, pglob)
       if (dirlen > 0)
        {
          /* Stick the directory on the front of each name.  */
+         int ignore = oldcount;
+
+         if ((flags & GLOB_DOOFFS) && ignore < pglob->gl_offs)
+           ignore = pglob->gl_offs;
+
          if (prefix_array (dirname,
-                           &pglob->gl_pathv[oldcount],
-                           pglob->gl_pathc - oldcount))
+                           &pglob->gl_pathv[ignore],
+                           pglob->gl_pathc - ignore))
            {
              globfree (pglob);
              return GLOB_NOSPACE;
@@ -742,10 +955,10 @@ glob (pattern, flags, errfunc, pglob)
       int i;
       struct stat st;
       for (i = oldcount; i < pglob->gl_pathc; ++i)
-       if (((flags & GLOB_ALTDIRFUNC) ?
-            (*pglob->gl_stat) (pglob->gl_pathv[i], &st) :
-            __stat (pglob->gl_pathv[i], &st)) == 0 &&
-           S_ISDIR (st.st_mode))
+       if (((flags & GLOB_ALTDIRFUNC)
+            ? (*pglob->gl_stat) (pglob->gl_pathv[i], &st)
+            : __stat (pglob->gl_pathv[i], &st)) == 0
+           && S_ISDIR (st.st_mode))
          {
            size_t len = strlen (pglob->gl_pathv[i]) + 2;
            char *new = realloc (pglob->gl_pathv[i], len);
@@ -760,10 +973,17 @@ glob (pattern, flags, errfunc, pglob)
     }
 
   if (!(flags & GLOB_NOSORT))
-    /* Sort the vector.  */
-    qsort ((__ptr_t) &pglob->gl_pathv[oldcount],
-          pglob->gl_pathc - oldcount,
-          sizeof (char *), collated_compare);
+    {
+      /* Sort the vector.  */
+      int non_sort = oldcount;
+
+      if ((flags & GLOB_DOOFFS) && pglob->gl_offs > oldcount)
+       non_sort = pglob->gl_offs;
+
+      qsort ((__ptr_t) &pglob->gl_pathv[non_sort],
+            pglob->gl_pathc - non_sort,
+            sizeof (char *), collated_compare);
+    }
 
   return 0;
 }
@@ -816,11 +1036,31 @@ prefix_array (dirname, array, n)
 {
   register size_t i;
   size_t dirlen = strlen (dirname);
+#if defined __MSDOS__ || defined WINDOWS32
+  int sep_char = '/';
+# define DIRSEP_CHAR sep_char
+#else
+# define DIRSEP_CHAR '/'
+#endif
 
   if (dirlen == 1 && dirname[0] == '/')
     /* DIRNAME is just "/", so normal prepending would get us "//foo".
        We want "/foo" instead, so don't prepend any chars from DIRNAME.  */
     dirlen = 0;
+#if defined __MSDOS__ || defined WINDOWS32
+  else if (dirlen > 1)
+    {
+      if (dirname[dirlen - 1] == '/')
+       /* DIRNAME is "d:/".  Don't prepend the slash from DIRNAME.  */
+       --dirlen;
+      else if (dirname[dirlen - 1] == ':')
+       {
+         /* DIRNAME is "d:".  Use `:' instead of `/'.  */
+         --dirlen;
+         sep_char = ':';
+       }
+    }
+#endif
 
   for (i = 0; i < n; ++i)
     {
@@ -833,9 +1073,17 @@ prefix_array (dirname, array, n)
          return 1;
        }
 
+#ifdef HAVE_MEMPCPY
+      {
+       char *endp = (char *) mempcpy (new, dirname, dirlen);
+       *endp++ = DIRSEP_CHAR;
+       mempcpy (endp, array[i], eltlen);
+      }
+#else
       memcpy (new, dirname, dirlen);
-      new[dirlen] = '/';
+      new[dirlen] = DIRSEP_CHAR;
       memcpy (&new[dirlen + 1], array[i], eltlen);
+#endif
       free ((__ptr_t) array[i]);
       array[i] = new;
     }
@@ -895,7 +1143,7 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob)
      int (*errfunc) __P ((const char *, int));
      glob_t *pglob;
 {
-  __ptr_t stream;
+  __ptr_t stream = NULL;
 
   struct globlink
     {
@@ -903,69 +1151,131 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob)
       char *name;
     };
   struct globlink *names = NULL;
-  size_t nfound = 0;
+  size_t nfound;
+  int meta;
+  int save;
 
-  if (!__glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE)))
+  meta = __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE));
+  if (meta == 0)
     {
-      stream = NULL;
-      flags |= GLOB_NOCHECK;
+      if (flags & (GLOB_NOCHECK|GLOB_NOMAGIC))
+       /* We need not do any tests.  The PATTERN contains no meta
+          characters and we must not return an error therefore the
+          result will always contain exactly one name.  */
+       flags |= GLOB_NOCHECK;
+      else
+       {
+         /* Since we use the normal file functions we can also use stat()
+            to verify the file is there.  */
+         struct stat st;
+         size_t patlen = strlen (pattern);
+         size_t dirlen = strlen (directory);
+         char *fullname = (char *) __alloca (dirlen + 1 + patlen + 1);
+
+# ifdef HAVE_MEMPCPY
+         mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
+                           "/", 1),
+                  pattern, patlen + 1);
+# else
+         memcpy (fullname, directory, dirlen);
+         fullname[dirlen] = '/';
+         memcpy (&fullname[dirlen + 1], pattern, patlen + 1);
+# endif
+         if (((flags & GLOB_ALTDIRFUNC)
+              ? (*pglob->gl_stat) (fullname, &st)
+              : __stat (fullname, &st)) == 0)
+           /* We found this file to be existing.  Now tell the rest
+              of the function to copy this name into the result.  */
+           flags |= GLOB_NOCHECK;
+       }
+
+      nfound = 0;
     }
   else
     {
-      flags |= GLOB_MAGCHAR;
-
-      stream = ((flags & GLOB_ALTDIRFUNC) ?
-               (*pglob->gl_opendir) (directory) :
-               (__ptr_t) opendir (directory));
-      if (stream == NULL)
+      if (pattern[0] == '\0')
        {
-         if ((errfunc != NULL && (*errfunc) (directory, errno)) ||
-             (flags & GLOB_ERR))
-           return GLOB_ABORTED;
+         /* This is a special case for matching directories like in
+            "*a/".  */
+         names = (struct globlink *) __alloca (sizeof (struct globlink));
+         names->name = (char *) malloc (1);
+         if (names->name == NULL)
+           goto memory_error;
+         names->name[0] = '\0';
+         names->next = NULL;
+         nfound = 1;
+         meta = 0;
        }
       else
-       while (1)
-         {
-           const char *name;
-           size_t len;
-           struct dirent *d = ((flags & GLOB_ALTDIRFUNC) ?
-                               (*pglob->gl_readdir) (stream) :
-                               readdir ((DIR *) stream));
-           if (d == NULL)
-             break;
-           if (! REAL_DIR_ENTRY (d))
-             continue;
+       {
+         stream = ((flags & GLOB_ALTDIRFUNC)
+                   ? (*pglob->gl_opendir) (directory)
+                   : (__ptr_t) opendir (directory));
+         if (stream == NULL)
+           {
+             if ((errfunc != NULL && (*errfunc) (directory, errno))
+                 || (flags & GLOB_ERR))
+               return GLOB_ABORTED;
+             nfound = 0;
+             meta = 0;
+           }
+         else
+           {
+             int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)
+                              | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)
+#if defined _AMIGA || defined VMS
+                                  | FNM_CASEFOLD
+#endif
+                                  );
+             nfound = 0;
+             flags |= GLOB_MAGCHAR;
 
-           name = d->d_name;
+             while (1)
+               {
+                 const char *name;
+                 size_t len;
+                 struct dirent *d = ((flags & GLOB_ALTDIRFUNC)
+                                     ? (*pglob->gl_readdir) (stream)
+                                     : readdir ((DIR *) stream));
+                 if (d == NULL)
+                   break;
+                 if (! REAL_DIR_ENTRY (d))
+                   continue;
+
+#ifdef HAVE_D_TYPE
+                 /* If we shall match only directories use the information
+                    provided by the dirent call if possible.  */
+                 if ((flags & GLOB_ONLYDIR)
+                     && d->d_type != DT_UNKNOWN && d->d_type != DT_DIR)
+                   continue;
+#endif
 
-           if (fnmatch (pattern, name,
-                        (!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) |
-                        ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)
-#ifdef _AMIGA
-                        | FNM_CASEFOLD
+                 name = d->d_name;
+
+                 if (fnmatch (pattern, name, fnm_flags) == 0)
+                   {
+                     struct globlink *new = (struct globlink *)
+                       __alloca (sizeof (struct globlink));
+                     len = NAMLEN (d);
+                     new->name = (char *) malloc (len + 1);
+                     if (new->name == NULL)
+                       goto memory_error;
+#ifdef HAVE_MEMPCPY
+                     *((char *) mempcpy ((__ptr_t) new->name, name, len))
+                       = '\0';
+#else
+                     memcpy ((__ptr_t) new->name, name, len);
+                     new->name[len] = '\0';
 #endif
-                        ) == 0)
-             {
-               struct globlink *new
-                 = (struct globlink *) __alloca (sizeof (struct globlink));
-               len = NAMLEN (d);
-               new->name
-                 = (char *) malloc (len + 1);
-               if (new->name == NULL)
-                 goto memory_error;
-               memcpy ((__ptr_t) new->name, name, len);
-               new->name[len] = '\0';
-               new->next = names;
-               names = new;
-               ++nfound;
-             }
-         }
+                     new->next = names;
+                     names = new;
+                     ++nfound;
+                   }
+               }
+           }
+       }
     }
 
-  if (nfound == 0 && (flags & GLOB_NOMAGIC) &&
-      ! __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE)))
-    flags |= GLOB_NOCHECK;
-
   if (nfound == 0 && (flags & GLOB_NOCHECK))
     {
       size_t len = strlen (pattern);
@@ -975,38 +1285,44 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob)
       names->name = (char *) malloc (len + 1);
       if (names->name == NULL)
        goto memory_error;
+#ifdef HAVE_MEMPCPY
+      *((char *) mempcpy (names->name, pattern, len)) = '\0';
+#else
       memcpy (names->name, pattern, len);
       names->name[len] = '\0';
+#endif
     }
 
-  pglob->gl_pathv
-    = (char **) realloc (pglob->gl_pathv,
-                        (pglob->gl_pathc +
-                         ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) +
-                         nfound + 1) *
-                        sizeof (char *));
-  if (pglob->gl_pathv == NULL)
-    goto memory_error;
+  if (nfound != 0)
+    {
+      pglob->gl_pathv
+       = (char **) realloc (pglob->gl_pathv,
+                            (pglob->gl_pathc +
+                             ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) +
+                             nfound + 1) *
+                            sizeof (char *));
+      if (pglob->gl_pathv == NULL)
+       goto memory_error;
 
-  if (flags & GLOB_DOOFFS)
-    while (pglob->gl_pathc < pglob->gl_offs)
-      pglob->gl_pathv[pglob->gl_pathc++] = NULL;
+      if (flags & GLOB_DOOFFS)
+       while (pglob->gl_pathc < pglob->gl_offs)
+         pglob->gl_pathv[pglob->gl_pathc++] = NULL;
 
-  for (; names != NULL; names = names->next)
-    pglob->gl_pathv[pglob->gl_pathc++] = names->name;
-  pglob->gl_pathv[pglob->gl_pathc] = NULL;
+      for (; names != NULL; names = names->next)
+       pglob->gl_pathv[pglob->gl_pathc++] = names->name;
+      pglob->gl_pathv[pglob->gl_pathc] = NULL;
 
-  pglob->gl_flags = flags;
+      pglob->gl_flags = flags;
+    }
 
+  save = errno;
   if (stream != NULL)
-    {
-      int save = errno;
-      if (flags & GLOB_ALTDIRFUNC)
-       (*pglob->gl_closedir) (stream);
-      else
-       closedir ((DIR *) stream);
-      __set_errno (save);
-    }
+    if (flags & GLOB_ALTDIRFUNC)
+      (*pglob->gl_closedir) (stream);
+    else
+      closedir ((DIR *) stream);
+  __set_errno (save);
+
   return nfound == 0 ? GLOB_NOMATCH : 0;
 
  memory_error:
index 713117b..a546c86 100644 (file)
 #define        _GLOB_H 1
 
 #ifdef __cplusplus
-extern "C"
-{
+extern "C" {
 #endif
 
 #undef __ptr_t
-#if (defined __cplusplus || (defined __STDC__ && __STDC__) \
-     || defined WINDOWS32)
+#if defined __cplusplus || (defined __STDC__ && __STDC__) || defined WINDOWS32
 # undef        __P
 # define __P(protos)   protos
 # define __ptr_t       void *
@@ -57,11 +55,12 @@ extern "C"
 # define GLOB_ALTDIRFUNC (1 << 9)/* Use gl_opendir et al functions.  */
 # define GLOB_BRACE     (1 << 10)/* Expand "{a,b}" to "a" "b".  */
 # define GLOB_NOMAGIC   (1 << 11)/* If no magic chars, return the pattern.  */
-# define GLOB_TILDE     (1 <<12)/* Expand ~user and ~ to home directories.  */
+# define GLOB_TILDE     (1 << 12)/* Expand ~user and ~ to home directories. */
+# define GLOB_ONLYDIR   (1 << 13)/* Match only directories.  */
 # define __GLOB_FLAGS  (GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \
                         GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND|     \
                         GLOB_PERIOD|GLOB_ALTDIRFUNC|GLOB_BRACE|     \
-                        GLOB_NOMAGIC|GLOB_TILDE)
+                        GLOB_NOMAGIC|GLOB_TILDE|GLOB_ONLYDIR)
 #else
 # define __GLOB_FLAGS  (GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \
                         GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND|     \
@@ -79,6 +78,14 @@ extern "C"
 # define GLOB_ABEND GLOB_ABORTED
 #endif
 
+/* This value is returned if the implementation does not support
+   `glob'.  Since this is not the case here it will never be
+   returned but the conformance test suites still require the symbol
+   to be defined.  */
+#if (_XOPEN_SOURCE - 0) == 500
+# define GLOB_NOSYS    (-1)
+#endif
+
 /* Structure describing a globbing run.  */
 #if !defined _AMIGA && !defined VMS /* Buggy compiler.   */
 struct stat;
index f7298c6..a999a0f 100644 (file)
@@ -111,14 +111,14 @@ pattern_search (file, archive, depth, recursions)
   /* This buffer records all the dependencies actually found for a rule.  */
   char **found_files = (char **) alloca (max_pattern_deps * sizeof (char *));
   /* Number of dep names now in FOUND_FILES.  */
-  unsigned int deps_found;
+  unsigned int deps_found = 0;
 
   /* Names of possible dependencies are constructed in this buffer.  */
   register char *depname = (char *) alloca (namelen + max_pattern_dep_length);
 
   /* The start and length of the stem of FILENAME for the current rule.  */
-  register char *stem;
-  register unsigned int stemlen;
+  register char *stem = 0;
+  register unsigned int stemlen = 0;
 
   /* Buffer in which we store all the rules that are possibly applicable.  */
   struct rule **tryrules
diff --git a/job.c b/job.c
index 2227bef..91bc30b 100644 (file)
--- a/job.c
+++ b/job.c
@@ -27,11 +27,12 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #ifdef WINDOWS32
 char *default_shell = "sh.exe";
 int no_default_sh_exe = 1;
+int batch_mode_shell = 1;
 #else  /* WINDOWS32 */
 #ifdef _AMIGA
 char default_shell[] = "";
 extern int MyExecute (char **);
-#else
+#else /* _AMIGA */
 #ifdef __MSDOS__
 /* The default shell is a pointer so we can change it if Makefile
    says so.  It is without an explicit path so we get a chance
@@ -41,6 +42,7 @@ char *default_shell = "command.com";
 #else  /* __MSDOS__ */
 char default_shell[] = "/bin/sh";
 #endif /* __MSDOS__ */
+int batch_mode_shell = 0;
 #endif /* _AMIGA */
 #endif /* WINDOWS32 */
 
@@ -74,11 +76,6 @@ static int amiga_batch_file;
 #include "sub_proc.h"
 #include "w32err.h"
 #include "pathstuff.h"
-
-/* this stuff used if no sh.exe is around */
-static char *dos_bname;
-static char *dos_bename;
-static int dos_batch_file;
 #endif /* WINDOWS32 */
 
 #ifdef HAVE_FCNTL_H
@@ -168,7 +165,7 @@ extern char *allocated_variable_expand_for_file PARAMS ((char *line, struct file
 extern int getloadavg PARAMS ((double loadavg[], int nelem));
 extern int start_remote_job PARAMS ((char **argv, char **envp, int stdin_fd,
                int *is_remote, int *id_ptr, int *used_stdin));
-extern int start_remote_job_p PARAMS ((void));
+extern int start_remote_job_p PARAMS ((int));
 extern int remote_status PARAMS ((int *exit_code_ptr, int *signal_ptr,
                int *coredump_ptr, int block));
 
@@ -327,9 +324,9 @@ reap_children (block, err)
          any_remote |= c->remote;
          any_local |= ! c->remote;
          if (debug_flag)
-           printf ("Live child 0x%08lx PID %d%s\n",
+           printf ("Live child 0x%08lx PID %ld%s\n",
                    (unsigned long int) c,
-                   c->pid, c->remote ? " (remote)" : "");
+                   (long) c->pid, c->remote ? " (remote)" : "");
 #ifdef VMS
          break;
 #endif
@@ -426,38 +423,33 @@ reap_children (block, err)
          coredump = 0;
 #endif /* _AMIGA */
 #ifdef WINDOWS32
-         {
-           HANDLE hPID;
-           int err;
-
-           /* wait for anything to finish */
-           if (hPID = process_wait_for_any()) {
+      {
+        HANDLE hPID;
+        int err;
 
-             /* was an error found on this process? */
-             err = process_last_err(hPID);
+        /* wait for anything to finish */
+        if (hPID = process_wait_for_any()) {
 
-             /* get exit data */
-             exit_code = process_exit_code(hPID);
+          /* was an error found on this process? */
+          err = process_last_err(hPID);
 
-             if (err)
-               fprintf(stderr, "make (e=%d): %s",
-                       exit_code, map_windows32_error_to_string(exit_code));
+          /* get exit data */
+          exit_code = process_exit_code(hPID);
 
-             exit_sig = process_signal(hPID);
+          if (err)
+            fprintf(stderr, "make (e=%d): %s",
+              exit_code, map_windows32_error_to_string(exit_code));
 
-             /* cleanup process */
-             process_cleanup(hPID);
+          /* signal */
+          exit_sig = process_signal(hPID);
 
-             if (dos_batch_file) {
-               remove (dos_bname);
-               remove (dos_bename);
-               dos_batch_file = 0;
-             }
+          /* cleanup process */
+          process_cleanup(hPID);
 
-             coredump = 0;
-           }
-           pid = (int) hPID;
-         }
+          coredump = 0;
+        }
+        pid = (int) hPID;
+      }
 #endif /* WINDOWS32 */
 #endif /* Not __MSDOS__ */
        }
@@ -498,10 +490,22 @@ reap_children (block, err)
       else
        {
          if (debug_flag)
-           printf ("Reaping %s child 0x%08lx PID %d%s\n",
+           printf ("Reaping %s child 0x%08lx PID %ld%s\n",
                    child_failed ? "losing" : "winning",
                    (unsigned long int) c,
-                   c->pid, c->remote ? " (remote)" : "");
+                   (long) c->pid, c->remote ? " (remote)" : "");
+
+      if (c->sh_batch_file) {
+         if (debug_flag)
+           printf("Cleaning up temporary batch file %s\n", c->sh_batch_file);
+
+         /* just try and remove, don't care if this fails */
+         remove(c->sh_batch_file);
+
+         /* all done with memory */
+         free(c->sh_batch_file);
+         c->sh_batch_file = NULL;
+      }
 
          /* If this child had the good stdin, say it is now free.  */
          if (c->good_stdin)
@@ -549,7 +553,7 @@ reap_children (block, err)
                         Whether or not we want to changes over time.
                         Also, start_remote_job may need state set up
                         by start_remote_job_p.  */
-                     c->remote = start_remote_job_p ();
+                     c->remote = start_remote_job_p (0);
                      start_job_command (c);
                      /* Fatal signals are left blocked in case we were
                         about to put that child on the chain.  But it is
@@ -586,9 +590,9 @@ reap_children (block, err)
            notice_finished_file (c->file);
 
          if (debug_flag)
-           printf ("Removing child 0x%08lx PID %d%s from chain.\n",
+           printf ("Removing child 0x%08lx PID %ld%s from chain.\n",
                    (unsigned long int) c,
-                   c->pid, c->remote ? " (remote)" : "");
+                   (long) c->pid, c->remote ? " (remote)" : "");
 
          /* Block fatal signals while frobnicating the list, so that
             children and job_slots_used are always consistent.  Otherwise
@@ -740,7 +744,7 @@ start_job_command (child)
 #ifdef VMS
     argv = p;
 #else
-    argv = construct_command_argv (p, &end, child->file);
+    argv = construct_command_argv (p, &end, child->file, &child->sh_batch_file);
 #endif
     if (end == NULL)
       child->command_ptr = NULL;
@@ -765,6 +769,9 @@ start_job_command (child)
   if (argv == 0)
     {
     next_command:
+#ifdef __MSDOS__
+         execute_by_shell = 0;   /* in case construct_command_argv sets it */
+#endif
       /* This line has no commands.  Go to the next.  */
       if (job_next_command (child))
        start_job_command (child);
@@ -887,7 +894,9 @@ start_job_command (child)
       if (start_remote_job (argv, child->environment,
                            child->good_stdin ? 0 : bad_stdin,
                            &is_remote, &id, &used_stdin))
-       goto error;
+        /* Don't give up; remote execution may fail for various reasons.  If
+           so, simply run the job locally.  */
+       goto run_local;
       else
        {
          if (child->good_stdin && !used_stdin)
@@ -906,6 +915,7 @@ start_job_command (child)
 
       char **parent_environ;
 
+    run_local:
       block_sigs ();
 
       child->remote = 0;
@@ -1066,7 +1076,7 @@ start_waiting_job (c)
      the local load average.  We record that the job should be started
      remotely in C->remote for start_job_command to test.  */
 
-  c->remote = start_remote_job_p ();
+  c->remote = start_remote_job_p (1);
 
   /* If this job is to be started locally, and we are already running
      some jobs, make this one wait if the load average is too high.  */
@@ -1251,6 +1261,7 @@ new_job (file)
   c->command_line = 0;
   c->command_ptr = 0;
   c->environment = 0;
+  c->sh_batch_file = NULL;
 
   /* Fetch the first command line to be run.  */
   job_next_command (c);
@@ -1479,11 +1490,12 @@ child_execute_job (argv, child)
     }
   *c = *p;
 
-  /* check for maximum dcl length and create *.com file if neccesary */
+  /* Check for maximum DCL length and create *.com file if neccesary.
+     Also create a .com file if the command is more than one line long.  */
 
   comname[0] = '\0';
 
-  if (strlen (cmd) > MAXCMDLEN)
+  if (strlen (cmd) > MAXCMDLEN || strchr (cmd, '\n'))
     {
       FILE *outfile;
       char tmp;
@@ -1743,9 +1755,10 @@ void clean_tmp (void)
    IFS is the value of $IFS, or nil (meaning the default).  */
 
 static char **
-construct_command_argv_internal (line, restp, shell, ifs)
+construct_command_argv_internal (line, restp, shell, ifs, batch_filename_ptr)
      char *line, **restp;
      char *shell, *ifs;
+     char **batch_filename_ptr;
 {
 #ifdef __MSDOS__
   /* MSDOS supports both the stock DOS shell and ports of Unixy shells.
@@ -1810,7 +1823,11 @@ construct_command_argv_internal (line, restp, shell, ifs)
                             "logout", "set", "umask", "wait", "while", "for",
                             "case", "if", ":", ".", "break", "continue",
                             "export", "read", "readonly", "shift", "times",
-                            "trap", "switch", "test", 0 };
+                            "trap", "switch", "test",
+#ifdef BATCH_MODE_ONLY_SHELL
+                 "echo",
+#endif
+                 0 };
   char*  sh_chars;
   char** sh_cmds;
 #else  /* WINDOWS32 */
@@ -2144,38 +2161,6 @@ construct_command_argv_internal (line, restp, shell, ifs)
     ++line;
   if (*line == '\0')
     return 0;
-
-  /*
-   * only come here if no sh.exe command
-   */
-  if (no_default_sh_exe)
-  {
-    FILE *batch;
-    dos_batch_file = 1;
-    if (dos_bname == 0)
-    {
-      dos_bname = tempnam (".", "mk");
-      for (i = 0; dos_bname[i] != '\0'; ++i)
-       if (dos_bname[i] == '/')
-         dos_bname[i] = '\\';
-      dos_bename = (char *) xmalloc (strlen (dos_bname) + 5);
-      strcpy (dos_bename, dos_bname);
-      strcat (dos_bname, ".bat");
-      strcat (dos_bename, ".err");
-    }
-    batch = fopen (dos_bename, "w"); /* Create a file.  */
-    if (batch != NULL)
-      fclose (batch);
-    batch = fopen (dos_bname, "w");
-    fputs ("@echo off\n", batch);
-    fputs (line, batch);
-    fprintf (batch, "\nif errorlevel 1 del %s\n", dos_bename);
-    fclose (batch);
-    new_argv = (char **) xmalloc(2 * sizeof(char *));
-    new_argv[0] = strdup (dos_bname);
-    new_argv[1] = 0;
-  }
-  else
 #endif /* WINDOWS32 */
   {
     /* SHELL may be a multi-word command.  Construct a command line
@@ -2189,12 +2174,14 @@ construct_command_argv_internal (line, restp, shell, ifs)
 
     char *new_line = (char *) alloca (shell_len + (sizeof (minus_c) - 1)
                                      + (line_len * 2) + 1);
+    char* command_ptr = NULL; /* used for batch_mode_shell mode */
 
     ap = new_line;
     bcopy (shell, ap, shell_len);
     ap += shell_len;
     bcopy (minus_c, ap, sizeof (minus_c) - 1);
     ap += sizeof (minus_c) - 1;
+       command_ptr = ap;
     for (p = line; *p != '\0'; ++p)
       {
        if (restp != NULL && *p == '\n')
@@ -2218,14 +2205,14 @@ construct_command_argv_internal (line, restp, shell, ifs)
 
            p = next_token (p);
            --p;
-            if (unixy_shell)
-              *ap++ = '\\';
+        if (unixy_shell && !batch_mode_shell)
+          *ap++ = '\\';
            *ap++ = ' ';
            continue;
          }
 
         /* DOS shells don't know about backslash-escaping.  */
-       if (unixy_shell &&
+       if (unixy_shell && !batch_mode_shell &&
             (*p == '\\' || *p == '\'' || *p == '"'
              || isspace (*p)
              || index (sh_chars, *p) != 0))
@@ -2246,9 +2233,63 @@ construct_command_argv_internal (line, restp, shell, ifs)
       return 0;
     *ap = '\0';
 
+#ifdef WINDOWS32
+    /*
+        * Some shells do not work well when invoked as 'sh -c  xxx' to run
+        * a command line (e.g. Cygnus GNUWIN32 sh.exe on WIN32 systems).
+        * In these cases, run commands via a script file.
+     */
+    if ((no_default_sh_exe || batch_mode_shell) && batch_filename_ptr) {
+      FILE* batch = NULL;
+      int id = GetCurrentProcessId();
+      PATH_VAR(fbuf);
+      char* fname = NULL;
+
+      /* create a file name */
+      sprintf(fbuf, "make%d", id);
+      fname = tempnam(".", fbuf);
+
+         /* create batch file name */
+      *batch_filename_ptr = xmalloc(strlen(fname) + 5);
+      strcpy(*batch_filename_ptr, fname);
+
+      /* make sure path name is in DOS backslash format */
+      if (!unixy_shell) {
+        fname = *batch_filename_ptr;
+        for (i = 0; fname[i] != '\0'; ++i)
+          if (fname[i] == '/')
+            fname[i] = '\\';
+        strcat(*batch_filename_ptr, ".bat");
+      } else {
+        strcat(*batch_filename_ptr, ".sh");
+      }
+
+      if (debug_flag)
+        printf("Creating temporary batch file %s\n", *batch_filename_ptr);
+
+      /* create batch file to execute command */
+      batch = fopen (*batch_filename_ptr, "w");
+      fputs ("@echo off\n", batch);
+      fputs (command_ptr, batch);
+      fputc ('\n', batch);
+      fclose (batch);
+
+      /* create argv */
+      new_argv = (char **) xmalloc(3 * sizeof(char *));
+      if (unixy_shell) {
+        new_argv[0] = strdup (shell);
+        new_argv[1] = *batch_filename_ptr; /* only argv[0] gets freed later */
+      } else {
+        new_argv[0] = strdup (*batch_filename_ptr);
+        new_argv[1] = NULL;
+      }
+      new_argv[2] = NULL;
+    } else
+#endif /* WINDOWS32 */
     if (unixy_shell)
       new_argv = construct_command_argv_internal (new_line, (char **) NULL,
-                                                  (char *) 0, (char *) 0);
+                                                  (char *) 0, (char *) 0,
+                                                  (char *) 0);
 #ifdef  __MSDOS__
     else
       {
@@ -2262,6 +2303,10 @@ construct_command_argv_internal (line, restp, shell, ifs)
                new_line + shell_len + sizeof (minus_c) - 1, line_len);
       new_argv[0][line_len] = '\0';
       }
+#else
+    else
+      fatal("%s (line %d) Invalid shell context (!unixy && !batch_mode_shell)\n",
+            __FILE__, __LINE__);
 #endif
   }
 #endif /* ! AMIGA */
@@ -2283,9 +2328,10 @@ construct_command_argv_internal (line, restp, shell, ifs)
    variable expansion for $(SHELL) and $(IFS).  */
 
 char **
-construct_command_argv (line, restp, file)
+construct_command_argv (line, restp, file, batch_filename_ptr)
      char *line, **restp;
      struct file *file;
+     char** batch_filename_ptr;
 {
   char *shell, *ifs;
   char **argv;
@@ -2311,7 +2357,7 @@ construct_command_argv (line, restp, file)
     warn_undefined_variables_flag = save;
   }
 
-  argv = construct_command_argv_internal (line, restp, shell, ifs);
+  argv = construct_command_argv_internal (line, restp, shell, ifs, batch_filename_ptr);
 
   free (shell);
   free (ifs);
diff --git a/job.h b/job.h
index ca7ad1d..eaac492 100644 (file)
--- a/job.h
+++ b/job.h
@@ -44,6 +44,7 @@ struct child
 
     unsigned int good_stdin:1; /* Nonzero if this child has a good stdin.  */
     unsigned int deleted:1;    /* Nonzero if targets have been deleted.  */
+       char* sh_batch_file; /* used to execute shell commands via scripts */
   };
 
 extern struct child *children;
@@ -52,7 +53,7 @@ extern void new_job PARAMS ((struct file *file));
 extern void reap_children PARAMS ((int block, int err));
 extern void start_waiting_jobs PARAMS ((void));
 
-extern char **construct_command_argv PARAMS ((char *line, char **restp, struct file *file));
+extern char **construct_command_argv PARAMS ((char *line, char **restp, struct file *file, char** batch_file));
 #ifdef VMS
 extern int child_execute_job PARAMS ((char *argv, struct child *child));
 #else
diff --git a/main.c b/main.c
index 0cf58fb..dcffa37 100644 (file)
--- a/main.c
+++ b/main.c
@@ -1,5 +1,5 @@
 /* Argument parsing and main program of GNU Make.
-Copyright (C) 1988,89,90,91,94,95,96,97 Free Software Foundation, Inc.
+Copyright (C) 1988,89,90,91,94,95,96,97,98 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
 GNU Make is free software; you can redistribute it and/or modify
@@ -180,7 +180,6 @@ int print_version_flag = 0;
 
 static struct stringlist *makefiles = 0;
 
-
 /* Number of job slots (commands that can be run at once).  */
 
 unsigned int job_slots = 1;
@@ -532,7 +531,98 @@ handle_runtime_exceptions( struct _EXCEPTION_POINTERS *exinfo )
   return EXCEPTION_CONTINUE_SEARCH;
 #else
   exit(255);
+  return (255); /* not reached */
+#endif
+}
+
+/*
+ * On WIN32 systems we don't have the luxury of a /bin directory that
+ * is mapped globally to every drive mounted to the system. Since make could
+ * be invoked from any drive, and we don't want to propogate /bin/sh
+ * to every single drive. Allow ourselves a chance to search for
+ * a value for default shell here (if the default path does not exist).
+ */
+
+int
+find_and_set_default_shell(char *token)
+{
+  int sh_found = 0;
+  char* search_token;
+  PATH_VAR(sh_path);
+  extern char *default_shell;
+
+  if (!token)
+    search_token = default_shell;
+  else
+    search_token = token;
+
+  if (!no_default_sh_exe &&
+      (token == NULL || !strcmp(search_token, default_shell))) {
+    /* no new information, path already set or known */
+    sh_found = 1;
+  } else if (file_exists_p(search_token)) {
+    /* search token path was found */
+    sprintf(sh_path, "%s", search_token);
+    default_shell = strdup(w32ify(sh_path,0));
+    if (debug_flag)
+      printf("find_and_set_shell setting default_shell = %s\n", default_shell);
+    sh_found = 1;
+  } else {
+    char *p;
+    struct variable *v = lookup_variable ("Path", 4);
+
+    /*
+     * Search Path for shell
+     */
+    if (v && v->value) {
+      char *ep;
+
+      p  = v->value;
+      ep = strchr(p, PATH_SEPARATOR_CHAR);
+
+      while (ep && *ep) {
+        *ep = '\0';
+
+        if (dir_file_exists_p(p, search_token)) {
+          sprintf(sh_path, "%s/%s", p, search_token);
+          default_shell = strdup(w32ify(sh_path,0));
+          sh_found = 1;
+          *ep = PATH_SEPARATOR_CHAR;
+
+          /* terminate loop */
+          p += strlen(p);
+        } else {
+          *ep = PATH_SEPARATOR_CHAR;
+           p = ++ep;
+        }
+
+        ep = strchr(p, PATH_SEPARATOR_CHAR);
+      }
+
+      /* be sure to check last element of Path */
+      if (p && *p && dir_file_exists_p(p, search_token)) {
+          sprintf(sh_path, "%s/%s", p, search_token);
+          default_shell = strdup(w32ify(sh_path,0));
+          sh_found = 1;
+      }
+
+      if (debug_flag && sh_found)
+        printf("find_and_set_shell path search set default_shell = %s\n", default_shell);
+    }
+  }
+
+  /* naive test */
+  if (!unixy_shell && sh_found &&
+      (strstr(default_shell, "sh") || strstr(default_shell, "SH"))) {
+    unixy_shell = 1;
+    batch_mode_shell = 0;
+  }
+
+#ifdef BATCH_MODE_ONLY_SHELL
+  batch_mode_shell = 1;
 #endif
+
+  return (sh_found);
 }
 #endif  /* WINDOWS32 */
 
@@ -556,17 +646,21 @@ main (argc, argv, envp)
 int main (int argc, char ** argv)
 #endif
 {
+  static char *stdin_nm = 0;
   register struct file *f;
   register unsigned int i;
   char **p;
   struct dep *read_makefiles;
   PATH_VAR (current_directory);
 #ifdef WINDOWS32
-  extern int no_default_sh_exe;
   char *unix_path = NULL;
   char *windows32_path = NULL;
 
   SetUnhandledExceptionFilter(handle_runtime_exceptions);
+
+  /* start off assuming we have no shell */
+  unixy_shell = 0;
+  no_default_sh_exe = 1;
 #endif
 
   default_goal_file = 0;
@@ -708,20 +802,28 @@ int main (int argc, char ** argv)
 #ifndef _AMIGA
   for (i = 0; envp[i] != 0; ++i)
     {
+      int do_not_define;
       register char *ep = envp[i];
+
+      /* by default, everything gets defined and exported */
+      do_not_define = 0;
+
       while (*ep != '=')
-       ++ep;
+        ++ep;
 #ifdef WINDOWS32
       if (!unix_path && !strncmp(envp[i], "PATH=", 5))
         unix_path = ep+1;
-      if (!windows32_path && !strncmp(envp[i], "Path=", 5))
+      else if (!windows32_path && !strnicmp(envp[i], "Path=", 5)) {
+        do_not_define = 1; /* it gets defined after loop exits */
         windows32_path = ep+1;
+      }
 #endif
       /* The result of pointer arithmetic is cast to unsigned int for
         machines where ptrdiff_t is a different size that doesn't widen
         the same.  */
-      define_variable (envp[i], (unsigned int) (ep - envp[i]),
-                      ep + 1, o_env, 1)
+      if (!do_not_define)
+        define_variable (envp[i], (unsigned int) (ep - envp[i]),
+                         ep + 1, o_env, 1)
        /* Force exportation of every variable culled from the environment.
           We used to rely on target_environment's v_default code to do this.
           But that does not work for the case where an environment variable
@@ -731,6 +833,16 @@ int main (int argc, char ** argv)
     }
 #ifdef WINDOWS32
     /*
+     * Make sure that this particular spelling of 'Path' is available
+     */
+    if (windows32_path)
+      define_variable("Path", 4, windows32_path, o_env, 1)->export = v_export;
+    else if (unix_path)
+      define_variable("Path", 4, unix_path, o_env, 1)->export = v_export;
+    else
+      define_variable("Path", 4, "", o_env, 1)->export = v_export;
+
+    /*
      * PATH defaults to Path iff PATH not found and Path is found.
      */
     if (!unix_path && windows32_path)
@@ -840,7 +952,7 @@ int main (int argc, char ** argv)
          if (! v->recursive)
            ++len;
          ++len;
-         len += 2 * strlen (v->value);
+         len += 3 * strlen (v->value);
        }
 
       /* Now allocate a buffer big enough and fill it.  */
@@ -899,68 +1011,8 @@ int main (int argc, char ** argv)
    * lookups to fail because the current directory (.) was pointing
    * at the wrong place when it was first evaluated.
    */
+   no_default_sh_exe = !find_and_set_default_shell(NULL);
 
-  /*
-   * On Windows/NT, we don't have the luxury of a /bin directory that
-   * is mapped globally to every drive mounted to the system. Since make could
-   * be invoked from any drive, and we don't want to propogate /bin/sh
-   * to every single drive. Allow ourselves a chance to search for
-   * a value for default shell here (if the default path does not exist).
-   *
-   * The value of default_shell is set here, but it could get reset after
-   * the Makefiles are read in. See logic below where SHELL is checked
-   * after the call to read_all_makefiles() completes.
-   *
-   * The reason SHELL is set here is so that macros can be safely evaluated
-   * as makefiles are read in (some macros require $SHELL).
-   */
-
-  {
-    extern char *default_shell;
-
-    if (!file_exists_p(default_shell)) {
-      char *p;
-      struct variable *v = lookup_variable ("Path", 4);
-
-      /*
-       * Try and make sure we have a full path to default_shell before
-       * we parse makefiles.
-       */
-      if (v && v->value) {
-        PATH_VAR(sh_path);
-        char *ep;
-
-        p  = v->value;
-        ep = strchr(p, PATH_SEPARATOR_CHAR);
-
-        while (ep && *ep) {
-          *ep = '\0';
-
-          if (dir_file_exists_p(p, default_shell)) {
-            sprintf(sh_path, "%s/%s", p, default_shell);
-            default_shell = strdup(w32ify(sh_path,0));
-            no_default_sh_exe = 0;
-            *ep = PATH_SEPARATOR_CHAR;
-
-            /* terminate loop */
-            p += strlen(p);
-          } else {
-            *ep = PATH_SEPARATOR_CHAR;
-             p = ++ep;
-          }
-
-          ep = strchr(p, PATH_SEPARATOR_CHAR);
-        }
-
-        /* be sure to check last element of Path */
-        if (p && *p && dir_file_exists_p(p, default_shell)) {
-            sprintf(sh_path, "%s/%s", p, default_shell);
-            default_shell = strdup(w32ify(sh_path,0));
-            no_default_sh_exe = 0;
-        }
-      }
-    }
-  }
 #endif /* WINDOWS32 */
   /* Figure out the level of recursion.  */
   {
@@ -1007,6 +1059,8 @@ int main (int argc, char ** argv)
        starting_directory = current_directory;
     }
 
+  (void) define_variable ("CURDIR", 6, current_directory, o_default, 0);
+
   /* Read any stdin makefiles into temporary files.  */
 
   if (makefiles != 0)
@@ -1034,6 +1088,9 @@ int main (int argc, char ** argv)
            (void) tmpnam (name);
 #endif
 
+            if (stdin_nm)
+              fatal("Makefile from standard input specified twice.");
+
            outfile = fopen (name, "w");
            if (outfile == 0)
              pfatal_with_name ("fopen (temporary file)");
@@ -1044,9 +1101,6 @@ int main (int argc, char ** argv)
                if (n > 0 && fwrite (buf, 1, n, outfile) != n)
                  pfatal_with_name ("fwrite (temporary file)");
              }
-           /* Try to make sure we won't remake the temporary
-              file when we are re-exec'd.  Kludge-o-matic!  */
-           fprintf (outfile, "%s:;\n", name);
            (void) fclose (outfile);
 
            /* Replace the name that read_all_makefiles will
@@ -1060,14 +1114,15 @@ int main (int argc, char ** argv)
            }
 
            /* Make sure the temporary file will not be remade.  */
-           f = enter_file (savestring (name, sizeof name - 1));
+            stdin_nm = savestring (name, sizeof(name) -1);
+           f = enter_file (stdin_nm);
            f->updated = 1;
            f->update_status = 0;
            f->command_state = cs_finished;
-           /* Let it be removed when we're done.  */
-           f->intermediate = 1;
-           /* But don't mention it.  */
-           f->dontcare = 1;
+           /* Can't be intermediate, or it'll be removed too early for
+               make re-exec.  */
+           f->intermediate = 0;
+           f->dontcare = 0;
          }
     }
 
@@ -1107,46 +1162,21 @@ int main (int argc, char ** argv)
 
   define_makeflags (0, 0);
 
-#ifdef WINDOWS32
-  /*
-   * Now that makefiles are parsed, see if a Makefile gave a
-   * value for SHELL and use that for default_shell instead if
-   * that filename exists. This should speed up the
-   * construct_argv_internal() function by avoiding unnecessary
-   * recursion.
-   */
-  {
-    struct variable *v = lookup_variable("SHELL", 5);
-    extern char* default_shell;
+  /* Define the default variables.  */
+  define_default_variables ();
 
-    /*
-     * to change value:
-     *
-     * SHELL must be found, SHELL must be set, value of SHELL
-     * must be different from current value, and the
-     * specified file must exist. Whew!
-     */
-    if (v != 0 && *v->value != '\0') {
-      char *fn = recursively_expand(v);
+  /* Read all the makefiles.  */
 
-      if (fn && strcmp(fn, default_shell) && file_exists_p(fn)) {
-        char *p;
+  default_file = enter_file (".DEFAULT");
 
-        default_shell = fn;
+  read_makefiles
+    = read_all_makefiles (makefiles == 0 ? (char **) 0 : makefiles->list);
 
-        /* if Makefile says SHELL is sh.exe, believe it */
-        if (strstr(default_shell, "sh.exe"))
-               no_default_sh_exe = 0;
+#ifdef WINDOWS32
+  /* look one last time after reading all Makefiles */
+  if (no_default_sh_exe)
+    no_default_sh_exe = !find_and_set_default_shell(NULL);
 
-        /*
-         * Convert from backslashes to forward slashes so
-         * create_command_line_argv_internal() is not confused.
-         */
-        for (p = strchr(default_shell, '\\'); p; p = strchr(default_shell, '\\'))
-          *p = '/';
-      }
-    }
-  }
   if (no_default_sh_exe && job_slots != 1) {
     error("Do not specify -j or --jobs if sh.exe is not available.");
     error("Resetting make for single job mode.");
@@ -1154,16 +1184,6 @@ int main (int argc, char ** argv)
   }
 #endif /* WINDOWS32 */
 
-  /* Define the default variables.  */
-  define_default_variables ();
-
-  /* Read all the makefiles.  */
-
-  default_file = enter_file (".DEFAULT");
-
-  read_makefiles
-    = read_all_makefiles (makefiles == 0 ? (char **) 0 : makefiles->list);
-
 #ifdef __MSDOS__
   /* We need to know what kind of shell we will be using.  */
   {
@@ -1295,7 +1315,7 @@ int main (int argc, char ** argv)
                      /* Free the storage.  */
                      free ((char *) d);
 
-                     d = last == 0 ? 0 : last->next;
+                     d = last == 0 ? read_makefiles : last->next;
 
                      break;
                    }
@@ -1416,24 +1436,14 @@ int main (int argc, char ** argv)
                  }
            }
 
-          /* Add -o options for all makefiles that were remade */
-          {
-            register unsigned int i;
-            struct dep *d;
-
-            for (i = argc+1, d = read_makefiles; d != 0; d = d->next)
-              i += d->file->updated != 0;
-
-            nargv = (char **)xmalloc(i * sizeof(char *));
-            bcopy(argv, nargv, argc * sizeof(char *));
-
-            for (i = 0, d = read_makefiles; d != 0; ++i, d = d->next)
-              {
-                if (d->file->updated)
-                  nargv[nargc++] = concat("-o", dep_name(d), "");
-              }
-            nargv[nargc] = 0;
-          }
+          /* Add -o option for the stdin temporary file, if necessary.  */
+          if (stdin_nm)
+            {
+              nargv = (char **)xmalloc((nargc + 2) * sizeof(char *));
+              bcopy(argv, nargv, argc * sizeof(char *));
+              nargv[nargc++] = concat("-o", stdin_nm, "");
+              nargv[nargc] = 0;
+            }
 
          if (directories != 0 && directories->idx > 0)
            {
@@ -1507,6 +1517,11 @@ int main (int argc, char ** argv)
   /* Set up `MAKEFLAGS' again for the normal targets.  */
   define_makeflags (1, 0);
 
+  /* If there is a temp file from reading a makefile from stdin, get rid of
+     it now.  */
+  if (stdin_nm && unlink(stdin_nm) < 0 && errno != ENOENT)
+    perror_with_name("unlink (temporary file): ", stdin_nm);
+
   {
     int status;
 
@@ -2324,12 +2339,12 @@ print_version ()
     printf ("-%s", remote_description);
 
   printf (", by Richard Stallman and Roland McGrath.\n\
-%sCopyright (C) 1988, 89, 90, 91, 92, 93, 94, 95, 96, 97\n\
+%sCopyright (C) 1988, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98\n\
 %s\tFree Software Foundation, Inc.\n\
 %sThis is free software; see the source for copying conditions.\n\
 %sThere is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n\
 %sPARTICULAR PURPOSE.\n\n\
-%sReport bugs to <bug-gnu-utils@prep.ai.mit.edu>.\n\n",
+%sReport bugs to <bug-make@gnu.org>.\n\n",
          precede, precede, precede, precede, precede, precede);
 
   printed_version = 1;
@@ -2373,13 +2388,6 @@ die (status)
 
       dying = 1;
 
-      /* Try to move back to the original directory.  This is essential on
-        MS-DOS (where there is really only one process), and on Unix it
-        puts core files in the original directory instead of the -C
-        directory.  */
-      if (directory_before_chdir != 0)
-       chdir (directory_before_chdir);
-
       if (print_version_flag)
        print_version ();
 
@@ -2396,6 +2404,14 @@ die (status)
       if (print_data_base_flag)
        print_data_base ();
 
+      /* Try to move back to the original directory.  This is essential on
+        MS-DOS (where there is really only one process), and on Unix it
+        puts core files in the original directory instead of the -C
+        directory.  Must wait until after remove_intermediates(), or unlinks
+         of relative pathnames fail.  */
+      if (directory_before_chdir != 0)
+       chdir (directory_before_chdir);
+
       log_working_directory (0);
     }
 
@@ -2410,7 +2426,7 @@ log_working_directory (entering)
      int entering;
 {
   static int entered = 0;
-  char *message = entering ? "Entering" : "Leaving";
+  char *msg = entering ? "Entering" : "Leaving";
 
   /* Print nothing without the flag.  Don't print the entering message
      again if we already have.  Don't print the leaving message if we
@@ -2424,9 +2440,9 @@ log_working_directory (entering)
     fputs ("# ", stdout);
 
   if (makelevel == 0)
-    printf ("%s: %s ", program, message);
+    printf ("%s: %s ", program, msg);
   else
-    printf ("%s[%u]: %s ", program, makelevel, message);
+    printf ("%s[%u]: %s ", program, makelevel, msg);
 
   if (starting_directory == 0)
     puts ("an unknown directory");
index 5aab784..0c9aa9b 100644 (file)
@@ -7,7 +7,8 @@
 globsrc := $(wildcard glob/*.c)
 globhdr := $(wildcard glob/*.h)
 
-TEMPLATES = README config.ami configh.dos config.h.W32 config.h-vms
+TEMPLATES = README README.DOS config.ami configh.dos config.h.W32 config.h-vms
+MTEMPLATES = Makefile.DOS SMakefile
 
 # General rule for turning a .template into a regular file.
 #
@@ -18,9 +19,9 @@ $(TEMPLATES) : % : %.template configure.in
          $< > $@
        chmod a-w $@
 
-# Construct Makefile.DOS
+# Construct Makefiles by adding on dependencies, etc.
 #
-Makefile.DOS: Makefile.DOS.template Makefile.am configure.in
+$(MTEMPLATES) : % : %.template .dep_segment Makefile.am maintMakefile
        rm -f $@
        sed -e 's@%VERSION%@$(VERSION)@' \
            -e 's@%PROGRAMS%@$(bin_PROGRAMS)@' \
@@ -29,28 +30,44 @@ Makefile.DOS: Makefile.DOS.template Makefile.am configure.in
            -e 's@%GLOB_SOURCES%@$(globsrc) $(globhdr)@' \
            -e 's@%GLOB_OBJECTS%@$(globsrc:glob/%.c=%.o)@' \
          $< > $@
+       echo >>$@; echo '# --------------- DEPENDENCIES' >>$@; echo '#' >>$@; \
+         cat $(word 2,$^) >>$@
+       chmod a-w $@
+
+NMakefile: NMakefile.template .dep_segment Makefile.am maintMakefile
+       rm -f $@
+       cp $< $@
+       echo >>$@; echo '# --------------- DEPENDENCIES' >>$@; echo '#' >>$@; \
+         sed 's/^\([^ ]*\)\.o:/$$(OUTDIR)\/\1.obj:/' $(word 2,$^) >>$@
        chmod a-w $@
 
 # Construct build.sh.in
 #
-build.sh.in: build.template Makefile.am
+build.sh.in: build.template Makefile.am maintMakefile
        rm -f $@
        sed -e 's@%objs%@$(filter-out remote-%, $(make_OBJECTS)\
               $(patsubst %.c,%.o,$(globsrc)))@' \
            $< > $@
        chmod a-w+x $@
 
+# Use automake to build a dependency list file, for "foreign" makefiles like
+# Makefile.DOS.
+#
+.dep_segment: Makefile.am maintMakefile $(DEP_FILES)
+       $(AUTOMAKE) --generate-deps --build-dir=. --srcdir-name=.
+
 # We clean everything here.  The GNU standards for makefile conventions say
 # you shouldn't remove configure, etc., but this makefile is only available
 # in a full development distribution, so they'll only be removed then.
 #
 # And _I_ want them to be removed ;)
 #
-maintFILES = configure aclocal.m4 config.h.in Makefile.in \
-            stamp-h.in glob/stamp-h.in
+maintFILES = configure aclocal.m4 config.h.in Makefile.in stamp-h.in \
+            glob/configure glob/aclocal.m4 glob/config.h.in glob/Makefile.in \
+            glob/stamp-h.in
 
-MAINTAINERCLEANFILES =  $(TEMPLATES) missing Makefile.DOS build.sh.in \
-                       $(maintFILES)
+MAINTAINERCLEANFILES =  $(maintFILES) $(TEMPLATES) $(MTEMPLATES) NMakefile \
+                       missing build.sh.in .dep_segment
 
 # Put the alpha distribution files up for anonymous FTP.
 #
@@ -61,3 +78,9 @@ TARFILE       := $(distdir).tar.gz
 alpha: $(ALPHA) $(TARFILE)
        @rm -f $(ALPHA)/$(TARFILE)
        cp -p $(TARFILE) $(ALPHA)
+
+# This is needed because normal builds with GCC don't compile alloca.c, so
+# alloca.P doesn't get built :-/.
+#
+.deps/alloca.P: alloca.c
+       $(COMPILE) -M -o $@ $<
diff --git a/make.1 b/make.1
index 1bd37a7..ab6ba47 100644 (file)
--- a/make.1
+++ b/make.1
@@ -5,17 +5,16 @@ make \- GNU make utility to maintain groups of programs
 .B "make "
 [
 .B \-f
-makefile ] [ option ] ...
+.I makefile
+] [ option ] ...
 target ...
 .SH WARNING
 This man page 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
+.B make.info
+which is made from the Texinfo source file
 .BR make.texinfo .
 .SH DESCRIPTION
 .LP
@@ -24,7 +23,7 @@ The purpose of the
 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
+The 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
@@ -288,12 +287,7 @@ command on the given file before running
 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
+.I "The GNU Make Manual"
 .SH BUGS
 See the chapter `Problems and Bugs' in
 .I "The GNU Make Manual" .
diff --git a/make.h b/make.h
index d99ccd0..58a0ff2 100644 (file)
--- a/make.h
+++ b/make.h
@@ -86,11 +86,11 @@ extern int errno;
 #define POSIX
 #endif
 
-#ifdef HAVE_SYS_SIGLIST
-#ifndef SYS_SIGLIST_DECLARED
+#if defined (HAVE_SYS_SIGLIST) && !defined (SYS_SIGLIST_DECLARED)
 extern char *sys_siglist[];
 #endif
-#else
+
+#if !defined (HAVE_SYS_SIGLIST) || !defined (HAVE_STRSIGNAL)
 #include "signame.h"
 #endif
 
@@ -241,6 +241,11 @@ extern void bcopy ();
 extern char *strerror PARAMS ((int errnum));
 #endif
 
+#ifndef __attribute__
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
+#  define __attribute__(x)
+# endif
+#endif
 
 #ifdef __GNUC__
 #undef alloca
@@ -259,7 +264,7 @@ extern char *alloca ();
 #define streq(a, b) \
   ((a) == (b) || \
    (*(a) == *(b) && (*(a) == '\0' || !strcmp ((a) + 1, (b) + 1))))
-#ifdef _AMIGA
+#ifdef HAVE_CASE_INSENSITIVE_FS
 #define strieq(a, b) \
   ((a) == (b) || \
    (tolower(*(a)) == tolower(*(b)) && (*(a) == '\0' || !strcmpi ((a) + 1, (b) + 1))))
@@ -277,7 +282,7 @@ extern char *alloca ();
 /* Add to VAR the hashing value of C, one character in a name.  */
 #define        HASH(var, c) \
   ((var += (c)), (var = ((var) << 7) + ((var) >> 20)))
-#ifdef _AMIGA /* Fold filenames on #amiga */
+#ifdef HAVE_CASE_INSENSITIVE_FS /* Fold filenames */
 #define HASHI(var, c) \
   ((var += tolower((c))), (var = ((var) << 7) + ((var) >> 20)))
 #else
@@ -310,16 +315,23 @@ extern void sync_Path_environment(void);
 extern int kill(int pid, int sig);
 extern int safe_stat(char *file, struct stat *sb);
 extern char *end_of_token_w32();
-#endif
+extern int find_and_set_default_shell(char *token);
+
+/* indicates whether or not we have Bourne shell */
+extern int no_default_sh_exe;
+
+/* is default_shell unixy? */
+extern int unixy_shell;
+#endif  /* WINDOWS32 */
 \f
-extern void die ();
+extern void die () __attribute__ ((noreturn));
 extern void message ();
-extern void fatal ();
+extern void fatal () __attribute__ ((noreturn));
 extern void error ();
 extern void log_working_directory ();
 extern void makefile_error ();
-extern void makefile_fatal ();
-extern void pfatal_with_name ();
+extern void makefile_fatal () __attribute__ ((noreturn));
+extern void pfatal_with_name () __attribute__ ((noreturn));
 extern void perror_with_name ();
 extern char *savestring ();
 extern char *concat ();
@@ -413,6 +425,9 @@ extern int print_directory_flag, warn_undefined_variables_flag;
 extern int posix_pedantic;
 extern int clock_skew_detected;
 
+/* can we run commands via 'sh -c xxx' or must we use batch files? */
+extern int batch_mode_shell;
+
 extern unsigned int job_slots;
 #ifndef NO_FLOAT
 extern double max_load_average;
index 3c7e4d3..05d0746 100644 (file)
@@ -8,12 +8,12 @@
 @c FSF publishers: format makebook.texi instead of using this file directly.
 
 @set RCSID $Id$
-@set EDITION 0.51
-@set VERSION 3.76 Beta
-@set UPDATED 26 Aug 1997
-@set UPDATE-MONTH Aug 1997
+@set EDITION 0.52
+@set VERSION 3.77
+@set UPDATED 20 May 1998
+@set UPDATE-MONTH May 1998
 @comment The ISBN number might need to change on next publication.
-@set ISBN 1-882114-78-7 @c CHANGE THIS BEFORE PRINTING AGAIN! --roland 9may96
+@set ISBN 1-882114-80-9 @c CHANGE THIS BEFORE PRINTING AGAIN! --psmith 16jul98
 
 @c finalout
 
@@ -27,7 +27,7 @@
 @ifinfo
 @dircategory The GNU make utility
 @direntry
-     * GNU make: (make.info).           The GNU make utility.
+     * Make: (make.info).               The GNU make utility.
 @end direntry
 
 This file documents the GNU Make utility, which determines
@@ -37,7 +37,7 @@ and issues the commands to recompile them.
 This is Edition @value{EDITION}, last updated @value{UPDATED},
 of @cite{The GNU Make Manual}, for @code{make}, Version @value{VERSION}.
 
-Copyright (C) 1988, '89, '90, '91, '92, '93, '94, '95, '96, '97
+Copyright (C) 1988, '89, '90, '91, '92, '93, '94, '95, '96, '97, '98
        Free Software Foundation, Inc.
 
 Permission is granted to make and distribute verbatim copies of
@@ -68,7 +68,7 @@ by the Free Software Foundation.
 @titlepage
 @title GNU Make
 @subtitle A Program for Directing Recompilation
-@subtitle Edition @value{EDITION}, for @code{make} Version @value{VERSION}.
+@subtitle GNU @code{make} Version @value{VERSION}.
 @subtitle @value{UPDATE-MONTH}
 @author Richard M. Stallman and Roland McGrath
 @page
@@ -107,9 +107,9 @@ The GNU @code{make} utility automatically determines which pieces of a
 large program need to be recompiled, and issues the commands to
 recompile them.@refill
 
-This is Edition @value{EDITION} of the @cite{GNU Make Manual},
-last updated @value{UPDATED}
-for @code{make} Version @value{VERSION}.@refill
+This edition of the @cite{GNU Make Manual},
+last updated @value{UPDATED},
+documents GNU @code{make} Version @value{VERSION}.@refill
 
 This manual describes @code{make} and contains the following chapters:@refill
 @end ifinfo
@@ -132,6 +132,7 @@ This manual describes @code{make} and contains the following chapters:@refill
 * Missing::                     What GNU @code{make} lacks from other @code{make}s.
 * Makefile Conventions::        Conventions for makefiles in GNU programs.
 * Quick Reference::             A quick reference for experienced users.
+* Make Errors::                 A list of common errors generated by @code{make}.
 * Complex Makefile::            A real example of a straightforward,
                                  but nontrivial, makefile.
 * Concept Index::               Index of Concepts
@@ -425,17 +426,10 @@ send us the makefile and the exact results @code{make} gave you.  Also
 say what you expected to occur; this will help us decide whether the
 problem was really in the documentation.
 
-Once you've got a precise problem, please send electronic mail either
-through the Internet or via UUCP:
+Once you've got a precise problem, please send electronic mail to:
 
 @example
-@group
-@r{Internet address:}
-    bug-gnu-utils@@prep.ai.mit.edu
-
-@r{UUCP path:}
-    mit-eddie!prep.ai.mit.edu!bug-gnu-utils
-@end group
+    bug-make@@gnu.org
 @end example
 
 @noindent
@@ -3228,6 +3222,14 @@ You can write recursive @code{make} commands just by copying this example,
 but there are many things to know about how they work and why, and about
 how the sub-@code{make} relates to the top-level @code{make}.
 
+For your convenience, GNU @code{make} sets the variable @code{CURDIR} to
+the pathname of the current working directory for you.  If @code{-C} is
+in effect, it will contain the path of the new directory, not the
+original.  The value has the same precedence it would have if it were
+set in the makefile (by default, an environment variable @code{CURDIR}
+will not override this value).  Note that setting this variable has no
+effect on the operation of @code{make}
+
 @menu
 * MAKE Variable::               The special effects of using @samp{$(MAKE)}.
 * Variables/Recursion::         How to communicate variables to a sub-@code{make}.
@@ -3828,6 +3830,10 @@ they have particular specialized uses.  @xref{Automatic, ,Automatic Variables}.
 * Defining::                    An alternate way to set a variable
                                   to a verbatim string.
 * Environment::                 Variable values can come from the environment.
+* Target-specific::             Variable values can be defined on a per-target
+                                  basis.
+* Pattern-specific::            Target-specific variable values can be applied
+                                  to a group of targets that match a pattern.
 * Automatic::                   Some special variables have predefined
                                   meanings for use with implicit rules.
 @end menu
@@ -4056,6 +4062,30 @@ Here the value of the variable @code{dir} is @w{@samp{/foo/bar    }}
 (with four trailing spaces), which was probably not the intention.
 (Imagine something like @w{@samp{$(dir)/file}} with this definition!)
 
+@cindex conditional variable assignment
+@cindex variables, conditional assignment
+@cindex ?=
+There is another assignment operator for variables, @samp{?=}.  This
+is called a conditional variable assignment operator, because it only
+has an effect if the variable is not yet defined.  This statement:
+
+@example
+FOO ?= bar
+@end example
+
+@noindent
+is exactly equivalent to this
+(@pxref{Origin Function, ,The @code{origin} Function}):
+
+@example
+ifeq ($(origin FOO), undefined)
+  FOO = bar
+endif
+@end example
+
+Note that a variable set to an empty value is still defined, so
+@samp{?=} will not set that variable.
+
 @node Advanced, Values, Flavors, Using Variables
 @section Advanced Features for Reference to Variables
 @cindex reference to variables
@@ -4353,6 +4383,7 @@ Several variables have constant initial values.
 @cindex variables, setting
 @cindex =
 @cindex :=
+@cindex ?=
 
 To set a variable from the makefile, write a line starting with the
 variable name followed by @samp{=} or @samp{:=}.  Whatever follows the
@@ -4389,6 +4420,24 @@ Several special variables are set
 automatically to a new value for each rule; these are called the
 @dfn{automatic} variables (@pxref{Automatic, ,Automatic Variables}).
 
+If you'd like a variable to be set to a value only if it's not already
+set, then you can use the shorthand operator @samp{?=} instead of
+@samp{=}.  These two settings of the variable @samp{FOO} are identical
+(@pxref{Origin Function, ,The @code{origin} Function}):
+
+@example
+FOO ?= bar
+@end example
+
+@noindent
+and
+
+@example
+ifeq ($(origin FOO), undefined)
+FOO = bar
+endif
+@end example
+
 @node Appending, Override Directive, Setting, Using Variables
 @section Appending More Text to Variables
 @cindex +=
@@ -4646,7 +4695,7 @@ endef
 @noindent
 @xref{Override Directive, ,The @code{override} Directive}.
 
-@node Environment,  , Defining, Using Variables
+@node Environment, Target-specific, Defining, Using Variables
 @section Variables from the Environment
 
 @cindex variables, environment
@@ -4690,6 +4739,113 @@ affect @code{make}.  So @code{make} ignores the environment value of
 usually not set.  @xref{Execution, ,Special handling of SHELL on
 MS-DOS}.)@refill
 
+@node Target-specific, Pattern-specific, Environment, Using Variables
+@section Target-specific Variable Values
+@cindex target-specific variables
+@cindex variables, target-specific
+
+Variable values in @code{make} are usually global; that is, they are the
+same regardless of where they are evaluated (unless they're reset, of
+course).  One exception to that is automatic variables
+(@pxref{Automatic, ,Automatic Variables}).
+
+The other exception is @dfn{target-specific variable values}.  This
+feature allows you to define different values for the same variable,
+based on the target that @code{make} is currently building.  As with
+automatic variables, these values are only available within the context
+of a target's command script (and in other target-specific assignments).
+
+Set a target-specific variable value like this:
+
+@example
+@var{target} @dots{} : @var{variable-assignment}
+@end example
+
+@noindent
+or like this:
+
+@example
+@var{target} @dots{} : override @var{variable-assignment}
+@end example
+
+Multiple @var{target} values create a target-specific variable value for
+each member of the target list individually.
+
+The @var{variable-assignment} can be any valid form of assignment;
+recursive (@samp{=}), static (@samp{:=}), appending (@samp{+=}), or
+conditional (@samp{?=}).  All variables that appear within the
+@var{variable-assignment} are evaluated within the context of the
+target: thus, any previously-defined target-specific variable values
+will be in effect.  Note that this variable is actually distinct from
+any ``global'' value: the two variables do not have to have the same
+flavor (recursive vs. static).
+
+Target-specific variables have the same priority as any other makefile
+variable.  Variables provided on the command-line (and in the
+environment if the @samp{-e} option is in force) will take precedence.
+Specifying the @code{override} directive will allow the target-specific
+variable value to be preferred.
+
+There is one more special feature of target-specific variables: when you
+define a target-specific variable, that variable value is also in effect
+for all dependencies of this target (unless those dependencies override
+it with their own target-specific variable value).  So, for example, a
+statement like this:
+
+@example
+prog : CFLAGS = -g
+prog : prog.o foo.o bar.o
+@end example
+
+@noindent
+will set @code{CFLAGS} to @samp{-g} in the command script for
+@file{prog}, but it will also set @code{CFLAGS} to @samp{-g} in the
+command scripts that create @file{prog.o}, @file{foo.o}, and
+@file{bar.o}, and any command scripts which create their dependencies.
+
+@node Pattern-specific,  , Target-specific, Using Variables
+@section Pattern-specific Variable Values
+@cindex pattern-specific variables
+@cindex variables, pattern-specific
+
+In addition to target-specific variable values (@pxref{Target-specific,
+,Target-specific Variable Values}), GNU @code{make} supports
+pattern-specific variable values.  In this form, a variable is defined
+for any target that matches the pattern specified.  Variables defined in
+this way are searched after any target-specific variables defined
+explicitly for that target, and before target-specific variables defined
+for the parent target.
+
+Set a pattern-specific variable value like this:
+
+@example
+@var{pattern} @dots{} : @var{variable-assignment}
+@end example
+
+@noindent
+or like this:
+
+@example
+@var{pattern} @dots{} : override @var{variable-assignment}
+@end example
+
+@noindent
+where @var{pattern} is a %-pattern.  As with target-specific variable
+values, multiple @var{pattern} values create a pattern-specific variable
+value for each pattern individually.  The @var{variable-assignment} can
+be any valid form of assignment.  Any command-line variable setting will
+take precedence, unless @code{override} is specified.
+
+For example:
+
+@example
+%.o : CFLAGS = -O
+@end example
+
+@noindent
+will assign @code{CFLAGS} the value of @samp{-O} for all targets
+matching the pattern @code{%.o}.
+
 @node Conditionals, Functions, Using Variables, Top
 @chapter Conditional Parts of Makefiles
 
@@ -6396,7 +6552,10 @@ pattern rules (@pxref{Pattern Rules, ,Defining and Redefining Pattern
 Rules}).  The @samp{-r} option also clears out the default list of
 suffixes for suffix rules (@pxref{Suffix Rules, ,Old-Fashioned Suffix
 Rules}).  But you can still define your own suffixes with a rule for
-@code{.SUFFIXES}, and then define your own suffix rules.
+@code{.SUFFIXES}, and then define your own suffix rules.  Note that only
+@emph{rules} are affected by the @code{-r} option; default variables
+remain in effect (@pxref{Implicit Variables, ,Variables Used by Implicit
+Rules}).
 
 @item -s
 @cindex @code{-s}
@@ -8546,7 +8705,7 @@ special treatment.
 @comment included by standards.texi.
 @include make-stds.texi
 
-@node Quick Reference, Complex Makefile, Makefile Conventions, Top
+@node Quick Reference, Make Errors, Makefile Conventions, Top
 @appendix Quick Reference
 
 This appendix summarizes the directives, text manipulation functions,
@@ -8821,12 +8980,136 @@ The targets given to @code{make} on the command line.  Setting this
 variable has no effect on the operation of @code{make}.@*
 @xref{Goals, ,Arguments to Specify the Goals}.
 
+@item CURDIR
+
+Set to the pathname of the current working directory (after all
+@code{-C} options are processed, if any).  Setting this variable has no
+effect on the operation of @code{make}.@*
+@xref{Recursion, ,Recursive Use of @code{make}}.
+
 @item SUFFIXES
 
 The default list of suffixes before @code{make} reads any makefiles.
 @end table
 
-@node Complex Makefile, Concept Index, Quick Reference, Top
+@node Make Errors, Complex Makefile, Quick Reference, Top
+@comment  node-name,  next,  previous,  up
+@appendix Errors Generated by Make
+
+Here is a list of the most common errors you might see generated by
+@code{make}, and some information about what they mean and how to fix
+them.
+
+Sometimes @code{make} errors are not fatal, especially in the presence
+of a @code{-} prefix on a command script line, or the @code{-k} command
+line option.  Errors that are fatal are prefixed with the string
+@code{***}.
+
+Error messages are all either prefixed with the name of the program
+(usually @samp{make}), or, if the error is found in a makefile, the name
+of the file and linenumber containing the problem.
+
+In the table below, these common prefixes are left off.
+
+@table @samp
+
+@item [@var{foo}] Error @var{NN}
+@itemx [@var{foo}] @var{signal description}
+These errors are not really @code{make} errors at all.  They mean that a
+program that @code{make} invoked as part of a command script returned a
+non-0 error code (@samp{Error @var{NN}}), which @code{make} interprets
+as failure, or it exited in some other abnormal fashion (with a
+signal of some type).
+
+If no @code{***} is attached to the message, then the subprocess failed
+but the rule in the makefile was prefixed with the @code{-} special
+character, so @code{make} ignored the error.
+
+@item missing separator.  Stop.
+This is @code{make}'s generic ``Huh?'' error message.  It means that
+@code{make} was completely unsuccessful at parsing this line of your
+makefile.  It basically means ``syntax error''.
+
+One of the most common reasons for this message is that you (or perhaps
+your oh-so-helpful editor, as is the case with many MS-Windows editors)
+have attempted to indent your command scripts with spaces instead of a
+TAB character.  Remember that every line in the command script must
+begin with a TAB character.  Eight spaces do not count.
+
+@item commands commence before first target.  Stop.
+@itemx missing rule before commands.  Stop.
+This means the first thing in the makefile seems to be part of a command
+script: it begins with a TAB character and doesn't appear to be a legal
+@code{make} command (such as a variable assignment).  Command scripts
+must always be associated with a target.
+
+The second form is generated if the line has a semicolon as the first
+non-whitespace character; @code{make} interprets this to mean you left
+out the "target: dependency" section of a rule.
+
+@item No rule to make target `@var{xxx}'.
+@itemx No rule to make target `@var{xxx}', needed by `@var{yyy}'.
+This means that @code{make} decided it needed to build a target, but
+then couldn't find any instructions in the makefile on how to do that,
+either explicit or implicit (including in the default rules database).
+
+If you want that file to be built, you will need to add a rule to your
+makefile describing how that target can be built.  Other possible
+sources of this problem are typos in the makefile (if that filename is
+wrong) or a corrupted source tree (if that file is not supposed to be
+built, but rather only a dependency).
+
+@item No targets specified and no makefile found.  Stop.
+@itemx No targets.  Stop.
+The former means that you didn't provide any targets to be built on the
+command line, and @code{make} couldn't find any makefiles to read in.
+The latter means that some makefile was found, but it didn't contain any
+default target and none was given on the command line.  GNU @code{make}
+has nothing to do in these situations.
+
+@item Makefile `@var{xxx}' was not found.
+@itemx Included makefile `@var{xxx}' was not found.
+A makefile specified on the command line (first form) or included
+(second form) was not found.
+
+@item warning: overriding commands for target `@var{xxx}'
+@itemx warning: ignoring old commands for target `@var{xxx}'
+GNU @code{make} allows commands to be specified only once per target
+(except for double-colon rules).  If you give commands for a target
+which already has been defined to have commands, this warning is issued
+and the second set of commands will overwrite the first set.
+
+@item Circular @var{xxx} <- @var{yyy} dependency dropped.
+This means that @code{make} detected a loop in the dependency graph:
+after tracing the dependency @var{yyy} of target @var{xxx}, and its
+dependencies, etc., one of them depended on @var{xxx} again.
+
+@item Recursive variable `@var{xxx}' references itself (eventually).  Stop.
+This means you've defined a normal (recursive) @code{make} variable
+@var{xxx} that, when its expanded, will refer to itself (@var{xxx}).
+This is not allowed; either use simply-expanded variables (@code{:=}) or
+use the append operator (@code{+=}).
+
+@item Unterminated variable reference.  Stop.
+This means you forgot to provide the proper closing parenthesis
+or brace in your variable or function reference.
+
+@item insufficient arguments to function `@var{xxx}'.  Stop.
+This means you haven't provided the requisite number of arguments for
+this function.  See the documentation of the function for a description
+of its arguments.
+
+@item missing target pattern.  Stop.
+@itemx multiple target patterns.  Stop.
+@itemx target pattern contains no `%'.  Stop.
+These are generated for malformed static pattern rules.  The first means
+there's no pattern in the target section of the rule, the second means
+there are multiple patterns in the target section, and the third means
+the target doesn't contain a pattern character (@code{%}).
+
+@end table
+
+@node Complex Makefile, Concept Index, Make Errors, Top
 @appendix Complex Makefile Example
 
 Here is the makefile for the GNU @code{tar} program.  This is a
index 23c720d..b7bb65c 100644 (file)
@@ -4,10 +4,37 @@ $!
 $! P1 is non-empty if you want to link with the VAXCRTL library instead
 $!    of the shareable executable
 $!
-$ def/nolog sys sys$library:
-$ filelist = "alloca ar arscan commands default dir expand file function implicit job main misc read remake remote-stub rule signame variable version vmsfunctions vmsify vpath [.glob]glob [.glob]fnmatch getopt getopt1"
+$! In case of problems with the install you might contact me at 
+$! zinser@decus.decus.de (preferred) or eurmpz@eur.sas.com
+$!
+$! Look for the compiler used
+$!
+$ lval = ""
+$ if f$search("SYS$SYSTEM:DECC$COMPILER.EXE").eqs.""
+$  then
+$   if f$trnlnm("SYS").eqs."" then def/nolog sys sys$library:
+$   ccopt = ""
+$  else
+$   ccopt = "/decc/prefix=all"
+$   if f$trnlnm("SYS").eqs.""
+$    then
+$     if f$trnlnm("DECC$LIBRARY_INCLUDE").nes."" 
+$      then 
+$       define sys decc$library_include:
+$      else
+$       if f$search("SYS$COMMON:[DECC$LIB.REFERENCE]DECC$RTLDEF.DIR").nes."" -
+           then lval = "SYS$COMMON:[DECC$LIB.REFERENCE.DECC$RTLDEF],"
+$       if f$search("SYS$COMMON:[DECC$LIB.REFERENCE]SYS$STARLET_C.DIR").nes."" -
+           then lval = lval+"SYS$COMMON:[DECC$LIB.REFERENCE.SYS$STARLET_C],"
+$       lval=lval+"SYS$LIBRARY:"
+$       define sys 'lval           
+$      endif
+$   endif
+$ endif
+$ filelist = "alloca ar arscan commands default dir expand file function implicit job main misc read remake remote-stub rule signame variable version vmsfunctions vmsify vpath [.glob]glob [.glob]fnmatch getopt1 getopt"
 $ copy config.h-vms config.h
 $ n=0
+$ open/write optf make.opt
 $ loop:
 $ cfile = f$elem(n," ",filelist)
 $ if cfile .eqs. " " then goto linkit
@@ -16,19 +43,18 @@ $ call compileit 'cfile' 'p1'
 $ n = n + 1
 $ goto loop
 $ linkit:
+$ close optf
 $ if p1 .nes. "" then goto link_using_library
-$ link/exe=make alloca,ar,arscan,commands,default,dir,expand,file,function,-
-               implicit,job,main,misc,read,remake,remote-stub,rule,-
-               signame,variable,version,vmsfunctions,vmsify,vpath,-
-               glob,fnmatch,getopt,getopt1
+$ link/exe=make make.opt/opt
 $ exit
 $ link_using_library:
-$ link/exe=make alloca,ar,arscan,commands,default,dir,expand,file,function,-
-               implicit,job,main,misc,read,remake,remote-stub,rule,-
-               signame,variable,version,vmsfunctions,vmsify,vpath,-
-               glob,fnmatch,getopt,getopt1,sys$library:vaxcrtl/lib
+$ link/exe=make make.opt/opt,sys$library:vaxcrtl/lib
 $!
 $ compileit : subroutine
-$ cc/include=([],[.glob])/define=("allocated_variable_expand_for_file=alloc_var_expand_for_file","unlink=remove","HAVE_CONFIG_H","VMS") 'p1'
+$ ploc = f$locate("]",p1)
+$ filnam = p1
+$ if ploc .lt. f$length(p1) then filnam=f$extract(ploc+1,100,p1)
+$ write optf "''filnam'"
+$ cc'ccopt'/include=([],[.glob])/define=("allocated_variable_expand_for_file=alloc_var_expand_for_file","unlink=remove","HAVE_CONFIG_H","VMS") 'p1'
 $ exit
 $ endsubroutine : compileit
diff --git a/misc.c b/misc.c
index dbbe41f..1411e54 100644 (file)
--- a/misc.c
+++ b/misc.c
@@ -253,6 +253,9 @@ makefile_fatal (file, lineno, s1, s2, s3, s4, s5, s6)
      unsigned int lineno;
      char *s1, *s2, *s3, *s4, *s5, *s6;
 {
+  if (!file)
+    fatal(s1, s2, s3, s4, s5, s6);
+
   log_working_directory (1);
 
   fprintf (stderr, "%s:%u: *** ", file, lineno);
@@ -470,7 +473,7 @@ copy_dep_chain (d)
 {
   register struct dep *c;
   struct dep *firstnew = 0;
-  struct dep *lastnew;
+  struct dep *lastnew = 0;
 
   while (d != 0)
     {
@@ -564,8 +567,9 @@ log_access (flavor)
      but we write this one to stderr because it might be
      run in a child fork whose stdout is piped.  */
 
-  fprintf (stderr, "%s access: user %d (real %d), group %d (real %d)\n",
-          flavor, geteuid (), getuid (), getegid (), getgid ());
+  fprintf (stderr, "%s access: user %lu (real %lu), group %lu (real %lu)\n",
+          flavor, (unsigned long) geteuid (), (unsigned long) getuid (),
+           (unsigned long) getegid (), (unsigned long) getgid ());
   fflush (stderr);
 }
 
diff --git a/read.c b/read.c
index bf7f80c..0207516 100644 (file)
--- a/read.c
+++ b/read.c
@@ -16,12 +16,15 @@ You should have received a copy of the GNU General Public License
 along with GNU Make; see the file COPYING.  If not, write to
 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
+#include <assert.h>
+
 #include "make.h"
 #include "dep.h"
 #include "filedef.h"
 #include "job.h"
 #include "commands.h"
 #include "variable.h"
+#include "rule.h"
 
 /* This is POSIX.2, but most systems using -DPOSIX probably don't have it.  */
 #ifdef HAVE_GLOB_H
@@ -57,6 +60,14 @@ struct linebuffer
 #define freebuffer(lb) free ((lb)->buffer)
 
 
+/* Types of "words" that can be read in a makefile.  */
+enum make_word_type
+  {
+     w_bogus, w_eol, w_static, w_variable, w_colon, w_dcolon, w_semicolon,
+     w_comment, w_varassign
+  };
+
+
 /* A `struct conditionals' contains the information describing
    all the active conditionals in a makefile.
 
@@ -122,9 +133,14 @@ static unsigned int do_define PARAMS ((char *name, unsigned int namelen, enum va
                        unsigned int lineno, FILE *infile, char *filename));
 static int conditional_line PARAMS ((char *line, char *filename, unsigned int lineno));
 static void record_files PARAMS ((struct nameseq *filenames, char *pattern, char *pattern_percent,
-                       struct dep *deps, unsigned int commands_started, char *commands,
+                       struct dep *deps, unsigned int cmds_started, char *commands,
                        unsigned int commands_idx, int two_colon, char *filename,
                        unsigned int lineno, int set_default));
+static void record_target_var PARAMS ((struct nameseq *filenames, char *defn,
+                        int two_colon, enum variable_origin origin,
+                        char *filename, unsigned int lineno));
+static enum make_word_type get_next_mword PARAMS ((char *buffer, char *delim,
+                        char **startp, unsigned int *length));
 \f
 /* Read in all the makefiles and return the chain of their names.  */
 
@@ -200,7 +216,7 @@ read_all_makefiles (makefiles)
       static char *default_makefiles[] =
 #ifdef VMS
        /* all lower case since readdir() (the vms version) 'lowercasifies' */
-       { "makefile.vms", "gnumakefile", "makefile", 0 };
+       { "makefile.vms", "gnumakefile.", "makefile.", 0 };
 #else
 #ifdef _AMIGA
        { "GNUmakefile", "Makefile", "SMakefile", 0 };
@@ -268,10 +284,10 @@ read_makefile (filename, flags)
   unsigned int commands_len = 200;
   char *commands = (char *) xmalloc (200);
   unsigned int commands_idx = 0;
-  unsigned int commands_started;
-  register char *p;
+  unsigned int cmds_started;
+  char *p;
   char *p2;
-  int len;
+  int len, reading_target;
   int ignoring = 0, in_ignored_define = 0;
   int no_targets = 0;          /* Set when reading a rule without targets.  */
   char *passed_filename = filename;
@@ -280,7 +296,7 @@ read_makefile (filename, flags)
   struct dep *deps;
   unsigned int lineno = 1;
   unsigned int nlines = 0;
-  int two_colon;
+  int two_colon = 0;
   char *pattern = 0, *pattern_percent;
 
   int makefile_errno;
@@ -293,19 +309,16 @@ read_makefile (filename, flags)
     {                                                                        \
       if (filenames != 0)                                                    \
        record_files (filenames, pattern, pattern_percent, deps,              \
-                     commands_started, commands, commands_idx,               \
+                     cmds_started, commands, commands_idx,                   \
                      two_colon, filename, lineno,                            \
                      !(flags & RM_NO_DEFAULT_GOAL));                         \
       filenames = 0;                                                         \
       commands_idx = 0;                                                              \
-      pattern = 0;                                                           \
+      if (pattern) { free(pattern); pattern = 0; }                            \
     } while (0)
 
-#ifdef lint    /* Suppress `used before set' messages.  */
-  two_colon = 0;
-#endif
   pattern_percent = 0;
-  commands_started = lineno;
+  cmds_started = lineno;
 
   if (debug_flag)
     {
@@ -424,7 +437,7 @@ read_makefile (filename, flags)
              /* Append this command line to the line being accumulated.  */
              p = lb.buffer;
              if (commands_idx == 0)
-               commands_started = lineno;
+               cmds_started = lineno;
              len = strlen (p);
              if (len + 1 + commands_idx > commands_len)
                {
@@ -453,7 +466,7 @@ read_makefile (filename, flags)
       collapse_continuations (collapsed);
       remove_comments (collapsed);
 
-      /* strncmp is first to avoid dereferencing out into space.  */
+      /* Compare a word, both length and contents. */
 #define        word1eq(s, l)   (len == l && !strncmp (s, p, l))
       p = collapsed;
       while (isspace (*p))
@@ -462,20 +475,27 @@ read_makefile (filename, flags)
        /* This line is completely empty.  */
        continue;
 
-      /* Find the end of the first token */
+      /* Find the end of the first token.  Note we don't need to worry about
+       * ":" here since we compare tokens by length (so "export" will never
+       * be equal to "export:").
+       */
       for (p2 = p+1; *p2 != '\0' && !isspace(*p2); ++p2)
         {}
       len = p2 - p;
 
-      /* Find the start of the second token.  If it's a `:', jump past
-         preprocessor stuff since it can't be that--this allows targets named
-         `export', etc. */
+      /* Find the start of the second token.  If it's a `:' remember it,
+         since it can't be a preprocessor token--this allows targets named
+         `ifdef', `export', etc. */
+      reading_target = 0;
       while (isspace (*p2))
         ++p2;
       if (*p2 == '\0')
         p2 = NULL;
       else if (p2[0] == ':' && p2[1] == '\0')
-        goto check_var;
+        {
+          reading_target = 1;
+          goto skip_conditionals;
+        }
 
       /* We must first check for conditional and `define' directives before
         ignoring anything, since they control what we will do with
@@ -494,7 +514,8 @@ read_makefile (filename, flags)
                            "invalid syntax in conditional");
          continue;
        }
-      else if (word1eq ("endef", 5))
+
+      if (word1eq ("endef", 5))
        {
          if (in_ignored_define)
            in_ignored_define = 0;
@@ -502,7 +523,8 @@ read_makefile (filename, flags)
            makefile_fatal (filename, lineno, "extraneous `endef'");
          continue;
        }
-      else if (word1eq ("define", 6))
+
+      if (word1eq ("define", 6))
        {
          if (ignoring)
            in_ignored_define = 1;
@@ -521,8 +543,9 @@ read_makefile (filename, flags)
            }
          continue;
        }
-      else if (word1eq ("override", 8))
-       {
+
+      if (word1eq ("override", 8))
+        {
          p2 = next_token (p + 8);
          if (p2 == 0)
            makefile_error (filename, lineno, "empty `override' directive");
@@ -551,12 +574,14 @@ read_makefile (filename, flags)
 
          continue;
        }
+ skip_conditionals:
 
       if (ignoring)
        /* Ignore the line.  We continue here so conditionals
           can appear in the middle of a rule.  */
        continue;
-      else if (word1eq ("export", 6))
+
+      if (!reading_target && word1eq ("export", 6))
        {
          struct variable *v;
          p2 = next_token (p + 6);
@@ -578,7 +603,7 @@ read_makefile (filename, flags)
                }
            }
        }
-      else if (word1eq ("unexport", 8))
+      else if (!reading_target && word1eq ("unexport", 8))
        {
          unsigned int len;
          struct variable *v;
@@ -614,9 +639,7 @@ read_makefile (filename, flags)
          if (pattern != 0)
            free (pattern);
        }
-      else
-    check_var:
-        if (word1eq ("include", 7) || word1eq ("-include", 8)
+      else if (word1eq ("include", 7) || word1eq ("-include", 8)
               || word1eq ("sinclude", 8))
        {
          /* We have found an `include' line specifying a nested
@@ -627,7 +650,7 @@ read_makefile (filename, flags)
             exist.  "sinclude" is an alias for this from SGI.  */
          int noerror = p[0] != 'i';
 
-         p = allocated_variable_expand (next_token (p + (noerror ? 9 : 8)));
+         p = allocated_variable_expand (next_token (p + (noerror ? 8 : 7)));
          if (*p == '\0')
            {
              makefile_error (filename, lineno,
@@ -667,6 +690,7 @@ read_makefile (filename, flags)
                  && ! noerror)
                makefile_error (filename, lineno,
                                "%s: %s", name, strerror (errno));
+              free(name);
            }
 
          /* Free any space allocated by conditional_line.  */
@@ -701,9 +725,20 @@ read_makefile (filename, flags)
        }
       else
        {
-         /* This line describes some target files.  */
+         /* This line describes some target files.  This is complicated by
+             the existence of target-specific variables, because we can't
+             expand the entire line until we know if we have one or not.  So
+             we expand the line word by word until we find the first `:',
+             then check to see if it's a target-specific variable.
+
+             In this algorithm, `lb_next' will point to the beginning of the
+             unexpanded parts of the input buffer, while `p2' points to the
+             parts of the expanded buffer we haven't searched yet. */
 
-         char *cmdleft;
+          enum make_word_type wtype;
+          enum variable_origin v_origin;
+          char *cmdleft, *lb_next;
+          unsigned int len, plen = 0;
 
          /* Record the previous rule.  */
 
@@ -720,55 +755,176 @@ read_makefile (filename, flags)
            }
          else if (cmdleft != 0)
            /* Found one.  Cut the line short there before expanding it.  */
-           *cmdleft = '\0';
+           *(cmdleft++) = '\0';
 
          collapse_continuations (lb.buffer);
 
-         /* Expand variable and function references before doing anything
-            else so that special characters can be inside variables.  */
-         p = variable_expand (lb.buffer);
-
-         if (cmdleft == 0)
-           /* Look for a semicolon in the expanded line.  */
-           cmdleft = find_char_unquote (p, ";", 0);
+         /* We can't expand the entire line, since if it's a per-target
+             variable we don't want to expand it.  So, walk from the
+             beginning, expanding as we go, and looking for "interesting"
+             chars.  The first word is always expandable.  */
+          wtype = get_next_mword(lb.buffer, NULL, &lb_next, &len);
+          switch (wtype)
+            {
+            case w_eol:
+              if (cmdleft != 0)
+                makefile_fatal (filename, lineno,
+                                "missing rule before commands");
+              else
+                /* This line contained a variable reference that
+                   expanded to nothing but whitespace.  */
+                continue;
+
+            case w_colon:
+            case w_dcolon:
+              /* We accept and ignore rules without targets for
+                 compatibility with SunOS 4 make.  */
+              no_targets = 1;
+              continue;
+
+            default:
+              break;
+            }
 
-         if (cmdleft != 0)
-           /* Cut the line short at the semicolon.  */
-           *cmdleft = '\0';
+          p2 = variable_expand_string(NULL, lb_next, len);
+          while (1)
+            {
+              char *colonp;
+
+              lb_next += len;
+              if (cmdleft == 0)
+                {
+                  /* Look for a semicolon in the expanded line.  */
+                  cmdleft = find_char_unquote (p2, ";", 0);
+
+                  if (cmdleft != 0)
+                    {
+                      unsigned long p2_off = p2 - variable_buffer;
+                      unsigned long cmd_off = cmdleft - variable_buffer;
+                      char *pend = p2 + strlen(p2);
+
+                      /* Append any remnants of lb, then cut the line short
+                         at the semicolon.  */
+                      *cmdleft = '\0';
+
+                      /* One school of thought says that you shouldn't expand
+                         here, but merely copy, since now you're beyond a ";"
+                         and into a command script.  However, the old parser
+                         expanded the whole line, so we continue that for
+                         backwards-compatiblity.  Also, it wouldn't be
+                         entirely consistent, since we do an unconditional
+                         expand below once we know we don't have a
+                         target-specific variable. */
+                      (void)variable_expand_string(pend, lb_next, -1);
+                      lb_next += strlen(lb_next);
+                      p2 = variable_buffer + p2_off;
+                      cmdleft = variable_buffer + cmd_off + 1;
+                    }
+                }
+
+              colonp = find_char_unquote(p2, ":", 0);
+#if defined(__MSDOS__) || defined(WINDOWS32)
+             /* The drive spec brain-damage strikes again...  */
+             /* FIXME: is whitespace the only possible separator of words
+                in this context?  If not, the `isspace' test below will
+                need to be changed into a call to `index'.  */
+             while (colonp && (colonp[1] == '/' || colonp[1] == '\\') &&
+                    colonp > p2 && isalpha(colonp[-1]) &&
+                    (colonp == p2 + 1 || isspace(colonp[-2])))
+               colonp = find_char_unquote(colonp + 1, ":", 0);
+#endif
+              if (colonp != 0)
+                break;
+
+              wtype = get_next_mword(lb_next, NULL, &lb_next, &len);
+              if (wtype == w_eol)
+                makefile_fatal (filename, lineno, "missing separator");
+
+              p2 += strlen(p2);
+              *(p2++) = ' ';
+              p2 = variable_expand_string(p2, lb_next, len);
+              /* We don't need to worry about cmdleft here, because if it was
+                 found in the variable_buffer the entire buffer has already
+                 been expanded... we'll never get here.  */
+            }
 
-         p2 = next_token (p);
-         if (*p2 == '\0')
-           {
-             if (cmdleft != 0)
-               makefile_fatal (filename, lineno,
-                               "missing rule before commands");
-             else
-               /* This line contained a variable reference that
-                  expanded to nothing but whitespace.  */
-               continue;
-           }
-         else if (*p2 == ':')
-           {
-             /* We accept and ignore rules without targets for
-                compatibility with SunOS 4 make.  */
-             no_targets = 1;
-             continue;
-           }
+         p2 = next_token (variable_buffer);
 
          filenames = multi_glob (parse_file_seq (&p2, ':',
                                                  sizeof (struct nameseq),
                                                  1),
                                  sizeof (struct nameseq));
-         if (*p2++ == '\0')
-           makefile_fatal (filename, lineno, "missing separator");
+
+          if (!filenames)
+            {
+              /* We accept and ignore rules without targets for
+                 compatibility with SunOS 4 make.  */
+              no_targets = 1;
+              continue;
+            }
+          /* This should never be possible; we handled it above.  */
+         assert(*p2 != '\0');
+          ++p2;
+
          /* Is this a one-colon or two-colon entry?  */
          two_colon = *p2 == ':';
          if (two_colon)
            p2++;
 
+          /* Test to see if it's a target-specific variable.  Copy the rest
+             of the buffer over, possibly temporarily (we'll expand it later
+             if it's not a target-specific variable).  PLEN saves the length
+             of the unparsed section of p2, for later.  */
+          if (*lb_next != '\0')
+            {
+              unsigned int l = p2 - variable_buffer;
+              plen = strlen(p2);
+              (void)variable_buffer_output(p2+plen,
+                                           lb_next, strlen(lb_next)+1);
+              p2 = variable_buffer + l;
+            }
+          wtype = get_next_mword(p2, NULL, &p, &len);
+          v_origin = o_file;
+          if (wtype == w_static && (len == (sizeof("override")-1)
+                                    && !strncmp(p, "override", len)))
+            {
+              v_origin = o_override;
+              (void)get_next_mword(p+len, NULL, &p, &len);
+            }
+          else if (wtype != w_eol)
+            wtype = get_next_mword(p+len, NULL, NULL, NULL);
+
+          if (wtype == w_varassign || v_origin == o_override)
+            {
+              record_target_var(filenames, p, two_colon, v_origin,
+                                filename, lineno);
+              filenames = 0;
+              continue;
+            }
+
+          /* This is a normal target, _not_ a target-specific variable.
+             Unquote any = in the dependency list.  */
+          find_char_unquote (lb_next, "=", 0);
+
          /* We have some targets, so don't ignore the following commands.  */
          no_targets = 0;
 
+          /* Expand the dependencies, etc.  */
+          if (*lb_next != '\0')
+            {
+              unsigned int l = p2 - variable_buffer;
+              (void)variable_expand_string(p2 + plen, lb_next, -1);
+              p2 = variable_buffer + l;
+
+              /* Look for a semicolon in the expanded line.  */
+              if (cmdleft == 0)
+                {
+                  cmdleft = find_char_unquote (p2, ";", 0);
+                  if (cmdleft != 0)
+                    *(cmdleft++) = '\0';
+                }
+            }
+
          /* Is this a static pattern rule: `target: %targ: %dep; ...'?  */
          p = index (p2, ':');
          while (p != 0 && p[-1] == '\\')
@@ -802,7 +958,8 @@ read_makefile (filename, flags)
           do {
             check_again = 0;
             /* For MSDOS and WINDOWS32, skip a "C:\..." or a "C:/..." */
-            if (p != 0 && (p[1] == '\\' || p[1] == '/') && isalpha (p[-1])) {
+            if (p != 0 && (p[1] == '\\' || p[1] == '/') &&
+               isalpha(p[-1]) && (p == p2 + 1 || index(" \t:", p[-2]) != 0)) {
               p = index(p + 1, ':');
               check_again = 1;
             }
@@ -822,6 +979,7 @@ read_makefile (filename, flags)
              if (pattern_percent == 0)
                makefile_fatal (filename, lineno,
                                "target pattern contains no `%%'");
+              free((char *)target);
            }
          else
            pattern = 0;
@@ -835,9 +993,9 @@ read_makefile (filename, flags)
          if (cmdleft != 0)
            {
              /* Semicolon means rest of line is a command.  */
-             unsigned int len = strlen (cmdleft + 1);
+             unsigned int len = strlen (cmdleft);
 
-             commands_started = lineno;
+             cmds_started = lineno;
 
              /* Add this command line to the buffer.  */
              if (len + 2 > commands_len)
@@ -845,7 +1003,7 @@ read_makefile (filename, flags)
                  commands_len = (len + 2) * 2;
                  commands = (char *) xrealloc (commands, commands_len);
                }
-             bcopy (cmdleft + 1, commands, len);
+             bcopy (cmdleft, commands, len);
              commands_idx += len;
              commands[commands_idx++] = '\n';
            }
@@ -1216,6 +1374,93 @@ uniquize_deps (chain)
     }
 }
 \f
+/* Record target-specific variable values for files FILENAMES.
+   TWO_COLON is nonzero if a double colon was used.
+
+   The links of FILENAMES are freed, and so are any names in it
+   that are not incorporated into other data structures.
+
+   If the target is a pattern, add the variable to the pattern-specific
+   variable value list.  */
+
+static void
+record_target_var (filenames, defn, two_colon, origin, filename, lineno)
+     struct nameseq *filenames;
+     char *defn;
+     int two_colon;
+     enum variable_origin origin;
+     char *filename;
+     unsigned int lineno;
+{
+  struct nameseq *nextf;
+  struct variable_set_list *global;
+
+  global = current_variable_set_list;
+
+  for (; filenames != 0; filenames = nextf)
+    {
+      struct variable *v;
+      register char *name = filenames->name;
+      struct variable_set_list *vlist;
+      char *fname;
+      char *percent;
+
+      nextf = filenames->next;
+      free ((char *) filenames);
+
+      /* If it's a pattern target, then add it to the pattern-specific
+         variable list.  */
+      percent = find_percent (name);
+      if (percent)
+        {
+          struct pattern_var *p;
+
+          /* Get a reference for this pattern-specific variable struct.  */
+          p = create_pattern_var(name, percent);
+          vlist = p->vars;
+          fname = p->target;
+        }
+      else
+        {
+          struct file *f;
+
+          /* Get a file reference for this file, and initialize it.  */
+          f = enter_file (name);
+          initialize_file_variables (f);
+          vlist = f->variables;
+          fname = f->name;
+        }
+
+      /* Make the new variable context current and define the variable.  */
+      current_variable_set_list = vlist;
+      v = try_variable_definition(filename, lineno, defn, origin);
+      if (!v)
+        makefile_error(filename, lineno,
+                       "Malformed per-target variable definition");
+      v->per_target = 1;
+
+      /* If it's not an override, check to see if there was a command-line
+         setting.  If so, reset the value.  */
+      if (origin != o_override)
+        {
+          struct variable *gv;
+          int len = strlen(v->name);
+
+          current_variable_set_list = global;
+          gv = lookup_variable(v->name, len);
+          if (gv && (gv->origin == o_env_override || gv->origin == o_command))
+            define_variable_in_set(v->name, len, gv->value, gv->origin,
+                                     gv->recursive, vlist->set);
+        }
+
+      /* Free name if not needed further.  */
+      if (name != fname && (name < fname || name > fname + strlen (fname)))
+        free (name);
+    }
+
+  current_variable_set_list = global;
+}
+\f
 /* Record a description line for files FILENAMES,
    with dependencies DEPS, commands to execute described
    by COMMANDS and COMMANDS_IDX, coming from FILENAME:COMMANDS_STARTED.
@@ -1228,12 +1473,12 @@ uniquize_deps (chain)
    that are not incorporated into other data structures.  */
 
 static void
-record_files (filenames, pattern, pattern_percent, deps, commands_started,
+record_files (filenames, pattern, pattern_percent, deps, cmds_started,
              commands, commands_idx, two_colon, filename, lineno, set_default)
      struct nameseq *filenames;
      char *pattern, *pattern_percent;
      struct dep *deps;
-     unsigned int commands_started;
+     unsigned int cmds_started;
      char *commands;
      unsigned int commands_idx;
      int two_colon;
@@ -1243,7 +1488,7 @@ record_files (filenames, pattern, pattern_percent, deps, commands_started,
 {
   struct nameseq *nextf;
   int implicit = 0;
-  unsigned int max_targets, target_idx;
+  unsigned int max_targets = 0, target_idx = 0;
   char **targets = 0, **target_percents = 0;
   struct commands *cmds;
 
@@ -1251,7 +1496,7 @@ record_files (filenames, pattern, pattern_percent, deps, commands_started,
     {
       cmds = (struct commands *) xmalloc (sizeof (struct commands));
       cmds->filename = filename;
-      cmds->lineno = commands_started;
+      cmds->lineno = cmds_started;
       cmds->commands = savestring (commands, commands_idx);
       cmds->command_lines = 0;
     }
@@ -1260,6 +1505,7 @@ record_files (filenames, pattern, pattern_percent, deps, commands_started,
 
   for (; filenames != 0; filenames = nextf)
     {
+
       register char *name = filenames->name;
       register struct file *f;
       register struct dep *d;
@@ -1641,13 +1887,6 @@ parse_file_seq (stringp, stopchar, size, strip)
       if (p && *p == ',')
        *p =' ';
 #endif
-#ifdef __MSDOS__
-      /* For MS-DOS, skip a "C:\..." or a "C:/..." until we find a
-        first colon which isn't followed by a slash or a backslash.  */
-      if (stopchar == ':')
-       while (p != 0 && (p[1] == '\\' || p[1] == '/') && isalpha (p[-1]))
-         p = find_char_unquote (p + 1, stopchars, 1);
-#endif
 #ifdef _AMIGA
       if (stopchar == ':' && p && *p == ':' &&
        !(isspace(p[1]) || !p[1] || isspace(p[-1])))
@@ -1655,16 +1894,15 @@ parse_file_seq (stringp, stopchar, size, strip)
        p = find_char_unquote (p+1, stopchars, 1);
       }
 #endif
-#ifdef WINDOWS32
-      /* For WINDOWS32, skip a "C:\..." or "C:/...". */
-      if (stopchar == ':' &&
-          p != 0 &&
-          (p[1] == '\\' || p[1] == '/') &&
-          isalpha (p[-1])) {
-        p = end_of_token_w32(++p, ':');
-        if (*p == '\0' && p[-1] == ':')
-          p--;
-      }
+#if defined(WINDOWS32) || defined(__MSDOS__)
+    /* For WINDOWS32, skip a "C:\..." or a "C:/..." until we find the
+       first colon which isn't followed by a slash or a backslash.
+       Note that tokens separated by spaces should be treated as separate
+       tokens since make doesn't allow path names with spaces */
+    if (stopchar == ':')
+      while (p != 0 && !isspace(*p) &&
+             (p[1] == '\\' || p[1] == '/') && isalpha (p[-1]))
+        p = find_char_unquote (p + 1, stopchars, 1);
 #endif
       if (p == 0)
        p = q + strlen (q);
@@ -1751,7 +1989,7 @@ parse_file_seq (stringp, stopchar, size, strip)
           Look back for an elt with an opening `(' but no closing `)'.  */
 
        struct nameseq *n = new1->next, *lastn = new1;
-       char *paren;
+       char *paren = 0;
        while (n != 0 && (paren = index (n->name, '(')) == 0)
          {
            lastn = n;
@@ -1944,6 +2182,190 @@ readline (linebuffer, stream, filename, lineno)
   return nlines;
 }
 \f
+/* Parse the next "makefile word" from the input buffer, and return info
+   about it.
+
+   A "makefile word" is one of:
+
+     w_bogus        Should never happen
+     w_eol          End of input
+     w_static       A static word; cannot be expanded
+     w_variable     A word containing one or more variables/functions
+     w_colon        A colon
+     w_dcolon       A double-colon
+     w_semicolon    A semicolon
+     w_comment      A comment character
+     w_varassign    A variable assignment operator (=, :=, +=, or ?=)
+
+   Note that this function is only used when reading certain parts of the
+   makefile.  Don't use it where special rules hold sway (RHS of a variable,
+   in a command list, etc.)  */
+
+static enum make_word_type
+get_next_mword (buffer, delim, startp, length)
+     char *buffer;
+     char *delim;
+     char **startp;
+     unsigned int *length;
+{
+  enum make_word_type wtype = w_bogus;
+  char *p = buffer, *beg;
+  char c;
+
+  /* Skip any leading whitespace.  */
+  while (isblank(*p))
+    ++p;
+
+  beg = p;
+  c = *(p++);
+  switch (c)
+    {
+    case '\0':
+      wtype = w_eol;
+      break;
+
+    case '#':
+      wtype = w_comment;
+      break;
+
+    case ';':
+      wtype = w_semicolon;
+      break;
+
+    case '=':
+      wtype = w_varassign;
+      break;
+
+    case ':':
+      wtype = w_colon;
+      switch (*p)
+        {
+        case ':':
+          ++p;
+          wtype = w_dcolon;
+          break;
+
+        case '=':
+          ++p;
+          wtype = w_varassign;
+          break;
+        }
+      break;
+
+    case '+':
+    case '?':
+      if (*p == '=')
+        {
+          ++p;
+          wtype = w_varassign;
+          break;
+        }
+
+    default:
+      if (delim && index(delim, c))
+        wtype = w_static;
+      break;
+    }
+
+  /* Did we find something?  If so, return now.  */
+  if (wtype != w_bogus)
+    goto done;
+
+  /* This is some non-operator word.  A word consists of the longest
+     string of characters that doesn't contain whitespace, one of [:=#],
+     or [?+]=, or one of the chars in the DELIM string.  */
+
+  /* We start out assuming a static word; if we see a variable we'll
+     adjust our assumptions then.  */
+  wtype = w_static;
+
+  /* We already found the first value of "c", above.  */
+  while (1)
+    {
+      char closeparen;
+      int count;
+
+      switch (c)
+        {
+        case '\0':
+        case ' ':
+        case '\t':
+        case '=':
+        case '#':
+          goto done_word;
+
+        case ':':
+#if defined(__MSDOS__) || defined(WINDOWS32)
+         /* A word CAN include a colon in its drive spec.  */
+         if (!(p - beg == 2 && (*p == '/' || *p == '\\') && isalpha (*beg)))
+#endif
+         goto done_word;
+
+        case '$':
+          c = *(p++);
+          if (c == '$')
+            break;
+
+          /* This is a variable reference, so note that it's expandable.
+             Then read it to the matching close paren.  */
+          wtype = w_variable;
+
+          if (c == '(')
+            closeparen = ')';
+          else if (c == '{')
+            closeparen = '}';
+          else
+            /* This is a single-letter variable reference.  */
+            break;
+
+          for (count=0; *p != '\0'; ++p)
+            {
+              if (*p == c)
+                ++count;
+              else if (*p == closeparen && --count < 0)
+                {
+                  ++p;
+                  break;
+                }
+            }
+          break;
+
+        case '?':
+        case '+':
+          if (*p == '=')
+            goto done_word;
+          break;
+
+        case '\\':
+          switch (*p)
+            {
+            case ';':
+            case '=':
+            case '\\':
+              ++p;
+              break;
+            }
+          break;
+
+        default:
+          if (delim && index(delim, c))
+            goto done_word;
+          break;
+        }
+
+      c = *(p++);
+    }
+ done_word:
+  --p;
+
+ done:
+  if (startp)
+    *startp = beg;
+  if (length)
+    *length = p - beg;
+  return wtype;
+}
+\f
 /* Construct the list of include directories
    from the arguments and the default list.  */
 
@@ -2075,11 +2497,11 @@ tilde_expand (name)
       if (home_dir == 0 || home_dir[0] == '\0')
        {
          extern char *getlogin ();
-         char *name = getlogin ();
+         char *logname = getlogin ();
          home_dir = 0;
-         if (name != 0)
+         if (logname != 0)
            {
-             struct passwd *p = getpwnam (name);
+             struct passwd *p = getpwnam (logname);
              if (p != 0)
                home_dir = p->pw_dir;
            }
index 18010cf..43b4dd0 100644 (file)
@@ -47,8 +47,15 @@ Multiple line DCL commands, such as "if" statements, must be put inside
 command files.  You can run a command file by using \@.
 
 
-VMS changes made for 3.74.3
-
+Change history:
+
+3.76.x
+======
+Added VMS help version (make.hlp) of the Unix man page. To integrate
+that with an existing Help library use a command like the following
+ $lib/ins/help sys$help:helplib.hlb make.hlp
+3.74.3
+======
 Lots of default settings are adapted for VMS. See default.c.
 
 Long command lines are now converted to command files.
index b4f15cf..9c459a4 100644 (file)
--- a/remake.c
+++ b/remake.c
@@ -91,9 +91,14 @@ update_goal_chain (goals, makefiles)
       g->changed = 0;
   }
 
+#if 0
+  /* Only run one job at a time when building makefiles.
+     No one seems to know why this was done, and no one can think of a good
+     reason to do it.  Hopefully an obvious one won't appear as soon as we
+     release the next version :-/.  */
   if (makefiles)
-    /* Only run one job at a time.  */
     job_slots = 1;
+#endif
 
   /* Update all the goals until they are all finished.  */
 
@@ -115,7 +120,7 @@ update_goal_chain (goals, makefiles)
        {
          /* Iterate over all double-colon entries for this file.  */
          struct file *file = g->file;
-         int stop, any_not_updated = 0;
+         int stop = 0, any_not_updated = 0;
 
          for (file = g->file->double_colon ? g->file->double_colon : g->file;
               file != NULL;
@@ -248,6 +253,38 @@ update_goal_chain (goals, makefiles)
   return status;
 }
 \f
+/* Generate an error/fatal message if no rules are available for the target.
+ */
+static void
+no_rule_error(file)
+  struct file *file;
+{
+  static const char msg_noparent[]
+    = "%sNo rule to make target `%s'%s";
+  static const char msg_parent[]
+    = "%sNo rule to make target `%s', needed by `%s'%s";
+  if (keep_going_flag || file->dontcare)
+    {
+      if (!file->dontcare)
+        {
+          if (file->parent == 0)
+            error (msg_noparent, "*** ", file->name, ".");
+          else
+            error (msg_parent, "*** ",
+                   file->name, file->parent->name, ".");
+          file->shownerror = 1;
+        }
+      file->update_status = 2;
+    }
+  else
+    {
+      if (file->parent == 0)
+        fatal (msg_noparent, "", file->name, "");
+      else
+        fatal (msg_parent, "", file->name, file->parent->name, "");
+    }
+}
+\f
 /* If FILE is not up to date, execute the commands for it.
    Return 0 if successful, 1 if unsuccessful;
    but with some flag settings, just call `exit' if unsuccessful.
@@ -317,6 +354,13 @@ update_file_1 (file, depth)
       if (file->update_status > 0)
        {
          DEBUGPR ("Recently tried and failed to update file `%s'.\n");
+          if (!file->shownerror)
+            {
+              int dontcare = file->dontcare;
+              file->dontcare = 0;
+              no_rule_error(file);
+              file->dontcare = dontcare;
+            }
          return file->update_status;
        }
 
@@ -394,18 +438,14 @@ update_file_1 (file, depth)
        {
          error ("Circular %s <- %s dependency dropped.",
                 file->name, d->file->name);
+         /* We cannot free D here because our the caller will still have
+            a reference to it when we were called recursively via
+            check_dep below.  */
          if (lastd == 0)
-           {
-             file->deps = d->next;
-             free ((char *) d);
-             d = file->deps;
-           }
+           file->deps = d->next;
          else
-           {
-             lastd->next = d->next;
-             free ((char *) d);
-             d = lastd->next;
-           }
+           lastd->next = d->next;
+         d = d->next;
          continue;
        }
 
@@ -594,7 +634,7 @@ update_file_1 (file, depth)
   DEBUGPR ("Must remake target `%s'.\n");
 
   /* It needs to be remade.  If it's VPATH and not reset via GPATH, toss the
-     VPATH */
+     VPATH */
   if (!streq(file->name, file->hname))
     {
       if (debug_flag)
@@ -910,32 +950,7 @@ remake_file (file)
           Pretend it was successfully remade.  */
        file->update_status = 0;
       else
-       {
-         /* This is a dependency file we cannot remake.  Fail.  */
-         static const char msg_noparent[]
-           = "%sNo rule to make target `%s'%s";
-         static const char msg_parent[]
-           = "%sNo rule to make target `%s', needed by `%s'%s";
-         if (keep_going_flag || file->dontcare)
-           {
-             if (!file->dontcare)
-               {
-                 if (file->parent == 0)
-                   error (msg_noparent, "*** ", file->name, ".");
-                 else
-                   error (msg_parent, "*** ",
-                          file->name, file->parent->name, ".");
-               }
-             file->update_status = 2;
-           }
-         else
-           {
-             if (file->parent == 0)
-               fatal (msg_noparent, "", file->name, "");
-             else
-               fatal (msg_parent, "", file->name, file->parent->name, "");
-           }
-       }
+        no_rule_error(file);
     }
   else
     {
@@ -994,11 +1009,12 @@ f_mtime (file, search)
        }
       mtime = f_mtime (arfile, search);
       check_renamed (arfile);
-      if (search && strcmp (arfile->name, arname))
+      if (search && strcmp (arfile->hname, arname))
        {
          /* The archive's name has changed.
             Change the archive-member reference accordingly.  */
 
+          char *name;
          unsigned int arlen, memlen;
 
          if (!arname_used)
@@ -1007,18 +1023,26 @@ f_mtime (file, search)
              arname_used = 1;
            }
 
-         arname = arfile->name;
+         arname = arfile->hname;
          arlen = strlen (arname);
          memlen = strlen (memname);
 
-         free (file->name);
-
-         file->name = (char *) xmalloc (arlen + 1 + memlen + 2);
-         bcopy (arname, file->name, arlen);
-         file->name[arlen] = '(';
-         bcopy (memname, file->name + arlen + 1, memlen);
-         file->name[arlen + 1 + memlen] = ')';
-         file->name[arlen + 1 + memlen + 1] = '\0';
+         /* free (file->name); */
+
+         name = (char *) xmalloc (arlen + 1 + memlen + 2);
+         bcopy (arname, name, arlen);
+         name[arlen] = '(';
+         bcopy (memname, name + arlen + 1, memlen);
+         name[arlen + 1 + memlen] = ')';
+         name[arlen + 1 + memlen + 1] = '\0';
+
+          /* If the archive was found with GPATH, make the change permanent;
+             otherwise defer it until later.  */
+          if (arfile->name == arfile->hname)
+            rename_file (file, name);
+          else
+            rehash_file (file, name);
+          check_renamed (file);
        }
 
       if (!arname_used)
@@ -1029,7 +1053,7 @@ f_mtime (file, search)
        /* The archive doesn't exist, so it's members don't exist either.  */
        return (time_t) -1;
 
-      mtime = ar_member_date (file->name);
+      mtime = ar_member_date (file->hname);
     }
   else
 #endif
@@ -1090,17 +1114,20 @@ f_mtime (file, search)
         * FAT filesystems round time to nearest even second(!). Just
         * allow for any file (NTFS or FAT) to perhaps suffer from this
         * braindamage.
-        *
-        * Apparently, this doesn't happen with the MS-DOS/DJGPP port,
-        * although MS-DOS and MS-Windows 3.X/9X also use FAT filesystems.
         */
        if (mtime > now && (((mtime % 2) == 0) && ((mtime-1) > now)))
 #else
+#ifdef __MSDOS__
+       /* Scrupulous testing indicates that some Windows
+          filesystems can set file times up to 3 sec into the future!  */
+       if (mtime > now + 3)
+#else
         if (mtime > now)
 #endif
+#endif
           {
-            error("*** Warning: File `%s' has modification time in the future",
-                  file->name);
+            error("*** Warning: File `%s' has modification time in the future (%ld > %ld)",
+                  file->name, mtime, now);
             clock_skew_detected = 1;
           }
       }
index 6aa2c96..e1d63a3 100644 (file)
@@ -21,15 +21,15 @@ along with GNU Make; see the file COPYING.  If not, write to
 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include "make.h"
+#include "job.h"
+#include "filedef.h"
 #include "commands.h"
 #include "job.h"
 #include <sys/time.h>
 #include <netdb.h>
 
-#define __STRICT_BSD__         /* Don't make conflicting declarations.  */
 #include "customs.h"
 
-
 char *remote_description = "Customs";
 
 /* File name of the Customs `export' client command.
@@ -42,25 +42,47 @@ static ExportPermit permit;
 /* Normalized path name of the current directory.  */
 static char *normalized_cwd;
 
+/* Call once at startup even if no commands are run.  */
+
+void
+remote_setup ()
+{
+}
+
+/* Called before exit.  */
+
+void
+remote_cleanup ()
+{
+}
+\f
 /* Return nonzero if the next job should be done remotely.  */
 
 int
-start_remote_job_p ()
+start_remote_job_p (first_p)
+     int first_p;
 {
   static int inited = 0;
   int status;
-
-  /* Allow the user to turn off job exportation
-     (useful while he is debugging Customs, for example).  */
-  if (getenv ("GNU_MAKE_NO_CUSTOMS") != 0)
-    return 0;
+  int njobs;
 
   if (!inited)
     {
+      /* Allow the user to turn off job exportation (useful while he is
+         debugging Customs, for example).  */
+      if (getenv ("GNU_MAKE_NO_CUSTOMS") != 0)
+        {
+          inited = -1;
+          return 0;
+        }
+
       /* For secure Customs, make is installed setuid root and
         Customs requires a privileged source port be used.  */
       make_access ();
 
+      if (debug_flag)
+        Rpc_Debug(1);
+
       /* Ping the daemon once to see if it is there.  */
       inited = Customs_Ping () == RPC_SUCCESS ? 1 : -1;
 
@@ -87,6 +109,15 @@ start_remote_job_p ()
   if (inited < 0)
     return 0;
 
+  njobs = job_slots_used;
+  if (!first_p)
+    njobs -= 1;                /* correction for being called from reap_children() */
+
+  /* the first job should run locally, or, if the -l flag is given, we use
+     that as clue as to how many local jobs should be scheduled locally */
+  if (max_load_average < 0 && njobs == 0 || njobs < max_load_average)
+     return 0;
+
   status = Customs_Host (EXPORT_SAME, &permit);
   if (status != RPC_SUCCESS)
     {
@@ -113,8 +144,8 @@ start_remote_job (argv, envp, stdin_fd, is_remote, id_ptr, used_stdin)
      int *id_ptr;
      int *used_stdin;
 {
-  extern int vfork (), execve ();
   char waybill[MAX_DATA_SIZE], msg[128];
+  struct hostent *host;
   struct timeval timeout;
   struct sockaddr_in sin;
   int len;
@@ -150,8 +181,8 @@ start_remote_job (argv, envp, stdin_fd, is_remote, id_ptr, used_stdin)
   /* Modify the waybill as if the remote child had done `child_access ()'.  */
   {
     WayBill *wb = (WayBill *) waybill;
-    wb->euid = wb->ruid;
-    wb->rgid = wb->rgid;
+    wb->ruid = wb->euid;
+    wb->rgid = wb->egid;
   }
 
   /* Send the request to the server, timing out in 20 seconds.  */
@@ -164,26 +195,31 @@ start_remote_job (argv, envp, stdin_fd, is_remote, id_ptr, used_stdin)
                     len, (Rpc_Opaque) waybill,
                     sizeof(msg), (Rpc_Opaque) msg,
                     1, &timeout);
+
+  host = gethostbyaddr((char *)&permit.addr, sizeof(permit.addr), AF_INET);
+
   if (status != RPC_SUCCESS)
     {
       (void) close (retsock);
       (void) close (sock);
-      error ("exporting: %s", Rpc_ErrorMessage (status));
+      error ("exporting to %s: %s",
+             host ? host->h_name : inet_ntoa (permit.addr),
+             Rpc_ErrorMessage (status));
       return 1;
     }
   else if (msg[0] != 'O' || msg[1] != 'k' || msg[2] != '\0')
     {
       (void) close (retsock);
       (void) close (sock);
-      error ("CUSTOMS_IMPORT: %s", msg);
+      error ("exporting to %s: %s",
+             host ? host->h_name : inet_ntoa (permit.addr),
+             msg);
       return 1;
     }
-  else if (debug_flag)
+  else
     {
-      struct hostent *host = gethostbyaddr (&permit.addr, sizeof (permit.addr),
-                                           AF_INET);
-      printf ("Job exported to %s ID %u\n",
-             host == 0 ? inet_ntoa (permit.addr) : host->h_name,
+      error ("*** exported to %s (id %u)",
+             host ? host->h_name : inet_ntoa (permit.addr),
              permit.id);
     }
 
@@ -225,6 +261,7 @@ start_remote_job (argv, envp, stdin_fd, is_remote, id_ptr, used_stdin)
   (void) close (sock);
   *is_remote = 0;
   *id_ptr = pid;
+  *used_stdin = 1;
   return 0;
 }
 \f
index 958c11d..1ff9b04 100644 (file)
@@ -41,7 +41,8 @@ remote_cleanup ()
 /* Return nonzero if the next job should be done remotely.  */
 
 int
-start_remote_job_p ()
+start_remote_job_p (first_p)
+     int first_p;
 {
   return 0;
 }
diff --git a/rule.c b/rule.c
index 831c18c..6933631 100644 (file)
--- a/rule.c
+++ b/rule.c
@@ -50,6 +50,14 @@ unsigned int max_pattern_deps;
 
 unsigned int max_pattern_dep_length;
 
+/* Chain of all pattern-specific variables.  */
+
+static struct pattern_var *pattern_vars;
+
+/* Pointer to last struct in the chain, so we can add onto the end.  */
+
+static struct pattern_var *last_pattern_var;
+
 /* Pointer to structure for the file .SUFFIXES
    whose dependencies are the suffixes to be searched.  */
 
@@ -86,7 +94,7 @@ count_implicit_rule_limits ()
       unsigned int ntargets;
 
       ++num_pattern_rules;
-      
+
       ntargets = 0;
       while (rule->targets[ntargets] != 0)
        ++ntargets;
@@ -157,7 +165,7 @@ count_implicit_rule_limits ()
     end_main_loop:
       rule = next;
     }
-  
+
   if (name != 0)
     free (name);
 }
@@ -336,7 +344,7 @@ new_pattern_rule (rule, override)
                  else
                    last_pattern_rule->next = rule;
                  last_pattern_rule = rule;
-                 
+
                  /* We got one.  Stop looking.  */
                  goto matched;
                }
@@ -519,6 +527,78 @@ create_pattern_rule (targets, target_percents,
     r->terminal = terminal;
 }
 \f
+/* Create a new pattern-specific variable struct.  */
+
+struct pattern_var *
+create_pattern_var (target, suffix)
+     char *target, *suffix;
+{
+  register struct pattern_var *p = 0;
+  unsigned int len = strlen(target);
+
+  /* Look to see if this pattern already exists in the list.  */
+  for (p = pattern_vars; p != NULL; p = p->next)
+    if (p->len == len && !strcmp(p->target, target))
+      break;
+
+  if (p == 0)
+    {
+      p = (struct pattern_var *) xmalloc (sizeof (struct pattern_var));
+      if (last_pattern_var != 0)
+        last_pattern_var->next = p;
+      else
+        pattern_vars = p;
+      last_pattern_var = p;
+      p->next = 0;
+      p->target = target;
+      p->len = len;
+      p->suffix = suffix + 1;
+      p->vars = create_new_variable_set();
+    }
+
+  return p;
+}
+\f
+/* Look up a target in the pattern-specific variable list.  */
+
+struct pattern_var *
+lookup_pattern_var (target)
+     char *target;
+{
+  struct pattern_var *p;
+  unsigned int targlen = strlen(target);
+
+  for (p = pattern_vars; p != 0; p = p->next)
+    {
+      char *stem;
+      unsigned int stemlen;
+
+      if (p->len > targlen)
+        /* It can't possibly match.  */
+        continue;
+
+      /* From the lengths of the filename and the pattern parts,
+         find the stem: the part of the filename that matches the %.  */
+      stem = target + (p->suffix - p->target - 1);
+      stemlen = targlen - p->len + 1;
+
+      /* Compare the text in the pattern before the stem, if any.  */
+      if (stem > target && strncmp (p->target, target, stem - target))
+        continue;
+
+      /* Compare the text in the pattern after the stem, if any.
+         We could test simply use streq, but this way we compare the
+         first two characters immediately.  This saves time in the very
+         common case where the first character matches because it is a
+         period.  */
+      if (*p->suffix == stem[stemlen]
+          && (*p->suffix == '\0'|| streq (&p->suffix[1], &stem[stemlen+1])))
+        break;
+    }
+
+  return p;
+}
+\f
 /* Print the data base of rules.  */
 
 static void                    /* Useful to call from gdb.  */
@@ -586,4 +666,26 @@ print_rule_data_base ()
   if (num_pattern_rules != rules)
     fatal ("BUG: num_pattern_rules wrong!  %u != %u",
           num_pattern_rules, rules);
+
+  puts ("\n# Pattern-specific variable values");
+
+  {
+    struct pattern_var *p;
+
+    rules = 0;
+    for (p = pattern_vars; p != 0; p = p->next)
+      {
+        ++rules;
+
+        printf ("\n%s :\n", p->target);
+        print_variable_set (p->vars->set, "# ");
+      }
+
+    if (rules == 0)
+      puts ("\n# No pattern-specific variable values.");
+    else
+      {
+        printf ("\n# %u pattern-specific variable values", rules);
+      }
+  }
 }
diff --git a/rule.h b/rule.h
index 9c6b1b0..4effeb0 100644 (file)
--- a/rule.h
+++ b/rule.h
@@ -30,6 +30,15 @@ struct rule
     char in_use;               /* If in use by a parent pattern_search.  */
   };
 
+struct pattern_var
+  {
+    struct pattern_var *next;
+    char *target;
+    unsigned int len;
+    char *suffix;
+    struct variable_set_list *vars;
+  };
+
 /* For calling install_pattern_rule.  */
 struct pspec
   {
@@ -51,3 +60,5 @@ extern unsigned int maxsuffix;
 
 extern void install_pattern_rule PARAMS ((struct pspec *p, int terminal));
 extern int new_pattern_rule PARAMS ((struct rule *rule, int override));
+extern struct pattern_var *create_pattern_var PARAMS ((char *target, char *suffix));
+extern struct pattern_var *lookup_pattern_var PARAMS ((char *target));
index b18694b..d64eeec 100644 (file)
@@ -1,3 +1,6 @@
 cd w32\subproc\r
-nmake /f %1 \r
+set MAKE=%2\r
+set MAKEFILE=%1\r
+if x%2 == x set MAKE=nmake\r
+%MAKE% /f %MAKEFILE%\r
 cd ..\..\r
index c0dc3dc..3155a92 100644 (file)
@@ -44,10 +44,8 @@ static struct variable_set_list global_setlist
   = { 0, &global_variable_set };
 struct variable_set_list *current_variable_set_list = &global_setlist;
 
-static struct variable *define_variable_in_set PARAMS ((char *name, unsigned int length,
-                                                       char *value, enum variable_origin origin,
-                                                       int recursive, struct variable_set *set));
-
+static struct variable *lookup_variable_in_set PARAMS ((char *name,
+                          unsigned int length, struct variable_set *set));
 \f
 /* Implement variables.  */
 
@@ -58,7 +56,7 @@ static struct variable *define_variable_in_set PARAMS ((char *name, unsigned int
    If RECURSIVE is nonzero a flag is set in the variable saying
    that it should be recursively re-expanded.  */
 
-static struct variable *
+struct variable *
 define_variable_in_set (name, length, value, origin, recursive, set)
      char *name;
      unsigned int length;
@@ -114,6 +112,7 @@ define_variable_in_set (name, length, value, origin, recursive, set)
   v->origin = origin;
   v->recursive = recursive;
   v->expanding = 0;
+  v->per_target = 0;
   v->export = v_default;
   v->next = set->table[hashval];
   set->table[hashval] = v;
@@ -184,6 +183,34 @@ lookup_variable (name, length)
   return 0;
 }
 \f
+/* Lookup a variable whose name is a string starting at NAME
+   and with LENGTH chars in set SET.  NAME need not be null-terminated.
+   Returns address of the `struct variable' containing all info
+   on the variable, or nil if no such variable is defined.  */
+
+static struct variable *
+lookup_variable_in_set (name, length, set)
+     char *name;
+     unsigned int length;
+     struct variable_set *set;
+{
+  register unsigned int i;
+  register unsigned int hash = 0;
+  register struct variable *v;
+
+  for (i = 0; i < length; ++i)
+    HASH (hash, name[i]);
+  hash %= set->buckets;
+
+  for (v = set->table[hash]; v != 0; v = v->next)
+    if (*v->name == *name
+        && !strncmp (v->name + 1, name + 1, length - 1)
+        && v->name[length] == 0)
+      return v;
+
+  return 0;
+}
+\f
 /* Initialize FILE's variable set list.  If FILE already has a variable set
    list, the topmost variable set is left intact, but the the rest of the
    chain is replaced with FILE->parent's setlist.  */
@@ -245,10 +272,8 @@ pop_variable_scope ()
   free ((char *) set);
 }
 
-/* Create a new variable set and push it on the current setlist.  */
-
-void
-push_new_variable_scope ()
+struct variable_set_list *
+create_new_variable_set ()
 {
   register struct variable_set_list *setlist;
   register struct variable_set *set;
@@ -263,7 +288,16 @@ push_new_variable_scope ()
     xmalloc (sizeof (struct variable_set_list));
   setlist->set = set;
   setlist->next = current_variable_set_list;
-  current_variable_set_list = setlist;
+
+  return setlist;
+}
+
+/* Create a new variable set and push it on the current setlist.  */
+
+struct variable_set_list *
+push_new_variable_scope ()
+{
+  return (current_variable_set_list = create_new_variable_set());
 }
 \f
 /* Merge SET1 into SET0, freeing unused storage in SET1.  */
@@ -506,6 +540,19 @@ target_environment (file)
                   added specially at the end.  */
                continue;
 
+              /* If this is a per-target variable and it hasn't been touched
+                 already then look up the global version and take its export
+                 value.  */
+              if (v->per_target && v->export == v_default)
+                {
+                  struct variable *gv;
+
+                  gv = lookup_variable_in_set(v->name, strlen(v->name),
+                                              &global_variable_set);
+                  if (gv)
+                    v->export = gv->export;
+                }
+
              switch (v->export)
                {
                case v_default:
@@ -524,15 +571,16 @@ target_environment (file)
                  for (++p; *p != '\0'; ++p)
                    if (*p != '_' && (*p < 'a' || *p > 'z')
                        && (*p < 'A' || *p > 'Z') && (*p < '0' || *p > '9'))
-                     break;
+                     continue;
                  if (*p != '\0')
                    continue;
-
-               case v_export:
                  break;
 
-               case v_noexport:
-                 continue;
+                case v_export:
+                  break;
+
+                case v_noexport:
+                  continue;
 
                case v_ifset:
                  if (v->origin == o_default)
@@ -540,9 +588,22 @@ target_environment (file)
                  break;
                }
 
+              /* If this was from a different-sized hash table, then
+                 recalculate the bucket it goes in.  */
+              if (set->buckets != buckets)
+                {
+                  register char *np;
+
+                  j = 0;
+                  for (np = v->name; *np != '\0'; ++np)
+                    HASH (j, *np);
+                  j %= buckets;
+                }
+
              for (ov = table[j]; ov != 0; ov = ov->next)
                if (streq (v->name, ov->variable->name))
                  break;
+
              if (ov == 0)
                {
                  register struct variable_bucket *entry;
@@ -565,6 +626,7 @@ target_environment (file)
       for (b = table[i]; b != 0; b = b->next)
        {
          register struct variable *v = b->variable;
+
          /* If V is recursively expanded and didn't come from the environment,
             expand its value.  If it came from the environment, it should
             go back into the environment unchanged.  */
@@ -607,14 +669,11 @@ target_environment (file)
    from a makefile, an override directive, the environment with
    or without the -e switch, or the command line.
 
-   A variable definition has the form "name = value" or "name := value".
-   Any whitespace around the "=" or ":=" is removed.  The first form
-   defines a variable that is recursively re-evaluated.  The second form
-   defines a variable whose value is variable-expanded at the time of
-   definition and then is evaluated only once at the time of expansion.
+   See the comments for parse_variable_definition().
 
-   If a variable was defined, a pointer to its `struct variable' is returned.
-   If not, NULL is returned.  */
+   If LINE was recognized as a variable definition, a pointer to its `struct
+   variable' is returned.  If LINE is not a variable definition, NULL is
+   returned.  */
 
 struct variable *
 try_variable_definition (filename, lineno, line, origin)
@@ -627,7 +686,8 @@ try_variable_definition (filename, lineno, line, origin)
   register char *p = line;
   register char *beg;
   register char *end;
-  enum { bogus, simple, recursive, append } flavor = bogus;
+  enum { f_bogus,
+         f_simple, f_recursive, f_append, f_conditional } flavor = f_bogus;
   char *name, *expanded_name, *value;
   struct variable *v;
 
@@ -639,14 +699,14 @@ try_variable_definition (filename, lineno, line, origin)
       if (c == '=')
        {
          end = p - 1;
-         flavor = recursive;
+         flavor = f_recursive;
          break;
        }
       else if (c == ':')
        if (*p == '=')
          {
            end = p++ - 1;
-           flavor = simple;
+           flavor = f_simple;
            break;
          }
        else
@@ -655,9 +715,15 @@ try_variable_definition (filename, lineno, line, origin)
       else if (c == '+' && *p == '=')
        {
          end = p++ - 1;
-         flavor = append;
+         flavor = f_append;
          break;
        }
+      else if (c == '?' && *p == '=')
+        {
+          end = p++ - 1;
+          flavor = f_conditional;
+          break;
+        }
       else if (c == '$')
        {
          /* This might begin a variable expansion reference.  Make sure we
@@ -700,31 +766,35 @@ try_variable_definition (filename, lineno, line, origin)
   expanded_name = allocated_variable_expand (name);
 
   if (expanded_name[0] == '\0')
-    {
-      if (filename == 0)
-       fatal ("empty variable name");
-      else
-       makefile_fatal (filename, lineno, "empty variable name");
-    }
+    makefile_fatal (filename, lineno, "empty variable name");
 
   /* Calculate the variable's new value in VALUE.  */
 
   switch (flavor)
     {
-    case bogus:
+    case f_bogus:
       /* Should not be possible.  */
       abort ();
-      return 0;
-    case simple:
+    case f_simple:
       /* A simple variable definition "var := value".  Expand the value.  */
       value = variable_expand (p);
       break;
-    case recursive:
+    case f_conditional:
+      /* A conditional variable definition "var ?= value".
+         The value is set IFF the variable is not defined yet. */
+      v = lookup_variable(expanded_name, strlen(expanded_name));
+      if (v)
+        {
+          free(expanded_name);
+          return v;
+        }
+      /* FALLTHROUGH */
+    case f_recursive:
       /* A recursive variable definition "var = value".
         The value is used verbatim.  */
       value = p;
       break;
-    case append:
+    case f_append:
       /* An appending variable definition "var += value".
         Extract the old value and append the new one.  */
       v = lookup_variable (expanded_name, strlen (expanded_name));
@@ -733,7 +803,7 @@ try_variable_definition (filename, lineno, line, origin)
          /* There was no old value.
             This becomes a normal recursive definition.  */
          value = p;
-         flavor = recursive;
+         flavor = f_recursive;
        }
       else
        {
@@ -744,7 +814,7 @@ try_variable_definition (filename, lineno, line, origin)
          if (v->recursive)
            /* The previous definition of the variable was recursive.
               The new value comes from the unexpanded old and new values.  */
-           flavor = recursive;
+           flavor = f_recursive;
          else
            /* The previous definition of the variable was simple.
               The new value comes from the old value, which was expanded
@@ -791,7 +861,7 @@ try_variable_definition (filename, lineno, line, origin)
                *p = '/';
            }
          v = define_variable (expanded_name, strlen (expanded_name),
-                              shellpath, origin, flavor == recursive);
+                              shellpath, origin, flavor == f_recursive);
        }
       else
        {
@@ -831,7 +901,7 @@ try_variable_definition (filename, lineno, line, origin)
                    *p = '/';
                }
              v = define_variable (expanded_name, strlen (expanded_name),
-                                  shellpath, origin, flavor == recursive);
+                                  shellpath, origin, flavor == f_recursive);
            }
          else
            v = lookup_variable (expanded_name, strlen (expanded_name));
@@ -841,9 +911,26 @@ try_variable_definition (filename, lineno, line, origin)
     }
   else
 #endif /* __MSDOS__ */
+#ifdef WINDOWS32
+  if (origin == o_file
+      && strcmp (expanded_name, "SHELL") == 0) {
+    extern char* default_shell;
+
+    /*
+     * Call shell locator function. If it returns TRUE, then
+        * set no_default_sh_exe to indicate sh was found and
+     * set new value for SHELL variable.
+        */
+    if (find_and_set_default_shell(value)) {
+       v = define_variable (expanded_name, strlen (expanded_name),
+                            default_shell, origin, flavor == f_recursive);
+       no_default_sh_exe = 0;
+    }
+  } else
+#endif
 
   v = define_variable (expanded_name, strlen (expanded_name),
-                      value, origin, flavor == recursive);
+                      value, origin, flavor == f_recursive);
 
   free (expanded_name);
 
@@ -923,7 +1010,7 @@ print_variable (v, prefix)
 /* Print all the variables in SET.  PREFIX is printed before
    the actual variable definitions (everything else is comments).  */
 
-static void
+void
 print_variable_set (set, prefix)
      register struct variable_set *set;
      char *prefix;
index 79d9739..4289c14 100644 (file)
@@ -43,7 +43,8 @@ struct variable
       origin ENUM_BITFIELD (3);        /* Variable origin.  */
     unsigned int recursive:1;  /* Gets recursively re-evaluated.  */
     unsigned int expanding:1;  /* Nonzero if currently being expanded.  */
-    enum
+    unsigned int per_target:1; /* Nonzero if a target-specific variable.  */
+    enum variable_export
       {
        v_export,               /* Export this variable.  */
        v_noexport,             /* Don't export this variable.  */
@@ -68,20 +69,22 @@ struct variable_set_list
     struct variable_set *set;          /* Variable set.  */
   };
 
+extern char *variable_buffer;
 extern struct variable_set_list *current_variable_set_list;
 
 /* expand.c */
 extern char *variable_buffer_output PARAMS ((char *ptr, char *string, unsigned int length));
 extern char *variable_expand PARAMS ((char *line));
-extern char *variable_expand_for_file PARAMS ((char *line, struct file *file));
 extern char *allocated_variable_expand_for_file PARAMS ((char *line, struct file *file));
 #define        allocated_variable_expand(line) \
   allocated_variable_expand_for_file (line, (struct file *) 0)
 extern char *expand_argument PARAMS ((char *str, char *end));
+extern char *variable_expand_string PARAMS ((char *line, char *string,
+                                             long length));
 
 /* function.c */
 extern int handle_function PARAMS ((char **op, char **stringp));
-extern int pattern_matches PARAMS ((char *pattern, char *percent, char *word));
+extern int pattern_matches PARAMS ((char *pattern, char *percent, char *str));
 extern char *subst_expand PARAMS ((char *o, char *text, char *subst, char *replace,
                unsigned int slen, unsigned int rlen, int by_word, int suffix_only));
 extern char *patsubst_expand PARAMS ((char *o, char *text, char *pattern, char *replace,
@@ -91,17 +94,21 @@ extern char *patsubst_expand PARAMS ((char *o, char *text, char *pattern, char *
 extern char *recursively_expand PARAMS ((struct variable *v));
 
 /* variable.c */
-extern void push_new_variable_scope PARAMS ((void));
+extern struct variable_set_list *create_new_variable_set PARAMS ((void));
+extern struct variable_set_list *push_new_variable_scope PARAMS ((void));
 extern void pop_variable_scope PARAMS ((void));
 extern void define_automatic_variables PARAMS ((void));
 extern void initialize_file_variables PARAMS ((struct file *file));
 extern void print_file_variables PARAMS ((struct file *file));
+extern void print_variable_set PARAMS ((struct variable_set *set, char *prefix));
 extern void merge_variable_set_lists PARAMS ((struct variable_set_list **setlist0, struct variable_set_list *setlist1));
 extern struct variable *try_variable_definition PARAMS ((char *filename, unsigned int lineno, char *line, enum variable_origin origin));
 
 extern struct variable *lookup_variable PARAMS ((char *name, unsigned int length));
 extern struct variable *define_variable PARAMS ((char *name, unsigned int length, char *value,
                enum variable_origin origin, int recursive));
+extern struct variable *define_variable_in_set PARAMS ((char *name, unsigned int length,
+               char *value, enum variable_origin origin, int recursive, struct variable_set *set));
 extern struct variable *define_variable_for_file PARAMS ((char *name, unsigned int length,
                char *value, enum variable_origin origin, int recursive, struct file *file));
 extern char **target_environment PARAMS ((struct file *file));
index daaa8b2..2bc93bd 100644 (file)
@@ -1,7 +1,9 @@
-#define KDEBUG 0
 /* vmsfunctions.c */
 
+#define KDEBUG 0
+
 #include <stdio.h>
+#include <ctype.h>
 #include "make.h"
 #ifdef __DECC
 #include <starlet.h>
 #include <fibdef.h>
 #include "vmsdir.h"
 
-DIR *opendir(char *dspec)
+#if __VMS_VER < 70000000
+
+DIR *
+opendir (dspec)
+     char *dspec;
 {
   static struct FAB *dfab;
   struct NAM *dnam;
   char *searchspec;
 
-  if ((dfab = (struct FAB *)xmalloc(sizeof (struct FAB))) == NULL) {
-    printf("Error mallocing for FAB\n");
-    return(NULL);
-  }
-  if ((dnam = (struct NAM *)xmalloc(sizeof (struct NAM))) == NULL) {
-    printf("Error mallocing for NAM\n");
-    free(dfab);
-    return(NULL);
-  }
-  if ((searchspec = (char *)xmalloc(MAXNAMLEN+1)) == NULL) {
-    printf("Error mallocing for searchspec\n");
-    free(dfab);
-    free(dnam);
-    return(NULL);
-  }
-
-  sprintf(searchspec,"%s*.*;",dspec);
+  dfab = (struct FAB *) xmalloc (sizeof (struct FAB));
+  if (! dfab)
+    {
+      printf ("Error mallocing for FAB\n");
+      return (NULL);
+    }
+
+  dnam = (struct NAM *) xmalloc (sizeof (struct NAM));
+  if (! dnam)
+    {
+      printf ("Error mallocing for NAM\n");
+      free (dfab);
+      return (NULL);
+    }
+
+  searchspec = (char *) xmalloc (MAXNAMLEN + 1);
+  if (! searchspec)
+    {
+      printf ("Error mallocing for searchspec\n");
+      free (dfab);
+      free (dnam);
+      return (NULL);
+    }
+
+  sprintf (searchspec, "%s*.*;", dspec);
 
   *dfab = cc$rms_fab;
   dfab->fab$l_fna = searchspec;
-  dfab->fab$b_fns = strlen(searchspec);
+  dfab->fab$b_fns = strlen (searchspec);
   dfab->fab$l_nam = dnam;
 
   *dnam = cc$rms_nam;
   dnam->nam$l_esa = searchspec;
   dnam->nam$b_ess = MAXNAMLEN;
 
-  if (!(sys$parse(dfab) & 1)) {
-    free(dfab);
-    free(dnam);
-    free(searchspec);
-    return(NULL);
-  }
+  if (! (sys$parse (dfab) & 1))
+    {
+      free (dfab);
+      free (dnam);
+      free (searchspec);
+      return (NULL);
+    }
 
-  return(dfab);
+  return (dfab);
 }
 
-#include <ctype.h>
-#define uppercasify(str) { char *tmp; for(tmp = (str); *tmp != '\0'; tmp++) if(islower(*tmp)) *tmp = toupper(*tmp); }
-
-struct direct *readdir(DIR *dfd)
+#define uppercasify(str) \
+  do \
+    { \
+      char *tmp; \
+      for (tmp = (str); *tmp != '\0'; tmp++) \
+        if (islower (*tmp)) \
+          *tmp = toupper (*tmp); \
+    } \
+  while (0)
+
+struct direct *
+readdir (dfd)
+     DIR * dfd;
 {
   static struct direct *dentry;
-  static char resultspec[MAXNAMLEN+1];
+  static char resultspec[MAXNAMLEN + 1];
   int i;
 
-  if ((dentry = (struct direct *)xmalloc(sizeof (struct direct))) == NULL) {
-    printf("Error mallocing for direct\n");
-    return(NULL);
-  }
+  dentry = (struct direct *) xmalloc (sizeof (struct direct));
+  if (! dentry)
+    {
+      printf ("Error mallocing for direct\n");
+      return (NULL);
+    }
 
   dfd->fab$l_nam->nam$l_rsa = resultspec;
   dfd->fab$l_nam->nam$b_rss = MAXNAMLEN;
 
   if (debug_flag)
-    printf(".");
+    printf (".");
 
-  if (!((i = sys$search(dfd)) & 1)) {
-    if (debug_flag)
-      printf("sys$search failed with %d\n", i);
-    free(dentry);
-    return(NULL);
-  }
+  if (!((i = sys$search (dfd)) & 1))
+    {
+      if (debug_flag)
+       printf ("sys$search failed with %d\n", i);
+      free (dentry);
+      return (NULL);
+    }
 
   dentry->d_off = 0;
   if (dfd->fab$l_nam->nam$w_fid == 0)
     dentry->d_fileno = 1;
-  else dentry->d_fileno = dfd->fab$l_nam->nam$w_fid[0]
-                        +dfd->fab$l_nam->nam$w_fid[1]<<16;
+  else
+    dentry->d_fileno = dfd->fab$l_nam->nam$w_fid[0]
+      + dfd->fab$l_nam->nam$w_fid[1] << 16;
   dentry->d_reclen = sizeof (struct direct);
-/*
-  if (!strcmp(dfd->fab$l_nam->nam$l_type,".DIR"))
+#if 0
+  if (!strcmp(dfd->fab$l_nam->nam$l_type, ".DIR"))
     dentry->d_namlen = dfd->fab$l_nam->nam$b_name;
   else
-*/
-    dentry->d_namlen = dfd->fab$l_nam->nam$b_name+dfd->fab$l_nam->nam$b_type;
-  strncpy(dentry->d_name,dfd->fab$l_nam->nam$l_name,dentry->d_namlen);
+#endif
+  dentry->d_namlen = dfd->fab$l_nam->nam$b_name + dfd->fab$l_nam->nam$b_type;
+  strncpy (dentry->d_name, dfd->fab$l_nam->nam$l_name, dentry->d_namlen);
   dentry->d_name[dentry->d_namlen] = '\0';
-  uppercasify(dentry->d_name);
-/*  uvUnFixRCSSeparator(dentry->d_name);*/
+  uppercasify (dentry->d_name);
+#if 0
+  uvUnFixRCSSeparator(dentry->d_name);
+#endif
 
-  return(dentry);
+  return (dentry);
 }
 
-closedir(DIR *dfd)
+closedir (dfd)
+     DIR *dfd;
 {
-  if (dfd != NULL) {
-    if (dfd->fab$l_nam != NULL)
-      free(dfd->fab$l_nam->nam$l_esa);
-    free(dfd->fab$l_nam);
-    free(dfd);
-  }
+  if (dfd)
+    {
+      if (dfd->fab$l_nam)
+       free (dfd->fab$l_nam->nam$l_esa);
+      free (dfd->fab$l_nam);
+      free (dfd);
+    }
 }
+#endif /* compiled for OpenVMS prior to V7.x */
 
-char *getwd(char *cwd)
+char *
+getwd (cwd)
+     char *cwd;
 {
   static char buf[512];
 
-    if (cwd)
-      return(getcwd(cwd,512));
-    else
-      return(getcwd(buf,512));
+  if (cwd)
+    return (getcwd (cwd, 512));
+  else
+    return (getcwd (buf, 512));
 }
 
 int
@@ -133,23 +168,33 @@ vms_stat (name, buf)
 
   static struct FAB Fab;
   static struct NAM Nam;
-  static struct fibdef Fib; /* short fib */
+  static struct fibdef Fib;    /* short fib */
   static struct dsc$descriptor FibDesc =
-    {sizeof(Fib), DSC$K_DTYPE_Z, DSC$K_CLASS_S, (char *)&Fib};
+  { sizeof (Fib), DSC$K_DTYPE_Z, DSC$K_CLASS_S, (char *) &Fib };
   static struct dsc$descriptor_s DevDesc =
-    {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, &Nam.nam$t_dvi[1]};
+  { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, &Nam.nam$t_dvi[1] };
   static char EName[NAM$C_MAXRSS];
   static char RName[NAM$C_MAXRSS];
   static struct dsc$descriptor_s FileName =
-    {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
+  { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0 };
   static struct dsc$descriptor_s string =
-    {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};  
+  { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0 };
   static unsigned long Rdate[2];
   static unsigned long Cdate[2];
-  static struct atrdef Atr[] = {  
-    {sizeof(Rdate),ATR$C_REVDATE,&Rdate[0]}, /* Revision date */
-    {sizeof(Cdate),ATR$C_CREDATE,&Cdate[0]}, /* Creation date */
-    {0,0,0}
+  static struct atrdef Atr[] =
+  {
+#if defined(VAX)
+    /* Revision date */
+    { sizeof (Rdate), ATR$C_REVDATE, (unsigned int) &Rdate[0] },
+    /* Creation date */
+    { sizeof (Cdate), ATR$C_CREDATE, (unsigned int) &Cdate[0] },
+#else
+    /* Revision date */
+    { sizeof (Rdate), ATR$C_REVDATE, &Rdate[0] },
+    /* Creation date */
+    { sizeof (Cdate), ATR$C_CREDATE, &Cdate[0]},
+#endif
+    { 0, 0, 0 }
   };
   static short int DevChan;
   static short int iosb[4];
@@ -158,43 +203,43 @@ vms_stat (name, buf)
 
   /* initialize RMS structures, we need a NAM to retrieve the FID */
   Fab = cc$rms_fab;
-  Fab.fab$l_fna = name ; /* name of file */
-  Fab.fab$b_fns = strlen(name);
-  Fab.fab$l_nam = &Nam; /* FAB has an associated NAM */
-      
+  Fab.fab$l_fna = name;                /* name of file */
+  Fab.fab$b_fns = strlen (name);
+  Fab.fab$l_nam = &Nam;                /* FAB has an associated NAM */
+
   Nam = cc$rms_nam;
-  Nam.nam$l_esa = EName; /* expanded filename */
-  Nam.nam$b_ess = sizeof(EName);
-  Nam.nam$l_rsa = RName; /* resultant filename */
-  Nam.nam$b_rss = sizeof(RName);
+  Nam.nam$l_esa = EName;       /* expanded filename */
+  Nam.nam$b_ess = sizeof (EName);
+  Nam.nam$l_rsa = RName;       /* resultant filename */
+  Nam.nam$b_rss = sizeof (RName);
 
   /* do $PARSE and $SEARCH here */
-  status = sys$parse(&Fab);
+  status = sys$parse (&Fab);
   if (!(status & 1))
     return -1;
 
   DevDesc.dsc$w_length = Nam.nam$t_dvi[0];
-  status = sys$assign(&DevDesc,&DevChan,0,0);
+  status = sys$assign (&DevDesc, &DevChan, 0, 0);
   if (!(status & 1))
     return -1;
 
   FileName.dsc$a_pointer = Nam.nam$l_name;
-  FileName.dsc$w_length = Nam.nam$b_name+Nam.nam$b_type+Nam.nam$b_ver;
-  
+  FileName.dsc$w_length = Nam.nam$b_name + Nam.nam$b_type + Nam.nam$b_ver;
+
   /* Initialize the FIB */
-  for (i=0;i<3;i++)
+  for (i = 0; i < 3; i++)
     {
 #if __DECC
-      Fib.fib$w_fid[i]=Nam.nam$w_fid[i];
-      Fib.fib$w_did[i]=Nam.nam$w_did[i];
+      Fib.fib$w_fid[i] = Nam.nam$w_fid[i];
+      Fib.fib$w_did[i] = Nam.nam$w_did[i];
 #else
-      Fib.fib$r_fid_overlay.fib$w_fid[i]=Nam.nam$w_fid[i];
-      Fib.fib$r_did_overlay.fib$w_did[i]=Nam.nam$w_did[i];
+      Fib.fib$r_fid_overlay.fib$w_fid[i] = Nam.nam$w_fid[i];
+      Fib.fib$r_did_overlay.fib$w_did[i] = Nam.nam$w_did[i];
 #endif
     }
 
-  status = sys$qiow(0,DevChan,IO$_ACCESS,&iosb,0,0,
-                        &FibDesc,&FileName,0,0,&Atr,0);
+  status = sys$qiow (0, DevChan, IO$_ACCESS, &iosb, 0, 0,
+                    &FibDesc, &FileName, 0, 0, &Atr, 0);
   sys$dassgn (DevChan);
   if (!(status & 1))
     return -1;
@@ -206,30 +251,29 @@ vms_stat (name, buf)
   if (status)
     return -1;
 
-  buf->st_mtime = ((Rdate[0]>>24) & 0xff) + ((Rdate[1]<<8) & 0xffffff00);
-  buf->st_ctime = ((Cdate[0]>>24) & 0xff) + ((Cdate[1]<<8) & 0xffffff00);
+  buf->st_mtime = ((Rdate[0] >> 24) & 0xff) + ((Rdate[1] << 8) & 0xffffff00);
+  buf->st_ctime = ((Cdate[0] >> 24) & 0xff) + ((Cdate[1] << 8) & 0xffffff00);
+
   return 0;
 }
 
 char *
-cvt_time(tval)
-  unsigned long tval;
+cvt_time (tval)
+     unsigned long tval;
 {
   static long int date[2];
   static char str[27];
   static struct dsc$descriptor date_str =
-    {26, DSC$K_DTYPE_T, DSC$K_CLASS_S, str};
+  { 26, DSC$K_DTYPE_T, DSC$K_CLASS_S, str };
 
   date[0] = (tval & 0xff) << 24;
-  date[1] = ((tval>>8) & 0xffffff);
+  date[1] = ((tval >> 8) & 0xffffff);
+
+  if ((date[0] == 0) && (date[1] == 0))
+    return ("never");
 
-  if ((date[0]==0) && (date[1]==0))
-    return("never");
-  sys$asctim(0,&date_str,date,0);
-  str[26]='\0';
+  sys$asctim (0, &date_str, date, 0);
+  str[26] = '\0';
 
-  return(str);
+  return (str);
 }
-  
-/* EOF */
index 35e30bd..8d242d7 100644 (file)
--- a/vmsify.c
+++ b/vmsify.c
@@ -727,48 +727,21 @@ vmsify (name, type)
                while (*fptr == '/');
              }
            {                                   /* got '..' or '../' */
-             char cwdbuf[MAXPATHLEN+1];
+             nstate = N_OPEN;
+             *vptr++ = '[';
+             while (count--)
+               *vptr++ = '-';
 
-             s1 = getcwd(cwdbuf, MAXPATHLEN);
-             if (s1 == 0)
+             if (*fptr == 0)   /* had '..' or '../' */
                {
-                 return "";        /* FIXME, err getcwd */
+                 *vptr++ = ']';
+                 state = -1;
                }
-             strcpy (vptr, s1);
-             s = strchr (vptr, ']');
-             if (s != 0)
+             else                      /* had '../xxx' */
                {
-                 nstate = N_OPEN;
-                 while (s > vptr)
-                   {
-                     s--;
-                     if (*s == '[')
-                       {
-                         s++;
-                         strcpy (s, "000000]");
-                         state = -1;
-                         break;
-                       }
-                     else if (*s == '.')
-                       {
-                         if (--count == 0)
-                           {
-                             if (*fptr == 0)   /* had '..' or '../' */
-                               {
-                                 *s++ = ']';
-                                 state = -1;
-                               }
-                             else                      /* had '../xxx' */
-                               {
-                                 state = 9;
-                               }
-                             *s = 0;
-                             break;
-                           }
-                       }
-                   }
+                 state = 9;
                }
-             vptr += strlen (vptr);
+             *vptr = 0;
            }
            break;
 
@@ -782,34 +755,86 @@ vmsify (name, type)
                fptr++;
              }
 
-           {
-             char cwdbuf[MAXPATHLEN+1];
+           if (*fptr)
+             {
+               state = 9;
 
-             s1 = getcwd(cwdbuf, MAXPATHLEN);
-             if (s1 == 0)
-               {
-                 return "";        /*FIXME, err getcwd */
-               }
-             strcpy (vptr, s1);
-             if (*fptr == 0)
-               {
-                 state = -1;
-                 break;
-               }
-             else
-               {
-                 s = strchr (vptr, ']');
-                 if (s == 0)
-                   {
-                     state = -1;
-                     break;
-                   }
-                 *s = 0;
-                 nstate = N_OPEN;
-                 vptr += strlen (vptr);
-                 state = 9;
-               }
-           }
+               switch (type)
+                 {
+                 case 0:
+                   nstate = N_CLOSED;
+                   *vptr++ = '[';
+                   *vptr++ = ']';
+                   break;
+
+                 case 1:
+                   nstate = N_OPEN;
+                   *vptr++ = '[';
+                   break;
+
+                 case 2:
+                   nstate = N_CLOSED;
+                   break;
+                 }
+             }
+           else
+             {
+               if (type == 1)
+                 {
+                   *vptr++ = '[';
+                   *vptr++ = ']';
+                   state = -1;
+                 }
+               else
+                 {
+                   char cwdbuf[MAXPATHLEN+1];
+
+                   s1 = getcwd(cwdbuf, MAXPATHLEN);
+                   if (s1 == 0)
+                     {
+                       return "foo";       /*FIXME, err getcwd */
+                     }
+                   strcpy (vptr, s1);
+                   vptr += strlen (vptr);
+
+                   if (type == 2)
+                     {
+                       s = vptr;
+                       while (s > vmsname)
+                         {
+                           if (*s == '.')
+                             {
+                               *s = ']';
+                               vptr--;
+                               break;
+                             }
+
+                           if (*s == '[')
+                             {
+                               int i;
+                               char *t = vptr - 2;
+                               while (t > s)
+                                 {
+                                   *(t+7) = *t;
+                                   t--;
+                                 }
+                               s++;
+                               for (i = 0; i < 6; i++)
+                                 *s++ = '0';
+                               *s = ']';
+                               vptr += 6;
+                               break;
+                             }
+                           s--;
+                         }
+
+                       strcpy (vptr, ".dir");
+                       vptr += 4;
+                     }
+
+                   state = -1;
+                 }
+             }
            break;
        }
 
diff --git a/vpath.c b/vpath.c
index ed7267b..ab88ac3 100644 (file)
--- a/vpath.c
+++ b/vpath.c
@@ -164,7 +164,7 @@ construct_vpath_list (pattern, dirpath)
   register char **vpath;
   register unsigned int maxvpath;
   unsigned int maxelem;
-  char *percent;
+  char *percent = NULL;
 
   if (pattern != 0)
     {
index ab11d96..f187827 100644 (file)
@@ -27,7 +27,7 @@ CC = cl
 OUTDIR=.\r
 MAKEFILE=NMakefile\r
 \r
-CFLAGS_any = /nologo /MT /W3 /GX /Z7 /YX /D WIN32 /D WINDOWS32 /D _WINDOWS  -I. -I../include\r
+CFLAGS_any = /nologo /MT /W3 /GX /Z7 /YX /D WIN32 /D WINDOWS32 /D _WINDOWS  -I. -I../include -I../..\r
 CFLAGS_debug = $(CFLAGS_any) /Od /D _DEBUG /FR.\WinDebug\ /Fp.\WinDebug\subproc.pch /Fo.\WinDebug/\r
 CFLAGS_release = $(CFLAGS_any) /O2 /FR.\WinRel\ /Fp.\WinRel\subproc.pch /Fo.\WinRel/\r
 \r
@@ -40,6 +40,7 @@ Debug:
 \r
 clean:\r
        rmdir /s /q WinRel WinDebug\r
+       erase *.pdb\r
 \r
 $(OUTDIR):\r
        if not exist .\$@\nul mkdir .\$@\r
index 955f6d5..26ab1cb 100644 (file)
@@ -1,10 +1,10 @@
 if not exist .\WinDebug\nul mkdir .\WinDebug\r
 cl.exe /nologo /MT /W3 /GX /Z7 /YX /Od /I .. /I . /I ../include /D WIN32 /D WINDOWS32 /D _DEBUG /D _WINDOWS /FR.\WinDebug/ /Fp.\WinDebug/subproc.pch /Fo.\WinDebug/ /c misc.c\r
-cl.exe /nologo /MT /W3 /GX /Z7 /YX /Od /I .. /I . /I ../include /D WIN32 /D WINDOWS32 /D _DEBUG /D _WINDOWS /FR.\WinDebug/ /Fp.\WinDebug/subproc.pch /Fo.\WinDebug/ /c sub_proc.c\r
+cl.exe /nologo /MT /W3 /GX /Z7 /YX /Od /I .. /I . /I ../include /I ../.. /D WIN32 /D WINDOWS32 /D _DEBUG /D _WINDOWS /FR.\WinDebug/ /Fp.\WinDebug/subproc.pch /Fo.\WinDebug/ /c sub_proc.c\r
 cl.exe /nologo /MT /W3 /GX /Z7 /YX /Od /I .. /I . /I ../include /D WIN32 /D WINDOWS32 /D _DEBUG /D _WINDOWS /FR.\WinDebug/ /Fp.\WinDebug/subproc.pch /Fo.\WinDebug/ /c w32err.c\r
 lib.exe /NOLOGO /OUT:.\WinDebug\subproc.lib  .\WinDebug/misc.obj  .\WinDebug/sub_proc.obj  .\WinDebug/w32err.obj\r
 if not exist .\WinRel\nul mkdir .\WinRel\r
 cl.exe /nologo /MT /W3 /GX /YX /O2 /I ../include /D WIN32 /D WINDOWS32 /D NDEBUG /D _WINDOWS /FR.\WinRel/ /Fp.\WinRel/subproc.pch /Fo.\WinRel/ /c misc.c\r
-cl.exe /nologo /MT /W3 /GX /YX /O2 /I ../include /D WIN32 /D WINDOWS32 /D NDEBUG /D _WINDOWS /FR.\WinRel/ /Fp.\WinRel/subproc.pch /Fo.\WinRel/ /c sub_proc.c\r
+cl.exe /nologo /MT /W3 /GX /YX /O2 /I ../include /I ../.. /D WIN32 /D WINDOWS32 /D NDEBUG /D _WINDOWS /FR.\WinRel/ /Fp.\WinRel/subproc.pch /Fo.\WinRel/ /c sub_proc.c\r
 cl.exe /nologo /MT /W3 /GX /YX /O2 /I ../include /D WIN32 /D WINDOWS32 /D NDEBUG /D _WINDOWS /FR.\WinRel/ /Fp.\WinRel/subproc.pch /Fo.\WinRel/ /c w32err.c\r
 lib.exe /NOLOGO /OUT:.\WinRel\subproc.lib  .\WinRel/misc.obj  .\WinRel/sub_proc.obj  .\WinRel/w32err.obj\r
index 4166d34..281c81c 100644 (file)
@@ -6,6 +6,7 @@
 #include "sub_proc.h"\r
 #include "proc.h"\r
 #include "w32err.h"\r
+#include "config.h"\r
 \r
 static char *make_command_line( char *shell_name, char *exec_path, char **argv);\r
 \r
@@ -889,170 +890,224 @@ process_cleanup(
 \r
 \r
 /*\r
- * Try to protect against WINDOWS32 argument munging. This function takes\r
- * an argv vector and outputs a 'protected' string as a return\r
- * value. The return code can be safely passed to CreateProcess().\r
+ * Description: \r
+ *      Create a command line buffer to pass to CreateProcess\r
+ *\r
+ * Returns:  the buffer or NULL for failure\r
+ *     Shell case:  sh_name a:/full/path/to/script argv[1] argv[2] ...\r
+ *  Otherwise:   argv[0] argv[1] argv[2] ...\r
  *\r
- * The caller should free the return value.\r
+ * Notes/Dependencies: \r
+ *   CreateProcess does not take an argv, so this command creates a\r
+ *   command line for the executable.  \r
  */\r
 \r
-#define TRACE(x)\r
-static char *fix_command_line(char *args[])\r
+static char *\r
+make_command_line( char *shell_name, char *full_exec_path, char **argv)\r
 {\r
-       int i;\r
-       char *narg;\r
-       char *nargp;\r
-       char *p;\r
-       char *q;\r
-       int alloc_len = 0;\r
-\r
-       for (i = 0; args[i]; i++)\r
-               alloc_len += ((strlen(args[i]) * 2) + 1);\r
-       /* account for possible enclosing quotes and null termination */\r
-       alloc_len += 3;\r
-\r
-       nargp = narg = malloc(alloc_len);\r
-\r
-       for (i = 0; args[i]; i++) {\r
-               p = args[i];\r
-               TRACE(("original arg: %s\n", p));\r
-\r
-               if (*p == '\0') {\r
-                       *nargp++ = '"';\r
-                       *nargp++ = '"';\r
-                       *nargp = '\0';\r
-                       TRACE(("empty string arg: %s\n", nargp-2));\r
-               } else if (strpbrk(p, "\" \t")) {\r
-                       /* point to end of copy buffer */\r
-                       q = narg;\r
-                       q += (alloc_len-1);\r
-                       *q-- = '\0'; /* ensure null terminated string */\r
-                       *q-- = '"';  /* terminating quote of argument */\r
-\r
-                       /* point to end of the input string */\r
-                       p = args[i];\r
-                       p += strlen(args[i]);\r
-                       p--;\r
-\r
-                       /* \r
-                        * Because arg is quoted, escape any backslashes \r
-                        * that might occur at the end of the string which\r
-                        * proceed the closing quote.\r
-                        * Example:\r
-                        *      foo c:\\r
-                        * Becomes:\r
-                        *      "foo c:\\"\r
-                        */\r
-                       while (*p == '\\')\r
-                               *q-- = *p--, *q-- = '\\';\r
+       int             argc = 0;\r
+       char**          argvi;\r
+       int*            enclose_in_quotes = NULL;\r
+       int*            enclose_in_quotes_i;\r
+       unsigned int    bytes_required = 0;\r
+       char*           command_line;\r
+       char*           command_line_i;\r
+\r
+       if (shell_name && full_exec_path) {\r
+               bytes_required\r
+                 = strlen(shell_name) + 1 + strlen(full_exec_path);\r
+               /*\r
+                * Skip argv[0] if any, when shell_name is given.\r
+                */\r
+               if (*argv) argv++;\r
+               /*\r
+                * Add one for the intervening space.\r
+                */\r
+               if (*argv) bytes_required++;\r
+       }\r
+\r
+       argvi = argv;\r
+       while (*(argvi++)) argc++;\r
+\r
+       if (argc) {\r
+               enclose_in_quotes = (int*) calloc(1, argc * sizeof(int));\r
+\r
+               if (!enclose_in_quotes) {\r
+                       return NULL;\r
+               }\r
+       }\r
 \r
-                       /* copy the string in reverse */\r
-                       while (p >= args[i]) {\r
-                               /* copy the character */\r
-                               *q-- = *p--;\r
+       /* We have to make one pass through each argv[i] to see if we need\r
+        * to enclose it in ", so we might as well figure out how much\r
+        * memory we'll need on the same pass.\r
+        */\r
 \r
-                               /* \r
-                                * Escape any double quote found. Also escape\r
-                                * each backslash preceding the double quote.\r
+       argvi = argv;\r
+       enclose_in_quotes_i = enclose_in_quotes;\r
+       while(*argvi) {\r
+               char* p = *argvi;\r
+               unsigned int backslash_count = 0;\r
+\r
+               /*\r
+                * We have to enclose empty arguments in ".\r
+                */\r
+               if (!(*p)) *enclose_in_quotes_i = 1;\r
+\r
+               while(*p) {\r
+                       switch (*p) {\r
+                       case '\"':\r
+                               /*\r
+                                * We have to insert a backslash for each "\r
+                                * and each \ that precedes the ".\r
                                 */\r
-                               if (*(p+1) == '"') {\r
-                                       *q-- = '\\';\r
-                                       if (p >= args[i] && *p == '\\')\r
-                                               while (p >= args[i] && *p == '\\')\r
-                                                       *q-- = *p--, *q-- = '\\';\r
-                               }\r
+                               bytes_required += (backslash_count + 1);\r
+                               backslash_count = 0;\r
+                               break;\r
+\r
+                       case '\\':\r
+                               backslash_count++;\r
+                               break;\r
+       /*\r
+        * At one time we set *enclose_in_quotes_i for '*' or '?' to suppress\r
+        * wildcard expansion in programs linked with MSVC's SETARGV.OBJ so\r
+        * that argv in always equals argv out. This was removed.  Say you have\r
+        * such a program named glob.exe.  You enter\r
+        * glob '*'\r
+        * at the sh command prompt.  Obviously the intent is to make glob do the\r
+        * wildcarding instead of sh.  If we set *enclose_in_quotes_i for '*' or '?',\r
+        * then the command line that glob would see would be\r
+        * glob "*"\r
+        * and the _setargv in SETARGV.OBJ would _not_ expand the *.\r
+        */\r
+                       case ' ':\r
+                       case '\t':\r
+                               *enclose_in_quotes_i = 1;\r
+                               /* fall through */\r
+\r
+                       default:\r
+                               backslash_count = 0;\r
+                               break;\r
                        }\r
+                       \r
+                       /*\r
+                        * Add one for each character in argv[i].\r
+                        */\r
+                       bytes_required++;\r
 \r
-                       /* finish quoting arg, q now points to complete arg */\r
-                       *q = '"';\r
+                       p++;\r
+               }\r
 \r
-                       /* rejustify */\r
-                       memmove(nargp, q, strlen(q) + 1);\r
-                       TRACE(("arg with white space or doublequotes: %s\n", nargp));\r
-                       nargp += strlen(nargp);\r
-               } else {\r
-                       /* just copy the argument, no protection needed */\r
-                       strcpy(nargp, args[i]);\r
-                       TRACE(("plain arg: %s\n", nargp));\r
-                       nargp += strlen(nargp);\r
+               if (*enclose_in_quotes_i) {\r
+                       /*\r
+                        * Add one for each enclosing ",\r
+                        * and one for each \ that precedes the\r
+                        * closing ".\r
+                        */\r
+                       bytes_required += (backslash_count + 2);\r
                }\r
+               \r
+               /*\r
+                * Add one for the intervening space.\r
+                */\r
+               if (*(++argvi)) bytes_required++;\r
+               enclose_in_quotes_i++;\r
+       }\r
 \r
-               /* separate arguments with spaces (if more args to gather) */\r
-               if (args[i+1])\r
-                       *nargp++ = ' ';\r
-               *nargp   = '\0';\r
-       } /* end for */\r
+       /*\r
+        * Add one for the terminating NULL.\r
+        */\r
+       bytes_required++;\r
 \r
-       /* NULL terminate the arg list */\r
-       *nargp = '\0';\r
+       command_line = (char*) malloc(bytes_required);\r
 \r
-       return (narg);\r
-}\r
-#undef TRACE\r
+       if (!command_line) {\r
+               if (enclose_in_quotes) free(enclose_in_quotes);\r
+               return NULL;\r
+       }\r
 \r
-/*\r
- * Description: \r
- *      Create a command line buffer to pass to CreateProcess\r
- *\r
- * Returns:  the buffer or NULL for failure\r
- *     Shell case:  sh_name a:/full/path/to/script argv[1] argv[2] ...\r
- *  Otherwise:   argv[0] argv[1] argv[2] ...\r
- *\r
- * Notes/Dependencies: \r
- *   CreateProcess does not take an argv, so this command creates a\r
- *   command line for the executable.  \r
- */\r
+       command_line_i = command_line;\r
 \r
-static char *\r
-make_command_line( char *shell_name, char *exec_path, char **argv)\r
-{\r
-       char** nargv;\r
-       char*  buf;\r
-       int    i;\r
-       char** shargv = NULL;\r
-       char*  p = NULL;\r
-       char*  q = NULL;\r
-       int    j = 0;\r
\r
-       if (shell_name) {\r
-               /* handle things like: #!/bin/sh -x */\r
-\r
-               /* count tokens */\r
-               q = strdup(shell_name);\r
-               for (j = 0, p = q; (p = strtok(p, " \t")) != NULL; p = NULL, j++);\r
-               free(q);\r
-\r
-               /* copy tokens */\r
-               q = strdup(shell_name);\r
-               shargv = (char **) malloc((j+1) * sizeof (char *));\r
-               for (j = 0, p = q; (p = strtok(p, " \t")) != NULL; p = NULL, j++)\r
-                       shargv[j] = strdup(p);\r
-               shargv[j] = NULL;\r
-               free(q);\r
-\r
-               /* create argv */\r
-               for (i = 0; argv[i]; i++);\r
-               i += (j+1);\r
-               nargv = (char **) malloc(i * sizeof (char *));\r
-               for (i = 0; shargv[i] != NULL; i++)\r
-                       nargv[i] = shargv[i];\r
-               for (j = 0; argv[j]; j++, i++)\r
-                       nargv[i] = argv[j];\r
-               nargv[i] = NULL;\r
-       } else\r
-               nargv = argv;\r
+       if (shell_name && full_exec_path) {\r
+               while(*shell_name) {\r
+                       *(command_line_i++) = *(shell_name++);\r
+               }\r
 \r
-       /* create string suitable for CreateProcess() */\r
-       buf = fix_command_line(nargv);\r
+               *(command_line_i++) = ' ';\r
 \r
-       if (shell_name) {\r
-               for (j = 0; shargv[j]; j++)\r
-                       free(shargv[j]);\r
-               free(shargv);\r
-               free(nargv);\r
+               while(*full_exec_path) {\r
+                       *(command_line_i++) = *(full_exec_path++);\r
+               }\r
+\r
+               if (*argv) {\r
+                       *(command_line_i++) = ' ';\r
+               }\r
        }\r
-       \r
-       return buf;\r
+\r
+       argvi = argv;\r
+       enclose_in_quotes_i = enclose_in_quotes;\r
+\r
+       while(*argvi) {\r
+               char* p = *argvi;\r
+               unsigned int backslash_count = 0;\r
+\r
+               if (*enclose_in_quotes_i) {\r
+                       *(command_line_i++) = '\"';\r
+               }\r
+\r
+               while(*p) {\r
+                       if (*p == '\"') {\r
+                               /*\r
+                                * We have to insert a backslash for the "\r
+                                * and each \ that precedes the ".\r
+                                */\r
+                               backslash_count++;\r
+\r
+                               while(backslash_count) {\r
+                                       *(command_line_i++) = '\\';\r
+                                       backslash_count--;\r
+                               };\r
+\r
+                       } else if (*p == '\\') {\r
+                               backslash_count++;\r
+                       } else {\r
+                               backslash_count = 0;\r
+                       }\r
+\r
+                       /*\r
+                        * Copy the character.\r
+                        */\r
+                       *(command_line_i++) = *(p++);\r
+               }\r
+\r
+               if (*enclose_in_quotes_i) {\r
+                       /*\r
+                        * Add one \ for each \ that precedes the\r
+                        * closing ".\r
+                        */\r
+                       while(backslash_count--) {\r
+                               *(command_line_i++) = '\\';\r
+                       };\r
+                               \r
+                       *(command_line_i++) = '\"';\r
+               }\r
+               \r
+               /*\r
+                * Append an intervening space.\r
+                */\r
+               if (*(++argvi)) {\r
+                       *(command_line_i++) = ' ';\r
+               }\r
+               \r
+               enclose_in_quotes_i++;\r
+       }\r
+\r
+       /*\r
+        * Append the terminating NULL.\r
+        */\r
+       *command_line_i = '\0';\r
+\r
+       if (enclose_in_quotes) free(enclose_in_quotes);\r
+       return command_line;\r
 }\r
 \r
 /*\r