summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Smith <psmith@gnu.org>1998-10-03 05:39:55 +0000
committerPaul Smith <psmith@gnu.org>1998-10-03 05:39:55 +0000
commit2c64fb221a265f9e7fc93374906b1e7540377561 (patch)
tree4603a4b4e5ec9a6366e02f5ece9b6f6e9371084c
parente90887e68aa6dfa8c91af7d3bb2d2799f5a51b5e (diff)
downloadgunmake-2c64fb221a265f9e7fc93374906b1e7540377561.tar.gz
Checkpoint changes. Bug fixes, mostly.
-rw-r--r--ChangeLog234
-rw-r--r--GNUmakefile20
-rw-r--r--acconfig.h8
-rw-r--r--acinclude.m481
-rw-r--r--amiga.c2
-rw-r--r--ar.c25
-rw-r--r--arscan.c6
-rw-r--r--commands.c17
-rw-r--r--commands.h3
-rw-r--r--config.ami.template188
-rw-r--r--config.h-vms.template105
-rw-r--r--config.h.W32.template149
-rw-r--r--configure.in35
-rw-r--r--default.c2
-rw-r--r--dep.h22
-rw-r--r--expand.c40
-rw-r--r--file.c85
-rw-r--r--filedef.h79
-rw-r--r--function.c73
-rw-r--r--getloadavg.c2
-rw-r--r--glob/ChangeLog5
-rw-r--r--implicit.c11
-rw-r--r--job.c304
-rw-r--r--job.h2
-rw-r--r--main.c94
-rw-r--r--make.h506
-rw-r--r--make.texinfo11
-rw-r--r--misc.c159
-rw-r--r--read.c219
-rw-r--r--remake.c97
-rw-r--r--remote-cstms.c8
-rw-r--r--rule.c6
-rw-r--r--rule.h7
-rw-r--r--variable.c7
-rw-r--r--variable.h2
-rw-r--r--vpath.c10
-rw-r--r--w32/subproc/NMakefile120
-rw-r--r--w32/subproc/sub_proc.c2376
38 files changed, 2847 insertions, 2273 deletions
diff --git a/ChangeLog b/ChangeLog
index c3ffc61..bf59080 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,225 @@
+1998-09-21 Paul D. Smith <psmith@gnu.org>
+
+ * job.c (construct_command_argv_internal): Only add COMMAND.COM
+ "@echo off" line for non-UNIXy shells.
+
+1998-09-09 Paul D. Smith <psmith@gnu.org>
+
+ * w32/subproc/sub_proc.c: Add in missing HAVE_MKS_SHELL tests.
+
+1998-09-04 Paul D. Smith <psmith@gnu.org>
+
+ * read.c (read_makefile): If we hit the "missing separator" error,
+ check for the common case of 8 spaces instead of a TAB and give an
+ extra comment to help people out.
+
+1998-08-29 Paul Eggert <eggert@twinsun.com>
+
+ * configure.in (AC_STRUCT_ST_MTIM_NSEC):
+ Renamed from AC_STRUCT_ST_MTIM.
+
+ * acinclude.m4 (AC_STRUCT_ST_MTIM_NSEC): Likewise.
+ Port to UnixWare 2.1.2 and pedantic Solaris 2.6.
+
+ * acconfig.h (ST_MTIM_NSEC):
+ Renamed from HAVE_ST_MTIM, with a new meaning.
+
+ * filedef.h (FILE_TIMESTAMP_FROM_S_AND_NS):
+ Use new ST_MTIM_NSEC macro.
+
+1998-08-26 Paul D. Smith <psmith@gnu.org>
+
+ * remake.c (check_dep): For any intermediate file, not just
+ secondary ones, try implicit and default rules if no explicit
+ rules are given. I'm not sure why this was restricted to
+ secondary rules in the first place.
+
+1998-08-24 Paul D. Smith <psmith@gnu.org>
+
+ * make.texinfo (Special Targets): Update documentation for
+ .INTERMEDIATE: if used with no dependencies, then it does nothing;
+ old docs said it marked all targets as intermediate, which it
+ didn't... and which would be silly :).
+
+ * implicit.c (pattern_search): If we find a dependency in our
+ internal tables, make sure it's not marked intermediate before
+ accepting it as a found_file[].
+
+1998-08-20 Paul D. Smith <psmith@gnu.org>
+
+ * ar.c (ar_glob): Use existing alpha_compare() with qsort.
+ (ar_glob_alphacompare): Remove it.
+
+ Modify Paul Eggert's patch so we don't abandon older systems:
+
+ * configure.in: Warn the user if neither waitpid() nor wait3() is
+ available.
+
+ * job.c (WAIT_NOHANG): Don't syntax error on ancient hosts.
+ (child_handler, dead_children): Define these if WAIT_NOHANG is not
+ available.
+ (reap_children): Only track the dead_children count if no
+ WAIT_NOHANG. Otherwise, it's a boolean.
+
+ * main.c (main): Add back signal handler if no WAIT_NOHANG is
+ available; only use default signal handler if it is.
+
+1998-08-20 Paul Eggert <eggert@twinsun.com>
+
+ Install a more robust signal handling mechanism for systems which
+ support it.
+
+ * job.c (WAIT_NOHANG): Define to a syntax error if our host
+ is truly ancient; this should never happen.
+ (child_handler, dead_children): Remove.
+ (reap_children): Don't try to keep separate track of how many
+ dead children we have, as this is too bug-prone.
+ Just ask the OS instead.
+ (vmsHandleChildTerm): Fix typo in error message; don't mention
+ child_handler.
+
+ * main.c (main): Make sure we're not ignoring SIGCHLD/SIGCLD;
+ do this early, before we could possibly create a subprocess.
+ Just use the default behavior; don't have our own handler.
+
+1998-08-18 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * read.c (read_makefile) [__MSDOS__, WINDOWS32]: Add code to
+ recognize library archive members when dealing with drive spec
+ mess. Discovery and initial fix by George Racz <gracz@mincom.com>.
+
+1998-08-18 Paul D. Smith <psmith@gnu.org>
+
+ * configure.in: Check for stdlib.h explicitly (some hosts have it
+ but don't have STDC_HEADERS).
+ * make.h: Use HAVE_STDLIB_H. Clean up some #defines.
+ * config.ami: Re-compute based on new config.h.in contents.
+ * config.h-vms: Ditto.
+ * config.h.W32: Ditto.
+ * configh.dos: Ditto.
+
+1998-08-17 Paul D. Smith <psmith@gnu.org>
+
+ * make.texinfo: Added copyright year to the printed copy. Removed
+ the price from the manual. Change the top-level reference to
+ running make to be "Invoking make" instead of "make Invocation",
+ to comply with GNU doc standards.
+
+ * make.h (__format__, __printf__): Added support for these in
+ __attribute__ macro.
+ (message, error, fatal): Use ... prototype form under __STDC__.
+ Add __format__ attributes for printf-style functions.
+
+ * configure.in (AC_FUNC_VPRINTF): Check for vprintf()/_doprnt().
+
+ * misc.c(message, error, fatal): Add preprocessor stuff to enable
+ creation of variable-argument functions with appropriate
+ prototypes, that works with ANSI, pre-ANSI, varargs.h, stdarg.h,
+ v*printf(), _doprnt(), or none of the above. Culled from GNU
+ fileutils and slightly modified.
+ (makefile_error, makefile_error): Removed (merged into error() and
+ fatal(), respectively).
+ * amiga.c: Use them.
+ * ar.c: Use them.
+ * arscan.c: Use them.
+ * commands.c: Use them.
+ * expand.c: Use them.
+ * file.c: Use them.
+ * function.c: Use them.
+ * job.c: Use them.
+ * main.c: Use them.
+ * misc.c: Use them.
+ * read.c: Use them.
+ * remake.c: Use them.
+ * remote-cstms.c: Use them.
+ * rule.c: Use them.
+ * variable.c: Use them.
+
+ * make.h (struct floc): New structure to store file location
+ information.
+ * commands.h (struct commands): Use it.
+ * variable.c (try_variable_definition): Use it.
+ * commands.c: Use it.
+ * default.c: Use it.
+ * file.c: Use it.
+ * function.c: Use it.
+ * misc.c: Use it.
+ * read.c: Use it.
+ * rule.c: Use it.
+
+1998-08-16 Paul Eggert <eggert@twinsun.com>
+
+ * filedef.h (FILE_TIMESTAMP_PRINT_LEN_BOUND): Add 10, for nanoseconds.
+
+1998-08-16 Paul Eggert <eggert@twinsun.com>
+
+ * filedef.h (FLOOR_LOG2_SECONDS_PER_YEAR): New macro.
+ (FILE_TIMESTAMP_PRINT_LEN_BOUND): Tighten bound, and try to
+ make it easier to understand.
+
+1998-08-14 Paul D. Smith <psmith@gnu.org>
+
+ * read.c (read_makefile): We've already unquoted any colon chars
+ by the time we're done reading the targets, so arrange for
+ parse_file_seq() on the target list to not do so again.
+
+1998-08-05 Paul D. Smith <psmith@gnu.org>
+
+ * configure.in: Added glob/configure.in data. We'll have the glob
+ code include the regular make config.h, rather than creating its
+ own.
+
+ * getloadavg.c (main): Change return type to int.
+
+1998-08-01 Paul Eggert <eggert@twinsun.com>
+
+ * job.c (reap_children): Ignore unknown children.
+
+1998-07-31 Paul D. Smith <psmith@gnu.org>
+
+ * make.h, filedef.h, dep.h, rule.h, commands.h, remake.c:
+ Add prototypes for functions. Some prototypes needed to be moved
+ in order to get #include order reasonable.
+
+1998-07-30 Paul D. Smith <psmith@gnu.org>
+
+ * make.h: Added MIN/MAX.
+ * filedef.h: Use them; remove FILE_TIMESTAMP_MIN.
+
+1998-07-30 Paul Eggert <eggert@twinsun.com>
+
+ Add support for sub-second timestamp resolution on hosts that
+ support it (just Solaris 2.6, so far).
+
+ * acconfig.h (HAVE_ST_MTIM, uintmax_t): New undefs.
+ * acinclude.m4 (jm_AC_HEADER_INTTYPES_H, AC_STRUCT_ST_MTIM,
+ jm_AC_TYPE_UINTMAX_T): New defuns.
+ * commands.c (delete_target): Convert file timestamp to
+ seconds before comparing to archive timestamp. Extract mod
+ time from struct stat using FILE_TIMESTAMP_STAT_MODTIME.
+ * configure.in (C_STRUCT_ST_MTIM, jm_AC_TYPE_UINTMAX_T): Add.
+ (AC_CHECK_LIB, AC_CHECK_FUNCS): Add clock_gettime.
+ * file.c (snap_deps): Use FILE_TIMESTAMP, not time_t.
+ (file_timestamp_now, file_timestamp_sprintf): New functions.
+ (print_file): Print file timestamps as FILE_TIMESTAMP, not
+ time_t.
+ * filedef.h: Include <inttypes.h> if available and if HAVE_ST_MTIM.
+ (FILE_TIMESTAMP, FILE_TIMESTAMP_STAT_MODTIME, FILE_TIMESTAMP_MIN,
+ FILE_TIMESTAMPS_PER_S, FILE_TIMESTAMP_FROM_S_AND_NS,
+ FILE_TIMESTAMP_DIV, FILE_TIMESTAMP_MOD, FILE_TIMESTAMP_S,
+ FILE_TIMESTAMP_NS, FILE_TIMESTAMP_PRINT_LEN_BOUND): New macros.
+ (file_timestamp_now, file_timestamp_sprintf): New decls.
+ (struct file.last_mtime, f_mtime, file_mtime_1, NEW_MTIME):
+ time_t -> FILE_TIMESTAMP.
+ * implicit.c (pattern_search): Likewise.
+ * vpath.c (vpath_search, selective_vpath_search): Likewise.
+ * main.c (main): Likewise.
+ * remake.c (check_dep, name_mtime, library_search, f_mtime): Likewise.
+ (f_mtime): Use file_timestamp_now instead of `time'.
+ Print file timestamp with file_timestamp_sprintf.
+ * vpath.c (selective_vpath_search): Extract file time stamp from
+ struct stat with FILE_TIMESTAMP_STAT_MODTIME.
+
1998-07-28 Paul D. Smith <psmith@gnu.org>
* Version 3.77 released.
@@ -118,7 +340,7 @@
1998-06-19 Eli Zaretskii <eliz@is.elta.co.il>
- * job.c (start_job_command): Reset execute_by_shell after an empty
+ * job.c (start_job_command): Reset execute_by_shell after an empty
command was skipped.
1998-06-09 Paul D. Smith <psmith@gnu.org>
@@ -503,7 +725,7 @@ Thu Aug 28 17:04:47 1997 Paul D. Smith <psmith@baynetworks.com>
Wed Aug 27 17:09:32 1997 Paul D. Smith <psmith@baynetworks.com>
- * Version 3.75.92
+ * Version 3.75.92
Tue Aug 26 11:59:15 1997 Paul D. Smith <psmith@baynetworks.com>
@@ -538,16 +760,16 @@ Fri Aug 22 1997 Eli Zaretskii <eliz@is.elta.co.il>
Sat Aug 16 00:56:15 1997 John W. Eaton <jwe@bevo.che.wisc.edu>
- * vmsify.c (vmsify, case 11): After translating `..' elements, set
+ * vmsify.c (vmsify, case 11): After translating `..' elements, set
nstate to N_OPEN if there are still more elements to process.
(vmsify, case 2): After translating `foo/bar' up to the slash,
set nstate to N_OPEN, not N_DOT.
Fri Aug 8 15:18:09 1997 John W. Eaton <jwe@bevo.che.wisc.edu>
- * dir.c (vmsstat_dir): Leave name unmodified on exit.
- * make.h (PATH_SEPARATOR_CHAR): Set to comma for VMS.
- * vpath.c: Fix comments to refer to path separator, not colon.
+ * dir.c (vmsstat_dir): Leave name unmodified on exit.
+ * make.h (PATH_SEPARATOR_CHAR): Set to comma for VMS.
+ * vpath.c: Fix comments to refer to path separator, not colon.
(selective_vpath_search): Avoid Unixy slash handling for VMS.
Thu Aug 7 22:24:03 1997 John W. Eaton <jwe@bevo.che.wisc.edu>
diff --git a/GNUmakefile b/GNUmakefile
index 15067c6..97b2e1d 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -7,13 +7,18 @@
NORECURSE = true
+ACLOCALARGS =
+
+CFLAGS = -g -O -Wall -D__USE_FIXED_PROTOTYPES__
+export CFLAGS
+
# 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 ] \
|| $(MAKE) __cfg NORECURSE=
@[ -f Makefile ] \
- || ./configure
+ || CFLAGS='-g -O -Wall -D__USE_FIXED_PROTOTYPES__' ./configure
$(MAKE) -f Makefile $@
.PHONY: __cfg __cfg_basic
@@ -23,21 +28,20 @@ NORECURSE = true
ACCONFIG = acconfig.h
__cfg: __cfg_basic config.h.in TAGS
- cd glob && $(MAKE) -f ../GNUmakefile __cfg_basic ACCONFIG=
ifdef NORECURSE
- @echo ""; echo "Now you should run one of:"; echo ""; \
- echo " make all"; \
+ @echo ""; echo "Now you should run:"; echo ""; \
+ echo " make all"; echo ""; \
+ echo "then, optionally, one of:"; echo ""; \
echo " make dist"; \
echo " make distdir"; \
- echo " make distcheck"; echo ""; \
- echo "Or similar to proceed.";\
+ echo " make distcheck"; \
echo ""
endif
__cfg_basic: aclocal.m4 stamp-h.in configure Makefile.in
aclocal.m4: configure.in $(wildcard acinclude.m4)
- aclocal
+ aclocal $(ACLOCALARGS)
config.h.in: stamp-h.in
stamp-h.in: configure.in aclocal.m4 $(ACCONFIG)
@@ -45,7 +49,7 @@ stamp-h.in: configure.in aclocal.m4 $(ACCONFIG)
echo timestamp > $@
configure: configure.in aclocal.m4
- autoconf
+ autoconf $(ACARGS)
Makefile.in: configure.in config.h.in Makefile.am aclocal.m4
automake --add-missing
diff --git a/acconfig.h b/acconfig.h
index d20cae1..d575b92 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -10,6 +10,10 @@
/* Define this if the SCCS `get' command understands the `-G<file>' option. */
#undef SCCS_GET_MINUS_G
+/* Define to be the nanoseconds member of struct stat's st_mtim,
+ if it exists. */
+#undef ST_MTIM_NSEC
+
/* Define this if the C library defines the variable `sys_siglist'. */
#undef HAVE_SYS_SIGLIST
@@ -18,3 +22,7 @@
/* Define this if you have the `union wait' type in <sys/wait.h>. */
#undef HAVE_UNION_WAIT
+
+/* Define to `unsigned long' or `unsigned long long'
+ if <inttypes.h> doesn't define. */
+#undef uintmax_t
diff --git a/acinclude.m4 b/acinclude.m4
index 343c333..ff51c4c 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -86,7 +86,7 @@ changequote([,])dnl
dnl ---------------------------------------------------------------------------
dnl Got this from the GNU fileutils 3.16r distribution
-dnl by Paul Eggert <egger@twinsun.com>
+dnl by Paul Eggert <eggert@twinsun.com>
dnl ---------------------------------------------------------------------------
dnl The problem is that the default compilation flags in Solaris 2.6 won't
@@ -129,3 +129,82 @@ AC_DEFUN(AC_LFS,
done ;;
esac
])
+
+
+dnl ---------------------------------------------------------------------------
+dnl From Paul Eggert <eggert@twinsun.com>
+
+dnl Define HAVE_INTTYPES_H if <inttypes.h> exists,
+dnl doesn't clash with <sys/types.h>, and declares uintmax_t.
+
+AC_DEFUN(jm_AC_HEADER_INTTYPES_H,
+[
+ if test x = y; then
+ dnl This code is deliberately never run via ./configure.
+ dnl FIXME: this is a gross hack to make autoheader put an entry
+ dnl for `HAVE_INTTYPES_H' in config.h.in.
+ AC_CHECK_FUNCS(INTTYPES_H)
+ fi
+ AC_CACHE_CHECK([for inttypes.h], jm_ac_cv_header_inttypes_h,
+ [AC_TRY_COMPILE(
+ [#include <sys/types.h>
+#include <inttypes.h>],
+ [uintmax_t i = (uintmax_t) -1;],
+ jm_ac_cv_header_inttypes_h=yes,
+ jm_ac_cv_header_inttypes_h=no)])
+ if test $jm_ac_cv_header_inttypes_h = yes; then
+ ac_kludge=HAVE_INTTYPES_H
+ AC_DEFINE_UNQUOTED($ac_kludge)
+ fi
+])
+
+
+dnl ---------------------------------------------------------------------------
+dnl From Paul Eggert <eggert@twinsun.com>
+
+AC_DEFUN(AC_STRUCT_ST_MTIM_NSEC,
+ [AC_CACHE_CHECK([for nanoseconds member of struct stat.st_mtim],
+ ac_cv_struct_st_mtim_nsec,
+ [ac_save_CPPFLAGS="$CPPFLAGS"
+ ac_cv_struct_st_mtim_nsec=no
+ # tv_nsec -- the usual case
+ # _tv_nsec -- Solaris 2.6, if
+ # (defined _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED == 1
+ # && !defined __EXTENSIONS__)
+ # st__tim.tv_nsec -- UnixWare 2.1.2
+ for ac_val in tv_nsec _tv_nsec st__tim.tv_nsec; do
+ CPPFLAGS="$ac_save_CPPFLAGS -DST_MTIM_NSEC=$ac_val"
+ AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/stat.h>], [struct stat s; s.st_mtim.ST_MTIM_NSEC;],
+ [ac_cv_struct_st_mtim_nsec=$ac_val; break])
+ done
+ CPPFLAGS="$ac_save_CPPFLAGS"])
+
+ if test $ac_cv_struct_st_mtim_nsec != no; then
+ AC_DEFINE_UNQUOTED(ST_MTIM_NSEC, $ac_cv_struct_st_mtim_nsec)
+ fi
+ ]
+)
+
+dnl ---------------------------------------------------------------------------
+dnl From Paul Eggert <eggert@twinsun.com>
+
+dnl Define uintmax_t to `unsigned long' or `unsigned long long'
+dnl if <inttypes.h> does not exist.
+
+AC_DEFUN(jm_AC_TYPE_UINTMAX_T,
+[
+ AC_REQUIRE([jm_AC_HEADER_INTTYPES_H])
+ if test $jm_ac_cv_header_inttypes_h = no; then
+ AC_CACHE_CHECK([for unsigned long long], ac_cv_type_unsigned_long_long,
+ [AC_TRY_COMPILE([],
+ [unsigned long long i = (unsigned long long) -1;],
+ ac_cv_type_unsigned_long_long=yes,
+ ac_cv_type_unsigned_long_long=no)])
+ if test $ac_cv_type_unsigned_long_long = yes; then
+ AC_DEFINE(uintmax_t, unsigned long long)
+ else
+ AC_DEFINE(uintmax_t, unsigned long)
+ fi
+ fi
+])
diff --git a/amiga.c b/amiga.c
index a163781..d0e4ff5 100644
--- a/amiga.c
+++ b/amiga.c
@@ -45,7 +45,7 @@ char ** argv;
buffer = AllocMem (len, MEMF_ANY);
if (!buffer)
- fatal ("MyExecute: Cannot allocate space for calling a command");
+ fatal (NILF, "MyExecute: Cannot allocate space for calling a command");
ptr = buffer;
diff --git a/ar.c b/ar.c
index 7167dc3..04d7411 100644
--- a/ar.c
+++ b/ar.c
@@ -46,7 +46,7 @@ ar_name (name)
return 0;
if (p[1] == '(' && end[-1] == ')')
- fatal ("attempt to use unsupported feature: `%s'", name);
+ fatal (NILF, "attempt to use unsupported feature: `%s'", name);
return 1;
}
@@ -137,7 +137,7 @@ int
ar_touch (name)
char *name;
{
- error ("touch archive member is not available on VMS");
+ error (NILF, "touch archive member is not available on VMS");
return -1;
}
#else
@@ -169,22 +169,24 @@ ar_touch (name)
switch (ar_member_touch (arname, memname))
{
case -1:
- error ("touch: Archive `%s' does not exist", arname);
+ error (NILF, "touch: Archive `%s' does not exist", arname);
break;
case -2:
- error ("touch: `%s' is not a valid archive", arname);
+ error (NILF, "touch: `%s' is not a valid archive", arname);
break;
case -3:
perror_with_name ("touch: ", arname);
break;
case 1:
- error ("touch: Member `%s' does not exist in `%s'", memname, arname);
+ error (NILF,
+ "touch: Member `%s' does not exist in `%s'", memname, arname);
break;
case 0:
val = 0;
break;
default:
- error ("touch: Bad return code from ar_member_touch on `%s'", name);
+ error (NILF,
+ "touch: Bad return code from ar_member_touch on `%s'", name);
}
if (!arname_used)
@@ -233,15 +235,6 @@ ar_glob_match (desc, mem, truncated,
return 0L;
}
-/* Alphabetic sorting function for `qsort'. */
-
-static int
-ar_glob_alphacompare (a, b)
- char **a, **b;
-{
- return strcmp (*a, *b);
-}
-
/* Return nonzero if PATTERN contains any metacharacters.
Metacharacters can be quoted with backslashes if QUOTE is nonzero. */
static int
@@ -316,7 +309,7 @@ ar_glob (arname, member_pattern, size)
names[i++] = n->name;
/* Sort them alphabetically. */
- qsort ((char *) names, i, sizeof (*names), ar_glob_alphacompare);
+ qsort ((char *) names, i, sizeof (*names), alpha_compare);
/* Put them back into the chain in the sorted order. */
i = 0;
diff --git a/arscan.c b/arscan.c
index 13ae45b..1fc0a16 100644
--- a/arscan.c
+++ b/arscan.c
@@ -69,7 +69,7 @@ VMS_get_member_info (module, rfa)
&bufdesc.dsc$w_length, 0);
if (! status)
{
- error ("lbr$set_module failed to extract module info, status = %d",
+ error (NILF, "lbr$set_module failed to extract module info, status = %d",
status);
lbr$close (&VMS_lib_idx);
@@ -151,7 +151,7 @@ ar_scan (archive, function, arg)
if (! status)
{
- error ("lbr$ini_control failed with status = %d",status);
+ error (NILF, "lbr$ini_control failed with status = %d",status);
return -2;
}
@@ -162,7 +162,7 @@ ar_scan (archive, function, arg)
if (! status)
{
- error ("unable to open library `%s' to lookup member `%s'",
+ error (NILF, "unable to open library `%s' to lookup member `%s'",
archive, (char *)arg);
return -1;
}
diff --git a/commands.c b/commands.c
index 5646b18..166b96d 100644
--- a/commands.c
+++ b/commands.c
@@ -473,13 +473,13 @@ delete_target (file, on_behalf_of)
#ifndef NO_ARCHIVES
if (ar_name (file->name))
{
- if (ar_member_date (file->name) != file->last_mtime)
+ if (ar_member_date (file->name) != FILE_TIMESTAMP_S (file->last_mtime))
{
if (on_behalf_of)
- error ("*** [%s] Archive member `%s' may be bogus; not deleted",
+ error (NILF, "*** [%s] Archive member `%s' may be bogus; not deleted",
on_behalf_of, file->name);
else
- error ("*** Archive member `%s' may be bogus; not deleted",
+ error (NILF, "*** Archive member `%s' may be bogus; not deleted",
file->name);
}
return;
@@ -488,12 +488,12 @@ delete_target (file, on_behalf_of)
if (stat (file->name, &st) == 0
&& S_ISREG (st.st_mode)
- && (time_t) st.st_mtime != file->last_mtime)
+ && FILE_TIMESTAMP_STAT_MODTIME (st) != file->last_mtime)
{
if (on_behalf_of)
- error ("*** [%s] Deleting file `%s'", on_behalf_of, file->name);
+ error (NILF, "*** [%s] Deleting file `%s'", on_behalf_of, file->name);
else
- error ("*** Deleting file `%s'", file->name);
+ error (NILF, "*** Deleting file `%s'", file->name);
if (unlink (file->name) < 0
&& errno != ENOENT) /* It disappeared; so what. */
perror_with_name ("unlink: ", file->name);
@@ -533,10 +533,11 @@ print_commands (cmds)
fputs ("# commands to execute", stdout);
- if (cmds->filename == 0)
+ if (cmds->fileinfo.filenm == 0)
puts (" (built-in):");
else
- printf (" (from `%s', line %u):\n", cmds->filename, cmds->lineno);
+ printf (" (from `%s', line %lu):\n",
+ cmds->fileinfo.filenm, cmds->fileinfo.lineno);
s = cmds->commands;
while (*s != '\0')
diff --git a/commands.h b/commands.h
index c55fa67..9547fc3 100644
--- a/commands.h
+++ b/commands.h
@@ -21,8 +21,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
struct commands
{
- char *filename; /* File that contains commands. */
- unsigned int lineno; /* Line number in file. */
+ struct floc fileinfo; /* Where commands were defined. */
char *commands; /* Commands text. */
unsigned int ncommand_lines;/* Number of command lines. */
char **command_lines; /* Commands chopped up into lines. */
diff --git a/config.ami.template b/config.ami.template
index b7103ed..523876e 100644
--- a/config.ami.template
+++ b/config.ami.template
@@ -4,121 +4,123 @@
System headers sometimes define this.
We just want to avoid a redefinition error message. */
#ifndef _ALL_SOURCE
-#undef _ALL_SOURCE
+/* #undef _ALL_SOURCE */
#endif
/* Define if using alloca.c. */
#define C_ALLOCA
+/* Define if the closedir function returns void instead of int. */
+/* #undef CLOSEDIR_VOID */
+
/* Define to empty if the keyword does not work. */
-#undef const
+/* #undef const */
/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
This function is required for alloca.c support on those systems. */
-#undef CRAY_STACKSEG_END
+/* #undef CRAY_STACKSEG_END */
/* Define for DGUX with <sys/dg_sys_info.h>. */
-#undef DGUX
+/* #undef DGUX */
/* Define if the `getloadavg' function needs to be run setuid or setgid. */
-#undef GETLOADAVG_PRIVILEGED
+/* #undef GETLOADAVG_PRIVILEGED */
/* Define to `int' if <sys/types.h> doesn't define. */
#define gid_t int
/* Define if you have alloca, as a function or macro. */
-#undef HAVE_ALLOCA
+/* #undef HAVE_ALLOCA */
/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
-#undef HAVE_ALLOCA_H
-
-/* Define if you have the memmove function. */
-#define HAVE_MEMMOVE 1
+/* #undef HAVE_ALLOCA_H */
/* Define if you don't have vprintf but do have _doprnt. */
-#undef HAVE_DOPRNT
+/* #undef HAVE_DOPRNT */
+
+/* Define if your system has a working fnmatch function. */
+/* #undef HAVE_FNMATCH */
/* Define if your system has its own `getloadavg' function. */
-#undef HAVE_GETLOADAVG
+/* #undef HAVE_GETLOADAVG */
/* Define if you have the getmntent function. */
-#undef HAVE_GETMNTENT
+/* #undef HAVE_GETMNTENT */
/* Define if the `long double' type works. */
-#undef HAVE_LONG_DOUBLE
+/* #undef HAVE_LONG_DOUBLE */
/* Define if you support file names longer than 14 characters. */
-#define HAVE_LONG_FILE_NAMES
+#define HAVE_LONG_FILE_NAMES 1
/* Define if you have a working `mmap' system call. */
-#undef HAVE_MMAP
+/* #undef HAVE_MMAP */
/* Define if system calls automatically restart after interruption
by a signal. */
-#undef HAVE_RESTARTABLE_SYSCALLS
+/* #undef HAVE_RESTARTABLE_SYSCALLS */
/* Define if your struct stat has st_blksize. */
-#undef HAVE_ST_BLKSIZE
+/* #undef HAVE_ST_BLKSIZE */
/* Define if your struct stat has st_blocks. */
-#undef HAVE_ST_BLOCKS
+/* #undef HAVE_ST_BLOCKS */
/* Define if you have the strcoll function and it is properly defined. */
-#define HAVE_STRCOLL
+#define HAVE_STRCOLL 1
/* Define if your struct stat has st_rdev. */
-#define HAVE_ST_RDEV
+#define HAVE_ST_RDEV 1
/* Define if you have the strftime function. */
-#define HAVE_STRFTIME
+#define HAVE_STRFTIME 1
/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
-#undef HAVE_SYS_WAIT_H
+/* #undef HAVE_SYS_WAIT_H */
/* Define if your struct tm has tm_zone. */
-#undef HAVE_TM_ZONE
+/* #undef HAVE_TM_ZONE */
/* Define if you don't have tm_zone but do have the external array
tzname. */
-#define HAVE_TZNAME
-/* #define tzname __tzname */
+#define HAVE_TZNAME 1
/* Define if you have <unistd.h>. */
-#define HAVE_UNISTD_H
+#define HAVE_UNISTD_H 1
/* Define if utime(file, NULL) sets file's timestamp to the present. */
-#undef HAVE_UTIME_NULL
+/* #undef HAVE_UTIME_NULL */
/* Define if you have <vfork.h>. */
-#undef HAVE_VFORK_H
+/* #undef HAVE_VFORK_H */
/* Define if you have the vprintf function. */
-#define HAVE_VPRINTF
+#define HAVE_VPRINTF 1
/* Define if you have the wait3 system call. */
-#undef HAVE_WAIT3
+/* #undef HAVE_WAIT3 */
/* Define if on MINIX. */
-#undef _MINIX
+/* #undef _MINIX */
/* Define if your struct nlist has an n_un member. */
-#undef NLIST_NAME_UNION
+/* #undef NLIST_NAME_UNION */
/* Define if you have <nlist.h>. */
-#undef NLIST_STRUCT
+/* #undef NLIST_STRUCT */
/* Define if your C compiler doesn't accept -c and -o together. */
-#undef NO_MINUS_C_MINUS_O
+/* #undef NO_MINUS_C_MINUS_O */
/* Define to `int' if <sys/types.h> doesn't define. */
#define pid_t int
/* Define if the system does not provide POSIX.1 features except
with this defined. */
-#undef _POSIX_1_SOURCE
+/* #undef _POSIX_1_SOURCE */
/* Define if you need to in order for stat and other things to work. */
-#undef _POSIX_SOURCE
+/* #undef _POSIX_SOURCE */
/* Define as the return type of signal handlers (int or void). */
#define RETSIGTYPE void
@@ -126,7 +128,7 @@
/* Define if the setvbuf function takes the buffering type as its second
argument and the buffer pointer as the third, as on System V
before release 3. */
-#undef SETVBUF_REVERSED
+/* #undef SETVBUF_REVERSED */
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
@@ -138,29 +140,29 @@
#define STACK_DIRECTION -1
/* Define if the `S_IS*' macros in <sys/stat.h> do not work properly. */
-#undef STAT_MACROS_BROKEN
+/* #undef STAT_MACROS_BROKEN */
/* Define if you have the ANSI C header files. */
#define STDC_HEADERS
/* Define on System V Release 4. */
-#undef SVR4
+/* #undef SVR4 */
/* Define if `sys_siglist' is declared by <signal.h>. */
-#undef SYS_SIGLIST_DECLARED
+/* #undef SYS_SIGLIST_DECLARED */
/* Define to `int' if <sys/types.h> doesn't define. */
#define uid_t int
/* Define for Encore UMAX. */
-#undef UMAX
+/* #undef UMAX */
/* Define for Encore UMAX 4.3 that has <inq_status/cpustats.h>
instead of <sys/cpustats.h>. */
-#undef UMAX4_3
+/* #undef UMAX4_3 */
/* Define vfork as fork if vfork does not work. */
-#undef vfork
+/* #undef vfork */
/* Name of this package (needed by automake) */
#define PACKAGE "%PACKAGE%"
@@ -172,112 +174,130 @@
#define SCCS_GET "get"
/* Define this if the SCCS `get' command understands the `-G<file>' option. */
-#undef SCCS_GET_MINUS_G
+/* #undef SCCS_GET_MINUS_G */
/* Define this if the C library defines the variable `sys_siglist'. */
-#undef HAVE_SYS_SIGLIST
+/* #undef HAVE_SYS_SIGLIST */
/* Define this if the C library defines the variable `_sys_siglist'. */
-#undef HAVE__SYS_SIGLIST
+/* #undef HAVE__SYS_SIGLIST */
/* Define this if you have the `union wait' type in <sys/wait.h>. */
-#undef HAVE_UNION_WAIT
-
-/* Define this if the POSIX.1 call `sysconf (_SC_OPEN_MAX)' works properly. */
-#undef HAVE_SYSCONF_OPEN_MAX
+/* #undef HAVE_UNION_WAIT */
/* Define if you have the dup2 function. */
-#undef HAVE_DUP2
+/* #undef HAVE_DUP2 */
/* Define if you have the getcwd function. */
-#define HAVE_GETCWD
-
-/* Define if you have the getdtablesize function. */
-#undef HAVE_GETDTABLESIZE
+#define HAVE_GETCWD 1
/* Define if you have the getgroups function. */
-#undef HAVE_GETGROUPS
+/* #undef HAVE_GETGROUPS */
+
+/* Define if you have the gethostbyname function. */
+/* #undef HAVE_GETHOSTBYNAME */
+
+/* Define if you have the gethostname function. */
+/* #undef HAVE_GETHOSTNAME */
+
+/* Define if you have the memmove function. */
+#define HAVE_MEMMOVE 1
/* Define if you have the mktemp function. */
-#define HAVE_MKTEMP
+#define HAVE_MKTEMP 1
/* Define if you have the psignal function. */
-#undef HAVE_PSIGNAL
+/* #undef HAVE_PSIGNAL */
+
+/* Define if you have the pstat_getdynamic function. */
+/* #undef HAVE_PSTAT_GETDYNAMIC */
/* Define if you have the setegid function. */
-#undef HAVE_SETEGID
+/* #undef HAVE_SETEGID */
/* Define if you have the seteuid function. */
-#undef HAVE_SETEUID
+/* #undef HAVE_SETEUID */
/* Define if you have the setlinebuf function. */
-#undef HAVE_SETLINEBUF
+/* #undef HAVE_SETLINEBUF */
/* Define if you have the setregid function. */
-#undef HAVE_SETREGID
+/* #undef HAVE_SETREGID */
/* Define if you have the setreuid function. */
-#undef HAVE_SETREUID
+/* #undef HAVE_SETREUID */
/* Define if you have the sigsetmask function. */
-#undef HAVE_SIGSETMASK
+/* #undef HAVE_SIGSETMASK */
+
+/* Define if you have the socket function. */
+/* #undef HAVE_SOCKET */
+
+/* Define if you have the strcasecmp function. */
+/* #undef HAVE_STRCASECMP */
/* Define if you have the strerror function. */
-#define HAVE_STRERROR
+#define HAVE_STRERROR 1
/* Define if you have the strsignal function. */
-#undef HAVE_STRSIGNAL
+/* #undef HAVE_STRSIGNAL */
/* Define if you have the wait3 function. */
-#undef HAVE_WAIT3
+/* #undef HAVE_WAIT3 */
/* Define if you have the waitpid function. */
-#undef HAVE_WAITPID
+/* #undef HAVE_WAITPID */
/* Define if you have the <dirent.h> header file. */
-#define HAVE_DIRENT_H
+#define HAVE_DIRENT_H 1
/* Define if you have the <fcntl.h> header file. */
-#define HAVE_FCNTL_H
+#define HAVE_FCNTL_H 1
/* Define if you have the <limits.h> header file. */
-#define HAVE_LIMITS_H
+#define HAVE_LIMITS_H 1
/* Define if you have the <mach/mach.h> header file. */
-#undef HAVE_MACH_MACH_H
+/* #undef HAVE_MACH_MACH_H */
/* Define if you have the <memory.h> header file. */
-#undef HAVE_MEMORY_H
+/* #undef HAVE_MEMORY_H */
/* Define if you have the <ndir.h> header file. */
-#undef HAVE_NDIR_H
+/* #undef HAVE_NDIR_H */
+
+/* Define if you have the <stdlib.h> header file. */
+/* #undef HAVE_STDLIB_H */
/* Define if you have the <string.h> header file. */
-#define HAVE_STRING_H
+#define HAVE_STRING_H 1
/* Define if you have the <sys/dir.h> header file. */
-#define HAVE_SYS_DIR_H
+#define HAVE_SYS_DIR_H 1
/* Define if you have the <sys/ndir.h> header file. */
-#undef HAVE_SYS_NDIR_H
+/* #undef HAVE_SYS_NDIR_H */
/* Define if you have the <sys/param.h> header file. */
-#undef HAVE_SYS_PARAM_H
+/* #undef HAVE_SYS_PARAM_H */
/* Define if you have the <sys/timeb.h> header file. */
-#undef HAVE_SYS_TIMEB_H
+/* #undef HAVE_SYS_TIMEB_H */
/* Define if you have the <sys/wait.h> header file. */
-#undef HAVE_SYS_WAIT_H
+/* #undef HAVE_SYS_WAIT_H */
/* Define if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H
+#define HAVE_UNISTD_H 1
/* Define if you have the dgc library (-ldgc). */
-#undef HAVE_LIBDGC
+/* #undef HAVE_LIBDGC */
+
+/* Define if you have the kstat library (-lkstat). */
+/* #undef HAVE_LIBKSTAT */
/* Define if you have the sun library (-lsun). */
-#undef HAVE_LIBSUN
+/* #undef HAVE_LIBSUN */
/* Define for Case Insensitve behavior */
#define HAVE_CASE_INSENSITIVE_FS
diff --git a/config.h-vms.template b/config.h-vms.template
index a41ae06..e44af44 100644
--- a/config.h-vms.template
+++ b/config.h-vms.template
@@ -12,6 +12,9 @@
/* Define if using alloca.c. */
/* #undef C_ALLOCA */
+/* Define if the closedir function returns void instead of int. */
+/* #undef CLOSEDIR_VOID */
+
/* Define to empty if the keyword does not work. */
/* #undef const */
@@ -23,7 +26,7 @@
/* #undef DGUX */
/* Define if the `getloadavg' function needs to be run setuid or setgid. */
-/* #undef GETLOADAVG_PRIVILEGED 1 */
+/* #undef GETLOADAVG_PRIVILEGED */
/* Define to `int' if <sys/types.h> doesn't define. */
/* #undef gid_t */
@@ -32,14 +35,14 @@
#define HAVE_ALLOCA 1
/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
-/* #undef HAVE_ALLOCA_H 1 */
-
-/* Define if you have the memmove function. */
-#define HAVE_MEMMOVE 1
+/* #undef HAVE_ALLOCA_H */
/* Define if you don't have vprintf but do have _doprnt. */
/* #undef HAVE_DOPRNT */
+/* Define if your system has a working fnmatch function. */
+/* #undef HAVE_FNMATCH */
+
/* Define if your system has its own `getloadavg' function. */
/* #undef HAVE_GETLOADAVG */
@@ -66,16 +69,16 @@
/* #undef HAVE_ST_BLOCKS */
/* Define if you have the strcoll function and it is properly defined. */
-/* #undef HAVE_STRCOLL 1 */
+/* #undef HAVE_STRCOLL */
/* Define if your struct stat has st_rdev. */
-/* #undef HAVE_ST_RDEV */
+/* #undef HAVE_ST_RDEV */
/* Define if you have the strftime function. */
/* #undef HAVE_STRFTIME */
/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
-/* #undef HAVE_SYS_WAIT_H 1 */
+/* #undef HAVE_SYS_WAIT_H */
/* Define if your struct tm has tm_zone. */
/* #undef HAVE_TM_ZONE */
@@ -93,13 +96,13 @@
/* #undef HAVE_UTIME_NULL */
/* Define if you have <vfork.h>. */
-/* #undef HAVE_VFORK_H 1 */
+/* #undef HAVE_VFORK_H */
/* Define if you have the vprintf function. */
#define HAVE_VPRINTF 1
/* Define if you have the wait3 system call. */
-/* #undef HAVE_WAIT3 1 */
+/* #undef HAVE_WAIT3 */
/* Define if on MINIX. */
/* #undef _MINIX */
@@ -108,7 +111,7 @@
/* #undef NLIST_NAME_UNION */
/* Define if you have <nlist.h>. */
-/* #undef NLIST_STRUCT 1 */
+/* #undef NLIST_STRUCT */
/* Define if your C compiler doesn't accept -c and -o together. */
/* #undef NO_MINUS_C_MINUS_O */
@@ -129,7 +132,7 @@
/* Define if the setvbuf function takes the buffering type as its second
argument and the buffer pointer as the third, as on System V
before release 3. */
-/* #undef SETVBUF_REVERSED 1 */
+/* #undef SETVBUF_REVERSED */
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
@@ -162,23 +165,23 @@
instead of <sys/cpustats.h>. */
/* #undef UMAX4_3 */
+/* Define vfork as fork if vfork does not work. */
+/* #undef vfork */
+
/* Name of this package (needed by automake) */
#define PACKAGE "%PACKAGE%"
/* Version of this package (needed by automake) */
#define VERSION "%VERSION%"
-/* Define vfork as fork if vfork does not work. */
-/* #undef vfork */
-
/* Define to the name of the SCCS `get' command. */
-/* #undef SCCS_GET "/usr/sccs/get" */
+/* #undef SCCS_GET */
/* Define this if the SCCS `get' command understands the `-G<file>' option. */
-/* #undef SCCS_GET_MINUS_G 1 */
+/* #undef SCCS_GET_MINUS_G */
/* Define this if the C library defines the variable `sys_siglist'. */
-/* #undefine HAVE_SYS_SIGLIST 1 */
+/* #undefine HAVE_SYS_SIGLIST */
/* Define this if the C library defines the variable `_sys_siglist'. */
/* #undef HAVE__SYS_SIGLIST */
@@ -186,45 +189,60 @@
/* Define this if you have the `union wait' type in <sys/wait.h>. */
/* #undef HAVE_UNION_WAIT */
-/* Define this if the POSIX.1 call `sysconf (_SC_OPEN_MAX)' works properly. */
-/* #undef HAVE_SYSCONF_OPEN_MAX */
-
/* Define if you have the dup2 function. */
#define HAVE_DUP2 1
/* Define if you have the getcwd function. */
#define HAVE_GETCWD 1
-/* Define if you have the getdtablesize function. */
-/* #undef HAVE_GETDTABLESIZE 1 */
-
/* Define if you have the getgroups function. */
-/* #undef HAVE_GETGROUPS 1 */
+/* #undef HAVE_GETGROUPS */
+
+/* Define if you have the gethostbyname function. */
+/* #undef HAVE_GETHOSTBYNAME */
+
+/* Define if you have the gethostname function. */
+/* #undef HAVE_GETHOSTNAME */
+
+/* Define if you have the getloadavg function. */
+/* #undef HAVE_GETLOADAVG */
+
+/* Define if you have the memmove function. */
+#define HAVE_MEMMOVE 1
/* Define if you have the mktemp function. */
#define HAVE_MKTEMP 1
/* Define if you have the psignal function. */
-/* #undef HAVE_PSIGNAL 1 */
+/* #undef HAVE_PSIGNAL */
+
+/* Define if you have the pstat_getdynamic function. */
+/* #undef HAVE_PSTAT_GETDYNAMIC */
/* Define if you have the setegid function. */
-/* #undef HAVE_SETEGID 1 */
+/* #undef HAVE_SETEGID */
/* Define if you have the seteuid function. */
-/* #undef HAVE_SETEUID 1 */
+/* #undef HAVE_SETEUID */
/* Define if you have the setlinebuf function. */
-/* #undef HAVE_SETLINEBUF 1 */
+/* #undef HAVE_SETLINEBUF */
/* Define if you have the setregid function. */
-/* #undefine HAVE_SETREGID 1 */
+/* #undefine HAVE_SETREGID */
/* Define if you have the setreuid function. */
-/* #define HAVE_SETREUID 1 */
+/* #define HAVE_SETREUID */
/* Define if you have the sigsetmask function. */
#define HAVE_SIGSETMASK 1
+/* Define if you have the socket function. */
+/* #undef HAVE_SOCKET */
+
+/* Define if you have the strcasecmp function. */
+/* #undef HAVE_STRCASECMP */
+
/* Define if you have the strerror function. */
#define HAVE_STRERROR 1
@@ -232,13 +250,13 @@
/* #undef HAVE_STRSIGNAL */
/* Define if you have the wait3 function. */
-/* #define HAVE_WAIT3 1 */
+/* #undef HAVE_WAIT3 */
/* Define if you have the waitpid function. */
-/* #undef HAVE_WAITPID 1 */
+/* #undef HAVE_WAITPID */
/* Define if you have the <dirent.h> header file. */
-/* #unddef HAVE_DIRENT_H 1 */
+/* #undef HAVE_DIRENT_H */
/* Define if you have the <fcntl.h> header file. */
#ifdef __DECC
@@ -252,17 +270,17 @@
/* #undef HAVE_MACH_MACH_H */
/* Define if you have the <memory.h> header file. */
-/* #undef HAVE_MEMORY_H 1 */
+/* #undef HAVE_MEMORY_H */
/* Define if you have the <ndir.h> header file. */
/* #undef HAVE_NDIR_H */
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
/* Define if you have the <string.h> header file. */
#define HAVE_STRING_H 1
-/* Define if you have the <pwd.h> header file. */
-/* #undef HAVE_PWD_H */
-
/* Define if you have the <sys/dir.h> header file. */
/* #undef HAVE_SYS_DIR_H */
@@ -270,24 +288,29 @@
/* #undef HAVE_SYS_NDIR_H */
/* Define if you have the <sys/param.h> header file. */
-/* #undef HAVE_SYS_PARAM_H 1 */
+/* #undef HAVE_SYS_PARAM_H */
/* Define if you have the <sys/timeb.h> header file. */
#define HAVE_SYS_TIMEB_H 1
/* Define if you have the <sys/wait.h> header file. */
-/* #undef HAVE_SYS_WAIT_H 1 */
+/* #undef HAVE_SYS_WAIT_H */
+
+/* Define if you have the <unistd.h> header file. */
+/* #undef HAVE_UNISTD_H */
/* Define if you have the dgc library (-ldgc). */
/* #undef HAVE_LIBDGC */
+/* Define if you have the kstat library (-lkstat). */
+/* #undef HAVE_LIBKSTAT */
+
/* Define if you have the sun library (-lsun). */
/* #undef HAVE_LIBSUN */
/* VMS specific */
#define HAVE_VMSDIR_H 1
-#define HAVE_STDLIB_H 1
#define INCLUDEDIR "sys$sysroot:[syslib]"
#define LIBDIR "sys$sysroot:[syslib]"
diff --git a/config.h.W32.template b/config.h.W32.template
index aa5a027..79bb6cd 100644
--- a/config.h.W32.template
+++ b/config.h.W32.template
@@ -4,24 +4,27 @@
System headers sometimes define this.
We just want to avoid a redefinition error message. */
#ifndef _ALL_SOURCE
-#undef _ALL_SOURCE
+/* #undef _ALL_SOURCE */
#endif
/* Define if using alloca.c. */
-#undef C_ALLOCA
+/* #undef C_ALLOCA */
+
+/* Define if the closedir function returns void instead of int. */
+/* #undef CLOSEDIR_VOID */
/* Define to empty if the keyword does not work. */
-#undef const
+/* #undef const */
/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
This function is required for alloca.c support on those systems. */
-#undef CRAY_STACKSEG_END
+/* #undef CRAY_STACKSEG_END */
/* Define for DGUX with <sys/dg_sys_info.h>. */
-#undef DGUX
+/* #undef DGUX */
/* Define if the `getloadavg' function needs to be run setuid or setgid. */
-#undef GETLOADAVG_PRIVILEGED
+/* #undef GETLOADAVG_PRIVILEGED */
/* Define to `int' if <sys/types.h> doesn't define. */
#undef gid_t
@@ -32,40 +35,39 @@
#define HAVE_ALLOCA 1
/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
-#undef HAVE_ALLOCA_H
-
-/* Define if you have the memmove function. */
-#undef HAVE_MEMMOVE
-#define HAVE_MEMMOVE 1
+/* #undef HAVE_ALLOCA_H */
/* Define if you don't have vprintf but do have _doprnt. */
-#undef HAVE_DOPRNT
+/* #undef HAVE_DOPRNT */
+
+/* Define if your system has a working fnmatch function. */
+/* #undef HAVE_FNMATCH */
/* Define if your system has its own `getloadavg' function. */
-#undef HAVE_GETLOADAVG
+/* #undef HAVE_GETLOADAVG */
/* Define if you have the getmntent function. */
-#undef HAVE_GETMNTENT
+/* #undef HAVE_GETMNTENT */
/* Define if the `long double' type works. */
-#undef HAVE_LONG_DOUBLE
+/* #undef HAVE_LONG_DOUBLE */
/* Define if you support file names longer than 14 characters. */
#undef HAVE_LONG_FILE_NAMES
#define HAVE_LONG_FILE_NAMES 1
/* Define if you have a working `mmap' system call. */
-#undef HAVE_MMAP
+/* #undef HAVE_MMAP */
/* Define if system calls automatically restart after interruption
by a signal. */
-#undef HAVE_RESTARTABLE_SYSCALLS
+/* #undef HAVE_RESTARTABLE_SYSCALLS */
/* Define if your struct stat has st_blksize. */
-#undef HAVE_ST_BLKSIZE
+/* #undef HAVE_ST_BLKSIZE */
/* Define if your struct stat has st_blocks. */
-#undef HAVE_ST_BLOCKS
+/* #undef HAVE_ST_BLOCKS */
/* Define if you have the strcoll function and it is properly defined. */
#undef HAVE_STRCOLL
@@ -80,10 +82,10 @@
#define HAVE_STRFTIME 1
/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
-#undef HAVE_SYS_WAIT_H
+/* #undef HAVE_SYS_WAIT_H */
/* Define if your struct tm has tm_zone. */
-#undef HAVE_TM_ZONE
+/* #undef HAVE_TM_ZONE */
/* Define if you don't have tm_zone but do have the external array
tzname. */
@@ -91,33 +93,33 @@
#define HAVE_TZNAME 1
/* Define if you have <unistd.h>. */
-#undef 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 1
/* Define if you have <vfork.h>. */
-#undef HAVE_VFORK_H
+/* #undef HAVE_VFORK_H */
/* Define if you have the vprintf function. */
#undef HAVE_VPRINTF
#define HAVE_VPRINTF 1
/* Define if you have the wait3 system call. */
-#undef HAVE_WAIT3
+/* #undef HAVE_WAIT3 */
/* Define if on MINIX. */
-#undef _MINIX
+/* #undef _MINIX */
/* Define if your struct nlist has an n_un member. */
-#undef NLIST_NAME_UNION
+/* #undef NLIST_NAME_UNION */
/* Define if you have <nlist.h>. */
-#undef NLIST_STRUCT
+/* #undef NLIST_STRUCT */
/* Define if your C compiler doesn't accept -c and -o together. */
-#undef NO_MINUS_C_MINUS_O
+/* #undef NO_MINUS_C_MINUS_O */
/* Define to `int' if <sys/types.h> doesn't define. */
#undef pid_t
@@ -125,7 +127,7 @@
/* Define if the system does not provide POSIX.1 features except
with this defined. */
-#undef _POSIX_1_SOURCE
+/* #undef _POSIX_1_SOURCE */
/* Define if you need to in order for stat and other things to work. */
#undef _POSIX_SOURCE
@@ -138,7 +140,7 @@
/* Define if the setvbuf function takes the buffering type as its second
argument and the buffer pointer as the third, as on System V
before release 3. */
-#undef SETVBUF_REVERSED
+/* #undef SETVBUF_REVERSED */
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
@@ -147,34 +149,34 @@
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown
*/
-#undef STACK_DIRECTION
+/* #undef STACK_DIRECTION */
/* Define if the `S_IS*' macros in <sys/stat.h> do not work properly. */
-#undef STAT_MACROS_BROKEN
+/* #undef STAT_MACROS_BROKEN */
/* Define if you have the ANSI C header files. */
#undef STDC_HEADERS
#define STDC_HEADERS 1
/* Define on System V Release 4. */
-#undef SVR4
+/* #undef SVR4 */
/* Define if `sys_siglist' is declared by <signal.h>. */
-#undef SYS_SIGLIST_DECLARED
+/* #undef SYS_SIGLIST_DECLARED */
/* Define to `int' if <sys/types.h> doesn't define. */
#undef uid_t
#define uid_t int
/* Define for Encore UMAX. */
-#undef UMAX
+/* #undef UMAX */
/* Define for Encore UMAX 4.3 that has <inq_status/cpustats.h>
instead of <sys/cpustats.h>. */
-#undef UMAX4_3
+/* #undef UMAX4_3 */
/* Define vfork as fork if vfork does not work. */
-#undef vfork
+/* #undef vfork */
/* Name of this package (needed by automake) */
#define PACKAGE "%PACKAGE%"
@@ -187,16 +189,16 @@
#define SCCS_GET "echo no sccs get"
/* Define this if the SCCS `get' command understands the `-G<file>' option. */
-#undef SCCS_GET_MINUS_G
+/* #undef SCCS_GET_MINUS_G */
/* Define this if the C library defines the variable `sys_siglist'. */
-#undef HAVE_SYS_SIGLIST
+/* #undef HAVE_SYS_SIGLIST */
/* Define this if the C library defines the variable `_sys_siglist'. */
-#undef HAVE__SYS_SIGLIST
+/* #undef HAVE__SYS_SIGLIST */
/* Define this if you have the `union wait' type in <sys/wait.h>. */
-#undef HAVE_UNION_WAIT
+/* #undef HAVE_UNION_WAIT */
/* Define if you have the dup2 function. */
#undef HAVE_DUP2
@@ -207,45 +209,67 @@
#define HAVE_GETCWD 1
/* Define if you have the getgroups function. */
-#undef HAVE_GETGROUPS
+/* #undef HAVE_GETGROUPS */
+
+/* Define if you have the gethostbyname function. */
+/* #undef HAVE_GETHOSTBYNAME */
+
+/* Define if you have the gethostname function. */
+/* #undef HAVE_GETHOSTNAME */
+
+/* Define if you have the getloadavg function. */
+/* #undef HAVE_GETLOADAVG */
+
+/* Define if you have the memmove function. */
+#undef HAVE_MEMMOVE
+#define HAVE_MEMMOVE 1
/* Define if you have the mktemp function. */
#undef HAVE_MKTEMP
#define HAVE_MKTEMP 1
/* Define if you have the psignal function. */
-#undef HAVE_PSIGNAL
+/* #undef HAVE_PSIGNAL */
+
+/* Define if you have the pstat_getdynamic function. */
+/* #undef HAVE_PSTAT_GETDYNAMIC */
/* Define if you have the setegid function. */
-#undef HAVE_SETEGID
+/* #undef HAVE_SETEGID */
/* Define if you have the seteuid function. */
-#undef HAVE_SETEUID
+/* #undef HAVE_SETEUID */
/* Define if you have the setlinebuf function. */
-#undef HAVE_SETLINEBUF
+/* #undef HAVE_SETLINEBUF */
/* Define if you have the setregid function. */
-#undef HAVE_SETREGID
+/* #undef HAVE_SETREGID */
/* Define if you have the setreuid function. */
-#undef HAVE_SETREUID
+/* #undef HAVE_SETREUID */
/* Define if you have the sigsetmask function. */
-#undef HAVE_SIGSETMASK
+/* #undef HAVE_SIGSETMASK */
+
+/* Define if you have the socket function. */
+/* #undef HAVE_SOCKET */
+
+/* Define if you have the strcasecmp function. */
+/* #undef HAVE_STRCASECMP */
/* Define if you have the strerror function. */
#undef HAVE_STRERROR
#define HAVE_STRERROR 1
/* Define if you have the strsignal function. */
-#undef HAVE_STRSIGNAL
+/* #undef HAVE_STRSIGNAL */
/* Define if you have the wait3 function. */
-#undef HAVE_WAIT3
+/* #undef HAVE_WAIT3 */
/* Define if you have the waitpid function. */
-#undef HAVE_WAITPID
+/* #undef HAVE_WAITPID */
/* Define if you have the <dirent.h> header file. */
#undef HAVE_DIRENT_H
@@ -260,43 +284,46 @@
#define HAVE_LIMITS_H 1
/* Define if you have the <mach/mach.h> header file. */
-#undef HAVE_MACH_MACH_H
+/* #undef HAVE_MACH_MACH_H */
/* Define if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
#define HAVE_MEMORY_H 1
/* Define if you have the <ndir.h> header file. */
-#undef HAVE_NDIR_H
+/* #undef HAVE_NDIR_H */
/* Define if you have the <string.h> header file. */
#undef HAVE_STRING_H
#define HAVE_STRING_H 1
/* Define if you have the <sys/dir.h> header file. */
-#undef HAVE_SYS_DIR_H
+/* #undef HAVE_SYS_DIR_H */
/* Define if you have the <sys/ndir.h> header file. */
-#undef HAVE_SYS_NDIR_H
+/* #undef HAVE_SYS_NDIR_H */
/* Define if you have the <sys/param.h> header file. */
-#undef HAVE_SYS_PARAM_H
+/* #undef HAVE_SYS_PARAM_H */
/* Define if you have the <sys/timeb.h> header file. */
#undef 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
+/* #undef HAVE_SYS_WAIT_H */
/* Define if you have the <unistd.h> header file. */
-#undef HAVE_UNISTD_H
+/* #undef HAVE_UNISTD_H */
/* Define if you have the dgc library (-ldgc). */
-#undef HAVE_LIBDGC
+/* #undef HAVE_LIBDGC */
+
+/* Define if you have the kstat library (-lkstat). */
+/* #undef HAVE_LIBKSTAT */
/* Define if you have the sun library (-lsun). */
-#undef HAVE_LIBSUN
+/* #undef HAVE_LIBSUN */
/*
* Refer to README.W32 for info on the following settings
diff --git a/configure.in b/configure.in
index 8fb99f7..ebc9cdf 100644
--- a/configure.in
+++ b/configure.in
@@ -3,9 +3,8 @@ 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.77)
+AM_INIT_AUTOMAKE(make, 3.77.90)
AM_CONFIG_HEADER(config.h)
-AC_CONFIG_SUBDIRS(glob)
AM_CONDITIONAL(MAINT_MAKEFILE, test -r $srcdir/maintMakefile)
@@ -14,6 +13,8 @@ dnl Regular configure stuff
AC_PROG_MAKE_SET
AC_PROG_CC
AC_PROG_INSTALL
+AC_CHECK_PROG(AR, ar, ar, ar)
+AC_PROG_RANLIB
AC_PROG_CPP dnl Later checks need this.
dnl AC_ARG_PROGRAM -- implied by AM_INIT_AUTOMAKE; gives errors if run twice.
AC_AIX
@@ -30,12 +31,15 @@ AC_HEADER_DIRENT
AC_TYPE_UID_T dnl Also does gid_t.
AC_TYPE_PID_T
AC_TYPE_SIGNAL
-AC_CHECK_HEADERS(unistd.h limits.h sys/param.h fcntl.h string.h memory.h \
- sys/timeb.h)
+AC_CHECK_HEADERS(stdlib.h unistd.h limits.h sys/param.h fcntl.h string.h \
+ memory.h sys/timeb.h)
AC_PROG_CC_C_O
AC_C_CONST dnl getopt needs this.
AC_HEADER_STAT
+AC_STRUCT_ST_MTIM_NSEC
+jm_AC_TYPE_UINTMAX_T
+
AC_SUBST(LIBOBJS)
AC_DEFUN(AC_CHECK_SYMBOL, [dnl
@@ -51,19 +55,25 @@ changequote([,])dnl
fi
AC_MSG_RESULT($ac_cv_check_symbol_$1)])dnl
+# clock_gettime is in -lposix4 in Solaris 2.6.
+AC_CHECK_LIB(posix4, clock_gettime)
+
AC_CHECK_FUNCS(memmove psignal mktemp pstat_getdynamic \
- dup2 getcwd sigsetmask getgroups setlinebuf \
+ clock_gettime dup2 getcwd sigsetmask getgroups setlinebuf \
seteuid setegid setreuid setregid strerror strsignal)
AC_CHECK_SYMBOL(sys_siglist)
AC_FUNC_ALLOCA
AC_FUNC_VFORK
+AC_FUNC_VPRINTF
+AC_FUNC_STRCOLL
+AC_FUNC_CLOSEDIR_VOID
AC_FUNC_SETVBUF_REVERSED
AC_FUNC_GETLOADAVG
AC_CHECK_LIB(kstat, kstat_open)
-AC_FUNC_STRCOLL
# Check out the wait reality.
-AC_CHECK_HEADERS(sys/wait.h) AC_CHECK_FUNCS(waitpid wait3)
+AC_CHECK_HEADERS(sys/wait.h)
+AC_CHECK_FUNCS(waitpid wait3)
AC_MSG_CHECKING(for union wait)
AC_CACHE_VAL(make_cv_union_wait, [dnl
AC_TRY_LINK([#include <sys/types.h>
@@ -137,7 +147,7 @@ if ( /usr/sccs/admin -n s.conftest || admin -n s.conftest ) >/dev/null 2>&1 &&
fi
rm -f s.conftest conftoast
-AC_OUTPUT(Makefile build.sh)
+AC_OUTPUT(Makefile glob/Makefile build.sh)
case "$make_badcust" in
yes) echo
@@ -159,6 +169,15 @@ case "$with_customs" in
fi ;;
esac
+case "$ac_cv_func_waitpid/$ac_cv_func_wait3" in
+ no/no) echo
+ echo "WARNING: Your system has neither waitpid() nor wait3()."
+ echo " Without one of these, signal handling is unreliable."
+ echo " You should be aware that run GNU make with -j could"
+ echo " result in erratic behavior."
+ echo ;;
+esac
+
dnl Local Variables:
dnl comment-start: "dnl "
dnl comment-end: ""
diff --git a/default.c b/default.c
index 653bc81..06f56fa 100644
--- a/default.c
+++ b/default.c
@@ -468,7 +468,7 @@ install_default_suffix_rules ()
if (f->cmds == 0)
{
f->cmds = (struct commands *) xmalloc (sizeof (struct commands));
- f->cmds->filename = 0;
+ f->cmds->fileinfo.filenm = 0;
f->cmds->commands = s[1];
f->cmds->command_lines = 0;
}
diff --git a/dep.h b/dep.h
index fa3e073..2f9561c 100644
--- a/dep.h
+++ b/dep.h
@@ -16,6 +16,16 @@ 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. */
+/* Flag bits for the second argument to `read_makefile'.
+ These flags are saved in the `changed' field of each
+ `struct dep' in the chain returned by `read_all_makefiles'. */
+
+#define RM_NO_DEFAULT_GOAL (1 << 0) /* Do not set default goal. */
+#define RM_INCLUDED (1 << 1) /* Search makefile search path. */
+#define RM_DONTCARE (1 << 2) /* No error if it doesn't exist. */
+#define RM_NO_TILDE (1 << 3) /* Don't expand ~ in file name. */
+#define RM_NOFLAG 0
+
/* Structure representing one dependency of a file.
Each struct file's `deps' points to a chain of these,
chained through the `next'.
@@ -59,13 +69,7 @@ extern struct nameseq *ar_glob PARAMS ((char *arname, char *member_pattern, unsi
extern char *dep_name ();
#endif
+extern struct dep *copy_dep_chain PARAMS ((struct dep *d));
extern struct dep *read_all_makefiles PARAMS ((char **makefiles));
-
-/* Flag bits for the second argument to `read_makefile'.
- These flags are saved in the `changed' field of each
- `struct dep' in the chain returned by `read_all_makefiles'. */
-#define RM_NO_DEFAULT_GOAL (1 << 0) /* Do not set default goal. */
-#define RM_INCLUDED (1 << 1) /* Search makefile search path. */
-#define RM_DONTCARE (1 << 2) /* No error if it doesn't exist. */
-#define RM_NO_TILDE (1 << 3) /* Don't expand ~ in file name. */
-#define RM_NOFLAG 0
+extern int update_goal_chain PARAMS ((struct dep *goals, int makefiles));
+extern void uniquize_deps PARAMS ((struct dep *));
diff --git a/expand.c b/expand.c
index 3f4bcfc..31c4024 100644
--- a/expand.c
+++ b/expand.c
@@ -95,17 +95,9 @@ recursively_expand (v)
char *value;
if (v->expanding)
- {
- /* Expanding V causes infinite recursion. Lose. */
- if (reading_filename == 0)
- fatal ("Recursive variable `%s' references itself (eventually)",
- v->name);
- else
- makefile_fatal
- (reading_filename, *reading_lineno_ptr,
- "Recursive variable `%s' references itself (eventually)",
- v->name);
- }
+ /* Expanding V causes infinite recursion. Lose. */
+ fatal (reading_file,
+ "Recursive variable `%s' references itself (eventually)", v->name);
v->expanding = 1;
value = allocated_variable_expand (v->value);
@@ -125,14 +117,8 @@ warn_undefined (name, length)
unsigned int length;
{
if (warn_undefined_variables_flag)
- {
- static const char warnmsg[] = "warning: undefined variable `%.*s'";
- if (reading_filename != 0)
- makefile_error (reading_filename, *reading_lineno_ptr,
- warnmsg, length, name);
- else
- error (warnmsg, length, name);
- }
+ error (reading_file,
+ "warning: undefined variable `%.*s'", (int)length, name);
}
/* Expand a simple reference to variable NAME, which is LENGTH chars long. */
@@ -243,14 +229,8 @@ variable_expand_string (line, string, length)
end = index (beg, closeparen);
if (end == 0)
- {
- /* Unterminated variable reference. */
- if (reading_filename != 0)
- makefile_fatal (reading_filename, *reading_lineno_ptr,
- "unterminated variable reference");
- else
- fatal ("unterminated variable reference");
- }
+ /* Unterminated variable reference. */
+ fatal (reading_file, "unterminated variable reference");
p1 = lindex (beg, end, '$');
if (p1 != 0)
{
@@ -460,8 +440,7 @@ variable_expand_for_file (line, file)
save = current_variable_set_list;
current_variable_set_list = file->variables;
- reading_filename = file->cmds->filename;
- reading_lineno_ptr = &file->cmds->lineno;
+ reading_file = &file->cmds->fileinfo;
fnext = file->variables->next;
/* See if there's a pattern-specific variable struct for this target. */
if (!file->pat_searched)
@@ -476,8 +455,7 @@ variable_expand_for_file (line, file)
}
result = variable_expand (line);
current_variable_set_list = save;
- reading_filename = 0;
- reading_lineno_ptr = 0;
+ reading_file = 0;
file->variables->next = fnext;
return result;
diff --git a/file.c b/file.c
index a60e70f..22e9584 100644
--- a/file.c
+++ b/file.c
@@ -16,13 +16,14 @@ 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 <assert.h>
/* Hash table of files the makefile knows how to make. */
@@ -294,22 +295,22 @@ file_hash_enter (file, name, oldhash, oldname)
/* We have two sets of commands. We will go with the
one given in the rule explicitly mentioning this name,
but give a message to let the user know what's going on. */
- if (oldfile->cmds->filename != 0)
- makefile_error (file->cmds->filename, file->cmds->lineno,
- "Commands were specified for \
-file `%s' at %s:%u,",
- oldname, oldfile->cmds->filename,
- oldfile->cmds->lineno);
+ if (oldfile->cmds->fileinfo.filenm != 0)
+ error (&file->cmds->fileinfo,
+ "Commands were specified for \
+file `%s' at %s:%lu,",
+ oldname, oldfile->cmds->fileinfo.filenm,
+ oldfile->cmds->fileinfo.lineno);
else
- makefile_error (file->cmds->filename, file->cmds->lineno,
+ error (&file->cmds->fileinfo,
"Commands for file `%s' were found by \
implicit rule search,",
oldname);
- makefile_error (file->cmds->filename, file->cmds->lineno,
+ error (&file->cmds->fileinfo,
"but `%s' is now considered the same file \
as `%s'.",
oldname, name);
- makefile_error (file->cmds->filename, file->cmds->lineno,
+ error (&file->cmds->fileinfo,
"Commands for `%s' will be ignored \
in favor of those for `%s'.",
name, oldname);
@@ -331,12 +332,12 @@ in favor of those for `%s'.",
merge_variable_set_lists (&oldfile->variables, file->variables);
if (oldfile->double_colon && file->is_target && !file->double_colon)
- fatal ("can't rename single-colon `%s' to double-colon `%s'",
+ fatal (NILF, "can't rename single-colon `%s' to double-colon `%s'",
oldname, name);
if (!oldfile->double_colon && file->double_colon)
{
if (oldfile->is_target)
- fatal ("can't rename double-colon `%s' to single-colon `%s'",
+ fatal (NILF, "can't rename double-colon `%s' to single-colon `%s'",
oldname, name);
else
oldfile->double_colon = file->double_colon;
@@ -401,7 +402,7 @@ remove_intermediates (sig)
if (!f->dontcare)
{
if (sig)
- error ("*** Deleting intermediate file `%s'", f->name);
+ error (NILF, "*** Deleting intermediate file `%s'", f->name);
else if (!silent_flag)
{
if (! doneany)
@@ -465,7 +466,7 @@ snap_deps ()
{
/* Mark this file as phony and nonexistent. */
f2->phony = 1;
- f2->last_mtime = (time_t) -1;
+ f2->last_mtime = (FILE_TIMESTAMP) -1;
}
for (f = lookup_file (".INTERMEDIATE"); f != 0; f = f->prev)
@@ -549,6 +550,51 @@ set_command_state (file, state)
d->file->command_state = state;
}
+/* Get and print file timestamps. */
+
+FILE_TIMESTAMP
+file_timestamp_now ()
+{
+#if HAVE_CLOCK_GETTIME && defined CLOCK_REALTIME
+ struct timespec timespec;
+ if (clock_gettime (CLOCK_REALTIME, &timespec) == 0)
+ return FILE_TIMESTAMP_FROM_S_AND_NS (timespec.tv_sec, timespec.tv_nsec);
+#endif
+ return FILE_TIMESTAMP_FROM_S_AND_NS (time ((time_t *) 0), 0);
+}
+
+void
+file_timestamp_sprintf (p, ts)
+ char *p;
+ FILE_TIMESTAMP ts;
+{
+ time_t t = FILE_TIMESTAMP_S (ts);
+ struct tm *tm = localtime (&t);
+
+ if (tm)
+ sprintf (p, "%04d-%02d-%02d %02d:%02d:%02d",
+ tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+ else if (t < 0)
+ sprintf (p, "%ld", (long) t);
+ else
+ sprintf (p, "%lu", (unsigned long) t);
+ p += strlen (p);
+
+ /* Append nanoseconds as a fraction, but remove trailing zeros.
+ We don't know the actual timestamp resolution, since clock_getres
+ applies only to local times, whereas this timestamp might come
+ from a remote filesystem. So removing trailing zeros is the
+ best guess that we can do. */
+ sprintf (p, ".%09ld", (long) FILE_TIMESTAMP_NS (ts));
+ p += strlen (p) - 1;
+ while (*p == '0')
+ p--;
+ p += *p != '.';
+
+ *p = '\0';
+}
+
/* Print the data base of files. */
static void
@@ -587,13 +633,16 @@ print_file (f)
printf (" %s", dep_name (d));
putchar ('\n');
}
- if (f->last_mtime == (time_t) 0)
+ if (f->last_mtime == 0)
puts ("# Modification time never checked.");
- else if (f->last_mtime == (time_t) -1)
+ else if (f->last_mtime == (FILE_TIMESTAMP) -1)
puts ("# File does not exist.");
else
- printf ("# Last modified %.24s (%ld)\n",
- ctime (&f->last_mtime), (long int) f->last_mtime);
+ {
+ char buf[FILE_TIMESTAMP_PRINT_LEN_BOUND + 1];
+ file_timestamp_sprintf (buf, f->last_mtime);
+ printf ("# Last modified %s\n", buf);
+ }
printf ("# File has%s been updated.\n",
f->updated ? "" : " not");
switch (f->command_state)
diff --git a/filedef.h b/filedef.h
index a5de0a1..6ee5214 100644
--- a/filedef.h
+++ b/filedef.h
@@ -16,6 +16,7 @@ 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. */
+
/* Structure that represents the info on one file
that the makefile says how to make.
All of these are chained together through `next'. */
@@ -32,7 +33,7 @@ struct file
char *stem; /* Implicit stem, if an implicit
rule has been used */
struct dep *also_make; /* Targets that are made by making this. */
- time_t last_mtime; /* File's modtime, if already known. */
+ FILE_TIMESTAMP last_mtime; /* File's modtime, if already known. */
struct file *prev; /* Previous entry for same file name;
used when there are multiple double-colon
entries for the same file. */
@@ -96,11 +97,62 @@ extern unsigned int num_intermediates;
extern struct file *default_goal_file, *suffix_file, *default_file;
-extern struct file *lookup_file (), *enter_file ();
-extern void remove_intermediates (), snap_deps ();
-extern void rename_file (), rehash_file (), file_hash_enter ();
-extern void set_command_state ();
-
+extern struct file *lookup_file PARAMS ((char *name));
+extern struct file *enter_file PARAMS ((char *name));
+extern void remove_intermediates PARAMS ((int sig));
+extern void snap_deps PARAMS ((void));
+extern void rename_file PARAMS ((struct file *file, char *name));
+extern void rehash_file PARAMS ((struct file *file, char *name));
+extern void file_hash_enter PARAMS ((struct file *file, char *name,
+ unsigned int oldhash, char *oldname));
+extern void set_command_state PARAMS ((struct file *file, int state));
+extern void notice_finished_file PARAMS ((struct file *file));
+
+
+#if ST_MTIM_NSEC
+# define FILE_TIMESTAMP_STAT_MODTIME(st) \
+ FILE_TIMESTAMP_FROM_S_AND_NS ((st).st_mtim.tv_sec, \
+ (st).st_mtim.ST_MTIM_NSEC)
+# define FILE_TIMESTAMPS_PER_S \
+ MIN ((FILE_TIMESTAMP) 1000000000, \
+ (INTEGER_TYPE_MAXIMUM (FILE_TIMESTAMP) \
+ / INTEGER_TYPE_MAXIMUM (time_t)))
+#else
+# define FILE_TIMESTAMP_STAT_MODTIME(st) ((st).st_mtime)
+# define FILE_TIMESTAMPS_PER_S 1
+#endif
+
+#define FILE_TIMESTAMP_FROM_S_AND_NS(s, ns) \
+ ((s) * FILE_TIMESTAMPS_PER_S \
+ + (ns) * FILE_TIMESTAMPS_PER_S / 1000000000)
+#define FILE_TIMESTAMP_DIV(a, b) ((a)/(b) - ((a)%(b) < 0))
+#define FILE_TIMESTAMP_MOD(a, b) ((a)%(b) + ((a)%(b) < 0) * (b))
+#define FILE_TIMESTAMP_S(ts) FILE_TIMESTAMP_DIV ((ts), FILE_TIMESTAMPS_PER_S)
+#define FILE_TIMESTAMP_NS(ts) \
+ (((FILE_TIMESTAMP_MOD ((ts), FILE_TIMESTAMPS_PER_S) * 1000000000) \
+ + (FILE_TIMESTAMPS_PER_S - 1)) \
+ / FILE_TIMESTAMPS_PER_S)
+
+/* Upper bound on length of string "YYYY-MM-DD HH:MM:SS.NNNNNNNNN"
+ representing a file timestamp. The upper bound is not necessarily 19,
+ since the year might be less than -999 or greater than 9999.
+
+ Subtract one for the sign bit if in case file timestamps can be negative;
+ subtract FLOOR_LOG2_SECONDS_PER_YEAR to yield an upper bound on how many
+ file timestamp bits might affect the year;
+ 302 / 1000 is log10 (2) rounded up;
+ add one for integer division truncation;
+ add one more for a minus sign if file timestamps can be negative;
+ add 4 to allow for any 4-digit epoch year (e.g. 1970);
+ add 25 to allow for "-MM-DD HH:MM:SS.NNNNNNNNN". */
+#define FLOOR_LOG2_SECONDS_PER_YEAR 24
+#define FILE_TIMESTAMP_PRINT_LEN_BOUND \
+ (((sizeof (FILE_TIMESTAMP) * CHAR_BIT - 1 - FLOOR_LOG2_SECONDS_PER_YEAR) \
+ * 302 / 1000) \
+ + 1 + 1 + 4 + 25)
+
+extern FILE_TIMESTAMP file_timestamp_now PARAMS ((void));
+extern void file_timestamp_sprintf PARAMS ((char *p, FILE_TIMESTAMP ts));
/* Return the mtime of file F (a struct file *), caching it.
The value is -1 if the file does not exist. */
@@ -110,9 +162,9 @@ extern void set_command_state ();
we don't find it.
The value is -1 if the file does not exist. */
#define file_mtime_no_search(f) file_mtime_1 ((f), 0)
-extern time_t f_mtime ();
+extern FILE_TIMESTAMP f_mtime PARAMS ((struct file *file, int search));
#define file_mtime_1(f, v) \
- ((f)->last_mtime != (time_t) 0 ? (f)->last_mtime : f_mtime ((f), v))
+ ((f)->last_mtime ? (f)->last_mtime : f_mtime ((f), v))
/* Modtime value to use for `infinitely new'. We used to get the current time
from the system and use that whenever we wanted `new'. But that causes
@@ -121,12 +173,13 @@ extern time_t f_mtime ();
targets, which need to be considered newer than anything that depends on
them, even if said dependents' modtimes are in the future.
- If time_t is unsigned, its maximum value is the same as "(time_t) -1",
- so use one less than that, because -1 is used for non-existing files. */
+ If FILE_TIMESTAMP is unsigned, its maximum value is the same as
+ ((FILE_TIMESTAMP) -1), so use one less than that, because -1 is
+ used for non-existing files. */
#define NEW_MTIME \
- (INTEGER_TYPE_SIGNED (time_t) \
- ? INTEGER_TYPE_MAXIMUM (time_t) \
- : (INTEGER_TYPE_MAXIMUM (time_t) - 1))
+ (INTEGER_TYPE_SIGNED (FILE_TIMESTAMP) \
+ ? INTEGER_TYPE_MAXIMUM (FILE_TIMESTAMP) \
+ : (INTEGER_TYPE_MAXIMUM (FILE_TIMESTAMP) - 1))
#define check_renamed(file) \
while ((file)->renamed != 0) (file) = (file)->renamed /* No ; here. */
diff --git a/function.c b/function.c
index 198ab44..13196eb 100644
--- a/function.c
+++ b/function.c
@@ -319,12 +319,8 @@ int shell_function_pid = 0, shell_function_completed;
/* Note this absorbs a semicolon and is safe to use in conditionals. */
#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); } while (0)
+ fatal (reading_file, "insufficient arguments to function `%s'", func); \
+ } while (0)
static char *
expand_function (o, function, text, end)
@@ -395,11 +391,11 @@ expand_function (o, function, text, end)
#endif /* Not Amiga. */
/* For error messages. */
- if (reading_filename != 0)
+ if (reading_file != 0)
{
- error_prefix = (char *) alloca (strlen (reading_filename) + 100);
+ error_prefix = (char *) alloca (strlen(reading_file->filenm)+100);
sprintf (error_prefix,
- "%s:%u: ", reading_filename, *reading_lineno_ptr);
+ "%s:%lu: ", reading_file->filenm, reading_file->lineno);
}
else
error_prefix = "";
@@ -417,7 +413,7 @@ expand_function (o, function, text, end)
0,
TRUE,
DUPLICATE_SAME_ACCESS) == FALSE) {
- fatal("create_child_process: DuplicateHandle(In) failed (e=%d)\n",
+ fatal (NILF, "create_child_process: DuplicateHandle(In) failed (e=%d)\n",
GetLastError());
}
if (DuplicateHandle(GetCurrentProcess(),
@@ -427,17 +423,17 @@ expand_function (o, function, text, end)
0,
TRUE,
DUPLICATE_SAME_ACCESS) == FALSE) {
- fatal("create_child_process: DuplicateHandle(Err) failed (e=%d)\n",
+ fatal (NILF, "create_child_process: DuplicateHandle(Err) failed (e=%d)\n",
GetLastError());
}
if (!CreatePipe(&hChildOutRd, &hChildOutWr, &saAttr, 0))
- fatal("CreatePipe() failed (e=%d)\n", GetLastError());
+ fatal (NILF, "CreatePipe() failed (e=%d)\n", GetLastError());
hProcess = process_init_fd(hIn, hChildOutWr, hErr);
if (!hProcess)
- fatal("expand_function: process_init_fd() failed\n");
+ fatal (NILF, "expand_function: process_init_fd() failed\n");
else
process_register(hProcess);
@@ -447,7 +443,7 @@ expand_function (o, function, text, end)
if (!process_begin(hProcess, argv, envp, argv[0], NULL))
pid = (int) hProcess;
else
- fatal("expand_function: unable to launch process (e=%d)\n",
+ fatal (NILF, "expand_function: unable to launch process (e=%d)\n",
process_last_err(hProcess));
/* set up to read data from child */
@@ -1178,24 +1174,13 @@ expand_function (o, function, text, end)
/* Check the first argument. */
for (p2 = text; *p2 != '\0'; ++p2)
if (*p2 < '0' || *p2 > '9')
- {
- if (reading_filename != 0)
- makefile_fatal (reading_filename, *reading_lineno_ptr,
- "non-numeric first argument to `word' function");
- else
- fatal ("non-numeric first argument to `word' function");
- }
+ fatal (reading_file,
+ "non-numeric first argument to `word' function");
i = (unsigned int) atoi (text);
if (i == 0)
- {
- if (reading_filename != 0)
- makefile_fatal (reading_filename, *reading_lineno_ptr,
- "the `word' function takes a one-origin \
-index argument");
- else
- fatal ("the `word' function takes a one-origin index argument");
- }
+ fatal (reading_file,
+ "the `word' function takes a one-origin index argument");
p2 = p3;
while ((p = find_next_token (&p2, &len)) != 0)
@@ -1245,13 +1230,8 @@ index argument");
/* Check the first argument. */
for (p2 = text; *p2 != '\0'; ++p2)
if (*p2 < '0' || *p2 > '9')
- {
- if (reading_filename != 0)
- makefile_fatal (reading_filename, *reading_lineno_ptr,
- "non-numeric first argument to `wordlist' function");
- else
- fatal ("non-numeric first argument to `wordlist' function");
- }
+ fatal (reading_file,
+ "non-numeric first argument to `wordlist' function");
i = (unsigned int)atoi(text);
free (text);
@@ -1274,13 +1254,8 @@ index argument");
for (p2 = text; *p2 != '\0'; ++p2)
if (*p2 < '0' || *p2 > '9')
- {
- if (reading_filename != 0)
- makefile_fatal (reading_filename, *reading_lineno_ptr,
- "non-numeric second argument to `wordlist' function");
- else
- fatal ("non-numeric second argument to `wordlist' function");
- }
+ fatal (reading_file,
+ "non-numeric second argument to `wordlist' function");
j = (unsigned int)atoi(text);
free (text);
@@ -1545,15 +1520,9 @@ handle_function (op, stringp)
}
if (count >= 0)
- {
- static const char errmsg[]
- = "unterminated call to function `%s': missing `%c'";
- if (reading_filename == 0)
- fatal (errmsg, function_table[code].name, closeparen);
- else
- makefile_fatal (reading_filename, *reading_lineno_ptr, errmsg,
- function_table[code].name, closeparen);
- }
+ fatal (reading_file,
+ "unterminated call to function `%s': missing `%c'",
+ function_table[code].name, closeparen);
/* We found the end; expand the function call. */
diff --git a/getloadavg.c b/getloadavg.c
index 7c1cc80..36245ef 100644
--- a/getloadavg.c
+++ b/getloadavg.c
@@ -1038,7 +1038,7 @@ getloadavg (loadavg, nelem)
#endif /* ! HAVE_GETLOADAVG */
#ifdef TEST
-void
+int
main (argc, argv)
int argc;
char **argv;
diff --git a/glob/ChangeLog b/glob/ChangeLog
index e3854a5..b7e85ad 100644
--- a/glob/ChangeLog
+++ b/glob/ChangeLog
@@ -1,3 +1,8 @@
+1998-08-05 Paul D. Smith <psmith@gnu.org>
+
+ * configure.in: Remove; configuration for glob is handled by the
+ make configure.in.
+
1998-07-29 Paul D. Smith <psmith@gnu.org>
* glob.c, fnmatch.c: New versions from the GLIBC folks (Ulrich
diff --git a/implicit.c b/implicit.c
index a999a0f..4be5cf5 100644
--- a/implicit.c
+++ b/implicit.c
@@ -148,7 +148,7 @@ pattern_search (file, archive, depth, recursions)
that is not just `%'. */
int specific_rule_matched = 0;
- register unsigned int i;
+ register unsigned int i = 0; /* uninit checks OK */
register struct rule *rule;
register struct dep *dep;
@@ -342,6 +342,8 @@ pattern_search (file, archive, depth, recursions)
deps_found = 0;
for (dep = rule->deps; dep != 0; dep = dep->next)
{
+ struct file *fp;
+
/* If the dependency name has a %, substitute the stem. */
p = index (dep_name (dep), '%');
if (p != 0)
@@ -390,9 +392,12 @@ pattern_search (file, archive, depth, recursions)
dependency file we are actually looking for is in a different
directory (the one gotten by prepending FILENAME's directory),
so it might actually exist. */
+ /* If we find a file but the intermediate flag is set, then it
+ was put here by a .INTERMEDIATE: rule so ignore it. */
if ((!dep->changed || check_lastslash)
- && (lookup_file (p) != 0 || file_exists_p (p)))
+ && (((fp = lookup_file (p)) != 0 && !fp->intermediate)
+ || file_exists_p (p)))
{
found_files[deps_found++] = savestring (p, strlen (p));
continue;
@@ -400,7 +405,7 @@ pattern_search (file, archive, depth, recursions)
/* This code, given FILENAME = "lib/foo.o", dependency name
"lib/foo.c", and VPATH=src, searches for "src/lib/foo.c". */
vp = p;
- if (vpath_search (&vp, (time_t *) 0))
+ if (vpath_search (&vp, (FILE_TIMESTAMP *) 0))
{
DEBUGP2 ("Found dependency `%s' as VPATH `%s'\n", p, vp);
strcpy(vp, p);
diff --git a/job.c b/job.c
index 91bc30b..fcdd2f1 100644
--- a/job.c
+++ b/job.c
@@ -29,25 +29,25 @@ char *default_shell = "sh.exe";
int no_default_sh_exe = 1;
int batch_mode_shell = 1;
#else /* WINDOWS32 */
-#ifdef _AMIGA
+# ifdef _AMIGA
char default_shell[] = "";
extern int MyExecute (char **);
-#else /* _AMIGA */
-#ifdef __MSDOS__
+# 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
to search the $PATH for it (since MSDOS doesn't have standard
directories we could trust). */
char *default_shell = "command.com";
-#else /* __MSDOS__ */
+# else /* __MSDOS__ */
char default_shell[] = "/bin/sh";
-#endif /* __MSDOS__ */
+# endif /* __MSDOS__ */
int batch_mode_shell = 0;
-#endif /* _AMIGA */
+# endif /* _AMIGA */
#endif /* WINDOWS32 */
#ifdef __MSDOS__
-#include <process.h>
+# include <process.h>
static int execute_by_shell;
static int dos_pid = 123;
int dos_status;
@@ -55,7 +55,7 @@ int dos_command_running;
#endif /* __MSDOS__ */
#ifdef _AMIGA
-#include <proto/dos.h>
+# include <proto/dos.h>
static int amiga_pid = 123;
static int amiga_status;
static char amiga_bname[32];
@@ -63,101 +63,101 @@ static int amiga_batch_file;
#endif /* Amiga. */
#ifdef VMS
-#include <time.h>
-#include <processes.h>
-#include <starlet.h>
-#include <lib$routines.h>
+# include <time.h>
+# include <processes.h>
+# include <starlet.h>
+# include <lib$routines.h>
#endif
#ifdef WINDOWS32
-#include <windows.h>
-#include <io.h>
-#include <process.h>
-#include "sub_proc.h"
-#include "w32err.h"
-#include "pathstuff.h"
+# include <windows.h>
+# include <io.h>
+# include <process.h>
+# include "sub_proc.h"
+# include "w32err.h"
+# include "pathstuff.h"
#endif /* WINDOWS32 */
#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
+# include <fcntl.h>
#else
-#include <sys/file.h>
+# include <sys/file.h>
#endif
#if defined (HAVE_SYS_WAIT_H) || defined (HAVE_UNION_WAIT)
-#include <sys/wait.h>
+# include <sys/wait.h>
#endif
-#ifdef HAVE_WAITPID
-#define WAIT_NOHANG(status) waitpid (-1, (status), WNOHANG)
+#ifdef HAVE_WAITPID
+# define WAIT_NOHANG(status) waitpid (-1, (status), WNOHANG)
#else /* Don't have waitpid. */
-#ifdef HAVE_WAIT3
-#ifndef wait3
+# ifdef HAVE_WAIT3
+# ifndef wait3
extern int wait3 ();
-#endif
-#define WAIT_NOHANG(status) wait3 ((status), WNOHANG, (struct rusage *) 0)
-#endif /* Have wait3. */
-#endif /* Have waitpid. */
+# endif
+# define WAIT_NOHANG(status) wait3 ((status), WNOHANG, (struct rusage *) 0)
+# endif /* Have wait3. */
+#endif /* Have waitpid. */
-#if !defined (wait) && !defined (POSIX)
+#if !defined (wait) && !defined (POSIX)
extern int wait ();
#endif
#ifndef HAVE_UNION_WAIT
-#define WAIT_T int
-
-#ifndef WTERMSIG
-#define WTERMSIG(x) ((x) & 0x7f)
-#endif
-#ifndef WCOREDUMP
-#define WCOREDUMP(x) ((x) & 0x80)
-#endif
-#ifndef WEXITSTATUS
-#define WEXITSTATUS(x) (((x) >> 8) & 0xff)
-#endif
-#ifndef WIFSIGNALED
-#define WIFSIGNALED(x) (WTERMSIG (x) != 0)
-#endif
-#ifndef WIFEXITED
-#define WIFEXITED(x) (WTERMSIG (x) == 0)
-#endif
+# define WAIT_T int
+
+# ifndef WTERMSIG
+# define WTERMSIG(x) ((x) & 0x7f)
+# endif
+# ifndef WCOREDUMP
+# define WCOREDUMP(x) ((x) & 0x80)
+# endif
+# ifndef WEXITSTATUS
+# define WEXITSTATUS(x) (((x) >> 8) & 0xff)
+# endif
+# ifndef WIFSIGNALED
+# define WIFSIGNALED(x) (WTERMSIG (x) != 0)
+# endif
+# ifndef WIFEXITED
+# define WIFEXITED(x) (WTERMSIG (x) == 0)
+# endif
#else /* Have `union wait'. */
-#define WAIT_T union wait
-#ifndef WTERMSIG
-#define WTERMSIG(x) ((x).w_termsig)
-#endif
-#ifndef WCOREDUMP
-#define WCOREDUMP(x) ((x).w_coredump)
-#endif
-#ifndef WEXITSTATUS
-#define WEXITSTATUS(x) ((x).w_retcode)
-#endif
-#ifndef WIFSIGNALED
-#define WIFSIGNALED(x) (WTERMSIG(x) != 0)
-#endif
-#ifndef WIFEXITED
-#define WIFEXITED(x) (WTERMSIG(x) == 0)
-#endif
+# define WAIT_T union wait
+# ifndef WTERMSIG
+# define WTERMSIG(x) ((x).w_termsig)
+# endif
+# ifndef WCOREDUMP
+# define WCOREDUMP(x) ((x).w_coredump)
+# endif
+# ifndef WEXITSTATUS
+# define WEXITSTATUS(x) ((x).w_retcode)
+# endif
+# ifndef WIFSIGNALED
+# define WIFSIGNALED(x) (WTERMSIG(x) != 0)
+# endif
+# ifndef WIFEXITED
+# define WIFEXITED(x) (WTERMSIG(x) == 0)
+# endif
#endif /* Don't have `union wait'. */
#ifdef VMS
-static int vms_jobsefnmask=0;
+static int vms_jobsefnmask = 0;
#endif /* !VMS */
#ifndef HAVE_UNISTD_H
extern int dup2 ();
extern int execve ();
extern void _exit ();
-#ifndef VMS
+# ifndef VMS
extern int geteuid ();
extern int getegid ();
extern int setgid ();
extern int getgid ();
-#endif
+# endif
#endif
extern char *allocated_variable_expand_for_file PARAMS ((char *line, struct file *file));
@@ -169,7 +169,6 @@ 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));
-RETSIGTYPE child_handler PARAMS ((int));
static void free_child PARAMS ((struct child *));
static void start_job_command PARAMS ((struct child *child));
static int load_too_high PARAMS ((void));
@@ -224,21 +223,19 @@ child_error (target_name, exit_code, exit_sig, coredump, ignored)
#ifdef VMS
if (!(exit_code & 1))
- error("*** [%s] Error 0x%x%s", target_name, exit_code, ((ignored)? " (ignored)" : ""));
+ error (NILF, "*** [%s] Error 0x%x%s", target_name, exit_code, ((ignored)? " (ignored)" : ""));
#else
if (exit_sig == 0)
- error (ignored ? "[%s] Error %d (ignored)" :
+ error (NILF, ignored ? "[%s] Error %d (ignored)" :
"*** [%s] Error %d",
target_name, exit_code);
else
- error ("*** [%s] %s%s",
+ error (NILF, "*** [%s] %s%s",
target_name, strsignal (exit_sig),
coredump ? " (core dumped)" : "");
#endif /* VMS */
}
-static unsigned int dead_children = 0;
-
#ifdef VMS
/* Wait for nchildren children to terminate */
static void
@@ -259,6 +256,13 @@ vmsWaitForChildren(int *status)
#endif
+/* If we can't use waitpid() or wait3(), then we use a signal handler
+ to track the number of SIGCHLD's we got. This is less robust. */
+
+#ifndef WAIT_NOHANG
+
+static unsigned int dead_children = 0;
+
/* Notice that a child died.
reap_children should be called when convenient. */
RETSIGTYPE
@@ -271,6 +275,8 @@ child_handler (sig)
printf ("Got a SIGCHLD; %d unreaped children.\n", dead_children);
}
+#endif /* WAIT_NOHANG */
+
extern int shell_function_pid, shell_function_completed;
/* Reap dead children, storing the returned status and the new command
@@ -284,9 +290,12 @@ reap_children (block, err)
int block, err;
{
WAIT_T status;
+#ifdef WAIT_NOHANG
+ int dead_children = 1; /* Initially, assume we have some. */
+#endif
while ((children != 0 || shell_function_pid != 0) &&
- (block || dead_children > 0))
+ (block || dead_children))
{
int remote = 0;
register int pid;
@@ -295,13 +304,14 @@ reap_children (block, err)
int child_failed;
int any_remote, any_local;
- if (err && dead_children == 0)
+ if (err && block)
{
/* We might block for a while, so let the user know why. */
fflush (stdout);
- error ("*** Waiting for unfinished jobs....");
+ error (NILF, "*** Waiting for unfinished jobs....");
}
+#ifndef WAIT_NOHANG
/* We have one less dead child to reap.
The test and decrement are not atomic; if it is compiled into:
register = dead_children - 1;
@@ -316,6 +326,7 @@ reap_children (block, err)
if (dead_children > 0)
--dead_children;
+#endif
any_remote = 0;
any_local = shell_function_pid != 0;
@@ -338,8 +349,12 @@ reap_children (block, err)
else
pid = 0;
- if (pid < 0)
+ if (pid > 0)
+ /* We got a remote child. */
+ remote = 1;
+ else if (pid < 0)
{
+ /* A remote status command failed miserably. Punt. */
remote_status_lose:
#ifdef EINTR
if (errno == EINTR)
@@ -347,11 +362,11 @@ reap_children (block, err)
#endif
pfatal_with_name ("remote_status");
}
- else if (pid == 0)
+ else
{
-#if !defined(__MSDOS__) && !defined(_AMIGA) && !defined(WINDOWS32)
/* No remote children. Check for local children. */
+#if !defined(__MSDOS__) && !defined(_AMIGA) && !defined(WINDOWS32)
if (any_local)
{
#ifdef VMS
@@ -371,15 +386,26 @@ reap_children (block, err)
if (pid < 0)
{
+ /* The wait*() failed miserably. Punt. */
#ifdef EINTR
if (errno == EINTR)
continue;
#endif
pfatal_with_name ("wait");
}
- else if (pid == 0)
+ else if (pid > 0)
+ {
+ /* We got one; chop the status word up. */
+ exit_code = WEXITSTATUS (status);
+ exit_sig = WIFSIGNALED (status) ? WTERMSIG (status) : 0;
+ coredump = WCOREDUMP (status);
+ }
+ else
{
- /* No local children. */
+ /* No local children are dead. */
+#ifdef WAIT_NOHANG
+ dead_children = 0;
+#endif
if (block && any_remote)
{
/* Now try a blocking wait for a remote child. */
@@ -396,14 +422,7 @@ reap_children (block, err)
else
break;
}
- else
- {
- /* Chop the status word up. */
- exit_code = WEXITSTATUS (status);
- exit_sig = WIFSIGNALED (status) ? WTERMSIG (status) : 0;
- coredump = WCOREDUMP (status);
- }
-#else /* __MSDOS__, Amiga, WINDOWS32. */
+#endif /* !__MSDOS__, !Amiga, !WINDOWS32. */
#ifdef __MSDOS__
/* Life is very different on MSDOS. */
pid = dos_pid - 1;
@@ -423,39 +442,35 @@ reap_children (block, err)
coredump = 0;
#endif /* _AMIGA */
#ifdef WINDOWS32
- {
- HANDLE hPID;
- int err;
+ {
+ HANDLE hPID;
+ int err;
- /* wait for anything to finish */
- if (hPID = process_wait_for_any()) {
+ /* wait for anything to finish */
+ if (hPID = process_wait_for_any()) {
- /* was an error found on this process? */
- err = process_last_err(hPID);
+ /* was an error found on this process? */
+ err = process_last_err(hPID);
- /* get exit data */
- exit_code = process_exit_code(hPID);
+ /* get exit data */
+ exit_code = process_exit_code(hPID);
- if (err)
- fprintf(stderr, "make (e=%d): %s",
- exit_code, map_windows32_error_to_string(exit_code));
+ if (err)
+ fprintf(stderr, "make (e=%d): %s",
+ exit_code, map_windows32_error_to_string(exit_code));
- /* signal */
- exit_sig = process_signal(hPID);
+ /* signal */
+ exit_sig = process_signal(hPID);
- /* cleanup process */
- process_cleanup(hPID);
+ /* cleanup process */
+ process_cleanup(hPID);
- coredump = 0;
- }
- pid = (int) hPID;
- }
+ coredump = 0;
+ }
+ pid = (int) hPID;
+ }
#endif /* WINDOWS32 */
-#endif /* Not __MSDOS__ */
}
- else
- /* We got a remote child. */
- remote = 1;
/* Check if this is the child of the `shell' function. */
if (!remote && pid == shell_function_pid)
@@ -478,14 +493,9 @@ reap_children (block, err)
if (c == 0)
{
- /* An unknown child died. */
- char buf[100];
- sprintf (buf, "Unknown%s job %d", remote ? " remote" : "", pid);
- if (child_failed)
- child_error (buf, exit_code, exit_sig, coredump,
- ignore_errors_flag);
- else
- error ("%s finished.", buf);
+ /* An unknown child died.
+ Ignore it; it was inherited from our invoker. */
+ continue;
}
else
{
@@ -495,17 +505,17 @@ reap_children (block, err)
(unsigned long int) c,
(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);
+ if (c->sh_batch_file) {
+ if (debug_flag)
+ printf("Cleaning up temp batch file %s\n", c->sh_batch_file);
- /* just try and remove, don't care if this fails */
- remove(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;
- }
+ /* 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)
@@ -661,12 +671,12 @@ extern sigset_t fatal_signal_set;
void
block_sigs ()
{
-#ifdef POSIX
+#ifdef POSIX
(void) sigprocmask (SIG_BLOCK, &fatal_signal_set, (sigset_t *) 0);
#else
-#ifdef HAVE_SIGSETMASK
+# ifdef HAVE_SIGSETMASK
(void) sigblock (fatal_signal_mask);
-#endif
+# endif
#endif
}
@@ -1098,9 +1108,9 @@ start_waiting_job (c)
case cs_running:
c->next = children;
if (debug_flag)
- printf ("Putting child 0x%08lx PID %05d%s on the chain.\n",
+ printf ("Putting child 0x%08lx PID %ld%s on the chain.\n",
(unsigned long int) c,
- c->pid, c->remote ? " (remote)" : "");
+ (long) c->pid, c->remote ? " (remote)" : "");
children = c;
/* One more job slot is in use. */
++job_slots_used;
@@ -1322,7 +1332,7 @@ load_too_high ()
{
if (errno == 0)
/* An errno value of zero means getloadavg is just unsupported. */
- error ("cannot enforce load limits on this operating system");
+ error (NILF, "cannot enforce load limits on this operating system");
else
perror_with_name ("cannot enforce load limit: ", "getloadavg");
}
@@ -1427,8 +1437,7 @@ int vmsHandleChildTerm(struct child *child)
break;
default:
- error ("internal error: `%s' command_state \
-%d in child_handler", c->file->name);
+ error (NILF, "internal error: `%s' command_state", c->file->name);
abort ();
break;
}
@@ -1682,7 +1691,7 @@ exec_command (argv, envp)
switch (errno)
{
case ENOENT:
- error ("%s: Command not found", argv[0]);
+ error (NILF, "%s: Command not found", argv[0]);
break;
case ENOEXEC:
{
@@ -1711,7 +1720,7 @@ exec_command (argv, envp)
execvp (shell, new_argv);
if (errno == ENOENT)
- error ("%s: Shell program not found", shell);
+ error (NILF, "%s: Shell program not found", shell);
else
perror_with_name ("execvp: ", shell);
break;
@@ -2205,8 +2214,8 @@ construct_command_argv_internal (line, restp, shell, ifs, batch_filename_ptr)
p = next_token (p);
--p;
- if (unixy_shell && !batch_mode_shell)
- *ap++ = '\\';
+ if (unixy_shell && !batch_mode_shell)
+ *ap++ = '\\';
*ap++ = ' ';
continue;
}
@@ -2234,11 +2243,9 @@ construct_command_argv_internal (line, restp, shell, ifs, batch_filename_ptr)
*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.
- */
+ /* 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();
@@ -2269,7 +2276,8 @@ construct_command_argv_internal (line, restp, shell, ifs, batch_filename_ptr)
/* create batch file to execute command */
batch = fopen (*batch_filename_ptr, "w");
- fputs ("@echo off\n", batch);
+ if (!unixy_shell)
+ fputs ("@echo off\n", batch);
fputs (command_ptr, batch);
fputc ('\n', batch);
fclose (batch);
@@ -2305,7 +2313,7 @@ construct_command_argv_internal (line, restp, shell, ifs, batch_filename_ptr)
}
#else
else
- fatal("%s (line %d) Invalid shell context (!unixy && !batch_mode_shell)\n",
+ fatal (NILF, "%s (line %d) Bad shell context (!unixy && !batch_mode_shell)\n",
__FILE__, __LINE__);
#endif
}
diff --git a/job.h b/job.h
index eaac492..d60247a 100644
--- a/job.h
+++ b/job.h
@@ -44,7 +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 */
+ char *sh_batch_file; /* Script file for shell commands */
};
extern struct child *children;
diff --git a/main.c b/main.c
index dcffa37..efad30d 100644
--- a/main.c
+++ b/main.c
@@ -22,6 +22,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "variable.h"
#include "job.h"
#include "commands.h"
+#include "rule.h"
#include "getopt.h"
#include <assert.h>
#ifdef _AMIGA
@@ -41,7 +42,6 @@ extern void init_dir PARAMS ((void));
extern void remote_setup PARAMS ((void));
extern void remote_cleanup PARAMS ((void));
extern RETSIGTYPE fatal_error_signal PARAMS ((int sig));
-extern RETSIGTYPE child_handler PARAMS ((int sig));
extern void print_variable_data_base PARAMS ((void));
extern void print_dir_data_base PARAMS ((void));
@@ -49,18 +49,22 @@ extern void print_rule_data_base PARAMS ((void));
extern void print_file_data_base PARAMS ((void));
extern void print_vpath_data_base PARAMS ((void));
+#if defined HAVE_WAITPID || defined HAVE_WAIT3
+# define HAVE_WAIT_NOHANG
+#endif
+
#ifndef HAVE_UNISTD_H
extern int chdir ();
#endif
#ifndef STDC_HEADERS
#ifndef sun /* Sun has an incorrect decl in a header. */
-extern void exit ();
+extern void exit PARAMS ((int)) __attribute__ ((noreturn));
#endif
extern double atof ();
#endif
extern char *mktemp ();
-static void print_data_base PARAMS((void));
+static void print_data_base PARAMS ((void));
static void print_version PARAMS ((void));
static void decode_switches PARAMS ((int argc, char **argv, int env));
static void decode_env_switches PARAMS ((char *envar, unsigned int len));
@@ -413,7 +417,7 @@ enter_command_line_file (name)
char *name;
{
if (name[0] == '\0')
- fatal ("empty string invalid as file name");
+ fatal (NILF, "empty string invalid as file name");
if (name[0] == '~')
{
@@ -664,8 +668,7 @@ int main (int argc, char ** argv)
#endif
default_goal_file = 0;
- reading_filename = 0;
- reading_lineno_ptr = 0;
+ reading_file = 0;
#if defined (__MSDOS__) && !defined (_POSIX_SOURCE)
/* Request the most powerful version of `system', to
@@ -722,6 +725,20 @@ int main (int argc, char ** argv)
#undef FATAL_SIG
+ /* Do not ignore the child-death signal. This must be done before
+ any children could possibly be created; otherwise, the wait
+ functions won't work on systems with the SVR4 ECHILD brain
+ damage, if our invoker is ignoring this signal. */
+
+#ifdef HAVE_WAIT_NOHANG
+# if defined SIGCHLD
+ (void) signal (SIGCHLD, SIG_DFL);
+# endif
+# if defined SIGCLD && SIGCLD != SIGCHLD
+ (void) signal (SIGCLD, SIG_DFL);
+# endif
+#endif
+
/* Make sure stdout is line-buffered. */
#ifdef HAVE_SETLINEBUF
@@ -782,7 +799,7 @@ int main (int argc, char ** argv)
#ifdef HAVE_GETCWD
perror_with_name ("getcwd: ", "");
#else
- error ("getwd: %s", current_directory);
+ error (NILF, "getwd: %s", current_directory);
#endif
current_directory[0] = '\0';
directory_before_chdir = 0;
@@ -1051,7 +1068,7 @@ int main (int argc, char ** argv)
#ifdef HAVE_GETCWD
perror_with_name ("getcwd: ", "");
#else
- error ("getwd: %s", current_directory);
+ error (NILF, "getwd: %s", current_directory);
#endif
starting_directory = 0;
}
@@ -1089,7 +1106,7 @@ int main (int argc, char ** argv)
#endif
if (stdin_nm)
- fatal("Makefile from standard input specified twice.");
+ fatal (NILF, "Makefile from standard input specified twice.");
outfile = fopen (name, "w");
if (outfile == 0)
@@ -1126,14 +1143,20 @@ int main (int argc, char ** argv)
}
}
- /* Set up to handle children dying. This must be done before
- reading in the makefiles so that `shell' function calls will work. */
-
-#ifdef SIGCHLD
- (void) signal (SIGCHLD, child_handler);
-#endif
-#ifdef SIGCLD
- (void) signal (SIGCLD, child_handler);
+#ifndef HAVE_WAIT_NOHANG
+ {
+ extern RETSIGTYPE child_handler PARAMS ((int sig));
+
+ /* Set up to handle children dying. This must be done before
+ reading in the makefiles so that `shell' function calls will work.
+ Note we only do this if we have to. */
+# if defined SIGCHLD
+ (void) signal (SIGCHLD, child_handler);
+# endif
+# if defined SIGCLD && SIGCLD != SIGCHLD
+ (void) signal (SIGCLD, child_handler);
+# endif
+ }
#endif
/* Let the user send us SIGUSR1 to toggle the -d flag during the run. */
@@ -1178,8 +1201,8 @@ int main (int argc, char ** argv)
no_default_sh_exe = !find_and_set_default_shell(NULL);
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.");
+ error (NILF, "Do not specify -j or --jobs if sh.exe is not available.");
+ error (NILF, "Resetting make for single job mode.");
job_slots = 1;
}
#endif /* WINDOWS32 */
@@ -1251,7 +1274,7 @@ int main (int argc, char ** argv)
for (p = old_files->list; *p != 0; ++p)
{
f = enter_command_line_file (*p);
- f->last_mtime = (time_t) 1;
+ f->last_mtime = (FILE_TIMESTAMP) 1;
f->updated = 1;
f->update_status = 0;
f->command_state = cs_finished;
@@ -1273,7 +1296,7 @@ int main (int argc, char ** argv)
{
/* Update any makefiles if necessary. */
- time_t *makefile_mtimes = 0;
+ FILE_TIMESTAMP *makefile_mtimes = 0;
unsigned int mm_idx = 0;
char **nargv = argv;
int nargc = argc;
@@ -1323,11 +1346,12 @@ int main (int argc, char ** argv)
if (f == NULL || !f->double_colon)
{
if (makefile_mtimes == 0)
- makefile_mtimes = (time_t *) xmalloc (sizeof (time_t));
+ makefile_mtimes = (FILE_TIMESTAMP *)
+ xmalloc (sizeof (FILE_TIMESTAMP));
else
- makefile_mtimes = (time_t *)
+ makefile_mtimes = (FILE_TIMESTAMP *)
xrealloc ((char *) makefile_mtimes,
- (mm_idx + 1) * sizeof (time_t));
+ (mm_idx + 1) * sizeof (FILE_TIMESTAMP));
makefile_mtimes[mm_idx++] = file_mtime_no_search (d->file);
last = d;
d = d->next;
@@ -1373,13 +1397,13 @@ int main (int argc, char ** argv)
}
else if (! (d->changed & RM_DONTCARE))
{
- time_t mtime;
+ FILE_TIMESTAMP mtime;
/* The update failed and this makefile was not
from the MAKEFILES variable, so we care. */
- error ("Failed to remake makefile `%s'.",
+ error (NILF, "Failed to remake makefile `%s'.",
d->file->name);
mtime = file_mtime_no_search (d->file);
- any_remade |= (mtime != (time_t) -1
+ any_remade |= (mtime != (FILE_TIMESTAMP) -1
&& mtime != makefile_mtimes[i]);
}
}
@@ -1391,12 +1415,12 @@ int main (int argc, char ** argv)
if (d->changed & RM_INCLUDED)
/* An included makefile. We don't need
to die, but we do want to complain. */
- error ("Included makefile `%s' was not found.",
+ error (NILF, "Included makefile `%s' was not found.",
dep_name (d));
else
{
/* A normal makefile. We must die later. */
- error ("Makefile `%s' was not found", dep_name (d));
+ error (NILF, "Makefile `%s' was not found", dep_name (d));
any_failed = 1;
}
}
@@ -1461,7 +1485,7 @@ int main (int argc, char ** argv)
else
bad = 1;
if (bad)
- fatal ("Couldn't change back to original directory.");
+ fatal (NILF, "Couldn't change back to original directory.");
}
#ifndef _AMIGA
@@ -1570,14 +1594,14 @@ int main (int argc, char ** argv)
else
{
if (read_makefiles == 0)
- fatal ("No targets specified and no makefile found");
+ fatal (NILF, "No targets specified and no makefile found");
else
- fatal ("No targets");
+ fatal (NILF, "No targets");
}
/* If we detected some clock skew, generate one last warning */
if (clock_skew_detected)
- error("*** Warning: Clock skew detected. Your build may be incomplete.");
+ error (NILF, "*** Warning: Clock skew detected. Your build may be incomplete.");
/* Exit. */
die (status);
@@ -1661,7 +1685,7 @@ handle_non_switch_argument (arg, env)
if (arg[0] == '-' && arg[1] == '\0')
/* Ignore plain `-' for compatibility. */
return;
- v = try_variable_definition ((char *) 0, 0, arg, o_command);
+ v = try_variable_definition (0, arg, o_command);
if (v != 0)
{
/* It is indeed a variable definition. Record a pointer to
@@ -1825,7 +1849,7 @@ decode_switches (argc, argv, env)
if (i < 1)
{
if (doit)
- error ("the `-%c' option requires a \
+ error (NILF, "the `-%c' option requires a \
positive integral argument",
cs->c);
bad = 1;
diff --git a/make.h b/make.h
index 58a0ff2..9f5af96 100644
--- a/make.h
+++ b/make.h
@@ -25,27 +25,27 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
(which it would do because make.h was found in $srcdir). */
#include <config.h>
-#undef HAVE_CONFIG_H
-#define HAVE_CONFIG_H
+#undef HAVE_CONFIG_H
+#define HAVE_CONFIG_H 1
/* Use prototypes if available. */
#if defined (__cplusplus) || (defined (__STDC__) && __STDC__)
-#undef PARAMS
-#define PARAMS(protos) protos
+# undef PARAMS
+# define PARAMS(protos) protos
#else /* Not C++ or ANSI C. */
-#undef PARAMS
-#define PARAMS(protos) ()
+# undef PARAMS
+# define PARAMS(protos) ()
#endif /* C++ or ANSI C. */
-#ifdef CRAY
+#ifdef CRAY
/* This must happen before #include <signal.h> so
that the declaration therein is changed. */
-#define signal bsdsignal
+# define signal bsdsignal
#endif
-#define _GNU_SOURCE
+#define _GNU_SOURCE 1
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
@@ -55,35 +55,35 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* SCO 3.2 "devsys 4.2" has a prototype for `ftime' in <time.h> that bombs
unless <sys/timeb.h> has been included first. Does every system have a
<sys/timeb.h>? If any does not, configure should check for it. */
-#include <sys/timeb.h>
+# include <sys/timeb.h>
#endif
#include <time.h>
#include <errno.h>
-#ifndef errno
+#ifndef errno
extern int errno;
#endif
-#ifndef isblank
-#define isblank(c) ((c) == ' ' || (c) == '\t')
+#ifndef isblank
+# define isblank(c) ((c) == ' ' || (c) == '\t')
#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
/* Ultrix's unistd.h always defines _POSIX_VERSION, but you only get
POSIX.1 behavior with `cc -YPOSIX', which predefines POSIX itself! */
-#if defined (_POSIX_VERSION) && !defined (ultrix) && !defined (VMS)
-#define POSIX
-#endif
+# if defined (_POSIX_VERSION) && !defined (ultrix) && !defined (VMS)
+# define POSIX 1
+# endif
#endif
/* Some systems define _POSIX_VERSION but are not really POSIX.1. */
#if (defined (butterfly) || defined (__arm) || (defined (__mips) && defined (_SYSTYPE_SVR3)) || (defined (sequent) && defined (i386)))
-#undef POSIX
+# undef POSIX
#endif
#if !defined (POSIX) && defined (_AIX) && defined (_POSIX_SOURCE)
-#define POSIX
+# define POSIX 1
#endif
#if defined (HAVE_SYS_SIGLIST) && !defined (SYS_SIGLIST_DECLARED)
@@ -91,54 +91,54 @@ extern char *sys_siglist[];
#endif
#if !defined (HAVE_SYS_SIGLIST) || !defined (HAVE_STRSIGNAL)
-#include "signame.h"
+# include "signame.h"
#endif
/* Some systems do not define NSIG in <signal.h>. */
-#ifndef NSIG
-#ifdef _NSIG
-#define NSIG _NSIG
-#else
-#define NSIG 32
-#endif
+#ifndef NSIG
+# ifdef _NSIG
+# define NSIG _NSIG
+# else
+# define NSIG 32
+# endif
#endif
-#ifndef RETSIGTYPE
-#define RETSIGTYPE void
+#ifndef RETSIGTYPE
+# define RETSIGTYPE void
#endif
-#ifndef sigmask
-#define sigmask(sig) (1 << ((sig) - 1))
+#ifndef sigmask
+# define sigmask(sig) (1 << ((sig) - 1))
#endif
-#ifdef HAVE_LIMITS_H
-#include <limits.h>
+#ifdef HAVE_LIMITS_H
+# include <limits.h>
#endif
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
#endif
-#ifndef PATH_MAX
-#ifndef POSIX
-#define PATH_MAX MAXPATHLEN
-#endif /* Not POSIX. */
-#endif /* No PATH_MAX. */
+#ifndef PATH_MAX
+# ifndef POSIX
+# define PATH_MAX MAXPATHLEN
+# endif
+#endif
#ifndef MAXPATHLEN
-#define MAXPATHLEN 1024
-#endif /* No MAXPATHLEN. */
+# define MAXPATHLEN 1024
+#endif
-#ifdef PATH_MAX
-#define GET_PATH_MAX PATH_MAX
-#define PATH_VAR(var) char var[PATH_MAX]
+#ifdef PATH_MAX
+# define GET_PATH_MAX PATH_MAX
+# define PATH_VAR(var) char var[PATH_MAX]
#else
-#define NEED_GET_PATH_MAX
+# define NEED_GET_PATH_MAX 1
+# define GET_PATH_MAX (get_path_max ())
+# define PATH_VAR(var) char *var = (char *) alloca (GET_PATH_MAX)
extern unsigned int get_path_max PARAMS ((void));
-#define GET_PATH_MAX (get_path_max ())
-#define PATH_VAR(var) char *var = (char *) alloca (GET_PATH_MAX)
#endif
#ifndef CHAR_BIT
-#define CHAR_BIT 8
+# define CHAR_BIT 8
#endif
/* Nonzero if the integer type T is signed. */
@@ -150,171 +150,189 @@ extern unsigned int get_path_max PARAMS ((void));
(! INTEGER_TYPE_SIGNED (t) ? (t) 0 : ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))
#define INTEGER_TYPE_MAXIMUM(t) (~ (t) 0 - INTEGER_TYPE_MINIMUM (t))
-#ifdef STAT_MACROS_BROKEN
-#ifdef S_ISREG
-#undef S_ISREG
-#endif
-#ifdef S_ISDIR
-#undef S_ISDIR
-#endif
-#endif /* STAT_MACROS_BROKEN. */
+#ifdef STAT_MACROS_BROKEN
+# ifdef S_ISREG
+# undef S_ISREG
+# endif
+# ifdef S_ISDIR
+# undef S_ISDIR
+# endif
+#endif /* STAT_MACROS_BROKEN. */
-#ifndef S_ISREG
-#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
+#ifndef S_ISREG
+# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
#endif
-#ifndef S_ISDIR
-#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
+#ifndef S_ISDIR
+# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#endif
#ifdef VMS
-#include <stdio.h>
-#include <types.h>
-#include <unixlib.h>
-#include <unixio.h>
-#include <errno.h>
-#include <perror.h>
+# include <stdio.h>
+# include <types.h>
+# include <unixlib.h>
+# include <unixio.h>
+# include <errno.h>
+# include <perror.h>
#endif
-#if (defined (STDC_HEADERS) || defined (__GNU_LIBRARY__) || defined(VMS))
-#include <stdlib.h>
-#include <string.h>
-#define ANSI_STRING
-#else /* No standard headers. */
-
-#ifdef HAVE_STRING_H
-#include <string.h>
-#define ANSI_STRING
-#else
-#include <strings.h>
-#endif
-#ifdef HAVE_MEMORY_H
-#include <memory.h>
+#ifndef __attribute__
+/* This feature is available in gcc versions 2.5 and later. */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
+# define __attribute__(x)
+# endif
+/* The __-protected variants of `format' and `printf' attributes
+ are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
+# define __format__ format
+# define __printf__ printf
+# endif
#endif
+#if defined (STDC_HEADERS) || defined (__GNU_LIBRARY__)
+# include <stdlib.h>
+# include <string.h>
+# define ANSI_STRING 1
+#else /* No standard headers. */
+# ifdef HAVE_STRING_H
+# include <string.h>
+# define ANSI_STRING 1
+# else
+# include <strings.h>
+# endif
+# ifdef HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# else
extern char *malloc PARAMS ((int));
extern char *realloc PARAMS ((char *, int));
extern void free PARAMS ((char *));
-extern void abort PARAMS ((void));
-extern void exit PARAMS ((int));
+extern void abort PARAMS ((void)) __attribute__ ((noreturn));
+extern void exit PARAMS ((int)) __attribute__ ((noreturn));
+# endif /* HAVE_STDLIB_H. */
-#endif /* Standard headers. */
+#endif /* Standard headers. */
-#ifdef ANSI_STRING
-
-#ifndef index
-#define index(s, c) strchr((s), (c))
-#endif
-#ifndef rindex
-#define rindex(s, c) strrchr((s), (c))
+#if ST_MTIM_NSEC
+# if HAVE_INTTYPES_H
+# include <inttypes.h>
+# endif
+# define FILE_TIMESTAMP uintmax_t
+#else
+# define FILE_TIMESTAMP time_t
#endif
-#ifndef bcmp
-#define bcmp(s1, s2, n) memcmp ((s1), (s2), (n))
-#endif
-#ifndef bzero
-#define bzero(s, n) memset ((s), 0, (n))
-#endif
-#if defined(HAVE_MEMMOVE) && !defined(bcopy)
-#define bcopy(s, d, n) memmove ((d), (s), (n))
-#endif
+#ifdef ANSI_STRING
-#else /* Not ANSI_STRING. */
+# ifndef index
+# define index(s, c) strchr((s), (c))
+# endif
+# ifndef rindex
+# define rindex(s, c) strrchr((s), (c))
+# endif
-#ifndef bcmp
-extern int bcmp ();
-#endif
-#ifndef bzero
-extern void bzero ();
-#endif
-#ifndef bcopy
-extern void bcopy ();
+# ifndef bcmp
+# define bcmp(s1, s2, n) memcmp ((s1), (s2), (n))
+# endif
+# ifndef bzero
+# define bzero(s, n) memset ((s), 0, (n))
+# endif
+# if defined(HAVE_MEMMOVE) && !defined(bcopy)
+# define bcopy(s, d, n) memmove ((d), (s), (n))
+# endif
+
+#else /* Not ANSI_STRING. */
+
+# ifndef bcmp
+extern int bcmp PARAMS ((const char *, const char *, int));
+# endif
+# ifndef bzero
+extern void bzero PARAMS ((char *, int));
#endif
+# ifndef bcopy
+extern void bcopy PARAMS ((const char *b1, char *b2, int));
+# endif
-#endif /* ANSI_STRING. */
-#undef ANSI_STRING
+#endif /* ANSI_STRING. */
+#undef ANSI_STRING
/* SCO Xenix has a buggy macro definition in <string.h>. */
-#undef strerror
+#undef strerror
#if !defined(ANSI_STRING) && !defined(__DECC)
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
-#define alloca(n) __builtin_alloca (n)
-#else /* Not GCC. */
-#ifdef HAVE_ALLOCA_H
-#include <alloca.h>
-#else /* Not HAVE_ALLOCA_H. */
-#ifndef _AIX
+#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
extern char *alloca ();
-#endif /* Not AIX. */
-#endif /* HAVE_ALLOCA_H. */
-#endif /* GCC. */
-
-#ifndef iAPX286
-#define streq(a, b) \
- ((a) == (b) || \
- (*(a) == *(b) && (*(a) == '\0' || !strcmp ((a) + 1, (b) + 1))))
-#ifdef HAVE_CASE_INSENSITIVE_FS
-#define strieq(a, b) \
- ((a) == (b) || \
- (tolower(*(a)) == tolower(*(b)) && (*(a) == '\0' || !strcmpi ((a) + 1, (b) + 1))))
-#else
-#define strieq(a, b) \
- ((a) == (b) || \
- (*(a) == *(b) && (*(a) == '\0' || !strcmp ((a) + 1, (b) + 1))))
-#endif
+# endif /* Not AIX. */
+# endif /* HAVE_ALLOCA_H. */
+#endif /* GCC. */
+
+#ifndef iAPX286
+# define streq(a, b) \
+ ((a) == (b) || \
+ (*(a) == *(b) && (*(a) == '\0' || !strcmp ((a) + 1, (b) + 1))))
+# ifdef HAVE_CASE_INSENSITIVE_FS
+# define strieq(a, b) \
+ ((a) == (b) || \
+ (tolower(*(a)) == tolower(*(b)) && (*(a) == '\0' || !strcmpi ((a) + 1, (b) + 1))))
+# else
+# define strieq(a, b) \
+ ((a) == (b) || \
+ (*(a) == *(b) && (*(a) == '\0' || !strcmp ((a) + 1, (b) + 1))))
+# endif
#else
/* Buggy compiler can't handle this. */
-#define streq(a, b) (strcmp ((a), (b)) == 0)
-#define strieq(a, b) (strcmp ((a), (b)) == 0)
+# define streq(a, b) (strcmp ((a), (b)) == 0)
+# define strieq(a, b) (strcmp ((a), (b)) == 0)
#endif
/* Add to VAR the hashing value of C, one character in a name. */
-#define HASH(var, c) \
+#define HASH(var, c) \
((var += (c)), (var = ((var) << 7) + ((var) >> 20)))
#ifdef HAVE_CASE_INSENSITIVE_FS /* Fold filenames */
-#define HASHI(var, c) \
- ((var += tolower((c))), (var = ((var) << 7) + ((var) >> 20)))
+# define HASHI(var, c) \
+ ((var += tolower((c))), (var = ((var) << 7) + ((var) >> 20)))
#else
-#define HASHI(var, c) HASH(var,c)
+# define HASHI(var, c) HASH(var,c)
#endif
#if defined(__GNUC__) || defined(ENUM_BITFIELDS)
-#define ENUM_BITFIELD(bits) :bits
+# define ENUM_BITFIELD(bits) :bits
#else
-#define ENUM_BITFIELD(bits)
+# define ENUM_BITFIELD(bits)
#endif
#if defined(__MSDOS__) || defined(WINDOWS32)
-#define PATH_SEPARATOR_CHAR ';'
-#else
-#if defined(VMS)
-#define PATH_SEPARATOR_CHAR ','
+# define PATH_SEPARATOR_CHAR ';'
#else
-#define PATH_SEPARATOR_CHAR ':'
-#endif
+# if defined(VMS)
+# define PATH_SEPARATOR_CHAR ','
+# else
+# define PATH_SEPARATOR_CHAR ':'
+# endif
#endif
#ifdef WINDOWS32
-#include <fcntl.h>
-#include <malloc.h>
-#define pipe(p) _pipe(p, 512, O_BINARY)
-#define kill(pid,sig) w32_kill(pid,sig)
+# include <fcntl.h>
+# include <malloc.h>
+# define pipe(p) _pipe(p, 512, O_BINARY)
+# define kill(pid,sig) w32_kill(pid,sig)
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();
+extern char *end_of_token_w32(char *s, char stopchar);
extern int find_and_set_default_shell(char *token);
/* indicates whether or not we have Bourne shell */
@@ -323,72 +341,81 @@ extern int no_default_sh_exe;
/* is default_shell unixy? */
extern int unixy_shell;
#endif /* WINDOWS32 */
+
+struct floc
+ {
+ char *filenm;
+ unsigned long lineno;
+ };
+#define NILF ((struct floc *)0)
+
-extern void die () __attribute__ ((noreturn));
+/* Fancy processing for variadic functions in both ANSI and pre-ANSI
+ compilers. */
+#if defined __STDC__ && __STDC__
+extern void message (int prefix, const char *fmt, ...)
+ __attribute__ ((__format__ (__printf__, 2, 3)));
+extern void error (const struct floc *flocp, const char *fmt, ...)
+ __attribute__ ((__format__ (__printf__, 2, 3)));
+extern void fatal (const struct floc *flocp, const char *fmt, ...)
+ __attribute__ ((noreturn, __format__ (__printf__, 2, 3)));
+#else
extern void message ();
-extern void fatal () __attribute__ ((noreturn));
extern void error ();
-extern void log_working_directory ();
-extern void makefile_error ();
-extern void makefile_fatal () __attribute__ ((noreturn));
-extern void pfatal_with_name () __attribute__ ((noreturn));
-extern void perror_with_name ();
-extern char *savestring ();
-extern char *concat ();
-extern char *xmalloc ();
-extern char *xrealloc ();
-extern char *find_next_token ();
-extern char *next_token ();
-extern char *end_of_token ();
-extern void collapse_continuations ();
-extern void remove_comments ();
-extern char *sindex ();
-extern char *lindex ();
-extern int alpha_compare ();
-extern void print_spaces ();
-extern struct dep *copy_dep_chain ();
-extern char *find_char_unquote ();
-extern char *find_percent ();
-
-#ifndef NO_ARCHIVES
-extern int ar_name ();
-extern void ar_parse_name ();
-extern int ar_touch ();
-extern time_t ar_member_date ();
-#endif
-
-extern void dir_load ();
-extern int dir_file_exists_p ();
-extern int file_exists_p ();
-extern int file_impossible_p ();
-extern void file_impossible ();
-extern char *dir_name ();
-
-extern void define_default_variables ();
-extern void set_default_suffixes ();
-extern void install_default_suffix_rules ();
-extern void install_default_implicit_rules ();
-extern void count_implicit_rule_limits ();
-extern void convert_to_pattern ();
-extern void create_pattern_rule ();
-
-extern void build_vpath_lists ();
-extern void construct_vpath_list ();
-extern int vpath_search ();
-extern int gpath_search ();
-
-extern void construct_include_path ();
-extern void uniquize_deps ();
-
-extern int update_goal_chain ();
-extern void notice_finished_file ();
-
-extern void user_access ();
-extern void make_access ();
-extern void child_access ();
-
-#ifdef HAVE_VFORK_H
-#include <vfork.h>
+extern void fatal ();
+#endif
+
+extern void die PARAMS ((int)) __attribute__ ((noreturn));
+extern void log_working_directory PARAMS ((int));
+extern void pfatal_with_name PARAMS ((char *)) __attribute__ ((noreturn));
+extern void perror_with_name PARAMS ((char *, char *));
+extern char *savestring PARAMS ((char *, unsigned int));
+extern char *concat PARAMS ((char *, char *, char *));
+extern char *xmalloc PARAMS ((unsigned int));
+extern char *xrealloc PARAMS ((char *, unsigned int));
+extern char *find_next_token PARAMS ((char **, unsigned int *));
+extern char *next_token PARAMS ((char *));
+extern char *end_of_token PARAMS ((char *));
+extern void collapse_continuations PARAMS ((char *));
+extern void remove_comments PARAMS((char *));
+extern char *sindex PARAMS ((char *, unsigned int, char *, unsigned int));
+extern char *lindex PARAMS ((char *, char *, int));
+extern int alpha_compare PARAMS ((const void *, const void *));
+extern void print_spaces PARAMS ((unsigned int));
+extern char *find_char_unquote PARAMS ((char *, char *, int));
+extern char *find_percent PARAMS ((char *));
+
+#ifndef NO_ARCHIVES
+extern int ar_name PARAMS ((char *));
+extern void ar_parse_name PARAMS ((char *, char **, char **));
+extern int ar_touch PARAMS ((char *));
+extern time_t ar_member_date PARAMS ((char *));
+#endif
+
+extern int dir_file_exists_p PARAMS ((char *, char *));
+extern int file_exists_p PARAMS ((char *));
+extern int file_impossible_p PARAMS ((char *));
+extern void file_impossible PARAMS ((char *));
+extern char *dir_name PARAMS ((char *));
+
+extern void define_default_variables PARAMS ((void));
+extern void set_default_suffixes PARAMS ((void));
+extern void install_default_suffix_rules PARAMS ((void));
+extern void install_default_implicit_rules PARAMS ((void));
+
+extern void build_vpath_lists PARAMS ((void));
+extern void construct_vpath_list PARAMS ((char *pattern, char *dirpath));
+extern int vpath_search PARAMS ((char **file, FILE_TIMESTAMP *mtime_ptr));
+extern int gpath_search PARAMS ((char *file, int len));
+
+extern void construct_include_path PARAMS ((char **arg_dirs));
+
+extern void user_access PARAMS ((void));
+extern void make_access PARAMS ((void));
+extern void child_access PARAMS ((void));
+
+#ifdef HAVE_VFORK_H
+# include <vfork.h>
#endif
/* We omit these declarations on non-POSIX systems which define _POSIX_VERSION,
@@ -397,26 +424,25 @@ extern void child_access ();
#if !defined (__GNU_LIBRARY__) && !defined (POSIX) && !defined (_POSIX_VERSION) && !defined(WINDOWS32)
extern long int atol ();
-#ifndef VMS
+# ifndef VMS
extern long int lseek ();
-#endif
+# endif
-#endif /* Not GNU C library or POSIX. */
+#endif /* Not GNU C library or POSIX. */
-#ifdef HAVE_GETCWD
+#ifdef HAVE_GETCWD
extern char *getcwd ();
-#ifdef VMS
+# ifdef VMS
extern char *getwd PARAMS ((char *));
-#endif
+# endif
#else
extern char *getwd ();
-#define getcwd(buf, len) getwd (buf)
+# define getcwd(buf, len) getwd (buf)
#endif
-extern char **environ;
+extern const struct floc *reading_file;
-extern char *reading_filename;
-extern unsigned int *reading_lineno_ptr;
+extern char **environ;
extern int just_print_flag, silent_flag, ignore_errors_flag, keep_going_flag;
extern int debug_flag, print_data_base_flag, question_flag, touch_flag;
@@ -445,9 +471,16 @@ extern unsigned int commands_started;
extern int handling_fatal_signal;
+#ifndef MIN
+#define MIN(_a,_b) ((_a)<(_b)?(_a):(_b))
+#endif
+#ifndef MAX
+#define MAX(_a,_b) ((_a)>(_b)?(_a):(_b))
+#endif
+
#define DEBUGPR(msg) \
do if (debug_flag) { print_spaces (depth); printf (msg, file->name); \
- fflush (stdout); } while (0)
+ fflush (stdout); } while (0)
#ifdef VMS
# ifndef EXIT_FAILURE
@@ -470,4 +503,3 @@ extern int handling_fatal_signal;
# define EXIT_TROUBLE 1
# endif
#endif
-
diff --git a/make.texinfo b/make.texinfo
index 05d0746..e7b3bbf 100644
--- a/make.texinfo
+++ b/make.texinfo
@@ -68,17 +68,17 @@ by the Free Software Foundation.
@titlepage
@title GNU Make
@subtitle A Program for Directing Recompilation
-@subtitle GNU @code{make} Version @value{VERSION}.
+@subtitle GNU @code{make} Version @value{VERSION}
@subtitle @value{UPDATE-MONTH}
@author Richard M. Stallman and Roland McGrath
@page
@vskip 0pt plus 1filll
-Copyright @copyright{} 1988, '89, '90, '91, '92, '93, '94, '95, '96, '97 Free Software Foundation, Inc.
+Copyright @copyright{} 1988, '89, '90, '91, '92, '93, '94, '95, '96, '97, '98
+Free Software Foundation, Inc.
@sp 2
Published by the Free Software Foundation @*
59 Temple Place -- Suite 330, @*
Boston, MA 02111-1307 USA @*
-Printed copies are available for $20 each. @*
ISBN @value{ISBN} @*
Permission is granted to make and distribute verbatim copies of
@@ -124,7 +124,7 @@ This manual describes @code{make} and contains the following chapters:@refill
* Conditionals:: Use or ignore parts of the makefile based
on the values of variables.
* Functions:: Many powerful ways to manipulate text.
-* make Invocation: Running. How to invoke @code{make} on the command line.
+* Invoking make: Running. How to invoke @code{make} on the command line.
* Implicit Rules:: Use implicit rules to treat many files alike,
based on their file names.
* Archives:: How @code{make} can update library archives.
@@ -2241,8 +2241,7 @@ match that file's name.
The targets which @code{.INTERMEDIATE} depends on are treated as
intermediate files. @xref{Chained Rules, ,Chains of Implicit Rules}.
-@code{.INTERMEDIATE} with no dependencies marks all file targets
-mentioned in the makefile as intermediate.
+@code{.INTERMEDIATE} with no dependencies has no effect.
@findex .SECONDARY
@item .SECONDARY
diff --git a/misc.c b/misc.c
index 1411e54..0612862 100644
--- a/misc.c
+++ b/misc.c
@@ -20,17 +20,52 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "dep.h"
+/* Variadic functions. We go through contortions to allow proper function
+ prototypes for both ANSI and pre-ANSI C compilers, and also for those
+ which support stdarg.h vs. varargs.h, and finally those which have
+ vfprintf(), etc. and those who have _doprnt... or nothing.
+
+ This fancy stuff all came from GNU fileutils, except for the VA_PRINTF and
+ VA_END macros used here since we have multiple print functions. */
+
+#if HAVE_VPRINTF || HAVE_DOPRNT
+# define HAVE_STDVARARGS 1
+# if __STDC__
+# include <stdarg.h>
+# define VA_START(args, lastarg) va_start(args, lastarg)
+# else
+# include <varargs.h>
+# define VA_START(args, lastarg) va_start(args)
+# endif
+# if HAVE_VPRINTF
+# define VA_PRINTF(fp, lastarg, args) vfprintf((fp), (lastarg), (args))
+# else
+# define VA_PRINTF(fp, lastarg, args) _doprnt((lastarg), (args), (fp))
+# endif
+# define VA_END(args) va_end(args)
+#else
+/* # undef HAVE_STDVARARGS */
+# define va_alist a1, a2, a3, a4, a5, a6, a7, a8
+# define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
+# define VA_START(args, lastarg)
+# define VA_END(args)
+#endif
+
+
/* Compare strings *S1 and *S2.
Return negative if the first is less, positive if it is greater,
zero if they are equal. */
int
-alpha_compare (s1, s2)
- char **s1, **s2;
+alpha_compare (v1, v2)
+ const void *v1, *v2;
{
- if (**s1 != **s2)
- return **s1 - **s2;
- return strcmp (*s1, *s2);
+ const char *s1 = *((char **)v1);
+ const char *s2 = *((char **)v2);
+
+ if (*s1 != *s2)
+ return *s1 - *s2;
+ return strcmp (s1, s2);
}
/* Discard each backslash-newline combination from LINE.
@@ -173,13 +208,22 @@ concat (s1, s2, s3)
/* Print a message on stdout. */
void
-message (prefix, s1, s2, s3, s4, s5, s6)
+#if __STDC__ && HAVE_STDVARARGS
+message (int prefix, const char *fmt, ...)
+#else
+message (prefix, fmt, va_alist)
int prefix;
- char *s1, *s2, *s3, *s4, *s5, *s6;
+ const char *fmt;
+ va_dcl
+#endif
{
+#if HAVE_STDVARARGS
+ va_list args;
+#endif
+
log_working_directory (1);
- if (s1 != 0)
+ if (fmt != 0)
{
if (prefix)
{
@@ -188,78 +232,77 @@ message (prefix, s1, s2, s3, s4, s5, s6)
else
printf ("%s[%u]: ", program, makelevel);
}
- printf (s1, s2, s3, s4, s5, s6);
+ VA_START (args, fmt);
+ VA_PRINTF (stdout, fmt, args);
+ VA_END (args);
putchar ('\n');
}
fflush (stdout);
}
-/* Print an error message and exit. */
+/* Print an error message. */
-/* VARARGS1 */
void
-fatal (s1, s2, s3, s4, s5, s6)
- char *s1, *s2, *s3, *s4, *s5, *s6;
+#if __STDC__ && HAVE_STDVARARGS
+error (const struct floc *flocp, const char *fmt, ...)
+#else
+error (flocp, fmt, va_alist)
+ const struct floc *flocp;
+ const char *fmt;
+ va_dcl
+#endif
{
- log_working_directory (1);
-
- if (makelevel == 0)
- fprintf (stderr, "%s: *** ", program);
- else
- fprintf (stderr, "%s[%u]: *** ", program, makelevel);
- fprintf (stderr, s1, s2, s3, s4, s5, s6);
- fputs (". Stop.\n", stderr);
-
- die (2);
-}
-
-/* Print error message. `s1' is printf control string, `s2' is arg for it. */
-
-/* VARARGS1 */
+#if HAVE_STDVARARGS
+ va_list args;
+#endif
-void
-error (s1, s2, s3, s4, s5, s6)
- char *s1, *s2, *s3, *s4, *s5, *s6;
-{
log_working_directory (1);
- if (makelevel == 0)
+ if (flocp && flocp->filenm)
+ fprintf (stderr, "%s:%lu: ", flocp->filenm, flocp->lineno);
+ else if (makelevel == 0)
fprintf (stderr, "%s: ", program);
else
fprintf (stderr, "%s[%u]: ", program, makelevel);
- fprintf (stderr, s1, s2, s3, s4, s5, s6);
- putc ('\n', stderr);
- fflush (stderr);
-}
-void
-makefile_error (file, lineno, s1, s2, s3, s4, s5, s6)
- char *file;
- unsigned int lineno;
- char *s1, *s2, *s3, *s4, *s5, *s6;
-{
- log_working_directory (1);
+ VA_START(args, fmt);
+ VA_PRINTF (stderr, fmt, args);
+ VA_END (args);
- fprintf (stderr, "%s:%u: ", file, lineno);
- fprintf (stderr, s1, s2, s3, s4, s5, s6);
putc ('\n', stderr);
fflush (stderr);
}
+/* Print an error message and exit. */
+
void
-makefile_fatal (file, lineno, s1, s2, s3, s4, s5, s6)
- char *file;
- unsigned int lineno;
- char *s1, *s2, *s3, *s4, *s5, *s6;
+#if __STDC__ && HAVE_STDVARARGS
+fatal (const struct floc *flocp, const char *fmt, ...)
+#else
+fatal (flocp, fmt, va_alist)
+ const struct floc *flocp;
+ const char *fmt;
+ va_dcl
+#endif
{
- if (!file)
- fatal(s1, s2, s3, s4, s5, s6);
+#if HAVE_STDVARARGS
+ va_list args;
+#endif
log_working_directory (1);
- fprintf (stderr, "%s:%u: *** ", file, lineno);
- fprintf (stderr, s1, s2, s3, s4, s5, s6);
+ if (flocp && flocp->filenm)
+ fprintf (stderr, "%s:%lu: *** ", flocp->filenm, flocp->lineno);
+ else if (makelevel == 0)
+ fprintf (stderr, "%s: *** ", program);
+ else
+ fprintf (stderr, "%s[%u]: *** ", program, makelevel);
+
+ VA_START(args, fmt);
+ VA_PRINTF (stderr, fmt, args);
+ VA_END (args);
+
fputs (". Stop.\n", stderr);
die (2);
@@ -293,7 +336,7 @@ void
perror_with_name (str, name)
char *str, *name;
{
- error ("%s%s: %s", str, name, strerror (errno));
+ error (NILF, "%s%s: %s", str, name, strerror (errno));
}
/* Print an error message from errno and exit. */
@@ -302,7 +345,7 @@ void
pfatal_with_name (name)
char *name;
{
- fatal ("%s: %s", name, strerror (errno));
+ fatal (NILF, "%s: %s", name, strerror (errno));
/* NOTREACHED */
}
@@ -318,7 +361,7 @@ xmalloc (size)
{
char *result = (char *) malloc (size);
if (result == 0)
- fatal ("virtual memory exhausted");
+ fatal (NILF, "virtual memory exhausted");
return result;
}
@@ -330,7 +373,7 @@ xrealloc (ptr, size)
{
char *result = (char *) realloc (ptr, size);
if (result == 0)
- fatal ("virtual memory exhausted");
+ fatal (NILF, "virtual memory exhausted");
return result;
}
diff --git a/read.c b/read.c
index 0207516..a677399 100644
--- a/read.c
+++ b/read.c
@@ -119,26 +119,27 @@ static unsigned int max_incl_len;
/* The filename and pointer to line number of the
makefile currently being read in. */
-char *reading_filename;
-unsigned int *reading_lineno_ptr;
+const struct floc *reading_file;
/* The chain of makefiles read by read_makefile. */
static struct dep *read_makefiles = 0;
static int read_makefile PARAMS ((char *filename, int flags));
-static unsigned int readline PARAMS ((struct linebuffer *linebuffer, FILE *stream,
- char *filename, unsigned int lineno));
-static unsigned int do_define PARAMS ((char *name, unsigned int namelen, enum variable_origin origin,
- unsigned int lineno, FILE *infile, char *filename));
-static int conditional_line PARAMS ((char *line, char *filename, unsigned int lineno));
+static unsigned long readline PARAMS ((struct linebuffer *linebuffer,
+ FILE *stream, const struct floc *flocp));
+static void do_define PARAMS ((char *name, unsigned int namelen,
+ enum variable_origin origin, FILE *infile,
+ struct floc *flocp));
+static int conditional_line PARAMS ((char *line, const struct floc *flocp));
static void record_files PARAMS ((struct nameseq *filenames, char *pattern, char *pattern_percent,
struct dep *deps, unsigned int cmds_started, char *commands,
- unsigned int commands_idx, int two_colon, char *filename,
- unsigned int lineno, int set_default));
+ unsigned int commands_idx, int two_colon,
+ const struct floc *flocp, 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));
+ int two_colon,
+ enum variable_origin origin,
+ const struct floc *flocp));
static enum make_word_type get_next_mword PARAMS ((char *buffer, char *delim,
char **startp, unsigned int *length));
@@ -290,11 +291,11 @@ read_makefile (filename, flags)
int len, reading_target;
int ignoring = 0, in_ignored_define = 0;
int no_targets = 0; /* Set when reading a rule without targets. */
+ struct floc fileinfo;
char *passed_filename = filename;
struct nameseq *filenames = 0;
struct dep *deps;
- unsigned int lineno = 1;
unsigned int nlines = 0;
int two_colon = 0;
char *pattern = 0, *pattern_percent;
@@ -310,19 +311,22 @@ read_makefile (filename, flags)
if (filenames != 0) \
record_files (filenames, pattern, pattern_percent, deps, \
cmds_started, commands, commands_idx, \
- two_colon, filename, lineno, \
+ two_colon, &fileinfo, \
!(flags & RM_NO_DEFAULT_GOAL)); \
filenames = 0; \
commands_idx = 0; \
if (pattern) { free(pattern); pattern = 0; } \
} while (0)
+ fileinfo.filenm = filename;
+ fileinfo.lineno = 1;
+
pattern_percent = 0;
- cmds_started = lineno;
+ cmds_started = fileinfo.lineno;
if (debug_flag)
{
- printf ("Reading makefile `%s'", filename);
+ printf ("Reading makefile `%s'", fileinfo.filenm);
if (flags & RM_NO_DEFAULT_GOAL)
printf (" (no default goal)");
if (flags & RM_INCLUDED)
@@ -398,8 +402,7 @@ read_makefile (filename, flags)
return 0;
}
- reading_filename = filename;
- reading_lineno_ptr = &lineno;
+ reading_file = &fileinfo;
/* Loop over lines in the file.
The strategy is to accumulate target names in FILENAMES, dependencies
@@ -410,8 +413,8 @@ read_makefile (filename, flags)
while (!feof (infile))
{
- lineno += nlines;
- nlines = readline (&lb, infile, filename, lineno);
+ fileinfo.lineno += nlines;
+ nlines = readline (&lb, infile, &fileinfo);
/* Check for a shell command line first.
If it is not one, we can stop treating tab specially. */
@@ -437,7 +440,7 @@ read_makefile (filename, flags)
/* Append this command line to the line being accumulated. */
p = lb.buffer;
if (commands_idx == 0)
- cmds_started = lineno;
+ cmds_started = fileinfo.lineno;
len = strlen (p);
if (len + 1 + commands_idx > commands_len)
{
@@ -506,12 +509,11 @@ read_makefile (filename, flags)
|| word1eq ("ifeq", 4) || word1eq ("ifneq", 5)
|| word1eq ("else", 4) || word1eq ("endif", 5)))
{
- int i = conditional_line (p, filename, lineno);
+ int i = conditional_line (p, &fileinfo);
if (i >= 0)
ignoring = i;
else
- makefile_fatal (filename, lineno,
- "invalid syntax in conditional");
+ fatal (&fileinfo, "invalid syntax in conditional");
continue;
}
@@ -520,7 +522,7 @@ read_makefile (filename, flags)
if (in_ignored_define)
in_ignored_define = 0;
else
- makefile_fatal (filename, lineno, "extraneous `endef'");
+ fatal (&fileinfo, "extraneous `endef'");
continue;
}
@@ -538,8 +540,7 @@ read_makefile (filename, flags)
p = index (p2, '\0');
while (isblank (p[-1]))
--p;
- lineno = do_define (p2, p - p2, o_file,
- lineno, infile, filename);
+ do_define (p2, p - p2, o_file, infile, &fileinfo);
}
continue;
}
@@ -548,7 +549,7 @@ read_makefile (filename, flags)
{
p2 = next_token (p + 8);
if (p2 == 0)
- makefile_error (filename, lineno, "empty `override' directive");
+ error (&fileinfo, "empty `override' directive");
if (!strncmp (p2, "define", 6) && (isblank (p2[6]) || p2[6] == '\0'))
{
if (ignoring)
@@ -563,14 +564,12 @@ read_makefile (filename, flags)
p = index (p2, '\0');
while (isblank (p[-1]))
--p;
- lineno = do_define (p2, p - p2, o_override,
- lineno, infile, filename);
+ do_define (p2, p - p2, o_override, infile, &fileinfo);
}
}
else if (!ignoring
- && !try_variable_definition (filename, lineno,
- p2, o_override))
- makefile_error (filename, lineno, "empty `override' directive");
+ && !try_variable_definition (&fileinfo, p2, o_override))
+ error (&fileinfo, "empty `override' directive");
continue;
}
@@ -587,7 +586,7 @@ read_makefile (filename, flags)
p2 = next_token (p + 6);
if (*p2 == '\0')
export_all_variables = 1;
- v = try_variable_definition (filename, lineno, p2, o_file);
+ v = try_variable_definition (&fileinfo, p2, o_file);
if (v != 0)
v->export = v_export;
else
@@ -653,7 +652,7 @@ read_makefile (filename, flags)
p = allocated_variable_expand (next_token (p + (noerror ? 8 : 7)));
if (*p == '\0')
{
- makefile_error (filename, lineno,
+ error (&fileinfo,
"no file name for `%sinclude'",
noerror ? "-" : "");
continue;
@@ -688,7 +687,7 @@ read_makefile (filename, flags)
if (! read_makefile (name, (RM_INCLUDED | RM_NO_TILDE
| (noerror ? RM_DONTCARE : 0)))
&& ! noerror)
- makefile_error (filename, lineno,
+ error (&fileinfo,
"%s: %s", name, strerror (errno));
free(name);
}
@@ -701,11 +700,10 @@ read_makefile (filename, flags)
/* Restore state. */
conditionals = save;
- reading_filename = filename;
- reading_lineno_ptr = &lineno;
+ reading_file = &fileinfo;
}
#undef word1eq
- else if (try_variable_definition (filename, lineno, p, o_file))
+ else if (try_variable_definition (&fileinfo, p, o_file))
/* This line has been dealt with. */
;
else if (lb.buffer[0] == '\t')
@@ -720,7 +718,7 @@ read_makefile (filename, flags)
because there was no preceding target, and the line
might have been usable as a variable definition.
But now it is definitely lossage. */
- makefile_fatal (filename, lineno,
+ fatal (&fileinfo,
"commands commence before first target");
}
else
@@ -739,6 +737,7 @@ read_makefile (filename, flags)
enum variable_origin v_origin;
char *cmdleft, *lb_next;
unsigned int len, plen = 0;
+ char *colonp;
/* Record the previous rule. */
@@ -768,7 +767,7 @@ read_makefile (filename, flags)
{
case w_eol:
if (cmdleft != 0)
- makefile_fatal (filename, lineno,
+ fatal (&fileinfo,
"missing rule before commands");
else
/* This line contained a variable reference that
@@ -789,8 +788,6 @@ read_makefile (filename, flags)
p2 = variable_expand_string(NULL, lb_next, len);
while (1)
{
- char *colonp;
-
lb_next += len;
if (cmdleft == 0)
{
@@ -825,12 +822,12 @@ read_makefile (filename, flags)
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'. */
+ /* Note that the only separators of targets in this context
+ are whitespace and a left paren. If others are possible,
+ they should be added to the string in the call to index. */
while (colonp && (colonp[1] == '/' || colonp[1] == '\\') &&
colonp > p2 && isalpha(colonp[-1]) &&
- (colonp == p2 + 1 || isspace(colonp[-2])))
+ (colonp == p2 + 1 || index(" \t(", colonp[-2]) != 0))
colonp = find_char_unquote(colonp + 1, ":", 0);
#endif
if (colonp != 0)
@@ -838,7 +835,11 @@ read_makefile (filename, flags)
wtype = get_next_mword(lb_next, NULL, &lb_next, &len);
if (wtype == w_eol)
- makefile_fatal (filename, lineno, "missing separator");
+ /* There's no need to be ivory-tower about this: check for
+ one of the most common bugs found in makefiles... */
+ fatal (&fileinfo, "missing separator%s",
+ strncmp(lb.buffer, " ", 8) ? ""
+ : " (did you mean TAB instead of 8 spaces?)");
p2 += strlen(p2);
*(p2++) = ' ';
@@ -850,10 +851,14 @@ read_makefile (filename, flags)
p2 = next_token (variable_buffer);
- filenames = multi_glob (parse_file_seq (&p2, ':',
+ /* Make the colon the end-of-string so we know where to stop
+ looking for targets. */
+ *colonp = '\0';
+ filenames = multi_glob (parse_file_seq (&p2, '\0',
sizeof (struct nameseq),
1),
sizeof (struct nameseq));
+ *colonp = ':';
if (!filenames)
{
@@ -896,8 +901,7 @@ read_makefile (filename, flags)
if (wtype == w_varassign || v_origin == o_override)
{
- record_target_var(filenames, p, two_colon, v_origin,
- filename, lineno);
+ record_target_var(filenames, p, two_colon, v_origin, &fileinfo);
filenames = 0;
continue;
}
@@ -959,7 +963,8 @@ read_makefile (filename, flags)
check_again = 0;
/* For MSDOS and WINDOWS32, skip a "C:\..." or a "C:/..." */
if (p != 0 && (p[1] == '\\' || p[1] == '/') &&
- isalpha(p[-1]) && (p == p2 + 1 || index(" \t:", p[-2]) != 0)) {
+ isalpha(p[-1]) &&
+ (p == p2 + 1 || index(" \t:(", p[-2]) != 0)) {
p = index(p + 1, ':');
check_again = 1;
}
@@ -971,13 +976,13 @@ read_makefile (filename, flags)
target = parse_file_seq (&p2, ':', sizeof (struct nameseq), 1);
++p2;
if (target == 0)
- makefile_fatal (filename, lineno, "missing target pattern");
+ fatal (&fileinfo, "missing target pattern");
else if (target->next != 0)
- makefile_fatal (filename, lineno, "multiple target patterns");
+ fatal (&fileinfo, "multiple target patterns");
pattern = target->name;
pattern_percent = find_percent (pattern);
if (pattern_percent == 0)
- makefile_fatal (filename, lineno,
+ fatal (&fileinfo,
"target pattern contains no `%%'");
free((char *)target);
}
@@ -995,7 +1000,7 @@ read_makefile (filename, flags)
/* Semicolon means rest of line is a command. */
unsigned int len = strlen (cmdleft);
- cmds_started = lineno;
+ cmds_started = fileinfo.lineno;
/* Add this command line to the buffer. */
if (len + 2 > commands_len)
@@ -1019,7 +1024,7 @@ read_makefile (filename, flags)
}
if (conditionals->if_cmds)
- makefile_fatal (filename, lineno, "missing `endif'");
+ fatal (&fileinfo, "missing `endif'");
/* At eof, record the last rule. */
record_waiting_files ();
@@ -1028,8 +1033,7 @@ read_makefile (filename, flags)
free ((char *) commands);
fclose (infile);
- reading_filename = 0;
- reading_lineno_ptr = 0;
+ reading_file = 0;
return 1;
}
@@ -1040,14 +1044,13 @@ read_makefile (filename, flags)
LINENO, INFILE and FILENAME refer to the makefile being read.
The value returned is LINENO, updated for lines read here. */
-static unsigned int
-do_define (name, namelen, origin, lineno, infile, filename)
+static void
+do_define (name, namelen, origin, infile, flocp)
char *name;
unsigned int namelen;
enum variable_origin origin;
- unsigned int lineno;
FILE *infile;
- char *filename;
+ struct floc *flocp;
{
struct linebuffer lb;
unsigned int nlines = 0;
@@ -1067,8 +1070,8 @@ do_define (name, namelen, origin, lineno, infile, filename)
{
unsigned int len;
- lineno += nlines;
- nlines = readline (&lb, infile, filename, lineno);
+ flocp->lineno += nlines;
+ nlines = readline (&lb, infile, flocp);
collapse_continuations (lb.buffer);
@@ -1080,8 +1083,7 @@ do_define (name, namelen, origin, lineno, infile, filename)
p += 5;
remove_comments (p);
if (*next_token (p) != '\0')
- makefile_error (filename, lineno,
- "Extraneous text after `endef' directive");
+ error (flocp, "Extraneous text after `endef' directive");
/* Define the variable. */
if (idx == 0)
definition[0] = '\0';
@@ -1090,7 +1092,7 @@ do_define (name, namelen, origin, lineno, infile, filename)
(void) define_variable (var, strlen (var), definition, origin, 1);
free (definition);
freebuffer (&lb);
- return (lineno + nlines);
+ return;
}
else
{
@@ -1110,10 +1112,10 @@ do_define (name, namelen, origin, lineno, infile, filename)
}
/* No `endef'!! */
- makefile_fatal (filename, lineno, "missing `endef', unterminated `define'");
+ fatal (flocp, "missing `endef', unterminated `define'");
/* NOTREACHED */
- return 0;
+ return;
}
/* Interpret conditional commands "ifdef", "ifndef", "ifeq",
@@ -1128,10 +1130,9 @@ do_define (name, namelen, origin, lineno, infile, filename)
1 if following text should be ignored. */
static int
-conditional_line (line, filename, lineno)
+conditional_line (line, flocp)
char *line;
- char *filename;
- unsigned int lineno;
+ const struct floc *flocp;
{
int notdef;
char *cmdname;
@@ -1165,17 +1166,16 @@ conditional_line (line, filename, lineno)
if (*cmdname == 'e')
{
if (*line != '\0')
- makefile_error (filename, lineno,
- "Extraneous text after `%s' directive",
- cmdname);
+ error (flocp,
+ "Extraneous text after `%s' directive", cmdname);
/* "Else" or "endif". */
if (conditionals->if_cmds == 0)
- makefile_fatal (filename, lineno, "extraneous `%s'", cmdname);
+ fatal (flocp, "extraneous `%s'", cmdname);
/* NOTDEF indicates an `endif' command. */
if (notdef)
--conditionals->if_cmds;
else if (conditionals->seen_else[conditionals->if_cmds - 1])
- makefile_fatal (filename, lineno, "only one `else' per conditional");
+ fatal (flocp, "only one `else' per conditional");
else
{
/* Toggle the state of ignorance. */
@@ -1321,9 +1321,8 @@ conditional_line (line, filename, lineno)
*line = '\0';
line = next_token (++line);
if (*line != '\0')
- makefile_error (filename, lineno,
- "Extraneous text after `%s' directive",
- cmdname);
+ error (flocp,
+ "Extraneous text after `%s' directive", cmdname);
s2 = variable_expand (s2);
conditionals->ignoring[conditionals->if_cmds - 1]
@@ -1384,13 +1383,12 @@ uniquize_deps (chain)
variable value list. */
static void
-record_target_var (filenames, defn, two_colon, origin, filename, lineno)
+record_target_var (filenames, defn, two_colon, origin, flocp)
struct nameseq *filenames;
char *defn;
int two_colon;
enum variable_origin origin;
- char *filename;
- unsigned int lineno;
+ const struct floc *flocp;
{
struct nameseq *nextf;
struct variable_set_list *global;
@@ -1433,10 +1431,9 @@ record_target_var (filenames, defn, two_colon, origin, filename, lineno)
/* Make the new variable context current and define the variable. */
current_variable_set_list = vlist;
- v = try_variable_definition(filename, lineno, defn, origin);
+ v = try_variable_definition(flocp, defn, origin);
if (!v)
- makefile_error(filename, lineno,
- "Malformed per-target variable definition");
+ error (flocp, "Malformed per-target variable definition");
v->per_target = 1;
/* If it's not an override, check to see if there was a command-line
@@ -1474,7 +1471,7 @@ record_target_var (filenames, defn, two_colon, origin, filename, lineno)
static void
record_files (filenames, pattern, pattern_percent, deps, cmds_started,
- commands, commands_idx, two_colon, filename, lineno, set_default)
+ commands, commands_idx, two_colon, flocp, set_default)
struct nameseq *filenames;
char *pattern, *pattern_percent;
struct dep *deps;
@@ -1482,8 +1479,7 @@ record_files (filenames, pattern, pattern_percent, deps, cmds_started,
char *commands;
unsigned int commands_idx;
int two_colon;
- char *filename;
- unsigned int lineno;
+ const struct floc *flocp;
int set_default;
{
struct nameseq *nextf;
@@ -1495,8 +1491,8 @@ record_files (filenames, pattern, pattern_percent, deps, cmds_started,
if (commands_idx > 0)
{
cmds = (struct commands *) xmalloc (sizeof (struct commands));
- cmds->filename = filename;
- cmds->lineno = cmds_started;
+ cmds->fileinfo.filenm = flocp->filenm;
+ cmds->fileinfo.lineno = cmds_started;
cmds->commands = savestring (commands, commands_idx);
cmds->command_lines = 0;
}
@@ -1519,11 +1515,10 @@ record_files (filenames, pattern, pattern_percent, deps, cmds_started,
implicit |= implicit_percent != 0;
if (implicit && pattern != 0)
- makefile_fatal (filename, lineno,
- "mixed implicit and static pattern rules");
+ fatal (flocp, "mixed implicit and static pattern rules");
if (implicit && implicit_percent == 0)
- makefile_fatal (filename, lineno, "mixed implicit and normal rules");
+ fatal (flocp, "mixed implicit and normal rules");
if (implicit)
{
@@ -1562,7 +1557,7 @@ record_files (filenames, pattern, pattern_percent, deps, cmds_started,
if (!pattern_matches (pattern, pattern_percent, name))
{
/* Give a warning if the rule is meaningless. */
- makefile_error (filename, lineno,
+ error (flocp,
"target `%s' doesn't match the target pattern",
name);
this = 0;
@@ -1594,15 +1589,15 @@ record_files (filenames, pattern, pattern_percent, deps, cmds_started,
f = enter_file (name);
if (f->double_colon)
- makefile_fatal (filename, lineno,
+ fatal (flocp,
"target file `%s' has both : and :: entries",
f->name);
/* If CMDS == F->CMDS, this target was listed in this rule
more than once. Just give a warning since this is harmless. */
if (cmds != 0 && cmds == f->cmds)
- makefile_error
- (filename, lineno,
+ error
+ (flocp,
"target `%s' given more than once in the same rule.",
f->name);
@@ -1611,10 +1606,10 @@ record_files (filenames, pattern, pattern_percent, deps, cmds_started,
whose commands were preinitialized. */
else if (cmds != 0 && f->cmds != 0 && f->is_target)
{
- makefile_error (cmds->filename, cmds->lineno,
+ error (&cmds->fileinfo,
"warning: overriding commands for target `%s'",
f->name);
- makefile_error (f->cmds->filename, f->cmds->lineno,
+ error (&f->cmds->fileinfo,
"warning: ignoring old commands for target `%s'",
f->name);
}
@@ -1696,7 +1691,7 @@ record_files (filenames, pattern, pattern_percent, deps, cmds_started,
/* Check for both : and :: rules. Check is_target so
we don't lose on default suffix rules or makefiles. */
if (f != 0 && f->is_target && !f->double_colon)
- makefile_fatal (filename, lineno,
+ fatal (flocp,
"target file `%s' has both : and :: entries",
f->name);
f = enter_file (name);
@@ -2089,12 +2084,11 @@ parse_file_seq (stringp, stopchar, size, strip)
Return the number of actual lines read (> 1 if hacked continuation lines).
*/
-static unsigned int
-readline (linebuffer, stream, filename, lineno)
+static unsigned long
+readline (linebuffer, stream, flocp)
struct linebuffer *linebuffer;
FILE *stream;
- char *filename;
- unsigned int lineno;
+ const struct floc *flocp;
{
char *buffer = linebuffer->buffer;
register char *p = linebuffer->buffer;
@@ -2116,8 +2110,7 @@ readline (linebuffer, stream, filename, lineno)
lossage strikes again! (xmkmf puts NULs in its makefiles.)
There is nothing really to be done; we synthesize a newline so
the following line doesn't appear to be part of this line. */
- makefile_error (filename, lineno,
- "warning: NUL character seen; rest of line ignored");
+ error (flocp, "warning: NUL character seen; rest of line ignored");
p[0] = '\n';
len = 1;
}
@@ -2177,7 +2170,7 @@ readline (linebuffer, stream, filename, lineno)
}
if (ferror (stream))
- pfatal_with_name (filename);
+ pfatal_with_name (flocp->filenm);
return nlines;
}
@@ -2296,8 +2289,12 @@ get_next_mword (buffer, delim, startp, length)
case ':':
#if defined(__MSDOS__) || defined(WINDOWS32)
- /* A word CAN include a colon in its drive spec. */
- if (!(p - beg == 2 && (*p == '/' || *p == '\\') && isalpha (*beg)))
+ /* A word CAN include a colon in its drive spec. The drive
+ spec is allowed either at the beginning of a word, or as part
+ of the archive member name, like in "libfoo.a(d:/foo/bar.o)". */
+ if (!(p - beg >= 2 &&
+ (*p == '/' || *p == '\\') && isalpha (p[-2]) &&
+ (p - beg == 2 || p[-3] == '(')))
#endif
goto done_word;
@@ -2657,7 +2654,7 @@ multi_glob (chain, size)
}
case GLOB_NOSPACE:
- fatal ("virtual memory exhausted");
+ fatal (NILF, "virtual memory exhausted");
break;
default:
diff --git a/remake.c b/remake.c
index 9c459a4..d312321 100644
--- a/remake.c
+++ b/remake.c
@@ -48,13 +48,11 @@ unsigned int commands_started = 0;
static int update_file PARAMS ((struct file *file, unsigned int depth));
static int update_file_1 PARAMS ((struct file *file, unsigned int depth));
-static int check_dep PARAMS ((struct file *file, unsigned int depth, time_t this_mtime, int *must_make_ptr));
+static int check_dep PARAMS ((struct file *file, unsigned int depth, FILE_TIMESTAMP this_mtime, int *must_make_ptr));
static int touch_file PARAMS ((struct file *file));
static void remake_file PARAMS ((struct file *file));
-static time_t name_mtime PARAMS ((char *name));
-static int library_search PARAMS ((char **lib, time_t *mtime_ptr));
-
-extern time_t f_mtime PARAMS ((struct file *file, int search));
+static FILE_TIMESTAMP name_mtime PARAMS ((char *name));
+static int library_search PARAMS ((char **lib, FILE_TIMESTAMP *mtime_ptr));
/* Remake all the goals in the `struct dep' chain GOALS. Return -1 if nothing
@@ -128,7 +126,7 @@ update_goal_chain (goals, makefiles)
{
unsigned int ocommands_started;
int x;
- time_t mtime = MTIME (file);
+ FILE_TIMESTAMP mtime = MTIME (file);
check_renamed (file);
if (makefiles)
{
@@ -268,9 +266,9 @@ no_rule_error(file)
if (!file->dontcare)
{
if (file->parent == 0)
- error (msg_noparent, "*** ", file->name, ".");
+ error (NILF, msg_noparent, "*** ", file->name, ".");
else
- error (msg_parent, "*** ",
+ error (NILF, msg_parent, "*** ",
file->name, file->parent->name, ".");
file->shownerror = 1;
}
@@ -279,9 +277,9 @@ no_rule_error(file)
else
{
if (file->parent == 0)
- fatal (msg_noparent, "", file->name, "");
+ fatal (NILF, msg_noparent, "", file->name, "");
else
- fatal (msg_parent, "", file->name, file->parent->name, "");
+ fatal (NILF, msg_parent, "", file->name, file->parent->name, "");
}
}
@@ -341,7 +339,7 @@ update_file_1 (file, depth)
struct file *file;
unsigned int depth;
{
- register time_t this_mtime;
+ register FILE_TIMESTAMP this_mtime;
int noexist, must_make, deps_changed;
int dep_status = 0;
register struct dep *d, *lastd;
@@ -396,7 +394,7 @@ update_file_1 (file, depth)
this_mtime = file_mtime (file);
check_renamed (file);
- noexist = this_mtime == (time_t) -1;
+ noexist = this_mtime == (FILE_TIMESTAMP) -1;
if (noexist)
DEBUGPR ("File `%s' does not exist.\n");
@@ -427,7 +425,7 @@ update_file_1 (file, depth)
d = file->deps;
while (d != 0)
{
- time_t mtime;
+ FILE_TIMESTAMP mtime;
check_renamed (d->file);
@@ -436,7 +434,7 @@ update_file_1 (file, depth)
if (d->file->updating)
{
- error ("Circular %s <- %s dependency dropped.",
+ error (NILF, "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
@@ -484,7 +482,7 @@ update_file_1 (file, depth)
for (d = file->deps; d != 0; d = d->next)
if (d->file->intermediate)
{
- time_t mtime = file_mtime (d->file);
+ FILE_TIMESTAMP mtime = file_mtime (d->file);
check_renamed (d->file);
d->file->parent = file;
dep_status |= update_file (d->file, depth);
@@ -537,7 +535,7 @@ update_file_1 (file, depth)
if (depth == 0 && keep_going_flag
&& !just_print_flag && !question_flag)
- error ("Target `%s' not remade because of errors.", file->name);
+ error (NILF, "Target `%s' not remade because of errors.", file->name);
return dep_status;
}
@@ -559,13 +557,13 @@ update_file_1 (file, depth)
deps_changed = 0;
for (d = file->deps; d != 0; d = d->next)
{
- time_t d_mtime = file_mtime (d->file);
+ FILE_TIMESTAMP d_mtime = file_mtime (d->file);
check_renamed (d->file);
#if 1 /* %%% In version 4, remove this code completely to
implement not remaking deps if their deps are newer
than their parents. */
- if (d_mtime == (time_t) -1 && !d->file->intermediate)
+ if (d_mtime == (FILE_TIMESTAMP) -1 && !d->file->intermediate)
/* We must remake if this dep does not
exist and is not intermediate. */
must_make = 1;
@@ -581,7 +579,7 @@ update_file_1 (file, depth)
if (debug_flag && !noexist)
{
print_spaces (depth);
- if (d_mtime == (time_t) -1)
+ if (d_mtime == (FILE_TIMESTAMP) -1)
printf ("Dependency `%s' does not exist.\n", dep_name (d));
else
printf ("Dependency `%s' is %s than dependent `%s'.\n",
@@ -771,7 +769,7 @@ static int
check_dep (file, depth, this_mtime, must_make_ptr)
struct file *file;
unsigned int depth;
- time_t this_mtime;
+ FILE_TIMESTAMP this_mtime;
int *must_make_ptr;
{
register struct dep *d;
@@ -784,21 +782,20 @@ check_dep (file, depth, this_mtime, must_make_ptr)
/* If this is a non-intermediate file, update it and record
whether it is newer than THIS_MTIME. */
{
- time_t mtime;
+ FILE_TIMESTAMP mtime;
dep_status = update_file (file, depth);
check_renamed (file);
mtime = file_mtime (file);
check_renamed (file);
- if (mtime == (time_t) -1 || mtime > this_mtime)
+ if (mtime == (FILE_TIMESTAMP) -1 || mtime > this_mtime)
*must_make_ptr = 1;
}
else
{
/* FILE is an intermediate file. */
- time_t mtime;
+ FILE_TIMESTAMP mtime;
- if (!file->phony && file->cmds == 0 && !file->tried_implicit
- && file->secondary)
+ if (!file->phony && file->cmds == 0 && !file->tried_implicit)
{
if (try_implicit_rule (file, depth))
DEBUGPR ("Found an implicit rule for `%s'.\n");
@@ -806,7 +803,7 @@ check_dep (file, depth, this_mtime, must_make_ptr)
DEBUGPR ("No implicit rule found for `%s'.\n");
file->tried_implicit = 1;
}
- if (file->cmds == 0 && !file->is_target && file->secondary
+ if (file->cmds == 0 && !file->is_target
&& default_file != 0 && default_file->cmds != 0)
{
DEBUGPR ("Using default commands for `%s'.\n");
@@ -818,7 +815,7 @@ check_dep (file, depth, this_mtime, must_make_ptr)
check_renamed (file);
mtime = file_mtime (file);
check_renamed (file);
- if (mtime != (time_t) -1 && mtime > this_mtime)
+ if (mtime != (FILE_TIMESTAMP) -1 && mtime > this_mtime)
*must_make_ptr = 1;
/* Otherwise, update all non-intermediate files we depend on,
if necessary, and see whether any of them is more
@@ -833,7 +830,7 @@ check_dep (file, depth, this_mtime, must_make_ptr)
{
if (d->file->updating)
{
- error ("Circular %s <- %s dependency dropped.",
+ error (NILF, "Circular %s <- %s dependency dropped.",
file->name, d->file->name);
if (lastd == 0)
{
@@ -858,7 +855,7 @@ check_dep (file, depth, this_mtime, must_make_ptr)
if (d->file->command_state == cs_running
|| d->file->command_state == cs_deps_running)
- /* Record that some of FILE's dependencies are still being made.
+ /* Record that some of FILE's deps are still being made.
This tells the upper levels to wait on processing it until
the commands are finished. */
set_command_state (file, cs_deps_running);
@@ -978,12 +975,12 @@ remake_file (file)
the library's actual name (/lib/libLIBNAME.a, etc.) is substituted into
FILE. */
-time_t
+FILE_TIMESTAMP
f_mtime (file, search)
register struct file *file;
int search;
{
- time_t mtime;
+ FILE_TIMESTAMP mtime;
/* File's mtime is not known; must get it from the system. */
@@ -1049,9 +1046,9 @@ f_mtime (file, search)
free (arname);
free (memname);
- if (mtime == (time_t) -1)
+ if (mtime == (FILE_TIMESTAMP) -1)
/* The archive doesn't exist, so it's members don't exist either. */
- return (time_t) -1;
+ return (FILE_TIMESTAMP) -1;
mtime = ar_member_date (file->hname);
}
@@ -1060,7 +1057,7 @@ f_mtime (file, search)
{
mtime = name_mtime (file->name);
- if (mtime == (time_t) -1 && search && !file->ignore_vpath)
+ if (mtime == (FILE_TIMESTAMP) -1 && search && !file->ignore_vpath)
{
/* If name_mtime failed, search VPATH. */
char *name = file->name;
@@ -1098,16 +1095,15 @@ f_mtime (file, search)
We only need to do this once, for now. */
- static time_t now = 0;
+ static FILE_TIMESTAMP now = 0;
if (!clock_skew_detected
- && mtime != (time_t)-1 && mtime > now
+ && mtime != (FILE_TIMESTAMP)-1 && mtime > now
&& !file->updated)
{
/* This file's time appears to be in the future.
Update our concept of the present, and compare again. */
- extern time_t time ();
- time (&now);
+ now = file_timestamp_now ();
#ifdef WINDOWS32
/*
@@ -1126,8 +1122,13 @@ f_mtime (file, search)
#endif
#endif
{
- error("*** Warning: File `%s' has modification time in the future (%ld > %ld)",
- file->name, mtime, now);
+ char mtimebuf[FILE_TIMESTAMP_PRINT_LEN_BOUND + 1];
+ char nowbuf[FILE_TIMESTAMP_PRINT_LEN_BOUND + 1];
+
+ file_timestamp_sprintf (mtimebuf, mtime);
+ file_timestamp_sprintf (nowbuf, now);
+ error (NILF, "*** Warning: File `%s' has modification time in the future (%s > %s)",
+ file->name, mtimebuf, nowbuf);
clock_skew_detected = 1;
}
}
@@ -1148,16 +1149,16 @@ f_mtime (file, search)
/* Return the mtime of the file or archive-member reference NAME. */
-static time_t
+static FILE_TIMESTAMP
name_mtime (name)
register char *name;
{
struct stat st;
if (stat (name, &st) < 0)
- return (time_t) -1;
+ return (FILE_TIMESTAMP) -1;
- return (time_t) st.st_mtime;
+ return FILE_TIMESTAMP_STAT_MODTIME (st);
}
@@ -1168,7 +1169,7 @@ name_mtime (name)
static int
library_search (lib, mtime_ptr)
char **lib;
- time_t *mtime_ptr;
+ FILE_TIMESTAMP *mtime_ptr;
{
static char *dirs[] =
{
@@ -1188,7 +1189,7 @@ library_search (lib, mtime_ptr)
};
char *libname = &(*lib)[2]; /* Name without the `-l'. */
- time_t mtime;
+ FILE_TIMESTAMP mtime;
/* Buffer to construct possible names in. */
char *buf = xmalloc (sizeof (LIBDIR) + 8 + strlen (libname) + 4 + 2 + 1);
@@ -1202,7 +1203,7 @@ library_search (lib, mtime_ptr)
sprintf (buf, "%s.lib", libname);
#endif
mtime = name_mtime (buf);
- if (mtime != (time_t) -1)
+ if (mtime != (FILE_TIMESTAMP) -1)
{
*lib = buf;
if (mtime_ptr != 0)
@@ -1235,7 +1236,7 @@ library_search (lib, mtime_ptr)
buf = (char *) xrealloc (djdir_len + 1);
sprintf (buf, "%s/lib/lib%s.a", djdir->value, libname);
mtime = name_mtime (buf);
- if (mtime != (time_t) -1)
+ if (mtime != (FILE_TIMESTAMP) -1)
{
*lib = buf;
if (mtime_ptr != 0)
@@ -1254,7 +1255,7 @@ library_search (lib, mtime_ptr)
sprintf (buf, "%s/%s.lib", *dp, libname);
#endif
mtime = name_mtime (buf);
- if (mtime != (time_t) -1)
+ if (mtime != (FILE_TIMESTAMP) -1)
{
*lib = buf;
if (mtime_ptr != 0)
diff --git a/remote-cstms.c b/remote-cstms.c
index e1d63a3..cf91816 100644
--- a/remote-cstms.c
+++ b/remote-cstms.c
@@ -157,7 +157,7 @@ start_remote_job (argv, envp, stdin_fd, is_remote, id_ptr, used_stdin)
retsock = Rpc_UdpCreate (True, 0);
if (retsock < 0)
{
- error ("exporting: Couldn't create return socket.");
+ error (NILF, "exporting: Couldn't create return socket.");
return 1;
}
@@ -202,7 +202,7 @@ start_remote_job (argv, envp, stdin_fd, is_remote, id_ptr, used_stdin)
{
(void) close (retsock);
(void) close (sock);
- error ("exporting to %s: %s",
+ error (NILF, "exporting to %s: %s",
host ? host->h_name : inet_ntoa (permit.addr),
Rpc_ErrorMessage (status));
return 1;
@@ -211,14 +211,14 @@ start_remote_job (argv, envp, stdin_fd, is_remote, id_ptr, used_stdin)
{
(void) close (retsock);
(void) close (sock);
- error ("exporting to %s: %s",
+ error (NILF, "exporting to %s: %s",
host ? host->h_name : inet_ntoa (permit.addr),
msg);
return 1;
}
else
{
- error ("*** exported to %s (id %u)",
+ error (NILF, "*** exported to %s (id %u)",
host ? host->h_name : inet_ntoa (permit.addr),
permit.id);
}
diff --git a/rule.c b/rule.c
index 6933631..eb4602f 100644
--- a/rule.c
+++ b/rule.c
@@ -416,8 +416,8 @@ install_pattern_rule (p, terminal)
{
r->terminal = terminal;
r->cmds = (struct commands *) xmalloc (sizeof (struct commands));
- r->cmds->filename = 0;
- r->cmds->lineno = 0;
+ r->cmds->fileinfo.filenm = 0;
+ r->cmds->fileinfo.lineno = 0;
/* These will all be string literals, but we malloc space for them
anyway because somebody might want to free them later. */
r->cmds->commands = savestring (p->commands, strlen (p->commands));
@@ -664,7 +664,7 @@ print_rule_data_base ()
}
if (num_pattern_rules != rules)
- fatal ("BUG: num_pattern_rules wrong! %u != %u",
+ fatal (NILF, "BUG: num_pattern_rules wrong! %u != %u",
num_pattern_rules, rules);
puts ("\n# Pattern-specific variable values");
diff --git a/rule.h b/rule.h
index 4effeb0..f57c7e0 100644
--- a/rule.h
+++ b/rule.h
@@ -62,3 +62,10 @@ 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));
+extern void count_implicit_rule_limits PARAMS ((void));
+extern void convert_to_pattern PARAMS ((void));
+extern void create_pattern_rule PARAMS ((char **targets,
+ char **target_percents, int terminal,
+ struct dep *deps,
+ struct commands *commands,
+ int override));
diff --git a/variable.c b/variable.c
index 3155a92..85987db 100644
--- a/variable.c
+++ b/variable.c
@@ -676,9 +676,8 @@ target_environment (file)
returned. */
struct variable *
-try_variable_definition (filename, lineno, line, origin)
- char *filename;
- unsigned int lineno;
+try_variable_definition (flocp, line, origin)
+ const struct floc *flocp;
char *line;
enum variable_origin origin;
{
@@ -766,7 +765,7 @@ try_variable_definition (filename, lineno, line, origin)
expanded_name = allocated_variable_expand (name);
if (expanded_name[0] == '\0')
- makefile_fatal (filename, lineno, "empty variable name");
+ fatal (flocp, "empty variable name");
/* Calculate the variable's new value in VALUE. */
diff --git a/variable.h b/variable.h
index 4289c14..b1d0daf 100644
--- a/variable.h
+++ b/variable.h
@@ -102,7 +102,7 @@ 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 *try_variable_definition PARAMS ((const struct floc *flocp, 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,
diff --git a/vpath.c b/vpath.c
index ab88ac3..d332031 100644
--- a/vpath.c
+++ b/vpath.c
@@ -48,7 +48,7 @@ static struct vpath *general_vpath;
static struct vpath *gpaths;
-static int selective_vpath_search PARAMS ((struct vpath *path, char **file, time_t *mtime_ptr));
+static int selective_vpath_search PARAMS ((struct vpath *path, char **file, FILE_TIMESTAMP *mtime_ptr));
/* Reverse the chain of selective VPATH lists so they
will be searched in the order given in the makefiles
@@ -338,7 +338,7 @@ gpath_search (file, len)
int
vpath_search (file, mtime_ptr)
char **file;
- time_t *mtime_ptr;
+ FILE_TIMESTAMP *mtime_ptr;
{
register struct vpath *v;
@@ -376,7 +376,7 @@ static int
selective_vpath_search (path, file, mtime_ptr)
struct vpath *path;
char **file;
- time_t *mtime_ptr;
+ FILE_TIMESTAMP *mtime_ptr;
{
int not_target;
char *name, *n;
@@ -524,7 +524,9 @@ selective_vpath_search (path, file, mtime_ptr)
/* Store the modtime into *MTIME_PTR for the caller.
If we have had no need to stat the file here,
we record a zero modtime to indicate this. */
- *mtime_ptr = exists_in_cache ? st.st_mtime : (time_t) 0;
+ *mtime_ptr = (exists_in_cache
+ ? FILE_TIMESTAMP_STAT_MODTIME (st)
+ : (FILE_TIMESTAMP) 0);
free (name);
return 1;
diff --git a/w32/subproc/NMakefile b/w32/subproc/NMakefile
index f187827..66afe65 100644
--- a/w32/subproc/NMakefile
+++ b/w32/subproc/NMakefile
@@ -1,60 +1,60 @@
-# NOTE: If you have no `make' program at all to process this makefile, run
-# `build.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 (subproc library)
-#
-LIB = lib
-CC = cl
-
-OUTDIR=.
-MAKEFILE=NMakefile
-
-CFLAGS_any = /nologo /MT /W3 /GX /Z7 /YX /D WIN32 /D WINDOWS32 /D _WINDOWS -I. -I../include -I../..
-CFLAGS_debug = $(CFLAGS_any) /Od /D _DEBUG /FR.\WinDebug\ /Fp.\WinDebug\subproc.pch /Fo.\WinDebug/
-CFLAGS_release = $(CFLAGS_any) /O2 /FR.\WinRel\ /Fp.\WinRel\subproc.pch /Fo.\WinRel/
-
-all: Release Debug
-
-Release:
- $(MAKE) /f $(MAKEFILE) OUTDIR=WinRel CFLAGS="$(CFLAGS_release)" WinRel/subproc.lib
-Debug:
- $(MAKE) /f $(MAKEFILE) OUTDIR=WinDebug CFLAGS="$(CFLAGS_debug)" WinDebug/subproc.lib
-
-clean:
- rmdir /s /q WinRel WinDebug
- erase *.pdb
-
-$(OUTDIR):
- if not exist .\$@\nul mkdir .\$@
-
-OBJS = $(OUTDIR)/misc.obj $(OUTDIR)/w32err.obj $(OUTDIR)/sub_proc.obj
-
-$(OUTDIR)/subproc.lib: $(OUTDIR) $(OBJS)
- $(LIB) -out:$@ @<<
- $(OBJS)
-<<
-
-.c{$(OUTDIR)}.obj:
- $(CC) $(CFLAGS) /c $<
-
-$(OUTDIR)/misc.obj: misc.c proc.h
-$(OUTDIR)/sub_proc.obj: sub_proc.c ../include/sub_proc.h ../include/w32err.h proc.h
-$(OUTDIR)/w32err.obj: w32err.c ../include/w32err.h
+# NOTE: If you have no `make' program at all to process this makefile, run
+# `build.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 (subproc library)
+#
+LIB = lib
+CC = cl
+
+OUTDIR=.
+MAKEFILE=NMakefile
+
+CFLAGS_any = /nologo /MT /W3 /GX /Z7 /YX /D WIN32 /D WINDOWS32 /D _WINDOWS -I. -I../include -I../../
+CFLAGS_debug = $(CFLAGS_any) /Od /D _DEBUG /FR.\WinDebug\ /Fp.\WinDebug\subproc.pch /Fo.\WinDebug/
+CFLAGS_release = $(CFLAGS_any) /O2 /FR.\WinRel\ /Fp.\WinRel\subproc.pch /Fo.\WinRel/
+
+all: Release Debug
+
+Release:
+ $(MAKE) /f $(MAKEFILE) OUTDIR=WinRel CFLAGS="$(CFLAGS_release)" WinRel/subproc.lib
+Debug:
+ $(MAKE) /f $(MAKEFILE) OUTDIR=WinDebug CFLAGS="$(CFLAGS_debug)" WinDebug/subproc.lib
+
+clean:
+ rmdir /s /q WinRel WinDebug
+ erase *.pdb
+
+$(OUTDIR):
+ if not exist .\$@\nul mkdir .\$@
+
+OBJS = $(OUTDIR)/misc.obj $(OUTDIR)/w32err.obj $(OUTDIR)/sub_proc.obj
+
+$(OUTDIR)/subproc.lib: $(OUTDIR) $(OBJS)
+ $(LIB) -out:$@ @<<
+ $(OBJS)
+<<
+
+.c{$(OUTDIR)}.obj:
+ $(CC) $(CFLAGS) /c $<
+
+$(OUTDIR)/misc.obj: misc.c proc.h
+$(OUTDIR)/sub_proc.obj: sub_proc.c ../include/sub_proc.h ../include/w32err.h proc.h
+$(OUTDIR)/w32err.obj: w32err.c ../include/w32err.h
diff --git a/w32/subproc/sub_proc.c b/w32/subproc/sub_proc.c
index 281c81c..300bb7b 100644
--- a/w32/subproc/sub_proc.c
+++ b/w32/subproc/sub_proc.c
@@ -1,1186 +1,1190 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <process.h> /* for msvc _beginthreadex, _endthreadex */
-#include <windows.h>
-
-#include "sub_proc.h"
-#include "proc.h"
-#include "w32err.h"
-#include "config.h"
-
-static char *make_command_line( char *shell_name, char *exec_path, char **argv);
-
-typedef struct sub_process_t {
- int sv_stdin[2];
- int sv_stdout[2];
- int sv_stderr[2];
- int using_pipes;
- char *inp;
- DWORD incnt;
- char * volatile outp;
- volatile DWORD outcnt;
- char * volatile errp;
- volatile DWORD errcnt;
- int pid;
- int exit_code;
- int signal;
- long last_err;
- long lerrno;
-} sub_process;
-
-/* keep track of children so we can implement a waitpid-like routine */
-static sub_process *proc_array[256];
-static int proc_index = 0;
-static int fake_exits_pending = 0;
-
-/*
- * When a process has been waited for, adjust the wait state
- * array so that we don't wait for it again
- */
-static void
-process_adjust_wait_state(sub_process* pproc)
-{
- int i;
-
- if (!proc_index)
- return;
-
- for (i = 0; i < proc_index; i++)
- if (proc_array[i]->pid == pproc->pid)
- break;
-
- if (i < proc_index) {
- proc_index--;
- if (i != proc_index)
- memmove(&proc_array[i], &proc_array[i+1],
- (proc_index-i) * sizeof(sub_process*));
- proc_array[proc_index] = NULL;
- }
-}
-
-/*
- * Waits for any of the registered child processes to finish.
- */
-static sub_process *
-process_wait_for_any_private(void)
-{
- HANDLE handles[256];
- DWORD retval, which;
- int i;
-
- if (!proc_index)
- return NULL;
-
- /* build array of handles to wait for */
- for (i = 0; i < proc_index; i++) {
- handles[i] = (HANDLE) proc_array[i]->pid;
-
- if (fake_exits_pending && proc_array[i]->exit_code)
- break;
- }
-
- /* wait for someone to exit */
- if (!fake_exits_pending) {
- retval = WaitForMultipleObjects(proc_index, handles, FALSE, INFINITE);
- which = retval - WAIT_OBJECT_0;
- } else {
- fake_exits_pending--;
- retval = !WAIT_FAILED;
- which = i;
- }
-
- /* return pointer to process */
- if (retval != WAIT_FAILED) {
- sub_process* pproc = proc_array[which];
- process_adjust_wait_state(pproc);
- return pproc;
- } else
- return NULL;
-}
-
-/*
- * Terminate a process.
- */
-BOOL
-process_kill(HANDLE proc, int signal)
-{
- sub_process* pproc = (sub_process*) proc;
- pproc->signal = signal;
- return (TerminateProcess((HANDLE) pproc->pid, signal));
-}
-
-/*
- * Use this function to register processes you wish to wait for by
- * calling process_file_io(NULL) or process_wait_any(). This must be done
- * because it is possible for callers of this library to reuse the same
- * handle for multiple processes launches :-(
- */
-void
-process_register(HANDLE proc)
-{
- proc_array[proc_index++] = (sub_process *) proc;
-}
-
-/*
- * Public function which works kind of like waitpid(). Wait for any
- * of the children to die and return results. To call this function,
- * you must do 1 of things:
- *
- * x = process_easy(...);
- *
- * or
- *
- * x = process_init_fd();
- * process_register(x);
- *
- * or
- *
- * x = process_init();
- * process_register(x);
- *
- * You must NOT then call process_pipe_io() because this function is
- * not capable of handling automatic notification of any child
- * death.
- */
-
-HANDLE
-process_wait_for_any(void)
-{
- sub_process* pproc = process_wait_for_any_private();
-
- if (!pproc)
- return NULL;
- else {
- /*
- * Ouch! can't tell caller if this fails directly. Caller
- * will have to use process_last_err()
- */
- (void) process_file_io(pproc);
- return ((HANDLE) pproc);
- }
-}
-
-long
-process_errno(HANDLE proc)
-{
- return (((sub_process *)proc)->lerrno);
-}
-
-long
-process_signal(HANDLE proc)
-{
- return (((sub_process *)proc)->signal);
-}
-
- long
-process_last_err(HANDLE proc)
-{
- return (((sub_process *)proc)->last_err);
-}
-
- long
-process_exit_code(HANDLE proc)
-{
- return (((sub_process *)proc)->exit_code);
-}
-
- char *
-process_outbuf(HANDLE proc)
-{
- return (((sub_process *)proc)->outp);
-}
-
- char *
-process_errbuf(HANDLE proc)
-{
- return (((sub_process *)proc)->errp);
-}
-
- int
-process_outcnt(HANDLE proc)
-{
- return (((sub_process *)proc)->outcnt);
-}
-
- int
-process_errcnt(HANDLE proc)
-{
- return (((sub_process *)proc)->errcnt);
-}
-
- void
-process_pipes(HANDLE proc, int pipes[3])
-{
- pipes[0] = ((sub_process *)proc)->sv_stdin[0];
- pipes[1] = ((sub_process *)proc)->sv_stdout[0];
- pipes[2] = ((sub_process *)proc)->sv_stderr[0];
- return;
-}
-
-
- HANDLE
-process_init()
-{
- sub_process *pproc;
- /*
- * open file descriptors for attaching stdin/stdout/sterr
- */
- HANDLE stdin_pipes[2];
- HANDLE stdout_pipes[2];
- HANDLE stderr_pipes[2];
- SECURITY_ATTRIBUTES inherit;
- BYTE sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
-
- pproc = malloc(sizeof(*pproc));
- memset(pproc, 0, sizeof(*pproc));
-
- /* We can't use NULL for lpSecurityDescriptor because that
- uses the default security descriptor of the calling process.
- Instead we use a security descriptor with no DACL. This
- allows nonrestricted access to the associated objects. */
-
- if (!InitializeSecurityDescriptor((PSECURITY_DESCRIPTOR)(&sd),
- SECURITY_DESCRIPTOR_REVISION)) {
- pproc->last_err = GetLastError();
- pproc->lerrno = E_SCALL;
- return((HANDLE)pproc);
- }
-
- inherit.nLength = sizeof(inherit);
- inherit.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR)(&sd);
- inherit.bInheritHandle = TRUE;
-
- // By convention, parent gets pipe[0], and child gets pipe[1]
- // This means the READ side of stdin pipe goes into pipe[1]
- // and the WRITE side of the stdout and stderr pipes go into pipe[1]
- if (CreatePipe( &stdin_pipes[1], &stdin_pipes[0], &inherit, 0) == FALSE ||
- CreatePipe( &stdout_pipes[0], &stdout_pipes[1], &inherit, 0) == FALSE ||
- CreatePipe( &stderr_pipes[0], &stderr_pipes[1], &inherit, 0) == FALSE) {
-
- pproc->last_err = GetLastError();
- pproc->lerrno = E_SCALL;
- return((HANDLE)pproc);
- }
-
- //
- // Mark the parent sides of the pipes as non-inheritable
- //
- if (SetHandleInformation(stdin_pipes[0],
- HANDLE_FLAG_INHERIT, 0) == FALSE ||
- SetHandleInformation(stdout_pipes[0],
- HANDLE_FLAG_INHERIT, 0) == FALSE ||
- SetHandleInformation(stderr_pipes[0],
- HANDLE_FLAG_INHERIT, 0) == FALSE) {
-
- pproc->last_err = GetLastError();
- pproc->lerrno = E_SCALL;
- return((HANDLE)pproc);
- }
- pproc->sv_stdin[0] = (int) stdin_pipes[0];
- pproc->sv_stdin[1] = (int) stdin_pipes[1];
- pproc->sv_stdout[0] = (int) stdout_pipes[0];
- pproc->sv_stdout[1] = (int) stdout_pipes[1];
- pproc->sv_stderr[0] = (int) stderr_pipes[0];
- pproc->sv_stderr[1] = (int) stderr_pipes[1];
-
- pproc->using_pipes = 1;
-
- pproc->lerrno = 0;
-
- return((HANDLE)pproc);
-}
-
-
- HANDLE
-process_init_fd(HANDLE stdinh, HANDLE stdouth, HANDLE stderrh)
-{
- sub_process *pproc;
-
- pproc = malloc(sizeof(*pproc));
- memset(pproc, 0, sizeof(*pproc));
-
- /*
- * Just pass the provided file handles to the 'child side' of the
- * pipe, bypassing pipes altogether.
- */
- pproc->sv_stdin[1] = (int) stdinh;
- pproc->sv_stdout[1] = (int) stdouth;
- pproc->sv_stderr[1] = (int) stderrh;
-
- pproc->last_err = pproc->lerrno = 0;
-
- return((HANDLE)pproc);
-}
-
-
-static HANDLE
-find_file(char *exec_path, LPOFSTRUCT file_info)
-{
- HANDLE exec_handle;
- char *fname;
- char *ext;
-
- fname = malloc(strlen(exec_path) + 5);
- strcpy(fname, exec_path);
- ext = fname + strlen(fname);
-
- strcpy(ext, ".exe");
- if ((exec_handle = (HANDLE)OpenFile(fname, file_info,
- OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) {
- free(fname);
- return(exec_handle);
- }
-
- strcpy(ext, ".cmd");
- if ((exec_handle = (HANDLE)OpenFile(fname, file_info,
- OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) {
- free(fname);
- return(exec_handle);
- }
-
- strcpy(ext, ".bat");
- if ((exec_handle = (HANDLE)OpenFile(fname, file_info,
- OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) {
- free(fname);
- return(exec_handle);
- }
-
- /* should .com come before this case? */
- if ((exec_handle = (HANDLE)OpenFile(exec_path, file_info,
- OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) {
- free(fname);
- return(exec_handle);
- }
-
- strcpy(ext, ".com");
- if ((exec_handle = (HANDLE)OpenFile(fname, file_info,
- OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) {
- free(fname);
- return(exec_handle);
- }
-
- free(fname);
- return(exec_handle);
-}
-
-
-/*
- * Description: Create the child process to be helped
- *
- * Returns:
- *
- * Notes/Dependencies:
- */
-long
-process_begin(
- HANDLE proc,
- char **argv,
- char **envp,
- char *exec_path,
- char *as_user)
-{
- sub_process *pproc = (sub_process *)proc;
- char *shell_name = 0;
- int file_not_found=0;
- HANDLE exec_handle;
- char buf[256];
- DWORD bytes_returned;
- DWORD flags;
- char *command_line;
- STARTUPINFO startInfo;
- PROCESS_INFORMATION procInfo;
- char *envblk=NULL;
- OFSTRUCT file_info;
-
-
- /*
- * Shell script detection... if the exec_path starts with #! then
- * we want to exec shell-script-name exec-path, not just exec-path
- * NT doesn't recognize #!/bin/sh or #!/etc/Tivoli/bin/perl. We do not
- * hard-code the path to the shell or perl or whatever: Instead, we
- * assume it's in the path somewhere (generally, the NT tools
- * bin directory)
- * We use OpenFile here because it is capable of searching the Path.
- */
-
- exec_handle = find_file(exec_path, &file_info);
-
- /*
- * If we couldn't open the file, just assume that Windows32 will be able
- * to find and execute it.
- */
- if (exec_handle == (HANDLE)HFILE_ERROR) {
- file_not_found++;
- }
- else {
- /* Attempt to read the first line of the file */
- if (ReadFile( exec_handle,
- buf, sizeof(buf) - 1, /* leave room for trailing NULL */
- &bytes_returned, 0) == FALSE || bytes_returned < 2) {
-
- pproc->last_err = GetLastError();
- pproc->lerrno = E_IO;
- CloseHandle(exec_handle);
- return(-1);
- }
- if (buf[0] == '#' && buf[1] == '!') {
- /*
- * This is a shell script... Change the command line from
- * exec_path args to shell_name exec_path args
- */
- char *p;
-
- /* Make sure buf is NULL terminated */
- buf[bytes_returned] = 0;
- /*
- * Depending on the file system type, etc. the first line
- * of the shell script may end with newline or newline-carriage-return
- * Whatever it ends with, cut it off.
- */
- p= strchr(buf, '\n');
- if (p)
- *p = 0;
- p = strchr(buf, '\r');
- if (p)
- *p = 0;
-
- /*
- * Find base name of shell
- */
- shell_name = strrchr( buf, '/');
- if (shell_name) {
- shell_name++;
- } else {
- shell_name = &buf[2];/* skipping "#!" */
- }
-
- }
- CloseHandle(exec_handle);
- }
-
- flags = 0;
-
- if (file_not_found)
- command_line = make_command_line( shell_name, exec_path, argv);
- else
- command_line = make_command_line( shell_name, file_info.szPathName,
- argv);
-
- if ( command_line == NULL ) {
- pproc->last_err = 0;
- pproc->lerrno = E_NO_MEM;
- return(-1);
- }
-
- if (envp) {
- if (arr2envblk(envp, &envblk) ==FALSE) {
- pproc->last_err = 0;
- pproc->lerrno = E_NO_MEM;
- free( command_line );
- return(-1);
- }
- }
-
- if ((shell_name) || (file_not_found)) {
- exec_path = 0; /* Search for the program in %Path% */
- } else {
- exec_path = file_info.szPathName;
- }
-
- /*
- * Set up inherited stdin, stdout, stderr for child
- */
- GetStartupInfo(&startInfo);
- startInfo.dwFlags = STARTF_USESTDHANDLES;
- startInfo.lpReserved = 0;
- startInfo.cbReserved2 = 0;
- startInfo.lpReserved2 = 0;
- startInfo.lpTitle = shell_name ? shell_name : exec_path;
- startInfo.hStdInput = (HANDLE)pproc->sv_stdin[1];
- startInfo.hStdOutput = (HANDLE)pproc->sv_stdout[1];
- startInfo.hStdError = (HANDLE)pproc->sv_stderr[1];
-
- if (as_user) {
- if (envblk) free(envblk);
- return -1;
- } else {
- if (CreateProcess(
- exec_path,
- command_line,
- NULL,
- 0, /* default security attributes for thread */
- TRUE, /* inherit handles (e.g. helper pipes, oserv socket) */
- flags,
- envblk,
- 0, /* default starting directory */
- &startInfo,
- &procInfo) == FALSE) {
-
- pproc->last_err = GetLastError();
- pproc->lerrno = E_FORK;
- fprintf(stderr, "process_begin: CreateProcess(%s, %s, ...) failed.\n", exec_path, command_line);
- if (envblk) free(envblk);
- free( command_line );
- return(-1);
- }
- }
-
- pproc->pid = (int)procInfo.hProcess;
- /* Close the thread handle -- we'll just watch the process */
- CloseHandle(procInfo.hThread);
-
- /* Close the halves of the pipes we don't need */
- if (pproc->sv_stdin) {
- CloseHandle((HANDLE)pproc->sv_stdin[1]);
- (HANDLE)pproc->sv_stdin[1] = 0;
- }
- if (pproc->sv_stdout) {
- CloseHandle((HANDLE)pproc->sv_stdout[1]);
- (HANDLE)pproc->sv_stdout[1] = 0;
- }
- if (pproc->sv_stderr) {
- CloseHandle((HANDLE)pproc->sv_stderr[1]);
- (HANDLE)pproc->sv_stderr[1] = 0;
- }
-
- free( command_line );
- if (envblk) free(envblk);
- pproc->lerrno=0;
- return 0;
-}
-
-
-
-static DWORD
-proc_stdin_thread(sub_process *pproc)
-{
- DWORD in_done;
- for (;;) {
- if (WriteFile( (HANDLE) pproc->sv_stdin[0], pproc->inp, pproc->incnt,
- &in_done, NULL) == FALSE)
- _endthreadex(0);
- // This if should never be true for anonymous pipes, but gives
- // us a chance to change I/O mechanisms later
- if (in_done < pproc->incnt) {
- pproc->incnt -= in_done;
- pproc->inp += in_done;
- } else {
- _endthreadex(0);
- }
- }
- return 0; // for compiler warnings only.. not reached
-}
-
-static DWORD
-proc_stdout_thread(sub_process *pproc)
-{
- DWORD bufsize = 1024;
- char c;
- DWORD nread;
- pproc->outp = malloc(bufsize);
- if (pproc->outp == NULL)
- _endthreadex(0);
- pproc->outcnt = 0;
-
- for (;;) {
- if (ReadFile( (HANDLE)pproc->sv_stdout[0], &c, 1, &nread, NULL)
- == FALSE) {
-/* map_windows32_error_to_string(GetLastError());*/
- _endthreadex(0);
- }
- if (nread == 0)
- _endthreadex(0);
- if (pproc->outcnt + nread > bufsize) {
- bufsize += nread + 512;
- pproc->outp = realloc(pproc->outp, bufsize);
- if (pproc->outp == NULL) {
- pproc->outcnt = 0;
- _endthreadex(0);
- }
- }
- pproc->outp[pproc->outcnt++] = c;
- }
- return 0;
-}
-
-static DWORD
-proc_stderr_thread(sub_process *pproc)
-{
- DWORD bufsize = 1024;
- char c;
- DWORD nread;
- pproc->errp = malloc(bufsize);
- if (pproc->errp == NULL)
- _endthreadex(0);
- pproc->errcnt = 0;
-
- for (;;) {
- if (ReadFile( (HANDLE)pproc->sv_stderr[0], &c, 1, &nread, NULL) == FALSE) {
- map_windows32_error_to_string(GetLastError());
- _endthreadex(0);
- }
- if (nread == 0)
- _endthreadex(0);
- if (pproc->errcnt + nread > bufsize) {
- bufsize += nread + 512;
- pproc->errp = realloc(pproc->errp, bufsize);
- if (pproc->errp == NULL) {
- pproc->errcnt = 0;
- _endthreadex(0);
- }
- }
- pproc->errp[pproc->errcnt++] = c;
- }
- return 0;
-}
-
-
-/*
- * Purpose: collects output from child process and returns results
- *
- * Description:
- *
- * Returns:
- *
- * Notes/Dependencies:
- */
- long
-process_pipe_io(
- HANDLE proc,
- char *stdin_data,
- int stdin_data_len)
-{
- sub_process *pproc = (sub_process *)proc;
- bool_t stdin_eof = FALSE, stdout_eof = FALSE, stderr_eof = FALSE;
- HANDLE childhand = (HANDLE) pproc->pid;
- HANDLE tStdin, tStdout, tStderr;
- DWORD dwStdin, dwStdout, dwStderr;
- HANDLE wait_list[4];
- DWORD wait_count;
- DWORD wait_return;
- HANDLE ready_hand;
- bool_t child_dead = FALSE;
-
-
- /*
- * Create stdin thread, if needed
- */
- pproc->inp = stdin_data;
- pproc->incnt = stdin_data_len;
- if (!pproc->inp) {
- stdin_eof = TRUE;
- CloseHandle((HANDLE)pproc->sv_stdin[0]);
- (HANDLE)pproc->sv_stdin[0] = 0;
- } else {
- tStdin = (HANDLE) _beginthreadex( 0, 1024,
- (unsigned (__stdcall *) (void *))proc_stdin_thread, pproc, 0,
- (unsigned int *) &dwStdin);
- if (tStdin == 0) {
- pproc->last_err = GetLastError();
- pproc->lerrno = E_SCALL;
- goto done;
- }
- }
-
- /*
- * Assume child will produce stdout and stderr
- */
- tStdout = (HANDLE) _beginthreadex( 0, 1024,
- (unsigned (__stdcall *) (void *))proc_stdout_thread, pproc, 0,
- (unsigned int *) &dwStdout);
- tStderr = (HANDLE) _beginthreadex( 0, 1024,
- (unsigned (__stdcall *) (void *))proc_stderr_thread, pproc, 0,
- (unsigned int *) &dwStderr);
-
- if (tStdout == 0 || tStderr == 0) {
-
- pproc->last_err = GetLastError();
- pproc->lerrno = E_SCALL;
- goto done;
- }
-
-
- /*
- * Wait for all I/O to finish and for the child process to exit
- */
-
- while (!stdin_eof || !stdout_eof || !stderr_eof || !child_dead) {
- wait_count = 0;
- if (!stdin_eof) {
- wait_list[wait_count++] = tStdin;
- }
- if (!stdout_eof) {
- wait_list[wait_count++] = tStdout;
- }
- if (!stderr_eof) {
- wait_list[wait_count++] = tStderr;
- }
- if (!child_dead) {
- wait_list[wait_count++] = childhand;
- }
-
- wait_return = WaitForMultipleObjects(wait_count, wait_list,
- FALSE, /* don't wait for all: one ready will do */
- child_dead? 1000 :INFINITE); /* after the child dies, subthreads have
- one second to collect all remaining output */
-
- if (wait_return == WAIT_FAILED) {
-/* map_windows32_error_to_string(GetLastError());*/
- pproc->last_err = GetLastError();
- pproc->lerrno = E_SCALL;
- goto done;
- }
-
- ready_hand = wait_list[wait_return - WAIT_OBJECT_0];
-
- if (ready_hand == tStdin) {
- CloseHandle((HANDLE)pproc->sv_stdin[0]);
- (HANDLE)pproc->sv_stdin[0] = 0;
- CloseHandle(tStdin);
- tStdin = 0;
- stdin_eof = TRUE;
-
- } else if (ready_hand == tStdout) {
-
- CloseHandle((HANDLE)pproc->sv_stdout[0]);
- (HANDLE)pproc->sv_stdout[0] = 0;
- CloseHandle(tStdout);
- tStdout = 0;
- stdout_eof = TRUE;
-
- } else if (ready_hand == tStderr) {
-
- CloseHandle((HANDLE)pproc->sv_stderr[0]);
- (HANDLE)pproc->sv_stderr[0] = 0;
- CloseHandle(tStderr);
- tStderr = 0;
- stderr_eof = TRUE;
-
- } else if (ready_hand == childhand) {
-
- if (GetExitCodeProcess(childhand, &pproc->exit_code) == FALSE) {
- pproc->last_err = GetLastError();
- pproc->lerrno = E_SCALL;
- goto done;
- }
- child_dead = TRUE;
-
- } else {
-
- /* ?? Got back a handle we didn't query ?? */
- pproc->last_err = 0;
- pproc->lerrno = E_FAIL;
- goto done;
- }
- }
-
- done:
- if (tStdin != 0)
- CloseHandle(tStdin);
- if (tStdout != 0)
- CloseHandle(tStdout);
- if (tStderr != 0)
- CloseHandle(tStderr);
-
- if (pproc->lerrno)
- return(-1);
- else
- return(0);
-
-}
-
-/*
- * Purpose: collects output from child process and returns results
- *
- * Description:
- *
- * Returns:
- *
- * Notes/Dependencies:
- */
- long
-process_file_io(
- HANDLE proc)
-{
- sub_process *pproc;
- HANDLE childhand;
- DWORD wait_return;
-
- if (proc == NULL)
- pproc = process_wait_for_any_private();
- else
- pproc = (sub_process *)proc;
-
- /* some sort of internal error */
- if (!pproc)
- return -1;
-
- childhand = (HANDLE) pproc->pid;
-
- /*
- * This function is poorly named, and could also be used just to wait
- * for child death if you're doing your own pipe I/O. If that is
- * the case, close the pipe handles here.
- */
- if (pproc->sv_stdin[0]) {
- CloseHandle((HANDLE)pproc->sv_stdin[0]);
- pproc->sv_stdin[0] = 0;
- }
- if (pproc->sv_stdout[0]) {
- CloseHandle((HANDLE)pproc->sv_stdout[0]);
- pproc->sv_stdout[0] = 0;
- }
- if (pproc->sv_stderr[0]) {
- CloseHandle((HANDLE)pproc->sv_stderr[0]);
- pproc->sv_stderr[0] = 0;
- }
-
- /*
- * Wait for the child process to exit
- */
-
- wait_return = WaitForSingleObject(childhand, INFINITE);
-
- if (wait_return != WAIT_OBJECT_0) {
-/* map_windows32_error_to_string(GetLastError());*/
- pproc->last_err = GetLastError();
- pproc->lerrno = E_SCALL;
- goto done2;
- }
-
- if (GetExitCodeProcess(childhand, &pproc->exit_code) == FALSE) {
- pproc->last_err = GetLastError();
- pproc->lerrno = E_SCALL;
- }
-
-done2:
- if (pproc->lerrno)
- return(-1);
- else
- return(0);
-
-}
-
-/*
- * Description: Clean up any leftover handles, etc. It is up to the
- * caller to manage and free the input, ouput, and stderr buffers.
- */
- void
-process_cleanup(
- HANDLE proc)
-{
- sub_process *pproc = (sub_process *)proc;
- int i;
-
- if (pproc->using_pipes) {
- for (i= 0; i <= 1; i++) {
- if ((HANDLE)pproc->sv_stdin[i])
- CloseHandle((HANDLE)pproc->sv_stdin[i]);
- if ((HANDLE)pproc->sv_stdout[i])
- CloseHandle((HANDLE)pproc->sv_stdout[i]);
- if ((HANDLE)pproc->sv_stderr[i])
- CloseHandle((HANDLE)pproc->sv_stderr[i]);
- }
- }
- if ((HANDLE)pproc->pid)
- CloseHandle((HANDLE)pproc->pid);
-
- free(pproc);
-}
-
-
-/*
- * Description:
- * Create a command line buffer to pass to CreateProcess
- *
- * Returns: the buffer or NULL for failure
- * Shell case: sh_name a:/full/path/to/script argv[1] argv[2] ...
- * Otherwise: argv[0] argv[1] argv[2] ...
- *
- * Notes/Dependencies:
- * CreateProcess does not take an argv, so this command creates a
- * command line for the executable.
- */
-
-static char *
-make_command_line( char *shell_name, char *full_exec_path, char **argv)
-{
- int argc = 0;
- char** argvi;
- int* enclose_in_quotes = NULL;
- int* enclose_in_quotes_i;
- unsigned int bytes_required = 0;
- char* command_line;
- char* command_line_i;
-
- if (shell_name && full_exec_path) {
- bytes_required
- = strlen(shell_name) + 1 + strlen(full_exec_path);
- /*
- * Skip argv[0] if any, when shell_name is given.
- */
- if (*argv) argv++;
- /*
- * Add one for the intervening space.
- */
- if (*argv) bytes_required++;
- }
-
- argvi = argv;
- while (*(argvi++)) argc++;
-
- if (argc) {
- enclose_in_quotes = (int*) calloc(1, argc * sizeof(int));
-
- if (!enclose_in_quotes) {
- return NULL;
- }
- }
-
- /* We have to make one pass through each argv[i] to see if we need
- * to enclose it in ", so we might as well figure out how much
- * memory we'll need on the same pass.
- */
-
- argvi = argv;
- enclose_in_quotes_i = enclose_in_quotes;
- while(*argvi) {
- char* p = *argvi;
- unsigned int backslash_count = 0;
-
- /*
- * We have to enclose empty arguments in ".
- */
- if (!(*p)) *enclose_in_quotes_i = 1;
-
- while(*p) {
- switch (*p) {
- case '\"':
- /*
- * We have to insert a backslash for each "
- * and each \ that precedes the ".
- */
- bytes_required += (backslash_count + 1);
- backslash_count = 0;
- break;
-
- case '\\':
- backslash_count++;
- break;
- /*
- * At one time we set *enclose_in_quotes_i for '*' or '?' to suppress
- * wildcard expansion in programs linked with MSVC's SETARGV.OBJ so
- * that argv in always equals argv out. This was removed. Say you have
- * such a program named glob.exe. You enter
- * glob '*'
- * at the sh command prompt. Obviously the intent is to make glob do the
- * wildcarding instead of sh. If we set *enclose_in_quotes_i for '*' or '?',
- * then the command line that glob would see would be
- * glob "*"
- * and the _setargv in SETARGV.OBJ would _not_ expand the *.
- */
- case ' ':
- case '\t':
- *enclose_in_quotes_i = 1;
- /* fall through */
-
- default:
- backslash_count = 0;
- break;
- }
-
- /*
- * Add one for each character in argv[i].
- */
- bytes_required++;
-
- p++;
- }
-
- if (*enclose_in_quotes_i) {
- /*
- * Add one for each enclosing ",
- * and one for each \ that precedes the
- * closing ".
- */
- bytes_required += (backslash_count + 2);
- }
-
- /*
- * Add one for the intervening space.
- */
- if (*(++argvi)) bytes_required++;
- enclose_in_quotes_i++;
- }
-
- /*
- * Add one for the terminating NULL.
- */
- bytes_required++;
-
- command_line = (char*) malloc(bytes_required);
-
- if (!command_line) {
- if (enclose_in_quotes) free(enclose_in_quotes);
- return NULL;
- }
-
- command_line_i = command_line;
-
- if (shell_name && full_exec_path) {
- while(*shell_name) {
- *(command_line_i++) = *(shell_name++);
- }
-
- *(command_line_i++) = ' ';
-
- while(*full_exec_path) {
- *(command_line_i++) = *(full_exec_path++);
- }
-
- if (*argv) {
- *(command_line_i++) = ' ';
- }
- }
-
- argvi = argv;
- enclose_in_quotes_i = enclose_in_quotes;
-
- while(*argvi) {
- char* p = *argvi;
- unsigned int backslash_count = 0;
-
- if (*enclose_in_quotes_i) {
- *(command_line_i++) = '\"';
- }
-
- while(*p) {
- if (*p == '\"') {
- /*
- * We have to insert a backslash for the "
- * and each \ that precedes the ".
- */
- backslash_count++;
-
- while(backslash_count) {
- *(command_line_i++) = '\\';
- backslash_count--;
- };
-
- } else if (*p == '\\') {
- backslash_count++;
- } else {
- backslash_count = 0;
- }
-
- /*
- * Copy the character.
- */
- *(command_line_i++) = *(p++);
- }
-
- if (*enclose_in_quotes_i) {
- /*
- * Add one \ for each \ that precedes the
- * closing ".
- */
- while(backslash_count--) {
- *(command_line_i++) = '\\';
- };
-
- *(command_line_i++) = '\"';
- }
-
- /*
- * Append an intervening space.
- */
- if (*(++argvi)) {
- *(command_line_i++) = ' ';
- }
-
- enclose_in_quotes_i++;
- }
-
- /*
- * Append the terminating NULL.
- */
- *command_line_i = '\0';
-
- if (enclose_in_quotes) free(enclose_in_quotes);
- return command_line;
-}
-
-/*
- * Description: Given an argv and optional envp, launch the process
- * using the default stdin, stdout, and stderr handles.
- * Also, register process so that process_wait_for_any_private()
- * can be used via process_file_io(NULL) or
- * process_wait_for_any().
- *
- * Returns:
- *
- * Notes/Dependencies:
- */
-HANDLE
-process_easy(
- char **argv,
- char **envp)
-{
- HANDLE hIn;
- HANDLE hOut;
- HANDLE hErr;
- HANDLE hProcess;
-
- if (DuplicateHandle(GetCurrentProcess(),
- GetStdHandle(STD_INPUT_HANDLE),
- GetCurrentProcess(),
- &hIn,
- 0,
- TRUE,
- DUPLICATE_SAME_ACCESS) == FALSE) {
- fprintf(stderr,
- "process_easy: DuplicateHandle(In) failed (e=%d)\n",
- GetLastError());
- return INVALID_HANDLE_VALUE;
- }
- if (DuplicateHandle(GetCurrentProcess(),
- GetStdHandle(STD_OUTPUT_HANDLE),
- GetCurrentProcess(),
- &hOut,
- 0,
- TRUE,
- DUPLICATE_SAME_ACCESS) == FALSE) {
- fprintf(stderr,
- "process_easy: DuplicateHandle(Out) failed (e=%d)\n",
- GetLastError());
- return INVALID_HANDLE_VALUE;
- }
- if (DuplicateHandle(GetCurrentProcess(),
- GetStdHandle(STD_ERROR_HANDLE),
- GetCurrentProcess(),
- &hErr,
- 0,
- TRUE,
- DUPLICATE_SAME_ACCESS) == FALSE) {
- fprintf(stderr,
- "process_easy: DuplicateHandle(Err) failed (e=%d)\n",
- GetLastError());
- return INVALID_HANDLE_VALUE;
- }
-
- hProcess = process_init_fd(hIn, hOut, hErr);
-
- if (process_begin(hProcess, argv, envp, argv[0], NULL)) {
- fake_exits_pending++;
- ((sub_process*) hProcess)->exit_code = process_last_err(hProcess);
-
- /* close up unused handles */
- CloseHandle(hIn);
- CloseHandle(hOut);
- CloseHandle(hErr);
- }
-
- process_register(hProcess);
-
- return hProcess;
-}
+#include <stdlib.h>
+#include <stdio.h>
+#include <process.h> /* for msvc _beginthreadex, _endthreadex */
+#include <windows.h>
+
+#include "sub_proc.h"
+#include "proc.h"
+#include "w32err.h"
+#include "config.h"
+
+static char *make_command_line( char *shell_name, char *exec_path, char **argv);
+
+typedef struct sub_process_t {
+ int sv_stdin[2];
+ int sv_stdout[2];
+ int sv_stderr[2];
+ int using_pipes;
+ char *inp;
+ DWORD incnt;
+ char * volatile outp;
+ volatile DWORD outcnt;
+ char * volatile errp;
+ volatile DWORD errcnt;
+ int pid;
+ int exit_code;
+ int signal;
+ long last_err;
+ long lerrno;
+} sub_process;
+
+/* keep track of children so we can implement a waitpid-like routine */
+static sub_process *proc_array[256];
+static int proc_index = 0;
+static int fake_exits_pending = 0;
+
+/*
+ * When a process has been waited for, adjust the wait state
+ * array so that we don't wait for it again
+ */
+static void
+process_adjust_wait_state(sub_process* pproc)
+{
+ int i;
+
+ if (!proc_index)
+ return;
+
+ for (i = 0; i < proc_index; i++)
+ if (proc_array[i]->pid == pproc->pid)
+ break;
+
+ if (i < proc_index) {
+ proc_index--;
+ if (i != proc_index)
+ memmove(&proc_array[i], &proc_array[i+1],
+ (proc_index-i) * sizeof(sub_process*));
+ proc_array[proc_index] = NULL;
+ }
+}
+
+/*
+ * Waits for any of the registered child processes to finish.
+ */
+static sub_process *
+process_wait_for_any_private(void)
+{
+ HANDLE handles[256];
+ DWORD retval, which;
+ int i;
+
+ if (!proc_index)
+ return NULL;
+
+ /* build array of handles to wait for */
+ for (i = 0; i < proc_index; i++) {
+ handles[i] = (HANDLE) proc_array[i]->pid;
+
+ if (fake_exits_pending && proc_array[i]->exit_code)
+ break;
+ }
+
+ /* wait for someone to exit */
+ if (!fake_exits_pending) {
+ retval = WaitForMultipleObjects(proc_index, handles, FALSE, INFINITE);
+ which = retval - WAIT_OBJECT_0;
+ } else {
+ fake_exits_pending--;
+ retval = !WAIT_FAILED;
+ which = i;
+ }
+
+ /* return pointer to process */
+ if (retval != WAIT_FAILED) {
+ sub_process* pproc = proc_array[which];
+ process_adjust_wait_state(pproc);
+ return pproc;
+ } else
+ return NULL;
+}
+
+/*
+ * Terminate a process.
+ */
+BOOL
+process_kill(HANDLE proc, int signal)
+{
+ sub_process* pproc = (sub_process*) proc;
+ pproc->signal = signal;
+ return (TerminateProcess((HANDLE) pproc->pid, signal));
+}
+
+/*
+ * Use this function to register processes you wish to wait for by
+ * calling process_file_io(NULL) or process_wait_any(). This must be done
+ * because it is possible for callers of this library to reuse the same
+ * handle for multiple processes launches :-(
+ */
+void
+process_register(HANDLE proc)
+{
+ proc_array[proc_index++] = (sub_process *) proc;
+}
+
+/*
+ * Public function which works kind of like waitpid(). Wait for any
+ * of the children to die and return results. To call this function,
+ * you must do 1 of things:
+ *
+ * x = process_easy(...);
+ *
+ * or
+ *
+ * x = process_init_fd();
+ * process_register(x);
+ *
+ * or
+ *
+ * x = process_init();
+ * process_register(x);
+ *
+ * You must NOT then call process_pipe_io() because this function is
+ * not capable of handling automatic notification of any child
+ * death.
+ */
+
+HANDLE
+process_wait_for_any(void)
+{
+ sub_process* pproc = process_wait_for_any_private();
+
+ if (!pproc)
+ return NULL;
+ else {
+ /*
+ * Ouch! can't tell caller if this fails directly. Caller
+ * will have to use process_last_err()
+ */
+ (void) process_file_io(pproc);
+ return ((HANDLE) pproc);
+ }
+}
+
+long
+process_errno(HANDLE proc)
+{
+ return (((sub_process *)proc)->lerrno);
+}
+
+long
+process_signal(HANDLE proc)
+{
+ return (((sub_process *)proc)->signal);
+}
+
+ long
+process_last_err(HANDLE proc)
+{
+ return (((sub_process *)proc)->last_err);
+}
+
+ long
+process_exit_code(HANDLE proc)
+{
+ return (((sub_process *)proc)->exit_code);
+}
+
+ char *
+process_outbuf(HANDLE proc)
+{
+ return (((sub_process *)proc)->outp);
+}
+
+ char *
+process_errbuf(HANDLE proc)
+{
+ return (((sub_process *)proc)->errp);
+}
+
+ int
+process_outcnt(HANDLE proc)
+{
+ return (((sub_process *)proc)->outcnt);
+}
+
+ int
+process_errcnt(HANDLE proc)
+{
+ return (((sub_process *)proc)->errcnt);
+}
+
+ void
+process_pipes(HANDLE proc, int pipes[3])
+{
+ pipes[0] = ((sub_process *)proc)->sv_stdin[0];
+ pipes[1] = ((sub_process *)proc)->sv_stdout[0];
+ pipes[2] = ((sub_process *)proc)->sv_stderr[0];
+ return;
+}
+
+
+ HANDLE
+process_init()
+{
+ sub_process *pproc;
+ /*
+ * open file descriptors for attaching stdin/stdout/sterr
+ */
+ HANDLE stdin_pipes[2];
+ HANDLE stdout_pipes[2];
+ HANDLE stderr_pipes[2];
+ SECURITY_ATTRIBUTES inherit;
+ BYTE sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
+
+ pproc = malloc(sizeof(*pproc));
+ memset(pproc, 0, sizeof(*pproc));
+
+ /* We can't use NULL for lpSecurityDescriptor because that
+ uses the default security descriptor of the calling process.
+ Instead we use a security descriptor with no DACL. This
+ allows nonrestricted access to the associated objects. */
+
+ if (!InitializeSecurityDescriptor((PSECURITY_DESCRIPTOR)(&sd),
+ SECURITY_DESCRIPTOR_REVISION)) {
+ pproc->last_err = GetLastError();
+ pproc->lerrno = E_SCALL;
+ return((HANDLE)pproc);
+ }
+
+ inherit.nLength = sizeof(inherit);
+ inherit.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR)(&sd);
+ inherit.bInheritHandle = TRUE;
+
+ // By convention, parent gets pipe[0], and child gets pipe[1]
+ // This means the READ side of stdin pipe goes into pipe[1]
+ // and the WRITE side of the stdout and stderr pipes go into pipe[1]
+ if (CreatePipe( &stdin_pipes[1], &stdin_pipes[0], &inherit, 0) == FALSE ||
+ CreatePipe( &stdout_pipes[0], &stdout_pipes[1], &inherit, 0) == FALSE ||
+ CreatePipe( &stderr_pipes[0], &stderr_pipes[1], &inherit, 0) == FALSE) {
+
+ pproc->last_err = GetLastError();
+ pproc->lerrno = E_SCALL;
+ return((HANDLE)pproc);
+ }
+
+ //
+ // Mark the parent sides of the pipes as non-inheritable
+ //
+ if (SetHandleInformation(stdin_pipes[0],
+ HANDLE_FLAG_INHERIT, 0) == FALSE ||
+ SetHandleInformation(stdout_pipes[0],
+ HANDLE_FLAG_INHERIT, 0) == FALSE ||
+ SetHandleInformation(stderr_pipes[0],
+ HANDLE_FLAG_INHERIT, 0) == FALSE) {
+
+ pproc->last_err = GetLastError();
+ pproc->lerrno = E_SCALL;
+ return((HANDLE)pproc);
+ }
+ pproc->sv_stdin[0] = (int) stdin_pipes[0];
+ pproc->sv_stdin[1] = (int) stdin_pipes[1];
+ pproc->sv_stdout[0] = (int) stdout_pipes[0];
+ pproc->sv_stdout[1] = (int) stdout_pipes[1];
+ pproc->sv_stderr[0] = (int) stderr_pipes[0];
+ pproc->sv_stderr[1] = (int) stderr_pipes[1];
+
+ pproc->using_pipes = 1;
+
+ pproc->lerrno = 0;
+
+ return((HANDLE)pproc);
+}
+
+
+ HANDLE
+process_init_fd(HANDLE stdinh, HANDLE stdouth, HANDLE stderrh)
+{
+ sub_process *pproc;
+
+ pproc = malloc(sizeof(*pproc));
+ memset(pproc, 0, sizeof(*pproc));
+
+ /*
+ * Just pass the provided file handles to the 'child side' of the
+ * pipe, bypassing pipes altogether.
+ */
+ pproc->sv_stdin[1] = (int) stdinh;
+ pproc->sv_stdout[1] = (int) stdouth;
+ pproc->sv_stderr[1] = (int) stderrh;
+
+ pproc->last_err = pproc->lerrno = 0;
+
+ return((HANDLE)pproc);
+}
+
+
+static HANDLE
+find_file(char *exec_path, LPOFSTRUCT file_info)
+{
+ HANDLE exec_handle;
+ char *fname;
+ char *ext;
+
+ fname = malloc(strlen(exec_path) + 5);
+ strcpy(fname, exec_path);
+ ext = fname + strlen(fname);
+
+ strcpy(ext, ".exe");
+ if ((exec_handle = (HANDLE)OpenFile(fname, file_info,
+ OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) {
+ free(fname);
+ return(exec_handle);
+ }
+
+ strcpy(ext, ".cmd");
+ if ((exec_handle = (HANDLE)OpenFile(fname, file_info,
+ OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) {
+ free(fname);
+ return(exec_handle);
+ }
+
+ strcpy(ext, ".bat");
+ if ((exec_handle = (HANDLE)OpenFile(fname, file_info,
+ OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) {
+ free(fname);
+ return(exec_handle);
+ }
+
+ /* should .com come before this case? */
+ if ((exec_handle = (HANDLE)OpenFile(exec_path, file_info,
+ OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) {
+ free(fname);
+ return(exec_handle);
+ }
+
+ strcpy(ext, ".com");
+ if ((exec_handle = (HANDLE)OpenFile(fname, file_info,
+ OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) {
+ free(fname);
+ return(exec_handle);
+ }
+
+ free(fname);
+ return(exec_handle);
+}
+
+
+/*
+ * Description: Create the child process to be helped
+ *
+ * Returns:
+ *
+ * Notes/Dependencies:
+ */
+long
+process_begin(
+ HANDLE proc,
+ char **argv,
+ char **envp,
+ char *exec_path,
+ char *as_user)
+{
+ sub_process *pproc = (sub_process *)proc;
+ char *shell_name = 0;
+ int file_not_found=0;
+ HANDLE exec_handle;
+ char buf[256];
+ DWORD bytes_returned;
+ DWORD flags;
+ char *command_line;
+ STARTUPINFO startInfo;
+ PROCESS_INFORMATION procInfo;
+ char *envblk=NULL;
+ OFSTRUCT file_info;
+
+
+ /*
+ * Shell script detection... if the exec_path starts with #! then
+ * we want to exec shell-script-name exec-path, not just exec-path
+ * NT doesn't recognize #!/bin/sh or #!/etc/Tivoli/bin/perl. We do not
+ * hard-code the path to the shell or perl or whatever: Instead, we
+ * assume it's in the path somewhere (generally, the NT tools
+ * bin directory)
+ * We use OpenFile here because it is capable of searching the Path.
+ */
+
+ exec_handle = find_file(exec_path, &file_info);
+
+ /*
+ * If we couldn't open the file, just assume that Windows32 will be able
+ * to find and execute it.
+ */
+ if (exec_handle == (HANDLE)HFILE_ERROR) {
+ file_not_found++;
+ }
+ else {
+ /* Attempt to read the first line of the file */
+ if (ReadFile( exec_handle,
+ buf, sizeof(buf) - 1, /* leave room for trailing NULL */
+ &bytes_returned, 0) == FALSE || bytes_returned < 2) {
+
+ pproc->last_err = GetLastError();
+ pproc->lerrno = E_IO;
+ CloseHandle(exec_handle);
+ return(-1);
+ }
+ if (buf[0] == '#' && buf[1] == '!') {
+ /*
+ * This is a shell script... Change the command line from
+ * exec_path args to shell_name exec_path args
+ */
+ char *p;
+
+ /* Make sure buf is NULL terminated */
+ buf[bytes_returned] = 0;
+ /*
+ * Depending on the file system type, etc. the first line
+ * of the shell script may end with newline or newline-carriage-return
+ * Whatever it ends with, cut it off.
+ */
+ p= strchr(buf, '\n');
+ if (p)
+ *p = 0;
+ p = strchr(buf, '\r');
+ if (p)
+ *p = 0;
+
+ /*
+ * Find base name of shell
+ */
+ shell_name = strrchr( buf, '/');
+ if (shell_name) {
+ shell_name++;
+ } else {
+ shell_name = &buf[2];/* skipping "#!" */
+ }
+
+ }
+ CloseHandle(exec_handle);
+ }
+
+ flags = 0;
+
+ if (file_not_found)
+ command_line = make_command_line( shell_name, exec_path, argv);
+ else
+ command_line = make_command_line( shell_name, file_info.szPathName,
+ argv);
+
+ if ( command_line == NULL ) {
+ pproc->last_err = 0;
+ pproc->lerrno = E_NO_MEM;
+ return(-1);
+ }
+
+ if (envp) {
+ if (arr2envblk(envp, &envblk) ==FALSE) {
+ pproc->last_err = 0;
+ pproc->lerrno = E_NO_MEM;
+ free( command_line );
+ return(-1);
+ }
+ }
+
+ if ((shell_name) || (file_not_found)) {
+ exec_path = 0; /* Search for the program in %Path% */
+ } else {
+ exec_path = file_info.szPathName;
+ }
+
+ /*
+ * Set up inherited stdin, stdout, stderr for child
+ */
+ GetStartupInfo(&startInfo);
+ startInfo.dwFlags = STARTF_USESTDHANDLES;
+ startInfo.lpReserved = 0;
+ startInfo.cbReserved2 = 0;
+ startInfo.lpReserved2 = 0;
+ startInfo.lpTitle = shell_name ? shell_name : exec_path;
+ startInfo.hStdInput = (HANDLE)pproc->sv_stdin[1];
+ startInfo.hStdOutput = (HANDLE)pproc->sv_stdout[1];
+ startInfo.hStdError = (HANDLE)pproc->sv_stderr[1];
+
+ if (as_user) {
+ if (envblk) free(envblk);
+ return -1;
+ } else {
+ if (CreateProcess(
+ exec_path,
+ command_line,
+ NULL,
+ 0, /* default security attributes for thread */
+ TRUE, /* inherit handles (e.g. helper pipes, oserv socket) */
+ flags,
+ envblk,
+ 0, /* default starting directory */
+ &startInfo,
+ &procInfo) == FALSE) {
+
+ pproc->last_err = GetLastError();
+ pproc->lerrno = E_FORK;
+ fprintf(stderr, "process_begin: CreateProcess(%s, %s, ...) failed.\n", exec_path, command_line);
+ if (envblk) free(envblk);
+ free( command_line );
+ return(-1);
+ }
+ }
+
+ pproc->pid = (int)procInfo.hProcess;
+ /* Close the thread handle -- we'll just watch the process */
+ CloseHandle(procInfo.hThread);
+
+ /* Close the halves of the pipes we don't need */
+ if (pproc->sv_stdin) {
+ CloseHandle((HANDLE)pproc->sv_stdin[1]);
+ (HANDLE)pproc->sv_stdin[1] = 0;
+ }
+ if (pproc->sv_stdout) {
+ CloseHandle((HANDLE)pproc->sv_stdout[1]);
+ (HANDLE)pproc->sv_stdout[1] = 0;
+ }
+ if (pproc->sv_stderr) {
+ CloseHandle((HANDLE)pproc->sv_stderr[1]);
+ (HANDLE)pproc->sv_stderr[1] = 0;
+ }
+
+ free( command_line );
+ if (envblk) free(envblk);
+ pproc->lerrno=0;
+ return 0;
+}
+
+
+
+static DWORD
+proc_stdin_thread(sub_process *pproc)
+{
+ DWORD in_done;
+ for (;;) {
+ if (WriteFile( (HANDLE) pproc->sv_stdin[0], pproc->inp, pproc->incnt,
+ &in_done, NULL) == FALSE)
+ _endthreadex(0);
+ // This if should never be true for anonymous pipes, but gives
+ // us a chance to change I/O mechanisms later
+ if (in_done < pproc->incnt) {
+ pproc->incnt -= in_done;
+ pproc->inp += in_done;
+ } else {
+ _endthreadex(0);
+ }
+ }
+ return 0; // for compiler warnings only.. not reached
+}
+
+static DWORD
+proc_stdout_thread(sub_process *pproc)
+{
+ DWORD bufsize = 1024;
+ char c;
+ DWORD nread;
+ pproc->outp = malloc(bufsize);
+ if (pproc->outp == NULL)
+ _endthreadex(0);
+ pproc->outcnt = 0;
+
+ for (;;) {
+ if (ReadFile( (HANDLE)pproc->sv_stdout[0], &c, 1, &nread, NULL)
+ == FALSE) {
+/* map_windows32_error_to_string(GetLastError());*/
+ _endthreadex(0);
+ }
+ if (nread == 0)
+ _endthreadex(0);
+ if (pproc->outcnt + nread > bufsize) {
+ bufsize += nread + 512;
+ pproc->outp = realloc(pproc->outp, bufsize);
+ if (pproc->outp == NULL) {
+ pproc->outcnt = 0;
+ _endthreadex(0);
+ }
+ }
+ pproc->outp[pproc->outcnt++] = c;
+ }
+ return 0;
+}
+
+static DWORD
+proc_stderr_thread(sub_process *pproc)
+{
+ DWORD bufsize = 1024;
+ char c;
+ DWORD nread;
+ pproc->errp = malloc(bufsize);
+ if (pproc->errp == NULL)
+ _endthreadex(0);
+ pproc->errcnt = 0;
+
+ for (;;) {
+ if (ReadFile( (HANDLE)pproc->sv_stderr[0], &c, 1, &nread, NULL) == FALSE) {
+ map_windows32_error_to_string(GetLastError());
+ _endthreadex(0);
+ }
+ if (nread == 0)
+ _endthreadex(0);
+ if (pproc->errcnt + nread > bufsize) {
+ bufsize += nread + 512;
+ pproc->errp = realloc(pproc->errp, bufsize);
+ if (pproc->errp == NULL) {
+ pproc->errcnt = 0;
+ _endthreadex(0);
+ }
+ }
+ pproc->errp[pproc->errcnt++] = c;
+ }
+ return 0;
+}
+
+
+/*
+ * Purpose: collects output from child process and returns results
+ *
+ * Description:
+ *
+ * Returns:
+ *
+ * Notes/Dependencies:
+ */
+ long
+process_pipe_io(
+ HANDLE proc,
+ char *stdin_data,
+ int stdin_data_len)
+{
+ sub_process *pproc = (sub_process *)proc;
+ bool_t stdin_eof = FALSE, stdout_eof = FALSE, stderr_eof = FALSE;
+ HANDLE childhand = (HANDLE) pproc->pid;
+ HANDLE tStdin, tStdout, tStderr;
+ DWORD dwStdin, dwStdout, dwStderr;
+ HANDLE wait_list[4];
+ DWORD wait_count;
+ DWORD wait_return;
+ HANDLE ready_hand;
+ bool_t child_dead = FALSE;
+
+
+ /*
+ * Create stdin thread, if needed
+ */
+ pproc->inp = stdin_data;
+ pproc->incnt = stdin_data_len;
+ if (!pproc->inp) {
+ stdin_eof = TRUE;
+ CloseHandle((HANDLE)pproc->sv_stdin[0]);
+ (HANDLE)pproc->sv_stdin[0] = 0;
+ } else {
+ tStdin = (HANDLE) _beginthreadex( 0, 1024,
+ (unsigned (__stdcall *) (void *))proc_stdin_thread, pproc, 0,
+ (unsigned int *) &dwStdin);
+ if (tStdin == 0) {
+ pproc->last_err = GetLastError();
+ pproc->lerrno = E_SCALL;
+ goto done;
+ }
+ }
+
+ /*
+ * Assume child will produce stdout and stderr
+ */
+ tStdout = (HANDLE) _beginthreadex( 0, 1024,
+ (unsigned (__stdcall *) (void *))proc_stdout_thread, pproc, 0,
+ (unsigned int *) &dwStdout);
+ tStderr = (HANDLE) _beginthreadex( 0, 1024,
+ (unsigned (__stdcall *) (void *))proc_stderr_thread, pproc, 0,
+ (unsigned int *) &dwStderr);
+
+ if (tStdout == 0 || tStderr == 0) {
+
+ pproc->last_err = GetLastError();
+ pproc->lerrno = E_SCALL;
+ goto done;
+ }
+
+
+ /*
+ * Wait for all I/O to finish and for the child process to exit
+ */
+
+ while (!stdin_eof || !stdout_eof || !stderr_eof || !child_dead) {
+ wait_count = 0;
+ if (!stdin_eof) {
+ wait_list[wait_count++] = tStdin;
+ }
+ if (!stdout_eof) {
+ wait_list[wait_count++] = tStdout;
+ }
+ if (!stderr_eof) {
+ wait_list[wait_count++] = tStderr;
+ }
+ if (!child_dead) {
+ wait_list[wait_count++] = childhand;
+ }
+
+ wait_return = WaitForMultipleObjects(wait_count, wait_list,
+ FALSE, /* don't wait for all: one ready will do */
+ child_dead? 1000 :INFINITE); /* after the child dies, subthreads have
+ one second to collect all remaining output */
+
+ if (wait_return == WAIT_FAILED) {
+/* map_windows32_error_to_string(GetLastError());*/
+ pproc->last_err = GetLastError();
+ pproc->lerrno = E_SCALL;
+ goto done;
+ }
+
+ ready_hand = wait_list[wait_return - WAIT_OBJECT_0];
+
+ if (ready_hand == tStdin) {
+ CloseHandle((HANDLE)pproc->sv_stdin[0]);
+ (HANDLE)pproc->sv_stdin[0] = 0;
+ CloseHandle(tStdin);
+ tStdin = 0;
+ stdin_eof = TRUE;
+
+ } else if (ready_hand == tStdout) {
+
+ CloseHandle((HANDLE)pproc->sv_stdout[0]);
+ (HANDLE)pproc->sv_stdout[0] = 0;
+ CloseHandle(tStdout);
+ tStdout = 0;
+ stdout_eof = TRUE;
+
+ } else if (ready_hand == tStderr) {
+
+ CloseHandle((HANDLE)pproc->sv_stderr[0]);
+ (HANDLE)pproc->sv_stderr[0] = 0;
+ CloseHandle(tStderr);
+ tStderr = 0;
+ stderr_eof = TRUE;
+
+ } else if (ready_hand == childhand) {
+
+ if (GetExitCodeProcess(childhand, &pproc->exit_code) == FALSE) {
+ pproc->last_err = GetLastError();
+ pproc->lerrno = E_SCALL;
+ goto done;
+ }
+ child_dead = TRUE;
+
+ } else {
+
+ /* ?? Got back a handle we didn't query ?? */
+ pproc->last_err = 0;
+ pproc->lerrno = E_FAIL;
+ goto done;
+ }
+ }
+
+ done:
+ if (tStdin != 0)
+ CloseHandle(tStdin);
+ if (tStdout != 0)
+ CloseHandle(tStdout);
+ if (tStderr != 0)
+ CloseHandle(tStderr);
+
+ if (pproc->lerrno)
+ return(-1);
+ else
+ return(0);
+
+}
+
+/*
+ * Purpose: collects output from child process and returns results
+ *
+ * Description:
+ *
+ * Returns:
+ *
+ * Notes/Dependencies:
+ */
+ long
+process_file_io(
+ HANDLE proc)
+{
+ sub_process *pproc;
+ HANDLE childhand;
+ DWORD wait_return;
+
+ if (proc == NULL)
+ pproc = process_wait_for_any_private();
+ else
+ pproc = (sub_process *)proc;
+
+ /* some sort of internal error */
+ if (!pproc)
+ return -1;
+
+ childhand = (HANDLE) pproc->pid;
+
+ /*
+ * This function is poorly named, and could also be used just to wait
+ * for child death if you're doing your own pipe I/O. If that is
+ * the case, close the pipe handles here.
+ */
+ if (pproc->sv_stdin[0]) {
+ CloseHandle((HANDLE)pproc->sv_stdin[0]);
+ pproc->sv_stdin[0] = 0;
+ }
+ if (pproc->sv_stdout[0]) {
+ CloseHandle((HANDLE)pproc->sv_stdout[0]);
+ pproc->sv_stdout[0] = 0;
+ }
+ if (pproc->sv_stderr[0]) {
+ CloseHandle((HANDLE)pproc->sv_stderr[0]);
+ pproc->sv_stderr[0] = 0;
+ }
+
+ /*
+ * Wait for the child process to exit
+ */
+
+ wait_return = WaitForSingleObject(childhand, INFINITE);
+
+ if (wait_return != WAIT_OBJECT_0) {
+/* map_windows32_error_to_string(GetLastError());*/
+ pproc->last_err = GetLastError();
+ pproc->lerrno = E_SCALL;
+ goto done2;
+ }
+
+ if (GetExitCodeProcess(childhand, &pproc->exit_code) == FALSE) {
+ pproc->last_err = GetLastError();
+ pproc->lerrno = E_SCALL;
+ }
+
+done2:
+ if (pproc->lerrno)
+ return(-1);
+ else
+ return(0);
+
+}
+
+/*
+ * Description: Clean up any leftover handles, etc. It is up to the
+ * caller to manage and free the input, ouput, and stderr buffers.
+ */
+ void
+process_cleanup(
+ HANDLE proc)
+{
+ sub_process *pproc = (sub_process *)proc;
+ int i;
+
+ if (pproc->using_pipes) {
+ for (i= 0; i <= 1; i++) {
+ if ((HANDLE)pproc->sv_stdin[i])
+ CloseHandle((HANDLE)pproc->sv_stdin[i]);
+ if ((HANDLE)pproc->sv_stdout[i])
+ CloseHandle((HANDLE)pproc->sv_stdout[i]);
+ if ((HANDLE)pproc->sv_stderr[i])
+ CloseHandle((HANDLE)pproc->sv_stderr[i]);
+ }
+ }
+ if ((HANDLE)pproc->pid)
+ CloseHandle((HANDLE)pproc->pid);
+
+ free(pproc);
+}
+
+
+/*
+ * Description:
+ * Create a command line buffer to pass to CreateProcess
+ *
+ * Returns: the buffer or NULL for failure
+ * Shell case: sh_name a:/full/path/to/script argv[1] argv[2] ...
+ * Otherwise: argv[0] argv[1] argv[2] ...
+ *
+ * Notes/Dependencies:
+ * CreateProcess does not take an argv, so this command creates a
+ * command line for the executable.
+ */
+
+static char *
+make_command_line( char *shell_name, char *full_exec_path, char **argv)
+{
+ int argc = 0;
+ char** argvi;
+ int* enclose_in_quotes = NULL;
+ int* enclose_in_quotes_i;
+ unsigned int bytes_required = 0;
+ char* command_line;
+ char* command_line_i;
+
+ if (shell_name && full_exec_path) {
+ bytes_required
+ = strlen(shell_name) + 1 + strlen(full_exec_path);
+ /*
+ * Skip argv[0] if any, when shell_name is given.
+ */
+ if (*argv) argv++;
+ /*
+ * Add one for the intervening space.
+ */
+ if (*argv) bytes_required++;
+ }
+
+ argvi = argv;
+ while (*(argvi++)) argc++;
+
+ if (argc) {
+ enclose_in_quotes = (int*) calloc(1, argc * sizeof(int));
+
+ if (!enclose_in_quotes) {
+ return NULL;
+ }
+ }
+
+ /* We have to make one pass through each argv[i] to see if we need
+ * to enclose it in ", so we might as well figure out how much
+ * memory we'll need on the same pass.
+ */
+
+ argvi = argv;
+ enclose_in_quotes_i = enclose_in_quotes;
+ while(*argvi) {
+ char* p = *argvi;
+ unsigned int backslash_count = 0;
+
+ /*
+ * We have to enclose empty arguments in ".
+ */
+ if (!(*p)) *enclose_in_quotes_i = 1;
+
+ while(*p) {
+ switch (*p) {
+ case '\"':
+ /*
+ * We have to insert a backslash for each "
+ * and each \ that precedes the ".
+ */
+ bytes_required += (backslash_count + 1);
+ backslash_count = 0;
+ break;
+
+#ifndef HAVE_MKS_SHELL
+ case '\\':
+ backslash_count++;
+ break;
+#endif
+ /*
+ * At one time we set *enclose_in_quotes_i for '*' or '?' to suppress
+ * wildcard expansion in programs linked with MSVC's SETARGV.OBJ so
+ * that argv in always equals argv out. This was removed. Say you have
+ * such a program named glob.exe. You enter
+ * glob '*'
+ * at the sh command prompt. Obviously the intent is to make glob do the
+ * wildcarding instead of sh. If we set *enclose_in_quotes_i for '*' or '?',
+ * then the command line that glob would see would be
+ * glob "*"
+ * and the _setargv in SETARGV.OBJ would _not_ expand the *.
+ */
+ case ' ':
+ case '\t':
+ *enclose_in_quotes_i = 1;
+ /* fall through */
+
+ default:
+ backslash_count = 0;
+ break;
+ }
+
+ /*
+ * Add one for each character in argv[i].
+ */
+ bytes_required++;
+
+ p++;
+ }
+
+ if (*enclose_in_quotes_i) {
+ /*
+ * Add one for each enclosing ",
+ * and one for each \ that precedes the
+ * closing ".
+ */
+ bytes_required += (backslash_count + 2);
+ }
+
+ /*
+ * Add one for the intervening space.
+ */
+ if (*(++argvi)) bytes_required++;
+ enclose_in_quotes_i++;
+ }
+
+ /*
+ * Add one for the terminating NULL.
+ */
+ bytes_required++;
+
+ command_line = (char*) malloc(bytes_required);
+
+ if (!command_line) {
+ if (enclose_in_quotes) free(enclose_in_quotes);
+ return NULL;
+ }
+
+ command_line_i = command_line;
+
+ if (shell_name && full_exec_path) {
+ while(*shell_name) {
+ *(command_line_i++) = *(shell_name++);
+ }
+
+ *(command_line_i++) = ' ';
+
+ while(*full_exec_path) {
+ *(command_line_i++) = *(full_exec_path++);
+ }
+
+ if (*argv) {
+ *(command_line_i++) = ' ';
+ }
+ }
+
+ argvi = argv;
+ enclose_in_quotes_i = enclose_in_quotes;
+
+ while(*argvi) {
+ char* p = *argvi;
+ unsigned int backslash_count = 0;
+
+ if (*enclose_in_quotes_i) {
+ *(command_line_i++) = '\"';
+ }
+
+ while(*p) {
+ if (*p == '\"') {
+ /*
+ * We have to insert a backslash for the "
+ * and each \ that precedes the ".
+ */
+ backslash_count++;
+
+ while(backslash_count) {
+ *(command_line_i++) = '\\';
+ backslash_count--;
+ };
+#ifndef HAVE_MKS_SHELL
+ } else if (*p == '\\') {
+ backslash_count++;
+ } else {
+ backslash_count = 0;
+#endif
+ }
+
+ /*
+ * Copy the character.
+ */
+ *(command_line_i++) = *(p++);
+ }
+
+ if (*enclose_in_quotes_i) {
+#ifndef HAVE_MKS_SHELL
+ /*
+ * Add one \ for each \ that precedes the
+ * closing ".
+ */
+ while(backslash_count--) {
+ *(command_line_i++) = '\\';
+ };
+#endif
+ *(command_line_i++) = '\"';
+ }
+
+ /*
+ * Append an intervening space.
+ */
+ if (*(++argvi)) {
+ *(command_line_i++) = ' ';
+ }
+
+ enclose_in_quotes_i++;
+ }
+
+ /*
+ * Append the terminating NULL.
+ */
+ *command_line_i = '\0';
+
+ if (enclose_in_quotes) free(enclose_in_quotes);
+ return command_line;
+}
+
+/*
+ * Description: Given an argv and optional envp, launch the process
+ * using the default stdin, stdout, and stderr handles.
+ * Also, register process so that process_wait_for_any_private()
+ * can be used via process_file_io(NULL) or
+ * process_wait_for_any().
+ *
+ * Returns:
+ *
+ * Notes/Dependencies:
+ */
+HANDLE
+process_easy(
+ char **argv,
+ char **envp)
+{
+ HANDLE hIn;
+ HANDLE hOut;
+ HANDLE hErr;
+ HANDLE hProcess;
+
+ if (DuplicateHandle(GetCurrentProcess(),
+ GetStdHandle(STD_INPUT_HANDLE),
+ GetCurrentProcess(),
+ &hIn,
+ 0,
+ TRUE,
+ DUPLICATE_SAME_ACCESS) == FALSE) {
+ fprintf(stderr,
+ "process_easy: DuplicateHandle(In) failed (e=%d)\n",
+ GetLastError());
+ return INVALID_HANDLE_VALUE;
+ }
+ if (DuplicateHandle(GetCurrentProcess(),
+ GetStdHandle(STD_OUTPUT_HANDLE),
+ GetCurrentProcess(),
+ &hOut,
+ 0,
+ TRUE,
+ DUPLICATE_SAME_ACCESS) == FALSE) {
+ fprintf(stderr,
+ "process_easy: DuplicateHandle(Out) failed (e=%d)\n",
+ GetLastError());
+ return INVALID_HANDLE_VALUE;
+ }
+ if (DuplicateHandle(GetCurrentProcess(),
+ GetStdHandle(STD_ERROR_HANDLE),
+ GetCurrentProcess(),
+ &hErr,
+ 0,
+ TRUE,
+ DUPLICATE_SAME_ACCESS) == FALSE) {
+ fprintf(stderr,
+ "process_easy: DuplicateHandle(Err) failed (e=%d)\n",
+ GetLastError());
+ return INVALID_HANDLE_VALUE;
+ }
+
+ hProcess = process_init_fd(hIn, hOut, hErr);
+
+ if (process_begin(hProcess, argv, envp, argv[0], NULL)) {
+ fake_exits_pending++;
+ ((sub_process*) hProcess)->exit_code = process_last_err(hProcess);
+
+ /* close up unused handles */
+ CloseHandle(hIn);
+ CloseHandle(hOut);
+ CloseHandle(hErr);
+ }
+
+ process_register(hProcess);
+
+ return hProcess;
+}