summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Shadura <andrew.shadura@collabora.co.uk>2016-03-06 09:59:07 +0100
committerAndrew Shadura <andrew.shadura@collabora.co.uk>2016-03-06 09:59:07 +0100
commit15434d7bce0a6df51e18b08e12151e0c467e495f (patch)
tree0046ee78f73d9ae7017726fad2966a44d15e757d
parent9a90ef7311027097a245bf2b8857a7d4e715c18f (diff)
Imported Upstream version 20160220
-rw-r--r--ChangeLog189
-rw-r--r--FILES101
-rw-r--r--Makefile13
-rw-r--r--PSD.doc/Makefile6
-rw-r--r--PSD.doc/tutorial.ms12
-rw-r--r--arch.c48
-rw-r--r--bmake.1251
-rw-r--r--bmake.cat1205
-rwxr-xr-xboot-strap11
-rw-r--r--compat.c72
-rw-r--r--cond.c73
-rw-r--r--config.h.in18
-rwxr-xr-xconfigure118
-rw-r--r--configure.in18
-rw-r--r--dirname.c89
-rw-r--r--for.c8
-rw-r--r--getopt.c89
-rw-r--r--job.c56
-rw-r--r--lst.h2
-rw-r--r--lst.lib/lstInt.h2
-rw-r--r--lst.lib/lstRemove.c6
-rwxr-xr-xmachine.sh6
-rw-r--r--main.c141
-rwxr-xr-xmake-bootstrap.sh.in2
-rw-r--r--make.1251
-rw-r--r--make.c28
-rw-r--r--make.h21
-rw-r--r--meta.c149
-rw-r--r--metachar.c88
-rw-r--r--metachar.h61
-rw-r--r--mk/ChangeLog247
-rw-r--r--mk/FILES4
-rw-r--r--mk/auto.dep.mk14
-rw-r--r--mk/auto.obj.mk17
-rw-r--r--mk/autodep.mk7
-rw-r--r--mk/cython.mk96
-rw-r--r--mk/dep.mk14
-rw-r--r--mk/dirdeps.mk237
-rw-r--r--mk/doc.mk18
-rw-r--r--mk/gendirdeps.mk21
-rw-r--r--mk/host-target.mk23
-rw-r--r--mk/init.mk6
-rw-r--r--mk/install-mk4
-rw-r--r--mk/lib.mk4
-rw-r--r--mk/links.mk13
-rw-r--r--mk/manifest.mk66
-rw-r--r--mk/meta.autodep.mk14
-rw-r--r--mk/meta.stage.mk82
-rw-r--r--mk/meta.subdir.mk4
-rw-r--r--mk/meta.sys.mk60
-rwxr-xr-xmk/meta2deps.py220
-rwxr-xr-xmk/meta2deps.sh30
-rw-r--r--mk/mk-files.txt20
-rw-r--r--mk/mkopt.sh103
-rw-r--r--mk/own.mk7
-rw-r--r--mk/rst2htm.mk13
-rw-r--r--mk/sys.clean-env.mk15
-rw-r--r--mk/sys.dependfile.mk10
-rw-r--r--mk/sys.mk49
-rw-r--r--mk/warnings.mk4
-rw-r--r--mk/whats.mk63
-rw-r--r--nonints.h9
-rw-r--r--os.sh60
-rw-r--r--parse.c135
-rw-r--r--suff.c48
-rw-r--r--targ.c12
-rw-r--r--unit-tests/Makefile.in109
-rw-r--r--unit-tests/comment.exp5
-rw-r--r--unit-tests/comment.mk (renamed from unit-tests/comment)0
-rw-r--r--unit-tests/cond1.exp23
-rw-r--r--unit-tests/cond1.mk (renamed from unit-tests/cond1)2
-rw-r--r--unit-tests/cond2.exp7
-rw-r--r--unit-tests/cond2.mk29
-rw-r--r--unit-tests/doterror.exp9
-rw-r--r--unit-tests/doterror.mk (renamed from unit-tests/doterror)2
-rw-r--r--unit-tests/dotwait.exp30
-rw-r--r--unit-tests/dotwait.mk (renamed from unit-tests/dotwait)2
-rw-r--r--unit-tests/error.exp4
-rw-r--r--unit-tests/error.mk (renamed from unit-tests/error)2
-rw-r--r--unit-tests/escape.exp104
-rw-r--r--unit-tests/escape.mk246
-rw-r--r--unit-tests/export-all.exp12
-rw-r--r--unit-tests/export-all.mk (renamed from unit-tests/export-all)4
-rw-r--r--unit-tests/export-env.exp11
-rw-r--r--unit-tests/export-env.mk (renamed from unit-tests/export-env)9
-rw-r--r--unit-tests/export.exp6
-rw-r--r--unit-tests/export.mk (renamed from unit-tests/export)2
-rw-r--r--unit-tests/forloop.exp19
-rw-r--r--unit-tests/forloop.mk (renamed from unit-tests/forloop)2
-rw-r--r--unit-tests/forsubst.exp2
-rw-r--r--unit-tests/forsubst.mk (renamed from unit-tests/forsubst)2
-rw-r--r--unit-tests/hash.exp9
-rw-r--r--unit-tests/hash.mk (renamed from unit-tests/hash)0
-rw-r--r--unit-tests/impsrc.exp13
-rw-r--r--unit-tests/impsrc.mk43
-rw-r--r--unit-tests/misc.exp1
-rw-r--r--unit-tests/misc.mk (renamed from unit-tests/misc)2
-rw-r--r--unit-tests/moderrs.exp16
-rw-r--r--unit-tests/moderrs.mk (renamed from unit-tests/moderrs)2
-rw-r--r--unit-tests/modmatch.exp17
-rw-r--r--unit-tests/modmatch.mk (renamed from unit-tests/modmatch)0
-rw-r--r--unit-tests/modmisc.exp10
-rw-r--r--unit-tests/modmisc.mk (renamed from unit-tests/modmisc)2
-rw-r--r--unit-tests/modorder.exp11
-rw-r--r--unit-tests/modorder.mk (renamed from unit-tests/modorder)2
-rw-r--r--unit-tests/modts.exp33
-rw-r--r--unit-tests/modts.mk (renamed from unit-tests/modts)4
-rw-r--r--unit-tests/modword.exp122
-rw-r--r--unit-tests/modword.mk (renamed from unit-tests/modword)2
-rw-r--r--unit-tests/order.exp4
-rw-r--r--unit-tests/order.mk (renamed from unit-tests/order)2
-rw-r--r--unit-tests/phony-end.exp6
-rw-r--r--unit-tests/phony-end.mk (renamed from unit-tests/phony-end)2
-rw-r--r--unit-tests/posix.exp23
-rw-r--r--unit-tests/posix.mk (renamed from unit-tests/posix)2
-rw-r--r--unit-tests/posix1.exp185
-rw-r--r--unit-tests/posix1.mk184
-rw-r--r--unit-tests/qequals.exp2
-rw-r--r--unit-tests/qequals.mk (renamed from unit-tests/qequals)2
-rw-r--r--unit-tests/suffixes.exp35
-rw-r--r--unit-tests/suffixes.mk89
-rw-r--r--unit-tests/sunshcmd.exp4
-rw-r--r--unit-tests/sunshcmd.mk (renamed from unit-tests/sunshcmd)0
-rw-r--r--unit-tests/sysv.exp7
-rw-r--r--unit-tests/sysv.mk (renamed from unit-tests/sysv)6
-rw-r--r--unit-tests/ternary.exp10
-rw-r--r--unit-tests/ternary.mk (renamed from unit-tests/ternary)0
-rw-r--r--unit-tests/test.exp383
-rw-r--r--unit-tests/unexport-env.exp2
-rw-r--r--unit-tests/unexport-env.mk (renamed from unit-tests/unexport-env)4
-rw-r--r--unit-tests/unexport.exp4
-rw-r--r--unit-tests/unexport.mk (renamed from unit-tests/unexport)4
-rw-r--r--unit-tests/varcmd.exp9
-rw-r--r--unit-tests/varcmd.mk (renamed from unit-tests/varcmd)2
-rw-r--r--unit-tests/varmisc.exp20
-rw-r--r--unit-tests/varmisc.mk42
-rw-r--r--unit-tests/varshell.exp10
-rw-r--r--unit-tests/varshell.mk19
-rw-r--r--var.c463
139 files changed, 4775 insertions, 1565 deletions
diff --git a/ChangeLog b/ChangeLog
index 1dbf0ef..850a239 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,8 +1,195 @@
+2016-02-19 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * var.c: default .MAKE.SAVE_DOLLARS to FALSE
+ for backwards compatability.
+
+ * Makefile (MAKE_VERSION): 20160220
+ Merge with NetBSD make, pick up
+ o var.c: add knob to control handling of '$$' in :=
+
+2016-02-18 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * Makefile (MAKE_VERSION): 20160218
+ Merge with NetBSD make, pick up
+ o var.c: add .export-literal allows us to fix sys.clean-env.mk
+ post the changes to Var_Subst.
+ Var_Subst now takes flags, and does not consume '$$' in :=
+
+2016-02-17 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * Makefile (MAKE_VERSION): 20160217
+ Merge with NetBSD make, pick up
+ o var.c: preserve '$$' in :=
+ o parse.c: add .dinclude for handling included
+ makefile like .depend
+
+2015-12-20 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * Makefile (MAKE_VERSION): 20151220
+ Merge with NetBSD make, pick up
+ o suff.c: re-initialize suffNull when clearing suffixes.
+
+2015-12-01 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * Makefile (MAKE_VERSION): 20151201
+ Merge with NetBSD make, pick up
+ o cond.c: CondCvtArg: avoid access beyond end of empty buffer.
+ o meta.c: meta_oodate: use lstat(2) for checking link target
+ in case it is a symlink.
+ o var.c: avoid calling brk_string and Var_Export1 with empty
+ strings.
+
+2015-11-26 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * Makefile (MAKE_VERSION): 20151126
+ Merge with NetBSD make, pick up
+ o parse.c: ParseTrackInput don't access beyond
+ end of old value.
+
+2015-10-22 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * Makefile (MAKE_VERSION): 20151022
+
+ * Add support for BSD/OS which lacks inttypes.h
+ and really needs sys/param.h for sys/sysctl.h
+ also 'type' is not a shell builtin.
+
+ * var.c: eliminate uint32_t and need for inttypes.h
+
+ * main.c: PrintOnError flush stdout before run .ERROR
+
+ * parse.c: cope with _SC_PAGESIZE not being defined.
+
+
+2015-10-20 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * Makefile (MAKE_VERSION): 20151020
+ Merge with NetBSD make, pick up
+ o var.c: fix uninitialized var
+
+2015-10-12 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * var.c: the conditional expressions used with ':?' can be
+ expensive, if already discarding do not evaluate or expand
+ anything.
+
+2015-10-10 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * Makefile (MAKE_VERSION): 20151010
+ Merge with NetBSD make, pick up
+ o Add Boolean wantit flag to Var_Subst and Var_Parse
+ when FALSE we know we are discarding the result and can
+ skip operations like Cmd_Exec.
+
+2015-10-09 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * Makefile (MAKE_VERSION): 20151009
+ Merge with NetBSD make, pick up
+ o var.c: don't check for NULL before free()
+ o meta.c: meta_oodate, do not hard code ignore of makeDependfile
+
+2015-09-10 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * Makefile (MAKE_VERSION): 20150910
+ Merge with NetBSD make, pick up
+ o main.c: with -w print Enter/Leaving messages for objdir too
+ if necessary.
+ o centralize shell metachar handling
+
+ * FILES: add metachar.[ch]
+
+2015-06-06 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * Makefile (MAKE_VERSION): 20150606
+ Merge with NetBSD make, pick up
+ o make.1: document .OBJDIR target
+
+2015-05-05 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * Makefile (MAKE_VERSION): 20150505
+ Merge with NetBSD make, pick up
+ o cond.c: be strict about lhs of comparison when evaluating .if
+ but less so when called from variable expansion.
+ o unit-tests/cond2.mk: test various error conditions
+
+2015-05-04 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * machine.sh (MACHINE): Add Bitrig
+ patch from joerg@netbsd.org
+
+2015-04-18 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * Makefile (MAKE_VERSION): 20150418
+ Merge with NetBSD make, pick up
+ o job.c: use memmove() rather than memcpy()
+
+ * unit-tests/varshell.mk: SunOS cannot handle the TERMINATED_BY_SIGNAL
+ case, so skip it.
+
+2015-04-11 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * Makefile (MAKE_VERSION): 20150411
+ bump version - only mk/ changes.
+
+2015-04-10 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * Makefile (MAKE_VERSION): 20150410
+ Merge with NetBSD make, pick up
+ o document different handling of '-' in jobs mode vs compat
+ o fix jobs mode so that '-' only applies to whole job
+ when shell lacks hasErrCtl
+ o meta.c: use separate vars to track lcwd and latestdir (read)
+ per process
+
+2015-04-01 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * Makefile (MAKE_VERSION): 20150401
+ Merge with NetBSD make, pick up
+ o meta.c: close meta file in child
+
+ * Makefile: use BINDIR.bmake if set.
+ Same for MANDIR and SHAREDIR
+ Handy for testing release candidates
+ in various environments.
+
+2015-03-26 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * move initialization of savederr to block where it is used
+ to avoid spurious warning from gcc5
+
+2014-11-11 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * Makefile (MAKE_VERSION): 20141111
+ just a cooler number
+
+2014-11-05 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * Makefile (MAKE_VERSION): 20141105
+ Merge with NetBSD make, pick up
+ o revert major overhaul of suffix handling
+ and POSIX compliance - too much breakage
+ and impossible to make backwards compatible.
+ o we still have the new unit test structure which is ok.
+ o meta.c ensure "-- filemon" is at start of line.
+
+2014-09-17 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * configure.in: test that result of getconf PATH_MAX is numeric
+ and discard if not. Apparently needed for Hurd.
+
+2014-08-30 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * Makefile (MAKE_VERSION): 20140830
+ Merge with NetBSD make, pick up
+ o major overhaul of suffix handling
+ o improved POSIX compliance
+ o overhauled unit-tests
+
2014-06-20 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (MAKE_VERSION): 20140620
Merge with NetBSD make, pick up
- o var.c return varNoError rather than var_Error for ::= modidiers.
+ o var.c return varNoError rather than var_Error for ::= modifiers.
2014-05-22 Simon J. Gerraty <sjg@bad.crufty.net>
diff --git a/FILES b/FILES
index d4b5dca..720eb1b 100644
--- a/FILES
+++ b/FILES
@@ -71,6 +71,8 @@ make_malloc.h
makefile.in
meta.c
meta.h
+metachar.c
+metachar.h
missing/sys/cdefs.h
mkdeps.sh
nonints.h
@@ -92,35 +94,76 @@ targ.c
trace.c
trace.h
unit-tests/Makefile.in
-unit-tests/comment
-unit-tests/cond1
-unit-tests/doterror
-unit-tests/dotwait
-unit-tests/error
-unit-tests/export
-unit-tests/export-all
-unit-tests/export-env
-unit-tests/forloop
-unit-tests/forsubst
-unit-tests/hash
-unit-tests/misc
-unit-tests/moderrs
-unit-tests/modmatch
-unit-tests/modmisc
-unit-tests/modorder
-unit-tests/modts
-unit-tests/modword
-unit-tests/order
-unit-tests/phony-end
-unit-tests/posix
-unit-tests/qequals
-unit-tests/sunshcmd
-unit-tests/sysv
-unit-tests/ternary
-unit-tests/test.exp
-unit-tests/unexport
-unit-tests/unexport-env
-unit-tests/varcmd
+unit-tests/comment.exp
+unit-tests/comment.mk
+unit-tests/cond1.exp
+unit-tests/cond1.mk
+unit-tests/cond2.exp
+unit-tests/cond2.mk
+unit-tests/doterror.exp
+unit-tests/doterror.mk
+unit-tests/dotwait.exp
+unit-tests/dotwait.mk
+unit-tests/error.exp
+unit-tests/error.mk
+unit-tests/escape.exp
+unit-tests/escape.mk
+unit-tests/export-all.exp
+unit-tests/export-all.mk
+unit-tests/export-env.exp
+unit-tests/export-env.mk
+unit-tests/export.exp
+unit-tests/export.mk
+unit-tests/forloop.exp
+unit-tests/forloop.mk
+unit-tests/forsubst.exp
+unit-tests/forsubst.mk
+unit-tests/hash.exp
+unit-tests/hash.mk
+unit-tests/impsrc.exp
+unit-tests/impsrc.mk
+unit-tests/misc.exp
+unit-tests/misc.mk
+unit-tests/moderrs.exp
+unit-tests/moderrs.mk
+unit-tests/modmatch.exp
+unit-tests/modmatch.mk
+unit-tests/modmisc.exp
+unit-tests/modmisc.mk
+unit-tests/modorder.exp
+unit-tests/modorder.mk
+unit-tests/modts.exp
+unit-tests/modts.mk
+unit-tests/modword.exp
+unit-tests/modword.mk
+unit-tests/order.exp
+unit-tests/order.mk
+unit-tests/phony-end.exp
+unit-tests/phony-end.mk
+unit-tests/posix.exp
+unit-tests/posix.mk
+unit-tests/posix1.exp
+unit-tests/posix1.mk
+unit-tests/qequals.exp
+unit-tests/qequals.mk
+unit-tests/suffixes.exp
+unit-tests/suffixes.mk
+unit-tests/sunshcmd.exp
+unit-tests/sunshcmd.mk
+unit-tests/sysv.exp
+unit-tests/sysv.mk
+unit-tests/ternary.exp
+unit-tests/ternary.mk
+unit-tests/unexport-env.exp
+unit-tests/unexport-env.mk
+unit-tests/unexport.exp
+unit-tests/unexport.mk
+unit-tests/varcmd.exp
+unit-tests/varcmd.mk
+unit-tests/varmisc.exp
+unit-tests/varmisc.mk
+unit-tests/varshell.exp
+unit-tests/varshell.mk
util.c
var.c
wait.h
diff --git a/Makefile b/Makefile
index 42258c4..d02e734 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
-# $Id: Makefile,v 1.27 2014/06/20 14:51:54 sjg Exp $
+# $Id: Makefile,v 1.53 2016/02/20 01:29:21 sjg Exp $
# Base version on src date
-MAKE_VERSION= 20140620
+MAKE_VERSION= 20160220
PROG= bmake
@@ -18,6 +18,7 @@ SRCS= \
make.c \
make_malloc.c \
meta.c \
+ metachar.c \
parse.c \
str.c \
strlist.c \
@@ -94,7 +95,7 @@ SUBDIR+= unit-tests
# we skip a lot of this when building as part of FreeBSD etc.
# list of OS's which are derrived from BSD4.4
-BSD44_LIST= NetBSD FreeBSD OpenBSD DragonFly
+BSD44_LIST= NetBSD FreeBSD OpenBSD DragonFly MirBSD Bitrig
# we are...
OS!= uname -s
# are we 4.4BSD ?
@@ -180,9 +181,9 @@ COPTS.parse.c += -Wno-format-nonliteral
COPTS.var.c += -Wno-format-nonliteral
# Force these
-SHAREDIR= ${prefix}/share
-BINDIR= ${prefix}/bin
-MANDIR= ${SHAREDIR}/man
+SHAREDIR= ${SHAREDIR.bmake:U${prefix}/share}
+BINDIR= ${BINDIR.bmake:U${prefix}/bin}
+MANDIR= ${MANDIR.bmake:U${SHAREDIR}/man}
.if !exists(.depend)
${OBJS}: config.h
diff --git a/PSD.doc/Makefile b/PSD.doc/Makefile
index 8e1f1fa..67702b8 100644
--- a/PSD.doc/Makefile
+++ b/PSD.doc/Makefile
@@ -1,8 +1,10 @@
-# $NetBSD: Makefile,v 1.2 1995/06/14 15:20:23 christos Exp $
+# $NetBSD: Makefile,v 1.4 2014/07/05 19:22:43 dholland Exp $
# @(#)Makefile 8.1 (Berkeley) 8/14/93
-DIR= psd/12.make
+SECTION=reference/ref1
+ARTICLE=make
SRCS= tutorial.ms
MACROS= -ms
+EXTRAHTMLFILES=make1.png make2.png
.include <bsd.doc.mk>
diff --git a/PSD.doc/tutorial.ms b/PSD.doc/tutorial.ms
index c1a6444..d5c8a7d 100644
--- a/PSD.doc/tutorial.ms
+++ b/PSD.doc/tutorial.ms
@@ -1,4 +1,4 @@
-.\" $NetBSD: tutorial.ms,v 1.11 2011/08/18 15:19:30 sjg Exp $
+.\" $NetBSD: tutorial.ms,v 1.12 2014/09/30 21:33:14 christos Exp $
.\" Copyright (c) 1988, 1989, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
@@ -67,6 +67,16 @@
.\"
.EH 'PSD:12-%''PMake \*- A Tutorial'
.OH 'PMake \*- A Tutorial''PSD:12-%'
+.\" Ix is an indexing macro similar to .IX but I've disabled it for now
+.\" Since that would require 2 passes and I am not in the mood for that.
+.de Ix
+..
+.\" Rd is section (region) define and Rm is region mention? Again disable for
+.\" now.
+.de Rd
+..
+.de Rm
+..
.\" xH is a macro to provide numbered headers that are automatically stuffed
.\" into a table-of-contents, properly indented, etc. If the first argument
.\" is numeric, it is taken as the depth for numbering (as for .NH), else
diff --git a/arch.c b/arch.c
index 943f41e..f613a66 100644
--- a/arch.c
+++ b/arch.c
@@ -1,4 +1,4 @@
-/* $NetBSD: arch.c,v 1.63 2012/06/12 19:21:50 joerg Exp $ */
+/* $NetBSD: arch.c,v 1.68 2016/02/18 18:29:14 christos Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -69,14 +69,14 @@
*/
#ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: arch.c,v 1.63 2012/06/12 19:21:50 joerg Exp $";
+static char rcsid[] = "$NetBSD: arch.c,v 1.68 2016/02/18 18:29:14 christos Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)arch.c 8.2 (Berkeley) 1/2/94";
#else
-__RCSID("$NetBSD: arch.c,v 1.63 2012/06/12 19:21:50 joerg Exp $");
+__RCSID("$NetBSD: arch.c,v 1.68 2016/02/18 18:29:14 christos Exp $");
#endif
#endif /* not lint */
#endif
@@ -136,7 +136,6 @@ __RCSID("$NetBSD: arch.c,v 1.63 2012/06/12 19:21:50 joerg Exp $");
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/param.h>
-#include <ctype.h>
#ifdef HAVE_AR_H
#include <ar.h>
#else
@@ -156,7 +155,6 @@ struct ar_hdr {
#if defined(HAVE_RANLIB_H) && !(defined(__ELF__) || defined(NO_RANLIB))
#include <ranlib.h>
#endif
-#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_UTIME_H
@@ -254,8 +252,7 @@ ArchFree(void *ap)
free(Hash_GetValue(entry));
free(a->name);
- if (a->fnametab)
- free(a->fnametab);
+ free(a->fnametab);
Hash_DeleteTable(&a->members);
free(a);
}
@@ -310,9 +307,10 @@ Arch_ParseArchive(char **linePtr, Lst nodeLst, GNode *ctxt)
void *freeIt;
char *result;
- result = Var_Parse(cp, ctxt, TRUE, &length, &freeIt);
- if (freeIt)
- free(freeIt);
+ result = Var_Parse(cp, ctxt, VARF_UNDEFERR|VARF_WANTRES,
+ &length, &freeIt);
+ free(freeIt);
+
if (result == var_Error) {
return(FAILURE);
} else {
@@ -325,7 +323,7 @@ Arch_ParseArchive(char **linePtr, Lst nodeLst, GNode *ctxt)
*cp++ = '\0';
if (subLibName) {
- libName = Var_Subst(NULL, libName, ctxt, TRUE);
+ libName = Var_Subst(NULL, libName, ctxt, VARF_UNDEFERR|VARF_WANTRES);
}
@@ -351,9 +349,10 @@ Arch_ParseArchive(char **linePtr, Lst nodeLst, GNode *ctxt)
void *freeIt;
char *result;
- result = Var_Parse(cp, ctxt, TRUE, &length, &freeIt);
- if (freeIt)
- free(freeIt);
+ result = Var_Parse(cp, ctxt, VARF_UNDEFERR|VARF_WANTRES,
+ &length, &freeIt);
+ free(freeIt);
+
if (result == var_Error) {
return(FAILURE);
} else {
@@ -404,7 +403,8 @@ Arch_ParseArchive(char **linePtr, Lst nodeLst, GNode *ctxt)
char *oldMemName = memName;
size_t sz;
- memName = Var_Subst(NULL, memName, ctxt, TRUE);
+ memName = Var_Subst(NULL, memName, ctxt,
+ VARF_UNDEFERR|VARF_WANTRES);
/*
* Now form an archive spec and recurse to deal with nested
@@ -759,8 +759,7 @@ ArchStatMember(char *archive, char *member, Boolean hash)
badarch:
fclose(arch);
Hash_DeleteTable(&ar->members);
- if (ar->fnametab)
- free(ar->fnametab);
+ free(ar->fnametab);
free(ar);
return NULL;
}
@@ -1045,10 +1044,10 @@ Arch_Touch(GNode *gn)
arch = ArchFindMember(Var_Value(ARCHIVE, gn, &p1),
Var_Value(MEMBER, gn, &p2),
&arh, "r+");
- if (p1)
- free(p1);
- if (p2)
- free(p2);
+
+ free(p1);
+ free(p2);
+
snprintf(arh.AR_DATE, sizeof(arh.AR_DATE), "%-12ld", (long) now);
if (arch != NULL) {
@@ -1127,10 +1126,9 @@ Arch_MTime(GNode *gn)
arhPtr = ArchStatMember(Var_Value(ARCHIVE, gn, &p1),
Var_Value(MEMBER, gn, &p2),
TRUE);
- if (p1)
- free(p1);
- if (p2)
- free(p2);
+
+ free(p1);
+ free(p2);
if (arhPtr != NULL) {
modTime = (time_t)strtol(arhPtr->AR_DATE, NULL, 10);
diff --git a/bmake.1 b/bmake.1
index 5363e88..04382db 100644
--- a/bmake.1
+++ b/bmake.1
@@ -1,4 +1,4 @@
-.\" $NetBSD: make.1,v 1.229 2014/01/19 10:23:29 apb Exp $
+.\" $NetBSD: make.1,v 1.253 2016/02/20 01:19:03 sjg Exp $
.\"
.\" Copyright (c) 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -29,7 +29,7 @@
.\"
.\" from: @(#)make.1 8.4 (Berkeley) 3/19/94
.\"
-.Dd February 14, 2014
+.Dd February 19, 2016
.Dt MAKE 1
.Os
.Sh NAME
@@ -209,8 +209,6 @@ Force the
option to print raw values of variables.
.It Ar v
Print debugging information about variable assignment.
-.It Ar w
-Print entering and leaving directory messages, pre and post processing.
.It Ar x
Run shell commands with
.Fl x
@@ -352,6 +350,8 @@ contains a
then the value will be expanded before printing.
.It Fl W
Treat any warnings during makefile parsing as errors.
+.It Fl w
+Print entering and leaving directory messages, pre and post processing.
.It Fl X
Don't export variables passed on the command line to the environment
individually.
@@ -441,17 +441,29 @@ The value
need not necessarily be used to describe existing files.
Expansion is in directory order, not alphabetically as done in the shell.
.Sh SHELL COMMANDS
-Each target may have associated with it a series of shell commands, normally
+Each target may have associated with it one or more lines of shell
+commands, normally
used to create the target.
-Each of the commands in this script
+Each of the lines in this script
.Em must
be preceded by a tab.
-While any target may appear on a dependency line, only one of these
-dependencies may be followed by a creation script, unless the
+(For historical reasons, spaces are not accepted.)
+While targets can appear in many dependency lines if desired, by
+default only one of these rules may be followed by a creation
+script.
+If the
.Ql Ic \&::
-operator is used.
+operator is used, however, all rules may include scripts and the
+scripts are executed in the order found.
.Pp
-If the first characters of the command line are any combination of
+Each line is treated as a separate shell command, unless the end of
+line is escaped with a backslash
+.Pq Ql \e
+in which case that line and the next are combined.
+.\" The escaped newline is retained and passed to the shell, which
+.\" normally ignores it.
+.\" However, the tab at the beginning of the following line is removed.
+If the first characters of the command are any combination of
.Ql Ic @ ,
.Ql Ic + ,
or
@@ -469,6 +481,7 @@ This is similar to the effect of the .MAKE special source,
except that the effect can be limited to a single line of a script.
A
.Ql Ic \-
+in compatibility mode
causes any non-zero exit status of the command line to be ignored.
.Pp
When
@@ -477,22 +490,21 @@ is run in jobs mode with
.Fl j Ar max_jobs ,
the entire script for the target is fed to a
single instance of the shell.
-.Pp
In compatibility (non-jobs) mode, each command is run in a separate process.
If the command contains any shell meta characters
.Pq Ql #=|^(){};&<>*?[]:$`\e\en
-it will be passed to the shell, otherwise
+it will be passed to the shell; otherwise
.Nm
will attempt direct execution.
-.Pp
-Since
-.Nm
-will
-.Xr chdir 2
-to
-.Ql Va .OBJDIR
-before executing any targets, each child process
-starts with that as its current working directory.
+If a line starts with
+.Ql Ic \-
+and the shell has ErrCtl enabled then failure of the command line
+will be ignored as in compatibility mode.
+Otherwise
+.Ql Ic \-
+affects the entire job;
+the script will stop at the first command line that fails,
+but the target will not be deemed to have failed.
.Pp
Makefiles should be written so that the mode of
.Nm
@@ -500,20 +512,32 @@ operation does not change their behavior.
For example, any command which needs to use
.Dq cd
or
-.Dq chdir ,
-without side-effect should be put in parenthesis:
+.Dq chdir
+without potentially changing the directory for subsequent commands
+should be put in parentheses so it executes in a subshell.
+To force the use of one shell, escape the line breaks so as to make
+the whole script one command.
+For example:
.Bd -literal -offset indent
-
avoid-chdir-side-effects:
@echo Building $@ in `pwd`
- @(cd ${.CURDIR} && ${.MAKE} $@)
+ @(cd ${.CURDIR} && ${MAKE} $@)
@echo Back in `pwd`
ensure-one-shell-regardless-of-mode:
- @echo Building $@ in `pwd`; \\
- (cd ${.CURDIR} && ${.MAKE} $@); \\
+ @echo Building $@ in `pwd`; \e
+ (cd ${.CURDIR} && ${MAKE} $@); \e
echo Back in `pwd`
.Ed
+.Pp
+Since
+.Nm
+will
+.Xr chdir 2
+to
+.Ql Va .OBJDIR
+before executing any targets, each child process
+starts with that as its current working directory.
.Sh VARIABLE ASSIGNMENTS
Variables in make are much like variables in the shell, and, by tradition,
consist of all upper-case letters.
@@ -624,13 +648,19 @@ Variables defined in the makefile or in included makefiles.
Variables defined as part of the command line.
.It Local variables
Variables that are defined specific to a certain target.
+.El
+.Pp
+Local variables are all built in and their values vary magically from
+target to target.
+It is not currently possible to define new local variables.
The seven local variables are as follows:
-.Bl -tag -width ".ARCHIVE"
+.Bl -tag -width ".ARCHIVE" -offset indent
.It Va .ALLSRC
The list of all sources for this target; also known as
.Ql Va \&\*[Gt] .
.It Va .ARCHIVE
-The name of the archive file.
+The name of the archive file; also known as
+.Ql Va \&! .
.It Va .IMPSRC
In suffix-transformation rules, the name/path of the source from which the
target is to be transformed (the
@@ -639,7 +669,8 @@ source); also known as
.Ql Va \&\*[Lt] .
It is not defined in explicit rules.
.It Va .MEMBER
-The name of the archive member.
+The name of the archive member; also known as
+.Ql Va % .
.It Va .OODATE
The list of sources for this target that were deemed out-of-date; also
known as
@@ -648,31 +679,41 @@ known as
The file prefix of the target, containing only the file portion, no suffix
or preceding directory components; also known as
.Ql Va * .
+The suffix must be one of the known suffixes declared with
+.Ic .SUFFIXES
+or it will not be recognized.
.It Va .TARGET
The name of the target; also known as
.Ql Va @ .
.El
.Pp
The shorter forms
-.Ql Va @ ,
+.Ql ( Va \*[Gt] ,
+.Ql Va \&! ,
+.Ql Va \*[Lt] ,
+.Ql Va % ,
.Ql Va \&? ,
-.Ql Va \&\*[Lt] ,
-.Ql Va \&\*[Gt] ,
+.Ql Va * ,
and
-.Ql Va *
+.Ql Va @ )
are permitted for backward
-compatibility with historical makefiles and are not recommended.
-The six variables
-.Ql Va "@F" ,
-.Ql Va "@D" ,
-.Ql Va "\*[Lt]F" ,
-.Ql Va "\*[Lt]D" ,
-.Ql Va "*F" ,
+compatibility with historical makefiles and legacy POSIX make and are
+not recommended.
+.Pp
+Variants of these variables with the punctuation followed immediately by
+.Ql D
+or
+.Ql F ,
+e.g.
+.Ql Va $(@D) ,
+are legacy forms equivalent to using the
+.Ql :H
and
-.Ql Va "*D"
-are permitted for compatibility with
+.Ql :T
+modifiers.
+These forms are accepted for compatibility with
.At V
-makefiles and are not recommended.
+makefiles and POSIX but are not recommended.
.Pp
Four of the local variables may be used in sources on dependency lines
because they expand to the proper value for each target on the line.
@@ -682,7 +723,6 @@ These variables are
.Ql Va .ARCHIVE ,
and
.Ql Va .MEMBER .
-.El
.Ss Additional built-in variables
In addition,
.Nm
@@ -901,6 +941,19 @@ The process-id of
.It Va .MAKE.PPID
The parent process-id of
.Nm .
+.It Va .MAKE.SAVE_DOLLARS
+value should be a boolen that controls wether
+.Ql $$
+are preserved when doing
+.Ql :=
+assignments.
+The default is false, for backwards compatability.
+Set to true for compatability with other makes.
+If set to false,
+.Ql $$
+becomes
+.Ql $
+per normal evaluation rules.
.It Va MAKE_PRINT_VAR_ON_ERROR
When
.Nm
@@ -953,14 +1006,15 @@ This is especially useful with
.Ql Ev MAKEOBJDIR .
.Pp
.Ql Va .OBJDIR
-may be modified in the makefile as a global variable.
+may be modified in the makefile via the special target
+.Ql Ic .OBJDIR .
In all cases,
.Nm
will
.Xr chdir 2
-to
+to the specified directory if it exists, and set
.Ql Va .OBJDIR
-and set
+and
.Ql Ev PWD
to that directory before executing any targets.
.
@@ -1489,12 +1543,20 @@ For compatibility with other versions of
.Nm
.Ql include file ...
is also accepted.
+.Pp
If the include statement is written as
.Cm .-include
or as
.Cm .sinclude
then errors locating and/or opening include files are ignored.
.Pp
+If the include statement is written as
+.Cm .dinclude
+not only are errors locating and/or opening include files ignored,
+but stale dependencies within the included file will be ignored
+just like
+.Va .MAKE.DEPENDFILE .
+.Pp
Conditional expressions are also preceded by a single dot as the first
character of a line.
The possible conditionals are as follows:
@@ -1530,6 +1592,10 @@ This allows exporting a value to the environment which is different from that
used by
.Nm
internally.
+.It Ic .export-literal Ar variable ...
+The same as
+.Ql .export-env ,
+except that variables in the value are not expanded.
.It Ic .info Ar message
The message is printed along with the name of the makefile and line number.
.It Ic .undef Ar variable
@@ -1961,6 +2027,15 @@ Disable parallel mode.
Synonym for
.Ic .NOTPARALLEL ,
for compatibility with other pmake variants.
+.It Ic .OBJDIR
+The source is a new value for
+.Ql Va .OBJDIR .
+If it exists,
+.Nm
+will
+.Xr chdir 2
+to it and update the value of
+.Ql Va .OBJDIR .
.It Ic .ORDER
The named targets are made in sequence.
This ordering does not add targets to the list of targets to be made.
@@ -2119,19 +2194,87 @@ system makefile
system makefile directory
.El
.Sh COMPATIBILITY
-The basic make syntax is compatible between different versions of make,
+The basic make syntax is compatible between different versions of make;
however the special variables, variable modifiers and conditionals are not.
-.Pp
-The way that parallel makes are scheduled changed in
-NetBSD 4.0
-so that .ORDER and .WAIT apply recursively to the dependent nodes.
-The algorithms used may change again in the future.
+.Ss Older versions
+An incomplete list of changes in older versions of
+.Nm :
.Pp
The way that .for loop variables are substituted changed after
NetBSD 5.0
so that they still appear to be variable expansions.
In particular this stops them being treated as syntax, and removes some
obscure problems using them in .if statements.
+.Pp
+The way that parallel makes are scheduled changed in
+NetBSD 4.0
+so that .ORDER and .WAIT apply recursively to the dependent nodes.
+The algorithms used may change again in the future.
+.Ss Other make dialects
+Other make dialects (GNU make, SVR4 make, POSIX make, etc.) do not
+support most of the features of
+.Nm
+as described in this manual.
+Most notably:
+.Bl -bullet -offset indent
+.It
+The
+.Ic .WAIT
+and
+.Ic .ORDER
+declarations and most functionality pertaining to parallelization.
+(GNU make supports parallelization but lacks these features needed to
+control it effectively.)
+.It
+Directives, including for loops and conditionals and most of the
+forms of include files.
+(GNU make has its own incompatible and less powerful syntax for
+conditionals.)
+.It
+All built-in variables that begin with a dot.
+.It
+Most of the special sources and targets that begin with a dot,
+with the notable exception of
+.Ic .PHONY ,
+.Ic .PRECIOUS ,
+and
+.Ic .SUFFIXES .
+.It
+Variable modifiers, except for the
+.Dl :old=new
+string substitution, which does not portably support globbing with
+.Ql %
+and historically only works on declared suffixes.
+.It
+The
+.Ic $>
+variable even in its short form; most makes support this functionality
+but its name varies.
+.El
+.Pp
+Some features are somewhat more portable, such as assignment with
+.Ic += ,
+.Ic ?= ,
+and
+.Ic != .
+The
+.Ic .PATH
+functionality is based on an older feature
+.Ic VPATH
+found in GNU make and many versions of SVR4 make; however,
+historically its behavior is too ill-defined (and too buggy) to rely
+upon.
+.Pp
+The
+.Ic $@
+and
+.Ic $<
+variables are more or less universally portable, as is the
+.Ic $(MAKE)
+variable.
+Basic use of suffix rules (for files only in the current directory,
+not trying to chain transformations together, etc.) is also reasonably
+portable.
.Sh SEE ALSO
.Xr mkdep 1
.Sh HISTORY
diff --git a/bmake.cat1 b/bmake.cat1
index 0ce26a5..90d2099 100644
--- a/bmake.cat1
+++ b/bmake.cat1
@@ -122,9 +122,6 @@ DDEESSCCRRIIPPTTIIOONN
_v Print debugging information about variable assignment.
- _w Print entering and leaving directory messages, pre and
- post processing.
-
_x Run shell commands with --xx so the actual commands are
printed as they are executed.
@@ -221,6 +218,9 @@ DDEESSCCRRIIPPTTIIOONN
--WW Treat any warnings during makefile parsing as errors.
+ --ww Print entering and leaving directory messages, pre and post pro-
+ cessing.
+
--XX Don't export variables passed on the command line to the environ-
ment individually. Variables passed on the command line are
still exported via the _M_A_K_E_F_L_A_G_S environment variable. This
@@ -273,46 +273,55 @@ FFIILLEE DDEEPPEENNDDEENNCCYY SSPPEECCIIFFIICCAATTIIOO
done in the shell.
SSHHEELLLL CCOOMMMMAANNDDSS
- Each target may have associated with it a series of shell commands, nor-
- mally used to create the target. Each of the commands in this script
- _m_u_s_t be preceded by a tab. While any target may appear on a dependency
- line, only one of these dependencies may be followed by a creation
- script, unless the `::::' operator is used.
-
- If the first characters of the command line are any combination of `@@',
- `++', or `--', the command is treated specially. A `@@' causes the command
- not to be echoed before it is executed. A `++' causes the command to be
- executed even when --nn is given. This is similar to the effect of the
- .MAKE special source, except that the effect can be limited to a single
- line of a script. A `--' causes any non-zero exit status of the command
- line to be ignored.
+ Each target may have associated with it one or more lines of shell com-
+ mands, normally used to create the target. Each of the lines in this
+ script _m_u_s_t be preceded by a tab. (For historical reasons, spaces are
+ not accepted.) While targets can appear in many dependency lines if
+ desired, by default only one of these rules may be followed by a creation
+ script. If the `::::' operator is used, however, all rules may include
+ scripts and the scripts are executed in the order found.
+
+ Each line is treated as a separate shell command, unless the end of line
+ is escaped with a backslash (`\') in which case that line and the next
+ are combined. If the first characters of the command are any combination
+ of `@@', `++', or `--', the command is treated specially. A `@@' causes the
+ command not to be echoed before it is executed. A `++' causes the command
+ to be executed even when --nn is given. This is similar to the effect of
+ the .MAKE special source, except that the effect can be limited to a sin-
+ gle line of a script. A `--' in compatibility mode causes any non-zero
+ exit status of the command line to be ignored.
When bbmmaakkee is run in jobs mode with --jj _m_a_x___j_o_b_s, the entire script for
- the target is fed to a single instance of the shell.
-
- In compatibility (non-jobs) mode, each command is run in a separate
- process. If the command contains any shell meta characters
- (`#=|^(){};&<>*?[]:$`\\n') it will be passed to the shell, otherwise
- bbmmaakkee will attempt direct execution.
-
- Since bbmmaakkee will chdir(2) to `_._O_B_J_D_I_R' before executing any targets, each
- child process starts with that as its current working directory.
+ the target is fed to a single instance of the shell. In compatibility
+ (non-jobs) mode, each command is run in a separate process. If the com-
+ mand contains any shell meta characters (`#=|^(){};&<>*?[]:$`\\n') it
+ will be passed to the shell; otherwise bbmmaakkee will attempt direct execu-
+ tion. If a line starts with `--' and the shell has ErrCtl enabled then
+ failure of the command line will be ignored as in compatibility mode.
+ Otherwise `--' affects the entire job; the script will stop at the first
+ command line that fails, but the target will not be deemed to have
+ failed.
Makefiles should be written so that the mode of bbmmaakkee operation does not
change their behavior. For example, any command which needs to use
- ``cd'' or ``chdir'', without side-effect should be put in parenthesis:
-
+ ``cd'' or ``chdir'' without potentially changing the directory for subse-
+ quent commands should be put in parentheses so it executes in a subshell.
+ To force the use of one shell, escape the line breaks so as to make the
+ whole script one command. For example:
avoid-chdir-side-effects:
@echo Building $@ in `pwd`
- @(cd ${.CURDIR} && ${.MAKE} $@)
+ @(cd ${.CURDIR} && ${MAKE} $@)
@echo Back in `pwd`
ensure-one-shell-regardless-of-mode:
@echo Building $@ in `pwd`; \
- (cd ${.CURDIR} && ${.MAKE} $@); \
+ (cd ${.CURDIR} && ${MAKE} $@); \
echo Back in `pwd`
+ Since bbmmaakkee will chdir(2) to `_._O_B_J_D_I_R' before executing any targets, each
+ child process starts with that as its current working directory.
+
VVAARRIIAABBLLEE AASSSSIIGGNNMMEENNTTSS
Variables in make are much like variables in the shell, and, by tradi-
tion, consist of all upper-case letters.
@@ -402,40 +411,47 @@ VVAARRIIAABBLLEE AASSSSIIGGNNMMEENNTTSS
Variables defined as part of the command line.
Local variables
- Variables that are defined specific to a certain target. The
- seven local variables are as follows:
+ Variables that are defined specific to a certain target.
+
+ Local variables are all built in and their values vary magically from
+ target to target. It is not currently possible to define new local vari-
+ ables. The seven local variables are as follows:
- _._A_L_L_S_R_C The list of all sources for this target; also known as
- `_>'.
+ _._A_L_L_S_R_C The list of all sources for this target; also known as
+ `_>'.
- _._A_R_C_H_I_V_E The name of the archive file.
+ _._A_R_C_H_I_V_E The name of the archive file; also known as `_!'.
- _._I_M_P_S_R_C In suffix-transformation rules, the name/path of the
- source from which the target is to be transformed (the
- ``implied'' source); also known as `_<'. It is not
- defined in explicit rules.
+ _._I_M_P_S_R_C In suffix-transformation rules, the name/path of the
+ source from which the target is to be transformed (the
+ ``implied'' source); also known as `_<'. It is not
+ defined in explicit rules.
- _._M_E_M_B_E_R The name of the archive member.
+ _._M_E_M_B_E_R The name of the archive member; also known as `_%'.
- _._O_O_D_A_T_E The list of sources for this target that were deemed
- out-of-date; also known as `_?'.
+ _._O_O_D_A_T_E The list of sources for this target that were deemed out-
+ of-date; also known as `_?'.
- _._P_R_E_F_I_X The file prefix of the target, containing only the file
- portion, no suffix or preceding directory components;
- also known as `_*'.
+ _._P_R_E_F_I_X The file prefix of the target, containing only the file
+ portion, no suffix or preceding directory components;
+ also known as `_*'. The suffix must be one of the known
+ suffixes declared with ..SSUUFFFFIIXXEESS or it will not be recog-
+ nized.
- _._T_A_R_G_E_T The name of the target; also known as `_@'.
+ _._T_A_R_G_E_T The name of the target; also known as `_@'.
- The shorter forms `_@', `_?', `_<', `_>', and `_*' are permitted for
- backward compatibility with historical makefiles and are not rec-
- ommended. The six variables `_@_F', `_@_D', `_<_F', `_<_D', `_*_F', and
- `_*_D' are permitted for compatibility with AT&T System V UNIX
- makefiles and are not recommended.
+ The shorter forms (`_>', `_!', `_<', `_%', `_?', `_*', and `_@') are permitted
+ for backward compatibility with historical makefiles and legacy POSIX
+ make and are not recommended.
- Four of the local variables may be used in sources on dependency
- lines because they expand to the proper value for each target on
- the line. These variables are `_._T_A_R_G_E_T', `_._P_R_E_F_I_X', `_._A_R_C_H_I_V_E',
- and `_._M_E_M_B_E_R'.
+ Variants of these variables with the punctuation followed immediately by
+ `D' or `F', e.g. `_$_(_@_D_)', are legacy forms equivalent to using the `:H'
+ and `:T' modifiers. These forms are accepted for compatibility with AT&T
+ System V UNIX makefiles and POSIX but are not recommended.
+
+ Four of the local variables may be used in sources on dependency lines
+ because they expand to the proper value for each target on the line.
+ These variables are `_._T_A_R_G_E_T', `_._P_R_E_F_I_X', `_._A_R_C_H_I_V_E', and `_._M_E_M_B_E_R'.
AAddddiittiioonnaall bbuuiilltt--iinn vvaarriiaabblleess
In addition, bbmmaakkee sets or knows about the following variables:
@@ -591,6 +607,13 @@ VVAARRIIAABBLLEE AASSSSIIGGNNMMEENNTTSS
_._M_A_K_E_._P_P_I_D The parent process-id of bbmmaakkee.
+ _._M_A_K_E_._S_A_V_E___D_O_L_L_A_R_S
+ value should be a boolen that controls wether `$$' are
+ preserved when doing `:=' assignments. The default is
+ false, for backwards compatability. Set to true for com-
+ patability with other makes. If set to false, `$$'
+ becomes `$' per normal evaluation rules.
+
_M_A_K_E___P_R_I_N_T___V_A_R___O_N___E_R_R_O_R
When bbmmaakkee stops due to an error, it prints its name and
the value of `_._C_U_R_D_I_R' as well as the value of any vari-
@@ -631,10 +654,10 @@ VVAARRIIAABBLLEE AASSSSIIGGNNMMEENNTTSS
may be used. This is especially useful with
`MAKEOBJDIR'.
- `_._O_B_J_D_I_R' may be modified in the makefile as a global
- variable. In all cases, bbmmaakkee will chdir(2) to `_._O_B_J_D_I_R'
- and set `PWD' to that directory before executing any tar-
- gets.
+ `_._O_B_J_D_I_R' may be modified in the makefile via the special
+ target `..OOBBJJDDIIRR'. In all cases, bbmmaakkee will chdir(2) to
+ the specified directory if it exists, and set `_._O_B_J_D_I_R'
+ and `PWD' to that directory before executing any targets.
_._P_A_R_S_E_D_I_R A path to the directory of the current `_M_a_k_e_f_i_l_e' being
parsed.
@@ -941,8 +964,14 @@ IINNCCLLUUDDEE SSTTAATTEEMMEENNTTSS,, CCOONNDDIITTIIOO
used, the including makefile's directory and any directories specified
using the --II option are searched before the system makefile directory.
For compatibility with other versions of bbmmaakkee `include file ...' is also
- accepted. If the include statement is written as ..--iinncclluuddee or as
- ..ssiinncclluuddee then errors locating and/or opening include files are ignored.
+ accepted.
+
+ If the include statement is written as ..--iinncclluuddee or as ..ssiinncclluuddee then
+ errors locating and/or opening include files are ignored.
+
+ If the include statement is written as ..ddiinncclluuddee not only are errors
+ locating and/or opening include files ignored, but stale dependencies
+ within the included file will be ignored just like _._M_A_K_E_._D_E_P_E_N_D_F_I_L_E.
Conditional expressions are also preceded by a single dot as the first
character of a line. The possible conditionals are as follows:
@@ -966,6 +995,10 @@ IINNCCLLUUDDEE SSTTAATTEEMMEENNTTSS,, CCOONNDDIITTIIOO
to _._M_A_K_E_._E_X_P_O_R_T_E_D. This allows exporting a value to the environ-
ment which is different from that used by bbmmaakkee internally.
+ ..eexxppoorrtt--lliitteerraall _v_a_r_i_a_b_l_e _._._.
+ The same as `.export-env', except that variables in the value are
+ not expanded.
+
..iinnffoo _m_e_s_s_a_g_e
The message is printed along with the name of the makefile and
line number.
@@ -1255,6 +1288,9 @@ SSPPEECCIIAALL TTAARRGGEETTSS
Synonym for ..NNOOTTPPAARRAALLLLEELL, for compatibility with other pmake
variants.
+ ..OOBBJJDDIIRR The source is a new value for `_._O_B_J_D_I_R'. If it exists, bbmmaakkee
+ will chdir(2) to it and update the value of `_._O_B_J_D_I_R'.
+
..OORRDDEERR The named targets are made in sequence. This ordering does not
add targets to the list of targets to be made. Since the depen-
dents of a target do not get built until the target itself could
@@ -1356,19 +1392,58 @@ FFIILLEESS
/usr/share/mk system makefile directory
CCOOMMPPAATTIIBBIILLIITTYY
- The basic make syntax is compatible between different versions of make,
+ The basic make syntax is compatible between different versions of make;
however the special variables, variable modifiers and conditionals are
not.
- The way that parallel makes are scheduled changed in NetBSD 4.0 so that
- .ORDER and .WAIT apply recursively to the dependent nodes. The algo-
- rithms used may change again in the future.
+ OOllddeerr vveerrssiioonnss
+ An incomplete list of changes in older versions of bbmmaakkee:
The way that .for loop variables are substituted changed after NetBSD 5.0
so that they still appear to be variable expansions. In particular this
stops them being treated as syntax, and removes some obscure problems
using them in .if statements.
+ The way that parallel makes are scheduled changed in NetBSD 4.0 so that
+ .ORDER and .WAIT apply recursively to the dependent nodes. The algo-
+ rithms used may change again in the future.
+
+ OOtthheerr mmaakkee ddiiaalleeccttss
+ Other make dialects (GNU make, SVR4 make, POSIX make, etc.) do not sup-
+ port most of the features of bbmmaakkee as described in this manual. Most
+ notably:
+
+ ++oo The ..WWAAIITT and ..OORRDDEERR declarations and most functionality per-
+ taining to parallelization. (GNU make supports parallelization
+ but lacks these features needed to control it effectively.)
+
+ ++oo Directives, including for loops and conditionals and most of
+ the forms of include files. (GNU make has its own incompatible
+ and less powerful syntax for conditionals.)
+
+ ++oo All built-in variables that begin with a dot.
+
+ ++oo Most of the special sources and targets that begin with a dot,
+ with the notable exception of ..PPHHOONNYY, ..PPRREECCIIOOUUSS, and ..SSUUFFFFIIXXEESS.
+
+ ++oo Variable modifiers, except for the
+ :old=new
+ string substitution, which does not portably support globbing
+ with `%' and historically only works on declared suffixes.
+
+ ++oo The $$>> variable even in its short form; most makes support this
+ functionality but its name varies.
+
+ Some features are somewhat more portable, such as assignment with ++==, ??==,
+ and !!==. The ..PPAATTHH functionality is based on an older feature VVPPAATTHH found
+ in GNU make and many versions of SVR4 make; however, historically its
+ behavior is too ill-defined (and too buggy) to rely upon.
+
+ The $$@@ and $$<< variables are more or less universally portable, as is the
+ $$((MMAAKKEE)) variable. Basic use of suffix rules (for files only in the cur-
+ rent directory, not trying to chain transformations together, etc.) is
+ also reasonably portable.
+
SSEEEE AALLSSOO
mkdep(1)
@@ -1394,4 +1469,4 @@ BBUUGGSS
There is no way of escaping a space character in a filename.
-NetBSD 5.1 February 14, 2014 NetBSD 5.1
+NetBSD 5.1 February 19, 2016 NetBSD 5.1
diff --git a/boot-strap b/boot-strap
index 340c46a..a49ffb1 100755
--- a/boot-strap
+++ b/boot-strap
@@ -111,7 +111,7 @@
# Simon J. Gerraty <sjg@crufty.net>
# RCSid:
-# $Id: boot-strap,v 1.45 2014/04/05 22:56:54 sjg Exp $
+# $Id: boot-strap,v 1.48 2015/10/25 05:20:48 sjg Exp $
#
# @(#) Copyright (c) 2001 Simon J. Gerraty
#
@@ -395,8 +395,15 @@ Bmake() {
)
}
+# there is actually a shell where type is not a builtin
+# if type is missing, which(1) had better exists!
+if (type cat) > /dev/null 2>&1; then
+which() {
+ type "$@" | sed 's,[()],,g;s,^[^/][^/]*,,;q'
+}
+fi
# make sure test below uses the same diff that configure did
-TOOL_DIFF=`type diff | sed 's,[()],,g;s,^[^/][^/]*,,;q'`
+TOOL_DIFF=`which diff`
export TOOL_DIFF
op_configure() {
diff --git a/compat.c b/compat.c
index 97fcfe4..475c59d 100644
--- a/compat.c
+++ b/compat.c
@@ -1,4 +1,4 @@
-/* $NetBSD: compat.c,v 1.94 2014/01/03 00:02:01 sjg Exp $ */
+/* $NetBSD: compat.c,v 1.104 2016/02/18 18:29:14 christos Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -70,14 +70,14 @@
*/
#ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: compat.c,v 1.94 2014/01/03 00:02:01 sjg Exp $";
+static char rcsid[] = "$NetBSD: compat.c,v 1.104 2016/02/18 18:29:14 christos Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)compat.c 8.2 (Berkeley) 3/19/94";
#else
-__RCSID("$NetBSD: compat.c,v 1.94 2014/01/03 00:02:01 sjg Exp $");
+__RCSID("$NetBSD: compat.c,v 1.104 2016/02/18 18:29:14 christos Exp $");
#endif
#endif /* not lint */
#endif
@@ -111,37 +111,14 @@ __RCSID("$NetBSD: compat.c,v 1.94 2014/01/03 00:02:01 sjg Exp $");
#include "hash.h"
#include "dir.h"
#include "job.h"
+#include "metachar.h"
#include "pathnames.h"
-/*
- * The following array is used to make a fast determination of which
- * characters are interpreted specially by the shell. If a command
- * contains any of these characters, it is executed by the shell, not
- * directly by us.
- */
-
-static char meta[256];
static GNode *curTarg = NULL;
static GNode *ENDNode;
static void CompatInterrupt(int);
-static void
-Compat_Init(void)
-{
- const char *cp;
-
- Shell_Init(); /* setup default shell */
-
- for (cp = "~#=|^(){};&<>*?[]:$`\\\n"; *cp != '\0'; cp++) {
- meta[(unsigned char) *cp] = 1;
- }
- /*
- * The null character serves as a sentinel in the string.
- */
- meta[0] = 1;
-}
-
/*-
*-----------------------------------------------------------------------
* CompatInterrupt --
@@ -169,8 +146,8 @@ CompatInterrupt(int signo)
if (!noExecute && eunlink(file) != -1) {
Error("*** %s removed", file);
}
- if (p1)
- free(p1);
+
+ free(p1);
/*
* Run .INTERRUPT only if hit with interrupt signal
@@ -236,7 +213,7 @@ CompatRunCommand(void *cmdp, void *gnp)
doIt = FALSE;
cmdNode = Lst_Member(gn->commands, cmd);
- cmdStart = Var_Subst(NULL, cmd, gn, FALSE);
+ cmdStart = Var_Subst(NULL, cmd, gn, VARF_WANTRES);
/*
* brk_string will return an argv with a NULL in av[0], thus causing
@@ -271,8 +248,8 @@ CompatRunCommand(void *cmdp, void *gnp)
break;
case '+':
doIt = TRUE;
- if (!meta[0]) /* we came here from jobs */
- Compat_Init();
+ if (!shellName) /* we came here from jobs */
+ Shell_Init();
break;
}
cmd++;
@@ -300,11 +277,13 @@ CompatRunCommand(void *cmdp, void *gnp)
* Search for meta characters in the command. If there are no meta
* characters, there's no need to execute a shell to execute the
* command.
+ *
+ * Additionally variable assignments and empty commands
+ * go to the shell. Therefore treat '=' and ':' like shell
+ * meta characters as documented in make(1).
*/
- for (cp = cmd; !meta[(unsigned char)*cp]; cp++) {
- continue;
- }
- useShell = (*cp != '\0');
+
+ useShell = needshell(cmd, FALSE);
#endif
/*
@@ -395,10 +374,10 @@ again:
execError("exec", av[0]);
_exit(1);
}
- if (mav)
- free(mav);
- if (bp)
- free(bp);
+
+ free(mav);
+ free(bp);
+
Lst_Replace(cmdNode, NULL);
#ifdef USE_META
@@ -512,8 +491,8 @@ Compat_Make(void *gnp, void *pgnp)
GNode *gn = (GNode *)gnp;
GNode *pgn = (GNode *)pgnp;
- if (!meta[0]) /* we came here from jobs */
- Compat_Init();
+ if (!shellName) /* we came here from jobs */
+ Shell_Init();
if (gn->made == UNMADE && (gn == pgn || (pgn->type & OP_MADE) == 0)) {
/*
* First mark ourselves to be made, then apply whatever transformations
@@ -537,8 +516,7 @@ Compat_Make(void *gnp, void *pgnp)
if (Lst_Member(gn->iParents, pgn) != NULL) {
char *p1;
Var_Set(IMPSRC, Var_Value(TARGET, gn, &p1), pgn, 0);
- if (p1)
- free(p1);
+ free(p1);
}
/*
@@ -641,8 +619,7 @@ Compat_Make(void *gnp, void *pgnp)
if (Lst_Member(gn->iParents, pgn) != NULL) {
char *p1;
Var_Set(IMPSRC, Var_Value(TARGET, gn, &p1), pgn, 0);
- if (p1)
- free(p1);
+ free(p1);
}
switch(gn->made) {
case BEINGMADE:
@@ -693,7 +670,8 @@ Compat_Run(Lst targs)
GNode *gn = NULL;/* Current root target */
int errors; /* Number of targets not remade due to errors */
- Compat_Init();
+ if (!shellName)
+ Shell_Init();
if (bmake_signal(SIGINT, SIG_IGN) != SIG_IGN) {
bmake_signal(SIGINT, CompatInterrupt);
diff --git a/cond.c b/cond.c
index a1c6705..cf0107b 100644
--- a/cond.c
+++ b/cond.c
@@ -1,4 +1,4 @@
-/* $NetBSD: cond.c,v 1.67 2012/11/03 13:59:27 christos Exp $ */
+/* $NetBSD: cond.c,v 1.74 2016/02/18 18:29:14 christos Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -70,14 +70,14 @@
*/
#ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: cond.c,v 1.67 2012/11/03 13:59:27 christos Exp $";
+static char rcsid[] = "$NetBSD: cond.c,v 1.74 2016/02/18 18:29:14 christos Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)cond.c 8.2 (Berkeley) 1/2/94";
#else
-__RCSID("$NetBSD: cond.c,v 1.67 2012/11/03 13:59:27 christos Exp $");
+__RCSID("$NetBSD: cond.c,v 1.74 2016/02/18 18:29:14 christos Exp $");
#endif
#endif /* not lint */
#endif
@@ -181,6 +181,15 @@ static Token condPushBack=TOK_NONE; /* Single push-back token used in
static unsigned int cond_depth = 0; /* current .if nesting level */
static unsigned int cond_min_depth = 0; /* depth at makefile open */
+/*
+ * Indicate when we should be strict about lhs of comparisons.
+ * TRUE when Cond_EvalExpression is called from Cond_Eval (.if etc)
+ * FALSE when Cond_EvalExpression is called from var.c:ApplyModifiers
+ * since lhs is already expanded and we cannot tell if
+ * it was a variable reference or not.
+ */
+static Boolean lhsStrict;
+
static int
istoken(const char *str, const char *tok, size_t len)
{
@@ -280,10 +289,10 @@ CondGetArg(char **linePtr, char **argPtr, const char *func)
int len;
void *freeIt;
- cp2 = Var_Parse(cp, VAR_CMD, TRUE, &len, &freeIt);
+ cp2 = Var_Parse(cp, VAR_CMD, VARF_UNDEFERR|VARF_WANTRES,
+ &len, &freeIt);
Buf_AddBytes(&buf, strlen(cp2), cp2);
- if (freeIt)
- free(freeIt);
+ free(freeIt);
cp += len;
continue;
}
@@ -337,8 +346,8 @@ CondDoDefined(int argLen MAKE_ATTR_UNUSED, const char *arg)
} else {
result = FALSE;
}
- if (p1)
- free(p1);
+
+ free(p1);
return (result);
}
@@ -481,6 +490,10 @@ CondCvtArg(char *str, double *value)
double d_val;
errno = 0;
+ if (!*str) {
+ *value = (double)0;
+ return TRUE;
+ }
l_val = strtoul(str, &eptr, str[1] == 'x' ? 16 : 10);
ech = *eptr;
if (ech == 0 && errno != ERANGE) {
@@ -517,7 +530,7 @@ CondCvtArg(char *str, double *value)
*/
/* coverity:[+alloc : arg-*2] */
static char *
-CondGetString(Boolean doEval, Boolean *quoted, void **freeIt)
+CondGetString(Boolean doEval, Boolean *quoted, void **freeIt, Boolean strictLHS)
{
Buffer buf;
char *cp;
@@ -561,8 +574,9 @@ CondGetString(Boolean doEval, Boolean *quoted, void **freeIt)
break;
case '$':
/* if we are in quotes, then an undefined variable is ok */
- str = Var_Parse(condExpr, VAR_CMD, (qt ? 0 : doEval),
- &len, freeIt);
+ str = Var_Parse(condExpr, VAR_CMD,
+ ((!qt && doEval) ? VARF_UNDEFERR : 0) |
+ VARF_WANTRES, &len, freeIt);
if (str == var_Error) {
if (*freeIt) {
free(*freeIt);
@@ -601,6 +615,16 @@ CondGetString(Boolean doEval, Boolean *quoted, void **freeIt)
condExpr--; /* don't skip over next char */
break;
default:
+ if (strictLHS && !qt && *start != '$' &&
+ !isdigit((unsigned char) *start)) {
+ /* lhs must be quoted, a variable reference or number */
+ if (*freeIt) {
+ free(*freeIt);
+ *freeIt = NULL;
+ }
+ str = NULL;
+ goto cleanup;
+ }
Buf_AddByte(&buf, *condExpr);
break;
}
@@ -648,7 +672,7 @@ compare_expression(Boolean doEval)
* Parse the variable spec and skip over it, saving its
* value in lhs.
*/
- lhs = CondGetString(doEval, &lhsQuoted, &lhsFree);
+ lhs = CondGetString(doEval, &lhsQuoted, &lhsFree, lhsStrict);
if (!lhs)
goto done;
@@ -709,7 +733,7 @@ compare_expression(Boolean doEval)
goto done;
}
- rhs = CondGetString(doEval, &rhsQuoted, &rhsFree);
+ rhs = CondGetString(doEval, &rhsQuoted, &rhsFree, FALSE);
if (!rhs)
goto done;
@@ -782,10 +806,8 @@ do_string_compare:
}
done:
- if (lhsFree)
- free(lhsFree);
- if (rhsFree)
- free(rhsFree);
+ free(lhsFree);
+ free(rhsFree);
return t;
}
@@ -804,7 +826,7 @@ get_mpt_arg(char **linePtr, char **argPtr, const char *func MAKE_ATTR_UNUSED)
/* We do all the work here and return the result as the length */
*argPtr = NULL;
- val = Var_Parse(cp - 1, VAR_CMD, FALSE, &length, &freeIt);
+ val = Var_Parse(cp - 1, VAR_CMD, VARF_WANTRES, &length, &freeIt);
/*
* Advance *linePtr to beyond the closing ). Note that
* we subtract one because 'length' is calculated from 'cp - 1'.
@@ -825,8 +847,7 @@ get_mpt_arg(char **linePtr, char **argPtr, const char *func MAKE_ATTR_UNUSED)
* true/false here.
*/
length = *val ? 2 : 1;
- if (freeIt)
- free(freeIt);
+ free(freeIt);
return length;
}
@@ -877,8 +898,7 @@ compare_function(Boolean doEval)
}
/* Evaluate the argument using the required function. */
t = !doEval || fn_def->fn_proc(arglen, arg);
- if (arg)
- free(arg);
+ free(arg);
condExpr = cp;
return t;
}
@@ -910,8 +930,7 @@ compare_function(Boolean doEval)
* be empty - even if it contained a variable expansion.
*/
t = !doEval || if_info->defProc(arglen, arg) != if_info->doNot;
- if (arg)
- free(arg);
+ free(arg);
return t;
}
@@ -1135,7 +1154,7 @@ CondE(Boolean doEval)
*-----------------------------------------------------------------------
*/
int
-Cond_EvalExpression(const struct If *info, char *line, Boolean *value, int eprint)
+Cond_EvalExpression(const struct If *info, char *line, Boolean *value, int eprint, Boolean strictLHS)
{
static const struct If *dflt_info;
const struct If *sv_if_info = if_info;
@@ -1143,6 +1162,8 @@ Cond_EvalExpression(const struct If *info, char *line, Boolean *value, int eprin
Token sv_condPushBack = condPushBack;
int rval;
+ lhsStrict = strictLHS;
+
while (*line == ' ' || *line == '\t')
line++;
@@ -1359,7 +1380,7 @@ Cond_Eval(char *line)
}
/* And evaluate the conditional expresssion */
- if (Cond_EvalExpression(ifp, line, &value, 1) == COND_INVALID) {
+ if (Cond_EvalExpression(ifp, line, &value, 1, TRUE) == COND_INVALID) {
/* Syntax error in conditional, error message already output. */
/* Skip everything to matching .endif */
cond_state[cond_depth] = SKIP_TO_ELSE;
diff --git a/config.h.in b/config.h.in
index ce30da1..ce1700d 100644
--- a/config.h.in
+++ b/config.h.in
@@ -59,6 +59,12 @@
/* Define to 1 if you have the `killpg' function. */
#undef HAVE_KILLPG
+/* Define to 1 if you have the <libgen.h> header file. */
+#undef HAVE_LIBGEN_H
+
+/* Define to 1 if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
@@ -158,6 +164,9 @@
*/
#undef HAVE_SYS_NDIR_H
+/* Define to 1 if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
/* Define to 1 if you have the <sys/select.h> header file. */
#undef HAVE_SYS_SELECT_H
@@ -304,6 +313,11 @@
/* Define to 1 if you need to in order for `stat' and other things to work. */
#undef _POSIX_SOURCE
+/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
+ <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
+ #define below would cause a syntax error. */
+#undef _UINT32_T
+
/* C99 function name */
#undef __func__
@@ -319,5 +333,9 @@
/* Define to `unsigned int' if <sys/types.h> does not define. */
#undef size_t
+/* Define to the type of an unsigned integer type of width exactly 32 bits if
+ such a type exists and the standard includes do not define it. */
+#undef uint32_t
+
/* Define as `fork' if `vfork' does not work. */
#undef vfork
diff --git a/configure b/configure
index e3ff4de..946b8da 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.64 for bmake 20140214.
+# Generated by GNU Autoconf 2.64 for bmake 20151022.
#
# Report bugs to <sjg@NetBSD.org>.
#
@@ -549,8 +549,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='bmake'
PACKAGE_TARNAME='bmake'
-PACKAGE_VERSION='20140214'
-PACKAGE_STRING='bmake 20140214'
+PACKAGE_VERSION='20151022'
+PACKAGE_STRING='bmake 20151022'
PACKAGE_BUGREPORT='sjg@NetBSD.org'
PACKAGE_URL=''
@@ -1221,7 +1221,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures bmake 20140214 to adapt to many kinds of systems.
+\`configure' configures bmake 20151022 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1282,7 +1282,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of bmake 20140214:";;
+ short | recursive ) echo "Configuration of bmake 20151022:";;
esac
cat <<\_ACEOF
@@ -1387,7 +1387,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-bmake configure 20140214
+bmake configure 20151022
generated by GNU Autoconf 2.64
Copyright (C) 2009 Free Software Foundation, Inc.
@@ -1742,6 +1742,58 @@ $as_echo "$ac_res" >&6; }
} # ac_fn_c_check_type
+# ac_fn_c_find_uintX_t LINENO BITS VAR
+# ------------------------------------
+# Finds an unsigned integer type with width BITS, setting cache variable VAR
+# accordingly.
+ac_fn_c_find_uintX_t ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uint$2_t" >&5
+$as_echo_n "checking for uint$2_t... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=no"
+ for ac_type in uint$2_t 'unsigned int' 'unsigned long int' \
+ 'unsigned long long int' 'unsigned short int' 'unsigned char'; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(($ac_type) -1 >> ($2 - 1) == 1)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ case $ac_type in #(
+ uint$2_t) :
+ eval "$3=yes" ;; #(
+ *) :
+ eval "$3=\$ac_type" ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ eval as_val=\$$3
+ if test "x$as_val" = x""no; then :
+
+else
+ break
+fi
+ done
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_find_uintX_t
+
# ac_fn_c_check_decl LINENO SYMBOL VAR
# ------------------------------------
# Tests whether SYMBOL is declared, setting cache variable VAR accordingly.
@@ -1908,7 +1960,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by bmake $as_me 20140214, which was
+It was created by bmake $as_me 20151022, which was
generated by GNU Autoconf 2.64. Invocation command line was
$ $0 $@
@@ -4247,6 +4299,8 @@ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
if test -x /usr/bin/getconf; then
bmake_path_max=`getconf PATH_MAX / 2> /dev/null`
+ # only a numeric response is useful
+ test ${bmake_path_max:-0} -gt 0 2> /dev/null || bmake_path_max=
fi
bmake_path_max=${bmake_path_max:-1024}
if test $bmake_path_max -gt 1024; then
@@ -4567,10 +4621,41 @@ fi
fi
+for ac_header in sys/param.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "sys/param.h" "ac_cv_header_sys_param_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_param_h" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_PARAM_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in sys/sysctl.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "sys/sysctl.h" "ac_cv_header_sys_sysctl_h" "#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+# endif
+
+"
+if test "x$ac_cv_header_sys_sysctl_h" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_SYSCTL_H 1
+_ACEOF
+
+fi
+
+done
+
+
for ac_header in \
ar.h \
err.h \
fcntl.h \
+ libgen.h \
+ limits.h \
paths.h \
poll.h \
ranlib.h \
@@ -4578,7 +4663,6 @@ for ac_header in \
sys/mman.h \
sys/select.h \
sys/socket.h \
- sys/sysctl.h \
sys/time.h \
sys/uio.h \
unistd.h \
@@ -5004,6 +5088,20 @@ _ACEOF
fi
+ac_fn_c_find_uintX_t "$LINENO" "32" "ac_cv_c_uint32_t"
+case $ac_cv_c_uint32_t in #(
+ no|yes) ;; #(
+ *)
+
+$as_echo "#define _UINT32_T 1" >>confdefs.h
+
+
+cat >>confdefs.h <<_ACEOF
+#define uint32_t $ac_cv_c_uint32_t
+_ACEOF
+;;
+ esac
+
ac_fn_c_check_decl "$LINENO" "sys_siglist" "ac_cv_have_decl_sys_siglist" "#include <signal.h>
/* NetBSD declares sys_siglist in unistd.h. */
#ifdef HAVE_UNISTD_H
@@ -6404,7 +6502,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by bmake $as_me 20140214, which was
+This file was extended by bmake $as_me 20151022, which was
generated by GNU Autoconf 2.64. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -6464,7 +6562,7 @@ Report bugs to <sjg@NetBSD.org>."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_version="\\
-bmake config.status 20140214
+bmake config.status 20151022
configured by $0, generated by GNU Autoconf 2.64,
with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
diff --git a/configure.in b/configure.in
index ecaa53a..c4b6808 100644
--- a/configure.in
+++ b/configure.in
@@ -1,11 +1,11 @@
dnl
dnl RCSid:
-dnl $Id: configure.in,v 1.52 2014/02/15 22:27:59 sjg Exp $
+dnl $Id: configure.in,v 1.56 2015/10/25 05:20:48 sjg Exp $
dnl
dnl Process this file with autoconf to produce a configure script
dnl
AC_PREREQ(2.50)
-AC_INIT([bmake], [20140214], [sjg@NetBSD.org])
+AC_INIT([bmake], [20151022], [sjg@NetBSD.org])
AC_CONFIG_HEADERS(config.h)
dnl make srcdir absolute
@@ -82,6 +82,8 @@ dnl
dnl Hurd refuses to define PATH_MAX or MAXPATHLEN
if test -x /usr/bin/getconf; then
bmake_path_max=`getconf PATH_MAX / 2> /dev/null`
+ # only a numeric response is useful
+ test ${bmake_path_max:-0} -gt 0 2> /dev/null || bmake_path_max=
fi
bmake_path_max=${bmake_path_max:-1024}
if test $bmake_path_max -gt 1024; then
@@ -99,10 +101,20 @@ AC_HEADER_STDC
AC_HEADER_SYS_WAIT
AC_HEADER_DIRENT
dnl Keep this list sorted
+AC_CHECK_HEADERS(sys/param.h)
+dnl On BSDi at least we really need sys/param.h for sys/sysctl.h
+AC_CHECK_HEADERS([sys/sysctl.h], [], [],
+[#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+# endif
+])
+
AC_CHECK_HEADERS( \
ar.h \
err.h \
fcntl.h \
+ libgen.h \
+ limits.h \
paths.h \
poll.h \
ranlib.h \
@@ -110,7 +122,6 @@ AC_CHECK_HEADERS( \
sys/mman.h \
sys/select.h \
sys/socket.h \
- sys/sysctl.h \
sys/time.h \
sys/uio.h \
unistd.h \
@@ -140,6 +151,7 @@ AC_C_CONST
AC_TYPE_OFF_T
AC_TYPE_PID_T
AC_TYPE_SIZE_T
+AC_TYPE_UINT32_T
AC_DECL_SYS_SIGLIST
AC_HEADER_TIME
AC_STRUCT_TM
diff --git a/dirname.c b/dirname.c
index 8b6b6c3..154593b 100644
--- a/dirname.c
+++ b/dirname.c
@@ -1,4 +1,4 @@
-/* $NetBSD: dirname.c,v 1.11 2009/11/24 13:34:20 tnozaki Exp $ */
+/* $NetBSD: dirname.c,v 1.13 2014/07/16 10:52:26 christos Exp $ */
/*-
* Copyright (c) 1997, 2002 The NetBSD Foundation, Inc.
@@ -35,7 +35,10 @@
#ifndef HAVE_DIRNAME
#include <sys/cdefs.h>
-
+#include <sys/param.h>
+#ifdef HAVE_LIBGEN_H
+#include <libgen.h>
+#endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
@@ -45,51 +48,73 @@
#ifndef PATH_MAX
# define PATH_MAX 1024
#endif
+#ifndef MIN
+# define MIN(a, b) ((a < b) ? a : b)
+#endif
-char *
-dirname(char *path)
+
+static size_t
+xdirname_r(const char *path, char *buf, size_t buflen)
{
- static char result[PATH_MAX];
- const char *lastp;
+ const char *endp;
size_t len;
/*
* If `path' is a null pointer or points to an empty string,
* return a pointer to the string ".".
*/
- if ((path == NULL) || (*path == '\0'))
- goto singledot;
-
+ if (path == NULL || *path == '\0') {
+ path = ".";
+ len = 1;
+ goto out;
+ }
/* Strip trailing slashes, if any. */
- lastp = path + strlen(path) - 1;
- while (lastp != path && *lastp == '/')
- lastp--;
+ endp = path + strlen(path) - 1;
+ while (endp != path && *endp == '/')
+ endp--;
- /* Terminate path at the last occurence of '/'. */
- do {
- if (*lastp == '/') {
- /* Strip trailing slashes, if any. */
- while (lastp != path && *lastp == '/')
- lastp--;
+ /* Find the start of the dir */
+ while (endp > path && *endp != '/')
+ endp--;
- /* ...and copy the result into the result buffer. */
- len = (lastp - path) + 1 /* last char */;
- if (len > (PATH_MAX - 1))
- len = PATH_MAX - 1;
+ if (endp == path) {
+ path = *endp == '/' ? "/" : ".";
+ len = 1;
+ goto out;
+ }
- memcpy(result, path, len);
- result[len] = '\0';
+ do
+ endp--;
+ while (endp > path && *endp == '/');
- return (result);
- }
- } while (--lastp >= path);
+ len = endp - path + 1;
+out:
+ if (buf != NULL && buflen != 0) {
+ buflen = MIN(len, buflen - 1);
+ memcpy(buf, path, buflen);
+ buf[buflen] = '\0';
+ }
+ return len;
+}
- /* No /'s found, return a pointer to the string ".". */
-singledot:
- result[0] = '.';
- result[1] = '\0';
+char *
+dirname(char *path)
+{
+ static char result[PATH_MAX];
+ (void)xdirname_r(path, result, sizeof(result));
+ return result;
+}
+
+#ifdef MAIN
+#include <stdlib.h>
+#include <stdio.h>
- return (result);
+int
+main(int argc, char *argv[])
+{
+ printf("%s\n", dirname(argv[1]));
+ exit(0);
}
#endif
+#endif
diff --git a/for.c b/for.c
index 33bcf13..ec00a45 100644
--- a/for.c
+++ b/for.c
@@ -1,4 +1,4 @@
-/* $NetBSD: for.c,v 1.49 2012/06/03 04:29:40 sjg Exp $ */
+/* $NetBSD: for.c,v 1.52 2016/02/18 18:29:14 christos Exp $ */
/*
* Copyright (c) 1992, The Regents of the University of California.
@@ -30,14 +30,14 @@
*/
#ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: for.c,v 1.49 2012/06/03 04:29:40 sjg Exp $";
+static char rcsid[] = "$NetBSD: for.c,v 1.52 2016/02/18 18:29:14 christos Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)for.c 8.1 (Berkeley) 6/6/93";
#else
-__RCSID("$NetBSD: for.c,v 1.49 2012/06/03 04:29:40 sjg Exp $");
+__RCSID("$NetBSD: for.c,v 1.52 2016/02/18 18:29:14 christos Exp $");
#endif
#endif /* not lint */
#endif
@@ -216,7 +216,7 @@ For_Eval(char *line)
* We can't do the escapes here - because we don't know whether
* we are substuting into ${...} or $(...).
*/
- sub = Var_Subst(NULL, ptr, VAR_GLOBAL, FALSE);
+ sub = Var_Subst(NULL, ptr, VAR_GLOBAL, VARF_WANTRES);
/*
* Split into words allowing for quoted strings.
diff --git a/getopt.c b/getopt.c
index c40bc13..da29dae 100644
--- a/getopt.c
+++ b/getopt.c
@@ -1,3 +1,5 @@
+/* $NetBSD: getopt.c,v 1.29 2014/06/05 22:00:22 christos Exp $ */
+
/*
* Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
@@ -10,11 +12,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
@@ -35,11 +33,7 @@
# include "config.h"
#endif
#if !defined(HAVE_GETOPT) || defined(WANT_GETOPT_LONG) || defined(BROKEN_GETOPT)
-
-#if defined(LIBC_SCCS) && !defined(lint)
-/* static char sccsid[] = "from: @(#)getopt.c 8.2 (Berkeley) 4/2/94"; */
-static char *rcsid = "$Id: getopt.c,v 1.3 1999/01/08 02:14:18 sjg Exp $";
-#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
#include <stdio.h>
#include <stdlib.h>
@@ -61,13 +55,10 @@ char *optarg; /* argument associated with option */
* Parse argc/argv argument vector.
*/
int
-getopt(nargc, nargv, ostr)
- int nargc;
- char * const *nargv;
- const char *ostr;
+getopt(int nargc, char * const nargv[], const char *ostr)
{
extern char *__progname;
- static char *place = EMSG; /* option letter processing */
+ static const char *place = EMSG; /* option letter processing */
char *oli; /* option letter list index */
#ifndef BSD4_4
@@ -79,43 +70,63 @@ getopt(nargc, nargv, ostr)
}
#endif
- if (optreset || !*place) { /* update scanning pointer */
+ if (optreset || *place == 0) { /* update scanning pointer */
optreset = 0;
- if (optind >= nargc || *(place = nargv[optind]) != '-') {
+ place = nargv[optind];
+ if (optind >= nargc || *place++ != '-') {
+ /* Argument is absent or is not an option */
place = EMSG;
return (-1);
}
- if (place[1] && *++place == '-' /* found "--" */
- && !place[1]) { /* and not "--foo" */
+ optopt = *place++;
+ if (optopt == '-' && *place == 0) {
+ /* "--" => end of options */
++optind;
place = EMSG;
return (-1);
}
- } /* option letter okay? */
- if ((optopt = (int)*place++) == (int)':' ||
- !(oli = strchr(ostr, optopt))) {
- /*
- * if the user didn't specify '-' as an option,
- * assume it means -1.
- */
- if (optopt == (int)'-')
- return (-1);
- if (!*place)
+ if (optopt == 0) {
+ /* Solitary '-', treat as a '-' option
+ if the program (eg su) is looking for it. */
+ place = EMSG;
+ if (strchr(ostr, '-') == NULL)
+ return -1;
+ optopt = '-';
+ }
+ } else
+ optopt = *place++;
+
+ /* See if option letter is one the caller wanted... */
+ if (optopt == ':' || (oli = strchr(ostr, optopt)) == NULL) {
+ if (*place == 0)
++optind;
if (opterr && *ostr != ':')
(void)fprintf(stderr,
- "%s: illegal option -- %c\n", __progname, optopt);
+ "%s: unknown option -- %c\n", __progname, optopt);
return (BADCH);
}
- if (*++oli != ':') { /* don't need argument */
+
+ /* Does this option need an argument? */
+ if (oli[1] != ':') {
+ /* don't need argument */
optarg = NULL;
- if (!*place)
+ if (*place == 0)
++optind;
- }
- else { /* need an argument */
- if (*place) /* no white space */
- optarg = place;
- else if (nargc <= ++optind) { /* no arg */
+ } else {
+ /* Option-argument is either the rest of this argument or the
+ entire next argument. */
+ if (*place)
+ optarg = __UNCONST(place);
+ else if (oli[2] == ':')
+ /*
+ * GNU Extension, for optional arguments if the rest of
+ * the argument is empty, we return NULL
+ */
+ optarg = NULL;
+ else if (nargc > ++optind)
+ optarg = nargv[optind];
+ else {
+ /* option-argument absent */
place = EMSG;
if (*ostr == ':')
return (BADARG);
@@ -125,12 +136,10 @@ getopt(nargc, nargv, ostr)
__progname, optopt);
return (BADCH);
}
- else /* white space */
- optarg = nargv[optind];
place = EMSG;
++optind;
}
- return (optopt); /* dump back option letter */
+ return (optopt); /* return option letter */
}
#endif
#ifdef MAIN
diff --git a/job.c b/job.c
index b5dbf4c..93e7430 100644
--- a/job.c
+++ b/job.c
@@ -1,4 +1,4 @@
-/* $NetBSD: job.c,v 1.176 2013/08/04 16:48:15 sjg Exp $ */
+/* $NetBSD: job.c,v 1.186 2016/02/18 18:29:14 christos Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -70,14 +70,14 @@
*/
#ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: job.c,v 1.176 2013/08/04 16:48:15 sjg Exp $";
+static char rcsid[] = "$NetBSD: job.c,v 1.186 2016/02/18 18:29:14 christos Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)job.c 8.2 (Berkeley) 3/19/94";
#else
-__RCSID("$NetBSD: job.c,v 1.176 2013/08/04 16:48:15 sjg Exp $");
+__RCSID("$NetBSD: job.c,v 1.186 2016/02/18 18:29:14 christos Exp $");
#endif
#endif /* not lint */
#endif
@@ -144,7 +144,6 @@ __RCSID("$NetBSD: job.c,v 1.176 2013/08/04 16:48:15 sjg Exp $");
#include <assert.h>
#include <errno.h>
-#include <fcntl.h>
#if !defined(USE_SELECT) && defined(HAVE_POLL_H)
#include <poll.h>
#else
@@ -425,8 +424,8 @@ JobCreatePipe(Job *job, int minfd)
}
/* Set close-on-exec flag for both */
- (void)fcntl(job->jobPipe[0], F_SETFD, 1);
- (void)fcntl(job->jobPipe[1], F_SETFD, 1);
+ (void)fcntl(job->jobPipe[0], F_SETFD, FD_CLOEXEC);
+ (void)fcntl(job->jobPipe[1], F_SETFD, FD_CLOEXEC);
/*
* We mark the input side of the pipe non-blocking; we poll(2) the
@@ -715,7 +714,7 @@ JobPrintCommand(void *cmdp, void *jobp)
numCommands += 1;
- cmdStart = cmd = Var_Subst(NULL, cmd, job->node, FALSE);
+ cmdStart = cmd = Var_Subst(NULL, cmd, job->node, VARF_WANTRES);
cmdTemplate = "%s\n";
@@ -728,7 +727,6 @@ JobPrintCommand(void *cmdp, void *jobp)
shutUp = DEBUG(LOUD) ? FALSE : TRUE;
break;
case '-':
- job->flags |= JOB_IGNERR;
errOff = TRUE;
break;
case '+':
@@ -807,6 +805,7 @@ JobPrintCommand(void *cmdp, void *jobp)
* to ignore errors. Set cmdTemplate to use the weirdness
* instead of the simple "%s\n" template.
*/
+ job->flags |= JOB_IGNERR;
if (!(job->flags & JOB_SILENT) && !shutUp) {
if (commandShell->hasEchoCtl) {
DBPRINTF("%s\n", commandShell->echoOff);
@@ -866,8 +865,7 @@ JobPrintCommand(void *cmdp, void *jobp)
DBPRINTF(cmdTemplate, cmd);
free(cmdStart);
- if (escCmd)
- free(escCmd);
+ free(escCmd);
if (errOff) {
/*
* If echoing is already off, there's no point in issuing the
@@ -903,7 +901,7 @@ JobPrintCommand(void *cmdp, void *jobp)
static int
JobSaveCommand(void *cmd, void *gn)
{
- cmd = Var_Subst(NULL, (char *)cmd, (GNode *)gn, FALSE);
+ cmd = Var_Subst(NULL, (char *)cmd, (GNode *)gn, VARF_WANTRES);
(void)Lst_AtEnd(postCommands->commands, cmd);
return(0);
}
@@ -1234,8 +1232,7 @@ Job_CheckCommands(GNode *gn, void (*abortProc)(const char *, ...))
*/
Make_HandleUse(DEFAULT, gn);
Var_Set(IMPSRC, Var_Value(TARGET, gn, &p1), gn, 0);
- if (p1)
- free(p1);
+ free(p1);
} else if (Dir_MTime(gn, 0) == 0 && (gn->type & OP_SPECIAL) == 0) {
/*
* The node wasn't the target of an operator we have no .DEFAULT
@@ -1360,7 +1357,7 @@ JobExec(Job *job, char **argv)
(void)fcntl(0, F_SETFD, 0);
(void)lseek(0, (off_t)0, SEEK_SET);
- if (job->node->type & OP_MAKE) {
+ if (job->node->type & (OP_MAKE | OP_SUBMAKE)) {
/*
* Pass job token pipe to submakes.
*/
@@ -1598,7 +1595,7 @@ JobStart(GNode *gn, int flags)
if (job->cmdFILE == NULL) {
Punt("Could not fdopen %s", tfile);
}
- (void)fcntl(FILENO(job->cmdFILE), F_SETFD, 1);
+ (void)fcntl(FILENO(job->cmdFILE), F_SETFD, FD_CLOEXEC);
/*
* Send the commands to the command file, flush all its buffers then
* rewind and remove the thing.
@@ -1894,16 +1891,16 @@ end_loop:
(void)fflush(stdout);
}
}
- if (i < max - 1) {
- /* shift the remaining characters down */
- (void)memcpy(job->outBuf, &job->outBuf[i + 1], max - (i + 1));
+ /*
+ * max is the last offset still in the buffer. Move any remaining
+ * characters to the start of the buffer and update the end marker
+ * curPos.
+ */
+ if (i < max) {
+ (void)memmove(job->outBuf, &job->outBuf[i + 1], max - (i + 1));
job->curPos = max - (i + 1);
-
} else {
- /*
- * We have written everything out, so we just start over
- * from the start of the buffer. No copying. No nothing.
- */
+ assert(i == max);
job->curPos = 0;
}
}
@@ -2194,7 +2191,8 @@ Job_SetPrefix(void)
Var_Set(MAKE_JOB_PREFIX, "---", VAR_GLOBAL, 0);
}
- targPrefix = Var_Subst(NULL, "${" MAKE_JOB_PREFIX "}", VAR_GLOBAL, 0);
+ targPrefix = Var_Subst(NULL, "${" MAKE_JOB_PREFIX "}",
+ VAR_GLOBAL, VARF_WANTRES);
}
/*-
@@ -2401,8 +2399,7 @@ Job_ParseShell(char *line)
line++;
}
- if (shellArgv)
- free(UNCONST(shellArgv));
+ free(UNCONST(shellArgv));
memset(&newShell, 0, sizeof(newShell));
@@ -2650,8 +2647,7 @@ void
Job_End(void)
{
#ifdef CLEANUP
- if (shellArgv)
- free(shellArgv);
+ free(shellArgv);
#endif
}
@@ -2850,8 +2846,8 @@ Job_ServerStart(int max_tokens, int jp_0, int jp_1)
/* Pipe passed in from parent */
tokenWaitJob.inPipe = jp_0;
tokenWaitJob.outPipe = jp_1;
- (void)fcntl(jp_0, F_SETFD, 1);
- (void)fcntl(jp_1, F_SETFD, 1);
+ (void)fcntl(jp_0, F_SETFD, FD_CLOEXEC);
+ (void)fcntl(jp_1, F_SETFD, FD_CLOEXEC);
return;
}
diff --git a/lst.h b/lst.h
index e067407..e207bc8 100644
--- a/lst.h
+++ b/lst.h
@@ -1,4 +1,4 @@
-/* $NetBSD: lst.h,v 1.18 2009/01/23 21:58:27 dsl Exp $ */
+/* $NetBSD: lst.h,v 1.20 2014/09/07 20:55:34 joerg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
diff --git a/lst.lib/lstInt.h b/lst.lib/lstInt.h
index 34a2fbd..ac53dcb 100644
--- a/lst.lib/lstInt.h
+++ b/lst.lib/lstInt.h
@@ -1,4 +1,4 @@
-/* $NetBSD: lstInt.h,v 1.20 2009/01/24 14:43:29 dsl Exp $ */
+/* $NetBSD: lstInt.h,v 1.22 2014/09/07 20:55:34 joerg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
diff --git a/lst.lib/lstRemove.c b/lst.lib/lstRemove.c
index 54d7b33..7480d30 100644
--- a/lst.lib/lstRemove.c
+++ b/lst.lib/lstRemove.c
@@ -1,4 +1,4 @@
-/* $NetBSD: lstRemove.c,v 1.14 2008/12/13 15:19:29 dsl Exp $ */
+/* $NetBSD: lstRemove.c,v 1.16 2014/09/07 20:55:34 joerg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -33,14 +33,14 @@
*/
#ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: lstRemove.c,v 1.14 2008/12/13 15:19:29 dsl Exp $";
+static char rcsid[] = "$NetBSD: lstRemove.c,v 1.16 2014/09/07 20:55:34 joerg Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)lstRemove.c 8.1 (Berkeley) 6/6/93";
#else
-__RCSID("$NetBSD: lstRemove.c,v 1.14 2008/12/13 15:19:29 dsl Exp $");
+__RCSID("$NetBSD: lstRemove.c,v 1.16 2014/09/07 20:55:34 joerg Exp $");
#endif
#endif /* not lint */
#endif
diff --git a/machine.sh b/machine.sh
index 32a0f7a..2209eaa 100755
--- a/machine.sh
+++ b/machine.sh
@@ -2,7 +2,7 @@
# derrived from /etc/rc_d/os.sh
# RCSid:
-# $Id: machine.sh,v 1.16 2010/10/17 00:05:51 sjg Exp $
+# $Id: machine.sh,v 1.17 2015/05/05 00:10:54 sjg Exp $
#
# @(#) Copyright (c) 1994-2002 Simon J. Gerraty
#
@@ -49,6 +49,10 @@ OpenBSD)
arch=`Which arch /usr/bin:/usr/ucb:$PATH`
MACHINE_ARCH=`$arch -s`;
;;
+Bitrig)
+ MACHINE=$OS$OSMAJOR.$machine
+ MACHINE_ARCH=`uname -m`;
+ ;;
*BSD)
MACHINE=$OS$OSMAJOR.$machine
;;
diff --git a/main.c b/main.c
index f86184c..4572aed 100644
--- a/main.c
+++ b/main.c
@@ -1,4 +1,4 @@
-/* $NetBSD: main.c,v 1.226 2014/02/07 17:23:35 pooka Exp $ */
+/* $NetBSD: main.c,v 1.241 2016/02/19 00:11:45 sjg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -69,7 +69,7 @@
*/
#ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: main.c,v 1.226 2014/02/07 17:23:35 pooka Exp $";
+static char rcsid[] = "$NetBSD: main.c,v 1.241 2016/02/19 00:11:45 sjg Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
@@ -81,7 +81,7 @@ __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993\
#if 0
static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 3/19/94";
#else
-__RCSID("$NetBSD: main.c,v 1.226 2014/02/07 17:23:35 pooka Exp $");
+__RCSID("$NetBSD: main.c,v 1.241 2016/02/19 00:11:45 sjg Exp $");
#endif
#endif /* not lint */
#endif
@@ -99,14 +99,14 @@ __RCSID("$NetBSD: main.c,v 1.226 2014/02/07 17:23:35 pooka Exp $");
*
* Error Print a tagged error message. The global
* MAKE variable must have been defined. This
- * takes a format string and two optional
- * arguments for it.
+ * takes a format string and optional arguments
+ * for it.
*
* Fatal Print an error message and exit. Also takes
- * a format string and two arguments.
+ * a format string and arguments for it.
*
* Punt Aborts all jobs and exits with a message. Also
- * takes a format string and two arguments.
+ * takes a format string and arguments for it.
*
* Finish Finish things up by printing the number of
* errors which occurred, as passed to it, and
@@ -125,7 +125,6 @@ __RCSID("$NetBSD: main.c,v 1.226 2014/02/07 17:23:35 pooka Exp $");
#include "wait.h"
#include <errno.h>
-#include <fcntl.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
@@ -172,6 +171,7 @@ Boolean keepgoing; /* -k flag */
Boolean queryFlag; /* -q flag */
Boolean touchFlag; /* -t flag */
Boolean enterFlag; /* -w flag */
+Boolean enterFlagObj; /* -w and objdir != srcdir */
Boolean ignoreErrors; /* -i flag */
Boolean beSilent; /* -s flag */
Boolean oldVars; /* variable substitution style */
@@ -695,8 +695,7 @@ Main_ParseArgLine(const char *line)
#endif
buf = bmake_malloc(len = strlen(line) + strlen(argv0) + 2);
(void)snprintf(buf, len, "%s %s", argv0, line);
- if (p1)
- free(p1);
+ free(p1);
argv = brk_string(buf, &argc, TRUE, &args);
if (argv == NULL) {
@@ -722,7 +721,7 @@ Main_SetObjdir(const char *path)
/* expand variable substitutions */
if (strchr(path, '$') != 0) {
snprintf(buf, MAXPATHLEN, "%s", path);
- path = p = Var_Subst(NULL, buf, VAR_GLOBAL, 0);
+ path = p = Var_Subst(NULL, buf, VAR_GLOBAL, VARF_WANTRES);
}
if (path[0] != '/') {
@@ -741,11 +740,12 @@ Main_SetObjdir(const char *path)
setenv("PWD", objdir, 1);
Dir_InitDot();
rc = TRUE;
+ if (enterFlag && strcmp(objdir, curdir) != 0)
+ enterFlagObj = TRUE;
}
}
- if (p)
- free(p);
+ free(p);
return rc;
}
@@ -803,7 +803,8 @@ MakeMode(const char *mode)
char *mp = NULL;
if (!mode)
- mode = mp = Var_Subst(NULL, "${" MAKE_MODE ":tl}", VAR_GLOBAL, 0);
+ mode = mp = Var_Subst(NULL, "${" MAKE_MODE ":tl}",
+ VAR_GLOBAL, VARF_WANTRES);
if (mode && *mode) {
if (strstr(mode, "compat")) {
@@ -815,8 +816,8 @@ MakeMode(const char *mode)
meta_mode_init(mode);
#endif
}
- if (mp)
- free(mp);
+
+ free(mp);
}
/*-
@@ -1249,7 +1250,7 @@ main(int argc, char **argv)
(char *)Lst_Datum(ln));
} else {
p1 = Var_Subst(NULL, "${" MAKEFILE_PREFERENCE "}",
- VAR_CMD, 0);
+ VAR_CMD, VARF_WANTRES);
if (p1) {
(void)str2Lst_Append(makefiles, p1, NULL);
(void)Lst_Find(makefiles, NULL, ReadMakefile);
@@ -1260,17 +1261,19 @@ main(int argc, char **argv)
/* In particular suppress .depend for '-r -V .OBJDIR -f /dev/null' */
if (!noBuiltins || !printVars) {
makeDependfile = Var_Subst(NULL, "${.MAKE.DEPENDFILE:T}",
- VAR_CMD, 0);
+ VAR_CMD, VARF_WANTRES);
doing_depend = TRUE;
(void)ReadMakefile(makeDependfile, NULL);
doing_depend = FALSE;
}
+ if (enterFlagObj)
+ printf("%s: Entering directory `%s'\n", progname, objdir);
+
MakeMode(NULL);
Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL);
- if (p1)
- free(p1);
+ free(p1);
if (!compatMake)
Job_ServerStart(maxJobTokens, jp_0, jp_1);
@@ -1295,7 +1298,7 @@ main(int argc, char **argv)
*/
static char VPATH[] = "${VPATH}";
- vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE);
+ vpath = Var_Subst(NULL, VPATH, VAR_CMD, VARF_WANTRES);
path = vpath;
do {
/* skip to end of directory */
@@ -1342,20 +1345,21 @@ main(int argc, char **argv)
char *value;
if (strchr(var, '$')) {
- value = p1 = Var_Subst(NULL, var, VAR_GLOBAL, 0);
+ value = p1 = Var_Subst(NULL, var, VAR_GLOBAL,
+ VARF_WANTRES);
} else if (expandVars) {
char tmp[128];
if (snprintf(tmp, sizeof(tmp), "${%s}", var) >= (int)(sizeof(tmp)))
Fatal("%s: variable name too big: %s",
progname, var);
- value = p1 = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
+ value = p1 = Var_Subst(NULL, tmp, VAR_GLOBAL,
+ VARF_WANTRES);
} else {
value = Var_Value(var, VAR_GLOBAL, &p1);
}
printf("%s\n", value ? value : "");
- if (p1)
- free(p1);
+ free(p1);
}
} else {
/*
@@ -1406,6 +1410,8 @@ main(int argc, char **argv)
Trace_Log(MAKEEND, 0);
+ if (enterFlagObj)
+ printf("%s: Leaving directory `%s'\n", progname, objdir);
if (enterFlag)
printf("%s: Leaving directory `%s'\n", progname, curdir);
@@ -1477,8 +1483,7 @@ ReadMakefile(const void *p, const void *q MAKE_ATTR_UNUSED)
name = Dir_FindFile(fname,
Lst_IsEmpty(sysIncPath) ? defIncPath : sysIncPath);
if (!name || (fd = open(name, O_RDONLY)) == -1) {
- if (name)
- free(name);
+ free(name);
free(path);
return(-1);
}
@@ -1522,7 +1527,8 @@ Cmd_Exec(const char *cmd, const char **errnum)
WAIT_T status; /* command exit status */
Buffer buf; /* buffer to store the result */
char *cp;
- int cc;
+ int cc; /* bytes read, or -1 */
+ int savederr; /* saved errno */
*errnum = NULL;
@@ -1579,6 +1585,7 @@ Cmd_Exec(const char *cmd, const char **errnum)
*/
(void)close(fds[1]);
+ savederr = 0;
Buf_Init(&buf, 0);
do {
@@ -1588,6 +1595,8 @@ Cmd_Exec(const char *cmd, const char **errnum)
Buf_AddBytes(&buf, cc, result);
}
while (cc > 0 || (cc == -1 && errno == EINTR));
+ if (cc == -1)
+ savederr = errno;
/*
* Close the input side of the pipe.
@@ -1604,7 +1613,7 @@ Cmd_Exec(const char *cmd, const char **errnum)
cc = Buf_Size(&buf);
res = Buf_Destroy(&buf, FALSE);
- if (cc == 0)
+ if (savederr != 0)
*errnum = "Couldn't read shell's output for \"%s\"";
if (WIFSIGNALED(status))
@@ -1881,12 +1890,14 @@ PrintOnError(GNode *gn, const char *s)
}
strncpy(tmp, "${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'\n@}",
sizeof(tmp) - 1);
- cp = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
+ cp = Var_Subst(NULL, tmp, VAR_GLOBAL, VARF_WANTRES);
if (cp) {
if (*cp)
printf("%s", cp);
free(cp);
}
+ fflush(stdout);
+
/*
* Finally, see if there is a .ERROR target, and run it if so.
*/
@@ -1910,7 +1921,7 @@ Main_ExportMAKEFLAGS(Boolean first)
strncpy(tmp, "${.MAKEFLAGS} ${.MAKEOVERRIDES:O:u:@v@$v=${$v:Q}@}",
sizeof(tmp));
- s = Var_Subst(NULL, tmp, VAR_CMD, 0);
+ s = Var_Subst(NULL, tmp, VAR_CMD, VARF_WANTRES);
if (s && *s) {
#ifdef POSIX
setenv("MAKEFLAGS", s, 1);
@@ -1932,7 +1943,8 @@ getTmpdir(void)
* Honor $TMPDIR but only if it is valid.
* Ensure it ends with /.
*/
- tmpdir = Var_Subst(NULL, "${TMPDIR:tA:U" _PATH_TMP "}/", VAR_GLOBAL, 0);
+ tmpdir = Var_Subst(NULL, "${TMPDIR:tA:U" _PATH_TMP "}/", VAR_GLOBAL,
+ VARF_WANTRES);
if (stat(tmpdir, &st) < 0 || !S_ISDIR(st.st_mode)) {
free(tmpdir);
tmpdir = bmake_strdup(_PATH_TMP);
@@ -1972,6 +1984,44 @@ mkTempFile(const char *pattern, char **fnamep)
return fd;
}
+/*
+ * Convert a string representation of a boolean.
+ * Anything that looks like "No", "False", "Off", "0" etc,
+ * is FALSE, otherwise TRUE.
+ */
+Boolean
+s2Boolean(const char *s, Boolean bf)
+{
+ if (s) {
+ switch(*s) {
+ case '\0': /* not set - the default wins */
+ break;
+ case '0':
+ case 'F':
+ case 'f':
+ case 'N':
+ case 'n':
+ bf = FALSE;
+ break;
+ case 'O':
+ case 'o':
+ switch (s[1]) {
+ case 'F':
+ case 'f':
+ bf = FALSE;
+ break;
+ default:
+ bf = TRUE;
+ break;
+ }
+ break;
+ default:
+ bf = TRUE;
+ break;
+ }
+ }
+ return (bf);
+}
/*
* Return a Boolean based on setting of a knob.
@@ -1986,32 +2036,11 @@ getBoolean(const char *name, Boolean bf)
char tmp[64];
char *cp;
- if (snprintf(tmp, sizeof(tmp), "${%s:tl}", name) < (int)(sizeof(tmp))) {
- cp = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
+ if (snprintf(tmp, sizeof(tmp), "${%s:U:tl}", name) < (int)(sizeof(tmp))) {
+ cp = Var_Subst(NULL, tmp, VAR_GLOBAL, VARF_WANTRES);
if (cp) {
- switch(*cp) {
- case '\0': /* not set - the default wins */
- break;
- case '0':
- case 'f':
- case 'n':
- bf = FALSE;
- break;
- case 'o':
- switch (cp[1]) {
- case 'f':
- bf = FALSE;
- break;
- default:
- bf = TRUE;
- break;
- }
- break;
- default:
- bf = TRUE;
- break;
- }
+ bf = s2Boolean(cp, bf);
free(cp);
}
}
diff --git a/make-bootstrap.sh.in b/make-bootstrap.sh.in
index 2bb4c25..638e293 100755
--- a/make-bootstrap.sh.in
+++ b/make-bootstrap.sh.in
@@ -52,7 +52,7 @@ do_link() {
}
BASE_OBJECTS="arch.o buf.o compat.o cond.o dir.o for.o getopt hash.o \
-job.o make.o make_malloc.o parse.o sigcompat.o str.o strlist.o \
+job.o make.o make_malloc.o metachar.o parse.o sigcompat.o str.o strlist.o \
suff.o targ.o trace.o var.o util.o"
LST_OBJECTS="lstAppend.o lstDupl.o lstInit.o lstOpen.o \
diff --git a/make.1 b/make.1
index ccc4832..7cae22a 100644
--- a/make.1
+++ b/make.1
@@ -1,4 +1,4 @@
-.\" $NetBSD: make.1,v 1.230 2014/02/15 18:55:30 sjg Exp $
+.\" $NetBSD: make.1,v 1.253 2016/02/20 01:19:03 sjg Exp $
.\"
.\" Copyright (c) 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -29,7 +29,7 @@
.\"
.\" from: @(#)make.1 8.4 (Berkeley) 3/19/94
.\"
-.Dd February 14, 2014
+.Dd February 19, 2016
.Dt MAKE 1
.Os
.Sh NAME
@@ -209,8 +209,6 @@ Force the
option to print raw values of variables.
.It Ar v
Print debugging information about variable assignment.
-.It Ar w
-Print entering and leaving directory messages, pre and post processing.
.It Ar x
Run shell commands with
.Fl x
@@ -352,6 +350,8 @@ contains a
then the value will be expanded before printing.
.It Fl W
Treat any warnings during makefile parsing as errors.
+.It Fl w
+Print entering and leaving directory messages, pre and post processing.
.It Fl X
Don't export variables passed on the command line to the environment
individually.
@@ -441,17 +441,29 @@ The value
need not necessarily be used to describe existing files.
Expansion is in directory order, not alphabetically as done in the shell.
.Sh SHELL COMMANDS
-Each target may have associated with it a series of shell commands, normally
+Each target may have associated with it one or more lines of shell
+commands, normally
used to create the target.
-Each of the commands in this script
+Each of the lines in this script
.Em must
be preceded by a tab.
-While any target may appear on a dependency line, only one of these
-dependencies may be followed by a creation script, unless the
+(For historical reasons, spaces are not accepted.)
+While targets can appear in many dependency lines if desired, by
+default only one of these rules may be followed by a creation
+script.
+If the
.Ql Ic \&::
-operator is used.
+operator is used, however, all rules may include scripts and the
+scripts are executed in the order found.
.Pp
-If the first characters of the command line are any combination of
+Each line is treated as a separate shell command, unless the end of
+line is escaped with a backslash
+.Pq Ql \e
+in which case that line and the next are combined.
+.\" The escaped newline is retained and passed to the shell, which
+.\" normally ignores it.
+.\" However, the tab at the beginning of the following line is removed.
+If the first characters of the command are any combination of
.Ql Ic @ ,
.Ql Ic + ,
or
@@ -469,6 +481,7 @@ This is similar to the effect of the .MAKE special source,
except that the effect can be limited to a single line of a script.
A
.Ql Ic \-
+in compatibility mode
causes any non-zero exit status of the command line to be ignored.
.Pp
When
@@ -477,22 +490,21 @@ is run in jobs mode with
.Fl j Ar max_jobs ,
the entire script for the target is fed to a
single instance of the shell.
-.Pp
In compatibility (non-jobs) mode, each command is run in a separate process.
If the command contains any shell meta characters
.Pq Ql #=|^(){};&<>*?[]:$`\e\en
-it will be passed to the shell, otherwise
+it will be passed to the shell; otherwise
.Nm
will attempt direct execution.
-.Pp
-Since
-.Nm
-will
-.Xr chdir 2
-to
-.Ql Va .OBJDIR
-before executing any targets, each child process
-starts with that as its current working directory.
+If a line starts with
+.Ql Ic \-
+and the shell has ErrCtl enabled then failure of the command line
+will be ignored as in compatibility mode.
+Otherwise
+.Ql Ic \-
+affects the entire job;
+the script will stop at the first command line that fails,
+but the target will not be deemed to have failed.
.Pp
Makefiles should be written so that the mode of
.Nm
@@ -500,20 +512,32 @@ operation does not change their behavior.
For example, any command which needs to use
.Dq cd
or
-.Dq chdir ,
-without side-effect should be put in parenthesis:
+.Dq chdir
+without potentially changing the directory for subsequent commands
+should be put in parentheses so it executes in a subshell.
+To force the use of one shell, escape the line breaks so as to make
+the whole script one command.
+For example:
.Bd -literal -offset indent
-
avoid-chdir-side-effects:
@echo Building $@ in `pwd`
- @(cd ${.CURDIR} && ${.MAKE} $@)
+ @(cd ${.CURDIR} && ${MAKE} $@)
@echo Back in `pwd`
ensure-one-shell-regardless-of-mode:
- @echo Building $@ in `pwd`; \\
- (cd ${.CURDIR} && ${.MAKE} $@); \\
+ @echo Building $@ in `pwd`; \e
+ (cd ${.CURDIR} && ${MAKE} $@); \e
echo Back in `pwd`
.Ed
+.Pp
+Since
+.Nm
+will
+.Xr chdir 2
+to
+.Ql Va .OBJDIR
+before executing any targets, each child process
+starts with that as its current working directory.
.Sh VARIABLE ASSIGNMENTS
Variables in make are much like variables in the shell, and, by tradition,
consist of all upper-case letters.
@@ -624,13 +648,19 @@ Variables defined in the makefile or in included makefiles.
Variables defined as part of the command line.
.It Local variables
Variables that are defined specific to a certain target.
+.El
+.Pp
+Local variables are all built in and their values vary magically from
+target to target.
+It is not currently possible to define new local variables.
The seven local variables are as follows:
-.Bl -tag -width ".ARCHIVE"
+.Bl -tag -width ".ARCHIVE" -offset indent
.It Va .ALLSRC
The list of all sources for this target; also known as
.Ql Va \&\*[Gt] .
.It Va .ARCHIVE
-The name of the archive file.
+The name of the archive file; also known as
+.Ql Va \&! .
.It Va .IMPSRC
In suffix-transformation rules, the name/path of the source from which the
target is to be transformed (the
@@ -639,7 +669,8 @@ source); also known as
.Ql Va \&\*[Lt] .
It is not defined in explicit rules.
.It Va .MEMBER
-The name of the archive member.
+The name of the archive member; also known as
+.Ql Va % .
.It Va .OODATE
The list of sources for this target that were deemed out-of-date; also
known as
@@ -648,31 +679,41 @@ known as
The file prefix of the target, containing only the file portion, no suffix
or preceding directory components; also known as
.Ql Va * .
+The suffix must be one of the known suffixes declared with
+.Ic .SUFFIXES
+or it will not be recognized.
.It Va .TARGET
The name of the target; also known as
.Ql Va @ .
.El
.Pp
The shorter forms
-.Ql Va @ ,
+.Ql ( Va \*[Gt] ,
+.Ql Va \&! ,
+.Ql Va \*[Lt] ,
+.Ql Va % ,
.Ql Va \&? ,
-.Ql Va \&\*[Lt] ,
-.Ql Va \&\*[Gt] ,
+.Ql Va * ,
and
-.Ql Va *
+.Ql Va @ )
are permitted for backward
-compatibility with historical makefiles and are not recommended.
-The six variables
-.Ql Va "@F" ,
-.Ql Va "@D" ,
-.Ql Va "\*[Lt]F" ,
-.Ql Va "\*[Lt]D" ,
-.Ql Va "*F" ,
+compatibility with historical makefiles and legacy POSIX make and are
+not recommended.
+.Pp
+Variants of these variables with the punctuation followed immediately by
+.Ql D
+or
+.Ql F ,
+e.g.
+.Ql Va $(@D) ,
+are legacy forms equivalent to using the
+.Ql :H
and
-.Ql Va "*D"
-are permitted for compatibility with
+.Ql :T
+modifiers.
+These forms are accepted for compatibility with
.At V
-makefiles and are not recommended.
+makefiles and POSIX but are not recommended.
.Pp
Four of the local variables may be used in sources on dependency lines
because they expand to the proper value for each target on the line.
@@ -682,7 +723,6 @@ These variables are
.Ql Va .ARCHIVE ,
and
.Ql Va .MEMBER .
-.El
.Ss Additional built-in variables
In addition,
.Nm
@@ -901,6 +941,19 @@ The process-id of
.It Va .MAKE.PPID
The parent process-id of
.Nm .
+.It Va .MAKE.SAVE_DOLLARS
+value should be a boolen that controls wether
+.Ql $$
+are preserved when doing
+.Ql :=
+assignments.
+The default is false, for backwards compatability.
+Set to true for compatability with other makes.
+If set to false,
+.Ql $$
+becomes
+.Ql $
+per normal evaluation rules.
.It Va MAKE_PRINT_VAR_ON_ERROR
When
.Nm
@@ -953,14 +1006,15 @@ This is especially useful with
.Ql Ev MAKEOBJDIR .
.Pp
.Ql Va .OBJDIR
-may be modified in the makefile as a global variable.
+may be modified in the makefile via the special target
+.Ql Ic .OBJDIR .
In all cases,
.Nm
will
.Xr chdir 2
-to
+to the specified directory if it exists, and set
.Ql Va .OBJDIR
-and set
+and
.Ql Ev PWD
to that directory before executing any targets.
.
@@ -1489,12 +1543,20 @@ For compatibility with other versions of
.Nm
.Ql include file ...
is also accepted.
+.Pp
If the include statement is written as
.Cm .-include
or as
.Cm .sinclude
then errors locating and/or opening include files are ignored.
.Pp
+If the include statement is written as
+.Cm .dinclude
+not only are errors locating and/or opening include files ignored,
+but stale dependencies within the included file will be ignored
+just like
+.Va .MAKE.DEPENDFILE .
+.Pp
Conditional expressions are also preceded by a single dot as the first
character of a line.
The possible conditionals are as follows:
@@ -1530,6 +1592,10 @@ This allows exporting a value to the environment which is different from that
used by
.Nm
internally.
+.It Ic .export-literal Ar variable ...
+The same as
+.Ql .export-env ,
+except that variables in the value are not expanded.
.It Ic .info Ar message
The message is printed along with the name of the makefile and line number.
.It Ic .undef Ar variable
@@ -1961,6 +2027,15 @@ Disable parallel mode.
Synonym for
.Ic .NOTPARALLEL ,
for compatibility with other pmake variants.
+.It Ic .OBJDIR
+The source is a new value for
+.Ql Va .OBJDIR .
+If it exists,
+.Nm
+will
+.Xr chdir 2
+to it and update the value of
+.Ql Va .OBJDIR .
.It Ic .ORDER
The named targets are made in sequence.
This ordering does not add targets to the list of targets to be made.
@@ -2119,19 +2194,87 @@ system makefile
system makefile directory
.El
.Sh COMPATIBILITY
-The basic make syntax is compatible between different versions of make,
+The basic make syntax is compatible between different versions of make;
however the special variables, variable modifiers and conditionals are not.
-.Pp
-The way that parallel makes are scheduled changed in
-.Nx 4.0
-so that .ORDER and .WAIT apply recursively to the dependent nodes.
-The algorithms used may change again in the future.
+.Ss Older versions
+An incomplete list of changes in older versions of
+.Nm :
.Pp
The way that .for loop variables are substituted changed after
.Nx 5.0
so that they still appear to be variable expansions.
In particular this stops them being treated as syntax, and removes some
obscure problems using them in .if statements.
+.Pp
+The way that parallel makes are scheduled changed in
+.Nx 4.0
+so that .ORDER and .WAIT apply recursively to the dependent nodes.
+The algorithms used may change again in the future.
+.Ss Other make dialects
+Other make dialects (GNU make, SVR4 make, POSIX make, etc.) do not
+support most of the features of
+.Nm
+as described in this manual.
+Most notably:
+.Bl -bullet -offset indent
+.It
+The
+.Ic .WAIT
+and
+.Ic .ORDER
+declarations and most functionality pertaining to parallelization.
+(GNU make supports parallelization but lacks these features needed to
+control it effectively.)
+.It
+Directives, including for loops and conditionals and most of the
+forms of include files.
+(GNU make has its own incompatible and less powerful syntax for
+conditionals.)
+.It
+All built-in variables that begin with a dot.
+.It
+Most of the special sources and targets that begin with a dot,
+with the notable exception of
+.Ic .PHONY ,
+.Ic .PRECIOUS ,
+and
+.Ic .SUFFIXES .
+.It
+Variable modifiers, except for the
+.Dl :old=new
+string substitution, which does not portably support globbing with
+.Ql %
+and historically only works on declared suffixes.
+.It
+The
+.Ic $>
+variable even in its short form; most makes support this functionality
+but its name varies.
+.El
+.Pp
+Some features are somewhat more portable, such as assignment with
+.Ic += ,
+.Ic ?= ,
+and
+.Ic != .
+The
+.Ic .PATH
+functionality is based on an older feature
+.Ic VPATH
+found in GNU make and many versions of SVR4 make; however,
+historically its behavior is too ill-defined (and too buggy) to rely
+upon.
+.Pp
+The
+.Ic $@
+and
+.Ic $<
+variables are more or less universally portable, as is the
+.Ic $(MAKE)
+variable.
+Basic use of suffix rules (for files only in the current directory,
+not trying to chain transformations together, etc.) is also reasonably
+portable.
.Sh SEE ALSO
.Xr mkdep 1
.Sh HISTORY
diff --git a/make.c b/make.c
index 7905f8c..5ea04fc 100644
--- a/make.c
+++ b/make.c
@@ -1,4 +1,4 @@
-/* $NetBSD: make.c,v 1.88 2012/11/09 18:53:05 sjg Exp $ */
+/* $NetBSD: make.c,v 1.95 2016/02/18 18:29:14 christos Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -69,14 +69,14 @@
*/
#ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: make.c,v 1.88 2012/11/09 18:53:05 sjg Exp $";
+static char rcsid[] = "$NetBSD: make.c,v 1.95 2016/02/18 18:29:14 christos Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)make.c 8.1 (Berkeley) 6/6/93";
#else
-__RCSID("$NetBSD: make.c,v 1.88 2012/11/09 18:53:05 sjg Exp $");
+__RCSID("$NetBSD: make.c,v 1.95 2016/02/18 18:29:14 christos Exp $");
#endif
#endif /* not lint */
#endif
@@ -482,10 +482,9 @@ Make_HandleUse(GNode *cgn, GNode *pgn)
if (gn->uname == NULL) {
gn->uname = gn->name;
} else {
- if (gn->name)
- free(gn->name);
+ free(gn->name);
}
- gn->name = Var_Subst(NULL, gn->uname, pgn, FALSE);
+ gn->name = Var_Subst(NULL, gn->uname, pgn, VARF_WANTRES);
if (gn->name && gn->uname && strcmp(gn->name, gn->uname) != 0) {
/* See if we have a target for this node. */
tgn = Targ_FindNode(gn->name, TARG_NOCREATE);
@@ -563,7 +562,7 @@ MakeHandleUse(void *cgnp, void *pgnp)
* in the comments below.
*
* Results:
- * returns 0 if the gnode does not exist, or it's filesystem
+ * returns 0 if the gnode does not exist, or its filesystem
* time if it does.
*
* Side Effects:
@@ -692,8 +691,7 @@ Make_Update(GNode *cgn)
checked++;
cname = Var_Value(TARGET, cgn, &p1);
- if (p1)
- free(p1);
+ free(p1);
if (DEBUG(MAKE))
fprintf(debug_file, "Make_Update: %s%s\n", cgn->name, cgn->cohort_num);
@@ -838,8 +836,7 @@ Make_Update(GNode *cgn)
Var_Set(PREFIX, cpref, pgn, 0);
}
}
- if (p1)
- free(p1);
+ free(p1);
Lst_Close(cgn->iParents);
}
}
@@ -907,8 +904,7 @@ MakeAddAllSrc(void *cgnp, void *pgnp)
}
if (allsrc != NULL)
Var_Append(ALLSRC, allsrc, pgn);
- if (p2)
- free(p2);
+ free(p2);
if (pgn->type & OP_JOIN) {
if (cgn->made == MADE) {
Var_Append(OODATE, child, pgn);
@@ -934,8 +930,7 @@ MakeAddAllSrc(void *cgnp, void *pgnp)
*/
Var_Append(OODATE, child, pgn);
}
- if (p1)
- free(p1);
+ free(p1);
}
return (0);
}
@@ -981,8 +976,7 @@ Make_DoAllVar(GNode *gn)
if (gn->type & OP_JOIN) {
char *p1;
Var_Set(TARGET, Var_Value(ALLSRC, gn, &p1), gn, 0);
- if (p1)
- free(p1);
+ free(p1);
}
gn->flags |= DONE_ALLSRC;
}
diff --git a/make.h b/make.h
index 7579f62..4448505 100644
--- a/make.h
+++ b/make.h
@@ -1,4 +1,4 @@
-/* $NetBSD: make.h,v 1.92 2013/09/04 15:38:26 sjg Exp $ */
+/* $NetBSD: make.h,v 1.98 2016/02/18 18:29:14 christos Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -88,6 +88,7 @@
#include <sys/param.h>
#include <ctype.h>
+#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_STRING_H
@@ -98,6 +99,10 @@
#include <unistd.h>
#include <sys/cdefs.h>
+#ifndef FD_CLOEXEC
+#define FD_CLOEXEC 1
+#endif
+
#if defined(__GNUC__)
#define MAKE_GNUC_PREREQ(x, y) \
((__GNUC__ == (x) && __GNUC_MINOR__ >= (y)) || \
@@ -289,6 +294,7 @@ typedef struct GNode {
#define OP_NOMETA 0x00080000 /* .NOMETA do not create a .meta file */
#define OP_META 0x00100000 /* .META we _do_ want a .meta file */
#define OP_NOMETA_CMP 0x00200000 /* Do not compare commands in .meta file */
+#define OP_SUBMAKE 0x00400000 /* Possibly a submake node */
/* Attributes applied by PMake */
#define OP_TRANSFORM 0x80000000 /* The node is a transformation rule */
#define OP_MEMBER 0x40000000 /* Target is a member of an archive */
@@ -500,6 +506,10 @@ Boolean Main_SetObjdir(const char *);
int mkTempFile(const char *, char **);
int str2Lst_Append(Lst, char *, const char *);
+#define VARF_UNDEFERR 1
+#define VARF_WANTRES 2
+#define VARF_ASSIGN 4
+
#ifdef __GNUC__
#define UNCONST(ptr) ({ \
union __unconst { \
@@ -518,8 +528,15 @@ int str2Lst_Append(Lst, char *, const char *);
#define MAX(a, b) ((a > b) ? a : b)
#endif
+/* At least GNU/Hurd systems lack hardcoded MAXPATHLEN/PATH_MAX */
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
#ifndef MAXPATHLEN
-#define MAXPATHLEN BMAKE_PATH_MAX
+#define MAXPATHLEN BMAKE_PATH_MAX
+#endif
+#ifndef PATH_MAX
+#define PATH_MAX MAXPATHLEN
#endif
#endif /* _MAKE_H_ */
diff --git a/meta.c b/meta.c
index 3ec0bdc..a6b00b5 100644
--- a/meta.c
+++ b/meta.c
@@ -1,4 +1,4 @@
-/* $NetBSD: meta.c,v 1.33 2013/10/01 05:37:17 sjg Exp $ */
+/* $NetBSD: meta.c,v 1.47 2016/02/18 20:33:40 sjg Exp $ */
/*
* Implement 'meta' mode.
@@ -37,8 +37,11 @@
#endif
#include <sys/stat.h>
#include <sys/ioctl.h>
-#include <fcntl.h>
+#ifdef HAVE_LIBGEN_H
#include <libgen.h>
+#elif !defined(HAVE_DIRNAME)
+char * dirname(char *);
+#endif
#include <errno.h>
#if !defined(HAVE_CONFIG_H) || defined(HAVE_ERR_H)
#include <err.h>
@@ -144,8 +147,8 @@ filemon_open(BuildMon *pbm)
err(1, "Could not set filemon file descriptor!");
}
/* we don't need these once we exec */
- (void)fcntl(pbm->mon_fd, F_SETFD, 1);
- (void)fcntl(pbm->filemon_fd, F_SETFD, 1);
+ (void)fcntl(pbm->mon_fd, F_SETFD, FD_CLOEXEC);
+ (void)fcntl(pbm->filemon_fd, F_SETFD, FD_CLOEXEC);
}
/*
@@ -155,8 +158,8 @@ filemon_open(BuildMon *pbm)
static void
filemon_read(FILE *mfp, int fd)
{
- FILE *fp;
char buf[BUFSIZ];
+ int n;
/* Check if we're not writing to a meta data file.*/
if (mfp == NULL) {
@@ -166,17 +169,14 @@ filemon_read(FILE *mfp, int fd)
}
/* rewind */
(void)lseek(fd, (off_t)0, SEEK_SET);
- if ((fp = fdopen(fd, "r")) == NULL)
- err(1, "Could not read build monitor file '%d'", fd);
- fprintf(mfp, "-- filemon acquired metadata --\n");
+ fprintf(mfp, "\n-- filemon acquired metadata --\n");
- while (fgets(buf, sizeof(buf), fp)) {
- fprintf(mfp, "%s", buf);
+ while ((n = read(fd, buf, sizeof(buf))) > 0) {
+ fwrite(buf, 1, n, mfp);
}
fflush(mfp);
- clearerr(fp);
- fclose(fp);
+ close(fd);
}
#endif
@@ -299,8 +299,7 @@ meta_name(struct GNode *gn, char *mname, size_t mnamelen,
}
free(tp);
for (i--; i >= 0; i--) {
- if (p[i])
- free(p[i]);
+ free(p[i]);
}
return (mname);
}
@@ -327,7 +326,7 @@ is_submake(void *cmdp, void *gnp)
}
cp = strchr(cmd, '$');
if ((cp)) {
- mp = Var_Subst(NULL, cmd, gn, FALSE);
+ mp = Var_Subst(NULL, cmd, gn, VARF_WANTRES);
cmd = mp;
}
cp2 = strstr(cmd, p_make);
@@ -352,8 +351,7 @@ is_submake(void *cmdp, void *gnp)
}
}
}
- if (mp)
- free(mp);
+ free(mp);
return (rc);
}
@@ -370,11 +368,10 @@ printCMD(void *cmdp, void *mfpp)
char *cp = NULL;
if (strchr(cmd, '$')) {
- cmd = cp = Var_Subst(NULL, cmd, mfp->gn, FALSE);
+ cmd = cp = Var_Subst(NULL, cmd, mfp->gn, VARF_WANTRES);
}
fprintf(mfp->fp, "CMD %s\n", cmd);
- if (cp)
- free(cp);
+ free(cp);
return 0;
}
@@ -465,7 +462,7 @@ meta_create(BuildMon *pbm, GNode *gn)
char *mp;
/* Describe the target we are building */
- mp = Var_Subst(NULL, "${" MAKE_META_PREFIX "}", gn, 0);
+ mp = Var_Subst(NULL, "${" MAKE_META_PREFIX "}", gn, VARF_WANTRES);
if (*mp)
fprintf(stdout, "%s\n", mp);
free(mp);
@@ -523,8 +520,7 @@ meta_create(BuildMon *pbm, GNode *gn)
}
out:
for (i--; i >= 0; i--) {
- if (p[i])
- free(p[i]);
+ free(p[i]);
}
return (mf.fp);
@@ -608,7 +604,8 @@ meta_mode_init(const char *make_mode)
* We consider ourselves master of all within ${.MAKE.META.BAILIWICK}
*/
metaBailiwick = Lst_Init(FALSE);
- cp = Var_Subst(NULL, "${.MAKE.META.BAILIWICK:O:u:tA}", VAR_GLOBAL, 0);
+ cp = Var_Subst(NULL, "${.MAKE.META.BAILIWICK:O:u:tA}", VAR_GLOBAL,
+ VARF_WANTRES);
if (cp) {
str2Lst_Append(metaBailiwick, cp, NULL);
}
@@ -619,7 +616,8 @@ meta_mode_init(const char *make_mode)
Var_Append(MAKE_META_IGNORE_PATHS,
"/dev /etc /proc /tmp /var/run /var/tmp ${TMPDIR}", VAR_GLOBAL);
cp = Var_Subst(NULL,
- "${" MAKE_META_IGNORE_PATHS ":O:u:tA}", VAR_GLOBAL, 0);
+ "${" MAKE_META_IGNORE_PATHS ":O:u:tA}", VAR_GLOBAL,
+ VARF_WANTRES);
if (cp) {
str2Lst_Append(metaIgnorePaths, cp, NULL);
}
@@ -662,17 +660,21 @@ meta_job_child(Job *job)
{
#ifdef USE_FILEMON
BuildMon *pbm;
- pid_t pid;
if (job != NULL) {
pbm = &job->bm;
} else {
pbm = &Mybm;
}
- pid = getpid();
- if (pbm->mfp != NULL && useFilemon) {
- if (ioctl(pbm->filemon_fd, FILEMON_SET_PID, &pid) < 0) {
- err(1, "Could not set filemon pid!");
+ if (pbm->mfp != NULL) {
+ close(fileno(pbm->mfp));
+ if (useFilemon) {
+ pid_t pid;
+
+ pid = getpid();
+ if (ioctl(pbm->filemon_fd, FILEMON_SET_PID, &pid) < 0) {
+ err(1, "Could not set filemon pid!");
+ }
}
}
#endif
@@ -726,7 +728,8 @@ meta_job_output(Job *job, char *cp, const char *nl)
if (!meta_prefix) {
char *cp2;
- meta_prefix = Var_Subst(NULL, "${" MAKE_META_PREFIX "}", VAR_GLOBAL, 0);
+ meta_prefix = Var_Subst(NULL, "${" MAKE_META_PREFIX "}",
+ VAR_GLOBAL, VARF_WANTRES);
if ((cp2 = strchr(meta_prefix, '$')))
meta_prefix_len = cp2 - meta_prefix;
else
@@ -844,9 +847,10 @@ string_match(const void *p, const void *q)
/*
* When running with 'meta' functionality, a target can be out-of-date
- * if any of the references in it's meta data file is more recent.
+ * if any of the references in its meta data file is more recent.
* We have to track the latestdir on a per-process basis.
*/
+#define LCWD_VNAME_FMT ".meta.%d.lcwd"
#define LDIR_VNAME_FMT ".meta.%d.ldir"
/*
@@ -872,11 +876,14 @@ meta_oodate(GNode *gn, Boolean oodate)
{
static char *tmpdir = NULL;
static char cwd[MAXPATHLEN];
+ char lcwd_vname[64];
char ldir_vname[64];
+ char lcwd[MAXPATHLEN];
char latestdir[MAXPATHLEN];
char fname[MAXPATHLEN];
char fname1[MAXPATHLEN];
char fname2[MAXPATHLEN];
+ char fname3[MAXPATHLEN];
char *p;
char *cp;
char *link_src;
@@ -928,6 +935,8 @@ meta_oodate(GNode *gn, Boolean oodate)
err(1, "Could not get current working directory");
cwdlen = strlen(cwd);
}
+ strlcpy(lcwd, cwd, sizeof(lcwd));
+ strlcpy(latestdir, cwd, sizeof(latestdir));
if (!tmpdir) {
tmpdir = getTmpdir();
@@ -1011,25 +1020,32 @@ meta_oodate(GNode *gn, Boolean oodate)
char *tp;
if (lastpid > 0) {
- /* We need to remember this. */
+ /* We need to remember these. */
+ Var_Set(lcwd_vname, lcwd, VAR_GLOBAL, 0);
Var_Set(ldir_vname, latestdir, VAR_GLOBAL, 0);
}
+ snprintf(lcwd_vname, sizeof(lcwd_vname), LCWD_VNAME_FMT, pid);
snprintf(ldir_vname, sizeof(ldir_vname), LDIR_VNAME_FMT, pid);
lastpid = pid;
ldir = Var_Value(ldir_vname, VAR_GLOBAL, &tp);
if (ldir) {
strlcpy(latestdir, ldir, sizeof(latestdir));
- if (tp)
- free(tp);
- } else
- strlcpy(latestdir, cwd, sizeof(latestdir));
+ free(tp);
+ }
+ ldir = Var_Value(lcwd_vname, VAR_GLOBAL, &tp);
+ if (ldir) {
+ strlcpy(lcwd, ldir, sizeof(lcwd));
+ free(tp);
+ }
}
/* Skip past the pid. */
if (strsep(&p, " ") == NULL)
continue;
#ifdef DEBUG_META_MODE
if (DEBUG(META))
- fprintf(debug_file, "%s: %d: cwd=%s ldir=%s\n", fname, lineno, cwd, latestdir);
+ fprintf(debug_file, "%s: %d: %d: %c: cwd=%s lcwd=%s ldir=%s\n",
+ fname, lineno,
+ pid, buf[0], cwd, lcwd, latestdir);
#endif
break;
}
@@ -1039,6 +1055,7 @@ meta_oodate(GNode *gn, Boolean oodate)
/* Process according to record type. */
switch (buf[0]) {
case 'X': /* eXit */
+ Var_Delete(lcwd_vname, VAR_GLOBAL);
Var_Delete(ldir_vname, VAR_GLOBAL);
lastpid = 0; /* no need to save ldir_vname */
break;
@@ -1050,15 +1067,30 @@ meta_oodate(GNode *gn, Boolean oodate)
child = atoi(p);
if (child > 0) {
+ snprintf(cldir, sizeof(cldir), LCWD_VNAME_FMT, child);
+ Var_Set(cldir, lcwd, VAR_GLOBAL, 0);
snprintf(cldir, sizeof(cldir), LDIR_VNAME_FMT, child);
Var_Set(cldir, latestdir, VAR_GLOBAL, 0);
+#ifdef DEBUG_META_MODE
+ if (DEBUG(META))
+ fprintf(debug_file, "%s: %d: %d: cwd=%s lcwd=%s ldir=%s\n",
+ fname, lineno,
+ child, cwd, lcwd, latestdir);
+#endif
}
}
break;
case 'C': /* Chdir */
- /* Update the latest directory. */
- strlcpy(latestdir, p, sizeof(latestdir));
+ /* Update lcwd and latest directory. */
+ strlcpy(latestdir, p, sizeof(latestdir));
+ strlcpy(lcwd, p, sizeof(lcwd));
+ Var_Set(lcwd_vname, lcwd, VAR_GLOBAL, 0);
+ Var_Set(ldir_vname, lcwd, VAR_GLOBAL, 0);
+#ifdef DEBUG_META_MODE
+ if (DEBUG(META))
+ fprintf(debug_file, "%s: %d: cwd=%s ldir=%s\n", fname, lineno, cwd, lcwd);
+#endif
break;
case 'M': /* renaMe */
@@ -1148,7 +1180,8 @@ meta_oodate(GNode *gn, Boolean oodate)
if ((strstr("tmp", p)))
break;
- if (stat(p, &fs) < 0) {
+ if ((link_src != NULL && lstat(p, &fs) < 0) ||
+ (link_src == NULL && stat(p, &fs) < 0)) {
Lst_AtEnd(missingFiles, bmake_strdup(p));
}
break;
@@ -1177,16 +1210,6 @@ meta_oodate(GNode *gn, Boolean oodate)
break;
}
- if ((cp = strrchr(p, '/'))) {
- cp++;
- /*
- * We don't normally expect to see this,
- * but we do expect it to change.
- */
- if (strcmp(cp, makeDependfile) == 0)
- break;
- }
-
/*
* The rest of the record is the file name.
* Check if it's not an absolute path.
@@ -1207,11 +1230,16 @@ meta_oodate(GNode *gn, Boolean oodate)
snprintf(fname1, sizeof(fname1), "%s/%s", latestdir, p);
sdirs[sdx++] = fname1;
- if (strcmp(latestdir, cwd) != 0) {
- /* Check vs cwd */
- snprintf(fname2, sizeof(fname2), "%s/%s", cwd, p);
+ if (strcmp(latestdir, lcwd) != 0) {
+ /* Check vs lcwd */
+ snprintf(fname2, sizeof(fname2), "%s/%s", lcwd, p);
sdirs[sdx++] = fname2;
}
+ if (strcmp(lcwd, cwd) != 0) {
+ /* Check vs cwd */
+ snprintf(fname3, sizeof(fname3), "%s/%s", cwd, p);
+ sdirs[sdx++] = fname3;
+ }
}
sdirs[sdx++] = NULL;
@@ -1250,6 +1278,10 @@ meta_oodate(GNode *gn, Boolean oodate)
oodate = TRUE;
}
}
+ if (buf[0] == 'E') {
+ /* previous latestdir is no longer relevant */
+ strlcpy(latestdir, lcwd, sizeof(latestdir));
+ }
break;
default:
break;
@@ -1281,7 +1313,7 @@ meta_oodate(GNode *gn, Boolean oodate)
if (DEBUG(META))
fprintf(debug_file, "%s: %d: cannot compare command using .OODATE\n", fname, lineno);
}
- cmd = Var_Subst(NULL, cmd, gn, TRUE);
+ cmd = Var_Subst(NULL, cmd, gn, VARF_WANTRES|VARF_UNDEFERR);
if ((cp = strchr(cmd, '\n'))) {
int n;
@@ -1360,8 +1392,7 @@ meta_oodate(GNode *gn, Boolean oodate)
*/
Var_Delete(OODATE, gn);
Var_Set(OODATE, Var_Value(ALLSRC, gn, &cp), gn, 0);
- if (cp)
- free(cp);
+ free(cp);
}
return oodate;
}
@@ -1388,8 +1419,8 @@ meta_compat_start(void)
if (pipe(childPipe) < 0)
Punt("Cannot create pipe: %s", strerror(errno));
/* Set close-on-exec flag for both */
- (void)fcntl(childPipe[0], F_SETFD, 1);
- (void)fcntl(childPipe[1], F_SETFD, 1);
+ (void)fcntl(childPipe[0], F_SETFD, FD_CLOEXEC);
+ (void)fcntl(childPipe[1], F_SETFD, FD_CLOEXEC);
}
void
diff --git a/metachar.c b/metachar.c
new file mode 100644
index 0000000..4960338
--- /dev/null
+++ b/metachar.c
@@ -0,0 +1,88 @@
+/* $NetBSD: metachar.c,v 1.5 2015/06/19 08:03:35 mlelstv Exp $ */
+
+/*-
+ * Copyright (c) 2015 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#if defined(MAKE_NATIVE) || defined(HAVE_NBTOOL_CONFIG_H)
+#include <sys/cdefs.h>
+#endif
+
+#if defined(__RCSID) && !defined(lint)
+__RCSID("$NetBSD: metachar.c,v 1.5 2015/06/19 08:03:35 mlelstv Exp $");
+#endif
+
+#include "metachar.h"
+/*
+ * The following array is used to make a fast determination of which
+ * characters are interpreted specially by the shell. If a command
+ * contains any of these characters, it is executed by the shell, not
+ * directly by us.
+ *
+ * perhaps move it to ctype?
+ */
+
+unsigned char _metachar[128] = {
+// nul soh stx etx eot enq ack bel
+ 1, 0, 0, 0, 0, 0, 0, 0,
+// bs ht nl vt np cr so si
+ 0, 0, 1, 0, 0, 0, 0, 0,
+// dle dc1 dc2 dc3 dc4 nak syn etb
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// can em sub esc fs gs rs us
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// sp ! " # $ % & '
+ 0, 1, 1, 1, 1, 0, 1, 1,
+// ( ) * + , - . /
+ 1, 1, 1, 0, 0, 0, 0, 0,
+// 0 1 2 3 4 5 6 7
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 8 9 : ; < = > ?
+ 0, 0, 0, 1, 1, 0, 1, 1,
+// @ A B C D E F G
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// H I J K L M N O
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// P Q R S T U V W
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// X Y Z [ \ ] ^ _
+ 0, 0, 0, 1, 1, 1, 1, 0,
+// ` a b c d e f g
+ 1, 0, 0, 0, 0, 0, 0, 0,
+// h i j k l m n o
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// p q r s t u v w
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// x y z { | } ~ del
+ 0, 0, 0, 1, 1, 1, 1, 0,
+};
+
diff --git a/metachar.h b/metachar.h
new file mode 100644
index 0000000..db88d67
--- /dev/null
+++ b/metachar.h
@@ -0,0 +1,61 @@
+/* $NetBSD: metachar.h,v 1.4 2015/06/21 20:26:02 christos Exp $ */
+
+/*-
+ * Copyright (c) 2015 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _METACHAR_H
+#define _METACHAR_H
+
+#include <ctype.h>
+
+extern unsigned char _metachar[];
+
+#define ismeta(c) _metachar[(c) & 0x7f]
+
+static inline int
+hasmeta(const char *cmd)
+{
+ while (!ismeta(*cmd))
+ cmd++;
+
+ return *cmd != '\0';
+}
+
+static inline int
+needshell(const char *cmd, int white)
+{
+ while (!ismeta(*cmd) && *cmd != ':' && *cmd != '=') {
+ if (white && isspace((unsigned char)*cmd))
+ break;
+ cmd++;
+ }
+
+ return *cmd != '\0';
+}
+
+#endif /* _METACHAR_H */
diff --git a/mk/ChangeLog b/mk/ChangeLog
index 80671ef..4687e4d 100644
--- a/mk/ChangeLog
+++ b/mk/ChangeLog
@@ -1,3 +1,248 @@
+2016-02-20 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * dirdeps.mk: we shouldn't normally include .depend but if we do
+ use .dinclude if we can.
+
+2016-02-18 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): 20160218
+ * sys.clean-env.mk: with recent change to Var_Subst()
+ we cannot use the '$$' trick, but .export-literal does the job
+ we need.
+ * auto.dep.mk: make use .dinclude if we can.
+
+
+2016-02-05 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * dirdeps.mk:
+ Add _build_all_dirs such that local.dirdeps.mk can
+ add fully qualified dirs to it.
+ These will be built normally but the current
+ DEP_RELDIR will not depend on then (to avoid cycles).
+ This makes it easy to hook things like unit-tests into build.
+
+
+2016-01-21 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * dirdeps.mk: add bootstrap-empty
+
+2015-12-12 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): 20151212
+ * auto.obj.mk: do not require MAKEOBJDIRPREFIX to exist.
+ only apply :tA to __objdir when comparing to .OBJDIR
+
+2015-11-14 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): 20151111
+
+ * meta.sys.mk: include sys.dependfile.mk
+
+ * sys.mk (OPTIONS_DEFAULT_NO): use options.mk
+ to set MK_AUTO_OBJ and MK_DIRDEPS_BUILD
+ include local.sys.env.mk early
+ include local.sys.mk later
+
+ * own.mk (OPTIONS_DEFAULT_NO): AUTO_OBJ etc moved to sys.mk
+
+2015-11-13 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * meta.sys.mk (META_COOKIE_TOUCH):
+ add ${META_COOKIE_TOUCH} to the end of scripts to touch cookie
+
+ * meta.stage.mk: stage_libs should ignore SYMLINKS.
+
+2015-10-23 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): 20151022
+
+ * sys.mk: BSD/OS does not have 'type' as a shell builtin.
+
+2015-10-20 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): 20151020
+
+ * dirdeps.mk: Add logic for
+ make -f dirdeps.mk some/dir.${TARGET_SPEC}
+
+2015-10-14 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): 20151010
+
+2015-10-02 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * meta.stage.mk: use staging: ${STAGE_TARGETS:...
+ to have stage_lins run last in non-jobs mode.
+ Use .ORDER only for jobs mode.
+
+2015-09-02 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * rst2htm.mk: allow for per target flags etc.
+
+2015-09-01 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): 20150901
+
+ * doc.mk: create dir if needed use DOC_INSTALL_OWN
+
+2015-06-15 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): 20150615
+
+ * auto.obj.mk: allow use of MAKEOBJDIRPREFIX too.
+ Follow make's normal precedence rules.
+
+ * gendirdeps.mk: allow customization of the header.
+ eg. for FreeBSD:
+ GENDIRDEPS_HEADER= echo '\# ${FreeBSD:L:@v@$$$v$$ @:M*F*}';
+
+ * meta.autodep.mk: ignore dirdeps.cache*
+
+ * meta.stage.mk: when bootstrapping options it can be handy to
+ throw warnings rather than errors for staging conflicts.
+
+ * meta.sys.mk: include local.meta.sys.mk for customization
+
+2015-06-06 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): 20150606
+
+ * dirdeps.mk: don't rely on manually maintained Makefile.depend
+ to set DEP_RELDIR and reset DIRDEPS.
+ By setting DEP_RELDIR ourselves we can skip :tA
+
+ * gendirdeps.mk: skip setting DEP_RELDIR.
+
+2015-05-24 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * dirdeps.mk: avoid wildcards like make(bootstrap*)
+
+2015-05-20 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): 20150520
+
+ * dirdeps.mk: when we are building dirdeps cache file we *want*
+ meta_oodate to look at all the Makefile.depend files, so
+ set .MAKE.DEPENDFILE to something that won't match.
+
+ * meta.stage.mk: for STAGE_AS_* basename of file may not be unique
+ so first use absolute path as key.
+ Also skip staging at level 0.
+
+2015-04-30 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): 20150430
+
+ * dirdeps.mk: fix _count_dirdeps for non-cache case.
+
+2015-04-16 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): 20150411
+ bump version
+
+ * own.mk: put AUTO_OBJ in OPTIONS_DEFAULT_NO rather than YES.
+ it is here mainly for documentation purposes, since
+ if using auto.obj.mk it is better done via sys.mk
+
+2015-04-01 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): 20150401
+
+ * meta2deps.sh: support @list
+
+ * meta2deps.py: updates from Juniper
+ o add EXCLUDES
+ o skip bogus input files.
+ o treat 'M' and 'L' as both an 'R' and a 'W'
+
+2015-03-03 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): 20150303
+
+ * dirdeps.mk: if MK_DIRDEPS_CACHE is yes, use dirdeps-cache
+ which is built via sub-make so we have a .meta file to tell if
+ it is out-of-date.
+ The dirdeps-cache contains the same dependency rules that we
+ normaly construct on the fly.
+ This adds a few seconds overhead when the cache is out of date,
+ but for a large target, the savings can be significant (10-20min).
+
+2014-11-18 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): 20141118
+
+ * meta.stage.mk: add stale_staged
+
+ * dirdeps.mk (_DIRDEP_USE_LEVEL): allow this to be tweaked
+ only useful under very rare conditions such as
+ FreeBSD's make universe.
+
+ * auto.obj.mk: Allow MK_AUTO_OBJ to set MKOBJDIRS=auto
+
+2014-11-11 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): 20141111
+
+ * mkopt.sh: use consistent semantics for _mk_opt and _mk_opts
+
+2014-11-09 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * FILES: include mkopt.sh which allows handling options in shell
+ scripts in a manner compatible with options.mk
+
+2014-10-12 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * meta.stage.mk: ensure only _STAGED_DIRS under objroot are used
+ for GENDIRDEPS_FILTER to avoid surprises.
+
+2014-10-10 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * dirdeps.mk (NSkipHostDir): this needs SRCTOP prepended since by
+ the time it is applied to __depdirs they have.
+
+ * dirdeps.mk fix filtering of _machines since M_dep_qual_fixes
+ expects patterns like *.${MACHINE}
+
+ * cython.mk (pyprefix?): use pyprefix to find python bits
+ since prefix might be something else (where we install our
+ stuff)
+
+2014-09-11 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): 20140911
+
+ * dirdeps.mk: add bootstrap target to simplify adding support for
+ new MACHINE.
+
+2014-09-01 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * gendirdeps.mk: Add handling of GENDIRDEPS_FILTER_DIR_VARS and
+ GENDIRDEPS_FILTER_VARS to make it easier to produce sharable
+ Makefile.depend files.
+
+2014-08-28 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): 20140828
+
+ * cython.mk: capture logic for building python extension modules
+ with Cython.
+
+2014-08-08 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * meta.stage.mk (_STAGE_AS_BASENAME_USE): Add StageAs variant
+
+2014-08-02 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): 20140801
+
+ * dep.mk: use explicit MKDEP_MK rather than overload MKDEP to
+ identify the autodep.mk variant.
+
+ * sys.dependfile.mk: delete .MAKE.DEPENDFILE if its
+ initial value does not match .MAKE.DEPENDFILE_PREFIX
+
+ * meta.autodep.mk: if _bootstrap_dirdeps add RELDIR to DIRDEPS
+
2014-05-22 Simon J. Gerraty <sjg@bad.crufty.net>
* install-mk (MK_VERSION): 20140522
@@ -275,7 +520,7 @@
needed.
* gendirdeps.mk: only produce unqualified deps if no
.MAKE.DEPENDFILE_PREFERENCE ends in .${MACHINE}
- * meta.subdir.mk: apply SUBDIREPS_FILTER
+ * meta.subdir.mk: apply SUBDIRDEPS_FILTER
2012-04-20 Simon J. Gerraty <sjg@bad.crufty.net>
diff --git a/mk/FILES b/mk/FILES
index 443aa2e..0a72c67 100644
--- a/mk/FILES
+++ b/mk/FILES
@@ -5,6 +5,7 @@ auto.obj.mk
autoconf.mk
autodep.mk
auto.dep.mk
+cython.mk
dep.mk
doc.mk
dpadd.mk
@@ -20,7 +21,9 @@ libnames.mk
libs.mk
links.mk
man.mk
+manifest.mk
mk-files.txt
+mkopt.sh
nls.mk
obj.mk
options.mk
@@ -49,6 +52,7 @@ sys/SunOS.mk
sys/UnixWare.mk
target-flags.mk
warnings.mk
+whats.mk
yacc.mk
dirdeps.mk
gendirdeps.mk
diff --git a/mk/auto.dep.mk b/mk/auto.dep.mk
index bb2d4c1..6bc53e5 100644
--- a/mk/auto.dep.mk
+++ b/mk/auto.dep.mk
@@ -1,6 +1,6 @@
#
# RCSid:
-# $Id: auto.dep.mk,v 1.2 2010/04/19 17:37:19 sjg Exp $
+# $Id: auto.dep.mk,v 1.4 2016/02/18 21:16:39 sjg Exp $
#
# @(#) Copyright (c) 2010, Simon J. Gerraty
#
@@ -18,7 +18,7 @@
# This module provides automagic dependency generation along the
# lines suggested in the GNU make.info
-# set MKDEP=auto.dep and dep.mk will include us
+# set MKDEP_MK=auto.dep.mk and dep.mk will include us
# This version differs from autodep.mk, in that
# we use ${.TARGET:T}.d rather than ${.TARGET:T:R}.d
@@ -45,6 +45,7 @@ CXXFLAGS += ${CFLAGS_MD} ${CFLAGS_MF}
CLEANFILES += .depend ${.MAKE.DEPENDFILE} *.d
+.if ${MAKE_VERSION} < 20160218
# skip generating dependfile for misc targets
.if ${.TARGETS:Uall:M*all} != ""
.END: ${.MAKE.DEPENDFILE}
@@ -60,5 +61,14 @@ ${.MAKE.DEPENDFILE}: ${OBJS} ${POBJS} ${SOBJS}
-@for f in ${.ALLSRC:M*o:T:O:u:%=%.d}; do \
echo ".-include \"$$f\""; \
done > $@
+.else
+# we have .dinclude
+.if empty(_SKIP_BUILD)
+_all_objs = ${OBJS} ${POBJS} ${SOBJS}
+.for d in ${_all_objs:M*o:T:O:u:%=%.d}
+.dinclude "$d"
+.endfor
+.endif
.endif
+.endif
diff --git a/mk/auto.obj.mk b/mk/auto.obj.mk
index adccd4b..2395f64 100644
--- a/mk/auto.obj.mk
+++ b/mk/auto.obj.mk
@@ -1,4 +1,4 @@
-# $Id: auto.obj.mk,v 1.8 2011/08/08 17:35:20 sjg Exp $
+# $Id: auto.obj.mk,v 1.12 2015/12/16 01:57:06 sjg Exp $
#
# @(#) Copyright (c) 2004, Simon J. Gerraty
#
@@ -34,11 +34,18 @@ Mkdirs= Mkdirs() { \
# if MKOBJDIRS is set to auto (and NOOBJ isn't defined) do some magic...
# This will automatically create objdirs as needed.
# Skip it if we are just doing 'clean'.
+.if ${MK_AUTO_OBJ:Uno} == "yes"
+MKOBJDIRS= auto
+.endif
.if !defined(NOOBJ) && !defined(NO_OBJ) && ${MKOBJDIRS:Uno} == auto
# Use __objdir here so it is easier to tweak without impacting
# the logic.
-__objdir?= ${MAKEOBJDIR}
-.if ${.OBJDIR} != ${__objdir}
+.if !empty(MAKEOBJDIRPREFIX)
+__objdir?= ${MAKEOBJDIRPREFIX}${.CURDIR}
+.endif
+__objdir?= ${MAKEOBJDIR:Uobj}
+__objdir:= ${__objdir}
+.if ${.OBJDIR:tA} != ${__objdir:tA}
# We need to chdir, make the directory if needed
.if !exists(${__objdir}/) && \
(${.TARGETS} == "" || ${.TARGETS:Nclean*:N*clean:Ndestroy*} != "")
@@ -49,8 +56,8 @@ __objdir_made != echo ${__objdir}/; umask ${OBJDIR_UMASK:U002}; \
.endif
# This causes make to use the specified directory as .OBJDIR
.OBJDIR: ${__objdir}
-.if ${.OBJDIR} != ${__objdir} && ${__objdir_made:Uno:M${__objdir}/*} != ""
-.error could not use ${__objdir}
+.if ${.OBJDIR:tA} != ${__objdir:tA} && ${__objdir_made:Uno:M${__objdir}/*} != ""
+.error could not use ${__objdir}: .OBJDIR=${.OBJDIR}
.endif
.endif
.endif
diff --git a/mk/autodep.mk b/mk/autodep.mk
index 818c474..84dea81 100644
--- a/mk/autodep.mk
+++ b/mk/autodep.mk
@@ -1,6 +1,6 @@
#
# RCSid:
-# $Id: autodep.mk,v 1.33 2014/04/05 22:56:54 sjg Exp $
+# $Id: autodep.mk,v 1.34 2014/08/04 05:12:27 sjg Exp $
#
# @(#) Copyright (c) 1999-2010, Simon J. Gerraty
#
@@ -19,14 +19,9 @@
# The depend target is mainly for backwards compatibility,
# dependencies are normally updated as part of compilation.
-# set MKDEP=autodep and dep.mk will include us
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
-# different versions of bsd.dep.mk use these
-MKDEP=autodep
-MKDEPCMD=autodep
-
DEPENDFILE?= .depend
.for d in ${DEPENDFILE:N.depend}
# bmake only groks .depend
diff --git a/mk/cython.mk b/mk/cython.mk
new file mode 100644
index 0000000..7d9b8cd
--- /dev/null
+++ b/mk/cython.mk
@@ -0,0 +1,96 @@
+# RCSid:
+# $Id: cython.mk,v 1.6 2014/10/15 06:23:51 sjg Exp $
+#
+# @(#) Copyright (c) 2014, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+# this is what we build
+CYTHON_MODULE = ${CYTHON_MODULE_NAME}${CYTHON_PYVERSION}.so
+
+CYTHON_MODULE_NAME?= it
+CYTHON_SRCS?= ${CYTHON_MODULE_NAME}.pyx
+
+# this is where we save generated src
+CYTHON_SAVEGENDIR?= ${.CURDIR}/gen
+
+# pyprefix is where python bits are
+# which may not be where we want to put ours (prefix)
+.if exists(/usr/pkg/include)
+pyprefix?= /usr/pkg
+.endif
+pyprefix?= /usr/local
+
+PYTHON_VERSION?= 2.7
+PYTHON_H?= ${pyprefix}/include/python${PYTHON_VERSION}/Python.h
+PYVERSION:= ${PYTHON_VERSION:C,\..*,,}
+
+# set this empty if you don't want to handle multiple versions
+.if !defined(CYTHON_PYVERSION)
+CYTHON_PYVERSION:= ${PYVERSION}
+.endif
+
+CFLAGS+= -I${PYTHON_H:H}
+
+CYTHON_GENSRCS= ${CYTHON_SRCS:R:S,$,${CYTHON_PYVERSION}.c,}
+SRCS+= ${CYTHON_GENSRCS}
+
+.SUFFIXES: .pyx .c .So
+
+CYTHON?= ${pyprefix}/bin/cython
+
+# if we don't have cython we can use pre-generated srcs
+.if ${type ${CYTHON} 2> /dev/null || echo:L:sh:M/*} == ""
+.PATH: ${CYTHON_SAVEGENDIR}
+.else
+
+.if !empty(CYTHON_PYVERSION)
+.for c in ${CYTHON_SRCS}
+${c:R}${CYTHON_PYVERSION}.${c:E}: $c
+ ln -sf ${.ALLSRC:M*pyx} ${.TARGET}
+.endfor
+.endif
+
+.pyx.c:
+ ${CYTHON} ${CYTHON_FLAGS} -${PYVERSION} -o ${.TARGET} ${.IMPSRC}
+
+
+save-gen: ${CYTHON_GENSRCS}
+ mkdir -p ${CYTHON_SAVEGENDIR}
+ cp -p ${.ALLSRC} ${CYTHON_SAVEGENDIR}
+
+.endif
+
+COMPILE.c?= ${CC} -c ${CFLAGS}
+
+.c.So:
+ ${COMPILE.c} ${PICFLAG} ${CC_PIC} ${.IMPSRC} -o ${.TARGET}
+
+${CYTHON_MODULE}: ${SRCS:S,.c,.So,}
+ ${CC} ${CC_SHARED:U-shared} -o ${.TARGET} ${.ALLSRC:M*.So} ${LDADD}
+
+# conf.host_target() is limited to uname -m rather than uname -p
+_HOST_MACHINE!= uname -m
+.if ${HOST_TARGET:M*${_HOST_MACHINE}} == ""
+PY_HOST_TARGET:= ${HOST_TARGET:S,${_HOST_ARCH:U${uname -p:L:sh}}$,${_HOST_MACHINE},}
+.endif
+
+MODULE_BINDIR?= ${.CURDIR:H}/${PY_HOST_TARGET:U${HOST_TARGET}}
+
+build-cython-module: ${CYTHON_MODULE}
+
+install-cython-module: ${CYTHON_MODULE}
+ test -d ${DESTDIR}${MODULE_BINDIR} || \
+ ${INSTALL} -d ${DESTDIR}${MODULE_BINDIR}
+ ${INSTALL} -m 755 ${.ALLSRC} ${DESTDIR}${MODULE_BINDIR}
+
+CLEANFILES+= *.So ${CYTHON_MODULE}
diff --git a/mk/dep.mk b/mk/dep.mk
index b754500..b07191a 100644
--- a/mk/dep.mk
+++ b/mk/dep.mk
@@ -1,4 +1,4 @@
-# $Id: dep.mk,v 1.16 2012/11/11 22:37:02 sjg Exp $
+# $Id: dep.mk,v 1.17 2014/08/04 05:12:27 sjg Exp $
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
@@ -34,21 +34,15 @@ MKDEP ?= ${MKDEP_CMD}
.NOPATH: .depend
-.if ${MKDEP} == "auto.dep" && make(depend)
+.if ${MKDEP_MK:Uno} == "auto.dep.mk" && make(depend)
# auto.dep.mk does not "do" depend
MK_AUTODEP= no
.endif
.if ${MK_AUTODEP} == yes
-.if ${MKDEP:T:S,auto,,} != ${MKDEP:T}
-.include <${MKDEP}.mk>
+MKDEP_MK ?= autodep.mk
+.include <${MKDEP_MK}>
.else
-.include <autodep.mk>
-.endif
-.else
-.if ${MKDEP:T:S,auto,,} != ${MKDEP:T}
-MKDEP = ${MKDEP_CMD}
-.endif
MKDEP_ENV_VARS += CC CXX
.for v in ${MKDEP_ENV_VARS:O:u}
.if !empty($v)
diff --git a/mk/dirdeps.mk b/mk/dirdeps.mk
index 8c342be..ec37e35 100644
--- a/mk/dirdeps.mk
+++ b/mk/dirdeps.mk
@@ -1,4 +1,4 @@
-# $Id: dirdeps.mk,v 1.35 2014/05/03 06:27:56 sjg Exp $
+# $Id: dirdeps.mk,v 1.59 2016/02/26 23:32:29 sjg Exp $
# Copyright (c) 2010-2013, Juniper Networks, Inc.
# All rights reserved.
@@ -111,7 +111,9 @@
# TARGET_SPEC = ${TARGET_SPEC_VARS:@v@${$v:U}@:ts,}
#
-.if ${.MAKE.LEVEL} == 0
+# touch this at your peril
+_DIRDEP_USE_LEVEL?= 0
+.if ${.MAKE.LEVEL} == ${_DIRDEP_USE_LEVEL}
# only the first instance is interested in all this
# First off, we want to know what ${MACHINE} to build for.
@@ -119,8 +121,17 @@
# and non-specific Makefile.depend*
.if !target(_DIRDEP_USE)
+# make sure we get the behavior we expect
+.MAKE.SAVE_DOLLARS = no
+
# do some setup we only need once
_CURDIR ?= ${.CURDIR}
+_OBJDIR ?= ${.OBJDIR}
+
+now_utc = ${%s:L:gmtime}
+.if !defined(start_utc)
+start_utc := ${now_utc}
+.endif
# make sure these are empty to start with
_DEP_TARGET_SPEC =
@@ -201,7 +212,7 @@ _last_dependfile := ${.INCLUDEDFROMFILE:M${.MAKE.DEPENDFILE_PREFIX}*}
.else
_last_dependfile := ${.MAKE.MAKEFILES:M*/${.MAKE.DEPENDFILE_PREFIX}*:[-1]}
.endif
-.if !empty(_debug_reldir)
+.if ${_debug_reldir:U0}
.info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: _last_dependfile='${_last_dependfile}'
.endif
@@ -234,10 +245,22 @@ DEP_${TARGET_SPEC_VARS:[$i]} := ${_tspec:[$i]}
DEP_MACHINE := ${_DEP_TARGET_SPEC}
.endif
-# pickup customizations
-# as below you can use !target(_DIRDEP_USE) to protect things
-# which should only be done once.
-.-include "local.dirdeps.mk"
+.if ${MAKEFILE:T} == ${.PARSEFILE} && empty(DIRDEPS) && ${.TARGETS:Uall:M*/*} != ""
+# This little trick let's us do
+#
+# mk -f dirdeps.mk some/dir.${TARGET_SPEC}
+#
+all:
+${.TARGETS:Nall}: all
+DIRDEPS := ${.TARGETS:M*/*}
+# so that -DNO_DIRDEPS works
+DEP_RELDIR := ${DIRDEPS:R:[1]}
+# disable DIRDEPS_CACHE as it does not like this trick
+MK_DIRDEPS_CACHE = no
+.endif
+
+# reset each time through
+_build_all_dirs =
# the first time we are included the _DIRDEP_USE target will not be defined
# we can use this as a clue to do initialization and other one time things.
@@ -257,10 +280,18 @@ DEBUG_DIRDEPS ?= no
# remember the initial value of DEP_RELDIR - we test for it below.
_DEP_RELDIR := ${DEP_RELDIR}
+.endif
+
+# pickup customizations
+# as below you can use !target(_DIRDEP_USE) to protect things
+# which should only be done once.
+.-include "local.dirdeps.mk"
+
+.if !target(_DIRDEP_USE)
# things we skip for host tools
SKIP_HOSTDIR ?=
-NSkipHostDir = ${SKIP_HOSTDIR:N*.host:S,$,.host,:N.host:${M_ListToSkip}}
+NSkipHostDir = ${SKIP_HOSTDIR:N*.host*:S,$,.host*,:N.host*:S,^,${SRCTOP}/,:${M_ListToSkip}}
# things we always skip
# SKIP_DIRDEPS allows for adding entries on command line.
@@ -332,8 +363,81 @@ _only_machines := ${_only_machines:${NOT_MACHINE_LIST:${M_ListToSkip}}}
DIRDEPS ?= ${RELDIR}
.endif # target
-_debug_reldir := ${DEBUG_DIRDEPS:@x@${DEP_RELDIR:M$x}${${DEP_RELDIR}.${DEP_MACHINE}:L:M$x}@}
-_debug_search := ${DEBUG_DIRDEPS:@x@${DEP_RELDIR:M$x}${${DEP_RELDIR}.depend:L:M$x}@}
+# if repeatedly building the same target,
+# we can avoid the overhead of re-computing the tree dependencies.
+MK_DIRDEPS_CACHE ?= no
+BUILD_DIRDEPS_CACHE ?= no
+BUILD_DIRDEPS ?= yes
+
+.if !defined(NO_DIRDEPS)
+.if ${MK_DIRDEPS_CACHE} == "yes"
+# this is where we will cache all our work
+DIRDEPS_CACHE?= ${_OBJDIR}/dirdeps.cache${.TARGETS:Nall:O:u:ts-:S,/,_,g:S,^,.,:N.}
+
+# just ensure this exists
+build-dirdeps:
+
+M_oneperline = @x@\\${.newline} $$x@
+
+.if ${BUILD_DIRDEPS_CACHE} == "no"
+.if !target(dirdeps-cached)
+# we do this via sub-make
+BUILD_DIRDEPS = no
+
+dirdeps: dirdeps-cached
+dirdeps-cached: ${DIRDEPS_CACHE} .MAKE
+ @echo "${TRACER}Using ${DIRDEPS_CACHE}"
+ @MAKELEVEL=${.MAKE.LEVEL} ${.MAKE} -C ${_CURDIR} -f ${DIRDEPS_CACHE} \
+ dirdeps MK_DIRDEPS_CACHE=no BUILD_DIRDEPS=no
+
+# these should generally do
+BUILD_DIRDEPS_MAKEFILE ?= ${MAKEFILE}
+BUILD_DIRDEPS_TARGETS ?= ${.TARGETS}
+
+# we need the .meta file to ensure we update if
+# any of the Makefile.depend* changed.
+# We do not want to compare the command line though.
+${DIRDEPS_CACHE}: .META .NOMETA_CMP
+ +@{ echo '# Autogenerated - do NOT edit!'; echo; \
+ echo 'BUILD_DIRDEPS=no'; echo; \
+ echo '.include <dirdeps.mk>'; \
+ } > ${.TARGET}.new
+ +@MAKELEVEL=${.MAKE.LEVEL} DIRDEPS_CACHE=${DIRDEPS_CACHE} \
+ DIRDEPS="${DIRDEPS}" \
+ MAKEFLAGS= ${.MAKE} -C ${_CURDIR} -f ${BUILD_DIRDEPS_MAKEFILE} \
+ ${BUILD_DIRDEPS_TARGETS} BUILD_DIRDEPS_CACHE=yes \
+ .MAKE.DEPENDFILE=.none \
+ ${.MAKEFLAGS:tW:S,-D ,-D,g:tw:M*WITH*} \
+ 3>&1 1>&2 | sed 's,${SRCTOP},$${SRCTOP},g' >> ${.TARGET}.new && \
+ mv ${.TARGET}.new ${.TARGET}
+
+.endif
+.elif !target(_count_dirdeps)
+# we want to capture the dirdeps count in the cache
+.END: _count_dirdeps
+_count_dirdeps: .NOMETA
+ @echo '.info $${.newline}$${TRACER}Makefiles read: total=${.MAKE.MAKEFILES:[#]} depend=${.MAKE.MAKEFILES:M*depend*:[#]} dirdeps=${.ALLTARGETS:M${SRCTOP}*:O:u:[#]}' >&3
+
+.endif
+.elif !make(dirdeps) && !target(_count_dirdeps)
+beforedirdeps: _count_dirdeps
+_count_dirdeps: .NOMETA
+ @echo "${TRACER}Makefiles read: total=${.MAKE.MAKEFILES:[#]} depend=${.MAKE.MAKEFILES:M*depend*:[#]} dirdeps=${.ALLTARGETS:M${SRCTOP}*:O:u:[#]} seconds=`expr ${now_utc} - ${start_utc}`"
+
+.endif
+.endif
+
+.if ${BUILD_DIRDEPS} == "yes"
+.if ${DEBUG_DIRDEPS:@x@${DEP_RELDIR:M$x}${${DEP_RELDIR}.${DEP_MACHINE}:L:M$x}@} != ""
+_debug_reldir = 1
+.else
+_debug_reldir = 0
+.endif
+.if ${DEBUG_DIRDEPS:@x@${DEP_RELDIR:M$x}${${DEP_RELDIR}.depend:L:M$x}@} != ""
+_debug_search = 1
+.else
+_debug_search = 0
+.endif
# the rest is done repeatedly for every Makefile.depend we read.
# if we are anything but the original dir we care only about the
@@ -368,7 +472,8 @@ _machines := ${_machines:O:u}
# we need to tweak _machines
_dm := ${DEP_MACHINE}
# apply the same filtering that we do when qualifying DIRDEPS.
-_machines := ${_machines:@DEP_MACHINE@${DEP_TARGET_SPEC}@:${M_dep_qual_fixes:ts:}:O:u}
+# M_dep_qual_fixes expects .${MACHINE}* so add (and remove) '.'
+_machines := ${_machines:@DEP_MACHINE@${DEP_TARGET_SPEC}@:S,^,.,:${M_dep_qual_fixes:ts:}:O:u:S,^.,,}
DEP_MACHINE := ${_dm}
.endif
@@ -383,12 +488,16 @@ _build_dirs += ${_machines:@m@${_CURDIR}.$m@}
_build_dirs += ${_machines:N${DEP_TARGET_SPEC}:@m@${_CURDIR}.$m@}
.if ${DEP_TARGET_SPEC} == ${TARGET_SPEC}
# pickup local dependencies now
+.if ${MAKE_VERSION} < 20160220
.-include <.depend>
+.else
+.dinclude <.depend>
+.endif
.endif
.endif
.endif
-.if !empty(_debug_reldir)
+.if ${_debug_reldir}
.info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: DIRDEPS='${DIRDEPS}'
.info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: _machines='${_machines}'
.endif
@@ -419,7 +528,7 @@ __hostdpadd := ${DPADD:U.:M${HOST_OBJTOP}/*:S,${HOST_OBJTOP}/,,:H:${NSkipDir}:${
__qual_depdirs += ${__hostdpadd}
.endif
-.if !empty(_debug_reldir)
+.if ${_debug_reldir}
.info depdirs=${__depdirs}
.info qualified=${__qual_depdirs}
.info unqualified=${__unqual_depdirs}
@@ -429,23 +538,33 @@ __qual_depdirs += ${__hostdpadd}
_build_dirs += \
${__qual_depdirs:M*.host:${NSkipHostDir}:N.host} \
${__qual_depdirs:N*.host} \
- ${_machines:@m@${__unqual_depdirs:@d@$d.$m@}@}
+ ${_machines:Mhost*:@m@${__unqual_depdirs:@d@$d.$m@}@:${NSkipHostDir}:N.host} \
+ ${_machines:Nhost*:@m@${__unqual_depdirs:@d@$d.$m@}@}
# qualify everything now
_build_dirs := ${_build_dirs:${M_dep_qual_fixes:ts:}:O:u}
+_build_all_dirs += ${_build_dirs}
+_build_all_dirs := ${_build_all_dirs:O:u}
+
.endif # empty DIRDEPS
# Normally if doing make -V something,
# we do not want to waste time chasing DIRDEPS
# but if we want to count the number of Makefile.depend* read, we do.
.if ${.MAKEFLAGS:M-V${_V_READ_DIRDEPS}} == ""
-.if !empty(_build_dirs)
+.if !empty(_build_all_dirs)
+.if ${BUILD_DIRDEPS_CACHE} == "yes"
+x!= { echo; echo '\# ${DEP_RELDIR}.${DEP_TARGET_SPEC}'; \
+ echo 'dirdeps: ${_build_all_dirs:${M_oneperline}}'; echo; } >&3; echo
+x!= { ${_build_all_dirs:@x@${target($x):?:echo '$x: _DIRDEP_USE';}@} echo; } >&3; echo
+.else
# this makes it all happen
-dirdeps: ${_build_dirs}
-${_build_dirs}: _DIRDEP_USE
+dirdeps: ${_build_all_dirs}
+.endif
+${_build_all_dirs}: _DIRDEP_USE
-.if !empty(_debug_reldir)
+.if ${_debug_reldir}
.info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: needs: ${_build_dirs}
.endif
@@ -454,29 +573,37 @@ ${_build_dirs}: _DIRDEP_USE
# it would be nice to do :N${.TARGET}
.if !empty(__qual_depdirs)
.for q in ${__qual_depdirs:${M_dep_qual_fixes:ts:}:E:O:u:N$m}
-.if !empty(_debug_reldir) || ${DEBUG_DIRDEPS:@x@${${DEP_RELDIR}.$m:L:M$x}${${DEP_RELDIR}.$q:L:M$x}@} != ""
+.if ${_debug_reldir} || ${DEBUG_DIRDEPS:@x@${${DEP_RELDIR}.$m:L:M$x}${${DEP_RELDIR}.$q:L:M$x}@} != ""
.info ${DEP_RELDIR}.$m: graph: ${_build_dirs:M*.$q}
.endif
+.if ${BUILD_DIRDEPS_CACHE} == "yes"
+x!= { echo; echo '${_this_dir}.$m: ${_build_dirs:M*.$q:${M_oneperline}}'; echo; } >&3; echo
+.else
${_this_dir}.$m: ${_build_dirs:M*.$q}
+.endif
.endfor
.endif
-.if !empty(_debug_reldir)
+.if ${_debug_reldir}
.info ${DEP_RELDIR}.$m: graph: ${_build_dirs:M*.$m:N${_this_dir}.$m}
.endif
+.if ${BUILD_DIRDEPS_CACHE} == "yes"
+x!= { echo; echo '${_this_dir}.$m: ${_build_dirs:M*.$m:N${_this_dir}.$m:${M_oneperline}}'; echo; } >&3; echo
+.else
${_this_dir}.$m: ${_build_dirs:M*.$m:N${_this_dir}.$m}
+.endif
.endfor
.endif
# Now find more dependencies - and recurse.
-.for d in ${_build_dirs}
+.for d in ${_build_all_dirs}
.if ${_DIRDEP_CHECKED:M$d} == ""
# once only
_DIRDEP_CHECKED += $d
-.if !empty(_debug_search)
+.if ${_debug_search}
.info checking $d
.endif
-# Note: _build_dirs is fully qualifed so d:R is always the directory
+# Note: _build_all_dirs is fully qualifed so d:R is always the directory
.if exists(${d:R})
# Warning: there is an assumption here that MACHINE is always
# the first entry in TARGET_SPEC_VARS.
@@ -485,14 +612,19 @@ _m := ${.MAKE.DEPENDFILE_PREFERENCE:T:S;${TARGET_SPEC}$;${d:E};:S;${MACHINE};${d
.if !empty(_m)
# M_dep_qual_fixes isn't geared to Makefile.depend
_qm := ${_m:C;(\.depend)$;\1.${d:E};:${M_dep_qual_fixes:ts:}}
-.if !empty(_debug_search)
+.if ${_debug_search}
.info Looking for ${_qm}
.endif
# we pass _DEP_TARGET_SPEC to tell the next step what we want
_DEP_TARGET_SPEC := ${d:E}
# some makefiles may still look at this
_DEP_MACHINE := ${d:E:C/,.*//}
-.if !empty(_debug_reldir) && ${_qm} != ${_m}
+# set this "just in case"
+# we can skip :tA since we computed the path above
+DEP_RELDIR := ${_m:H:S,${SRCTOP}/,,}
+# and reset this
+DIRDEPS =
+.if ${_debug_reldir} && ${_qm} != ${_m}
.info loading ${_m} for ${d:E}
.endif
.include <${_m}>
@@ -502,12 +634,65 @@ _DEP_MACHINE := ${d:E:C/,.*//}
.endfor
.endif # -V
+.endif # BUILD_DIRDEPS
.elif ${.MAKE.LEVEL} > 42
.error You should have stopped recursing by now.
.else
-_DEP_RELDIR := ${DEP_RELDIR}
+# we are building something
+DEP_RELDIR := ${RELDIR}
+_DEP_RELDIR := ${RELDIR}
# pickup local dependencies
+.if ${MAKE_VERSION} < 20160220
.-include <.depend>
+.else
+.dinclude <.depend>
+.endif
.endif
+# bootstrapping new dependencies made easy?
+.if !target(bootstrap) && (make(bootstrap) || \
+ make(bootstrap-this) || \
+ make(bootstrap-recurse) || \
+ make(bootstrap-empty))
+
+.if exists(${.CURDIR}/${.MAKE.DEPENDFILE:T})
+# stop here
+${.TARGETS:Mboot*}:
+.elif !make(bootstrap-empty)
+# find a Makefile.depend to use as _src
+_src != cd ${.CURDIR} && for m in ${.MAKE.DEPENDFILE_PREFERENCE:T:S,${MACHINE},*,}; do test -s $$m || continue; echo $$m; break; done; echo
+.if empty(_src)
+.error cannot find any of ${.MAKE.DEPENDFILE_PREFERENCE:T}${.newline}Use: bootstrap-empty
+.endif
+
+_src?= ${.MAKE.DEPENDFILE:T}
+
+# just create Makefile.depend* for this dir
+bootstrap-this: .NOTMAIN
+ @echo Bootstrapping ${RELDIR}/${.MAKE.DEPENDFILE:T} from ${_src:T}
+ (cd ${.CURDIR} && sed 's,${_src:E},${MACHINE},g' ${_src} > ${.MAKE.DEPENDFILE:T})
+
+# create Makefile.depend* for this dir and its dependencies
+bootstrap: bootstrap-recurse
+bootstrap-recurse: bootstrap-this
+
+_mf := ${.PARSEFILE}
+bootstrap-recurse: .NOTMAIN .MAKE
+ @cd ${SRCTOP} && \
+ for d in `cd ${RELDIR} && ${.MAKE} -B -f ${"${.MAKEFLAGS:M-n}":?${_src}:${.MAKE.DEPENDFILE:T}} -V DIRDEPS`; do \
+ test -d $$d || d=$${d%.*}; \
+ test -d $$d || continue; \
+ echo "Checking $$d for bootstrap ..."; \
+ (cd $$d && ${.MAKE} -f ${_mf} bootstrap-recurse); \
+ done
+
+.endif
+
+# create an empty Makefile.depend* to get the ball rolling.
+bootstrap-empty: .NOTMAIN .NOMETA
+ @echo Creating empty ${RELDIR}/${.MAKE.DEPENDFILE:T}; \
+ echo You need to build ${RELDIR} to correctly populate it.
+ @{ echo DIRDEPS=; echo ".include <dirdeps.mk>"; } > ${.CURDIR}/${.MAKE.DEPENDFILE:T}
+
+.endif
diff --git a/mk/doc.mk b/mk/doc.mk
index d496c42..d1385e9 100644
--- a/mk/doc.mk
+++ b/mk/doc.mk
@@ -1,4 +1,4 @@
-# $Id: doc.mk,v 1.4 2012/11/11 22:37:02 sjg Exp $
+# $Id: doc.mk,v 1.5 2015/09/08 06:15:31 sjg Exp $
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
@@ -47,17 +47,19 @@ install:
.else
FILES?= ${SRCS}
install:
- ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 \
- Makefile ${FILES} ${EXTRA} ${DESTDIR}${BINDIR}/${DIR}
+ test -d ${DESTDIR}${DOCDIR}/${DIR} || \
+ ${INSTALL} -d ${DOC_INSTALL_OWN} -m ${DIRMODE} ${DESTDIR}${DOCDIR}/${DIR}
+ ${INSTALL} ${COPY} ${DOC_INSTALL_OWN} -m ${DOCMODE} \
+ Makefile ${FILES} ${EXTRA} ${DESTDIR}${DOCDIR}/${DIR}
.endif
spell: ${SRCS}
spell ${SRCS} | sort | comm -23 - spell.ok > paper.spell
-BINDIR?= /usr/share/doc
-BINGRP?= bin
-BINOWN?= bin
-BINMODE?= 444
-
.include <own.mk>
+
+.if !empty(DOCOWN)
+DOC_INSTALL_OWN?= -o ${DOCOWN} -g ${DOGGRP}
+.endif
+
.endif
diff --git a/mk/gendirdeps.mk b/mk/gendirdeps.mk
index b313298..2497f85 100644
--- a/mk/gendirdeps.mk
+++ b/mk/gendirdeps.mk
@@ -1,4 +1,4 @@
-# $Id: gendirdeps.mk,v 1.25 2014/03/14 21:28:37 sjg Exp $
+# $Id: gendirdeps.mk,v 1.29 2015/10/03 05:00:46 sjg Exp $
# Copyright (c) 2010-2013, Juniper Networks, Inc.
# All rights reserved.
@@ -93,6 +93,17 @@ _skip_gendirdeps = egrep -v '^(${SKIP_GENDIRDEPS:O:u:ts|})' |
_skip_gendirdeps =
.endif
+# Below we will turn _{VAR} into ${VAR} which keeps this simple
+# GENDIRDEPS_FILTER_DIR_VARS is a list of dirs to be substiuted for.
+# GENDIRDEPS_FILTER_VARS is more general.
+# In each case order matters.
+.if !empty(GENDIRDEPS_FILTER_DIR_VARS)
+GENDIRDEPS_FILTER += ${GENDIRDEPS_FILTER_DIR_VARS:@v@S,${$v},_{${v}},@}
+.endif
+.if !empty(GENDIRDEPS_FILTER_VARS)
+GENDIRDEPS_FILTER += ${GENDIRDEPS_FILTER_VARS:@v@S,/${$v}/,/_{${v}}/,@:NS,//,*:u}
+.endif
+
# this (*should* be set in meta.sys.mk)
# is the script that extracts what we want.
META2DEPS ?= ${.PARSEDIR}/meta2deps.sh
@@ -146,7 +157,7 @@ M2D_OBJROOTS += ${SB_BACKING_SB}/${SB_OBJPREFIX}
.endif
# we are only interested in the dirs
-# sepecifically those we read something from.
+# specifically those we read something from.
# we canonicalize them to keep things simple
# if we are using a split-fs sandbox, it gets a little messier.
_objtop := ${_OBJTOP:tA}
@@ -299,8 +310,7 @@ CAT_DEPEND ?= .depend
# The sed command at the end of the stream, allows for the filters
# to output _{VAR} tokens which we will turn into proper ${VAR} references.
${_DEPENDFILE}: ${CAT_DEPEND:M.depend} ${META_FILES:O:u:@m@${exists($m):?$m:}@} ${_this} ${META2DEPS}
- @(echo '# Autogenerated - do NOT edit!'; echo; \
- echo 'DEP_RELDIR := $${_PARSEDIR:S,$${SRCTOP}/,,}'; echo; \
+ @(${GENDIRDEPS_HEADER} echo '# Autogenerated - do NOT edit!'; echo; \
echo 'DIRDEPS = \'; \
echo '${DIRDEPS:@d@ $d \\${.newline}@}'; echo; \
${_include_src_dirdeps} \
@@ -320,8 +330,7 @@ DIRDEPS := ${SUBDIR:S,^,${RELDIR}/,:O:u}
all: ${_DEPENDFILE}
${_DEPENDFILE}: ${MAKEFILE} ${_this}
- @(echo '# Autogenerated - do NOT edit!'; echo; \
- echo 'DEP_RELDIR := $${_PARSEDIR:S,$${SRCTOP}/,,}'; echo; \
+ @(${GENDIRDEPS_HEADER} echo '# Autogenerated - do NOT edit!'; echo; \
echo 'DIRDEPS = \'; \
echo '${DIRDEPS:@d@ $d \\${.newline}@}'; echo; \
echo '.include <dirdeps.mk>'; \
diff --git a/mk/host-target.mk b/mk/host-target.mk
index eacdf1d..f528db9 100644
--- a/mk/host-target.mk
+++ b/mk/host-target.mk
@@ -1,5 +1,5 @@
# RCSid:
-# $Id: host-target.mk,v 1.7 2014/05/16 17:54:52 sjg Exp $
+# $Id: host-target.mk,v 1.11 2015/10/25 00:07:20 sjg Exp $
# Host platform information; may be overridden
.if !defined(_HOST_OSNAME)
@@ -10,24 +10,33 @@ _HOST_OSNAME != uname -s
_HOST_OSREL != uname -r
.export _HOST_OSREL
.endif
+.if !defined(_HOST_MACHINE)
+_HOST_MACHINE != uname -m
+.export _HOST_MACHINE
+.endif
.if !defined(_HOST_ARCH)
-_HOST_ARCH != uname -p 2>/dev/null || uname -m
+# for NetBSD prefer $MACHINE (amd64 rather than x86_64)
+.if ${_HOST_OSNAME:NNetBSD} == ""
+_HOST_ARCH := ${_HOST_MACHINE}
+.else
+_HOST_ARCH != uname -p 2> /dev/null || uname -m
# uname -p may produce garbage on linux
-.if ${_HOST_ARCH:[\#]} > 1
-_HOST_ARCH != uname -m
+.if ${_HOST_ARCH:[\#]} > 1 || ${_HOST_ARCH:Nunknown} == ""
+_HOST_ARCH := ${_HOST_MACHINE}
+.endif
.endif
.export _HOST_ARCH
.endif
.if !defined(HOST_MACHINE)
-HOST_MACHINE != uname -m
+HOST_MACHINE := ${_HOST_MACHINE}
.export HOST_MACHINE
.endif
HOST_OSMAJOR := ${_HOST_OSREL:C/[^0-9].*//}
-HOST_OSTYPE := ${_HOST_OSNAME}-${_HOST_OSREL:C/\([^\)]*\)//}-${_HOST_ARCH}
+HOST_OSTYPE := ${_HOST_OSNAME:S,/,,g}-${_HOST_OSREL:C/\([^\)]*\)//}-${_HOST_ARCH}
HOST_OS := ${_HOST_OSNAME}
host_os := ${_HOST_OSNAME:tl}
-HOST_TARGET := ${host_os}${HOST_OSMAJOR}-${_HOST_ARCH}
+HOST_TARGET := ${host_os:S,/,,g}${HOST_OSMAJOR}-${_HOST_ARCH}
# tr is insanely non-portable, accommodate the lowest common denominator
TR ?= tr
diff --git a/mk/init.mk b/mk/init.mk
index e700370..43561b5 100644
--- a/mk/init.mk
+++ b/mk/init.mk
@@ -1,4 +1,4 @@
-# $Id: init.mk,v 1.9 2013/07/18 05:46:24 sjg Exp $
+# $Id: init.mk,v 1.10 2015/12/07 04:28:31 sjg Exp $
#
# @(#) Copyright (c) 2002, Simon J. Gerraty
#
@@ -47,4 +47,8 @@ PROFFLAGS?= -DGPROF -DPROF
_SKIP_BUILD = not building at level 0
.endif
+.if !empty(_SKIP_BUILD)
+all: .PHONY
+.warning ${_SKIP_BUILD}
+.endif
.endif
diff --git a/mk/install-mk b/mk/install-mk
index 7e4ee8b..e735c44 100644
--- a/mk/install-mk
+++ b/mk/install-mk
@@ -55,7 +55,7 @@
# Simon J. Gerraty <sjg@crufty.net>
# RCSid:
-# $Id: install-mk,v 1.100 2014/05/23 01:30:36 sjg Exp $
+# $Id: install-mk,v 1.120 2016/02/26 23:34:39 sjg Exp $
#
# @(#) Copyright (c) 1994 Simon J. Gerraty
#
@@ -70,7 +70,7 @@
# sjg@crufty.net
#
-MK_VERSION=20140522
+MK_VERSION=20160220
OWNER=
GROUP=
MODE=444
diff --git a/mk/lib.mk b/mk/lib.mk
index 417aa02..c76fd9b 100644
--- a/mk/lib.mk
+++ b/mk/lib.mk
@@ -1,4 +1,4 @@
-# $Id: lib.mk,v 1.51 2014/05/23 01:30:36 sjg Exp $
+# $Id: lib.mk,v 1.52 2015/11/14 18:09:57 sjg Exp $
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
@@ -254,7 +254,7 @@ DLLIB ?= -ldl
# is a waste of time, this tells meta.autodep.mk to just pick one
# (typically .So)
# yes, 42 is a random number.
-.if ${MK_META_MODE} == "yes" && ${SRCS:Uno:[\#]} > 42
+.if ${MK_DIRDEPS_BUILD} == "yes" && ${SRCS:Uno:[\#]} > 42
OPTIMIZE_OBJECT_META_FILES ?= yes
.endif
diff --git a/mk/links.mk b/mk/links.mk
index 4ec8a01..aac3914 100644
--- a/mk/links.mk
+++ b/mk/links.mk
@@ -1,4 +1,4 @@
-# $Id: links.mk,v 1.5 2005/07/11 18:01:05 sjg Exp $
+# $Id: links.mk,v 1.6 2014/09/29 17:14:40 sjg Exp $
#
# @(#) Copyright (c) 2005, Simon J. Gerraty
#
@@ -22,9 +22,14 @@ SYMLINKS?=
__SYMLINK_SCRIPT= \
${ECHO} "$$t -> $$l"; \
- mkdir -p `dirname $$t`; \
- rm -f $$t; \
- ${LN} -s $$l $$t
+ case `'ls' -l $$t 2> /dev/null` in \
+ *"> $$l") ;; \
+ *) \
+ mkdir -p `dirname $$t`; \
+ rm -f $$t; \
+ ${LN} -s $$l $$t;; \
+ esac
+
__LINK_SCRIPT= \
${ECHO} "$$t -> $$l"; \
diff --git a/mk/manifest.mk b/mk/manifest.mk
new file mode 100644
index 0000000..797038d
--- /dev/null
+++ b/mk/manifest.mk
@@ -0,0 +1,66 @@
+# $Id: manifest.mk,v 1.2 2014/10/31 18:06:17 sjg Exp $
+#
+# @(#) Copyright (c) 2014, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+# generate mtree style manifest supported by makefs in FreeBSD
+
+# input looks like
+# MANIFEST= my.mtree
+# for each MANIFEST we have a list of dirs
+# ${MANIFEST}.DIRS += bin sbin usr/bin ...
+# for each dir we have a ${MANIFEST}.SRCS.$dir
+# that provides the absolute path to the contents
+# ${MANIFEST}.SRCS.bin += ${OBJTOP}/bin/sh/sh
+# ${MANIFEST}.SYMLINKS is a list of src target pairs
+# for each file/dir there are a number of attributes
+# UID GID MODE FLAGS
+# which can be set per dir, per file or we use defaults
+# eg.
+# MODE.sbin = 550
+# MODE.usr/sbin = 550
+# MODE.dirs = 555
+# means that sbin and usr/sbin get 550 all other dirs get 555
+# MODE.usr/bin/passwd = 4555
+# MODE.usr/bin.files = 555
+# MODE.usr/sbin.files = 500
+# means passwd gets 4555 other files in usr/bin get 555 and
+# files in usr/sbin get 500
+# STORE defaults to basename of src and target directory
+# but we can use
+# ${MANIFEST}.SRCS.sbin += ${OBJTOP}/bin/sh-static/sh-static
+# STORE.sbin/sh-static = sbin/sh
+#
+# the above is a little overkill but means we can easily adapt to
+# different formats
+
+UID.dirs ?= 0
+GID.dirs ?= 0
+MODE.dirs ?= 775
+FLAGS.dirs ?=
+
+UID.files ?= 0
+GID.files ?= 0
+MODE.files ?= 555
+
+# a is attribute name d is dirname
+M_DIR_ATTR = L:@a@$${$$a.$$d:U$${$$a.dirs}}@
+# as above and s is set to the name we store f as
+M_FILE_ATTR = L:@a@$${$$a.$$s:U$${$$a.$$d.files:U$${$$a.files}}}@
+
+# this produces the body of the manifest
+# there should typically be a header prefixed
+_GEN_MTREE_MANIFEST_USE: .USE
+ @(${${.TARGET}.DIRS:O:u:@d@echo '$d type=dir uid=${UID:${M_DIR_ATTR}} gid=${GID:${M_DIR_ATTR}} mode=${MODE:${M_DIR_ATTR}} ${FLAGS:${M_DIR_ATTR}}';@} \
+ ${${.TARGET}.DIRS:O:u:@d@${${.TARGET}.SRCS.$d:O:u:@f@echo '${s::=${STORE.$d/${f:T}:U$d/${f:T}}}$s contents="$f" type=file uid=${UID:${M_FILE_ATTR}} gid=${GID:${M_FILE_ATTR}} mode=${MODE:${M_FILE_ATTR}} ${FLAGS:${M_FILE_ATTR}}';@}@} \
+ set ${${.TARGET}.SYMLINKS}; while test $$# -ge 2; do echo "$$2 type=link link=$$1"; shift 2; done) > ${.TARGET}
diff --git a/mk/meta.autodep.mk b/mk/meta.autodep.mk
index a961bff..5f70564 100644
--- a/mk/meta.autodep.mk
+++ b/mk/meta.autodep.mk
@@ -1,4 +1,4 @@
-# $Id: meta.autodep.mk,v 1.35 2014/05/09 00:05:46 sjg Exp $
+# $Id: meta.autodep.mk,v 1.40 2016/02/22 22:44:58 sjg Exp $
#
# @(#) Copyright (c) 2010, Simon J. Gerraty
@@ -50,6 +50,9 @@ UPDATE_DEPENDFILE = NO
.endif
_CURDIR ?= ${.CURDIR}
+_OBJDIR ?= ${.OBJDIR}
+_OBJTOP ?= ${OBJTOP}
+_OBJROOT ?= ${OBJROOT:U${_OBJTOP}}
_DEPENDFILE := ${_CURDIR}/${.MAKE.DEPENDFILE:T}
.if ${.MAKE.LEVEL} == 0
@@ -83,7 +86,7 @@ WANT_UPDATE_DEPENDFILE ?= yes
.endif
.if ${WANT_UPDATE_DEPENDFILE:Uno:tl} != "no"
-.if ${.MAKE.MODE:Mmeta*} == "" || ${.MAKE.MODE:M*read*} != ""
+.if ${.MAKE.MODE:Uno:Mmeta*} == "" || ${.MAKE.MODE:Uno:M*read*} != ""
UPDATE_DEPENDFILE = no
.endif
@@ -97,6 +100,8 @@ UPDATE_DEPENDFILE = no
# for example the result of running configure
# just make sure this is not empty
META_FILE_FILTER ?= N.meta
+# never consider these
+META_FILE_FILTER += Ndirdeps.cache*
.if !empty(DPADD)
# if we have any non-libs in DPADD,
@@ -188,7 +193,7 @@ gendirdeps: ${_DEPENDFILE}
# anything which matches ${_OBJROOT}* but not ${_OBJTOP}*
# needs to be qualified in DIRDEPS
# The pseudo machine "host" is used for HOST_TARGET
-DIRDEPS = \
+DIRDEPS += \
${DPADD:M${_OBJTOP}*:H:C,${_OBJTOP}[^/]*/,,:N.:O:u} \
${DPADD:M${_OBJROOT}*:N${_OBJTOP}*:H:S,${_OBJROOT},,:C,^([^/]+)/(.*),\2.\1,:S,${HOST_TARGET}$,host,:N.*:O:u}
@@ -254,6 +259,9 @@ ${_DEPENDFILE}: ${_depend} ${.PARSEDIR}/gendirdeps.mk ${META2DEPS} $${.MAKE.MET
.endif
.if ${_bootstrap_dirdeps} == "yes"
+.if ${BUILD_AT_LEVEL0:Uno} == "no"
+DIRDEPS+= ${RELDIR}.${TARGET_SPEC:U${MACHINE}}
+.endif
# make sure this is included at least once
.include <dirdeps.mk>
.else
diff --git a/mk/meta.stage.mk b/mk/meta.stage.mk
index 2f02700..0355d66 100644
--- a/mk/meta.stage.mk
+++ b/mk/meta.stage.mk
@@ -1,4 +1,4 @@
-# $Id: meta.stage.mk,v 1.30 2013/04/19 16:32:57 sjg Exp $
+# $Id: meta.stage.mk,v 1.43 2016/02/24 18:46:32 sjg Exp $
#
# @(#) Copyright (c) 2011, Simon J. Gerraty
#
@@ -23,8 +23,10 @@ _dirdep = ${RELDIR}.${MACHINE}
_dirdep = ${RELDIR}
.endif
+CLEANFILES+= .dirdep
+
# this allows us to trace dependencies back to their src dir
-.dirdep:
+.dirdep: .NOPATH
@echo '${_dirdep}' > $@
.if defined(NO_POSIX_SHELL) || ${type printf:L:sh:Mbuiltin} == ""
@@ -35,7 +37,13 @@ _stage_file_basename = $${f\#\#*/}
_stage_target_dirname = $${t%/*}
.endif
+_OBJROOT ?= ${OBJROOT:U${OBJTOP:H}}
+.if ${_OBJROOT:M*/} != ""
+_objroot ?= ${_OBJROOT:tA}/
+.else
_objroot ?= ${_OBJROOT:tA}
+.endif
+
# make sure this is global
_STAGED_DIRS ?=
.export _STAGED_DIRS
@@ -46,21 +54,30 @@ STAGE_DIR_FILTER = tA:@d@$${_STAGED_DIRS::+=$$d}$$d@
# convert _STAGED_DIRS into suitable filters
GENDIRDEPS_FILTER += Nnot-empty-is-important \
${_STAGED_DIRS:O:u:M${OBJTOP}*:S,${OBJTOP}/,N,} \
- ${_STAGED_DIRS:O:u:N${OBJTOP}*:S,${_objroot},,:C,^([^/]+)/(.*),N\2.\1,:S,${HOST_TARGET},.host,}
+ ${_STAGED_DIRS:O:u:M${_objroot}*:N${OBJTOP}*:S,${_objroot},,:C,^([^/]+)/(.*),N\2.\1,:S,${HOST_TARGET},.host,}
LN_CP_SCRIPT = LnCp() { \
rm -f $$2 2> /dev/null; \
ln $$1 $$2 2> /dev/null || \
cp -p $$1 $$2; }
+# a staging conflict should cause an error
+# a warning is handy when bootstapping different options.
+STAGE_CONFLICT?= ERROR
+.if ${STAGE_CONFLICT:tl} == "error"
+STAGE_CONFLICT_ACTION= exit 1;
+.else
+STAGE_CONFLICT_ACTION=
+.endif
+
# it is an error for more than one src dir to try and stage
# the same file
STAGE_DIRDEP_SCRIPT = ${LN_CP_SCRIPT}; StageDirdep() { \
t=$$1; \
if [ -s $$t.dirdep ]; then \
cmp -s .dirdep $$t.dirdep && return; \
- echo "ERROR: $$t installed by `cat $$t.dirdep` not ${_dirdep}" >&2; \
- exit 1; \
+ echo "${STAGE_CONFLICT}: $$t installed by `cat $$t.dirdep` not ${_dirdep}" >&2; \
+ ${STAGE_CONFLICT_ACTION} \
fi; \
LnCp .dirdep $$t.dirdep || exit 1; }
@@ -113,10 +130,14 @@ STAGE_AS_SCRIPT = ${STAGE_DIRDEP_SCRIPT}; StageAs() { \
_STAGE_BASENAME_USE: .USE ${.TARGET:T}
@${STAGE_FILE_SCRIPT}; StageFiles ${.TARGET:H:${STAGE_DIR_FILTER}} ${.TARGET:T}
+_STAGE_AS_BASENAME_USE: .USE ${.TARGET:T}
+ @${STAGE_AS_SCRIPT}; StageAs ${.TARGET:H:${STAGE_DIR_FILTER}} ${.TARGET:T} ${STAGE_AS_${.TARGET:T}:U${.TARGET:T}}
+
.if !empty(STAGE_INCSDIR)
STAGE_TARGETS += stage_incs
-STAGE_INCS ?= ${.ALLSRC:N.dirdep}
+STAGE_INCS ?= ${.ALLSRC:N.dirdep:Nstage_*}
+stage_includes: stage_incs
stage_incs: .dirdep
@${STAGE_FILE_SCRIPT}; StageFiles ${STAGE_INCSDIR:${STAGE_DIR_FILTER}} ${STAGE_INCS}
@touch $@
@@ -125,15 +146,17 @@ stage_incs: .dirdep
.if !empty(STAGE_LIBDIR)
STAGE_TARGETS += stage_libs
-STAGE_LIBS ?= ${.ALLSRC:N.dirdep}
+STAGE_LIBS ?= ${.ALLSRC:N.dirdep:Nstage_*}
stage_libs: .dirdep
@${STAGE_FILE_SCRIPT}; StageFiles ${STAGE_LIBDIR:${STAGE_DIR_FILTER}} ${STAGE_LIBS}
+.if !defined(NO_SHLIB_LINKS)
.if !empty(SHLIB_LINKS)
@${STAGE_LINKS_SCRIPT}; StageLinks -s ${STAGE_LIBDIR:${STAGE_DIR_FILTER}} \
${SHLIB_LINKS:@t@${STAGE_LIBS:T:M$t.*} $t@}
.elif !empty(SHLIB_LINK) && !empty(SHLIB_NAME)
- @${STAGE_LINKS_SCRIPT}; StageLinks -s ${STAGE_LIBDIR:${STAGE_DIR_FILTER}} ${SHLIB_NAME} ${SHLIB_LINK} ${SYMLINKS:T}
+ @${STAGE_LINKS_SCRIPT}; StageLinks -s ${STAGE_LIBDIR:${STAGE_DIR_FILTER}} ${SHLIB_NAME} ${SHLIB_LINK}
+.endif
.endif
@touch $@
.endif
@@ -155,8 +178,8 @@ CLEANFILES += ${STAGE_SETS:@s@stage*$s@}
# some makefiles need to populate multiple directories
.for s in ${STAGE_SETS:O:u}
-STAGE_FILES.$s ?= ${.ALLSRC:N.dirdep}
-STAGE_SYMLINKS.$s ?= ${.ALLSRC:N.dirdep}
+STAGE_FILES.$s ?= ${.ALLSRC:N.dirdep:Nstage_*}
+STAGE_SYMLINKS.$s ?= ${.ALLSRC:N.dirdep:Nstage_*}
STAGE_LINKS_DIR.$s ?= ${STAGE_OBJTOP}
STAGE_SYMLINKS_DIR.$s ?= ${STAGE_OBJTOP}
@@ -202,31 +225,35 @@ STAGE_TARGETS += stage_as
# each ${file} will be staged as ${STAGE_AS_${file:T}}
# one could achieve the same with SYMLINKS
.for s in ${STAGE_AS_SETS:O:u}
-STAGE_AS.$s ?= ${.ALLSRC:N.dirdep}
+STAGE_AS.$s ?= ${.ALLSRC:N.dirdep:Nstage_*}
stage_as: stage_as.$s
stage_as.$s: .dirdep
- @${STAGE_AS_SCRIPT}; StageAs ${FLAGS.$@} ${STAGE_FILES_DIR.$s:U${STAGE_DIR.$s}:${STAGE_DIR_FILTER}} ${STAGE_AS.$s:@f@$f ${STAGE_AS_${f:T}:U${f:T}}@}
+ @${STAGE_AS_SCRIPT}; StageAs ${FLAGS.$@} ${STAGE_FILES_DIR.$s:U${STAGE_DIR.$s}:${STAGE_DIR_FILTER}} ${STAGE_AS.$s:@f@$f ${STAGE_AS_${f:tA}:U${STAGE_AS_${f:T}:U${f:T}}}@}
@touch $@
.endfor
.endif
-CLEANFILES += ${STAGE_TARGETS}
+CLEANFILES += ${STAGE_TARGETS} stage_incs stage_includes
# stage_*links usually needs to follow any others.
+# for non-jobs mode the order here matters
+staging: ${STAGE_TARGETS:N*_links} ${STAGE_TARGETS:M*_links}
+
+.if ${.MAKE.JOBS:U0} > 0 && ${STAGE_TARGETS:U:M*_links} != ""
+# the above isn't sufficient
.for t in ${STAGE_TARGETS:N*links:O:u}
.ORDER: $t stage_links
-.ORDER: $t stage_symlinks
.endfor
-
-# make sure this exists
-staging:
+.endif
# generally we want staging to wait until everything else is done
STAGING_WAIT ?= .WAIT
+.if ${.MAKE.LEVEL} > 0
all: ${STAGING_WAIT} staging
+.endif
.if exists(${.PARSEDIR}/stage-install.sh) && !defined(STAGE_INSTALL)
# this will run install(1) and then followup with .dirdep files.
@@ -240,5 +267,26 @@ INSTALL := ${STAGE_INSTALL}
beforeinstall: .dirdep
.endif
.endif
+.NOPATH: ${STAGE_FILES}
+
+.if !empty(STAGE_TARGETS)
+MK_STALE_STAGED?= no
+.if ${MK_STALE_STAGED} == "yes"
+all: stale_staged
+# get a list of paths that we have just staged
+# get a list of paths that we have previously staged to those same dirs
+# anything in the 2nd list but not the first is stale - remove it.
+stale_staged: staging .NOMETA
+ @egrep '^[WL] .*${STAGE_OBJTOP}' /dev/null ${.MAKE.META.FILES:M*stage_*} | \
+ sed "/\.dirdep/d;s,.* '*\(${STAGE_OBJTOP}/[^ '][^ ']*\).*,\1," | \
+ sort > ${.TARGET}.staged1
+ @grep -l '${_dirdep}' /dev/null ${_STAGED_DIRS:M${STAGE_OBJTOP}*:O:u:@d@$d/*.dirdep@} | \
+ sed 's,\.dirdep,,' | sort > ${.TARGET}.staged2
+ @comm -13 ${.TARGET}.staged1 ${.TARGET}.staged2 > ${.TARGET}.stale
+ @test ! -s ${.TARGET}.stale || { \
+ echo "Removing stale staged files..."; \
+ sed 's,.*,& &.dirdep,' ${.TARGET}.stale | xargs rm -f; }
.endif
+.endif
+.endif
diff --git a/mk/meta.subdir.mk b/mk/meta.subdir.mk
index 2b739ee..d27de10 100644
--- a/mk/meta.subdir.mk
+++ b/mk/meta.subdir.mk
@@ -1,4 +1,4 @@
-# $Id: meta.subdir.mk,v 1.10 2012/07/03 05:26:46 sjg Exp $
+# $Id: meta.subdir.mk,v 1.11 2015/11/24 22:26:51 sjg Exp $
#
# @(#) Copyright (c) 2010, Simon J. Gerraty
@@ -62,7 +62,7 @@ _subdeps != cd ${.CURDIR} && \
DIRDEPS =
.else
# clean up if needed
-DIRDEPS := ${DIRDEPS:S,^./,,:S,/./,/,g:${SUBDIREPS_FILTER:Uu}}
+DIRDEPS := ${DIRDEPS:S,^./,,:S,/./,/,g:${SUBDIRDEPS_FILTER:Uu}}
.endif
# we just dealt with it, if we leave it defined,
# dirdeps.mk will compute some interesting combinations.
diff --git a/mk/meta.sys.mk b/mk/meta.sys.mk
index 1707a66..764f2d1 100644
--- a/mk/meta.sys.mk
+++ b/mk/meta.sys.mk
@@ -1,4 +1,4 @@
-# $Id: meta.sys.mk,v 1.16 2012/07/03 05:26:00 sjg Exp $
+# $Id: meta.sys.mk,v 1.27 2016/02/22 22:44:58 sjg Exp $
#
# @(#) Copyright (c) 2010, Simon J. Gerraty
@@ -20,6 +20,10 @@
.if ${MAKE_VERSION:U0} > 20100901
.if !target(.ERROR)
+.-include "local.meta.sys.mk"
+
+# absoulte path to what we are reading.
+_PARSEDIR = ${.PARSEDIR:tA}
META_MODE += meta verbose
.MAKE.MODE ?= ${META_MODE}
@@ -47,17 +51,6 @@ META_MODE += silent=yes
.endif
.endif
-# make defaults .MAKE.DEPENDFILE to .depend
-# that won't work for us.
-.if ${.MAKE.DEPENDFILE} == ".depend"
-.undef .MAKE.DEPENDFILE
-.endif
-
-# if you don't cross build for multiple MACHINEs concurrently, then
-# .MAKE.DEPENDFILE = Makefile.depend
-# probably makes sense - you can set that in local.sys.mk
-.MAKE.DEPENDFILE ?= Makefile.depend.${MACHINE}
-
# we use the pseudo machine "host" for the build host.
# this should be taken care of before we get here
.if ${OBJTOP:Ua} == ${HOST_OBJTOP:Ub}
@@ -69,6 +62,7 @@ MACHINE = host
# for example, if using Makefild.depend for multiple machines,
# allowing only MACHINE0 to update can keep things simple.
MACHINE0 := ${MACHINE}
+.export MACHINE0
.if defined(PYTHON) && exists(${PYTHON})
# we prefer the python version of this - it is much faster
@@ -104,9 +98,37 @@ _metaError: .NOMETA .NOTMAIN
.endif
+META_COOKIE_TOUCH=
+# some targets need to be .PHONY in non-meta mode
+META_NOPHONY= .PHONY
# Are we, after all, in meta mode?
-.if ${.MAKE.MODE:Mmeta*} != ""
-MKDEP = meta.autodep
+.if ${.MAKE.MODE:Uno:Mmeta*} != ""
+MKDEP_MK = meta.autodep.mk
+
+.if ${.MAKE.MAKEFILES:M*sys.dependfile.mk} == ""
+# this does all the smarts of setting .MAKE.DEPENDFILE
+.-include <sys.dependfile.mk>
+# check if we got anything sane
+.if ${.MAKE.DEPENDFILE} == ".depend"
+.undef .MAKE.DEPENDFILE
+.endif
+.MAKE.DEPENDFILE ?= Makefile.depend
+.endif
+
+# we can afford to use cookies to prevent some targets
+# re-running needlessly
+META_COOKIE_TOUCH= touch ${COOKIE.${.TARGET}:U${.OBJDIR}/${.TARGET}}
+META_NOPHONY=
+.if ${UPDATE_DEPENDFILE:Uyes:tl} != "no"
+.if ${.MAKEFLAGS:Uno:M-k} != ""
+# make this more obvious
+.warning Setting UPDATE_DEPENDFILE=NO due to -k
+UPDATE_DEPENDFILE= NO
+.export UPDATE_DEPENDFILE
+.elif !exists(/dev/filemon)
+.error ${.newline}ERROR: The filemon module (/dev/filemon) is not loaded.
+.endif
+.endif
.if ${.MAKE.LEVEL} == 0
# make sure dirdeps target exists and do it first
@@ -121,19 +143,11 @@ dirdeps:
# tell dirdeps.mk what we want
BUILD_AT_LEVEL0 = no
.endif
-
-.if ${.MAKE.DEPENDFILE:E} == ${MACHINE}
+.if ${.TARGETS:Nall} == ""
# it works best if we do everything via sub-makes
BUILD_AT_LEVEL0 ?= no
.endif
-BUILD_AT_LEVEL0 ?= yes
-.endif
-# if we think we are updating dependencies,
-# then filemon had better be present
-.if ${UPDATE_DEPENDFILE:Uyes:tl} != "no" && !exists(/dev/filemon)
-.error ${.newline}ERROR: The filemon module (/dev/filemon) is not loaded.
.endif
-
.endif
.endif
diff --git a/mk/meta2deps.py b/mk/meta2deps.py
index 8e349e7..ed183f0 100755
--- a/mk/meta2deps.py
+++ b/mk/meta2deps.py
@@ -37,7 +37,7 @@ We only pay attention to a subset of the information in the
"""
RCSid:
- $Id: meta2deps.py,v 1.17 2014/04/05 22:56:54 sjg Exp $
+ $Id: meta2deps.py,v 1.18 2015/04/03 18:23:25 sjg Exp $
Copyright (c) 2011-2013, Juniper Networks, Inc.
All rights reserved.
@@ -112,7 +112,8 @@ def abspath(path, cwd, last_dir=None, debug=0, debug_out=sys.stderr):
rpath = resolve(path, cwd, last_dir, debug, debug_out)
if rpath:
path = rpath
- if (path.find('./') > 0 or
+ if (path.find('/') < 0 or
+ path.find('./') > 0 or
path.endswith('/..') or
os.path.islink(path)):
return os.path.realpath(path)
@@ -142,7 +143,7 @@ class MetaFile:
host_target = None
srctops = []
objroots = []
-
+ excludes = []
seen = {}
obj_deps = []
src_deps = []
@@ -179,6 +180,10 @@ class MetaFile:
This can allow 'bmake' to learn all the dirs within
the tree that depend on 'foo.h'
+ EXCLUDES
+ A list of paths to ignore.
+ ccache(1) can otherwise be trouble.
+
debug desired debug level
debug_out open file to send debug output to (sys.stderr)
@@ -236,11 +241,14 @@ class MetaFile:
# we want the longest match
self.srctops.sort(reverse=True)
self.objroots.sort(reverse=True)
-
+
+ self.excludes = getv(conf, 'EXCLUDES', [])
+
if self.debug:
print("host_target=", self.host_target, file=self.debug_out)
print("srctops=", self.srctops, file=self.debug_out)
print("objroots=", self.objroots, file=self.debug_out)
+ print("excludes=", self.excludes, file=self.debug_out)
self.dirdep_re = re.compile(r'([^/]+)/(.+)')
@@ -257,6 +265,7 @@ class MetaFile:
self.dpdeps = None # we cannot do it?
self.cwd = os.getcwd() # make sure this is initialized
+ self.last_dir = self.cwd
if name:
self.try_parse()
@@ -360,18 +369,18 @@ class MetaFile:
V 3
C "pid" "cwd"
E "pid" "path"
- F "pid" "child"
+ F "pid" "child"
R "pid" "path"
W "pid" "path"
X "pid" "status"
- D "pid" "path"
- L "pid" "src" "target"
- M "pid" "old" "new"
- S "pid" "path"
- # Bye bye
-
- We go to some effort to avoid processing a dependency more than once.
- Of the above record types only C,E,F,L,R,V and W are of interest.
+ D "pid" "path"
+ L "pid" "src" "target"
+ M "pid" "old" "new"
+ S "pid" "path"
+ # Bye bye
+
+ We go to some effort to avoid processing a dependency more than once.
+ Of the above record types only C,E,F,L,R,V and W are of interest.
"""
version = 0 # unknown
@@ -379,7 +388,7 @@ class MetaFile:
self.name = name;
if file:
f = file
- cwd = last_dir = self.cwd
+ cwd = self.last_dir = self.cwd
else:
f = open(self.name, 'r')
skip = True
@@ -412,7 +421,7 @@ class MetaFile:
interesting += 'W'
"""
elif w[0] == 'CWD':
- self.cwd = cwd = last_dir = w[1]
+ self.cwd = cwd = self.last_dir = w[1]
self.seenit(cwd) # ignore this
if self.debug:
print("%s: CWD=%s" % (self.name, cwd), file=self.debug_out)
@@ -422,9 +431,9 @@ class MetaFile:
if pid != last_pid:
if last_pid:
pid_cwd[last_pid] = cwd
- pid_last_dir[last_pid] = last_dir
+ pid_last_dir[last_pid] = self.last_dir
cwd = getv(pid_cwd, pid, self.cwd)
- last_dir = getv(pid_last_dir, pid, self.cwd)
+ self.last_dir = getv(pid_last_dir, pid, self.cwd)
last_pid = pid
# process operations
@@ -438,7 +447,7 @@ class MetaFile:
cwd = abspath(w[2], cwd, None, self.debug, self.debug_out)
if cwd.endswith('/.'):
cwd = cwd[0:-2]
- last_dir = cwd
+ self.last_dir = cwd
if self.debug > 1:
print("cwd=", cwd, file=self.debug_out)
continue
@@ -449,98 +458,114 @@ class MetaFile:
continue
# file operations
if w[0] in 'ML':
- path = w[2].strip("'")
- else:
- path = w[2]
- # we are never interested in .dirdep files as dependencies
- if path.endswith('.dirdep'):
+ # these are special, tread src as read and
+ # target as write
+ self.parse_path(w[1].strip("'"), cwd, 'R', w)
+ self.parse_path(w[2].strip("'"), cwd, 'W', w)
continue
- # we don't want to resolve the last component if it is
- # a symlink
- path = resolve(path, cwd, last_dir, self.debug, self.debug_out)
- if not path:
- continue
- dir,base = os.path.split(path)
- if dir in self.seen:
+ elif w[0] in 'ERWS':
+ path = w[2]
+ self.parse_path(path, cwd, w[0], w)
+
+ if not file:
+ f.close()
+
+ def parse_path(self, path, cwd, op=None, w=[]):
+ """look at a path for the op specified"""
+
+ if not op:
+ op = w[0]
+
+ # we are never interested in .dirdep files as dependencies
+ if path.endswith('.dirdep'):
+ return
+ for p in self.excludes:
+ if p and path.startswith(p):
if self.debug > 2:
- print("seen:", dir, file=self.debug_out)
- continue
- # we can have a path in an objdir which is a link
- # to the src dir, we may need to add dependencies for each
- rdir = dir
- dir = abspath(dir, cwd, last_dir, self.debug, self.debug_out)
- if rdir == dir or rdir.find('./') > 0:
- rdir = None
- # now put path back together
- path = '/'.join([dir,base])
- if self.debug > 1:
- print("raw=%s rdir=%s dir=%s path=%s" % (w[2], rdir, dir, path), file=self.debug_out)
- if w[0] in 'SRWL':
- if w[0] == 'W' and path.endswith('.dirdep'):
- continue
- if path in [last_dir, cwd, self.cwd, self.curdir]:
- if self.debug > 1:
- print("skipping:", path, file=self.debug_out)
- continue
- if os.path.isdir(path):
- if w[0] in 'RW':
- last_dir = path;
- if self.debug > 1:
- print("ldir=", last_dir, file=self.debug_out)
- continue
+ print >> self.debug_out, "exclude:", p, path
+ return
+ # we don't want to resolve the last component if it is
+ # a symlink
+ path = resolve(path, cwd, self.last_dir, self.debug, self.debug_out)
+ if not path:
+ return
+ dir,base = os.path.split(path)
+ if dir in self.seen:
+ if self.debug > 2:
+ print("seen:", dir, file=self.debug_out)
+ return
+ # we can have a path in an objdir which is a link
+ # to the src dir, we may need to add dependencies for each
+ rdir = dir
+ dir = abspath(dir, cwd, self.last_dir, self.debug, self.debug_out)
+ if rdir == dir or rdir.find('./') > 0:
+ rdir = None
+ # now put path back together
+ path = '/'.join([dir,base])
+ if self.debug > 1:
+ print("raw=%s rdir=%s dir=%s path=%s" % (w[2], rdir, dir, path), file=self.debug_out)
+ if op in 'RWS':
+ if path in [self.last_dir, cwd, self.cwd, self.curdir]:
+ if self.debug > 1:
+ print("skipping:", path, file=self.debug_out)
+ return
+ if os.path.isdir(path):
+ if op in 'RW':
+ self.last_dir = path;
+ if self.debug > 1:
+ print("ldir=", self.last_dir, file=self.debug_out)
+ return
+
+ if op in 'ERW':
+ # finally, we get down to it
+ if dir == self.cwd or dir == self.curdir:
+ return
+ srctop = self.find_top(path, self.srctops)
+ if srctop:
+ if self.dpdeps:
+ self.add(self.file_deps, path.replace(srctop,''), 'file')
+ self.add(self.src_deps, dir.replace(srctop,''), 'src')
+ self.seenit(w[2])
+ self.seenit(dir)
+ if rdir and not rdir.startswith(srctop):
+ dir = rdir # for below
+ rdir = None
+ else:
+ return
- if w[0] in 'REWML':
- # finally, we get down to it
- if dir == self.cwd or dir == self.curdir:
+ objroot = None
+ for dir in [dir,rdir]:
+ if not dir:
continue
- srctop = self.find_top(path, self.srctops)
- if srctop:
- if self.dpdeps:
- self.add(self.file_deps, path.replace(srctop,''), 'file')
- self.add(self.src_deps, dir.replace(srctop,''), 'src')
- self.seenit(w[2])
- self.seenit(dir)
- if rdir and not rdir.startswith(srctop):
- dir = rdir # for below
- rdir = None
- else:
- continue
-
- objroot = None
- for dir in [dir,rdir]:
- if not dir:
- continue
- objroot = self.find_top(dir, self.objroots)
- if objroot:
- break
+ objroot = self.find_top(dir, self.objroots)
if objroot:
- ddep = self.find_obj(objroot, dir, path, w[2])
- if ddep:
- self.add(self.obj_deps, ddep, 'obj')
- else:
- # don't waste time looking again
- self.seenit(w[2])
- self.seenit(dir)
- if not file:
- f.close()
+ break
+ if objroot:
+ ddep = self.find_obj(objroot, dir, path, w[2])
+ if ddep:
+ self.add(self.obj_deps, ddep, 'obj')
+ else:
+ # don't waste time looking again
+ self.seenit(w[2])
+ self.seenit(dir)
def main(argv, klass=MetaFile, xopts='', xoptf=None):
"""Simple driver for class MetaFile.
Usage:
- script [options] [key=value ...] "meta" ...
+ script [options] [key=value ...] "meta" ...
Options and key=value pairs contribute to the
dictionary passed to MetaFile.
-S "SRCTOP"
- add "SRCTOP" to the "SRCTOPS" list.
+ add "SRCTOP" to the "SRCTOPS" list.
-C "CURDIR"
-O "OBJROOT"
- add "OBJROOT" to the "OBJROOTS" list.
+ add "OBJROOT" to the "OBJROOTS" list.
-m "MACHINE"
@@ -550,7 +575,7 @@ def main(argv, klass=MetaFile, xopts='', xoptf=None):
-D "DPDEPS"
- -d bumps debug level
+ -d bumps debug level
"""
import getopt
@@ -568,6 +593,7 @@ def main(argv, klass=MetaFile, xopts='', xoptf=None):
conf = {
'SRCTOPS': [],
'OBJROOTS': [],
+ 'EXCLUDES': [],
}
try:
@@ -589,7 +615,7 @@ def main(argv, klass=MetaFile, xopts='', xoptf=None):
debug = 0
output = True
- opts, args = getopt.getopt(argv[1:], 'a:dS:C:O:R:m:D:H:qT:' + xopts)
+ opts, args = getopt.getopt(argv[1:], 'a:dS:C:O:R:m:D:H:qT:X:' + xopts)
for o, a in opts:
if o == '-a':
conf['MACHINE_ARCH'] = a
@@ -615,6 +641,9 @@ def main(argv, klass=MetaFile, xopts='', xoptf=None):
conf['MACHINE'] = a
elif o == '-T':
conf['TARGET_SPEC'] = a
+ elif o == '-X':
+ if a not in conf['EXCLUDES']:
+ conf['EXCLUDES'].append(a)
elif xoptf:
xoptf(o, a, conf)
@@ -649,16 +678,21 @@ def main(argv, klass=MetaFile, xopts='', xoptf=None):
for k,v in list(conf.items()):
print("%s=%s" % (k,v), file=debug_out)
+ m = None
for a in args:
if a.endswith('.meta'):
+ if not os.path.exists(a):
+ continue
m = klass(a, conf)
elif a.startswith('@'):
# there can actually multiple files per line
for line in open(a[1:]):
for f in line.strip().split():
+ if not os.path.exists(f):
+ continue
m = klass(f, conf)
- if output:
+ if output and m:
print(m.dirdeps())
print(m.src_dirdeps('\nsrc:'))
diff --git a/mk/meta2deps.sh b/mk/meta2deps.sh
index d96ce07..2a79be1 100755
--- a/mk/meta2deps.sh
+++ b/mk/meta2deps.sh
@@ -77,7 +77,7 @@
# RCSid:
-# $Id: meta2deps.sh,v 1.7 2014/04/05 22:56:54 sjg Exp $
+# $Id: meta2deps.sh,v 1.9 2015/04/03 18:23:25 sjg Exp $
# Copyright (c) 2010-2013, Juniper Networks, Inc.
# All rights reserved.
@@ -139,10 +139,15 @@ add_list() {
eval "$name=\"$list\""
}
+_excludes_f() {
+ egrep -v "$EXCLUDES"
+}
+
meta2deps() {
DPDEPS=
SRCTOPS=$SRCTOP
OBJROOTS=
+ EXCLUDES=
while :
do
case "$1" in
@@ -153,6 +158,7 @@ meta2deps() {
-H) HOST_TARGET=$2; shift 2;;
-S) add_list SRCTOPS $2; shift 2;;
-O) add_list OBJROOTS $2; shift 2;;
+ -X) add_list EXCLUDES '|' $2; shift 2;;
-R) RELDIR=$2; shift 2;;
-T) TARGET_SPEC=$2; shift 2;;
*) break;;
@@ -212,8 +218,26 @@ meta2deps() {
seenit=
seensrc=
lpid=
- cat /dev/null "$@" |
- sed -e 's,^CWD,C C,;/^[CREFL] /!d' -e "s,',,g" |
+ case "$EXCLUDES" in
+ "") _excludes=cat;;
+ *) _excludes=_excludes_f;;
+ esac
+ # handle @list files
+ case "$@" in
+ *@[!.]*)
+ for f in "$@"
+ do
+ case "$f" in
+ *.meta) cat $f;;
+ @*) xargs cat < ${f#@};;
+ *) cat $f;;
+ esac
+ done
+ ;;
+ *) cat /dev/null "$@";;
+ esac 2> /dev/null |
+ sed -e 's,^CWD,C C,;/^[CREFLM] /!d' -e "s,',,g" |
+ $_excludes |
while read op pid path junk
do
: op=$op pid=$pid path=$path
diff --git a/mk/mk-files.txt b/mk/mk-files.txt
index 7882641..7eebfd6 100644
--- a/mk/mk-files.txt
+++ b/mk/mk-files.txt
@@ -432,13 +432,27 @@ You should never need to edit ``warnings.mk``, it will include
``warnings-sets.mk`` if it exists and you use that to make any local
customizations.
+rst2htm.mk
+----------
+
+Logic to simplify generating HTML (and PDF) documents from ReStructuredText.
+
+cython.mk
+---------
+
+Logic to build Python C interface modules using Cython_
+
+.. _Cython: http://www.cython.org/
+
Meta mode
=========
The 20110505 and later versions of ``mk-files`` include a number of
-makefile contributed by Juniper Networks, Inc.
-These allow the latest version of bmake_ to run in `meta mode`_.
+makefiles contributed by Juniper Networks, Inc.
+These allow the latest version of bmake_ to run in `meta mode`_
+see `dirdeps.mk`_
+.. _`dirdeps.mk`: /help/sjg/dirdeps.htm
.. _`meta mode`: bmake-meta-mode.htm
Install
@@ -463,5 +477,5 @@ where you unpacked the tar file, you can::
.. _mk.tar.gz: http://www.crufty.net/ftp/pub/sjg/mk.tar.gz
:Author: sjg@crufty.net
-:Revision: $Id: mk-files.txt,v 1.15 2011/06/08 07:06:18 sjg Exp $
+:Revision: $Id: mk-files.txt,v 1.16 2014/09/05 04:41:16 sjg Exp $
:Copyright: Crufty.NET
diff --git a/mk/mkopt.sh b/mk/mkopt.sh
new file mode 100644
index 0000000..c3a39c5
--- /dev/null
+++ b/mk/mkopt.sh
@@ -0,0 +1,103 @@
+:
+# $Id: mkopt.sh,v 1.10 2015/06/07 17:29:08 sjg Exp $
+#
+# @(#) Copyright (c) 2014, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+# handle WITH[OUT]_* options in a manner compatible with
+# options.mk and bsd.mkopt.mk in recent FreeBSD
+
+# no need to be included more than once
+_MKOPT_SH=:
+_MKOPT_PREFIX=${_MKOPT_PREFIX:-MK_}
+
+#
+# _mk_opt default OPT
+#
+# Set MK_$OPT
+#
+# The semantics are simple, if MK_$OPT has no value
+# WITHOUT_$OPT results in MK_$OPT=no
+# otherwise WITH_$OPT results in MK_$OPT=yes.
+# Note WITHOUT_$OPT overrides WITH_$OPT.
+#
+# For backwards compatability reasons we treat WITH_$OPT=no
+# the same as WITHOUT_$OPT.
+#
+_mk_opt() {
+ _d=$1
+ _mo=${_MKOPT_PREFIX}$2 _wo=WITHOUT_$2 _wi=WITH_$2
+ eval "_mov=\$$_mo _wov=\$$_wo _wiv=\$$_wi"
+
+ case "$_wiv" in
+ no) _wov=no;;
+ esac
+ _v=${_mov:-${_wov:+no}}
+ _v=${_v:-${_wiv:+yes}}
+ _v=${_v:-$_d}
+ _opt_list="$_opt_list $_mo"
+ case "$_v" in
+ yes|no) ;; # sane
+ 0|[NnFf]*) _v=no;; # they mean no
+ 1|[YyTt]*) _v=yes;; # they mean yes
+ *) _v=$_d;; # ignore bogus value
+ esac
+ eval "$_mo=$_v"
+}
+
+#
+# _mk_opts default opt ... [default [opt] ...]
+#
+# see _mk_opts_defaults for example
+#
+_mk_opts() {
+ _d=no
+ for _o in "$@"
+ do
+ case "$_o" in
+ */*) # option is dirname default comes from basename
+ eval "_d=\$${_MKOPT_PREFIX}${_o#*/}"
+ _o=${_o%/*}
+ ;;
+ yes|no) _d=$_o; continue;;
+ esac
+ _mk_opt $_d $_o
+ done
+}
+
+# handle either options.mk style OPTIONS_DEFAULT_*
+# or FreeBSD's new bsd.mkopt.mk style __DEFAULT_*_OPTIONS
+_mk_opts_defaults() {
+ _mk_opts no $OPTIONS_DEFAULT_NO $__DEFAULT_NO_OPTIONS \
+ yes $OPTIONS_DEFAULT_YES $__DEFAULT_YES_OPTIONS \
+ $OPTIONS_DEFAULT_DEPENDENT $__DEFAULT_DEPENDENT_OPTIONS
+}
+
+case "/$0" in
+*/mkopt*)
+ _list=no
+ while :
+ do
+ case "$1" in
+ *=*) eval "$1"; shift;;
+ --no|no) _list="$_list no"; shift;;
+ --yes|yes) _list="$_list yes"; shift;;
+ -DWITH*) eval "${1#-D}=1"; shift;;
+ [A-Z]*) _list="$_list $1"; shift;;
+ *) break;;
+ esac
+ done
+ _mk_opts $_list
+ ;;
+esac
+
diff --git a/mk/own.mk b/mk/own.mk
index e29ff9e..070044f 100644
--- a/mk/own.mk
+++ b/mk/own.mk
@@ -1,4 +1,4 @@
-# $Id: own.mk,v 1.27 2013/07/18 05:46:24 sjg Exp $
+# $Id: own.mk,v 1.30 2015/11/14 18:09:57 sjg Exp $
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
@@ -93,12 +93,10 @@ OPTIONS_DEFAULT_NO+= \
GPROF \
LIBTOOL \
LINT \
- META_MODE \
OPTIONS_DEFAULT_YES+= \
ARCHIVE \
AUTODEP \
- AUTO_OBJ \
CRYPTO \
DOC \
DPADD_MK \
@@ -133,7 +131,9 @@ USERGRP!= id -g
.for x in BIN CONF DOC INFO KMOD LIB MAN NLS SHARE
$xOWN= ${USER}
$xGRP= ${USERGRP}
+$x_INSTALL_OWN=
.endfor
+PROG_INSTALL_OWN=
.endif
.endif
@@ -143,6 +143,7 @@ BINGRP?= ${ROOT_GROUP}
BINOWN?= root
BINMODE?= 555
NONBINMODE?= 444
+DIRMODE?= 755
# Define MANZ to have the man pages compressed (gzip)
#MANZ= 1
diff --git a/mk/rst2htm.mk b/mk/rst2htm.mk
index 4d4c940..296b73c 100644
--- a/mk/rst2htm.mk
+++ b/mk/rst2htm.mk
@@ -1,4 +1,4 @@
-# $Id: rst2htm.mk,v 1.9 2014/02/22 01:52:41 sjg Exp $
+# $Id: rst2htm.mk,v 1.10 2015/09/08 22:17:46 sjg Exp $
#
# @(#) Copyright (c) 2009, Simon J. Gerraty
#
@@ -26,7 +26,12 @@ RST2PDF ?= rst2pdf
RST2S5 ?= rst2s5.py
# the following will run RST2S5 if the target name contains the word 'slides'
# otherwise it uses RST2HTML
-RST2HTM = ${"${.TARGET:T:M*slides*}":?${RST2S5} ${RST2S5_FLAGS}:${RST2HTML} ${RST2HTML_FLAGS}}
+RST2HTM = ${"${.TARGET:T:M*slides*}":?${RST2S5}:${RST2HTML}}
+RST2HTM_SLIDES_FLAGS ?= ${RST2S5_FLAGS}
+RST2HTM_DOC_FLAGS ?= ${RST2HTML_FLAGS}
+RST2HTM_FLAGS ?= ${"${.TARGET:T:M*slides*}":?${RST2HTM_SLIDES_FLAGS}:${RST2HTM_DOC_FLAGS}}
+
+RST2PDF_FLAGS ?= ${"${.TARGET:T:M*slides*}":?${RST2PDF_SLIDES_FLAGS}:${RST2PDF_DOC_FLAGS}}
RST_SUFFIXES ?= .rst .txt
@@ -37,10 +42,10 @@ html: ${HTMFILES}
.SUFFIXES: ${RST_SUFFIXES} .htm .pdf
${RST_SUFFIXES:@s@$s.htm@}:
- ${RST2HTM} ${.IMPSRC} ${.TARGET}
+ ${RST2HTM} ${RST2HTM_FLAGS} ${FLAGS.${.TARGET}} ${.IMPSRC} ${.TARGET}
${RST_SUFFIXES:@s@$s.pdf@}:
- ${RST2PDF} ${.IMPSRC} ${.TARGET}
+ ${RST2PDF} ${RST2PDF_FLAGS} ${FLAGS.${.TARGET}} ${.IMPSRC} ${.TARGET}
.for s in ${RSTSRCS:O:u}
${s:R:T}.htm: $s
diff --git a/mk/sys.clean-env.mk b/mk/sys.clean-env.mk
index b1867c3..396599b 100644
--- a/mk/sys.clean-env.mk
+++ b/mk/sys.clean-env.mk
@@ -1,4 +1,4 @@
-# $Id: sys.clean-env.mk,v 1.20 2012/11/12 06:56:04 sjg Exp $
+# $Id: sys.clean-env.mk,v 1.21 2016/02/18 21:16:40 sjg Exp $
#
# @(#) Copyright (c) 2009, Simon J. Gerraty
#
@@ -94,6 +94,7 @@ _tricky_env_vars = MAKEOBJDIR OBJTOP
# MAKEOBJDIR='${.CURDIR:S,${SRCTOP},${OBJTOP},}'
_srctop := ${SRCTOP:U${SB_SRC:U${SB}/src}}
_objroot := ${OBJROOT:U${SB_OBJROOT:U${SB}/${SB_OBJPREFIX}}}
+.if ${MAKE_VERSION} < 20160218
_objtop := ${OBJTOP:U${_objroot}${MACHINE}}
# Take care of ${MACHINE}
.if ${MACHINE} == "host" || ${OBJTOP} == ${HOST_OBJTOP:Uno}
@@ -113,7 +114,17 @@ MAKEOBJDIR = $${.CURDIR:S,${_srctop},$${OBJTOP},}
.for v in ${_tricky_env_vars}
$v := ${$v}
.endfor
+.else
+# we cannot use the '$$' trick, anymore
+# but we can export a literal (unexpanded) value
+SRCTOP := ${_srctop}
+OBJROOT := ${_objroot}
+OBJTOP = ${OBJROOT}${MACHINE}
+MAKEOBJDIR = ${.CURDIR:S,${SRCTOP},${OBJTOP},}
+.export-literal SRCTOP OBJROOT ${_tricky_env_vars}
+.endif
#.info ${_tricky_env_vars:@v@${.newline}$v=${$v}@}
-
+#showenv:
+# @env | egrep 'OBJ|SRC'
.endif # MAKEOBJDIR
.endif # level 0
diff --git a/mk/sys.dependfile.mk b/mk/sys.dependfile.mk
index 42cec61..b4d79f7 100644
--- a/mk/sys.dependfile.mk
+++ b/mk/sys.dependfile.mk
@@ -1,4 +1,4 @@
-# $Id: sys.dependfile.mk,v 1.5 2013/03/08 00:59:21 sjg Exp $
+# $Id: sys.dependfile.mk,v 1.7 2016/02/20 01:57:39 sjg Exp $
#
# @(#) Copyright (c) 2012, Simon J. Gerraty
#
@@ -25,6 +25,12 @@
# All depend file names should start with this
.MAKE.DEPENDFILE_PREFIX ?= Makefile.depend
+.if !empty(.MAKE.DEPENDFILE) && \
+ ${.MAKE.DEPENDFILE:M${.MAKE.DEPENDFILE_PREFIX}*} == ""
+# let us do our thing below...
+.undef .MAKE.DEPENDFILE
+.endif
+
# The order of preference: we will use the first one of these we find.
# It usually makes sense to order from most specific to least.
.MAKE.DEPENDFILE_PREFERENCE ?= \
@@ -43,7 +49,9 @@ _e := ${.MAKE.DEPENDFILE_PREFERENCE:@m@${exists($m):?$m:}@}
# If any already exist, we should follow suit.
_aml = ${ALL_MACHINE_LIST:Uarm amd64 i386 powerpc:N${MACHINE}} ${MACHINE}
# MACHINE must be the last entry in _aml ;-)
+_m := ${MACHINE}
_e := ${_aml:@MACHINE@${.MAKE.DEPENDFILE_PREFERENCE:@m@${exists($m):?$m:}@}@}
+MACHINE := ${_m}
.if !empty(_e)
.MAKE.DEPENDFILE ?= ${.MAKE.DEPENDFILE_PREFERENCE:M*${MACHINE}:[1]}
.endif
diff --git a/mk/sys.mk b/mk/sys.mk
index 236f62d..9dc0796 100644
--- a/mk/sys.mk
+++ b/mk/sys.mk
@@ -1,4 +1,4 @@
-# $Id: sys.mk,v 1.36 2014/05/11 00:30:19 sjg Exp $
+# $Id: sys.mk,v 1.41 2015/11/14 20:20:34 sjg Exp $
#
# @(#) Copyright (c) 2003-2009, Simon J. Gerraty
#
@@ -75,8 +75,12 @@ M_L_TARGETS = ${M_ListToMatch:S,V,_TARGETS,}
M_ListToSkip= O:u:ts::S,:,:N,g:S,^,N,
# type should be a builtin in any sh since about 1980,
+# but sadly there are exceptions!
+.if ${.MAKE.OS:Unknown:NBSD/OS} == ""
+_type_sh = which
+.endif
# AUTOCONF := ${autoconf:L:${M_whence}}
-M_type = @x@(type $$x 2> /dev/null); echo;@:sh:[0]:N* found*:[@]:C,[()],,g
+M_type = @x@(${_type_sh:Utype} $$x) 2> /dev/null; echo;@:sh:[0]:N* found*:[@]:C,[()],,g
M_whence = ${M_type}:M/*:[1]
# convert a path to a valid shell variable
@@ -102,6 +106,9 @@ _TARGETS := ${.TARGETS}
# we need HOST_TARGET etc below.
.include <host-target.mk>
+# early customizations
+.-include <local.sys.env.mk>
+
# find the OS specifics
.if defined(SYS_OS_MK)
.include <${SYS_OS_MK}>
@@ -126,11 +133,30 @@ SYS_OS_MK := ${_sys_mk}
.export SYS_OS_MK
.endif
-# allow customization without editing.
-.-include <local.sys.mk>
+# some options we need to know early
+OPTIONS_DEFAULT_NO += \
+ DIRDEPS_BUILD \
+ DIRDEPS_CACHE \
+ META_MODE
+
+OPTIONS_DEFAULT_DEPENDENT += \
+ AUTO_OBJ/DIRDEPS_BUILD \
+ STAGING/DIRDEPS_BUILD \
+
+.-include "options.mk"
+
+.if ${MK_DIRDEPS_BUILD:Uno} == "yes"
+MK_META_MODE = yes
+.-include <meta.sys.mk>
+.elif ${MK_META_MODE:Uno} == "yes"
+.MAKE.MODE = meta verbose
+.endif
+# make sure we have a harmless value
+.MAKE.MODE ?= normal
# if you want objdirs make them automatic
-.if ${MKOBJDIRS:Uno} == "auto"
+# and do it early before we compute .PATH
+.if ${MK_AUTO_OBJ:Uno} == "yes" || ${MKOBJDIRS:Uno} == "auto"
.include <auto.obj.mk>
.endif
@@ -178,17 +204,8 @@ Mkdirs= Mkdirs() { \
.cc.cpp-out:
@${COMPILE.cc:N-c} -E ${.IMPSRC} | grep -v '^[ ]*$$'
-# we don't include own.mk but user can expect -DWITH_META_MODE to work
-.if defined(WITHOUT_META_MODE)
-USE_META= no
-.elif defined(WITH_META_MODE)
-USE_META= yes
-.endif
-.if ${USE_META:Uno} == "yes"
-.-include <meta.sys.mk>
-.endif
-# make sure we have a harmless value
-.MAKE.MODE ?= normal
+# late customizations
+.-include <local.sys.mk>
# if .CURDIR is matched by any entry in DEBUG_MAKE_DIRS we
# will apply DEBUG_MAKE_FLAGS, now.
diff --git a/mk/warnings.mk b/mk/warnings.mk
index bacbefb..dc230bc 100644
--- a/mk/warnings.mk
+++ b/mk/warnings.mk
@@ -1,5 +1,5 @@
# RCSid:
-# $Id: warnings.mk,v 1.8 2014/04/02 19:20:23 sjg Exp $
+# $Id: warnings.mk,v 1.9 2016/02/20 02:00:58 sjg Exp $
#
# @(#) Copyright (c) 2002, Simon J. Gerraty
#
@@ -15,6 +15,8 @@
#
.ifndef _w_cflags
+# make sure we get the behavior we expect
+.MAKE.SAVE_DOLLARS = no
# Any number of warnings sets can be added.
.-include "warnings-sets.mk"
diff --git a/mk/whats.mk b/mk/whats.mk
new file mode 100644
index 0000000..d17c3ef
--- /dev/null
+++ b/mk/whats.mk
@@ -0,0 +1,63 @@
+# $Id: whats.mk,v 1.1 2014/08/30 22:40:47 sjg Exp $
+#
+# @(#) Copyright (c) 2014, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+.if ${MK_WHATSTRING:Uno} != "no"
+what_build_exts?= o
+# it can be useful to embed a what(1) string in binaries
+# so that the build location can be seen from a core file.
+.if defined(PROG) && ${.MAKE.MAKEFILES:M*prog.mk} != ""
+what_thing?= ${PROGNAME:U${PROG}}
+what_build_thing?= ${PROG}
+.elif defined(LIB) && ${.MAKE.MAKEFILES:M*lib.mk} != ""
+# probably only makes sense for shared libs
+# and the plumbing needed varies depending on *lib.mk
+what_thing?= lib${LIB}
+.if !empty(SOBJS)
+_soe:= ${SOBJS:E:[1]}
+what_build_exts= ${_soe}
+SOBJS+= ${what_uuid}.${_soe}
+.endif
+.elif defined(KMOD) && ${.MAKE.MAKEFILES:M*kmod.mk} != ""
+what_thing?= ${KMOD}
+what_build_thing?= ${KMOD}.ko
+.endif
+
+.if !empty(what_thing)
+# a unique name that won't conflict with anything
+what_uuid = what_${.CURDIR:T:hash}
+
+.if !empty(what_build_thing)
+${what_build_thing}: ${what_build_exts:@e@${what_uuid}.$e@}
+.endif
+OBJS+= ${what_uuid}.o
+CLEANFILES+= ${what_uuid}.c
+
+# we do not need to capture this
+SUPPRESS_DEPEND+= *${what_uuid}.c
+
+SB?= ${SRCTOP:H}
+SB_LOCATION?= ${HOST}:${SB}
+what_location:= ${.OBJDIR:S,${SB},${SB_LOCATION},}
+
+# this works with clang and gcc
+_what_t= const char __attribute__ ((section(".data")))
+_what1:= @(\#)${what_thing:tu} built ${%Y%m%d:L:localtime} by ${USER}
+_what2:= @(\#)${what_location}
+
+${what_uuid}.c:
+ echo '${_what_t} ${what_uuid}1[] = "${_what1}";' > $@ ${.OODATE:MNO_META_CMP}
+ echo '${_what_t} ${what_uuid}2[] = "${_what2}";' >> $@
+.endif
+.endif
diff --git a/nonints.h b/nonints.h
index c19ba89..5a5c613 100644
--- a/nonints.h
+++ b/nonints.h
@@ -1,4 +1,4 @@
-/* $NetBSD: nonints.h,v 1.65 2012/08/30 21:17:05 sjg Exp $ */
+/* $NetBSD: nonints.h,v 1.72 2016/02/18 20:25:08 sjg Exp $ */
/*-
* Copyright (c) 1988, 1989, 1990, 1993
@@ -91,7 +91,7 @@ int Compat_Make(void *, void *);
/* cond.c */
struct If;
-int Cond_EvalExpression(const struct If *, char *, Boolean *, int);
+int Cond_EvalExpression(const struct If *, char *, Boolean *, int, Boolean);
int Cond_Eval(char *);
void Cond_restore_depth(unsigned int);
unsigned int Cond_save_depth(void);
@@ -120,6 +120,7 @@ void Finish(int) MAKE_ATTR_DEAD;
int eunlink(const char *);
void execError(const char *, const char *);
char *getTmpdir(void);
+Boolean s2Boolean(const char *, Boolean);
Boolean getBoolean(const char *, Boolean);
/* parse.c */
@@ -184,8 +185,8 @@ void Var_Set(const char *, const char *, GNode *, int);
void Var_Append(const char *, const char *, GNode *);
Boolean Var_Exists(const char *, GNode *);
char *Var_Value(const char *, GNode *, char **);
-char *Var_Parse(const char *, GNode *, Boolean, int *, void **);
-char *Var_Subst(const char *, const char *, GNode *, Boolean);
+char *Var_Parse(const char *, GNode *, int, int *, void **);
+char *Var_Subst(const char *, const char *, GNode *, int);
char *Var_GetTail(const char *);
char *Var_GetHead(const char *);
void Var_Init(void);
diff --git a/os.sh b/os.sh
index b714eb7..1dd394f 100644
--- a/os.sh
+++ b/os.sh
@@ -17,7 +17,7 @@
# Simon J. Gerraty <sjg@crufty.net>
# RCSid:
-# $Id: os.sh,v 1.46 2014/05/19 16:38:09 sjg Exp $
+# $Id: os.sh,v 1.50 2015/12/17 17:06:29 sjg Exp $
#
# @(#) Copyright (c) 1994 Simon J. Gerraty
#
@@ -44,7 +44,7 @@ MACHINE_ARCH=`uname -p 2>/dev/null || echo $MACHINE`
# there is at least one case of `uname -p` outputting
# a bunch of usless drivel
case "$MACHINE_ARCH" in
-*[!A-Za-z0-9_-]*) MACHINE_ARCH="$MACHINE";;
+unknown|*[!A-Za-z0-9_-]*) MACHINE_ARCH="$MACHINE";;
esac
# we need this here, and it is not always available...
@@ -56,10 +56,10 @@ Which() {
case "$1" in
/*) test $t $1 && echo $1;;
*)
- # some shells cannot correctly handle `IFS`
- # in conjunction with the for loop.
- _dirs=`IFS=:; echo ${2:-$PATH}`
- for d in $_dirs
+ # some shells cannot correctly handle `IFS`
+ # in conjunction with the for loop.
+ _dirs=`IFS=:; echo ${2:-$PATH}`
+ for d in $_dirs
do
test $t $d/$1 && { echo $d/$1; break; }
done
@@ -70,11 +70,11 @@ Which() {
# tr is insanely non-portable wrt char classes, so we need to
# spell out the alphabet. sed y/// would work too.
toUpper() {
- ${TR:-tr} abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ
+ ${TR:-tr} abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ
}
toLower() {
- ${TR:-tr} ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz
+ ${TR:-tr} ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz
}
K=
@@ -91,7 +91,7 @@ SunOS)
export CHOWN
# Great! Solaris keeps moving arch(1)
- # should just bite the bullet and use uname -p
+ # should just bite the bullet and use uname -p
arch=`Which arch /usr/bin:/usr/ucb`
MAILER=/usr/ucb/Mail
@@ -105,8 +105,8 @@ SunOS)
MACHINE=$MACHINE_ARCH
;;
4*)
- MACHINE_ARCH=`arch`
- ;;
+ MACHINE_ARCH=`arch`
+ ;;
5*)
K=-k
LOCAL_FS=ufs
@@ -116,8 +116,8 @@ SunOS)
# overwriting an existing file!!!!! We want one that works!
test -x /usr/xpg4/bin/ln && LN=${LN:-/usr/xpg4/bin/ln}
# wonderful, 5.8's tr again require's []'s
- # but /usr/xpg4/bin/tr causes problems if LC_COLLATE is set!
- # use toUpper/toLower instead.
+ # but /usr/xpg4/bin/tr causes problems if LC_COLLATE is set!
+ # use toUpper/toLower instead.
;;
esac
case "$OS/$MACHINE_ARCH" in
@@ -137,11 +137,14 @@ SunOS)
# NetBSD at least has good backward compatibility
# so NetBSD/i386 is good enough
case $OS in
- NetBSD) SHARE_ARCH=$OS/${MACHINE_ARCH:-$MACHINE};;
+ NetBSD)
+ HOST_ARCH=$MACHINE
+ SHARE_ARCH=$OS/$HOST
+ ;;
OpenBSD)
- arch=`Which arch /usr/bin:/usr/ucb:$PATH`
- MACHINE_ARCH=`$arch -s`
- ;;
+ arch=`Which arch /usr/bin:/usr/ucb:$PATH`
+ MACHINE_ARCH=`$arch -s`
+ ;;
esac
NAWK=awk
export NAWK
@@ -203,28 +206,37 @@ esac
TMP_DIRS=${TMP_DIRS:-"/tmp /var/tmp"}
MACHINE_ARCH=${MACHINE_ARCH:-$MACHINE}
+HOST_ARCH=${HOST_ARCH:-$MACHINE_ARCH}
# we mount server:/share/arch/$SHARE_ARCH as /usr/local
-SHARE_ARCH=${SHARE_ARCH:-$OS/$OSMAJOR.X/$MACHINE_ARCH}
+SHARE_ARCH=${SHARE_ARCH:-$OS/$OSMAJOR.X/$HOST_ARCH}
LN=${LN:-ln}
TR=${TR:-tr}
# Some people like have /share/$HOST_TARGET/bin etc.
-HOST_TARGET=`echo ${OS}${OSMAJOR}-${MACHINE_ARCH} | toLower`
+HOST_TARGET=`echo ${OS}${OSMAJOR}-$HOST_ARCH | tr -d / | toLower`
export HOST_TARGET
case `echo -n .` in -n*) N=; C="\c";; *) N=-n; C=;; esac
-export HOSTNAME HOST
+Echo() {
+ case "$1" in
+ -n) _n=$N _c=$C; shift;;
+ *) _n= _c=;;
+ esac
+ echo $_n "$@" $_c
+}
+
+export HOSTNAME HOST
export OS MACHINE MACHINE_ARCH OSREL OSMAJOR LOCAL_FS TMP_DIRS MAILER N C K PS_AXC
export LN SHARE_ARCH TR
case /$0 in
*/os.sh)
- for v in $*
+ for v in $*
do
- eval vv=\$$v
- echo "$v='$vv'"
+ eval vv=\$$v
+ echo "$v='$vv'"
done
- ;;
+ ;;
esac
diff --git a/parse.c b/parse.c
index 0f9a8fc..2a22c0b 100644
--- a/parse.c
+++ b/parse.c
@@ -1,4 +1,4 @@
-/* $NetBSD: parse.c,v 1.194 2014/02/15 00:17:17 christos Exp $ */
+/* $NetBSD: parse.c,v 1.212 2016/02/19 06:19:06 sjg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -69,14 +69,14 @@
*/
#ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: parse.c,v 1.194 2014/02/15 00:17:17 christos Exp $";
+static char rcsid[] = "$NetBSD: parse.c,v 1.212 2016/02/19 06:19:06 sjg Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)parse.c 8.3 (Berkeley) 3/19/94";
#else
-__RCSID("$NetBSD: parse.c,v 1.194 2014/02/15 00:17:17 christos Exp $");
+__RCSID("$NetBSD: parse.c,v 1.212 2016/02/19 06:19:06 sjg Exp $");
#endif
#endif /* not lint */
#endif
@@ -128,7 +128,6 @@ __RCSID("$NetBSD: parse.c,v 1.194 2014/02/15 00:17:17 christos Exp $");
#include <assert.h>
#include <ctype.h>
#include <errno.h>
-#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
@@ -161,6 +160,7 @@ typedef struct IFile {
int lineno; /* current line number in file */
int first_lineno; /* line number of start of text */
int cond_depth; /* 'if' nesting when file opened */
+ Boolean depending; /* state of doing_depend on EOF */
char *P_str; /* point to base of string buffer */
char *P_ptr; /* point to next char of string buffer */
char *P_end; /* point to the end of string buffer */
@@ -508,7 +508,11 @@ loadfile(const char *path, int fd)
#ifdef HAVE_MMAP
if (load_getsize(fd, &lf->len) == SUCCESS) {
/* found a size, try mmap */
+#ifdef _SC_PAGESIZE
pagesize = sysconf(_SC_PAGESIZE);
+#else
+ pagesize = 0;
+#endif
if (pagesize <= 0) {
pagesize = 0x1000;
}
@@ -812,7 +816,7 @@ ParseMessage(char *line)
while (isspace((u_char)*line))
line++;
- line = Var_Subst(NULL, line, VAR_CMD, 0);
+ line = Var_Subst(NULL, line, VAR_CMD, VARF_WANTRES);
Parse_Error(mtype, "%s", line);
free(line);
@@ -1203,7 +1207,17 @@ ParseDoDependency(char *line)
curTargs = Lst_Init(FALSE);
+ /*
+ * First, grind through the targets.
+ */
+
do {
+ /*
+ * Here LINE points to the beginning of the next word, and
+ * LSTART points to the actual beginning of the line.
+ */
+
+ /* Find the end of the next word. */
for (cp = line; *cp && (ParseIsEscaped(lstart, cp) ||
!(isspace((unsigned char)*cp) ||
*cp == '!' || *cp == ':' || *cp == LPAREN));
@@ -1219,13 +1233,17 @@ ParseDoDependency(char *line)
int length;
void *freeIt;
- (void)Var_Parse(cp, VAR_CMD, TRUE, &length, &freeIt);
- if (freeIt)
- free(freeIt);
+ (void)Var_Parse(cp, VAR_CMD, VARF_UNDEFERR|VARF_WANTRES,
+ &length, &freeIt);
+ free(freeIt);
cp += length-1;
}
}
+ /*
+ * If the word is followed by a left parenthesis, it's the
+ * name of an object file inside an archive (ar file).
+ */
if (!ParseIsEscaped(lstart, cp) && *cp == LPAREN) {
/*
* Archives must be handled specially to make sure the OP_ARCHV
@@ -1242,13 +1260,16 @@ ParseDoDependency(char *line)
"Error in archive specification: \"%s\"", line);
goto out;
} else {
+ /* Done with this word; on to the next. */
continue;
}
}
- savec = *cp;
if (!*cp) {
/*
+ * We got to the end of the line while we were still
+ * looking at targets.
+ *
* Ending a dependency line without an operator is a Bozo
* no-no. As a heuristic, this is also often triggered by
* undetected conflicts from cvs/rcs merges.
@@ -1263,10 +1284,13 @@ ParseDoDependency(char *line)
: "Need an operator");
goto out;
}
+
+ /* Insert a null terminator. */
+ savec = *cp;
*cp = '\0';
/*
- * Have a word in line. See if it's a special target and set
+ * Got the word. See if it's a special target and if so set
* specType to match it.
*/
if (*line == '.' && isupper ((unsigned char)line[1])) {
@@ -1405,6 +1429,8 @@ ParseDoDependency(char *line)
(void)Lst_AtEnd(curTargs, line);
}
+ /* Apply the targets. */
+
while(!Lst_IsEmpty(curTargs)) {
char *targName = (char *)Lst_DeQueue(curTargs);
@@ -1422,7 +1448,9 @@ ParseDoDependency(char *line)
Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line);
}
+ /* Don't need the inserted null terminator any more. */
*cp = savec;
+
/*
* If it is a special type and not .PATH, it's the only target we
* allow on this line...
@@ -1498,12 +1526,21 @@ ParseDoDependency(char *line)
goto out;
}
- cp++; /* Advance beyond operator */
+ /* Advance beyond the operator */
+ cp++;
+ /*
+ * Apply the operator to the target. This is how we remember which
+ * operator a target was defined with. It fails if the operator
+ * used isn't consistent across all references.
+ */
Lst_ForEach(targets, ParseDoOp, &op);
/*
- * Get to the first source
+ * Onward to the sources.
+ *
+ * LINE will now point to the first source word, if any, or the
+ * end of the string if not.
*/
while (*cp && isspace ((unsigned char)*cp)) {
cp++;
@@ -1911,7 +1948,7 @@ Parse_DoVar(char *line, GNode *ctxt)
if (!Var_Exists(line, ctxt))
Var_Set(line, "", ctxt, 0);
- cp = Var_Subst(NULL, cp, ctxt, FALSE);
+ cp = Var_Subst(NULL, cp, ctxt, VARF_WANTRES|VARF_ASSIGN);
oldVars = oldOldVars;
freeCp = TRUE;
@@ -1926,7 +1963,7 @@ Parse_DoVar(char *line, GNode *ctxt)
* expansion on the whole thing. The resulting string will need
* freeing when we're done, so set freeCmd to TRUE.
*/
- cp = Var_Subst(NULL, cp, VAR_CMD, TRUE);
+ cp = Var_Subst(NULL, cp, VAR_CMD, VARF_UNDEFERR|VARF_WANTRES);
freeCp = TRUE;
}
@@ -1962,6 +1999,40 @@ Parse_DoVar(char *line, GNode *ctxt)
}
+/*
+ * ParseMaybeSubMake --
+ * Scan the command string to see if it a possible submake node
+ * Input:
+ * cmd the command to scan
+ * Results:
+ * TRUE if the command is possibly a submake, FALSE if not.
+ */
+static Boolean
+ParseMaybeSubMake(const char *cmd)
+{
+ size_t i;
+ static struct {
+ const char *name;
+ size_t len;
+ } vals[] = {
+#define MKV(A) { A, sizeof(A) - 1 }
+ MKV("${MAKE}"),
+ MKV("${.MAKE}"),
+ MKV("$(MAKE)"),
+ MKV("$(.MAKE)"),
+ MKV("make"),
+ };
+ for (i = 0; i < sizeof(vals)/sizeof(vals[0]); i++) {
+ char *ptr;
+ if ((ptr = strstr(cmd, vals[i].name)) == NULL)
+ continue;
+ if ((ptr == cmd || !isalnum((unsigned char)ptr[-1]))
+ && !isalnum((unsigned char)ptr[vals[i].len]))
+ return TRUE;
+ }
+ return FALSE;
+}
+
/*-
* ParseAddCmd --
* Lst_ForEach function to add a command line to all targets
@@ -1974,7 +2045,9 @@ Parse_DoVar(char *line, GNode *ctxt)
* Always 0
*
* Side Effects:
- * A new element is added to the commands list of the node.
+ * A new element is added to the commands list of the node,
+ * and the node can be marked as a submake node if the command is
+ * determined to be that.
*/
static int
ParseAddCmd(void *gnp, void *cmd)
@@ -1988,6 +2061,8 @@ ParseAddCmd(void *gnp, void *cmd)
/* if target already supplied, ignore commands */
if (!(gn->type & OP_HAS_COMMANDS)) {
(void)Lst_AtEnd(gn->commands, cmd);
+ if (ParseMaybeSubMake(cmd))
+ gn->type |= OP_SUBMAKE;
ParseMark(gn);
} else {
#ifdef notyet
@@ -2080,7 +2155,7 @@ Parse_AddIncludeDir(char *dir)
*/
static void
-Parse_include_file(char *file, Boolean isSystem, int silent)
+Parse_include_file(char *file, Boolean isSystem, Boolean depinc, int silent)
{
struct loadedfile *lf;
char *fullname; /* full pathname of file */
@@ -2180,6 +2255,8 @@ Parse_include_file(char *file, Boolean isSystem, int silent)
/* Start reading from this file next */
Parse_SetInput(fullname, 0, -1, loadedfile_nextbuf, lf);
curFile->lf = lf;
+ if (depinc)
+ doing_depend = depinc; /* only turn it on */
}
static void
@@ -2227,9 +2304,9 @@ ParseDoInclude(char *line)
* Substitute for any variables in the file name before trying to
* find the thing.
*/
- file = Var_Subst(NULL, file, VAR_CMD, FALSE);
+ file = Var_Subst(NULL, file, VAR_CMD, VARF_WANTRES);
- Parse_include_file(file, endc == '>', silent);
+ Parse_include_file(file, endc == '>', (*line == 'd'), silent);
free(file);
}
@@ -2264,10 +2341,8 @@ ParseSetIncludedFile(void)
fprintf(debug_file, "%s: ${.INCLUDEDFROMDIR} = `%s' "
"${.INCLUDEDFROMFILE} = `%s'\n", __func__, pd, pf);
- if (fp)
- free(fp);
- if (dp)
- free(dp);
+ free(fp);
+ free(dp);
}
/*-
*---------------------------------------------------------------------
@@ -2319,15 +2394,19 @@ static void
ParseTrackInput(const char *name)
{
char *old;
+ char *ep;
char *fp = NULL;
size_t name_len = strlen(name);
old = Var_Value(MAKE_MAKEFILES, VAR_GLOBAL, &fp);
if (old) {
+ ep = old + strlen(old) - name_len;
/* does it contain name? */
for (; old != NULL; old = strchr(old, ' ')) {
if (*old == ' ')
old++;
+ if (old >= ep)
+ break; /* cannot contain name */
if (memcmp(old, name, name_len) == 0
&& (old[name_len] == 0 || old[name_len] == ' '))
goto cleanup;
@@ -2393,6 +2472,7 @@ Parse_SetInput(const char *name, int line, int fd,
curFile->nextbuf = nextbuf;
curFile->nextbuf_arg = arg;
curFile->lf = NULL;
+ curFile->depending = doing_depend; /* restore this on EOF */
assert(nextbuf != NULL);
@@ -2453,7 +2533,7 @@ ParseTraditionalInclude(char *line)
* Substitute for any variables in the file name before trying to
* find the thing.
*/
- all_files = Var_Subst(NULL, file, VAR_CMD, FALSE);
+ all_files = Var_Subst(NULL, file, VAR_CMD, VARF_WANTRES);
if (*file == '\0') {
Parse_Error(PARSE_FATAL,
@@ -2471,7 +2551,7 @@ ParseTraditionalInclude(char *line)
else
done = 1;
- Parse_include_file(file, FALSE, silent);
+ Parse_include_file(file, FALSE, FALSE, silent);
}
free(all_files);
}
@@ -2521,7 +2601,7 @@ ParseGmakeExport(char *line)
/*
* Expand the value before putting it in the environment.
*/
- value = Var_Subst(NULL, value, VAR_CMD, FALSE);
+ value = Var_Subst(NULL, value, VAR_CMD, VARF_WANTRES);
setenv(variable, value, 1);
}
#endif
@@ -2549,6 +2629,7 @@ ParseEOF(void)
assert(curFile->nextbuf != NULL);
+ doing_depend = curFile->depending; /* restore this */
/* get next input buffer, if any */
ptr = curFile->nextbuf(curFile->nextbuf_arg, &len);
curFile->P_ptr = ptr;
@@ -2911,7 +2992,7 @@ Parse_File(const char *name, int fd)
continue;
}
if (strncmp(cp, "include", 7) == 0 ||
- ((cp[0] == 's' || cp[0] == '-') &&
+ ((cp[0] == 'd' || cp[0] == 's' || cp[0] == '-') &&
strncmp(&cp[1], "include", 7) == 0)) {
ParseDoInclude(cp);
continue;
@@ -3070,7 +3151,7 @@ Parse_File(const char *name, int fd)
* variables expanded before being parsed. Tell the variable
* module to complain if some variable is undefined...
*/
- line = Var_Subst(NULL, line, VAR_CMD, TRUE);
+ line = Var_Subst(NULL, line, VAR_CMD, VARF_UNDEFERR|VARF_WANTRES);
/*
* Need a non-circular list for the target nodes
diff --git a/suff.c b/suff.c
index d4f0eb1..98bd447 100644
--- a/suff.c
+++ b/suff.c
@@ -1,4 +1,4 @@
-/* $NetBSD: suff.c,v 1.70 2013/05/18 13:13:34 sjg Exp $ */
+/* $NetBSD: suff.c,v 1.78 2016/02/18 18:29:14 christos Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -69,14 +69,14 @@
*/
#ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: suff.c,v 1.70 2013/05/18 13:13:34 sjg Exp $";
+static char rcsid[] = "$NetBSD: suff.c,v 1.78 2016/02/18 18:29:14 christos Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)suff.c 8.4 (Berkeley) 3/21/94";
#else
-__RCSID("$NetBSD: suff.c,v 1.70 2013/05/18 13:13:34 sjg Exp $");
+__RCSID("$NetBSD: suff.c,v 1.78 2016/02/18 18:29:14 christos Exp $");
#endif
#endif /* not lint */
#endif
@@ -553,7 +553,20 @@ Suff_ClearSuffixes(void)
#endif
sufflist = Lst_Init(FALSE);
sNum = 0;
- suffNull = emptySuff;
+ if (suffNull)
+ SuffFree(suffNull);
+ emptySuff = suffNull = bmake_malloc(sizeof(Suff));
+
+ suffNull->name = bmake_strdup("");
+ suffNull->nameLen = 0;
+ suffNull->searchPath = Lst_Init(FALSE);
+ Dir_Concat(suffNull->searchPath, dirSearchPath);
+ suffNull->children = Lst_Init(FALSE);
+ suffNull->parents = Lst_Init(FALSE);
+ suffNull->ref = Lst_Init(FALSE);
+ suffNull->sNum = sNum++;
+ suffNull->flags = SUFF_NULL;
+ suffNull->refCount = 1;
}
/*-
@@ -1543,7 +1556,7 @@ SuffExpandChildren(LstNode cln, GNode *pgn)
if (DEBUG(SUFF)) {
fprintf(debug_file, "Expanding \"%s\"...", cgn->name);
}
- cp = Var_Subst(NULL, cgn->name, pgn, TRUE);
+ cp = Var_Subst(NULL, cgn->name, pgn, VARF_UNDEFERR|VARF_WANTRES);
if (cp != NULL) {
Lst members = Lst_Init(FALSE);
@@ -1596,13 +1609,13 @@ SuffExpandChildren(LstNode cln, GNode *pgn)
int len;
void *freeIt;
- junk = Var_Parse(cp, pgn, TRUE, &len, &freeIt);
+ junk = Var_Parse(cp, pgn, VARF_UNDEFERR|VARF_WANTRES,
+ &len, &freeIt);
if (junk != var_Error) {
cp += len - 1;
}
- if (freeIt)
- free(freeIt);
+ free(freeIt);
} else if (*cp == '\\' && *cp != '\0') {
/*
* Escaped something -- skip over it
@@ -1920,8 +1933,7 @@ SuffFindArchiveDeps(GNode *gn, Lst slst)
for (i = (sizeof(copy)/sizeof(copy[0]))-1; i >= 0; i--) {
char *p1;
Var_Set(copy[i], Var_Value(copy[i], mem, &p1), gn, 0);
- if (p1)
- free(p1);
+ free(p1);
}
@@ -2524,32 +2536,18 @@ Suff_SetNull(char *name)
void
Suff_Init(void)
{
- sufflist = Lst_Init(FALSE);
#ifdef CLEANUP
suffClean = Lst_Init(FALSE);
#endif
srclist = Lst_Init(FALSE);
transforms = Lst_Init(FALSE);
- sNum = 0;
/*
* Create null suffix for single-suffix rules (POSIX). The thing doesn't
* actually go on the suffix list or everyone will think that's its
* suffix.
*/
- emptySuff = suffNull = bmake_malloc(sizeof(Suff));
-
- suffNull->name = bmake_strdup("");
- suffNull->nameLen = 0;
- suffNull->searchPath = Lst_Init(FALSE);
- Dir_Concat(suffNull->searchPath, dirSearchPath);
- suffNull->children = Lst_Init(FALSE);
- suffNull->parents = Lst_Init(FALSE);
- suffNull->ref = Lst_Init(FALSE);
- suffNull->sNum = sNum++;
- suffNull->flags = SUFF_NULL;
- suffNull->refCount = 1;
-
+ Suff_ClearSuffixes();
}
diff --git a/targ.c b/targ.c
index d26b845..dd52b29 100644
--- a/targ.c
+++ b/targ.c
@@ -1,4 +1,4 @@
-/* $NetBSD: targ.c,v 1.57 2012/06/12 19:21:51 joerg Exp $ */
+/* $NetBSD: targ.c,v 1.61 2016/01/17 17:45:21 christos Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -69,14 +69,14 @@
*/
#ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: targ.c,v 1.57 2012/06/12 19:21:51 joerg Exp $";
+static char rcsid[] = "$NetBSD: targ.c,v 1.61 2016/01/17 17:45:21 christos Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)targ.c 8.2 (Berkeley) 3/19/94";
#else
-__RCSID("$NetBSD: targ.c,v 1.57 2012/06/12 19:21:51 joerg Exp $");
+__RCSID("$NetBSD: targ.c,v 1.61 2016/01/17 17:45:21 christos Exp $");
#endif
#endif /* not lint */
#endif
@@ -292,10 +292,8 @@ TargFreeGN(void *gnp)
free(gn->name);
- if (gn->uname)
- free(gn->uname);
- if (gn->path)
- free(gn->path);
+ free(gn->uname);
+ free(gn->path);
/* gn->fname points to name allocated when file was opened, don't free */
Lst_Destroy(gn->iParents, NULL);
diff --git a/unit-tests/Makefile.in b/unit-tests/Makefile.in
index 3f70f8a..4ee94bd 100644
--- a/unit-tests/Makefile.in
+++ b/unit-tests/Makefile.in
@@ -1,17 +1,18 @@
-# $Id: Makefile.in,v 1.44 2013/08/28 22:09:29 sjg Exp $
+# $Id: Makefile.in,v 1.48 2015/12/07 04:06:29 sjg Exp $
#
-# $NetBSD: Makefile,v 1.38 2013/08/28 21:56:50 sjg Exp $
+# $NetBSD: Makefile,v 1.52 2015/05/05 21:51:09 sjg Exp $
#
# Unit tests for make(1)
# The main targets are:
#
# all: run all the tests
-# test: run 'all', capture output and compare to expected results
+# test: run 'all', and compare to expected results
# accept: move generated output to expected results
#
# Adding a test case.
# Each feature should get its own set of tests in its own suitably
-# named makefile which should be added to SUBFILES to hook it in.
+# named makefile (*.mk), with its own set of expected results (*.exp),
+# and it should be added to the TESTNAMES list.
#
srcdir= @srcdir@
@@ -19,12 +20,14 @@ srcdir= @srcdir@
.MAIN: all
UNIT_TESTS:= ${srcdir}
+.PATH: ${UNIT_TESTS}
-# Simple sub-makefiles - we run them as a black box
-# keep the list sorted.
-SUBFILES= \
+# Each test is in a sub-makefile.
+# Keep the list sorted.
+TESTNAMES= \
comment \
cond1 \
+ cond2 \
error \
export \
export-all \
@@ -42,7 +45,6 @@ SUBFILES= \
modts \
modword \
order \
- phony-end \
posix \
qequals \
sunshcmd \
@@ -50,23 +52,36 @@ SUBFILES= \
ternary \
unexport \
unexport-env \
- varcmd
+ varcmd \
+ varmisc \
+ varshell
-all: ${SUBFILES}
+# these tests were broken by referting POSIX chanegs
+STRICT_POSIX_TESTS = \
+ escape \
+ impsrc \
+ phony-end \
+ posix1 \
+ suffixes
+# Override make flags for certain tests
flags.doterror=
flags.order=-j1
-# the tests are actually done with sub-makes.
-.PHONY: ${SUBFILES}
-.PRECIOUS: ${SUBFILES}
-${SUBFILES}:
- -@${.MAKE} ${flags.$@:U-k} -f ${UNIT_TESTS}/$@
+OUTFILES= ${TESTNAMES:S/$/.out/}
-clean:
- rm -f *.out *.fail *.core
+all: ${OUTFILES}
-.-include <obj.mk>
+CLEANFILES += *.rawout *.out *.status *.tmp *.core *.tmp
+CLEANFILES += obj*.[och] lib*.a # posix1.mk
+CLEANFILES += issue* .[ab]* # suffixes.mk
+CLEANRECURSIVE += dir dummy # posix1.mk
+
+clean:
+ rm -f ${CLEANFILES}
+.if !empty(CLEANRECURSIVE)
+ rm -rf ${CLEANRECURSIVE}
+.endif
TEST_MAKE?= ${.MAKE}
TOOL_SED?= sed
@@ -81,22 +96,56 @@ LANG= C
.export LANG LC_ALL
.endif
-# The driver.
+# some tests need extra post-processing
+SED_CMDS.varshell = -e 's,^[a-z]*sh: ,,' \
+ -e '/command/s,No such.*,not found,'
+
+# the tests are actually done with sub-makes.
+.SUFFIXES: .mk .rawout .out
+.mk.rawout:
+ @echo ${TEST_MAKE} ${flags.${.TARGET:R}:U-k} -f ${.IMPSRC}
+ -@cd ${.OBJDIR} && \
+ { ${TEST_MAKE} ${flags.${.TARGET:R}:U-k} -f ${.IMPSRC} \
+ 2>&1 ; echo $$? >${.TARGET:R}.status ; } > ${.TARGET}.tmp
+ @mv ${.TARGET}.tmp ${.TARGET}
+
# We always pretend .MAKE was called 'make'
# and strip ${.CURDIR}/ from the output
# and replace anything after 'stopped in' with unit-tests
# so the results can be compared.
-test:
- @echo "${TEST_MAKE} -f ${MAKEFILE} > ${.TARGET}.out 2>&1"
- @cd ${.OBJDIR} && ${TEST_MAKE} -f ${MAKEFILE} 2>&1 | \
- ${TOOL_TR} -d '\015' | \
- ${TOOL_SED} -e 's,^${TEST_MAKE:T:C/\./\\\./g}[^:]*:,make:,' \
- -e '/stopped/s, /.*, unit-tests,' \
- -e 's,${.CURDIR:C/\./\\\./g}/,,g' \
- -e 's,${UNIT_TESTS:C/\./\\\./g}/,,g' > ${.TARGET}.out || { \
- tail ${.TARGET}.out; mv ${.TARGET}.out ${.TARGET}.fail; exit 1; }
- ${TOOL_DIFF} ${DIFF_FLAGS} ${UNIT_TESTS}/${.TARGET}.exp ${.TARGET}.out
+.rawout.out:
+ @echo postprocess ${.TARGET}
+ @${TOOL_SED} -e 's,^${TEST_MAKE:T:C/\./\\\./g}[][0-9]*:,make:,' \
+ -e 's,${TEST_MAKE:C/\./\\\./g},make,' \
+ -e '/stopped/s, /.*, unit-tests,' \
+ -e 's,${.CURDIR:C/\./\\\./g}/,,g' \
+ -e 's,${UNIT_TESTS:C/\./\\\./g}/,,g' ${SED_CMDS.${.TARGET:T:R}} \
+ < ${.IMPSRC} > ${.TARGET}.tmp
+ @echo "exit status `cat ${.TARGET:R}.status`" >> ${.TARGET}.tmp
+ @mv ${.TARGET}.tmp ${.TARGET}
+
+# Compare all output files
+test: ${OUTFILES} .PHONY
+ @failed= ; \
+ for test in ${TESTNAMES}; do \
+ ${TOOL_DIFF} ${DIFF_FLAGS} ${UNIT_TESTS}/$${test}.exp $${test}.out \
+ || failed="$${failed}$${failed:+ }$${test}" ; \
+ done ; \
+ if [ -n "$${failed}" ]; then \
+ echo "Failed tests: $${failed}" ; false ; \
+ else \
+ echo "All tests passed" ; \
+ fi
accept:
- mv test.out ${srcdir}/test.exp
+ @for test in ${TESTNAMES}; do \
+ cmp -s ${UNIT_TESTS}/$${test}.exp $${test}.out \
+ || { echo "Replacing $${test}.exp" ; \
+ cp $${test}.out ${UNIT_TESTS}/$${test}.exp ; } \
+ done
+.if exists(${TEST_MAKE})
+${TESTNAMES:S/$/.rawout/}: ${TEST_MAKE}
+.endif
+
+.-include <obj.mk>
diff --git a/unit-tests/comment.exp b/unit-tests/comment.exp
new file mode 100644
index 0000000..9a97df0
--- /dev/null
+++ b/unit-tests/comment.exp
@@ -0,0 +1,5 @@
+comment testing start
+this is foo
+This is how a comment looks: # comment
+comment testing done
+exit status 0
diff --git a/unit-tests/comment b/unit-tests/comment.mk
index 7dd7dbb..7dd7dbb 100644
--- a/unit-tests/comment
+++ b/unit-tests/comment.mk
diff --git a/unit-tests/cond1.exp b/unit-tests/cond1.exp
new file mode 100644
index 0000000..701d504
--- /dev/null
+++ b/unit-tests/cond1.exp
@@ -0,0 +1,23 @@
+make: "cond1.mk" line 75: warning: extra else
+make: "cond1.mk" line 85: warning: extra else
+2 is prime
+A='other' B='unknown' C='clever' o='no,no'
+Passed:
+ var
+ ("var")
+ (var != var)
+ var != var
+ !((var != var) && defined(name))
+ var == quoted
+
+1 is not prime
+2 is prime
+3 is prime
+4 is not prime
+5 is prime
+
+make: warning: String comparison operator should be either == or !=
+make: Bad conditional expression `"0" > 0' in "0" > 0?OK:No
+
+OK
+exit status 0
diff --git a/unit-tests/cond1 b/unit-tests/cond1.mk
index c877c3d..2fc2c7c 100644
--- a/unit-tests/cond1
+++ b/unit-tests/cond1.mk
@@ -1,4 +1,4 @@
-# $Id: cond1,v 1.1.1.3 2011/03/06 00:04:58 sjg Exp $
+# $Id: cond1.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $
# hard code these!
TEST_UNAME_S= NetBSD
diff --git a/unit-tests/cond2.exp b/unit-tests/cond2.exp
new file mode 100644
index 0000000..22e76a5
--- /dev/null
+++ b/unit-tests/cond2.exp
@@ -0,0 +1,7 @@
+make: Bad conditional expression ` == "empty"' in == "empty"?oops:ok
+make: "cond2.mk" line 13: Malformed conditional ({TEST_TYPO} == "Ok")
+TEST_NOT_SET is empty or not defined
+make: "cond2.mk" line 20: Malformed conditional (${TEST_NOT_SET} == "empty")
+make: Fatal errors encountered -- cannot continue
+make: stopped in unit-tests
+exit status 1
diff --git a/unit-tests/cond2.mk b/unit-tests/cond2.mk
new file mode 100644
index 0000000..943df43
--- /dev/null
+++ b/unit-tests/cond2.mk
@@ -0,0 +1,29 @@
+# $Id: cond2.mk,v 1.1.1.2 2015/12/02 00:34:27 sjg Exp $
+
+TEST_UNAME_S= NetBSD
+
+# this should be ok
+X:= ${${TEST_UNAME_S} == "NetBSD":?Ok:fail}
+.if $X == "Ok"
+Y= good
+.endif
+# expect: Bad conditional expression ` == "empty"' in == "empty"?oops:ok
+X:= ${${TEST_NOT_SET} == "empty":?oops:ok}
+# expect: Malformed conditional ({TEST_TYPO} == "Ok")
+.if {TEST_TYPO} == "Ok"
+Y= oops
+.endif
+.if empty(TEST_NOT_SET)
+Y!= echo TEST_NOT_SET is empty or not defined >&2; echo
+.endif
+# expect: Malformed conditional (${TEST_NOT_SET} == "empty")
+.if ${TEST_NOT_SET} == "empty"
+Y= oops
+.endif
+
+.if defined(.NDEF) && ${.NDEF} > 0
+Z= yes
+.endif
+
+all:
+ @echo $@
diff --git a/unit-tests/doterror.exp b/unit-tests/doterror.exp
new file mode 100644
index 0000000..5655644
--- /dev/null
+++ b/unit-tests/doterror.exp
@@ -0,0 +1,9 @@
+At first, I am
+happy
+and now: sad
+*** Error code 1
+
+Stop.
+make: stopped in unit-tests
+.ERROR: Looks like 'sad' is upset.
+exit status 1
diff --git a/unit-tests/doterror b/unit-tests/doterror.mk
index 75d8920..9030dce 100644
--- a/unit-tests/doterror
+++ b/unit-tests/doterror.mk
@@ -1,4 +1,4 @@
-# $Id: doterror,v 1.1.1.1 2010/04/08 17:43:00 sjg Exp $
+# $Id: doterror.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $
.BEGIN:
diff --git a/unit-tests/dotwait.exp b/unit-tests/dotwait.exp
new file mode 100644
index 0000000..6bf96e3
--- /dev/null
+++ b/unit-tests/dotwait.exp
@@ -0,0 +1,30 @@
+simple.1
+simple.1
+simple.2
+simple.2
+recursive.1.1.*
+recursive.1.1.*
+recursive.1.1.*
+recursive.1.1.*
+recursive.1.99
+recursive.1.99
+recursive.2.1.*
+recursive.2.1.*
+recursive.2.1.*
+recursive.2.1.*
+recursive.2.99
+recursive.2.99
+shared.0
+shared.0
+shared.1.99
+shared.1.99
+shared.2.1
+shared.2.1
+shared.2.99
+shared.2.99
+make: Graph cycles through `cycle.2.99'
+make: Graph cycles through `cycle.2.98'
+make: Graph cycles through `cycle.2.97'
+cycle.1.99
+cycle.1.99
+exit status 0
diff --git a/unit-tests/dotwait b/unit-tests/dotwait.mk
index 43706af..9bdaaba 100644
--- a/unit-tests/dotwait
+++ b/unit-tests/dotwait.mk
@@ -1,4 +1,4 @@
-# $NetBSD: dotwait,v 1.1 2006/02/26 22:45:46 apb Exp $
+# $NetBSD: dotwait.mk,v 1.1 2014/08/21 13:44:51 apb Exp $
THISMAKEFILE:= ${.PARSEDIR}/${.PARSEFILE}
diff --git a/unit-tests/error.exp b/unit-tests/error.exp
new file mode 100644
index 0000000..a2bf71b
--- /dev/null
+++ b/unit-tests/error.exp
@@ -0,0 +1,4 @@
+make: "error.mk" line 3: just FYI
+make: "error.mk" line 4: warning: this could be serious
+make: "error.mk" line 5: this is fatal
+exit status 1
diff --git a/unit-tests/error b/unit-tests/error.mk
index c0a1403..c6b553e 100644
--- a/unit-tests/error
+++ b/unit-tests/error.mk
@@ -1,4 +1,4 @@
-# $Id: error,v 1.1.1.2 2010/05/24 23:36:03 sjg Exp $
+# $Id: error.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $
.info just FYI
.warning this could be serious
diff --git a/unit-tests/escape.exp b/unit-tests/escape.exp
new file mode 100644
index 0000000..6238e27
--- /dev/null
+++ b/unit-tests/escape.exp
@@ -0,0 +1,104 @@
+var-1bs
+printf "%s=:%s:\n" VAR1BS 111\\111; printf "%s=:%s:\n" VAR1BSa 111\\aaa; printf "%s=:%s:\n" VAR1BSA 111\\aaa; printf "%s=:%s:\n" VAR1BSda 111\\\$\{a\}; printf "%s=:%s:\n" VAR1BSdA 111\\\$\{A\}; printf "%s=:%s:\n" VAR1BSc 111\#\ backslash\ escapes\ comment\ char,\ so\ this\ is\ part\ of\ the\ value; printf "%s=:%s:\n" VAR1BSsc 111\\\ ;
+VAR1BS=:111\111:
+VAR1BSa=:111\aaa:
+VAR1BSA=:111\aaa:
+VAR1BSda=:111\${a}:
+VAR1BSdA=:111\${A}:
+VAR1BSc=:111# backslash escapes comment char, so this is part of the value:
+VAR1BSsc=:111\ :
+var-2bs
+printf "%s=:%s:\n" VAR2BS 222\\\\222; printf "%s=:%s:\n" VAR2BSa 222\\\\aaa; printf "%s=:%s:\n" VAR2BSA 222\\\\aaa; printf "%s=:%s:\n" VAR2BSda 222\\\\\$\{a\}; printf "%s=:%s:\n" VAR2BSdA 222\\\\\$\{A\}; printf "%s=:%s:\n" VAR2BSc 222\\\\; printf "%s=:%s:\n" VAR2BSsc 222\\\\;
+VAR2BS=:222\\222:
+VAR2BSa=:222\\aaa:
+VAR2BSA=:222\\aaa:
+VAR2BSda=:222\\${a}:
+VAR2BSdA=:222\\${A}:
+VAR2BSc=:222\\:
+VAR2BSsc=:222\\:
+var-1bsnl
+printf "%s=:%s:\n" VAR1BSNL 111\ 111; printf "%s=:%s:\n" VAR1BSNLa 111\ aaa; printf "%s=:%s:\n" VAR1BSNLA 111\ aaa; printf "%s=:%s:\n" VAR1BSNLda 111\ \$\{a\}; printf "%s=:%s:\n" VAR1BSNLdA 111\ \$\{A\}; printf "%s=:%s:\n" VAR1BSNLc 111; printf "%s=:%s:\n" VAR1BSNLsc 111;
+VAR1BSNL=:111 111:
+VAR1BSNLa=:111 aaa:
+VAR1BSNLA=:111 aaa:
+VAR1BSNLda=:111 ${a}:
+VAR1BSNLdA=:111 ${A}:
+VAR1BSNLc=:111:
+VAR1BSNLsc=:111:
+var-2bsnl
+printf "%s=:%s:\n" VAR2BSNL 222\\\\; printf "%s=:%s:\n" VAR2BSNLa 222\\\\; printf "%s=:%s:\n" VAR2BSNLA 222\\\\; printf "%s=:%s:\n" VAR2BSNLda 222\\\\; printf "%s=:%s:\n" VAR2BSNLdA 222\\\\; printf "%s=:%s:\n" VAR2BSNLc 222\\\\; printf "%s=:%s:\n" VAR2BSNLsc 222\\\\;
+VAR2BSNL=:222\\:
+VAR2BSNLa=:222\\:
+VAR2BSNLA=:222\\:
+VAR2BSNLda=:222\\:
+VAR2BSNLdA=:222\\:
+VAR2BSNLc=:222\\:
+VAR2BSNLsc=:222\\:
+var-3bsnl
+printf "%s=:%s:\n" VAR3BSNL 333\\\\\ 333=; printf "%s=:%s:\n" VAR3BSNLa 333\\\\\ aaa=; printf "%s=:%s:\n" VAR3BSNLA 333\\\\\ aaa=; printf "%s=:%s:\n" VAR3BSNLda 333\\\\\ \$\{a\}=; printf "%s=:%s:\n" VAR3BSNLdA 333\\\\\ \$\{A\}=; printf "%s=:%s:\n" VAR3BSNLc 333\\\\; printf "%s=:%s:\n" VAR3BSNLsc 333\\\\;
+VAR3BSNL=:333\\ 333=:
+VAR3BSNLa=:333\\ aaa=:
+VAR3BSNLA=:333\\ aaa=:
+VAR3BSNLda=:333\\ ${a}=:
+VAR3BSNLdA=:333\\ ${A}=:
+VAR3BSNLc=:333\\:
+VAR3BSNLsc=:333\\:
+var-1bsnl-space
+printf "%s=:%s:\n" VAR1BSNL00 first\ line; printf "%s=:%s:\n" VAR1BSNL0 first\ line\ no\ space\ on\ second\ line; printf "%s=:%s:\n" VAR1BSNLs first\ line\ one\ space\ on\ second\ line; printf "%s=:%s:\n" VAR1BSNLss first\ line\ two\ spaces\ on\ second\ line; printf "%s=:%s:\n" VAR1BSNLt first\ line\ one\ tab\ on\ second\ line; printf "%s=:%s:\n" VAR1BSNLtt first\ line\ two\ tabs\ on\ second\ line; printf "%s=:%s:\n" VAR1BSNLxx first\ line\ many\ spaces\ and\ tabs\ \[\ \ \ \ \]\ on\ second\ line;
+VAR1BSNL00=:first line:
+VAR1BSNL0=:first line no space on second line:
+VAR1BSNLs=:first line one space on second line:
+VAR1BSNLss=:first line two spaces on second line:
+VAR1BSNLt=:first line one tab on second line:
+VAR1BSNLtt=:first line two tabs on second line:
+VAR1BSNLxx=:first line many spaces and tabs [ ] on second line:
+cmd-1bsnl
+echo :'first line\
+#second line without space\
+third line':
+:first line\
+#second line without space\
+third line:
+echo :'first line\
+ second line spaces should be retained':
+:first line\
+ second line spaces should be retained:
+echo :'first line\
+second line tab should be elided':
+:first line\
+second line tab should be elided:
+echo :'first line\
+ only one tab should be elided, second tab remains'
+:first line\
+ only one tab should be elided, second tab remains
+cmd-1bsnl-eof
+echo :'command ending with backslash-newline'; \
+
+:command ending with backslash-newline
+cmd-2bsnl
+echo take one\\
+take one\
+echo take two\\
+take two\
+echo take three\\
+take three\
+cmd-3bsnl
+echo :'first line\\\
+#second line without space\\\
+third line':
+:first line\\\
+#second line without space\\\
+third line:
+echo :'first line\\\
+ second line spaces should be retained':
+:first line\\\
+ second line spaces should be retained:
+echo :'first line\\\
+second line tab should be elided':
+:first line\\\
+second line tab should be elided:
+echo :'first line\\\
+ only one tab should be elided, second tab remains'
+:first line\\\
+ only one tab should be elided, second tab remains
+exit status 0
diff --git a/unit-tests/escape.mk b/unit-tests/escape.mk
new file mode 100644
index 0000000..bb37c92
--- /dev/null
+++ b/unit-tests/escape.mk
@@ -0,0 +1,246 @@
+# $Id: escape.mk,v 1.1.1.2 2014/11/06 01:40:37 sjg Exp $
+#
+# Test backslash escaping.
+
+# Extracts from the POSIX 2008 specification
+# <http://pubs.opengroup.org/onlinepubs/9699919799/utilities/make.html>:
+#
+# Comments start with a <number-sign> ( '#' ) and continue until an
+# unescaped <newline> is reached.
+#
+# When an escaped <newline> (one preceded by a <backslash>) is found
+# anywhere in the makefile except in a command line, an include
+# line, or a line immediately preceding an include line, it shall
+# be replaced, along with any leading white space on the following
+# line, with a single <space>.
+#
+# When an escaped <newline> is found in a command line in a
+# makefile, the command line shall contain the <backslash>, the
+# <newline>, and the next line, except that the first character of
+# the next line shall not be included if it is a <tab>.
+#
+# When an escaped <newline> is found in an include line or in a
+# line immediately preceding an include line, the behavior is
+# unspecified.
+#
+# Notice that the behaviour of <backslash><backslash> or
+# <backslash><anything other than newline> is not mentioned. I think
+# this implies that <backslash> should be taken literally everywhere
+# except before <newline>.
+#
+# Our practice, despite what POSIX might say, is that "\#"
+# in a variable assignment stores "#" as part of the value.
+# The "\" is not taken literally, and the "#" does not begin a comment.
+#
+# Also, our practice is that an even number of backslashes before a
+# newline in a variable assignment simply stores the backslashes as part
+# of the value, and treats the newline as though it was not escaped.
+# Similarly, ann even number of backslashes before a newline in a
+# command simply uses the backslashes as part of the command test, but
+# does not escape the newline. This is compatible with GNU make.
+
+all: .PHONY
+# We will add dependencies like "all: yet-another-test" later.
+
+# Some variables to be expanded in tests
+#
+a = aaa
+A = ${a}
+
+# Backslash at end of line in a comment\
+should continue the comment. \
+# This is also tested in comment.mk.
+
+__printvars: .USE .MADE
+ @echo ${.TARGET}
+ ${.ALLSRC:@v@ printf "%s=:%s:\n" ${v:Q} ${${v}:Q}; @}
+
+# Embedded backslash in variable should be taken literally.
+#
+VAR1BS = 111\111
+VAR1BSa = 111\${a}
+VAR1BSA = 111\${A}
+VAR1BSda = 111\$${a}
+VAR1BSdA = 111\$${A}
+VAR1BSc = 111\# backslash escapes comment char, so this is part of the value
+VAR1BSsc = 111\ # This is a comment. Value ends with <backslash><space>
+
+all: var-1bs
+var-1bs: .PHONY __printvars VAR1BS VAR1BSa VAR1BSA VAR1BSda VAR1BSdA \
+ VAR1BSc VAR1BSsc
+
+# Double backslash in variable should be taken as two literal backslashes.
+#
+VAR2BS = 222\\222
+VAR2BSa = 222\\${a}
+VAR2BSA = 222\\${A}
+VAR2BSda = 222\\$${a}
+VAR2BSdA = 222\\$${A}
+VAR2BSc = 222\\# backslash does not escape comment char, so this is a comment
+VAR2BSsc = 222\\ # This is a comment. Value ends with <backslash><backslash>
+
+all: var-2bs
+var-2bs: .PHONY __printvars VAR2BS VAR2BSa VAR2BSA VAR2BSda VAR2BSdA \
+ VAR2BSc VAR2BSsc
+
+# Backslash-newline in a variable setting is replaced by a single space.
+#
+VAR1BSNL = 111\
+111
+VAR1BSNLa = 111\
+${a}
+VAR1BSNLA = 111\
+${A}
+VAR1BSNLda = 111\
+$${a}
+VAR1BSNLdA = 111\
+$${A}
+VAR1BSNLc = 111\
+# this should be processed as a comment
+VAR1BSNLsc = 111\
+ # this should be processed as a comment
+
+all: var-1bsnl
+var-1bsnl: .PHONY
+var-1bsnl: .PHONY __printvars \
+ VAR1BSNL VAR1BSNLa VAR1BSNLA VAR1BSNLda VAR1BSNLdA \
+ VAR1BSNLc VAR1BSNLsc
+
+# Double-backslash-newline in a variable setting.
+# Both backslashes should be taken literally, and the newline is NOT escaped.
+#
+# The second lines below each end with '=' so that they will not
+# generate syntax errors regardless of whether or not they are
+# treated as part of the value.
+#
+VAR2BSNL = 222\\
+222=
+VAR2BSNLa = 222\\
+${a}=
+VAR2BSNLA = 222\\
+${A}=
+VAR2BSNLda = 222\\
+$${a}=
+VAR2BSNLdA = 222\\
+$${A}=
+VAR2BSNLc = 222\\
+# this should be processed as a comment
+VAR2BSNLsc = 222\\
+ # this should be processed as a comment
+
+all: var-2bsnl
+var-2bsnl: .PHONY __printvars \
+ VAR2BSNL VAR2BSNLa VAR2BSNLA VAR2BSNLda VAR2BSNLdA \
+ VAR2BSNLc VAR2BSNLsc
+
+# Triple-backslash-newline in a variable setting.
+# First two should be taken literally, and last should escape the newline.
+#
+# The second lines below each end with '=' so that they will not
+# generate syntax errors regardless of whether or not they are
+# treated as part of the value.
+#
+VAR3BSNL = 333\\\
+333=
+VAR3BSNLa = 333\\\
+${a}=
+VAR3BSNLA = 333\\\
+${A}=
+VAR3BSNLda = 333\\\
+$${a}=
+VAR3BSNLdA = 333\\\
+$${A}=
+VAR3BSNLc = 333\\\
+# this should be processed as a comment
+VAR3BSNLsc = 333\\\
+ # this should be processed as a comment
+
+all: var-3bsnl
+var-3bsnl: .PHONY __printvars \
+ VAR3BSNL VAR3BSNLa VAR3BSNLA VAR3BSNLda VAR3BSNLdA \
+ VAR3BSNLc VAR3BSNLsc
+
+# Backslash-newline in a variable setting, plus any amount of white space
+# on the next line, is replaced by a single space.
+#
+VAR1BSNL00= first line\
+
+# above line is entirely empty, and this is a comment
+VAR1BSNL0= first line\
+no space on second line
+VAR1BSNLs= first line\
+ one space on second line
+VAR1BSNLss= first line\
+ two spaces on second line
+VAR1BSNLt= first line\
+ one tab on second line
+VAR1BSNLtt= first line\
+ two tabs on second line
+VAR1BSNLxx= first line\
+ many spaces and tabs [ ] on second line
+
+all: var-1bsnl-space
+var-1bsnl-space: .PHONY __printvars \
+ VAR1BSNL00 VAR1BSNL0 VAR1BSNLs VAR1BSNLss VAR1BSNLt VAR1BSNLtt \
+ VAR1BSNLxx
+
+# Backslash-newline in a command is retained.
+#
+# The "#" in "# second line without space" makes it a comment instead
+# of a syntax error if the preceding line is parsed incorretly.
+# The ":" in "third line':" makes it look like the start of a
+# target instead of a syntax error if the first line is parsed incorrectly.
+#
+all: cmd-1bsnl
+cmd-1bsnl: .PHONY
+ @echo ${.TARGET}
+ echo :'first line\
+#second line without space\
+third line':
+ echo :'first line\
+ second line spaces should be retained':
+ echo :'first line\
+ second line tab should be elided':
+ echo :'first line\
+ only one tab should be elided, second tab remains'
+
+# When backslash-newline appears at the end of a command script,
+# both the backslash and the newline should be passed to the shell.
+# The shell should elide the backslash-newline.
+#
+all: cmd-1bsnl-eof
+cmd-1bsnl-eof:
+ @echo ${.TARGET}
+ echo :'command ending with backslash-newline'; \
+
+# above line must be blank
+
+# Double-backslash-newline in a command.
+# Both backslashes are retained, but the newline is not escaped.
+# XXX: This may differ from POSIX, but matches gmake.
+#
+# When make passes two backslashes to the shell, the shell will pass one
+# backslash to the echo commant.
+#
+all: cmd-2bsnl
+cmd-2bsnl: .PHONY
+ @echo ${.TARGET}
+ echo take one\\
+# this should be a comment
+ echo take two\\
+ echo take three\\
+
+# Triple-backslash-newline in a command is retained.
+#
+all: cmd-3bsnl
+cmd-3bsnl: .PHONY
+ @echo ${.TARGET}
+ echo :'first line\\\
+#second line without space\\\
+third line':
+ echo :'first line\\\
+ second line spaces should be retained':
+ echo :'first line\\\
+ second line tab should be elided':
+ echo :'first line\\\
+ only one tab should be elided, second tab remains'
diff --git a/unit-tests/export-all.exp b/unit-tests/export-all.exp
new file mode 100644
index 0000000..e3aefd4
--- /dev/null
+++ b/unit-tests/export-all.exp
@@ -0,0 +1,12 @@
+UT_ALL=even this gets exported
+UT_BADDIR=unit-tests
+UT_DOLLAR=This is $UT_FU
+UT_F=fine
+UT_FOO=foobar is fubar
+UT_FU=fubar
+UT_NO=all
+UT_OK=good
+UT_OKDIR=unit-tests
+UT_TEST=export-all
+UT_ZOO=hoopie
+exit status 0
diff --git a/unit-tests/export-all b/unit-tests/export-all.mk
index a243fe3..200412f 100644
--- a/unit-tests/export-all
+++ b/unit-tests/export-all.mk
@@ -1,4 +1,4 @@
-# $Id: export-all,v 1.1.1.2 2010/04/21 04:26:14 sjg Exp $
+# $Id: export-all.mk,v 1.1.1.2 2015/04/10 20:43:38 sjg Exp $
UT_OK=good
UT_F=fine
@@ -17,7 +17,7 @@ UT_OKDIR = ${${here}/../${here:T}:L:${M_tA}:T}
.export
-.include "export"
+.include "export.mk"
UT_TEST=export-all
UT_ALL=even this gets exported
diff --git a/unit-tests/export-env.exp b/unit-tests/export-env.exp
new file mode 100644
index 0000000..8a779e6
--- /dev/null
+++ b/unit-tests/export-env.exp
@@ -0,0 +1,11 @@
+make:
+UT_TEST=export-env.mk
+UT_ENV=not-exported
+UT_EXP=not-exported
+UT_LIT=literal export-env.mk
+env:
+UT_TEST=export-env.mk
+UT_ENV=exported
+UT_EXP=exported
+UT_LIT=literal ${UT_TEST}
+exit status 0
diff --git a/unit-tests/export-env b/unit-tests/export-env.mk
index b6ce6a2..93aa672 100644
--- a/unit-tests/export-env
+++ b/unit-tests/export-env.mk
@@ -1,4 +1,4 @@
-# $Id: export-env,v 1.1.1.1 2013/03/23 02:26:59 sjg Exp $
+# $Id: export-env.mk,v 1.1.1.2 2016/02/18 20:35:24 sjg Exp $
# our normal .export, subsequent changes affect the environment
UT_TEST=this
@@ -15,9 +15,12 @@ UT_EXP=before-export
export UT_EXP=exported
UT_EXP=not-exported
+UT_LIT= literal ${UT_TEST}
+.export-literal UT_LIT
+
all:
- @echo make:; ${UT_TEST UT_ENV UT_EXP:L:@v@echo $v=${$v};@}
- @echo env:; ${UT_TEST UT_ENV UT_EXP:L:@v@echo $v=$${$v};@}
+ @echo make:; ${UT_TEST UT_ENV UT_EXP UT_LIT:L:@v@echo $v=${$v};@}
+ @echo env:; ${UT_TEST UT_ENV UT_EXP UT_LIT:L:@v@echo $v=$${$v};@}
diff --git a/unit-tests/export.exp b/unit-tests/export.exp
new file mode 100644
index 0000000..143771c
--- /dev/null
+++ b/unit-tests/export.exp
@@ -0,0 +1,6 @@
+UT_DOLLAR=This is $UT_FU
+UT_FOO=foobar is fubar
+UT_FU=fubar
+UT_TEST=export
+UT_ZOO=hoopie
+exit status 0
diff --git a/unit-tests/export b/unit-tests/export.mk
index 3e2ad95..01f69f9 100644
--- a/unit-tests/export
+++ b/unit-tests/export.mk
@@ -1,4 +1,4 @@
-# $Id: export,v 1.1.1.1 2007/10/08 20:30:12 sjg Exp $
+# $Id: export.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $
UT_TEST=export
UT_FOO=foo${BAR}
diff --git a/unit-tests/forloop.exp b/unit-tests/forloop.exp
new file mode 100644
index 0000000..df14b75
--- /dev/null
+++ b/unit-tests/forloop.exp
@@ -0,0 +1,19 @@
+x=one
+x="two and three"
+x=four
+x="five"
+x=-I/this
+x=-I"This or that"
+x=-Ithat
+x="-DTHIS=\"this and that\""
+cfl=-I/this -I"This or that" -Ithat "-DTHIS=\"this and that\""
+a=one b="two and three"
+a=four b="five"
+a=ONE b="TWO AND THREE"
+a=FOUR b="FIVE"
+We expect an error next:
+make: "forloop.mk" line 38: Wrong number of words (9) in .for substitution list with 2 vars
+make: Fatal errors encountered -- cannot continue
+make: stopped in unit-tests
+OK
+exit status 0
diff --git a/unit-tests/forloop b/unit-tests/forloop.mk
index 0b50e66..9aad7c6 100644
--- a/unit-tests/forloop
+++ b/unit-tests/forloop.mk
@@ -1,4 +1,4 @@
-# $Id: forloop,v 1.1.1.1 2012/06/19 23:30:49 sjg Exp $
+# $Id: forloop.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $
all: for-loop
diff --git a/unit-tests/forsubst.exp b/unit-tests/forsubst.exp
new file mode 100644
index 0000000..0a98c00
--- /dev/null
+++ b/unit-tests/forsubst.exp
@@ -0,0 +1,2 @@
+.for with :S;... OK
+exit status 0
diff --git a/unit-tests/forsubst b/unit-tests/forsubst.mk
index d3a7de1..2923e4b 100644
--- a/unit-tests/forsubst
+++ b/unit-tests/forsubst.mk
@@ -1,4 +1,4 @@
-# $Id: forsubst,v 1.1.1.1 2009/10/07 18:53:35 sjg Exp $
+# $Id: forsubst.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $
all: for-subst
diff --git a/unit-tests/hash.exp b/unit-tests/hash.exp
new file mode 100644
index 0000000..0a24234
--- /dev/null
+++ b/unit-tests/hash.exp
@@ -0,0 +1,9 @@
+b2af338b
+3360ac65
+7747f046
+9ca87054
+880fe816
+208fcbd3
+d5d376eb
+de41416c
+exit status 0
diff --git a/unit-tests/hash b/unit-tests/hash.mk
index 1ed84e7..1ed84e7 100644
--- a/unit-tests/hash
+++ b/unit-tests/hash.mk
diff --git a/unit-tests/impsrc.exp b/unit-tests/impsrc.exp
new file mode 100644
index 0000000..23e8347
--- /dev/null
+++ b/unit-tests/impsrc.exp
@@ -0,0 +1,13 @@
+expected: source4
+actual: source4
+expected: target1.x
+actual: target1.x
+expected: target1.y
+actual: target1.y
+expected: source1
+actual: source1
+expected: source2
+actual: source2
+expected: source1
+actual: source1
+exit status 0
diff --git a/unit-tests/impsrc.mk b/unit-tests/impsrc.mk
new file mode 100644
index 0000000..95ae0c3
--- /dev/null
+++ b/unit-tests/impsrc.mk
@@ -0,0 +1,43 @@
+# $NetBSD: impsrc.mk,v 1.2 2014/08/30 22:21:07 sjg Exp $
+
+# Does ${.IMPSRC} work properly?
+# It should be set, in order of precedence, to ${.TARGET} of:
+# 1) the implied source of a transformation rule,
+# 2) the first prerequisite from the dependency line of an explicit rule, or
+# 3) the first prerequisite of an explicit rule.
+#
+
+all: target1.z target2 target3 target4
+
+.SUFFIXES: .x .y .z
+
+.x.y: source1
+ @echo 'expected: target1.x'
+ @echo 'actual: $<'
+
+.y.z: source2
+ @echo 'expected: target1.y'
+ @echo 'actual: $<'
+
+target1.y: source3
+
+target1.x: source4
+ @echo 'expected: source4'
+ @echo 'actual: $<'
+
+target2: source1 source2
+ @echo 'expected: source1'
+ @echo 'actual: $<'
+
+target3: source1
+target3: source2 source3
+ @echo 'expected: source2'
+ @echo 'actual: $<'
+
+target4: source1
+target4:
+ @echo 'expected: source1'
+ @echo 'actual: $<'
+
+source1 source2 source3 source4:
+
diff --git a/unit-tests/misc.exp b/unit-tests/misc.exp
new file mode 100644
index 0000000..39a9383
--- /dev/null
+++ b/unit-tests/misc.exp
@@ -0,0 +1 @@
+exit status 0
diff --git a/unit-tests/misc b/unit-tests/misc.mk
index 4ba3655..0301150 100644
--- a/unit-tests/misc
+++ b/unit-tests/misc.mk
@@ -1,4 +1,4 @@
-# $Id: misc,v 1.1.1.1 2011/03/06 00:04:58 sjg Exp $
+# $Id: misc.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $
.if !exists(${.CURDIR}/)
.warning ${.CURDIR}/ doesn't exist ?
diff --git a/unit-tests/moderrs.exp b/unit-tests/moderrs.exp
new file mode 100644
index 0000000..cb51aa0
--- /dev/null
+++ b/unit-tests/moderrs.exp
@@ -0,0 +1,16 @@
+Expect: Unknown modifier 'Z'
+make: Unknown modifier 'Z'
+VAR:Z=
+Expect: Unknown modifier 'Z'
+make: Unknown modifier 'Z'
+VAR:Z=
+Expect: Unclosed variable specification for VAR
+make: Unclosed variable specification (expecting '}') for "VAR" (value "Thevariable") modifier S
+VAR:S,V,v,=Thevariable
+Expect: Unclosed variable specification for VAR
+make: Unclosed variable specification after complex modifier (expecting '}') for VAR
+VAR:S,V,v,=Thevariable
+Expect: Unclosed substitution for VAR (, missing)
+make: Unclosed substitution for VAR (, missing)
+VAR:S,V,v=
+exit status 0
diff --git a/unit-tests/moderrs b/unit-tests/moderrs.mk
index b8f78ce..d0eb17f 100644
--- a/unit-tests/moderrs
+++ b/unit-tests/moderrs.mk
@@ -1,4 +1,4 @@
-# $Id: moderrs,v 1.2 2006/05/11 18:53:39 sjg Exp $
+# $Id: moderrs.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $
#
# various modifier error tests
diff --git a/unit-tests/modmatch.exp b/unit-tests/modmatch.exp
new file mode 100644
index 0000000..fcaf6c0
--- /dev/null
+++ b/unit-tests/modmatch.exp
@@ -0,0 +1,17 @@
+LIB=a X_LIBS:M${LIB${LIB:tu}} is "/tmp/liba.a"
+LIB=a X_LIBS:M*/lib${LIB}.a is "/tmp/liba.a"
+LIB=a X_LIBS:M*/lib${LIB}.a:tu is "/TMP/LIBA.A"
+LIB=b X_LIBS:M${LIB${LIB:tu}} is ""
+LIB=b X_LIBS:M*/lib${LIB}.a is ""
+LIB=b X_LIBS:M*/lib${LIB}.a:tu is ""
+LIB=c X_LIBS:M${LIB${LIB:tu}} is ""
+LIB=c X_LIBS:M*/lib${LIB}.a is ""
+LIB=c X_LIBS:M*/lib${LIB}.a:tu is ""
+LIB=d X_LIBS:M${LIB${LIB:tu}} is "/tmp/libd.a"
+LIB=d X_LIBS:M*/lib${LIB}.a is "/tmp/libd.a"
+LIB=d X_LIBS:M*/lib${LIB}.a:tu is "/TMP/LIBD.A"
+LIB=e X_LIBS:M${LIB${LIB:tu}} is "/tmp/libe.a"
+LIB=e X_LIBS:M*/lib${LIB}.a is "/tmp/libe.a"
+LIB=e X_LIBS:M*/lib${LIB}.a:tu is "/TMP/LIBE.A"
+Mscanner=OK
+exit status 0
diff --git a/unit-tests/modmatch b/unit-tests/modmatch.mk
index 48a1bef..48a1bef 100644
--- a/unit-tests/modmatch
+++ b/unit-tests/modmatch.mk
diff --git a/unit-tests/modmisc.exp b/unit-tests/modmisc.exp
new file mode 100644
index 0000000..e406647
--- /dev/null
+++ b/unit-tests/modmisc.exp
@@ -0,0 +1,10 @@
+path=':/bin:/tmp::/:.:/no/such/dir:.'
+path='/bin:/tmp:/:/no/such/dir'
+path='/bin:/tmp:/:/no/such/dir'
+path='/bin':'/tmp':'/':'/no/such/dir'
+path='/bin':'/tmp':'/':'/no/such/dir'
+path_/usr/xbin=/opt/xbin/
+paths=/bin /tmp / /no/such/dir /opt/xbin
+PATHS=/BIN /TMP / /NO/SUCH/DIR /OPT/XBIN
+The answer is 42
+exit status 0
diff --git a/unit-tests/modmisc b/unit-tests/modmisc.mk
index d562e46..043498f 100644
--- a/unit-tests/modmisc
+++ b/unit-tests/modmisc.mk
@@ -1,4 +1,4 @@
-# $Id: modmisc,v 1.1.1.5 2011/04/11 15:10:32 sjg Exp $
+# $Id: modmisc.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $
#
# miscellaneous modifier tests
diff --git a/unit-tests/modorder.exp b/unit-tests/modorder.exp
new file mode 100644
index 0000000..4117427
--- /dev/null
+++ b/unit-tests/modorder.exp
@@ -0,0 +1,11 @@
+LIST = one two three four five six seven eight nine ten
+LIST:O = eight five four nine one seven six ten three two
+LIST:Ox = Ok
+LIST:O:Ox = Ok
+LISTX = Ok
+LISTSX = Ok
+make: Bad modifier `:OX' for LIST
+BADMOD 1 = }
+make: Bad modifier `:OxXX' for LIST
+BADMOD 2 = XX}
+exit status 0
diff --git a/unit-tests/modorder b/unit-tests/modorder.mk
index 68b66fb..bc24d33 100644
--- a/unit-tests/modorder
+++ b/unit-tests/modorder.mk
@@ -1,4 +1,4 @@
-# $NetBSD: modorder,v 1.2 2007/10/05 15:27:46 sjg Exp $
+# $NetBSD: modorder.mk,v 1.1 2014/08/21 13:44:51 apb Exp $
LIST= one two three four five six seven eight nine ten
LISTX= ${LIST:Ox}
diff --git a/unit-tests/modts.exp b/unit-tests/modts.exp
new file mode 100644
index 0000000..cf3c91d
--- /dev/null
+++ b/unit-tests/modts.exp
@@ -0,0 +1,33 @@
+LIST="one two three four five six"
+LIST:ts,="one,two,three,four,five,six"
+LIST:ts/:tu="ONE/TWO/THREE/FOUR/FIVE/SIX"
+LIST:ts::tu="ONE:TWO:THREE:FOUR:FIVE:SIX"
+LIST:ts:tu="ONETWOTHREEFOURFIVESIX"
+LIST:tu:ts/="ONE/TWO/THREE/FOUR/FIVE/SIX"
+LIST:ts:="one:two:three:four:five:six"
+LIST:ts="onetwothreefourfivesix"
+LIST:ts:S/two/2/="one2threefourfivesix"
+LIST:S/two/2/:ts="one2threefourfivesix"
+LIST:ts/:S/two/2/="one/2/three/four/five/six"
+Pretend the '/' in '/n' etc. below are back-slashes.
+LIST:ts/n="one
+two
+three
+four
+five
+six"
+LIST:ts/t="one two three four five six"
+LIST:ts/012:tu="ONE
+TWO
+THREE
+FOUR
+FIVE
+SIX"
+make: Bad modifier `:tx' for LIST
+LIST:tx="}"
+make: Bad modifier `:ts\x' for LIST
+LIST:ts/x:tu="\x:tu}"
+FU_mod-ts="a/b/cool"
+FU_mod-ts:ts:T="cool" == cool?
+B.${AAA:ts}="Baaa" == Baaa?
+exit status 0
diff --git a/unit-tests/modts b/unit-tests/modts.mk
index 616bd89..54b3d3d 100644
--- a/unit-tests/modts
+++ b/unit-tests/modts.mk
@@ -12,9 +12,9 @@ all: mod-ts
# Use print or printf iff they are builtin.
# XXX note that this causes problems, when make decides
# there is no need to use a shell, so avoid where possible.
-.if ${type print 2> /dev/null || echo:L:sh:Mbuiltin} != ""
+.if ${(type print) 2> /dev/null || echo:L:sh:Mbuiltin} != ""
PRINT= print -r --
-.elif ${type printf 2> /dev/null || echo:L:sh:Mbuiltin} != ""
+.elif ${(type printf) 2> /dev/null || echo:L:sh:Mbuiltin} != ""
PRINT= printf '%s\n'
.else
PRINT= echo
diff --git a/unit-tests/modword.exp b/unit-tests/modword.exp
new file mode 100644
index 0000000..258d7ea
--- /dev/null
+++ b/unit-tests/modword.exp
@@ -0,0 +1,122 @@
+make: Bad modifier `:[]' for LIST
+LIST:[]="" is an error
+LIST:[0]="one two three four five six"
+LIST:[0x0]="one two three four five six"
+LIST:[000]="one two three four five six"
+LIST:[*]="one two three four five six"
+LIST:[@]="one two three four five six"
+LIST:[0]:C/ /,/="one,two three four five six"
+LIST:[0]:C/ /,/g="one,two,three,four,five,six"
+LIST:[0]:C/ /,/1g="one,two,three,four,five,six"
+LIST:[*]:C/ /,/="one,two three four five six"
+LIST:[*]:C/ /,/g="one,two,three,four,five,six"
+LIST:[*]:C/ /,/1g="one,two,three,four,five,six"
+LIST:[@]:C/ /,/="one two three four five six"
+LIST:[@]:C/ /,/g="one two three four five six"
+LIST:[@]:C/ /,/1g="one two three four five six"
+LIST:[@]:[0]:C/ /,/="one,two three four five six"
+LIST:[0]:[@]:C/ /,/="one two three four five six"
+LIST:[@]:[*]:C/ /,/="one,two three four five six"
+LIST:[*]:[@]:C/ /,/="one two three four five six"
+EMPTY=""
+EMPTY:[#]="1" == 1 ?
+ESCAPEDSPACE="\ "
+ESCAPEDSPACE:[#]="1" == 1 ?
+REALLYSPACE=" "
+REALLYSPACE:[#]="1" == 1 ?
+LIST:[#]="6"
+LIST:[0]:[#]="1" == 1 ?
+LIST:[*]:[#]="1" == 1 ?
+LIST:[@]:[#]="6"
+LIST:[1]:[#]="1"
+LIST:[1..3]:[#]="3"
+EMPTY:[1]=""
+ESCAPEDSPACE="\ "
+ESCAPEDSPACE:[1]="\ "
+REALLYSPACE=" "
+REALLYSPACE:[1]="" == "" ?
+REALLYSPACE:[*]:[1]=" " == " " ?
+LIST:[1]="one"
+make: Bad modifier `:[1.]' for LIST
+LIST:[1.]="" is an error
+make: Bad modifier `:[1].' for LIST
+LIST:[1].="}" is an error
+LIST:[2]="two"
+LIST:[6]="six"
+LIST:[7]=""
+LIST:[999]=""
+make: Bad modifier `:[-]' for LIST
+LIST:[-]="" is an error
+make: Bad modifier `:[--]' for LIST
+LIST:[--]="" is an error
+LIST:[-1]="six"
+LIST:[-2]="five"
+LIST:[-6]="one"
+LIST:[-7]=""
+LIST:[-999]=""
+LONGLIST:[17]="17"
+LONGLIST:[0x11]="17"
+LONGLIST:[021]="17"
+LIST:[0]:[1]="one two three four five six"
+LIST:[*]:[1]="one two three four five six"
+LIST:[@]:[1]="one"
+LIST:[0]:[2]=""
+LIST:[*]:[2]=""
+LIST:[@]:[2]="two"
+LIST:[*]:C/ /,/:[2]=""
+LIST:[*]:C/ /,/:[*]:[2]=""
+LIST:[*]:C/ /,/:[@]:[2]="three"
+make: Bad modifier `:[1.]' for LIST
+LIST:[1.]="" is an error
+make: Bad modifier `:[1..]' for LIST
+LIST:[1..]="" is an error
+LIST:[1..1]="one"
+make: Bad modifier `:[1..1.]' for LIST
+LIST:[1..1.]="" is an error
+LIST:[1..2]="one two"
+LIST:[2..1]="two one"
+LIST:[3..-2]="three four five"
+LIST:[-4..4]="three four"
+make: Bad modifier `:[0..1]' for LIST
+LIST:[0..1]="" is an error
+make: Bad modifier `:[-1..0]' for LIST
+LIST:[-1..0]="" is an error
+LIST:[-1..1]="six five four three two one"
+LIST:[0..0]="one two three four five six"
+LIST:[3..99]="three four five six"
+LIST:[-3..-99]="four three two one"
+LIST:[-99..-3]="one two three four"
+HASH="#" == "#" ?
+LIST:[${HASH}]="6"
+LIST:[${ZERO}]="one two three four five six"
+LIST:[${ZERO}x${ONE}]="one"
+LIST:[${ONE}]="one"
+LIST:[${MINUSONE}]="six"
+LIST:[${STAR}]="one two three four five six"
+LIST:[${AT}]="one two three four five six"
+make: Bad modifier `:[${EMPTY' for LIST
+LIST:[${EMPTY}]="" is an error
+LIST:[${LONGLIST:[21]:S/2//}]="one"
+LIST:[${LIST:[#]}]="six"
+LIST:[${LIST:[${HASH}]}]="six"
+LIST:S/ /,/="one two three four five six"
+LIST:S/ /,/W="one,two three four five six"
+LIST:S/ /,/gW="one,two,three,four,five,six"
+EMPTY:S/^/,/=","
+EMPTY:S/^/,/W=","
+LIST:C/ /,/="one two three four five six"
+LIST:C/ /,/W="one,two three four five six"
+LIST:C/ /,/gW="one,two,three,four,five,six"
+EMPTY:C/^/,/=","
+EMPTY:C/^/,/W=","
+LIST:tW="one two three four five six"
+LIST:tw="one two three four five six"
+LIST:tW:C/ /,/="one,two three four five six"
+LIST:tW:C/ /,/g="one,two,three,four,five,six"
+LIST:tW:C/ /,/1g="one,two,three,four,five,six"
+LIST:tw:C/ /,/="one two three four five six"
+LIST:tw:C/ /,/g="one two three four five six"
+LIST:tw:C/ /,/1g="one two three four five six"
+LIST:tw:tW:C/ /,/="one,two three four five six"
+LIST:tW:tw:C/ /,/="one two three four five six"
+exit status 0
diff --git a/unit-tests/modword b/unit-tests/modword.mk
index 39355d7..1327624 100644
--- a/unit-tests/modword
+++ b/unit-tests/modword.mk
@@ -1,4 +1,4 @@
-# $Id: modword,v 1.1.1.1 2003/09/28 17:01:48 sjg Exp $
+# $Id: modword.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $
#
# Test behaviour of new :[] modifier
diff --git a/unit-tests/order.exp b/unit-tests/order.exp
new file mode 100644
index 0000000..d876914
--- /dev/null
+++ b/unit-tests/order.exp
@@ -0,0 +1,4 @@
+Making the.c
+Making the.h
+Making the.o from the.h the.c
+exit status 0
diff --git a/unit-tests/order b/unit-tests/order.mk
index 175da47..f90b627 100644
--- a/unit-tests/order
+++ b/unit-tests/order.mk
@@ -1,4 +1,4 @@
-# $NetBSD: order,v 1.1 2012/11/09 19:08:28 sjg Exp $
+# $NetBSD: order.mk,v 1.1 2014/08/21 13:44:51 apb Exp $
# Test that .ORDER is handled correctly.
# The explicit dependency the.o: the.h will make us examine the.h
diff --git a/unit-tests/phony-end.exp b/unit-tests/phony-end.exp
new file mode 100644
index 0000000..c3c517c
--- /dev/null
+++ b/unit-tests/phony-end.exp
@@ -0,0 +1,6 @@
+.TARGET="phony" .PREFIX="phony" .IMPSRC=""
+.TARGET="all" .PREFIX="all" .IMPSRC="phony"
+.TARGET="ok" .PREFIX="ok" .IMPSRC=""
+.TARGET="also.ok" .PREFIX="also.ok" .IMPSRC=""
+.TARGET="bug" .PREFIX="bug" .IMPSRC=""
+exit status 0
diff --git a/unit-tests/phony-end b/unit-tests/phony-end.mk
index d61884c..07f4b02 100644
--- a/unit-tests/phony-end
+++ b/unit-tests/phony-end.mk
@@ -1,4 +1,4 @@
-# $Id: phony-end,v 1.1.1.1 2011/10/01 17:19:39 sjg Exp $
+# $Id: phony-end.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $
all ok also.ok bug phony:
@echo '${.TARGET .PREFIX .IMPSRC:L:@v@$v="${$v}"@}'
diff --git a/unit-tests/posix.exp b/unit-tests/posix.exp
new file mode 100644
index 0000000..7e74cab
--- /dev/null
+++ b/unit-tests/posix.exp
@@ -0,0 +1,23 @@
+Posix says we should execute the command as if run by system(3)
+Expect 'Hello,' and 'World!'
+Hello,
+World!
+a command
+a command prefixed by '+' executes even with -n
+another command
+make -n
+echo a command
+echo "a command prefixed by '+' executes even with -n"
+a command prefixed by '+' executes even with -n
+echo another command
+make -n -j1
+{ echo a command
+} || exit $?
+echo "a command prefixed by '+' executes even with -n"
+a command prefixed by '+' executes even with -n
+{ echo another command
+} || exit $?
+Now we expect an error...
+*** Error code 1 (continuing)
+`all' not remade because of errors.
+exit status 0
diff --git a/unit-tests/posix b/unit-tests/posix.mk
index 48ed7a3..608a24a 100644
--- a/unit-tests/posix
+++ b/unit-tests/posix.mk
@@ -1,4 +1,4 @@
-# $Id: posix,v 1.1.1.1 2004/05/08 16:45:39 sjg Exp $
+# $Id: posix.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $
all: x plus subs err
diff --git a/unit-tests/posix1.exp b/unit-tests/posix1.exp
new file mode 100644
index 0000000..92809e6
--- /dev/null
+++ b/unit-tests/posix1.exp
@@ -0,0 +1,185 @@
+${VAR} = "foo bar baz"
+a
+b
+c
+foo baR baz, bar baz, foo bar baz, fooadd baradd bazadd
+mkdir -p 'dir'
+touch 'dir/obj_1.h'
+mkdir -p 'dir'
+printf '#include "obj_1.h"\nconst char* obj_1 = "dir/obj_1.c";\n' \
+ >'dir/obj_1.c'
+Local variables
+ ${@}="dir/obj_1.o" ${<}="dir/obj_1.c"
+ ${*}="dir/obj_1" ${?}="dir/obj_1.h dir/obj_1.c"
+ ${%}=""
+
+Directory and filename parts of local variables
+ ${@D}="dir" ${@F}="obj_1.o"
+ ${<D}="dir" ${<F}="obj_1.c"
+ ${*D}="dir" ${*F}="obj_1"
+ ${?D}="dir dir" ${?F}="obj_1.h obj_1.c"
+ ${%D}="" ${%F}=""
+
+Local variable substitutions
+ ${@:.o=}="dir/obj_1" ${<:.c=.C}="dir/obj_1.C"
+ ${*:=.h}="dir/obj_1.h" ${?:.h=.H}="dir/obj_1.H dir/obj_1.c"
+ ${%:=}=""
+
+Target with suffix transformations
+ ${@D:=append}="dirappend"
+ ${@F:.o=.O}="obj_1.O"
+
+ Implied source with suffix transformations
+ ${<D:r=rr}="dirr"
+ ${<F:.c=.C}="obj_1.C"
+
+ Suffixless target with suffix transformations
+ ${*D:.=dot}="dir"
+ ${*F:.a=}="obj_1"
+
+ Out-of-date dependencies with suffix transformations
+ ${?D:ir=}="d d"
+ ${?F:.h=.H}="obj_1.H obj_1.c"
+
+ Member with suffix transformations
+ ${%D:.=}=""
+ ${%F:${VAR2}=${VAR}}=""
+
+cc -c -o 'dir/obj_1.o' 'dir/obj_1.c'
+mkdir -p '.'
+touch 'dummy'
+Local variables
+ ${@}="lib.a" ${<}="dir/obj_1.o"
+ ${*}="obj1" ${?}="dir/obj_1.o dummy"
+ ${%}="obj1.o"
+
+Directory and filename parts of local variables
+ ${@D}="." ${@F}="lib.a"
+ ${<D}="dir" ${<F}="obj_1.o"
+ ${*D}="." ${*F}="obj1"
+ ${?D}="dir ." ${?F}="obj_1.o dummy"
+ ${%D}="." ${%F}="obj1.o"
+
+Local variable substitutions
+ ${@:.o=}="lib.a" ${<:.c=.C}="dir/obj_1.o"
+ ${*:=.h}="obj1.h" ${?:.h=.H}="dir/obj_1.o dummy"
+ ${%:=}="obj1.o"
+
+Target with suffix transformations
+ ${@D:=append}=".append"
+ ${@F:.o=.O}="lib.a"
+
+ Implied source with suffix transformations
+ ${<D:r=rr}="dirr"
+ ${<F:.c=.C}="obj_1.o"
+
+ Suffixless target with suffix transformations
+ ${*D:.=dot}="dot"
+ ${*F:.a=}="obj1"
+
+ Out-of-date dependencies with suffix transformations
+ ${?D:ir=}="d ."
+ ${?F:.h=.H}="obj_1.o dummy"
+
+ Member with suffix transformations
+ ${%D:.=}=""
+ ${%F:${VAR2}=${VAR}}="obj1foo bar baz"
+
+cp 'dir/obj_1.o' 'obj1.o'
+ar -rcv 'lib.a' 'obj1.o'
+a - obj1.o
+rm -f 'obj1.o'
+mkdir -p '.'
+printf '#include "obj_2.h"\nconst char* obj_2 = "obj_2.c";\n' \
+ >'obj_2.c'
+mkdir -p '.'
+touch 'obj_2.h'
+Local variables
+ ${@}="obj2.o" ${<}="obj_2.c"
+ ${*}="obj2" ${?}="obj_2.c obj_2.h dir/obj_1.h"
+ ${%}=""
+
+Directory and filename parts of local variables
+ ${@D}="." ${@F}="obj2.o"
+ ${<D}="." ${<F}="obj_2.c"
+ ${*D}="." ${*F}="obj2"
+ ${?D}=". . dir" ${?F}="obj_2.c obj_2.h obj_1.h"
+ ${%D}="" ${%F}=""
+
+Local variable substitutions
+ ${@:.o=}="obj2" ${<:.c=.C}="obj_2.C"
+ ${*:=.h}="obj2.h" ${?:.h=.H}="obj_2.c obj_2.H dir/obj_1.H"
+ ${%:=}=""
+
+Target with suffix transformations
+ ${@D:=append}=".append"
+ ${@F:.o=.O}="obj2.O"
+
+ Implied source with suffix transformations
+ ${<D:r=rr}="."
+ ${<F:.c=.C}="obj_2.C"
+
+ Suffixless target with suffix transformations
+ ${*D:.=dot}="dot"
+ ${*F:.a=}="obj2"
+
+ Out-of-date dependencies with suffix transformations
+ ${?D:ir=}=". . d"
+ ${?F:.h=.H}="obj_2.c obj_2.H obj_1.H"
+
+ Member with suffix transformations
+ ${%D:.=}=""
+ ${%F:${VAR2}=${VAR}}=""
+
+cc -c -o 'obj2.o' 'obj_2.c'
+ar -rcv 'lib.a' 'obj2.o'
+a - obj2.o
+mkdir -p '.'
+touch 'obj3.h'
+mkdir -p 'dir'
+touch 'dir/dummy'
+mkdir -p '.'
+printf '#include "obj3.h"\nconst char* obj3 = "obj3.c";\n' \
+ >'obj3.c'
+Local variables
+ ${@}="lib.a" ${<}="obj3.c"
+ ${*}="obj3" ${?}="obj3.h dir/dummy obj3.c"
+ ${%}="obj3.o"
+
+Directory and filename parts of local variables
+ ${@D}="." ${@F}="lib.a"
+ ${<D}="." ${<F}="obj3.c"
+ ${*D}="." ${*F}="obj3"
+ ${?D}=". dir ." ${?F}="obj3.h dummy obj3.c"
+ ${%D}="." ${%F}="obj3.o"
+
+Local variable substitutions
+ ${@:.o=}="lib.a" ${<:.c=.C}="obj3.C"
+ ${*:=.h}="obj3.h" ${?:.h=.H}="obj3.H dir/dummy obj3.c"
+ ${%:=}="obj3.o"
+
+Target with suffix transformations
+ ${@D:=append}=".append"
+ ${@F:.o=.O}="lib.a"
+
+ Implied source with suffix transformations
+ ${<D:r=rr}="."
+ ${<F:.c=.C}="obj3.C"
+
+ Suffixless target with suffix transformations
+ ${*D:.=dot}="dot"
+ ${*F:.a=}="obj3"
+
+ Out-of-date dependencies with suffix transformations
+ ${?D:ir=}=". d ."
+ ${?F:.h=.H}="obj3.H dummy obj3.c"
+
+ Member with suffix transformations
+ ${%D:.=}=""
+ ${%F:${VAR2}=${VAR}}="obj3foo bar baz"
+
+cc -c -o 'obj3.o' 'obj3.c'
+ar -rcv 'lib.a' 'obj3.o'
+a - obj3.o
+rm -f 'obj3.o'
+exit status 0
diff --git a/unit-tests/posix1.mk b/unit-tests/posix1.mk
new file mode 100644
index 0000000..50b0a63
--- /dev/null
+++ b/unit-tests/posix1.mk
@@ -0,0 +1,184 @@
+# $NetBSD: posix1.mk,v 1.3 2014/08/30 22:21:08 sjg Exp $
+
+# Keep the default suffixes from interfering, just in case.
+.SUFFIXES:
+
+all: line-continuations suffix-substitution localvars
+
+# we need to clean for repeatable results
+.BEGIN: clean
+clean:
+ @rm -f lib.a dir/* dummy obj*
+
+#
+# Line continuations
+#
+
+# Escaped newlines and leading whitespace from the next line are replaced
+# with single space, except in commands, where the escape and the newline
+# are retained, but a single leading tab (if any) from the next line is
+# removed. (PR 49085)
+# Expect:
+# ${VAR} = "foo bar baz"
+# a
+# b
+# c
+VAR = foo\
+\
+ bar\
+ baz
+
+line-continuations:
+ @echo '$${VAR} = "${VAR}"'
+ @echo 'aXbXc' | sed -e 's/X/\
+ /g'
+
+
+#
+# Suffix substitution
+#
+
+# The only variable modifier accepted by POSIX.
+# ${VAR:s1=s2}: replace s1, if found, with s2 at end of each word in
+# ${VAR}. s1 and s2 may contain macro expansions.
+# Expect: foo baR baz, bar baz, foo bar baz, fooadd baradd bazadd
+suffix-substitution:
+ @echo '${VAR:r=R}, ${VAR:foo=}, ${VAR:not_there=wrong}, ${VAR:=add}'
+
+
+#
+# Local variables: regular forms, D/F forms and suffix substitution.
+#
+
+# In the past substitutions did not work with the D/F forms and those
+# forms were not available for $?. (PR 49085)
+
+ARFLAGS = -rcv
+
+localvars: lib.a
+
+# $@ = target or archive name $< = implied source
+# $* = target without suffix $? = sources newer than target
+# $% = archive member name
+LOCALS = \
+ "Local variables\n\
+ \$${@}=\"${@}\" \$${<}=\"${<}\"\n\
+ \$${*}=\"${*}\" \$${?}=\"${?}\"\n\
+ \$${%%}=\"${%}\"\n\n"
+
+# $XD = directory part of X $XF = file part of X
+# X is one of the local variables.
+LOCAL_ALTERNATIVES = \
+ "Directory and filename parts of local variables\n\
+ \$${@D}=\"${@D}\" \$${@F}=\"${@F}\"\n\
+ \$${<D}=\"${<D}\" \$${<F}=\"${<F}\"\n\
+ \$${*D}=\"${*D}\" \$${*F}=\"${*F}\"\n\
+ \$${?D}=\"${?D}\" \$${?F}=\"${?F}\"\n\
+ \$${%%D}=\"${%D}\" \$${%%F}=\"${%F}\"\n\n"
+
+# Do all kinds of meaningless substitutions on local variables to see
+# if they work. Add, remove and replace things.
+VAR2 = .o
+VAR3 = foo
+LOCAL_SUBSTITUTIONS = \
+ "Local variable substitutions\n\
+ \$${@:.o=}=\"${@:.o=}\" \$${<:.c=.C}=\"${<:.c=.C}\"\n\
+ \$${*:=.h}=\"${*:=.h}\" \$${?:.h=.H}=\"${?:.h=.H}\"\n\
+ \$${%%:=}=\"${%:=}\"\n\n"
+
+LOCAL_ALTERNATIVE_SUBSTITUTIONS = \
+ "Target with suffix transformations\n\
+ \$${@D:=append}=\"${@D:=append}\"\n\
+ \$${@F:.o=.O}=\"${@F:.o=.O}\"\n\
+ \n\
+ Implied source with suffix transformations\n\
+ \$${<D:r=rr}=\"${<D:r=rr}\"\n\
+ \$${<F:.c=.C}=\"${<F:.c=.C}\"\n\
+ \n\
+ Suffixless target with suffix transformations\n\
+ \$${*D:.=dot}=\"${*D:.=dot}\"\n\
+ \$${*F:.a=}=\"${*F:.a=}\"\n\
+ \n\
+ Out-of-date dependencies with suffix transformations\n\
+ \$${?D:ir=}=\"${?D:ir=}\"\n\
+ \$${?F:.h=.H}=\"${?F:.h=.H}\"\n\
+ \n\
+ Member with suffix transformations\n\
+ \$${%%D:.=}=\"${%D:.=}\"\n\
+ \$${%%F:\$${VAR2}=\$${VAR}}=\"${%F:${VAR2}=${VAR}}\"\n\n"
+
+.SUFFIXES: .c .o .a
+
+# The system makefiles make the .c.a rule .PRECIOUS with a special source,
+# but such a thing is not POSIX compatible. It's also somewhat useless
+# in a test makefile.
+.c.a:
+ @printf ${LOCALS}
+ @printf ${LOCAL_ALTERNATIVES}
+ @printf ${LOCAL_SUBSTITUTIONS}
+ @printf ${LOCAL_ALTERNATIVE_SUBSTITUTIONS}
+ cc -c -o '${%}' '${<}'
+ ar ${ARFLAGS} '${@}' '${%}'
+ rm -f '${%}'
+
+.c.o:
+ @printf ${LOCALS}
+ @printf ${LOCAL_ALTERNATIVES}
+ @printf ${LOCAL_SUBSTITUTIONS}
+ @printf ${LOCAL_ALTERNATIVE_SUBSTITUTIONS}
+ cc -c -o '${@}' '${<}'
+
+# Some of these rules are padded with useless extra dependencies just so
+# that ${?} has more than one file.
+
+lib.a: lib.a(obj1.o) lib.a(obj2.o) lib.a(obj3.o)
+ @ar -s '${@}'
+
+# Explicit rule where the dependency is an inferred file. The dependency
+# object's name differs from the member's because there was a bug which
+# forced a dependency on member even when no such dependency was specified
+# (PR 49086).
+lib.a(obj1.o): dir/obj_1.o dummy
+ @printf ${LOCALS}
+ @printf ${LOCAL_ALTERNATIVES}
+ @printf ${LOCAL_SUBSTITUTIONS}
+ @printf ${LOCAL_ALTERNATIVE_SUBSTITUTIONS}
+ cp 'dir/obj_1.o' '$%'
+ ar ${ARFLAGS} '${@}' '$%'
+ rm -f '$%'
+
+# Excplicit rule where the dependency also has an explicit rule.
+lib.a(obj2.o): obj2.o
+ ar ${ARFLAGS} '${@}' '${%}'
+
+# Use .c.a inference with an extra dependency.
+lib.a(obj3.o): obj3.h dir/dummy
+
+# Use .c.o inference with an extra dependency.
+dir/obj_1.o: dir/obj_1.h
+
+# According to POSIX, $* is only required for inference rules and $<'s
+# value is unspecified outside of inference rules. Strictly speaking
+# we shouldn't be expanding them here but who cares. At least we get
+# to check that the program does nothing stupid (like crash) with them.
+# The C file is named differently from the object file because there
+# was a bug which forced dependencies based on inference rules on all
+# applicable targets (PR 49086).
+obj2.o: obj_2.c obj_2.h dir/obj_1.h
+ @printf ${LOCALS}
+ @printf ${LOCAL_ALTERNATIVES}
+ @printf ${LOCAL_SUBSTITUTIONS}
+ @printf ${LOCAL_ALTERNATIVE_SUBSTITUTIONS}
+ cc -c -o '${@}' 'obj_2.c'
+
+# Hey, this is make, we can make our own test data setup! obj1.c
+# and obj2.c are not used, so they should not get created. They're here
+# as a bait for a regression into the forced dependencies discussed earlier.
+obj1.c dir/obj_1.c obj2.c obj_2.c obj3.c:
+ mkdir -p '${@D}'
+ printf '#include "${@F:.c=.h}"\nconst char* ${@F:.c=} = "${@}";\n' \
+ >'${@}'
+
+dir/obj_1.h obj_2.h obj3.h dummy dir/dummy:
+ mkdir -p '${@D}'
+ touch '${@}'
diff --git a/unit-tests/qequals.exp b/unit-tests/qequals.exp
new file mode 100644
index 0000000..6b2f4dc
--- /dev/null
+++ b/unit-tests/qequals.exp
@@ -0,0 +1,2 @@
+V.i386 ?= OK
+exit status 0
diff --git a/unit-tests/qequals b/unit-tests/qequals.mk
index e23078e..67a48ad 100644
--- a/unit-tests/qequals
+++ b/unit-tests/qequals.mk
@@ -1,4 +1,4 @@
-# $Id: qequals,v 1.1.1.1 2008/03/31 00:13:05 sjg Exp $
+# $Id: qequals.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $
M= i386
V.i386= OK
diff --git a/unit-tests/suffixes.exp b/unit-tests/suffixes.exp
new file mode 100644
index 0000000..2a46e1c
--- /dev/null
+++ b/unit-tests/suffixes.exp
@@ -0,0 +1,35 @@
+make: don't know how to make issue3 (continuing)
+There should be no text after the colon:
+touch .a
+There should be no text after the colon:
+touch .a.b
+There should be no text after the colon:
+touch .b.a
+touch issue5a.c
+first set
+cp issue5a.c issue5a.d
+touch issue5b.d
+first set
+cp issue5b.d issue5b.c
+touch issue5c.d
+first set
+cp issue5c.d issue5c
+touch issue5d.d
+first set
+cp issue5d.d issue5d.e
+touch issue5e.e
+first set
+cp issue5e.e issue5e.d
+make: don't know how to make issue6.f (continuing)
+touch issue10.d
+first set
+cp issue10.d issue10.e
+touch issue11.h
+touch issue11.first
+.ALLSRC: issue11.h issue11.first
+cp issue11.h issue11.i
+touch issue11.second
+.ALLSRC: issue11.i issue11.second
+cp issue11.i issue11.j
+`all' not remade because of errors.
+exit status 0
diff --git a/unit-tests/suffixes.mk b/unit-tests/suffixes.mk
new file mode 100644
index 0000000..113484a
--- /dev/null
+++ b/unit-tests/suffixes.mk
@@ -0,0 +1,89 @@
+# $NetBSD: suffixes.mk,v 1.3 2014/08/30 22:21:08 sjg Exp $
+
+# Issues from PR 49086
+
+# Issue 3: single suffix rules remain active after .SUFFIXES is cleared
+#
+# There's a rule for issue3.a, but .a is no longer a known suffix when
+# targets are being made, so issue3 should not get made.
+all: issue3
+
+# Issue 4: suffix rules do not become regular rules when .SUFFIXES is cleared
+#
+# When the rules were encountered, .a and .b were known suffices, but later
+# on they were forgotten. These should get created as regular targets.
+all: .a .a.b .b.a
+
+# Issue 5: adding more suffixes does not make existing rules into suffix rules
+#
+# When the targets .c.d, .d.c, .d, .d.e, and .e.d were encountered, only .a,
+# .b and .c were known suffixes, so all of them were regular rules. Later
+# rest of the suffixes were made known, so they should all be suffix
+# transformation rules.
+all: issue5a.d issue5b.c issue5c issue5d.e issue5e.d
+
+# Issue 6: transformation search can end up in an infinite loop
+#
+# There is no file or target from which issue6.f could be made from so
+# this should fail. The bug was that because rules .e.f, .d.e and .e.d
+# exist, make would try to make .f from .e and then infinitely try
+# to do .e from .d and vice versa.
+all: issue6.f
+
+# Issue 10: explicit dependencies affect transformation rule selection
+#
+# If issue10.e is wanted and both issue10.d and issue10.f are available,
+# make should choose the .d.e rule, because .d is before .f in .SUFFIXES.
+# The bug was that if issue10.d had an explicit dependency on issue10.f,
+# it would choose .f.e instead.
+all: issue10.e
+
+# Issue 11: sources from transformation rules are expanded incorrectly
+#
+# issue11.j should depend on issue11.i and issue11.second and issue11.i
+# should depend on issue11.h and issue11.first. The bug was that
+# the dynamic sources were expanded before ${.PREFIX} and ${.TARGET} were
+# available, so they would have expanded to a null string.
+all: issue11.j
+
+# we need to clean for repeatable results
+.BEGIN: clean
+clean:
+ @rm -f issue* .[ab]*
+
+.SUFFIXES: .a .b .c
+
+.a .a.b .b.a:
+ @echo 'There should be no text after the colon: ${.IMPSRC}'
+ touch ${.TARGET}
+
+.c.d .d.c .d .d.e .e.d:
+ @echo 'first set'
+ cp ${.IMPSRC} ${.TARGET}
+
+.SUFFIXES:
+.SUFFIXES: .c .d .e .f .g
+
+.e .e.f .f.e:
+ @echo 'second set'
+ cp ${.IMPSRC} ${.TARGET}
+
+issue3.a:
+ @echo 'There is a bug if you see this.'
+ touch ${.TARGET}
+
+issue5a.c issue5b.d issue5c.d issue5d.d issue5e.e issue10.d issue10.f:
+ touch ${.TARGET}
+
+.SUFFIXES: .h .i .j
+
+.h.i: ${.PREFIX}.first
+ @echo '.ALLSRC: ${.ALLSRC}'
+ cp ${.IMPSRC} ${.TARGET}
+
+.i.j: ${.PREFIX}.second
+ @echo '.ALLSRC: ${.ALLSRC}'
+ cp ${.IMPSRC} ${.TARGET}
+
+issue11.h issue11.first issue11.second:
+ touch ${.TARGET}
diff --git a/unit-tests/sunshcmd.exp b/unit-tests/sunshcmd.exp
new file mode 100644
index 0000000..b14f6b6
--- /dev/null
+++ b/unit-tests/sunshcmd.exp
@@ -0,0 +1,4 @@
+TEST1=hello
+TEST2=bye
+TEST3=later
+exit status 0
diff --git a/unit-tests/sunshcmd b/unit-tests/sunshcmd.mk
index e3baf90..e3baf90 100644
--- a/unit-tests/sunshcmd
+++ b/unit-tests/sunshcmd.mk
diff --git a/unit-tests/sysv.exp b/unit-tests/sysv.exp
new file mode 100644
index 0000000..4cce2de
--- /dev/null
+++ b/unit-tests/sysv.exp
@@ -0,0 +1,7 @@
+FOOBAR =
+FOOBAR = foobar fubar
+fun
+fun
+fun
+In the Sun
+exit status 0
diff --git a/unit-tests/sysv b/unit-tests/sysv.mk
index 9eedacb..d5e99ff 100644
--- a/unit-tests/sysv
+++ b/unit-tests/sysv.mk
@@ -1,7 +1,7 @@
-# $Id: sysv,v 1.1.1.2 2011/06/05 04:23:49 sjg Exp $
+# $Id: sysv.mk,v 1.2 2014/08/30 22:25:14 sjg Exp $
FOO ?=
-FOOBAR = $(FOO:=bar)
+FOOBAR = ${FOO:=bar}
_this := ${.PARSEDIR}/${.PARSEFILE}
@@ -14,7 +14,7 @@ SUN = the Sun
all: foo fun
foo:
- @echo FOOBAR = $(FOOBAR)
+ @echo FOOBAR = ${FOOBAR}
.if empty(FOO)
@FOO="foo fu" ${.MAKE} -f ${_this} foo
.endif
diff --git a/unit-tests/ternary.exp b/unit-tests/ternary.exp
new file mode 100644
index 0000000..ed9c1bd
--- /dev/null
+++ b/unit-tests/ternary.exp
@@ -0,0 +1,10 @@
+The answer is unknown
+The answer is unknown
+The answer is empty
+The answer is known
+The answer is
+The answer is empty
+The answer is known
+The answer is 42
+The answer is 42
+exit status 0
diff --git a/unit-tests/ternary b/unit-tests/ternary.mk
index 77f8349..77f8349 100644
--- a/unit-tests/ternary
+++ b/unit-tests/ternary.mk
diff --git a/unit-tests/test.exp b/unit-tests/test.exp
deleted file mode 100644
index aaecb96..0000000
--- a/unit-tests/test.exp
+++ /dev/null
@@ -1,383 +0,0 @@
-comment testing start
-this is foo
-This is how a comment looks: # comment
-comment testing done
-make: "cond1" line 75: warning: extra else
-make: "cond1" line 85: warning: extra else
-2 is prime
-A='other' B='unknown' C='clever' o='no,no'
-Passed:
- var
- ("var")
- (var != var)
- var != var
- !((var != var) && defined(name))
- var == quoted
-
-1 is not prime
-2 is prime
-3 is prime
-4 is not prime
-5 is prime
-
-make: warning: String comparison operator should be either == or !=
-make: Bad conditional expression `"0" > 0' in "0" > 0?OK:No
-
-OK
-make: "error" line 3: just FYI
-make: "error" line 4: warning: this could be serious
-make: "error" line 5: this is fatal
-UT_DOLLAR=This is $UT_FU
-UT_FOO=foobar is fubar
-UT_FU=fubar
-UT_TEST=export
-UT_ZOO=hoopie
-UT_ALL=even this gets exported
-UT_BADDIR=unit-tests
-UT_DOLLAR=This is $UT_FU
-UT_F=fine
-UT_FOO=foobar is fubar
-UT_FU=fubar
-UT_NO=all
-UT_OK=good
-UT_OKDIR=unit-tests
-UT_TEST=export-all
-UT_ZOO=hoopie
-make:
-UT_TEST=export-env
-UT_ENV=not-exported
-UT_EXP=not-exported
-env:
-UT_TEST=export-env
-UT_ENV=exported
-UT_EXP=exported
-At first, I am
-happy
-and now: sad
-.ERROR: Looks like 'sad' is upset.
-*** Error code 1
-
-Stop.
-make: stopped in unit-tests
-simple.1
-simple.1
-simple.2
-simple.2
-recursive.1.1.*
-recursive.1.1.*
-recursive.1.1.*
-recursive.1.1.*
-recursive.1.99
-recursive.1.99
-recursive.2.1.*
-recursive.2.1.*
-recursive.2.1.*
-recursive.2.1.*
-recursive.2.99
-recursive.2.99
-shared.0
-shared.0
-shared.1.99
-shared.1.99
-shared.2.1
-shared.2.1
-shared.2.99
-shared.2.99
-make: Graph cycles through `cycle.2.99'
-make: Graph cycles through `cycle.2.98'
-make: Graph cycles through `cycle.2.97'
-cycle.1.99
-cycle.1.99
-x=one
-x="two and three"
-x=four
-x="five"
-x=-I/this
-x=-I"This or that"
-x=-Ithat
-x="-DTHIS=\"this and that\""
-cfl=-I/this -I"This or that" -Ithat "-DTHIS=\"this and that\""
-a=one b="two and three"
-a=four b="five"
-a=ONE b="TWO AND THREE"
-a=FOUR b="FIVE"
-We expect an error next:
-make: "forloop" line 38: Wrong number of words (9) in .for substitution list with 2 vars
-make: Fatal errors encountered -- cannot continue
-make: stopped in unit-tests
-OK
-.for with :S;... OK
-b2af338b
-3360ac65
-7747f046
-9ca87054
-880fe816
-208fcbd3
-d5d376eb
-de41416c
-Expect: Unknown modifier 'Z'
-make: Unknown modifier 'Z'
-VAR:Z=
-Expect: Unknown modifier 'Z'
-make: Unknown modifier 'Z'
-VAR:Z=
-Expect: Unclosed variable specification for VAR
-make: Unclosed variable specification (expecting '}') for "VAR" (value "Thevariable") modifier S
-VAR:S,V,v,=Thevariable
-Expect: Unclosed variable specification for VAR
-make: Unclosed variable specification after complex modifier (expecting '}') for VAR
-VAR:S,V,v,=Thevariable
-Expect: Unclosed substitution for VAR (, missing)
-make: Unclosed substitution for VAR (, missing)
-VAR:S,V,v=
-LIB=a X_LIBS:M${LIB${LIB:tu}} is "/tmp/liba.a"
-LIB=a X_LIBS:M*/lib${LIB}.a is "/tmp/liba.a"
-LIB=a X_LIBS:M*/lib${LIB}.a:tu is "/TMP/LIBA.A"
-LIB=b X_LIBS:M${LIB${LIB:tu}} is ""
-LIB=b X_LIBS:M*/lib${LIB}.a is ""
-LIB=b X_LIBS:M*/lib${LIB}.a:tu is ""
-LIB=c X_LIBS:M${LIB${LIB:tu}} is ""
-LIB=c X_LIBS:M*/lib${LIB}.a is ""
-LIB=c X_LIBS:M*/lib${LIB}.a:tu is ""
-LIB=d X_LIBS:M${LIB${LIB:tu}} is "/tmp/libd.a"
-LIB=d X_LIBS:M*/lib${LIB}.a is "/tmp/libd.a"
-LIB=d X_LIBS:M*/lib${LIB}.a:tu is "/TMP/LIBD.A"
-LIB=e X_LIBS:M${LIB${LIB:tu}} is "/tmp/libe.a"
-LIB=e X_LIBS:M*/lib${LIB}.a is "/tmp/libe.a"
-LIB=e X_LIBS:M*/lib${LIB}.a:tu is "/TMP/LIBE.A"
-Mscanner=OK
-path=':/bin:/tmp::/:.:/no/such/dir:.'
-path='/bin:/tmp:/:/no/such/dir'
-path='/bin:/tmp:/:/no/such/dir'
-path='/bin':'/tmp':'/':'/no/such/dir'
-path='/bin':'/tmp':'/':'/no/such/dir'
-path_/usr/xbin=/opt/xbin/
-paths=/bin /tmp / /no/such/dir /opt/xbin
-PATHS=/BIN /TMP / /NO/SUCH/DIR /OPT/XBIN
-The answer is 42
-LIST = one two three four five six seven eight nine ten
-LIST:O = eight five four nine one seven six ten three two
-LIST:Ox = Ok
-LIST:O:Ox = Ok
-LISTX = Ok
-LISTSX = Ok
-make: Bad modifier `:OX' for LIST
-BADMOD 1 = }
-make: Bad modifier `:OxXX' for LIST
-BADMOD 2 = XX}
-LIST="one two three four five six"
-LIST:ts,="one,two,three,four,five,six"
-LIST:ts/:tu="ONE/TWO/THREE/FOUR/FIVE/SIX"
-LIST:ts::tu="ONE:TWO:THREE:FOUR:FIVE:SIX"
-LIST:ts:tu="ONETWOTHREEFOURFIVESIX"
-LIST:tu:ts/="ONE/TWO/THREE/FOUR/FIVE/SIX"
-LIST:ts:="one:two:three:four:five:six"
-LIST:ts="onetwothreefourfivesix"
-LIST:ts:S/two/2/="one2threefourfivesix"
-LIST:S/two/2/:ts="one2threefourfivesix"
-LIST:ts/:S/two/2/="one/2/three/four/five/six"
-Pretend the '/' in '/n' etc. below are back-slashes.
-LIST:ts/n="one
-two
-three
-four
-five
-six"
-LIST:ts/t="one two three four five six"
-LIST:ts/012:tu="ONE
-TWO
-THREE
-FOUR
-FIVE
-SIX"
-make: Bad modifier `:tx' for LIST
-LIST:tx="}"
-make: Bad modifier `:ts\x' for LIST
-LIST:ts/x:tu="\x:tu}"
-FU_mod-ts="a/b/cool"
-FU_mod-ts:ts:T="cool" == cool?
-B.${AAA:ts}="Baaa" == Baaa?
-make: Bad modifier `:[]' for LIST
-LIST:[]="" is an error
-LIST:[0]="one two three four five six"
-LIST:[0x0]="one two three four five six"
-LIST:[000]="one two three four five six"
-LIST:[*]="one two three four five six"
-LIST:[@]="one two three four five six"
-LIST:[0]:C/ /,/="one,two three four five six"
-LIST:[0]:C/ /,/g="one,two,three,four,five,six"
-LIST:[0]:C/ /,/1g="one,two,three,four,five,six"
-LIST:[*]:C/ /,/="one,two three four five six"
-LIST:[*]:C/ /,/g="one,two,three,four,five,six"
-LIST:[*]:C/ /,/1g="one,two,three,four,five,six"
-LIST:[@]:C/ /,/="one two three four five six"
-LIST:[@]:C/ /,/g="one two three four five six"
-LIST:[@]:C/ /,/1g="one two three four five six"
-LIST:[@]:[0]:C/ /,/="one,two three four five six"
-LIST:[0]:[@]:C/ /,/="one two three four five six"
-LIST:[@]:[*]:C/ /,/="one,two three four five six"
-LIST:[*]:[@]:C/ /,/="one two three four five six"
-EMPTY=""
-EMPTY:[#]="1" == 1 ?
-ESCAPEDSPACE="\ "
-ESCAPEDSPACE:[#]="1" == 1 ?
-REALLYSPACE=" "
-REALLYSPACE:[#]="1" == 1 ?
-LIST:[#]="6"
-LIST:[0]:[#]="1" == 1 ?
-LIST:[*]:[#]="1" == 1 ?
-LIST:[@]:[#]="6"
-LIST:[1]:[#]="1"
-LIST:[1..3]:[#]="3"
-EMPTY:[1]=""
-ESCAPEDSPACE="\ "
-ESCAPEDSPACE:[1]="\ "
-REALLYSPACE=" "
-REALLYSPACE:[1]="" == "" ?
-REALLYSPACE:[*]:[1]=" " == " " ?
-LIST:[1]="one"
-make: Bad modifier `:[1.]' for LIST
-LIST:[1.]="" is an error
-make: Bad modifier `:[1].' for LIST
-LIST:[1].="}" is an error
-LIST:[2]="two"
-LIST:[6]="six"
-LIST:[7]=""
-LIST:[999]=""
-make: Bad modifier `:[-]' for LIST
-LIST:[-]="" is an error
-make: Bad modifier `:[--]' for LIST
-LIST:[--]="" is an error
-LIST:[-1]="six"
-LIST:[-2]="five"
-LIST:[-6]="one"
-LIST:[-7]=""
-LIST:[-999]=""
-LONGLIST:[17]="17"
-LONGLIST:[0x11]="17"
-LONGLIST:[021]="17"
-LIST:[0]:[1]="one two three four five six"
-LIST:[*]:[1]="one two three four five six"
-LIST:[@]:[1]="one"
-LIST:[0]:[2]=""
-LIST:[*]:[2]=""
-LIST:[@]:[2]="two"
-LIST:[*]:C/ /,/:[2]=""
-LIST:[*]:C/ /,/:[*]:[2]=""
-LIST:[*]:C/ /,/:[@]:[2]="three"
-make: Bad modifier `:[1.]' for LIST
-LIST:[1.]="" is an error
-make: Bad modifier `:[1..]' for LIST
-LIST:[1..]="" is an error
-LIST:[1..1]="one"
-make: Bad modifier `:[1..1.]' for LIST
-LIST:[1..1.]="" is an error
-LIST:[1..2]="one two"
-LIST:[2..1]="two one"
-LIST:[3..-2]="three four five"
-LIST:[-4..4]="three four"
-make: Bad modifier `:[0..1]' for LIST
-LIST:[0..1]="" is an error
-make: Bad modifier `:[-1..0]' for LIST
-LIST:[-1..0]="" is an error
-LIST:[-1..1]="six five four three two one"
-LIST:[0..0]="one two three four five six"
-LIST:[3..99]="three four five six"
-LIST:[-3..-99]="four three two one"
-LIST:[-99..-3]="one two three four"
-HASH="#" == "#" ?
-LIST:[${HASH}]="6"
-LIST:[${ZERO}]="one two three four five six"
-LIST:[${ZERO}x${ONE}]="one"
-LIST:[${ONE}]="one"
-LIST:[${MINUSONE}]="six"
-LIST:[${STAR}]="one two three four five six"
-LIST:[${AT}]="one two three four five six"
-make: Bad modifier `:[${EMPTY' for LIST
-LIST:[${EMPTY}]="" is an error
-LIST:[${LONGLIST:[21]:S/2//}]="one"
-LIST:[${LIST:[#]}]="six"
-LIST:[${LIST:[${HASH}]}]="six"
-LIST:S/ /,/="one two three four five six"
-LIST:S/ /,/W="one,two three four five six"
-LIST:S/ /,/gW="one,two,three,four,five,six"
-EMPTY:S/^/,/=","
-EMPTY:S/^/,/W=","
-LIST:C/ /,/="one two three four five six"
-LIST:C/ /,/W="one,two three four five six"
-LIST:C/ /,/gW="one,two,three,four,five,six"
-EMPTY:C/^/,/=","
-EMPTY:C/^/,/W=","
-LIST:tW="one two three four five six"
-LIST:tw="one two three four five six"
-LIST:tW:C/ /,/="one,two three four five six"
-LIST:tW:C/ /,/g="one,two,three,four,five,six"
-LIST:tW:C/ /,/1g="one,two,three,four,five,six"
-LIST:tw:C/ /,/="one two three four five six"
-LIST:tw:C/ /,/g="one two three four five six"
-LIST:tw:C/ /,/1g="one two three four five six"
-LIST:tw:tW:C/ /,/="one,two three four five six"
-LIST:tW:tw:C/ /,/="one two three four five six"
-Making the.c
-Making the.h
-Making the.o from the.h the.c
-.TARGET="phony" .PREFIX="phony" .IMPSRC=""
-.TARGET="all" .PREFIX="all" .IMPSRC=""
-.TARGET="ok" .PREFIX="ok" .IMPSRC=""
-.TARGET="also.ok" .PREFIX="also.ok" .IMPSRC=""
-.TARGET="bug" .PREFIX="bug" .IMPSRC=""
-Posix says we should execute the command as if run by system(3)
-Expect 'Hello,' and 'World!'
-Hello,
-World!
-a command
-a command prefixed by '+' executes even with -n
-another command
-make -n
-echo a command
-echo "a command prefixed by '+' executes even with -n"
-a command prefixed by '+' executes even with -n
-echo another command
-make -n -j1
-{ echo a command
-} || exit $?
-echo "a command prefixed by '+' executes even with -n"
-a command prefixed by '+' executes even with -n
-{ echo another command
-} || exit $?
-Now we expect an error...
-*** Error code 1 (continuing)
-`all' not remade because of errors.
-V.i386 ?= OK
-TEST1=hello
-TEST2=bye
-TEST3=later
-FOOBAR =
-FOOBAR = foobar fubar
-fun
-fun
-fun
-In the Sun
-The answer is unknown
-The answer is unknown
-The answer is empty
-The answer is known
-The answer is
-The answer is empty
-The answer is known
-The answer is 42
-The answer is 42
-UT_DOLLAR=This is $UT_FU
-UT_FU=fubar
-UT_TEST=unexport
-UT_TEST=unexport-env
-default FU=<v>fu</v> FOO=<v>foo</v> VAR=<v></v>
-two FU=<v>bar</v> FOO=<v>goo</v> VAR=<v></v>
-three FU=<v>bar</v> FOO=<v>goo</v> VAR=<v></v>
-four FU=<v>bar</v> FOO=<v>goo</v> VAR=<v>Internal</v>
-five FU=<v>bar</v> FOO=<v>goo</v> VAR=<v>Internal</v>
-five v=is x k=is x
-six v=is y k=is y
-show-v v=override k=override
-*** Error code 1 (ignored)
-*** Error code 1 (ignored)
diff --git a/unit-tests/unexport-env.exp b/unit-tests/unexport-env.exp
new file mode 100644
index 0000000..6d43cab
--- /dev/null
+++ b/unit-tests/unexport-env.exp
@@ -0,0 +1,2 @@
+UT_TEST=unexport-env
+exit status 0
diff --git a/unit-tests/unexport-env b/unit-tests/unexport-env.mk
index f6a2ff9..aaabcd4 100644
--- a/unit-tests/unexport-env
+++ b/unit-tests/unexport-env.mk
@@ -1,7 +1,7 @@
-# $Id: unexport-env,v 1.1.1.1 2009/11/19 00:31:11 sjg Exp $
+# $Id: unexport-env.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $
# pick up a bunch of exported vars
-.include "export"
+.include "export.mk"
# an example of setting up a minimal environment.
PATH = /bin:/usr/bin:/sbin:/usr/sbin
diff --git a/unit-tests/unexport.exp b/unit-tests/unexport.exp
new file mode 100644
index 0000000..7b16ea3
--- /dev/null
+++ b/unit-tests/unexport.exp
@@ -0,0 +1,4 @@
+UT_DOLLAR=This is $UT_FU
+UT_FU=fubar
+UT_TEST=unexport
+exit status 0
diff --git a/unit-tests/unexport b/unit-tests/unexport.mk
index fb40d0c..0f12452 100644
--- a/unit-tests/unexport
+++ b/unit-tests/unexport.mk
@@ -1,7 +1,7 @@
-# $Id: unexport,v 1.1.1.1 2009/11/19 00:31:11 sjg Exp $
+# $Id: unexport.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $
# pick up a bunch of exported vars
-.include "export"
+.include "export.mk"
.unexport UT_ZOO UT_FOO
diff --git a/unit-tests/varcmd.exp b/unit-tests/varcmd.exp
new file mode 100644
index 0000000..34dd637
--- /dev/null
+++ b/unit-tests/varcmd.exp
@@ -0,0 +1,9 @@
+default FU=<v>fu</v> FOO=<v>foo</v> VAR=<v></v>
+two FU=<v>bar</v> FOO=<v>goo</v> VAR=<v></v>
+three FU=<v>bar</v> FOO=<v>goo</v> VAR=<v></v>
+four FU=<v>bar</v> FOO=<v>goo</v> VAR=<v>Internal</v>
+five FU=<v>bar</v> FOO=<v>goo</v> VAR=<v>Internal</v>
+five v=is x k=is x
+six v=is y k=is y
+show-v v=override k=override
+exit status 0
diff --git a/unit-tests/varcmd b/unit-tests/varcmd.mk
index a58e014..a5fd198 100644
--- a/unit-tests/varcmd
+++ b/unit-tests/varcmd.mk
@@ -1,4 +1,4 @@
-# $Id: varcmd,v 1.3 2008/05/15 04:30:47 sjg Exp $
+# $Id: varcmd.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $
#
# Test behaviour of recursive make and vars set on command line.
diff --git a/unit-tests/varmisc.exp b/unit-tests/varmisc.exp
new file mode 100644
index 0000000..e2af496
--- /dev/null
+++ b/unit-tests/varmisc.exp
@@ -0,0 +1,20 @@
+
+:D expanded when var set
+true
+TRUE
+:U expanded when var undef
+true
+TRUE
+:D skipped if var undef
+
+:U skipped when var set
+is set
+:? only lhs when value true
+true
+TRUE
+:? only rhs when value false
+false
+FALSE
+do not evaluate or expand :? if discarding
+is set
+exit status 0
diff --git a/unit-tests/varmisc.mk b/unit-tests/varmisc.mk
new file mode 100644
index 0000000..14b52d2
--- /dev/null
+++ b/unit-tests/varmisc.mk
@@ -0,0 +1,42 @@
+# $Id: varmisc.mk,v 1.5 2015/10/12 17:10:48 sjg Exp $
+#
+# Miscellaneous variable tests.
+
+all: unmatched_var_paren D_true U_true D_false U_false Q_lhs Q_rhs NQ_none
+
+unmatched_var_paren:
+ @echo ${foo::=foo-text}
+
+True = ${echo true >&2:L:sh}TRUE
+False= ${echo false >&2:L:sh}FALSE
+
+VSET= is set
+.undef UNDEF
+
+U_false:
+ @echo :U skipped when var set
+ @echo ${VSET:U${False}}
+
+D_false:
+ @echo :D skipped if var undef
+ @echo ${UNDEF:D${False}}
+
+U_true:
+ @echo :U expanded when var undef
+ @echo ${UNDEF:U${True}}
+
+D_true:
+ @echo :D expanded when var set
+ @echo ${VSET:D${True}}
+
+Q_lhs:
+ @echo :? only lhs when value true
+ @echo ${1:L:?${True}:${False}}
+
+Q_rhs:
+ @echo :? only rhs when value false
+ @echo ${0:L:?${True}:${False}}
+
+NQ_none:
+ @echo do not evaluate or expand :? if discarding
+ @echo ${VSET:U${1:L:?${True}:${False}}}
diff --git a/unit-tests/varshell.exp b/unit-tests/varshell.exp
new file mode 100644
index 0000000..dae2c6b
--- /dev/null
+++ b/unit-tests/varshell.exp
@@ -0,0 +1,10 @@
+make: "varshell.mk" line 5: warning: "/bin/no/such/command 2> /dev/null" returned non-zero status
+make: "varshell.mk" line 8: warning: "false" returned non-zero status
+make: "varshell.mk" line 9: warning: "echo "output before the error"; false" returned non-zero status
+EXEC_FAILED=''
+TERMINATED_BY_SIGNAL=''
+ERROR_NO_OUTPUT=''
+ERROR_WITH_OUTPUT='output before the error'
+NO_ERROR_NO_OUTPUT=''
+NO_ERROR_WITH_OUTPUT='this is good'
+exit status 0
diff --git a/unit-tests/varshell.mk b/unit-tests/varshell.mk
new file mode 100644
index 0000000..9c8baac
--- /dev/null
+++ b/unit-tests/varshell.mk
@@ -0,0 +1,19 @@
+# $Id: varshell.mk,v 1.4 2015/04/20 03:16:39 sjg Exp $
+#
+# Test VAR != shell command
+
+EXEC_FAILED != /bin/no/such/command 2> /dev/null
+# SunOS cannot handle this one
+#TERMINATED_BY_SIGNAL != kill -14 $$$$
+ERROR_NO_OUTPUT != false
+ERROR_WITH_OUTPUT != echo "output before the error"; false
+NO_ERROR_NO_OUTPUT != true
+NO_ERROR_WITH_OUTPUT != echo "this is good"
+
+allvars= EXEC_FAILED TERMINATED_BY_SIGNAL ERROR_NO_OUTPUT ERROR_WITH_OUTPUT \
+ NO_ERROR_NO_OUTPUT NO_ERROR_WITH_OUTPUT
+
+all:
+.for v in ${allvars}
+ @echo ${v}=\'${${v}}\'
+.endfor
diff --git a/var.c b/var.c
index 26e3f4b..c404b95 100644
--- a/var.c
+++ b/var.c
@@ -1,4 +1,4 @@
-/* $NetBSD: var.c,v 1.186 2014/06/20 06:13:45 sjg Exp $ */
+/* $NetBSD: var.c,v 1.205 2016/02/20 01:19:03 sjg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -69,14 +69,14 @@
*/
#ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: var.c,v 1.186 2014/06/20 06:13:45 sjg Exp $";
+static char rcsid[] = "$NetBSD: var.c,v 1.205 2016/02/20 01:19:03 sjg Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 3/19/94";
#else
-__RCSID("$NetBSD: var.c,v 1.186 2014/06/20 06:13:45 sjg Exp $");
+__RCSID("$NetBSD: var.c,v 1.205 2016/02/20 01:19:03 sjg Exp $");
#endif
#endif /* not lint */
#endif
@@ -129,7 +129,6 @@ __RCSID("$NetBSD: var.c,v 1.186 2014/06/20 06:13:45 sjg Exp $");
#include <regex.h>
#endif
#include <ctype.h>
-#include <inttypes.h>
#include <stdlib.h>
#include <limits.h>
#include <time.h>
@@ -138,6 +137,7 @@ __RCSID("$NetBSD: var.c,v 1.186 2014/06/20 06:13:45 sjg Exp $");
#include "buf.h"
#include "dir.h"
#include "job.h"
+#include "metachar.h"
extern int makelevel;
/*
@@ -154,13 +154,23 @@ char **savedEnv = NULL;
char var_Error[] = "";
/*
- * Similar to var_Error, but returned when the 'errnum' flag for Var_Parse is
- * set false. Why not just use a constant? Well, gcc likes to condense
- * identical string instances...
+ * Similar to var_Error, but returned when the 'VARF_UNDEFERR' flag for
+ * Var_Parse is not set. Why not just use a constant? Well, gcc likes
+ * to condense identical string instances...
*/
static char varNoError[] = "";
/*
+ * Traditionally we consume $$ during := like any other expansion.
+ * Other make's do not.
+ * This knob allows controlling the behavior.
+ * FALSE for old behavior.
+ * TRUE for new compatible.
+ */
+#define SAVE_DOLLARS ".MAKE.SAVE_DOLLARS"
+static Boolean save_dollars = FALSE;
+
+/*
* Internally, variables are contained in four different contexts.
* 1) the environment. They may not be changed. If an environment
* variable is appended-to, the result is placed in the global
@@ -216,7 +226,11 @@ static int var_exportedVars = VAR_EXPORTED_NONE;
* We pass this to Var_Export when doing the initial export
* or after updating an exported var.
*/
-#define VAR_EXPORT_PARENT 1
+#define VAR_EXPORT_PARENT 1
+/*
+ * We pass this to Var_Export1 to tell it to leave the value alone.
+ */
+#define VAR_EXPORT_LITERAL 2
/* Var*Pattern flags */
#define VAR_SUB_GLOBAL 0x01 /* Apply substitution globally */
@@ -541,7 +555,7 @@ Var_Delete(const char *name, GNode *ctxt)
char *cp;
if (strchr(name, '$')) {
- cp = Var_Subst(NULL, name, VAR_GLOBAL, 0);
+ cp = Var_Subst(NULL, name, VAR_GLOBAL, VARF_WANTRES);
} else {
cp = (char *)name;
}
@@ -580,12 +594,13 @@ Var_Delete(const char *name, GNode *ctxt)
* We only manipulate flags of vars if 'parent' is set.
*/
static int
-Var_Export1(const char *name, int parent)
+Var_Export1(const char *name, int flags)
{
char tmp[BUFSIZ];
Var *v;
char *val = NULL;
int n;
+ int parent = (flags & VAR_EXPORT_PARENT);
if (*name == '.')
return 0; /* skip internals */
@@ -613,7 +628,7 @@ Var_Export1(const char *name, int parent)
return 0; /* nothing to do */
}
val = Buf_GetAll(&v->val, NULL);
- if (strchr(val, '$')) {
+ if ((flags & VAR_EXPORT_LITERAL) == 0 && strchr(val, '$')) {
if (parent) {
/*
* Flag this as something we need to re-export.
@@ -632,7 +647,7 @@ Var_Export1(const char *name, int parent)
}
n = snprintf(tmp, sizeof(tmp), "${%s}", name);
if (n < (int)sizeof(tmp)) {
- val = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
+ val = Var_Subst(NULL, tmp, VAR_GLOBAL, VARF_WANTRES);
setenv(name, val, 1);
free(val);
}
@@ -700,14 +715,16 @@ Var_ExportVars(void)
int ac;
int i;
- val = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
- av = brk_string(val, &ac, FALSE, &as);
- for (i = 0; i < ac; i++) {
- Var_Export1(av[i], 0);
+ val = Var_Subst(NULL, tmp, VAR_GLOBAL, VARF_WANTRES);
+ if (*val) {
+ av = brk_string(val, &ac, FALSE, &as);
+ for (i = 0; i < ac; i++) {
+ Var_Export1(av[i], 0);
+ }
+ free(as);
+ free(av);
}
free(val);
- free(as);
- free(av);
}
}
@@ -723,7 +740,7 @@ Var_Export(char *str, int isExport)
char *val;
char **av;
char *as;
- int track;
+ int flags;
int ac;
int i;
@@ -732,42 +749,47 @@ Var_Export(char *str, int isExport)
return;
}
+ flags = 0;
if (strncmp(str, "-env", 4) == 0) {
- track = 0;
str += 4;
+ } else if (strncmp(str, "-literal", 8) == 0) {
+ str += 8;
+ flags |= VAR_EXPORT_LITERAL;
} else {
- track = VAR_EXPORT_PARENT;
+ flags |= VAR_EXPORT_PARENT;
}
- val = Var_Subst(NULL, str, VAR_GLOBAL, 0);
- av = brk_string(val, &ac, FALSE, &as);
- for (i = 0; i < ac; i++) {
- name = av[i];
- if (!name[1]) {
- /*
- * A single char.
- * If it is one of the vars that should only appear in
- * local context, skip it, else we can get Var_Subst
- * into a loop.
- */
- switch (name[0]) {
- case '@':
- case '%':
- case '*':
- case '!':
- continue;
+ val = Var_Subst(NULL, str, VAR_GLOBAL, VARF_WANTRES);
+ if (*val) {
+ av = brk_string(val, &ac, FALSE, &as);
+ for (i = 0; i < ac; i++) {
+ name = av[i];
+ if (!name[1]) {
+ /*
+ * A single char.
+ * If it is one of the vars that should only appear in
+ * local context, skip it, else we can get Var_Subst
+ * into a loop.
+ */
+ switch (name[0]) {
+ case '@':
+ case '%':
+ case '*':
+ case '!':
+ continue;
+ }
}
- }
- if (Var_Export1(name, track)) {
- if (VAR_EXPORTED_ALL != var_exportedVars)
- var_exportedVars = VAR_EXPORTED_YES;
- if (isExport && track) {
- Var_Append(MAKE_EXPORTED, name, VAR_GLOBAL);
+ if (Var_Export1(name, flags)) {
+ if (VAR_EXPORTED_ALL != var_exportedVars)
+ var_exportedVars = VAR_EXPORTED_YES;
+ if (isExport && (flags & VAR_EXPORT_PARENT)) {
+ Var_Append(MAKE_EXPORTED, name, VAR_GLOBAL);
+ }
}
}
+ free(as);
+ free(av);
}
free(val);
- free(as);
- free(av);
}
@@ -826,7 +848,7 @@ Var_UnExport(char *str)
/* Using .MAKE.EXPORTED */
n = snprintf(tmp, sizeof(tmp), "${" MAKE_EXPORTED ":O:u}");
if (n < (int)sizeof(tmp)) {
- vlist = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
+ vlist = Var_Subst(NULL, tmp, VAR_GLOBAL, VARF_WANTRES);
}
}
if (vlist) {
@@ -856,7 +878,7 @@ Var_UnExport(char *str)
n = snprintf(tmp, sizeof(tmp),
"${" MAKE_EXPORTED ":N%s}", v->name);
if (n < (int)sizeof(tmp)) {
- cp = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
+ cp = Var_Subst(NULL, tmp, VAR_GLOBAL, VARF_WANTRES);
Var_Set(MAKE_EXPORTED, cp, VAR_GLOBAL, 0);
free(cp);
}
@@ -911,7 +933,7 @@ Var_Set(const char *name, const char *val, GNode *ctxt, int flags)
* point in searching them all just to save a bit of memory...
*/
if (strchr(name, '$') != NULL) {
- expanded_name = Var_Subst(NULL, name, ctxt, 0);
+ expanded_name = Var_Subst(NULL, name, ctxt, VARF_WANTRES);
if (expanded_name[0] == 0) {
if (DEBUG(VAR)) {
fprintf(debug_file, "Var_Set(\"%s\", \"%s\", ...) "
@@ -979,10 +1001,13 @@ Var_Set(const char *name, const char *val, GNode *ctxt, int flags)
Var_Append(MAKEOVERRIDES, name, VAR_GLOBAL);
}
-
+ if (*name == '.') {
+ if (strcmp(name, SAVE_DOLLARS) == 0)
+ save_dollars = s2Boolean(val, save_dollars);
+ }
+
out:
- if (expanded_name != NULL)
- free(expanded_name);
+ free(expanded_name);
if (v != NULL)
VarFreeEnv(v, TRUE);
}
@@ -1022,7 +1047,7 @@ Var_Append(const char *name, const char *val, GNode *ctxt)
char *expanded_name = NULL;
if (strchr(name, '$') != NULL) {
- expanded_name = Var_Subst(NULL, name, ctxt, 0);
+ expanded_name = Var_Subst(NULL, name, ctxt, VARF_WANTRES);
if (expanded_name[0] == 0) {
if (DEBUG(VAR)) {
fprintf(debug_file, "Var_Append(\"%s\", \"%s\", ...) "
@@ -1060,8 +1085,7 @@ Var_Append(const char *name, const char *val, GNode *ctxt)
Hash_SetValue(h, v);
}
}
- if (expanded_name != NULL)
- free(expanded_name);
+ free(expanded_name);
}
/*-
@@ -1088,12 +1112,10 @@ Var_Exists(const char *name, GNode *ctxt)
char *cp;
if ((cp = strchr(name, '$')) != NULL) {
- cp = Var_Subst(NULL, name, ctxt, FALSE);
+ cp = Var_Subst(NULL, name, ctxt, VARF_WANTRES);
}
v = VarFind(cp ? cp : name, ctxt, FIND_CMD|FIND_GLOBAL|FIND_ENV);
- if (cp != NULL) {
- free(cp);
- }
+ free(cp);
if (v == NULL) {
return(FALSE);
} else {
@@ -1388,7 +1410,7 @@ VarSYSVMatch(GNode *ctx, Var_Parse_State *vpstate,
addSpace = TRUE;
if ((ptr = Str_SYSVMatch(word, pat->lhs, &len)) != NULL) {
- varexp = Var_Subst(NULL, pat->rhs, ctx, 0);
+ varexp = Var_Subst(NULL, pat->rhs, ctx, VARF_WANTRES);
Str_SYSVSubst(buf, varexp, ptr, len);
free(varexp);
} else {
@@ -1628,14 +1650,14 @@ VarSubstitute(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate,
*-----------------------------------------------------------------------
*/
static void
-VarREError(int errnum, regex_t *pat, const char *str)
+VarREError(int reerr, regex_t *pat, const char *str)
{
char *errbuf;
int errlen;
- errlen = regerror(errnum, pat, 0, 0);
+ errlen = regerror(reerr, pat, 0, 0);
errbuf = bmake_malloc(errlen);
- regerror(errnum, pat, errbuf, errlen);
+ regerror(reerr, pat, errbuf, errlen);
Error("%s: %s", str, errbuf);
free(errbuf);
}
@@ -1808,7 +1830,7 @@ VarLoopExpand(GNode *ctx MAKE_ATTR_UNUSED,
if (word && *word) {
Var_Set(loop->tvar, word, loop->ctxt, VAR_NO_EXPORT);
- s = Var_Subst(NULL, loop->str, loop->ctxt, loop->errnum);
+ s = Var_Subst(NULL, loop->str, loop->ctxt, loop->errnum | VARF_WANTRES);
if (s != NULL && *s != '\0') {
if (addSpace && *s != '\n')
Buf_AddByte(buf, ' ');
@@ -2142,13 +2164,14 @@ VarUniq(const char *str)
*/
static char *
VarGetPattern(GNode *ctxt, Var_Parse_State *vpstate MAKE_ATTR_UNUSED,
- int errnum, const char **tstr, int delim, int *flags,
+ int flags, const char **tstr, int delim, int *vflags,
int *length, VarPattern *pattern)
{
const char *cp;
char *rstr;
Buffer buf;
int junk;
+ int errnum = flags & VARF_UNDEFERR;
Buf_Init(&buf, 0);
if (length == NULL)
@@ -2170,16 +2193,16 @@ VarGetPattern(GNode *ctxt, Var_Parse_State *vpstate MAKE_ATTR_UNUSED,
cp++;
} else if (*cp == '$') {
if (cp[1] == delim) {
- if (flags == NULL)
+ if (vflags == NULL)
Buf_AddByte(&buf, *cp);
else
/*
* Unescaped $ at end of pattern => anchor
* pattern at end.
*/
- *flags |= VAR_MATCH_END;
+ *vflags |= VAR_MATCH_END;
} else {
- if (flags == NULL || (*flags & VAR_NOSUBST) == 0) {
+ if (vflags == NULL || (*vflags & VAR_NOSUBST) == 0) {
char *cp2;
int len;
void *freeIt;
@@ -2189,10 +2212,10 @@ VarGetPattern(GNode *ctxt, Var_Parse_State *vpstate MAKE_ATTR_UNUSED,
* delimiter, assume it's a variable
* substitution and recurse.
*/
- cp2 = Var_Parse(cp, ctxt, errnum, &len, &freeIt);
+ cp2 = Var_Parse(cp, ctxt, errnum | VARF_WANTRES, &len,
+ &freeIt);
Buf_AddBytes(&buf, strlen(cp2), cp2);
- if (freeIt)
- free(freeIt);
+ free(freeIt);
cp += len - 1;
} else {
const char *cp2 = &cp[1];
@@ -2245,7 +2268,7 @@ VarGetPattern(GNode *ctxt, Var_Parse_State *vpstate MAKE_ATTR_UNUSED,
/*-
*-----------------------------------------------------------------------
* VarQuote --
- * Quote shell meta-characters in the string
+ * Quote shell meta-characters and space characters in the string
*
* Results:
* The quoted string
@@ -2260,29 +2283,25 @@ VarQuote(char *str)
{
Buffer buf;
- /* This should cover most shells :-( */
- static const char meta[] = "\n \t'`\";&<>()|*?{}[]\\$!#^~";
const char *newline;
- size_t len, nlen;
+ size_t nlen;
if ((newline = Shell_GetNewline()) == NULL)
newline = "\\\n";
nlen = strlen(newline);
Buf_Init(&buf, 0);
- while (*str != '\0') {
- if ((len = strcspn(str, meta)) != 0) {
- Buf_AddBytes(&buf, len, str);
- str += len;
- } else if (*str == '\n') {
+
+ for (; *str != '\0'; str++) {
+ if (*str == '\n') {
Buf_AddBytes(&buf, nlen, newline);
- ++str;
- } else {
- Buf_AddByte(&buf, '\\');
- Buf_AddByte(&buf, *str);
- ++str;
+ continue;
}
+ if (isspace((unsigned char)*str) || ismeta((unsigned char)*str))
+ Buf_AddByte(&buf, '\\');
+ Buf_AddByte(&buf, *str);
}
+
str = Buf_Destroy(&buf, FALSE);
if (DEBUG(VAR))
fprintf(debug_file, "QuoteMeta: [%s]\n", str);
@@ -2313,7 +2332,7 @@ VarHash(char *str)
Buffer buf;
size_t len, len2;
unsigned char *ustr = (unsigned char *)str;
- uint32_t h, k, c1, c2;
+ unsigned int h, k, c1, c2;
h = 0x971e137bU;
c1 = 0x95543787U;
@@ -2467,7 +2486,7 @@ VarStrftime(const char *fmt, int zulu)
static char *
ApplyModifiers(char *nstr, const char *tstr,
int startc, int endc,
- Var *v, GNode *ctxt, Boolean errnum,
+ Var *v, GNode *ctxt, int flags,
int *lengthPtr, void **freePtr)
{
const char *start;
@@ -2498,7 +2517,7 @@ ApplyModifiers(char *nstr, const char *tstr,
int rlen;
int c;
- rval = Var_Parse(tstr, ctxt, errnum, &rlen, &freeIt);
+ rval = Var_Parse(tstr, ctxt, flags, &rlen, &freeIt);
/*
* If we have not parsed up to endc or ':',
@@ -2508,8 +2527,7 @@ ApplyModifiers(char *nstr, const char *tstr,
(c = tstr[rlen]) != '\0' &&
c != ':' &&
c != endc) {
- if (freeIt)
- free(freeIt);
+ free(freeIt);
goto apply_mods;
}
@@ -2524,18 +2542,15 @@ ApplyModifiers(char *nstr, const char *tstr,
int used;
nstr = ApplyModifiers(nstr, rval,
- 0, 0,
- v, ctxt, errnum, &used, freePtr);
+ 0, 0, v, ctxt, flags, &used, freePtr);
if (nstr == var_Error
- || (nstr == varNoError && errnum == 0)
+ || (nstr == varNoError && (flags & VARF_UNDEFERR) == 0)
|| strlen(rval) != (size_t) used) {
- if (freeIt)
- free(freeIt);
+ free(freeIt);
goto out; /* error already reported */
}
}
- if (freeIt)
- free(freeIt);
+ free(freeIt);
if (*tstr == ':')
tstr++;
else if (!*tstr && endc) {
@@ -2564,6 +2579,7 @@ ApplyModifiers(char *nstr, const char *tstr,
char *sv_name;
VarPattern pattern;
int how;
+ int vflags;
if (v->name[0] == 0)
goto bad_modifier;
@@ -2599,8 +2615,9 @@ ApplyModifiers(char *nstr, const char *tstr,
delim = startc == PROPEN ? PRCLOSE : BRCLOSE;
pattern.flags = 0;
- pattern.rhs = VarGetPattern(ctxt, &parsestate, errnum,
- &cp, delim, NULL,
+ vflags = (flags & VARF_WANTRES) ? 0 : VAR_NOSUBST;
+ pattern.rhs = VarGetPattern(ctxt, &parsestate, flags,
+ &cp, delim, &vflags,
&pattern.rightLen,
NULL);
if (v->flags & VAR_JUNK) {
@@ -2614,26 +2631,27 @@ ApplyModifiers(char *nstr, const char *tstr,
termc = *--cp;
delim = '\0';
- switch (how) {
- case '+':
- Var_Append(v->name, pattern.rhs, v_ctxt);
- break;
- case '!':
- newStr = Cmd_Exec(pattern.rhs, &emsg);
- if (emsg)
- Error(emsg, nstr);
- else
- Var_Set(v->name, newStr, v_ctxt, 0);
- if (newStr)
+ if (flags & VARF_WANTRES) {
+ switch (how) {
+ case '+':
+ Var_Append(v->name, pattern.rhs, v_ctxt);
+ break;
+ case '!':
+ newStr = Cmd_Exec(pattern.rhs, &emsg);
+ if (emsg)
+ Error(emsg, nstr);
+ else
+ Var_Set(v->name, newStr, v_ctxt, 0);
free(newStr);
- break;
- case '?':
- if ((v->flags & VAR_JUNK) == 0)
break;
- /* FALLTHROUGH */
- default:
- Var_Set(v->name, pattern.rhs, v_ctxt, 0);
- break;
+ case '?':
+ if ((v->flags & VAR_JUNK) == 0)
+ break;
+ /* FALLTHROUGH */
+ default:
+ Var_Set(v->name, pattern.rhs, v_ctxt, 0);
+ break;
+ }
}
free(UNCONST(pattern.rhs));
newStr = varNoError;
@@ -2644,29 +2662,30 @@ ApplyModifiers(char *nstr, const char *tstr,
case '@':
{
VarLoop_t loop;
- int flags = VAR_NOSUBST;
+ int vflags = VAR_NOSUBST;
cp = ++tstr;
delim = '@';
- if ((loop.tvar = VarGetPattern(ctxt, &parsestate, errnum,
+ if ((loop.tvar = VarGetPattern(ctxt, &parsestate, flags,
&cp, delim,
- &flags, &loop.tvarLen,
+ &vflags, &loop.tvarLen,
NULL)) == NULL)
goto cleanup;
- if ((loop.str = VarGetPattern(ctxt, &parsestate, errnum,
+ if ((loop.str = VarGetPattern(ctxt, &parsestate, flags,
&cp, delim,
- &flags, &loop.strLen,
+ &vflags, &loop.strLen,
NULL)) == NULL)
goto cleanup;
termc = *cp;
delim = '\0';
- loop.errnum = errnum;
+ loop.errnum = flags & VARF_UNDEFERR;
loop.ctxt = ctxt;
newStr = VarModify(ctxt, &parsestate, nstr, VarLoopExpand,
&loop);
+ Var_Delete(loop.tvar, ctxt);
free(loop.tvar);
free(loop.str);
break;
@@ -2675,8 +2694,19 @@ ApplyModifiers(char *nstr, const char *tstr,
case 'U':
{
Buffer buf; /* Buffer for patterns */
- int wantit; /* want data in buffer */
-
+ int nflags;
+
+ if (flags & VARF_WANTRES) {
+ int wantres;
+ if (*tstr == 'U')
+ wantres = ((v->flags & VAR_JUNK) != 0);
+ else
+ wantres = ((v->flags & VAR_JUNK) == 0);
+ nflags = flags & ~VARF_WANTRES;
+ if (wantres)
+ nflags |= VARF_WANTRES;
+ } else
+ nflags = flags;
/*
* Pass through tstr looking for 1) escaped delimiters,
* '$'s and backslashes (place the escaped character in
@@ -2705,10 +2735,9 @@ ApplyModifiers(char *nstr, const char *tstr,
int len;
void *freeIt;
- cp2 = Var_Parse(cp, ctxt, errnum, &len, &freeIt);
+ cp2 = Var_Parse(cp, ctxt, nflags, &len, &freeIt);
Buf_AddBytes(&buf, strlen(cp2), cp2);
- if (freeIt)
- free(freeIt);
+ free(freeIt);
cp += len - 1;
} else {
Buf_AddByte(&buf, *cp);
@@ -2717,13 +2746,9 @@ ApplyModifiers(char *nstr, const char *tstr,
termc = *cp;
- if (*tstr == 'U')
- wantit = ((v->flags & VAR_JUNK) != 0);
- else
- wantit = ((v->flags & VAR_JUNK) == 0);
if ((v->flags & VAR_JUNK) != 0)
v->flags |= VAR_KEEP;
- if (wantit) {
+ if (nflags & VARF_WANTRES) {
newStr = Buf_Destroy(&buf, FALSE);
} else {
newStr = nstr;
@@ -2768,14 +2793,17 @@ ApplyModifiers(char *nstr, const char *tstr,
pattern.flags = 0;
delim = '!';
-
+ emsg = NULL;
cp = ++tstr;
- if ((pattern.rhs = VarGetPattern(ctxt, &parsestate, errnum,
+ if ((pattern.rhs = VarGetPattern(ctxt, &parsestate, flags,
&cp, delim,
NULL, &pattern.rightLen,
NULL)) == NULL)
goto cleanup;
- newStr = Cmd_Exec(pattern.rhs, &emsg);
+ if (flags & VARF_WANTRES)
+ newStr = Cmd_Exec(pattern.rhs, &emsg);
+ else
+ newStr = varNoError;
free(UNCONST(pattern.rhs));
if (emsg)
Error(emsg, nstr);
@@ -2800,7 +2828,7 @@ ApplyModifiers(char *nstr, const char *tstr,
cp = tstr+1; /* point to char after '[' */
delim = ']'; /* look for closing ']' */
estr = VarGetPattern(ctxt, &parsestate,
- errnum, &cp, delim,
+ flags, &cp, delim,
NULL, NULL, NULL);
if (estr == NULL)
goto cleanup; /* report missing ']' */
@@ -3151,7 +3179,7 @@ ApplyModifiers(char *nstr, const char *tstr,
* expand it.
*/
cp2 = pattern;
- pattern = Var_Subst(NULL, cp2, ctxt, errnum);
+ pattern = Var_Subst(NULL, cp2, ctxt, flags | VARF_WANTRES);
free(cp2);
}
if (DEBUG(VAR))
@@ -3187,14 +3215,14 @@ ApplyModifiers(char *nstr, const char *tstr,
}
cp = tstr;
- if ((pattern.lhs = VarGetPattern(ctxt, &parsestate, errnum,
+ if ((pattern.lhs = VarGetPattern(ctxt, &parsestate, flags,
&cp, delim,
&pattern.flags,
&pattern.leftLen,
NULL)) == NULL)
goto cleanup;
- if ((pattern.rhs = VarGetPattern(ctxt, &parsestate, errnum,
+ if ((pattern.rhs = VarGetPattern(ctxt, &parsestate, flags,
&cp, delim, NULL,
&pattern.rightLen,
&pattern)) == NULL)
@@ -3237,31 +3265,47 @@ ApplyModifiers(char *nstr, const char *tstr,
{
VarPattern pattern;
Boolean value;
-
+ int cond_rc;
+ int lhs_flags, rhs_flags;
+
/* find ':', and then substitute accordingly */
-
+ if (flags & VARF_WANTRES) {
+ cond_rc = Cond_EvalExpression(NULL, v->name, &value, 0, FALSE);
+ if (cond_rc == COND_INVALID) {
+ lhs_flags = rhs_flags = VAR_NOSUBST;
+ } else if (value) {
+ lhs_flags = 0;
+ rhs_flags = VAR_NOSUBST;
+ } else {
+ lhs_flags = VAR_NOSUBST;
+ rhs_flags = 0;
+ }
+ } else {
+ /* we are just consuming and discarding */
+ cond_rc = value = 0;
+ lhs_flags = rhs_flags = VAR_NOSUBST;
+ }
pattern.flags = 0;
cp = ++tstr;
delim = ':';
- if ((pattern.lhs = VarGetPattern(ctxt, &parsestate, errnum,
- &cp, delim, NULL,
+ if ((pattern.lhs = VarGetPattern(ctxt, &parsestate, flags,
+ &cp, delim, &lhs_flags,
&pattern.leftLen,
NULL)) == NULL)
goto cleanup;
/* BROPEN or PROPEN */
delim = endc;
- if ((pattern.rhs = VarGetPattern(ctxt, &parsestate, errnum,
- &cp, delim, NULL,
+ if ((pattern.rhs = VarGetPattern(ctxt, &parsestate, flags,
+ &cp, delim, &rhs_flags,
&pattern.rightLen,
NULL)) == NULL)
goto cleanup;
termc = *--cp;
delim = '\0';
- if (Cond_EvalExpression(NULL, v->name, &value, 0)
- == COND_INVALID) {
+ if (cond_rc == COND_INVALID) {
Error("Bad conditional expression `%s' in %s?%s:%s",
v->name, v->name, pattern.lhs, pattern.rhs);
goto cleanup;
@@ -3294,12 +3338,12 @@ ApplyModifiers(char *nstr, const char *tstr,
cp = tstr;
- if ((re = VarGetPattern(ctxt, &parsestate, errnum, &cp, delim,
+ if ((re = VarGetPattern(ctxt, &parsestate, flags, &cp, delim,
NULL, NULL, NULL)) == NULL)
goto cleanup;
if ((pattern.replace = VarGetPattern(ctxt, &parsestate,
- errnum, &cp, delim, NULL,
+ flags, &cp, delim, NULL,
NULL, NULL)) == NULL){
free(re);
goto cleanup;
@@ -3423,9 +3467,12 @@ ApplyModifiers(char *nstr, const char *tstr,
case 's':
if (tstr[1] == 'h' && (tstr[2] == endc || tstr[2] == ':')) {
const char *emsg;
- newStr = Cmd_Exec(nstr, &emsg);
- if (emsg)
- Error(emsg, nstr);
+ if (flags & VARF_WANTRES) {
+ newStr = Cmd_Exec(nstr, &emsg);
+ if (emsg)
+ Error(emsg, nstr);
+ } else
+ newStr = varNoError;
cp = tstr + 2;
termc = *cp;
break;
@@ -3473,12 +3520,12 @@ ApplyModifiers(char *nstr, const char *tstr,
delim='=';
cp = tstr;
if ((pattern.lhs = VarGetPattern(ctxt, &parsestate,
- errnum, &cp, delim, &pattern.flags,
+ flags, &cp, delim, &pattern.flags,
&pattern.leftLen, NULL)) == NULL)
goto cleanup;
delim = endc;
if ((pattern.rhs = VarGetPattern(ctxt, &parsestate,
- errnum, &cp, delim, NULL, &pattern.rightLen,
+ flags, &cp, delim, NULL, &pattern.rightLen,
&pattern)) == NULL)
goto cleanup;
@@ -3546,10 +3593,8 @@ ApplyModifiers(char *nstr, const char *tstr,
if (delim != '\0')
Error("Unclosed substitution for %s (%c missing)",
v->name, delim);
- if (*freePtr) {
- free(*freePtr);
- *freePtr = NULL;
- }
+ free(*freePtr);
+ *freePtr = NULL;
return (var_Error);
}
@@ -3563,7 +3608,9 @@ ApplyModifiers(char *nstr, const char *tstr,
* Input:
* str The string to parse
* ctxt The context for the variable
- * errnum TRUE if undefined variables are an error
+ * flags VARF_UNDEFERR if undefineds are an error
+ * VARF_WANTRES if we actually want the result
+ * VARF_ASSIGN if we are in a := assignment
* lengthPtr OUT: The length of the specification
* freePtr OUT: Non-NULL if caller should free *freePtr
*
@@ -3582,8 +3629,8 @@ ApplyModifiers(char *nstr, const char *tstr,
*/
/* coverity[+alloc : arg-*4] */
char *
-Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr,
- void **freePtr)
+Var_Parse(const char *str, GNode *ctxt, int flags,
+ int *lengthPtr, void **freePtr)
{
const char *tstr; /* Pointer into str */
Var *v; /* Variable in invocation */
@@ -3599,14 +3646,13 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr,
* expanding it in a non-local context. This
* is done to support dynamic sources. The
* result is just the invocation, unaltered */
- Var_Parse_State parsestate; /* Flags passed to helper functions */
+ const char *extramodifiers; /* extra modifiers to apply first */
char name[2];
*freePtr = NULL;
+ extramodifiers = NULL;
dynamic = FALSE;
start = str;
- parsestate.oneBigWord = FALSE;
- parsestate.varSpace = ' '; /* word separator */
startc = str[1];
if (startc != PROPEN && startc != BROPEN) {
@@ -3652,7 +3698,7 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr,
/*
* Error
*/
- return (errnum ? var_Error : varNoError);
+ return (flags & VARF_UNDEFERR) ? var_Error : varNoError;
} else {
haveModifier = FALSE;
tstr = &str[1];
@@ -3689,12 +3735,11 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr,
if (*tstr == '$') {
int rlen;
void *freeIt;
- char *rval = Var_Parse(tstr, ctxt, errnum, &rlen, &freeIt);
+ char *rval = Var_Parse(tstr, ctxt, flags, &rlen, &freeIt);
if (rval != NULL) {
Buf_AddBytes(&buf, strlen(rval), rval);
}
- if (freeIt)
- free(freeIt);
+ free(freeIt);
tstr += rlen - 1;
}
else
@@ -3734,7 +3779,7 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr,
*/
if ((v == NULL) && (ctxt != VAR_CMD) && (ctxt != VAR_GLOBAL) &&
(vlen == 2) && (str[1] == 'F' || str[1] == 'D') &&
- strchr("@%*!<>", str[0]) != NULL) {
+ strchr("@%?*!<>", str[0]) != NULL) {
/*
* Well, it's local -- go look for it.
*/
@@ -3743,29 +3788,12 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr,
v = VarFind(name, ctxt, 0);
if (v != NULL) {
- /*
- * No need for nested expansion or anything, as we're
- * the only one who sets these things and we sure don't
- * but nested invocations in them...
- */
- nstr = Buf_GetAll(&v->val, NULL);
-
if (str[1] == 'D') {
- nstr = VarModify(ctxt, &parsestate, nstr, VarHead,
- NULL);
- } else {
- nstr = VarModify(ctxt, &parsestate, nstr, VarTail,
- NULL);
+ extramodifiers = "H:";
+ }
+ else { /* F */
+ extramodifiers = "T:";
}
- /*
- * Resulting string is dynamically allocated, so
- * tell caller to free it.
- */
- *freePtr = nstr;
- *lengthPtr = tstr-start+1;
- Buf_Destroy(&buf, TRUE);
- VarFreeEnv(v, TRUE);
- return nstr;
}
}
@@ -3820,7 +3848,7 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr,
return(pstr);
} else {
Buf_Destroy(&buf, TRUE);
- return (errnum ? var_Error : varNoError);
+ return (flags & VARF_UNDEFERR) ? var_Error : varNoError;
}
} else {
/*
@@ -3854,22 +3882,33 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr,
*/
nstr = Buf_GetAll(&v->val, NULL);
if (strchr(nstr, '$') != NULL) {
- nstr = Var_Subst(NULL, nstr, ctxt, errnum);
+ nstr = Var_Subst(NULL, nstr, ctxt, flags);
*freePtr = nstr;
}
v->flags &= ~VAR_IN_USE;
- if ((nstr != NULL) && haveModifier) {
+ if ((nstr != NULL) && (haveModifier || extramodifiers != NULL)) {
+ void *extraFree;
int used;
- /*
- * Skip initial colon.
- */
- tstr++;
- nstr = ApplyModifiers(nstr, tstr, startc, endc,
- v, ctxt, errnum, &used, freePtr);
- tstr += used;
+ extraFree = NULL;
+ if (extramodifiers != NULL) {
+ nstr = ApplyModifiers(nstr, extramodifiers, '(', ')',
+ v, ctxt, flags, &used, &extraFree);
+ }
+
+ if (haveModifier) {
+ /* Skip initial colon. */
+ tstr++;
+
+ nstr = ApplyModifiers(nstr, tstr, startc, endc,
+ v, ctxt, flags, &used, freePtr);
+ tstr += used;
+ free(extraFree);
+ } else {
+ *freePtr = extraFree;
+ }
}
if (*tstr) {
*lengthPtr = tstr - start + 1;
@@ -3905,7 +3944,7 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr,
nstr = bmake_strndup(start, *lengthPtr);
*freePtr = nstr;
} else {
- nstr = errnum ? var_Error : varNoError;
+ nstr = (flags & VARF_UNDEFERR) ? var_Error : varNoError;
}
}
if (nstr != Buf_GetAll(&v->val, NULL))
@@ -3920,14 +3959,16 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr,
*-----------------------------------------------------------------------
* Var_Subst --
* Substitute for all variables in the given string in the given context
- * If undefErr is TRUE, Parse_Error will be called when an undefined
+ * If flags & VARF_UNDEFERR, Parse_Error will be called when an undefined
* variable is encountered.
*
* Input:
* var Named variable || NULL for all
* str the string which to substitute
* ctxt the context wherein to find variables
- * undefErr TRUE if undefineds are an error
+ * flags VARF_UNDEFERR if undefineds are an error
+ * VARF_WANTRES if we actually want the result
+ * VARF_ASSIGN if we are in a := assignment
*
* Results:
* The resulting string.
@@ -3937,7 +3978,7 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr,
*-----------------------------------------------------------------------
*/
char *
-Var_Subst(const char *var, const char *str, GNode *ctxt, Boolean undefErr)
+Var_Subst(const char *var, const char *str, GNode *ctxt, int flags)
{
Buffer buf; /* Buffer for forming things */
char *val; /* Value to substitute for a variable */
@@ -3961,6 +4002,8 @@ Var_Subst(const char *var, const char *str, GNode *ctxt, Boolean undefErr)
* In such a case, we skip over the escape character and store the
* dollar sign into the buffer directly.
*/
+ if (save_dollars && (flags & VARF_ASSIGN))
+ Buf_AddByte(&buf, *str);
str++;
Buf_AddByte(&buf, *str);
str++;
@@ -4035,7 +4078,7 @@ Var_Subst(const char *var, const char *str, GNode *ctxt, Boolean undefErr)
continue;
}
- val = Var_Parse(str, ctxt, undefErr, &length, &freeIt);
+ val = Var_Parse(str, ctxt, flags, &length, &freeIt);
/*
* When we come down here, val should either point to the
@@ -4052,7 +4095,7 @@ Var_Subst(const char *var, const char *str, GNode *ctxt, Boolean undefErr)
*/
if (oldVars) {
str += length;
- } else if (undefErr || val == var_Error) {
+ } else if ((flags & VARF_UNDEFERR) || val == var_Error) {
/*
* If variable is undefined, complain and skip the
* variable. The complaint will stop us from doing anything
@@ -4083,10 +4126,8 @@ Var_Subst(const char *var, const char *str, GNode *ctxt, Boolean undefErr)
Buf_AddBytes(&buf, length, val);
trailingBslash = length > 0 && val[length - 1] == '\\';
}
- if (freeIt) {
- free(freeIt);
- freeIt = NULL;
- }
+ free(freeIt);
+ freeIt = NULL;
}
}