1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-11-25 07:49:18 +00:00

Merge bmake-20211212

commit '2935fe8237c83c1dcb113dd5335733263e68e6fd'
This commit is contained in:
Simon J. Gerraty 2021-12-18 10:09:14 -08:00
commit 129043849f
166 changed files with 4801 additions and 1891 deletions

View File

@ -1,3 +1,234 @@
2021-12-15 Simon J Gerraty <sjg@beast.crufty.net>
* cond.c: fix mem leak in CondParser_Leaf
2021-12-12 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20211212
Merge with NetBSD make, pick up
o rename Parse_SetInput to Parse_PushInput
o remove remove period from end of error messages and warnings
to be more consistent
o arch.c: use simpler memory management for parsing archive members
o cond.c: rework and reduce recursion
o for.c: rename some functions to better reflect purpose
o suff.c: add Suff_NamesStr to provide .SUFFIXES as a string.
o var.c: in parse errors, mark whitespace more clearly
inline ParseEmptyArg into CondParser_FuncCallEmpty
minimize calls to LazyBuf_Get in ParseVarnameLong
treat .SUFFIXES as a read-only variable
2021-12-07 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20211207
Merge with NetBSD make, pick up
o inline HashIter_Init
o parse.c: inline common subexpression in ParseRawLine
o var.c: merge branches for modifiers ':D' and ':U'
extract common code into Expr_Words
extract common code into Expr_Str
move low-level implementation details out of Var_Parse
2021-12-06 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20211206
Merge with NetBSD make, pick up
o add unit-tests/varmod-loop-delete
o for.c: inline Str_Words - reduce memory allocation
o parse.c: do not try to expand fixed variable names
only allocate the name of an included file if necessary
clean up ParseInclude
o var.c: fix use-after-free in modifier ':@'
save a memory allocation in each modifier ':O' and ':u'
save a memory allocation in the modifier ':[...]'
in UnexportVars, replace Str_Words with Substring_Words to
reduce allocations and copying.
2021-12-04 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20211204
Merge with NetBSD make, pick up
o flesh out a number of tests
o replace enums with bitfields, this simplifies a lot of code.
o var.c: refactor ParseModifierPartSubst
2021-10-24 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20211024
Merge with NetBSD make, pick up
o Punt on write errors - ENOSPC etc.
2021-10-22 Simon J Gerraty <sjg@beast.crufty.net>
* configure.in: use_defshell, set both DEFSHELL_INDEX
and defshell_path if appropriate.
This makes it easier to use say the KSH specification with
and alternate path for the shell.
* configure.in compat.c: for SCO we need to force UseShell
* configure.in: SCO /bin/sh is not usable, provide a list of
alternatives for use as .SHELL.
We still have to mark some tests as broken, plus more if we end up
with ksh as .SHELL.
Issue a warning about skipped tests.
* boot-strap: leave TOOL_DIFF to configure
* configure.in: on SCO native cc is not usable,
gcc is to be found in /usr/gnu/bin
and while ancient is at least able to compile bmake.
Thus we add /usr/gnu/bin to PATH if it exists, and later
check if $CC would have been found via $PATH.
If not we set CC to the full path of $CC.
Also gnu diff is known to support -u, so if it exists use it.
* configure.in: move getopt to AC_REPLACE_FUNCS
also add AC_C_INLINE - in an attempt to compile using
native cc on SCO.
* configure.in: check for stresep as well as strsep, since we
define the later to the former if necessary, and if we have to
provide stresep we also need to provide a prototype.
* configure.in: we no longer need to worry about
sys/cdefs.h providing __RCSID which simplifies things quite a bit.
* make.h: make sure we have __RCSID
* unit-tests/Makefile.config.in: add TOOL_DIFF so configure
can control it.
2021-10-20 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION: 20211020
Merge with NetBSD make, pick up
o confirm sync of unit-tests
2021-10-18 Simon J Gerraty <sjg@beast.crufty.net>
* configure.in: check if timezone Europe/Berlin is supported
if not try UTC-1
* configure.in: if .OBJDIR is $srcdir/obj we need to create a
symlink unit-tests -> ../unit-tests/obj so that
unit-tests/Makefile.config is put in the right place.
* refine filtering of .OBJDIR in unit-tests
2021-10-16 Simon J Gerraty <sjg@beast.crufty.net>
* Fix unit-tests on Minix 3.2.0
o job.c: do not punt if read of token pipe fails for EAGAIN.
On Minix at least, we are not ready to read the childExitJob pipe
when poll says we are.
There should actually be no reason for this pipe to be
non-blocking, but while that works fine on {Net,Free}BSD it
breaks another test case on Minix.
o unit-tests/Makefile: deal with variants of error messages
and use of obj as .OBJDIR
2021-10-14 Simon J Gerraty <sjg@beast.crufty.net>
* configure.in: add sigaction to AC_REPLACE_FUNCS
we also need to check for sigaddset etc just for the benefit of
sigact.c
* Add sigact.c as sigaction.c so this "just works".
This should have been done back when bmake_signal started using
sigaction (I only just noticed that sigact.c wasn't here ;-)
Note: I no longer have access to any system where this would matter.
2021-10-13 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20211011
* Makefile: cleanup a little
* configure.in: check for sigsetmask
2021-10-01 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20211001
Merge with NetBSD make, pick up
o reduce locations reducing text size
o remove unnecessary const
o cond.c: fix lint warning on i386
do not allow unquoted 'left == right' after modifier ':?'
o hash.c: fix build for DEBUG_HASH_LOOKUP
o var.c: fix memory leak in error case of the ':?' modifier
2021-09-11 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20210911
Merge with NetBSD make, pick up
o var.c: replace remaining ModChain_ShouldEval with Expr_ShouldEval
2021-09-08 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20210906
Merge with NetBSD make, pick up
o more unit tests
o lint cleanup
o rename some functions to better fit purpose
o for.c: cleanup - remove unnecessary optimization
fix embedded newlines
o parse.c: correct case for CVS/RCS
2021-08-11 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20210808
Merge with NetBSD make, pick up
o var.c: remove redundant initialization in ApplyModifier_Order
* mk/options.mk: issue warning for incorrect usage
2021-08-03 Simon J Gerraty <sjg@beast.crufty.net>
* var.c: use long for :On if we don't have a 64bit int type
* VERSION (_MAKE_VERSION): 20210803
Merge with NetBSD make, pick up
o rework varmod-order tests to avoid qsort instability
o make.1: clarify :On entry
2021-07-31 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20210731
Merge with NetBSD make, pick up
o fix some lint issues
o more unit tests
o var.c: rework of ApplyModifier_Order
2021-07-30 Simon J Gerraty <sjg@beast.crufty.net>
* util.c: add strto*l if HAVE_STRTO*L not defined
* VERSION (_MAKE_VERSION): 20210730
Merge with NetBSD make, pick up
o var.c: add :On and :Orn for numeric sort
disabled if no 64bit type available.
o _strtol.h: to implement strto*l functions
2021-07-04 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20210704
Merge with NetBSD make, pick up
o unit-tests: fix some tests to be more portable
- job-output-null not all shells do the same number of write calls
- objdir-writable if TMPDIR is set; /tmp may not be usable
2021-07-01 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20210701
Merge with NetBSD make, pick up
o unit-tests: allow for BROKEN_TESTS to list TESTS to be skipped;
some tests just cannot work in some environments.
o buf.c: simpler upper bound for length in Buf_AddInt
o cond.c: fix grammar in error message for malformed conditional
o for.c: prevent newline injection (from ${.newline}) in .for loops
o var.c: use more practical data type in RegexReplace
(avoid need for %zu)
extract RegexReplace from ModifyWord_SubstRegex
2021-06-21 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20210621

View File

@ -7,6 +7,7 @@ PSD.doc/Makefile
PSD.doc/tutorial.ms
README
VERSION
_strtol.h
aclocal.m4
arch.c
bmake.1
@ -23,8 +24,6 @@ configure.in
dir.c
dir.h
dirname.c
enum.c
enum.h
filemon/filemon.h
filemon/filemon_dev.c
filemon/filemon_ktrace.c
@ -61,6 +60,8 @@ pathnames.h
ranlib.h
realpath.c
setenv.c
sigact.h
sigaction.c
sigcompat.c
str.c
str.h
@ -322,6 +323,8 @@ unit-tests/directive-for-escape.exp
unit-tests/directive-for-escape.mk
unit-tests/directive-for-generating-endif.exp
unit-tests/directive-for-generating-endif.mk
unit-tests/directive-for-if.exp
unit-tests/directive-for-if.mk
unit-tests/directive-for-lines.exp
unit-tests/directive-for-lines.mk
unit-tests/directive-for-null.exp
@ -684,6 +687,8 @@ unit-tests/varmod-l-name-to-value.exp
unit-tests/varmod-l-name-to-value.mk
unit-tests/varmod-localtime.exp
unit-tests/varmod-localtime.mk
unit-tests/varmod-loop-delete.exp
unit-tests/varmod-loop-delete.mk
unit-tests/varmod-loop-varname.exp
unit-tests/varmod-loop-varname.mk
unit-tests/varmod-loop.exp
@ -694,10 +699,14 @@ unit-tests/varmod-match.exp
unit-tests/varmod-match.mk
unit-tests/varmod-no-match.exp
unit-tests/varmod-no-match.mk
unit-tests/varmod-order-numeric.exp
unit-tests/varmod-order-numeric.mk
unit-tests/varmod-order-reverse.exp
unit-tests/varmod-order-reverse.mk
unit-tests/varmod-order-shuffle.exp
unit-tests/varmod-order-shuffle.mk
unit-tests/varmod-order-string.exp
unit-tests/varmod-order-string.mk
unit-tests/varmod-order.exp
unit-tests/varmod-order.mk
unit-tests/varmod-path.exp
@ -814,6 +823,8 @@ unit-tests/varname-dot-path.exp
unit-tests/varname-dot-path.mk
unit-tests/varname-dot-shell.exp
unit-tests/varname-dot-shell.mk
unit-tests/varname-dot-suffixes.exp
unit-tests/varname-dot-suffixes.mk
unit-tests/varname-dot-targets.exp
unit-tests/varname-dot-targets.mk
unit-tests/varname-empty.exp

View File

@ -1,4 +1,4 @@
# $Id: Makefile,v 1.114 2020/11/13 21:47:25 sjg Exp $
# $Id: Makefile,v 1.117 2021/12/04 18:51:30 sjg Exp $
PROG= bmake
@ -8,7 +8,6 @@ SRCS= \
compat.c \
cond.c \
dir.c \
enum.c \
for.c \
hash.c \
job.c \
@ -92,10 +91,11 @@ isBSD44:=${BSD44_LIST:M${OS}}
.if ${isBSD44} == ""
MANTARGET= cat
INSTALL?=${srcdir}/install-sh
.if (${MACHINE} == "sun386")
.if ${MACHINE} == "sun386"
# even I don't have one of these anymore :-)
CFLAGS+= -DPORTAR
.elif (${MACHINE} != "sunos")
.elif ${OS} != "SunOS"
# assume the worst
SRCS+= sigcompat.c
CFLAGS+= -DSIGNAL_FLAGS=SA_RESTART
.endif
@ -131,7 +131,7 @@ EXTRACT_MAN=no
MAN= ${PROG}.1
MAN1= ${MAN}
.if (${PROG} != "make")
.if ${PROG} != "make"
CLEANFILES+= my.history
.if make(${MAN}) || !exists(${srcdir}/${MAN})
my.history:
@ -189,11 +189,12 @@ main.o: ${srcdir}/VERSION
CONFIGURE_DEPS += ${.CURDIR}/VERSION
# we do not need or want the generated makefile
CONFIGURE_ARGS += --without-makefile
AUTOCONF_GENERATED_MAKEFILE = Makefile.config
.include <autoconf.mk>
.endif
SHARE_MK?=${SHAREDIR}/mk
MKSRC=${srcdir}/mk
INSTALL?=${srcdir}/install-sh
SHARE_MK ?= ${SHAREDIR}/mk
MKSRC = ${srcdir}/mk
INSTALL ?= ${srcdir}/install-sh
.if ${MK_INSTALL_MK} == "yes"
install: install-mk

View File

@ -4,7 +4,7 @@ _MAKE_VERSION?=@_MAKE_VERSION@
prefix?= @prefix@
srcdir= @srcdir@
CC?= @CC@
CC= @CC@
@force_machine@MACHINE?= @machine@
@force_machine_arch@MACHINE_ARCH?= @machine_arch@
DEFAULT_SYS_PATH?= @default_sys_path@

View File

@ -1,2 +1,2 @@
# keep this compatible with sh and make
_MAKE_VERSION=20210621
_MAKE_VERSION=20211212

213
contrib/bmake/_strtol.h Normal file
View File

@ -0,0 +1,213 @@
/* $NetBSD: _strtol.h,v 1.11 2017/07/06 21:08:44 joerg Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* 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.
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*
* Original version ID:
* NetBSD: src/lib/libc/locale/_wcstol.h,v 1.2 2003/08/07 16:43:03 agc Exp
*/
/*
* function template for strtol, strtoll and strtoimax.
*
* parameters:
* _FUNCNAME : function name
* __INT : return type
* __INT_MIN : lower limit of the return type
* __INT_MAX : upper limit of the return type
*/
#if defined(_KERNEL) || defined(_STANDALONE) || defined(HAVE_NBTOOL_CONFIG_H) || defined(BCS_ONLY)
__INT
_FUNCNAME(const char *nptr, char **endptr, int base)
#else
#include <locale.h>
#include "setlocale_local.h"
#define INT_FUNCNAME_(pre, name, post) pre ## name ## post
#define INT_FUNCNAME(pre, name, post) INT_FUNCNAME_(pre, name, post)
static __INT
INT_FUNCNAME(_int_, _FUNCNAME, _l)(const char *nptr, char **endptr,
int base, locale_t loc)
#endif
{
const char *s;
__INT acc, cutoff;
unsigned char c;
int i, neg, any, cutlim;
_DIAGASSERT(nptr != NULL);
/* endptr may be NULL */
/* check base value */
if (base && (base < 2 || base > 36)) {
#if !defined(_KERNEL) && !defined(_STANDALONE)
errno = EINVAL;
if (endptr != NULL)
/* LINTED interface specification */
*endptr = __UNCONST(nptr);
return 0;
#else
panic("%s: invalid base %d", __func__, base);
#endif
}
/*
* Skip white space and pick up leading +/- sign if any.
* If base is 0, allow 0x for hex and 0 for octal, else
* assume decimal; if base is already 16, allow 0x.
*/
s = nptr;
#if defined(_KERNEL) || defined(_STANDALONE) || \
defined(HAVE_NBTOOL_CONFIG_H) || defined(BCS_ONLY)
do {
c = *s++;
} while (isspace(c));
#else
do {
c = *s++;
} while (isspace_l(c, loc));
#endif
if (c == '-') {
neg = 1;
c = *s++;
} else {
neg = 0;
if (c == '+')
c = *s++;
}
if ((base == 0 || base == 16) &&
c == '0' && (*s == 'x' || *s == 'X') &&
((s[1] >= '0' && s[1] <= '9') ||
(s[1] >= 'a' && s[1] <= 'f') ||
(s[1] >= 'A' && s[1] <= 'F'))) {
c = s[1];
s += 2;
base = 16;
#if 0
} else if ((base == 0 || base == 2) &&
c == '0' && (*s == 'b' || *s == 'B') &&
(s[1] >= '0' && s[1] <= '1')) {
c = s[1];
s += 2;
base = 2;
#endif
} else if (base == 0)
base = (c == '0' ? 8 : 10);
/*
* Compute the cutoff value between legal numbers and illegal
* numbers. That is the largest legal value, divided by the
* base. An input number that is greater than this value, if
* followed by a legal input character, is too big. One that
* is equal to this value may be valid or not; the limit
* between valid and invalid numbers is then based on the last
* digit. For instance, if the range for longs is
* [-2147483648..2147483647] and the input base is 10,
* cutoff will be set to 214748364 and cutlim to either
* 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
* a value > 214748364, or equal but the next digit is > 7 (or 8),
* the number is too big, and we will return a range error.
*
* Set any if any `digits' consumed; make it negative to indicate
* overflow.
*/
cutoff = (__INT)(neg ? __INT_MIN : __INT_MAX);
cutlim = (int)(cutoff % base);
cutoff /= base;
if (neg) {
if (cutlim > 0) {
cutlim -= base;
cutoff += 1;
}
cutlim = -cutlim;
}
for (acc = 0, any = 0;; c = *s++) {
if (c >= '0' && c <= '9')
i = c - '0';
else if (c >= 'a' && c <= 'z')
i = (c - 'a') + 10;
else if (c >= 'A' && c <= 'Z')
i = (c - 'A') + 10;
else
break;
if (i >= base)
break;
if (any < 0)
continue;
if (neg) {
if (acc < cutoff || (acc == cutoff && i > cutlim)) {
acc = __INT_MIN;
#if !defined(_KERNEL) && !defined(_STANDALONE)
any = -1;
errno = ERANGE;
#else
any = 0;
break;
#endif
} else {
any = 1;
acc *= base;
acc -= i;
}
} else {
if (acc > cutoff || (acc == cutoff && i > cutlim)) {
acc = __INT_MAX;
#if !defined(_KERNEL) && !defined(_STANDALONE)
any = -1;
errno = ERANGE;
#else
any = 0;
break;
#endif
} else {
any = 1;
acc *= base;
acc += i;
}
}
}
if (endptr != NULL)
/* LINTED interface specification */
*endptr = __UNCONST(any ? s - 1 : nptr);
return(acc);
}
#if !defined(_KERNEL) && !defined(_STANDALONE) && \
!defined(HAVE_NBTOOL_CONFIG_H) && !defined(BCS_ONLY)
__INT
_FUNCNAME(const char *nptr, char **endptr, int base)
{
return INT_FUNCNAME(_int_, _FUNCNAME, _l)(nptr, endptr, base, _current_locale());
}
__INT
INT_FUNCNAME(, _FUNCNAME, _l)(const char *nptr, char **endptr, int base, locale_t loc)
{
return INT_FUNCNAME(_int_, _FUNCNAME, _l)(nptr, endptr, base, loc);
}
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: arch.c,v 1.200 2021/05/30 21:16:54 rillig Exp $ */
/* $NetBSD: arch.c,v 1.205 2021/12/12 22:41:47 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@ -147,7 +147,7 @@ struct ar_hdr {
#include "dir.h"
/* "@(#)arch.c 8.2 (Berkeley) 1/2/94" */
MAKE_RCSID("$NetBSD: arch.c,v 1.200 2021/05/30 21:16:54 rillig Exp $");
MAKE_RCSID("$NetBSD: arch.c,v 1.205 2021/12/12 22:41:47 rillig Exp $");
typedef struct List ArchList;
typedef struct ListNode ArchListNode;
@ -250,7 +250,7 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *scope)
char *cp; /* Pointer into line */
GNode *gn; /* New node */
MFStr libName; /* Library-part of specification */
char *memName; /* Member-part of specification */
FStr mem; /* Member-part of specification */
char saveChar; /* Ending delimiter of member-name */
bool expandLibName; /* Whether the parsed libName contains
* variable expressions that need to be
@ -301,7 +301,7 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *scope)
pp_skip_whitespace(&cp);
memName = cp;
mem = FStr_InitRefer(cp);
while (*cp != '\0' && *cp != ')' && !ch_isspace(*cp)) {
if (*cp == '$') {
/* Expand nested variable expressions. */
@ -342,7 +342,7 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *scope)
/*
* If we didn't move anywhere, we must be done
*/
if (cp == memName)
if (cp == mem.str)
break;
saveChar = *cp;
@ -363,22 +363,22 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *scope)
*/
if (doSubst) {
char *fullName;
char *p;
char *unexpandedMemName = memName;
char *p, *expandedMem;
const char *unexpandedMem = mem.str;
(void)Var_Subst(memName, scope, VARE_UNDEFERR,
&memName);
(void)Var_Subst(mem.str, scope, VARE_UNDEFERR,
&expandedMem);
/* TODO: handle errors */
mem = FStr_InitOwn(expandedMem);
/*
* Now form an archive spec and recurse to deal with
* nested variables and multi-word variable values.
*/
fullName = FullName(libName.str, memName);
fullName = FullName(libName.str, mem.str);
p = fullName;
if (strchr(memName, '$') != NULL &&
strcmp(memName, unexpandedMemName) == 0) {
if (strcmp(mem.str, unexpandedMem) == 0) {
/*
* Must contain dynamic sources, so we can't
* deal with it now. Just create an ARCHV node
@ -398,9 +398,9 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *scope)
free(fullName);
/* XXX: does unexpandedMemName leak? */
} else if (Dir_HasWildcards(memName)) {
} else if (Dir_HasWildcards(mem.str)) {
StringList members = LST_INIT;
SearchPath_Expand(&dirSearchPath, memName, &members);
SearchPath_Expand(&dirSearchPath, mem.str, &members);
while (!Lst_IsEmpty(&members)) {
char *member = Lst_Dequeue(&members);
@ -416,7 +416,7 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *scope)
Lst_Done(&members);
} else {
char *fullname = FullName(libName.str, memName);
char *fullname = FullName(libName.str, mem.str);
gn = Targ_GetNode(fullname);
free(fullname);
@ -430,8 +430,7 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *scope)
gn->type |= OP_ARCHV;
Lst_Append(gns, gn);
}
if (doSubst)
free(memName);
FStr_Done(&mem);
*cp = saveChar;
}
@ -600,14 +599,14 @@ ArchStatMember(const char *archive, const char *member, bool addToCache)
if (strncmp(memName, AR_EFMT1, sizeof AR_EFMT1 - 1) == 0 &&
ch_isdigit(memName[sizeof AR_EFMT1 - 1])) {
int elen = atoi(memName + sizeof AR_EFMT1 - 1);
size_t elen = atoi(memName + sizeof AR_EFMT1 - 1);
if ((unsigned int)elen > MAXPATHLEN)
if (elen > MAXPATHLEN)
goto badarch;
if (fread(memName, (size_t)elen, 1, arch) != 1)
if (fread(memName, elen, 1, arch) != 1)
goto badarch;
memName[elen] = '\0';
if (fseek(arch, -elen, SEEK_CUR) != 0)
if (fseek(arch, -(long)elen, SEEK_CUR) != 0)
goto badarch;
if (DEBUG(ARCH) || DEBUG(MAKE))
debug_printf(
@ -839,14 +838,15 @@ ArchFindMember(const char *archive, const char *member, struct ar_hdr *out_arh,
if (strncmp(out_arh->AR_NAME, AR_EFMT1, sizeof AR_EFMT1 - 1) ==
0 &&
(ch_isdigit(out_arh->AR_NAME[sizeof AR_EFMT1 - 1]))) {
int elen = atoi(&out_arh->AR_NAME[sizeof AR_EFMT1 - 1]);
size_t elen = atoi(
&out_arh->AR_NAME[sizeof AR_EFMT1 - 1]);
char ename[MAXPATHLEN + 1];
if ((unsigned int)elen > MAXPATHLEN) {
if (elen > MAXPATHLEN) {
fclose(arch);
return NULL;
}
if (fread(ename, (size_t)elen, 1, arch) != 1) {
if (fread(ename, elen, 1, arch) != 1) {
fclose(arch);
return NULL;
}
@ -859,14 +859,14 @@ ArchFindMember(const char *archive, const char *member, struct ar_hdr *out_arh,
if (strncmp(ename, member, len) == 0) {
/* Found as extended name */
if (fseek(arch,
-(long)sizeof(struct ar_hdr) - elen,
SEEK_CUR) != 0) {
-(long)(sizeof(struct ar_hdr) - elen),
SEEK_CUR) != 0) {
fclose(arch);
return NULL;
}
return arch;
}
if (fseek(arch, -elen, SEEK_CUR) != 0) {
if (fseek(arch, -(long)elen, SEEK_CUR) != 0) {
fclose(arch);
return NULL;
}
@ -882,7 +882,7 @@ ArchFindMember(const char *archive, const char *member, struct ar_hdr *out_arh,
*/
out_arh->AR_SIZE[sizeof out_arh->AR_SIZE - 1] = '\0';
size = (int)strtol(out_arh->AR_SIZE, NULL, 10);
if (fseek(arch, (size + 1) & ~1, SEEK_CUR) != 0) {
if (fseek(arch, (size + 1) & ~1L, SEEK_CUR) != 0) {
fclose(arch);
return NULL;
}
@ -991,12 +991,12 @@ Arch_UpdateMemberMTime(GNode *gn)
const char *nameEnd = strchr(nameStart, ')');
size_t nameLen = (size_t)(nameEnd - nameStart);
if ((pgn->flags & REMAKE) &&
if (pgn->flags.remake &&
strncmp(nameStart, gn->name, nameLen) == 0) {
Arch_UpdateMTime(pgn);
gn->mtime = pgn->mtime;
}
} else if (pgn->flags & REMAKE) {
} else if (pgn->flags.remake) {
/*
* Something which isn't a library depends on the
* existence of this target, so it needs to exist.
@ -1036,6 +1036,35 @@ Arch_FindLib(GNode *gn, SearchPath *path)
#endif
}
/* ARGSUSED */
static bool
RanlibOODate(const GNode *gn MAKE_ATTR_UNUSED)
{
#ifdef RANLIBMAG
struct ar_hdr *arh; /* Header for __.SYMDEF */
int tocModTime; /* The table-of-contents' mod time */
arh = ArchStatMember(gn->path, RANLIBMAG, false);
if (arh == NULL) {
/* A library without a table of contents is out-of-date. */
if (DEBUG(ARCH) || DEBUG(MAKE))
debug_printf("no toc...");
return true;
}
tocModTime = (int)strtol(arh->ar_date, NULL, 10);
if (DEBUG(ARCH) || DEBUG(MAKE))
debug_printf("%s modified %s...",
RANLIBMAG, Targ_FmtTime(tocModTime));
return gn->youngestChild == NULL ||
gn->youngestChild->mtime > tocModTime;
#else
return false;
#endif
}
/*
* Decide if a node with the OP_LIB attribute is out-of-date. Called from
* GNode_IsOODate to make its life easier.
@ -1069,46 +1098,19 @@ Arch_FindLib(GNode *gn, SearchPath *path)
bool
Arch_LibOODate(GNode *gn)
{
bool oodate;
if (gn->type & OP_PHONY) {
oodate = true;
return true;
} else if (!GNode_IsTarget(gn) && Lst_IsEmpty(&gn->children)) {
oodate = false;
return false;
} else if ((!Lst_IsEmpty(&gn->children) && gn->youngestChild == NULL) ||
(gn->mtime > now) ||
(gn->youngestChild != NULL &&
gn->mtime < gn->youngestChild->mtime)) {
oodate = true;
return true;
} else {
#ifdef RANLIBMAG
struct ar_hdr *arh; /* Header for __.SYMDEF */
int modTimeTOC; /* The table-of-contents' mod time */
arh = ArchStatMember(gn->path, RANLIBMAG, false);
if (arh != NULL) {
modTimeTOC = (int)strtol(arh->ar_date, NULL, 10);
if (DEBUG(ARCH) || DEBUG(MAKE))
debug_printf("%s modified %s...",
RANLIBMAG,
Targ_FmtTime(modTimeTOC));
oodate = gn->youngestChild == NULL ||
gn->youngestChild->mtime > modTimeTOC;
} else {
/*
* A library without a table of contents is out-of-date.
*/
if (DEBUG(ARCH) || DEBUG(MAKE))
debug_printf("no toc...");
oodate = true;
}
#else
oodate = false;
#endif
return RanlibOODate(gn);
}
return oodate;
}
/* Initialize the archives module. */

View File

@ -1,4 +1,4 @@
.\" $NetBSD: make.1,v 1.296 2021/02/04 21:42:46 rillig Exp $
.\" $NetBSD: make.1,v 1.300 2021/12/12 20:45:48 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 December 22, 2020
.Dd December 12, 2021
.Dt BMAKE 1
.Os
.Sh NAME
@ -1163,6 +1163,9 @@ executes.
.It Ev .SHELL
The pathname of the shell used to run target scripts.
It is read-only.
.It Ev .SUFFIXES
The list of known suffixes.
It is read-only.
.It Ev .TARGETS
The list of targets explicitly specified on the command line, if any.
.It Ev VPATH
@ -1233,8 +1236,20 @@ but selects all words which do not match
.Ar pattern .
.It Cm \&:O
Orders every word in variable alphabetically.
.It Cm \&:On
Orders every word in variable numerically.
A number followed by one of
.Ql k ,
.Ql M
or
.Ql G
is multiplied by the appropriate factor (1024 (k), 1048576 (M), or
1073741824 (G)).
Both upper- and lower-case letters are accepted.
.It Cm \&:Or
Orders every word in variable in reverse alphabetical order.
.It Cm \&:Orn
Orders every word in variable in reverse numerical order.
.It Cm \&:Ox
Shuffles the words in variable.
The results will be different each time you are referring to the

View File

@ -757,6 +757,8 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
.SHELL The pathname of the shell used to run target scripts. It
is read-only.
.SUFFIXES The list of known suffixes. It is read-only.
.TARGETS The list of targets explicitly specified on the command
line, if any.
@ -809,8 +811,16 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
:O Orders every word in variable alphabetically.
:On Orders every word in variable numerically. A number followed by one
of `k', `M' or `G' is multiplied by the appropriate factor (1024
(k), 1048576 (M), or 1073741824 (G)). Both upper- and lower-case
letters are accepted.
:Or Orders every word in variable in reverse alphabetical order.
:Orn
Orders every word in variable in reverse numerical order.
:Ox Shuffles the words in variable. The results will be different each
time you are referring to the modified variable; use the assignment
with expansion (`:=') to prevent such behavior. For example,
@ -1581,4 +1591,4 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
There is no way of escaping a space character in a filename.
FreeBSD 13.0 December 22, 2020 FreeBSD 13.0
FreeBSD 13.0 December 12, 2021 FreeBSD 13.0

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 81 KiB

View File

@ -119,7 +119,7 @@
# Simon J. Gerraty <sjg@crufty.net>
# RCSid:
# $Id: boot-strap,v 1.54 2020/11/13 21:47:25 sjg Exp $
# $Id: boot-strap,v 1.57 2021/10/22 20:32:21 sjg Exp $
#
# @(#) Copyright (c) 2001 Simon J. Gerraty
#
@ -405,17 +405,6 @@ 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=`which diff`
export TOOL_DIFF
op_configure() {
$srcdir/configure $CONFIGURE_ARGS || exit 1
}
@ -431,7 +420,7 @@ op_build() {
op_test() {
[ -x bmake ] || op_build
Bmake test || exit 1
Bmake test "$@" || exit 1
}
op_clean() {
@ -483,5 +472,5 @@ You may need the -r or -R option to more/less to view it correctly.
EOM
}
op_$op
op_$op "$@"
exit 0

View File

@ -1,4 +1,4 @@
# $Id: bsd.after-import.mk,v 1.16 2020/07/12 03:39:01 sjg Exp $
# $Id: bsd.after-import.mk,v 1.17 2021/10/22 06:31:32 sjg Exp $
# This makefile is for use when integrating bmake into a BSD build
# system. Use this makefile after importing bmake.
@ -59,6 +59,7 @@ bootstrap: ${BMAKE_SRC}/boot-strap ${MAKEFILE}
# Makefiles need a little more tweaking than say config.h
MAKEFILE_SED = sed -e '/^MACHINE/d' \
-e '/include.*VERSION/d' \
-e '/^CC=/s,=,?=,' \
-e '/^PROG/ { s,=,?=,;s,bmake,$${.CURDIR:T},; }' \
-e 's,^.-include,.sinclude,' \
-e '/^\..*include *</ { s,<,<bsd.,;/autoconf/d; }' \

View File

@ -1,4 +1,4 @@
/* $NetBSD: buf.c,v 1.51 2021/01/30 21:18:14 rillig Exp $ */
/* $NetBSD: buf.c,v 1.53 2021/11/28 22:48:06 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@ -75,7 +75,7 @@
#include "make.h"
/* "@(#)buf.c 8.1 (Berkeley) 6/6/93" */
MAKE_RCSID("$NetBSD: buf.c,v 1.51 2021/01/30 21:18:14 rillig Exp $");
MAKE_RCSID("$NetBSD: buf.c,v 1.53 2021/11/28 22:48:06 rillig Exp $");
/* Make space in the buffer for adding at least 16 more bytes. */
void
@ -122,19 +122,22 @@ Buf_AddStr(Buffer *buf, const char *str)
void
Buf_AddInt(Buffer *buf, int n)
{
enum {
bits = sizeof(int) * CHAR_BIT,
max_octal_digits = (bits + 2) / 3,
max_decimal_digits = /* at most */ max_octal_digits,
max_sign_chars = 1,
str_size = max_sign_chars + max_decimal_digits + 1
};
char str[str_size];
char str[sizeof(int) * CHAR_BIT + 1];
size_t len = (size_t)snprintf(str, sizeof str, "%d", n);
Buf_AddBytes(buf, str, len);
}
void
Buf_AddFlag(Buffer *buf, bool flag, const char *name)
{
if (flag) {
if (buf->len > 0)
Buf_AddByte(buf, '|');
Buf_AddBytes(buf, name, strlen(name));
}
}
/* Mark the buffer as empty, so it can be filled with data again. */
void
Buf_Empty(Buffer *buf)

View File

@ -1,4 +1,4 @@
/* $NetBSD: buf.h,v 1.43 2021/04/03 11:08:40 rillig Exp $ */
/* $NetBSD: buf.h,v 1.44 2021/11/28 22:48:06 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@ -111,6 +111,7 @@ void Buf_AddBytes(Buffer *, const char *, size_t);
void Buf_AddBytesBetween(Buffer *, const char *, const char *);
void Buf_AddStr(Buffer *, const char *);
void Buf_AddInt(Buffer *, int);
void Buf_AddFlag(Buffer *, bool, const char *);
void Buf_Empty(Buffer *);
void Buf_Init(Buffer *);
void Buf_InitSize(Buffer *, size_t);

View File

@ -1,4 +1,4 @@
/* $NetBSD: compat.c,v 1.227 2021/04/27 15:19:25 christos Exp $ */
/* $NetBSD: compat.c,v 1.229 2021/11/28 23:12:51 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@ -99,7 +99,7 @@
#include "pathnames.h"
/* "@(#)compat.c 8.2 (Berkeley) 3/19/94" */
MAKE_RCSID("$NetBSD: compat.c,v 1.227 2021/04/27 15:19:25 christos Exp $");
MAKE_RCSID("$NetBSD: compat.c,v 1.229 2021/11/28 23:12:51 rillig Exp $");
static GNode *curTarg = NULL;
static pid_t compatChild;
@ -187,7 +187,7 @@ DebugFailedTarget(const char *cmd, const GNode *gn)
static bool
UseShell(const char *cmd MAKE_ATTR_UNUSED)
{
#if !defined(MAKE_NATIVE)
#if defined(FORCE_USE_SHELL) || !defined(MAKE_NATIVE)
/*
* In a non-native build, the host environment might be weird enough
* that it's necessary to go through a shell to get the correct
@ -240,7 +240,7 @@ Compat_RunCommand(const char *cmdp, GNode *gn, StringListNode *ln)
* using a shell */
const char *volatile cmd = cmdp;
silent = (gn->type & OP_SILENT) != 0;
silent = (gn->type & OP_SILENT) != OP_NONE;
errCheck = !(gn->type & OP_IGNORE);
doIt = false;
@ -497,7 +497,7 @@ MakeUnmade(GNode *gn, GNode *pgn)
* again. This is our signal to not attempt to do anything but abort
* our parent as well.
*/
gn->flags |= REMAKE;
gn->flags.remake = true;
gn->made = BEINGMADE;
if (!(gn->type & OP_MADE))
@ -505,9 +505,9 @@ MakeUnmade(GNode *gn, GNode *pgn)
MakeNodes(&gn->children, gn);
if (!(gn->flags & REMAKE)) {
if (!gn->flags.remake) {
gn->made = ABORTED;
pgn->flags &= ~(unsigned)REMAKE;
pgn->flags.remake = false;
return false;
}
@ -565,7 +565,7 @@ MakeUnmade(GNode *gn, GNode *pgn)
RunCommands(gn);
curTarg = NULL;
} else {
Job_Touch(gn, (gn->type & OP_SILENT) != 0);
Job_Touch(gn, (gn->type & OP_SILENT) != OP_NONE);
}
} else {
gn->made = ERROR;
@ -585,13 +585,13 @@ MakeUnmade(GNode *gn, GNode *pgn)
*/
gn->made = MADE;
if (Make_Recheck(gn) == 0)
pgn->flags |= FORCE;
pgn->flags.force = true;
if (!(gn->type & OP_EXEC)) {
pgn->flags |= CHILDMADE;
pgn->flags.childMade = true;
GNode_UpdateYoungestChild(pgn, gn);
}
} else if (opts.keepgoing) {
pgn->flags &= ~(unsigned)REMAKE;
pgn->flags.remake = false;
} else {
PrintOnError(gn, "\nStop.");
exit(1);
@ -612,11 +612,11 @@ MakeOther(GNode *gn, GNode *pgn)
case BEINGMADE:
Error("Graph cycles through %s", gn->name);
gn->made = ERROR;
pgn->flags &= ~(unsigned)REMAKE;
pgn->flags.remake = false;
break;
case MADE:
if (!(gn->type & OP_EXEC)) {
pgn->flags |= CHILDMADE;
pgn->flags.childMade = true;
GNode_UpdateYoungestChild(pgn, gn);
}
break;
@ -663,7 +663,7 @@ Compat_Make(GNode *gn, GNode *pgn)
* Already had an error when making this.
* Tell the parent to abort.
*/
pgn->flags &= ~(unsigned)REMAKE;
pgn->flags.remake = false;
} else {
MakeOther(gn, pgn);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: cond.c,v 1.267 2021/06/11 14:52:03 rillig Exp $ */
/* $NetBSD: cond.c,v 1.302 2021/12/12 09:36:00 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@ -95,14 +95,12 @@
#include "dir.h"
/* "@(#)cond.c 8.2 (Berkeley) 1/2/94" */
MAKE_RCSID("$NetBSD: cond.c,v 1.267 2021/06/11 14:52:03 rillig Exp $");
MAKE_RCSID("$NetBSD: cond.c,v 1.302 2021/12/12 09:36:00 rillig Exp $");
/*
* The parsing of conditional expressions is based on this grammar:
* Or -> And '||' Or
* Or -> And
* And -> Term '&&' And
* And -> Term
* Or -> And ('||' And)*
* And -> Term ('&&' Term)*
* Term -> Function '(' Argument ')'
* Term -> Leaf Operator Leaf
* Term -> Leaf
@ -151,9 +149,23 @@ typedef struct CondParser {
bool plain;
/* The function to apply on unquoted bare words. */
bool (*evalBare)(size_t, const char *);
bool (*evalBare)(const char *);
bool negateEvalBare;
/*
* Whether the left-hand side of a comparison may be an unquoted
* string. This is allowed for expressions of the form
* ${condition:?:}, see ApplyModifier_IfElse. Such a condition is
* expanded before it is evaluated, due to ease of implementation.
* This means that at the point where the condition is evaluated,
* make cannot know anymore whether the left-hand side had originally
* been a variable expression or a plain word.
*
* In all other contexts, the left-hand side must either be a
* variable expression, a quoted string or a number.
*/
bool leftUnquotedOK;
const char *p; /* The remaining condition to parse */
Token curr; /* Single push-back token used in parsing */
@ -171,24 +183,13 @@ static CondResult CondParser_Or(CondParser *par, bool);
static unsigned int cond_depth = 0; /* current .if nesting level */
static unsigned int cond_min_depth = 0; /* depth at makefile open */
static const char *opname[] = { "<", "<=", ">", ">=", "==", "!=" };
/*
* Indicate when we should be strict about lhs of comparisons.
* In strict mode, the lhs must be a variable expression or a string literal
* in quotes. In non-strict mode it may also be an unquoted string literal.
*
* True when CondEvalExpression is called from Cond_EvalLine (.if etc).
* False when CondEvalExpression is called from ApplyModifier_IfElse
* since lhs is already expanded, and at that point we cannot tell if
* it was a variable reference or not.
*/
static bool lhsStrict;
/* Names for ComparisonOp. */
static const char opname[][3] = { "<", "<=", ">", ">=", "==", "!=" };
static bool
is_token(const char *str, const char *tok, size_t len)
is_token(const char *str, const char *tok, unsigned char len)
{
return strncmp(str, tok, len) == 0 && !ch_isalpha(str[len]);
return strncmp(str, tok, (size_t)len) == 0 && !ch_isalpha(str[len]);
}
static Token
@ -197,16 +198,6 @@ ToToken(bool cond)
return cond ? TOK_TRUE : TOK_FALSE;
}
/* Push back the most recent token read. We only need one level of this. */
static void
CondParser_PushBack(CondParser *par, Token t)
{
assert(par->curr == TOK_NONE);
assert(t != TOK_NONE);
par->curr = t;
}
static void
CondParser_SkipWhitespace(CondParser *par)
{
@ -214,7 +205,9 @@ CondParser_SkipWhitespace(CondParser *par)
}
/*
* Parse the argument of a built-in function.
* Parse a single word, taking into account balanced parentheses as well as
* embedded expressions. Used for the argument of a built-in function as
* well as for bare words, which are then passed to the default function.
*
* Arguments:
* *pp initially points at the '(',
@ -223,12 +216,12 @@ CondParser_SkipWhitespace(CondParser *par)
* *out_arg receives the argument as string.
*
* func says whether the argument belongs to an actual function, or
* whether the parsed argument is passed to the default function.
* NULL when parsing a bare word.
*
* Return the length of the argument, or 0 on error.
* Return the length of the argument, or an ambiguous 0 on error.
*/
static size_t
ParseFuncArg(CondParser *par, const char **pp, bool doEval, const char *func,
ParseWord(CondParser *par, const char **pp, bool doEval, const char *func,
char **out_arg)
{
const char *p = *pp;
@ -239,11 +232,6 @@ ParseFuncArg(CondParser *par, const char **pp, bool doEval, const char *func,
if (func != NULL)
p++; /* Skip opening '(' - verified by caller */
if (*p == '\0') {
*out_arg = NULL; /* Missing closing parenthesis: */
return 0; /* .if defined( */
}
cpp_skip_hspace(&p);
Buf_InitSize(&argBuf, 16);
@ -299,9 +287,8 @@ ParseFuncArg(CondParser *par, const char **pp, bool doEval, const char *func,
}
/* Test whether the given variable is defined. */
/*ARGSUSED*/
static bool
FuncDefined(size_t argLen MAKE_ATTR_UNUSED, const char *arg)
FuncDefined(const char *arg)
{
FStr value = Var_Value(SCOPE_CMDLINE, arg);
bool result = value.str != NULL;
@ -309,10 +296,9 @@ FuncDefined(size_t argLen MAKE_ATTR_UNUSED, const char *arg)
return result;
}
/* See if the given target is being made. */
/*ARGSUSED*/
/* See if the given target is requested to be made. */
static bool
FuncMake(size_t argLen MAKE_ATTR_UNUSED, const char *arg)
FuncMake(const char *arg)
{
StringListNode *ln;
@ -323,9 +309,8 @@ FuncMake(size_t argLen MAKE_ATTR_UNUSED, const char *arg)
}
/* See if the given file exists. */
/*ARGSUSED*/
static bool
FuncExists(size_t argLen MAKE_ATTR_UNUSED, const char *arg)
FuncExists(const char *arg)
{
bool result;
char *path;
@ -339,9 +324,8 @@ FuncExists(size_t argLen MAKE_ATTR_UNUSED, const char *arg)
}
/* See if the given node exists and is an actual target. */
/*ARGSUSED*/
static bool
FuncTarget(size_t argLen MAKE_ATTR_UNUSED, const char *arg)
FuncTarget(const char *arg)
{
GNode *gn = Targ_FindNode(arg);
return gn != NULL && GNode_IsTarget(gn);
@ -351,9 +335,8 @@ FuncTarget(size_t argLen MAKE_ATTR_UNUSED, const char *arg)
* See if the given node exists and is an actual target with commands
* associated with it.
*/
/*ARGSUSED*/
static bool
FuncCommands(size_t argLen MAKE_ATTR_UNUSED, const char *arg)
FuncCommands(const char *arg)
{
GNode *gn = Targ_FindNode(arg);
return gn != NULL && GNode_IsTarget(gn) && !Lst_IsEmpty(&gn->commands);
@ -375,12 +358,12 @@ TryParseNumber(const char *str, double *out_value)
unsigned long ul_val;
double dbl_val;
errno = 0;
if (str[0] == '\0') { /* XXX: why is an empty string a number? */
*out_value = 0.0;
return true;
}
errno = 0;
ul_val = strtoul(str, &end, str[1] == 'x' ? 16 : 10);
if (*end == '\0' && errno != ERANGE) {
*out_value = str[0] == '-' ? -(double)-ul_val : (double)ul_val;
@ -412,17 +395,16 @@ is_separator(char ch)
*/
static bool
CondParser_StringExpr(CondParser *par, const char *start,
bool const doEval, bool const quoted,
Buffer *buf, FStr *const inout_str)
bool doEval, bool quoted,
Buffer *buf, FStr *inout_str)
{
VarEvalMode emode;
const char *nested_p;
bool atStart;
VarParseResult parseResult;
/* if we are in quotes, an undefined variable is ok */
emode = doEval && !quoted ? VARE_UNDEFERR
: doEval ? VARE_WANTRES
emode = doEval && quoted ? VARE_WANTRES
: doEval ? VARE_UNDEFERR
: VARE_PARSE_ONLY;
nested_p = par->p;
@ -477,7 +459,7 @@ CondParser_StringExpr(CondParser *par, const char *start,
* Sets out_quoted if the leaf was a quoted string literal.
*/
static void
CondParser_Leaf(CondParser *par, bool doEval, bool strictLHS,
CondParser_Leaf(CondParser *par, bool doEval, bool unquotedOK,
FStr *out_str, bool *out_quoted)
{
Buffer buf;
@ -525,11 +507,11 @@ CondParser_Leaf(CondParser *par, bool doEval, bool strictLHS,
goto cleanup;
continue;
default:
if (strictLHS && !quoted && *start != '$' &&
if (!unquotedOK && !quoted && *start != '$' &&
!ch_isdigit(*start)) {
/*
* The left-hand side must be quoted,
* a variable reference or a number.
* a variable expression or a number.
*/
str = FStr_InitRefer(NULL);
goto cleanup;
@ -541,15 +523,16 @@ CondParser_Leaf(CondParser *par, bool doEval, bool strictLHS,
}
got_str:
str = FStr_InitOwn(buf.data);
buf.data = NULL;
cleanup:
Buf_DoneData(&buf); /* XXX: memory leak on failure? */
Buf_Done(&buf);
*out_str = str;
}
static bool
EvalBare(const CondParser *par, const char *arg, size_t arglen)
EvalBare(const CondParser *par, const char *arg)
{
bool res = par->evalBare(arglen, arg);
bool res = par->evalBare(arg);
return par->negateEvalBare ? !res : res;
}
@ -573,11 +556,14 @@ EvalNotEmpty(CondParser *par, const char *value, bool quoted)
/* For .if ${...}, check for non-empty string. This is different from
* the evaluation function from that .if variant, which would test
* whether a variable of the given name were defined. */
/* XXX: Whitespace should count as empty, just as in ParseEmptyArg. */
/*
* XXX: Whitespace should count as empty, just as in
* CondParser_FuncCallEmpty.
*/
if (par->plain)
return value[0] != '\0';
return EvalBare(par, value, strlen(value));
return EvalBare(par, value);
}
/* Evaluate a numerical comparison, such as in ".if ${VAR} >= 9". */
@ -682,11 +668,7 @@ CondParser_Comparison(CondParser *par, bool doEval)
ComparisonOp op;
bool lhsQuoted, rhsQuoted;
/*
* Parse the variable spec and skip over it, saving its
* value in lhs.
*/
CondParser_Leaf(par, doEval, lhsStrict, &lhs, &lhsQuoted);
CondParser_Leaf(par, doEval, par->leftUnquotedOK, &lhs, &lhsQuoted);
if (lhs.str == NULL)
goto done_lhs;
@ -702,12 +684,12 @@ CondParser_Comparison(CondParser *par, bool doEval)
if (par->p[0] == '\0') {
Parse_Error(PARSE_FATAL,
"Missing right-hand-side of operator '%s'", opname[op]);
"Missing right-hand side of operator '%s'", opname[op]);
par->printedError = true;
goto done_lhs;
}
CondParser_Leaf(par, doEval, false, &rhs, &rhsQuoted);
CondParser_Leaf(par, doEval, true, &rhs, &rhsQuoted);
if (rhs.str == NULL)
goto done_rhs;
@ -729,50 +711,37 @@ CondParser_Comparison(CondParser *par, bool doEval)
* The argument to empty() is a variable name, optionally followed by
* variable modifiers.
*/
/*ARGSUSED*/
static size_t
ParseEmptyArg(CondParser *par MAKE_ATTR_UNUSED, const char **pp,
bool doEval, const char *func MAKE_ATTR_UNUSED,
char **out_arg)
static bool
CondParser_FuncCallEmpty(CondParser *par, bool doEval, Token *out_token)
{
const char *cp = par->p;
Token tok;
FStr val;
size_t magic_res;
/* We do all the work here and return the result as the length */
*out_arg = NULL;
if (!is_token(cp, "empty", 5))
return false;
cp += 5;
(*pp)--; /* Make (*pp)[1] point to the '('. */
(void)Var_Parse(pp, SCOPE_CMDLINE,
cpp_skip_whitespace(&cp);
if (*cp != '(')
return false;
cp--; /* Make cp[1] point to the '('. */
(void)Var_Parse(&cp, SCOPE_CMDLINE,
doEval ? VARE_WANTRES : VARE_PARSE_ONLY, &val);
/* TODO: handle errors */
/* If successful, *pp points beyond the closing ')' now. */
if (val.str == var_Error) {
FStr_Done(&val);
return (size_t)-1;
if (val.str == var_Error)
tok = TOK_ERROR;
else {
cpp_skip_whitespace(&val.str);
tok = val.str[0] != '\0' && doEval ? TOK_FALSE : TOK_TRUE;
}
/*
* A variable is empty when it just contains spaces...
* 4/15/92, christos
*/
cpp_skip_whitespace(&val.str);
/*
* For consistency with the other functions we can't generate the
* true/false here.
*/
magic_res = val.str[0] != '\0' ? 2 : 1;
FStr_Done(&val);
return magic_res;
}
/*ARGSUSED*/
static bool
FuncEmpty(size_t arglen, const char *arg MAKE_ATTR_UNUSED)
{
/* Magic values ahead, see ParseEmptyArg. */
return arglen == 1;
*out_token = tok;
par->p = cp;
return true;
}
/* Parse a function call expression, such as 'defined(${file})'. */
@ -780,61 +749,51 @@ static bool
CondParser_FuncCall(CondParser *par, bool doEval, Token *out_token)
{
static const struct fn_def {
const char *fn_name;
size_t fn_name_len;
size_t (*fn_parse)(CondParser *, const char **, bool,
const char *, char **);
bool (*fn_eval)(size_t, const char *);
const char fn_name[9];
unsigned char fn_name_len;
bool (*fn_eval)(const char *);
} fns[] = {
{ "defined", 7, ParseFuncArg, FuncDefined },
{ "make", 4, ParseFuncArg, FuncMake },
{ "exists", 6, ParseFuncArg, FuncExists },
{ "empty", 5, ParseEmptyArg, FuncEmpty },
{ "target", 6, ParseFuncArg, FuncTarget },
{ "commands", 8, ParseFuncArg, FuncCommands }
{ "defined", 7, FuncDefined },
{ "make", 4, FuncMake },
{ "exists", 6, FuncExists },
{ "target", 6, FuncTarget },
{ "commands", 8, FuncCommands }
};
const struct fn_def *fn;
char *arg = NULL;
size_t arglen;
const char *cp = par->p;
const struct fn_def *fns_end = fns + sizeof fns / sizeof fns[0];
const struct fn_def *last_fn = fns + sizeof fns / sizeof fns[0] - 1;
for (fn = fns; fn != fns_end; fn++) {
if (!is_token(cp, fn->fn_name, fn->fn_name_len))
continue;
for (fn = fns; !is_token(cp, fn->fn_name, fn->fn_name_len); fn++)
if (fn == last_fn)
return false;
cp += fn->fn_name_len;
cpp_skip_whitespace(&cp);
if (*cp != '(')
break;
cp += fn->fn_name_len;
cpp_skip_whitespace(&cp);
if (*cp != '(')
return false;
arglen = fn->fn_parse(par, &cp, doEval, fn->fn_name, &arg);
if (arglen == 0 || arglen == (size_t)-1) {
par->p = cp;
*out_token = arglen == 0 ? TOK_FALSE : TOK_ERROR;
return true;
}
arglen = ParseWord(par, &cp, doEval, fn->fn_name, &arg);
*out_token = ToToken(arglen != 0 && (!doEval || fn->fn_eval(arg)));
/* Evaluate the argument using the required function. */
*out_token = ToToken(!doEval || fn->fn_eval(arglen, arg));
free(arg);
par->p = cp;
return true;
}
return false;
free(arg);
par->p = cp;
return true;
}
/*
* Parse a comparison such as '${VAR} == "value"', or a simple leaf without
* Parse a comparison that neither starts with '"' nor '$', such as the
* unusual 'bare == right' or '3 == ${VAR}', or a simple leaf without
* operator, which is a number, a variable expression or a string literal.
*
* TODO: Can this be merged into CondParser_Comparison?
*/
static Token
CondParser_ComparisonOrLeaf(CondParser *par, bool doEval)
{
Token t;
char *arg = NULL;
size_t arglen;
const char *cp;
const char *cp1;
@ -855,7 +814,7 @@ CondParser_ComparisonOrLeaf(CondParser *par, bool doEval)
* XXX: Is it possible to have a variable expression evaluated twice
* at this point?
*/
arglen = ParseFuncArg(par, &cp, doEval, NULL, &arg);
(void)ParseWord(par, &cp, doEval, NULL, &arg);
cp1 = cp;
cpp_skip_whitespace(&cp1);
if (*cp1 == '=' || *cp1 == '!' || *cp1 == '<' || *cp1 == '>')
@ -868,7 +827,7 @@ CondParser_ComparisonOrLeaf(CondParser *par, bool doEval)
* after .if must have been taken literally, so the argument cannot
* be empty - even if it contained a variable expansion.
*/
t = ToToken(!doEval || EvalBare(par, arg, arglen));
t = ToToken(!doEval || EvalBare(par, arg));
free(arg);
return t;
}
@ -934,12 +893,30 @@ CondParser_Token(CondParser *par, bool doEval)
return CondParser_Comparison(par, doEval);
default:
if (CondParser_FuncCallEmpty(par, doEval, &t))
return t;
if (CondParser_FuncCall(par, doEval, &t))
return t;
return CondParser_ComparisonOrLeaf(par, doEval);
}
}
/* Skip the next token if it equals t. */
static bool
CondParser_Skip(CondParser *par, Token t)
{
Token actual;
actual = CondParser_Token(par, false);
if (actual == t)
return true;
assert(par->curr == TOK_NONE);
assert(actual != TOK_NONE);
par->curr = actual;
return false;
}
/*
* Term -> '(' Or ')'
* Term -> '!' Term
@ -980,56 +957,44 @@ CondParser_Term(CondParser *par, bool doEval)
}
/*
* And -> Term '&&' And
* And -> Term
* And -> Term ('&&' Term)*
*/
static CondResult
CondParser_And(CondParser *par, bool doEval)
{
CondResult res;
Token op;
CondResult res, rhs;
res = CondParser_Term(par, doEval);
if (res == CR_ERROR)
return CR_ERROR;
op = CondParser_Token(par, doEval);
if (op == TOK_AND) {
if (res == CR_TRUE)
return CondParser_And(par, doEval);
if (CondParser_And(par, false) == CR_ERROR)
res = CR_TRUE;
do {
if ((rhs = CondParser_Term(par, doEval)) == CR_ERROR)
return CR_ERROR;
return res;
}
if (rhs == CR_FALSE) {
res = CR_FALSE;
doEval = false;
}
} while (CondParser_Skip(par, TOK_AND));
CondParser_PushBack(par, op);
return res;
}
/*
* Or -> And '||' Or
* Or -> And
* Or -> And ('||' And)*
*/
static CondResult
CondParser_Or(CondParser *par, bool doEval)
{
CondResult res;
Token op;
CondResult res, rhs;
res = CondParser_And(par, doEval);
if (res == CR_ERROR)
return CR_ERROR;
op = CondParser_Token(par, doEval);
if (op == TOK_OR) {
if (res == CR_FALSE)
return CondParser_Or(par, doEval);
if (CondParser_Or(par, false) == CR_ERROR)
res = CR_FALSE;
do {
if ((rhs = CondParser_And(par, doEval)) == CR_ERROR)
return CR_ERROR;
return res;
}
if (rhs == CR_TRUE) {
res = CR_TRUE;
doEval = false;
}
} while (CondParser_Skip(par, TOK_OR));
CondParser_PushBack(par, op);
return res;
}
@ -1060,23 +1025,22 @@ CondParser_Eval(CondParser *par, bool *out_value)
* COND_PARSE if the condition was valid grammatically
* COND_INVALID if not a valid conditional.
*
* (*value) is set to the boolean value of the condition
* *out_value is set to the boolean value of the condition
*/
static CondEvalResult
CondEvalExpression(const char *cond, bool *out_value, bool plain,
bool (*evalBare)(size_t, const char *), bool negate,
bool eprint, bool strictLHS)
bool (*evalBare)(const char *), bool negate,
bool eprint, bool leftUnquotedOK)
{
CondParser par;
CondEvalResult rval;
lhsStrict = strictLHS;
cpp_skip_hspace(&cond);
par.plain = plain;
par.evalBare = evalBare;
par.negateEvalBare = negate;
par.leftUnquotedOK = leftUnquotedOK;
par.p = cond;
par.curr = TOK_NONE;
par.printedError = false;
@ -1097,7 +1061,7 @@ CondEvalResult
Cond_EvalCondition(const char *cond, bool *out_value)
{
return CondEvalExpression(cond, out_value, true,
FuncDefined, false, false, false);
FuncDefined, false, false, true);
}
static bool
@ -1109,7 +1073,7 @@ IsEndif(const char *p)
static bool
DetermineKindOfConditional(const char **pp, bool *out_plain,
bool (**out_evalBare)(size_t, const char *),
bool (**out_evalBare)(const char *),
bool *out_negate)
{
const char *p = *pp;
@ -1198,7 +1162,7 @@ Cond_EvalLine(const char *line)
static unsigned int cond_states_cap = 128;
bool plain;
bool (*evalBare)(size_t, const char *);
bool (*evalBare)(const char *);
bool negate;
bool isElif;
bool value;
@ -1217,7 +1181,7 @@ Cond_EvalLine(const char *line)
if (IsEndif(p)) { /* It is an '.endif'. */
if (p[5] != '\0') {
Parse_Error(PARSE_FATAL,
"The .endif directive does not take arguments.");
"The .endif directive does not take arguments");
}
if (cond_depth == cond_min_depth) {
@ -1236,7 +1200,7 @@ Cond_EvalLine(const char *line)
if (p[1] != 'l') {
/*
* Unknown directive. It might still be a
* transformation rule like '.elisp.scm',
* transformation rule like '.err.txt',
* therefore no error message here.
*/
return COND_INVALID;
@ -1248,8 +1212,8 @@ Cond_EvalLine(const char *line)
if (p[2] != '\0')
Parse_Error(PARSE_FATAL,
"The .else directive "
"does not take arguments.");
"The .else directive "
"does not take arguments");
if (cond_depth == cond_min_depth) {
Parse_Error(PARSE_FATAL, "if-less else");
@ -1328,7 +1292,7 @@ Cond_EvalLine(const char *line)
/* And evaluate the conditional expression */
if (CondEvalExpression(p, &value, plain, evalBare, negate,
true, true) == COND_INVALID) {
true, false) == COND_INVALID) {
/* Syntax error in conditional, error message already output. */
/* Skip everything to matching .endif */
/* XXX: An extra '.else' is not detected in this case. */

View File

@ -9,6 +9,9 @@
/* Shell spec to use by default */
#undef DEFSHELL_INDEX
/* Path of default shell */
#undef DEFSHELL_PATH
/* Define to 1 if you have the <ar.h> header file. */
#undef HAVE_AR_H
@ -65,6 +68,9 @@
/* Define to 1 if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H
/* Define to 1 if the system has the type `long long int'. */
#undef HAVE_LONG_LONG_INT
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
@ -98,15 +104,36 @@
/* Define to 1 if you have the `setpgid' function. */
#undef HAVE_SETPGID
/* Define to 1 if you have the `setrlimit' function. */
#undef HAVE_SETRLIMIT
/* Define to 1 if you have the `setsid' function. */
#undef HAVE_SETSID
/* Define to 1 if you have the `sigaction' function. */
#undef HAVE_SIGACTION
/* Define to 1 if you have the `sigaddset' function. */
#undef HAVE_SIGADDSET
/* Define to 1 if you have the `sigpending' function. */
#undef HAVE_SIGPENDING
/* Define to 1 if you have the `sigprocmask' function. */
#undef HAVE_SIGPROCMASK
/* Define to 1 if you have the `sigsetmask' function. */
#undef HAVE_SIGSETMASK
/* Define to 1 if you have the `sigsuspend' function. */
#undef HAVE_SIGSUSPEND
/* Define to 1 if you have the `sigvec' function. */
#undef HAVE_SIGVEC
/* Define to 1 if the system has the type `sig_atomic_t'. */
#undef HAVE_SIG_ATOMIC_T
/* Define to 1 if you have the `snprintf' function. */
#undef HAVE_SNPRINTF
@ -143,6 +170,12 @@
/* Define to 1 if you have the `strtol' function. */
#undef HAVE_STRTOL
/* Define to 1 if you have the `strtoll' function. */
#undef HAVE_STRTOLL
/* Define to 1 if you have the `strtoul' function. */
#undef HAVE_STRTOUL
/* Define to 1 if `st_rdev' is a member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_RDEV
@ -197,6 +230,9 @@
/* Define to 1 if you have the `unsetenv' function. */
#undef HAVE_UNSETENV
/* Define to 1 if the system has the type `unsigned long long int'. */
#undef HAVE_UNSIGNED_LONG_LONG_INT
/* Define to 1 if you have the <utime.h> header file. */
#undef HAVE_UTIME_H
@ -324,6 +360,16 @@
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
#undef inline
#endif
/* Define to the type of a signed integer type of width exactly 64 bits if
such a type exists and the standard includes do not define it. */
#undef int64_t
/* Define to `int' if <sys/types.h> does not define. */
#undef mode_t

View File

@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for bmake 20210201.
# Generated by GNU Autoconf 2.69 for bmake 20211020.
#
# Report bugs to <sjg@NetBSD.org>.
#
@ -580,8 +580,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='bmake'
PACKAGE_TARNAME='bmake'
PACKAGE_VERSION='20210201'
PACKAGE_STRING='bmake 20210201'
PACKAGE_VERSION='20211020'
PACKAGE_STRING='bmake 20211020'
PACKAGE_BUGREPORT='sjg@NetBSD.org'
PACKAGE_URL=''
@ -622,11 +622,13 @@ ac_includes_default="\
#endif"
ac_subst_vars='LTLIBOBJS
UTC_1
_MAKE_VERSION
filemon_h
use_filemon
use_meta
diff_u
diff
GCC
INSTALL
default_sys_path
@ -1255,7 +1257,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 20210201 to adapt to many kinds of systems.
\`configure' configures bmake 20211020 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1316,7 +1318,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of bmake 20210201:";;
short | recursive ) echo "Configuration of bmake 20211020:";;
esac
cat <<\_ACEOF
@ -1422,7 +1424,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
bmake configure 20210201
bmake configure 20211020
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@ -1721,6 +1723,82 @@ fi
} # ac_fn_c_try_link
# ac_fn_c_find_intX_t LINENO BITS VAR
# -----------------------------------
# Finds a signed integer type with width BITS, setting cache variable VAR
# accordingly.
ac_fn_c_find_intX_t ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for int$2_t" >&5
$as_echo_n "checking for int$2_t... " >&6; }
if eval \${$3+:} false; then :
$as_echo_n "(cached) " >&6
else
eval "$3=no"
# Order is important - never check a type that is potentially smaller
# than half of the expected target width.
for ac_type in int$2_t 'int' 'long int' \
'long long int' 'short int' 'signed char'; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$ac_includes_default
enum { N = $2 / 2 - 1 };
int
main ()
{
static int test_array [1 - 2 * !(0 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1))];
test_array [0] = 0;
return test_array [0];
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$ac_includes_default
enum { N = $2 / 2 - 1 };
int
main ()
{
static int test_array [1 - 2 * !(($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1)
< ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 2))];
test_array [0] = 0;
return test_array [0];
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
else
case $ac_type in #(
int$2_t) :
eval "$3=yes" ;; #(
*) :
eval "$3=\$ac_type" ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
if eval test \"x\$"$3"\" = 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; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_find_intX_t
# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
# -------------------------------------------
# Tests whether TYPE exists after having included INCLUDES, setting cache
@ -2002,7 +2080,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 20210201, which was
It was created by bmake $as_me 20211020, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@ -2355,26 +2433,41 @@ ac_config_headers="$ac_config_headers config.h"
case "$srcdir" in
/*) ;;
*) srcdir=`cd $srcdir && pwd`;;
*) srcdir=`cd $srcdir && 'pwd'`;;
esac
. $srcdir/VERSION
OS=`uname -s`
use_defshell() {
case "$defshell_path$DEFSHELL_INDEX" in
"") ;;
*) return 0;;
esac
case "$1" in
*csh) # we must be desperate
DEFSHELL_INDEX=DEFSHELL_INDEX_CSH;;
*ksh)
DEFSHELL_INDEX=DEFSHELL_INDEX_KSH;;
sh|/bin/sh)
DEFSHELL_INDEX=DEFSHELL_INDEX_SH;;
*) DEFSHELL_INDEX=DEFSHELL_INDEX_CUSTOM
defshell_path=$1
;;
esac
case "$1" in
/bin/*) ;;
*/*) defshell_path=$1;;
esac
}
# Check whether --with-defshell was given.
if test "${with_defshell+set}" = set; then :
withval=$with_defshell; case "${withval}" in
yes) as_fn_error $? "bad value ${withval} given for bmake DEFSHELL" "$LINENO" 5 ;;
no) ;;
*) case "$with_defshell" in
sh) DEFSHELL_INDEX=DEFSHELL_INDEX_SH;; # it's the default anyway
ksh) DEFSHELL_INDEX=DEFSHELL_INDEX_KSH;;
csh) DEFSHELL_INDEX=DEFSHELL_INDEX_CSH;; # kidding right?
*) defshell_path=$with_defshell;; # better be sh compatible!
esac
;;
esac
*) use_defshell $with_defshell;;
esac
fi
case "$OS" in
@ -2446,6 +2539,37 @@ yes)
esac
;;
esac
case "$OS" in
Minix) CPPFLAGS="${CPPFLAGS} -D_NETBSD_SOURCE"
test -x /usr/pkg/bin/clang && CC=${CC:-clang}
;;
SCO_SV) # /bin/sh is not usable
ALT_DEF_SHELLS="/bin/lsh /usr/bin/bash /bin/ksh"
CPPFLAGS="${CPPFLAGS} -DFORCE_USE_SHELL"
;;
esac
echo $ECHO_N "checking whether system has timezone Europe/Berlin... $ECHO_C" >&6
if test -f /usr/share/zoneinfo/Europe/Berlin; then
echo yes >&6
# seems a safe bet
UTC_1=Europe/Berlin
else
utcH=`TZ=UTC date +%H 2> /dev/null`
utc_1H=`TZ=UTC-1 date +%H 2> /dev/null`
if test ${utcH-0} -lt ${utc_1H-0}; then
UTC_1=UTC-1
echo no, using UTC-1 >&6
else
echo no >&6
fi
fi
oldPATH=$PATH
for d in /usr/gnu/bin
do
test -d $d || continue
PATH=$PATH:$d
done
export PATH
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@ -4543,7 +4667,29 @@ if test $bmake_path_max -gt 1024; then
bmake_path_max=1024
fi
echo "Using: BMAKE_PATH_MAX=$bmake_path_max" >&6
if (type cat) > /dev/null 2>&1; then
: which
which() {
type "$@" | sed 's,[()],,g;s,^[^/][^/]*,,;q'
}
fi
case "$CC" in
/*) ;;
*)
for x in $CC
do
_cc=`which $x`
break
done
if test -x ${_cc:-/dev/null}; then
_cc_dir=`dirname $_cc`
case ":$oldPATH:" in
*:$_cc_dir:*) ;;
*) CC=$_cc_dir/$CC;;
esac
fi
;;
esac
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sys/wait.h that is POSIX.1 compatible" >&5
$as_echo_n "checking for sys/wait.h that is POSIX.1 compatible... " >&6; }
if ${ac_cv_header_sys_wait_h+:} false; then :
@ -4803,22 +4949,6 @@ done
ac_fn_c_check_header_mongrel "$LINENO" "sys/cdefs.h" "ac_cv_header_sys_cdefs_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_cdefs_h" = xyes; then :
echo $ECHO_N "checking whether sys/cdefs.h is compatible... $ECHO_C" >&6
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/cdefs.h>
#ifdef __RCSID
yes
#endif
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "yes" >/dev/null 2>&1; then :
echo yes >&6
else
echo no >&6; CPPFLAGS="${CPPFLAGS} -I`cd ${srcdir}/missing && pwd` -DNEED_HOST_CDEFS_H"
fi
rm -f conftest*
else
CPPFLAGS="${CPPFLAGS} -I`cd ${srcdir}/missing && pwd`"
@ -5175,6 +5305,176 @@ $as_echo "#define const /**/" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
$as_echo_n "checking for inline... " >&6; }
if ${ac_cv_c_inline+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_cv_c_inline=no
for ac_kw in inline __inline__ __inline; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#ifndef __cplusplus
typedef int foo_t;
static $ac_kw foo_t static_foo () {return 0; }
$ac_kw foo_t foo () {return 0; }
#endif
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_c_inline=$ac_kw
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
test "$ac_cv_c_inline" != no && break
done
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5
$as_echo "$ac_cv_c_inline" >&6; }
case $ac_cv_c_inline in
inline | yes) ;;
*)
case $ac_cv_c_inline in
no) ac_val=;;
*) ac_val=$ac_cv_c_inline;;
esac
cat >>confdefs.h <<_ACEOF
#ifndef __cplusplus
#define inline $ac_val
#endif
_ACEOF
;;
esac
ac_fn_c_find_intX_t "$LINENO" "64" "ac_cv_c_int64_t"
case $ac_cv_c_int64_t in #(
no|yes) ;; #(
*)
cat >>confdefs.h <<_ACEOF
#define int64_t $ac_cv_c_int64_t
_ACEOF
;;
esac
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for unsigned long long int" >&5
$as_echo_n "checking for unsigned long long int... " >&6; }
if ${ac_cv_type_unsigned_long_long_int+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_cv_type_unsigned_long_long_int=yes
if test "x${ac_cv_prog_cc_c99-no}" = xno; then
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* For now, do not test the preprocessor; as of 2007 there are too many
implementations with broken preprocessors. Perhaps this can
be revisited in 2012. In the meantime, code should not expect
#if to work with literals wider than 32 bits. */
/* Test literals. */
long long int ll = 9223372036854775807ll;
long long int nll = -9223372036854775807LL;
unsigned long long int ull = 18446744073709551615ULL;
/* Test constant expressions. */
typedef int a[((-9223372036854775807LL < 0 && 0 < 9223372036854775807ll)
? 1 : -1)];
typedef int b[(18446744073709551615ULL <= (unsigned long long int) -1
? 1 : -1)];
int i = 63;
int
main ()
{
/* Test availability of runtime routines for shift and division. */
long long int llmax = 9223372036854775807ll;
unsigned long long int ullmax = 18446744073709551615ull;
return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i)
| (llmax / ll) | (llmax % ll)
| (ull << 63) | (ull >> 63) | (ull << i) | (ull >> i)
| (ullmax / ull) | (ullmax % ull));
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
else
ac_cv_type_unsigned_long_long_int=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_unsigned_long_long_int" >&5
$as_echo "$ac_cv_type_unsigned_long_long_int" >&6; }
if test $ac_cv_type_unsigned_long_long_int = yes; then
$as_echo "#define HAVE_UNSIGNED_LONG_LONG_INT 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for long long int" >&5
$as_echo_n "checking for long long int... " >&6; }
if ${ac_cv_type_long_long_int+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_cv_type_long_long_int=yes
if test "x${ac_cv_prog_cc_c99-no}" = xno; then
ac_cv_type_long_long_int=$ac_cv_type_unsigned_long_long_int
if test $ac_cv_type_long_long_int = yes; then
if test "$cross_compiling" = yes; then :
:
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <limits.h>
#ifndef LLONG_MAX
# define HALF \
(1LL << (sizeof (long long int) * CHAR_BIT - 2))
# define LLONG_MAX (HALF - 1 + HALF)
#endif
int
main ()
{
long long int n = 1;
int i;
for (i = 0; ; i++)
{
long long int m = n << i;
if (m >> i != n)
return 1;
if (LLONG_MAX / 2 < m)
break;
}
return 0;
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
else
ac_cv_type_long_long_int=no
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
fi
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_long_long_int" >&5
$as_echo "$ac_cv_type_long_long_int" >&6; }
if test $ac_cv_type_long_long_int = yes; then
$as_echo "#define HAVE_LONG_LONG_INT 1" >>confdefs.h
fi
ac_fn_c_check_type "$LINENO" "mode_t" "ac_cv_type_mode_t" "$ac_includes_default"
if test "x$ac_cv_type_mode_t" = xyes; then :
@ -5332,9 +5632,9 @@ ac_fn_c_check_type "$LINENO" "sig_atomic_t" "ac_cv_type_sig_atomic_t" "
"
if test "x$ac_cv_type_sig_atomic_t" = xyes; then :
else
$as_echo "#define sig_atomic_t int" >>confdefs.h
cat >>confdefs.h <<_ACEOF
#define HAVE_SIG_ATOMIC_T 1
_ACEOF
fi
@ -5674,7 +5974,6 @@ for ac_func in \
errx \
getcwd \
getenv \
getopt \
getwd \
killpg \
mmap \
@ -5682,15 +5981,23 @@ for ac_func in \
select \
setenv \
setpgid \
setrlimit \
setsid \
sigaction \
sigaddset \
sigpending \
sigprocmask \
sigsetmask \
sigsuspend \
sigvec \
snprintf \
strerror \
stresep \
strftime \
strsep \
strtod \
strtol \
strtoll \
strtoul \
sysctl \
unsetenv \
vsnprintf \
@ -5712,6 +6019,19 @@ fi
done
ac_fn_c_check_func "$LINENO" "getopt" "ac_cv_func_getopt"
if test "x$ac_cv_func_getopt" = xyes; then :
$as_echo "#define HAVE_GETOPT 1" >>confdefs.h
else
case " $LIBOBJS " in
*" getopt.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS getopt.$ac_objext"
;;
esac
fi
ac_fn_c_check_func "$LINENO" "realpath" "ac_cv_func_realpath"
if test "x$ac_cv_func_realpath" = xyes; then :
$as_echo "#define HAVE_REALPATH 1" >>confdefs.h
@ -5738,6 +6058,19 @@ esac
fi
ac_fn_c_check_func "$LINENO" "sigaction" "ac_cv_func_sigaction"
if test "x$ac_cv_func_sigaction" = xyes; then :
$as_echo "#define HAVE_SIGACTION 1" >>confdefs.h
else
case " $LIBOBJS " in
*" sigaction.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS sigaction.$ac_objext"
;;
esac
fi
ac_fn_c_check_func "$LINENO" "stresep" "ac_cv_func_stresep"
if test "x$ac_cv_func_stresep" = xyes; then :
$as_echo "#define HAVE_STRESEP 1" >>confdefs.h
@ -6006,13 +6339,19 @@ $as_echo "#define __func__ __FUNCTION__" >>confdefs.h
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
echo $ECHO_N "checking if diff -u works... $ECHO_C" >&6
if diff -u /dev/null /dev/null > /dev/null 2>&1; then
diff_u=-u
echo yes >&6
if test -x /usr/gnu/bin/diff; then
diff=/usr/gnu/bin/diff
diff_u=-u
else
diff_u=
echo no >&6
diff=${diff:-diff}
echo $ECHO_N "checking if $diff -u works... $ECHO_C" >&6
if $diff -u /dev/null /dev/null > /dev/null 2>&1; then
diff_u=-u
echo yes >&6
else
diff_u=
echo no >&6
fi
fi
echo "checking for MACHINE & MACHINE_ARCH..." >&6
cat > conftest.$ac_ext <<EOF
@ -6140,24 +6479,46 @@ do
done
mksrc=`echo $mksrc | sed "s,$srcdir,\\\${srcdir},"`
echo "Using: MKSRC=$mksrc" 1>&6
if test -x /usr/xpg4/bin/sh; then
defshell_path=${defshell_path:-/usr/xpg4/bin/sh}
fi
if test -n "$defshell_path"; then
for sh in /usr/xpg4/bin/sh $ALT_DEF_SHELLS
do
test -x $sh || continue
use_defshell $sh
break
done
case "$defshell_path$DEFSHELL_INDEX" in
"") ;;
*DEFSHELL_INDEX_CUSTOM)
echo "Using: SHELL=$defshell_path" >&6
cat >>confdefs.h <<_ACEOF
#define DEFSHELL_CUSTOM "$defshell_path"
_ACEOF
fi
if test -n "$DEFSHELL_INDEX"; then
;;
/*INDEX*)
echo "Using: SHELL=$DEFSHELL_INDEX ($defshell_path)" | sed 's,DEFSHELL_INDEX_,,' >&6
cat >>confdefs.h <<_ACEOF
#define DEFSHELL_INDEX $DEFSHELL_INDEX
_ACEOF
fi
cat >>confdefs.h <<_ACEOF
#define DEFSHELL_PATH "$defshell_path"
_ACEOF
;;
*)
echo "Using: SHELL=$DEFSHELL_INDEX" | sed 's,DEFSHELL_INDEX_,,' >&6
cat >>confdefs.h <<_ACEOF
#define DEFSHELL_INDEX $DEFSHELL_INDEX
_ACEOF
;;
esac
@ -6175,6 +6536,18 @@ bm_outfiles="Makefile.config unit-tests/Makefile.config make-bootstrap.sh"
if test $use_makefile = yes; then
bm_outfiles="makefile $bm_outfiles"
fi
here=`'pwd'`
: srcdir=$srcdir
: here= $here
case "$here" in
$srcdir/obj*) # make sure we put unit-tests/Makefile.config in the right place
obj=`basename $here`
mkdir -p $srcdir/unit-tests/$obj
test -d unit-tests || ln -s ../unit-tests/$obj unit-tests
;;
esac
ac_config_files="$ac_config_files $bm_outfiles"
cat >confcache <<\_ACEOF
@ -6684,7 +7057,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 20210201, which was
This file was extended by bmake $as_me 20211020, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@ -6746,7 +7119,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
bmake config.status 20210201
bmake config.status 20211020
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"

View File

@ -1,37 +1,53 @@
dnl
dnl RCSid:
dnl $Id: configure.in,v 1.70 2021/02/01 18:29:26 sjg Exp $
dnl $Id: configure.in,v 1.85 2021/10/23 20:57:08 sjg Exp $
dnl
dnl Process this file with autoconf to produce a configure script
dnl
AC_PREREQ(2.50)
AC_INIT([bmake], [20210201], [sjg@NetBSD.org])
AC_INIT([bmake], [20211020], [sjg@NetBSD.org])
AC_CONFIG_HEADERS(config.h)
dnl make srcdir absolute
case "$srcdir" in
/*) ;;
*) srcdir=`cd $srcdir && pwd`;;
*) srcdir=`cd $srcdir && 'pwd'`;;
esac
dnl get _MAKE_VERSION
. $srcdir/VERSION
OS=`uname -s`
dnl function to set DEFSHELL_INDEX
use_defshell() {
case "$defshell_path$DEFSHELL_INDEX" in
"") ;;
*) return 0;;
esac
case "$1" in
*csh) # we must be desperate
DEFSHELL_INDEX=DEFSHELL_INDEX_CSH;;
*ksh)
DEFSHELL_INDEX=DEFSHELL_INDEX_KSH;;
sh|/bin/sh)
DEFSHELL_INDEX=DEFSHELL_INDEX_SH;;
*) DEFSHELL_INDEX=DEFSHELL_INDEX_CUSTOM
defshell_path=$1
;;
esac
case "$1" in
/bin/*) ;;
*/*) defshell_path=$1;;
esac
}
dnl
AC_ARG_WITH(defshell,
[ --with-defshell=SHELL use SHELL by default - must be sh compatible, use sh or ksh to pick the internal definitions],
[case "${withval}" in
yes) AC_MSG_ERROR(bad value ${withval} given for bmake DEFSHELL) ;;
no) ;;
*) case "$with_defshell" in
sh) DEFSHELL_INDEX=DEFSHELL_INDEX_SH;; # it's the default anyway
ksh) DEFSHELL_INDEX=DEFSHELL_INDEX_KSH;;
csh) DEFSHELL_INDEX=DEFSHELL_INDEX_CSH;; # kidding right?
*) defshell_path=$with_defshell;; # better be sh compatible!
esac
;;
esac])
*) use_defshell $with_defshell;;
esac])
dnl
case "$OS" in
CYGWIN*|MINGW*) use_makefile=no;;
@ -97,6 +113,45 @@ yes)
esac
dnl
dnl Check for OS problems
dnl
dnl Minix 3 at least has bugs in headers where _NETBSD_SOURCE
dnl is needed for compilation
case "$OS" in
Minix) CPPFLAGS="${CPPFLAGS} -D_NETBSD_SOURCE"
test -x /usr/pkg/bin/clang && CC=${CC:-clang}
;;
SCO_SV) # /bin/sh is not usable
ALT_DEF_SHELLS="/bin/lsh /usr/bin/bash /bin/ksh"
CPPFLAGS="${CPPFLAGS} -DFORCE_USE_SHELL"
;;
esac
dnl
dnl Not everyone groks TZ=Europe/Berlin
dnl which is used by the localtime tests
echo $ECHO_N "checking whether system has timezone Europe/Berlin... $ECHO_C" >&6
if test -f /usr/share/zoneinfo/Europe/Berlin; then
echo yes >&6
# seems a safe bet
UTC_1=Europe/Berlin
else
utcH=`TZ=UTC date +%H 2> /dev/null`
utc_1H=`TZ=UTC-1 date +%H 2> /dev/null`
if test ${utcH-0} -lt ${utc_1H-0}; then
UTC_1=UTC-1
echo no, using UTC-1 >&6
else
echo no >&6
fi
fi
dnl
dnl Add some places to look for compilers
oldPATH=$PATH
for d in /usr/gnu/bin
do
test -d $d || continue
PATH=$PATH:$d
done
export PATH
dnl Solaris's signal.h only privides sigset_t etc if one of
dnl _EXTENSIONS_ _POSIX_C_SOURCE or _XOPEN_SOURCE are defined.
dnl The later two seem to cause more problems than they solve so if we
@ -126,7 +181,33 @@ AC_SUBST(bmake_path_max)dnl
dnl
dnl AC_C_CROSS
dnl
dnl if type does not work which(1) had better!
dnl note we cannot rely on type returning non-zero on failure
if (type cat) > /dev/null 2>&1; then
: which
which() {
type "$@" | sed 's,[[()]],,g;s,^[[^/]][[^/]]*,,;q'
}
fi
dnl if CC is somewhere that was not in PATH we need its full path
dnl watch out for included flags!
case "$CC" in
/*) ;;
*)
for x in $CC
do
_cc=`which $x`
break
done
if test -x ${_cc:-/dev/null}; then
_cc_dir=`dirname $_cc`
case ":$oldPATH:" in
*:$_cc_dir:*) ;;
*) CC=$_cc_dir/$CC;;
esac
fi
;;
esac
dnl Checks for header files.
AC_HEADER_SYS_WAIT
AC_HEADER_DIRENT
@ -158,24 +239,16 @@ AC_CHECK_HEADERS( \
dnl Both *BSD and Linux have sys/cdefs.h, most do not.
dnl If it is missing, we add -I${srcdir}/missing to CFLAGS
dnl also if sys/cdefs.h does not have __RCSID we need to use ours
dnl but we need to include the host's one too *sigh*
AC_CHECK_HEADER(sys/cdefs.h,
echo $ECHO_N "checking whether sys/cdefs.h is compatible... $ECHO_C" >&6
AC_EGREP_CPP(yes,
[#include <sys/cdefs.h>
#ifdef __RCSID
yes
#endif
],
echo yes >&6,
echo no >&6; CPPFLAGS="${CPPFLAGS} -I`cd ${srcdir}/missing && pwd` -DNEED_HOST_CDEFS_H"),
AC_CHECK_HEADER(sys/cdefs.h,,
CPPFLAGS="${CPPFLAGS} -I`cd ${srcdir}/missing && pwd`")
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C___ATTRIBUTE__
AC_C_BIGENDIAN
AC_C_CONST
AC_C_INLINE
AC_TYPE_INT64_T
AC_TYPE_LONG_LONG_INT
AC_TYPE_MODE_T
AC_TYPE_OFF_T
AC_TYPE_PID_T
@ -187,9 +260,8 @@ AC_STRUCT_TM
dnl we need sig_atomic_t
AH_TEMPLATE([sig_atomic_t],[type that signal handlers can safely frob])
AC_CHECK_TYPE(sig_atomic_t,,[
AC_DEFINE([sig_atomic_t],[int],)
],[
AC_CHECK_TYPES([sig_atomic_t],[],[],
[
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
@ -207,7 +279,6 @@ AC_CHECK_FUNCS( \
errx \
getcwd \
getenv \
getopt \
getwd \
killpg \
mmap \
@ -215,15 +286,23 @@ AC_CHECK_FUNCS( \
select \
setenv \
setpgid \
setrlimit \
setsid \
sigaction \
sigaddset \
sigpending \
sigprocmask \
sigsetmask \
sigsuspend \
sigvec \
snprintf \
strerror \
stresep \
strftime \
strsep \
strtod \
strtol \
strtoll \
strtoul \
sysctl \
unsetenv \
vsnprintf \
@ -236,8 +315,10 @@ AC_CHECK_FUNCS( \
dnl functions which we may need to provide
AC_REPLACE_FUNCS( \
getopt \
realpath \
dirname \
sigaction \
stresep \
strlcpy \
)
@ -261,13 +342,20 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[[const char *func = __func__;]])],,
AC_DEFINE(__func__, __FUNCTION__, C99 function name))
dnl
dnl we want this for unit-tests/Makefile
echo $ECHO_N "checking if diff -u works... $ECHO_C" >&6
if diff -u /dev/null /dev/null > /dev/null 2>&1; then
diff_u=-u
echo yes >&6
dnl GNU diff is known to support -u
if test -x /usr/gnu/bin/diff; then
diff=/usr/gnu/bin/diff
diff_u=-u
else
diff_u=
echo no >&6
diff=${diff:-diff}
echo $ECHO_N "checking if $diff -u works... $ECHO_C" >&6
if $diff -u /dev/null /dev/null > /dev/null 2>&1; then
diff_u=-u
echo yes >&6
else
diff_u=
echo no >&6
fi
fi
dnl
dnl AC_* don't quite cut it.
@ -404,16 +492,28 @@ done
mksrc=`echo $mksrc | sed "s,$srcdir,\\\${srcdir},"`
echo "Using: MKSRC=$mksrc" 1>&6
dnl On some systems we want a different default shell by default
if test -x /usr/xpg4/bin/sh; then
defshell_path=${defshell_path:-/usr/xpg4/bin/sh}
fi
if test -n "$defshell_path"; then
for sh in /usr/xpg4/bin/sh $ALT_DEF_SHELLS
do
test -x $sh || continue
use_defshell $sh
break
done
case "$defshell_path$DEFSHELL_INDEX" in
"") ;;
*DEFSHELL_INDEX_CUSTOM)
echo "Using: SHELL=$defshell_path" >&6
AC_DEFINE_UNQUOTED(DEFSHELL_CUSTOM, "$defshell_path", Path of default shell)
fi
if test -n "$DEFSHELL_INDEX"; then
AC_DEFINE_UNQUOTED(DEFSHELL_INDEX, $DEFSHELL_INDEX, Shell spec to use by default)
fi
;;
/*INDEX*)
echo "Using: SHELL=$DEFSHELL_INDEX ($defshell_path)" | sed 's,DEFSHELL_INDEX_,,' >&6
AC_DEFINE_UNQUOTED(DEFSHELL_INDEX, $DEFSHELL_INDEX, Shell spec to use by default)
AC_DEFINE_UNQUOTED(DEFSHELL_PATH, "$defshell_path", Path of default shell)
;;
*)
echo "Using: SHELL=$DEFSHELL_INDEX" | sed 's,DEFSHELL_INDEX_,,' >&6
AC_DEFINE_UNQUOTED(DEFSHELL_INDEX, $DEFSHELL_INDEX, Shell spec to use by default)
;;
esac
dnl
AC_SUBST(machine)
AC_SUBST(force_machine)
@ -423,15 +523,29 @@ AC_SUBST(mksrc)
AC_SUBST(default_sys_path)
AC_SUBST(INSTALL)
AC_SUBST(GCC)
AC_SUBST(diff)
AC_SUBST(diff_u)
AC_SUBST(use_meta)
AC_SUBST(use_filemon)
AC_SUBST(filemon_h)
AC_SUBST(_MAKE_VERSION)
AC_SUBST(UTC_1)
bm_outfiles="Makefile.config unit-tests/Makefile.config make-bootstrap.sh"
if test $use_makefile = yes; then
bm_outfiles="makefile $bm_outfiles"
fi
here=`'pwd'`
: srcdir=$srcdir
: here= $here
case "$here" in
$srcdir/obj*) # make sure we put unit-tests/Makefile.config in the right place
obj=`basename $here`
mkdir -p $srcdir/unit-tests/$obj
test -d unit-tests || ln -s ../unit-tests/$obj unit-tests
;;
esac
AC_OUTPUT($bm_outfiles)
cat <<EOF

View File

@ -1,4 +1,4 @@
/* $NetBSD: dir.c,v 1.272 2021/04/04 10:13:09 rillig Exp $ */
/* $NetBSD: dir.c,v 1.275 2021/11/28 21:46:17 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@ -138,7 +138,7 @@
#include "job.h"
/* "@(#)dir.c 8.2 (Berkeley) 1/2/94" */
MAKE_RCSID("$NetBSD: dir.c,v 1.272 2021/04/04 10:13:09 rillig Exp $");
MAKE_RCSID("$NetBSD: dir.c,v 1.275 2021/11/28 21:46:17 rillig Exp $");
/*
* A search path is a list of CachedDir structures. A CachedDir has in it the
@ -246,12 +246,6 @@ typedef struct OpenDirs {
HashTable /* of CachedDirListNode */ table;
} OpenDirs;
typedef enum CachedStatsFlags {
CST_NONE = 0,
CST_LSTAT = 1 << 0, /* call lstat(2) instead of stat(2) */
CST_UPDATE = 1 << 1 /* ignore existing cached entry */
} CachedStatsFlags;
SearchPath dirSearchPath = { LST_INIT }; /* main search path */
@ -419,9 +413,9 @@ OpenDirs_Remove(OpenDirs *odirs, const char *name)
*/
static int
cached_stats(const char *pathname, struct cached_stat *out_cst,
CachedStatsFlags flags)
bool useLstat, bool forceRefresh)
{
HashTable *tbl = flags & CST_LSTAT ? &lmtimes : &mtimes;
HashTable *tbl = useLstat ? &lmtimes : &mtimes;
struct stat sys_st;
struct cached_stat *cst;
int rc;
@ -430,14 +424,14 @@ cached_stats(const char *pathname, struct cached_stat *out_cst,
return -1; /* This can happen in meta mode. */
cst = HashTable_FindValue(tbl, pathname);
if (cst != NULL && !(flags & CST_UPDATE)) {
if (cst != NULL && !forceRefresh) {
*out_cst = *cst;
DEBUG2(DIR, "Using cached time %s for %s\n",
Targ_FmtTime(cst->cst_mtime), pathname);
return 0;
}
rc = (flags & CST_LSTAT ? lstat : stat)(pathname, &sys_st);
rc = (useLstat ? lstat : stat)(pathname, &sys_st);
if (rc == -1)
return -1; /* don't cache negative lookups */
@ -462,13 +456,13 @@ cached_stats(const char *pathname, struct cached_stat *out_cst,
int
cached_stat(const char *pathname, struct cached_stat *cst)
{
return cached_stats(pathname, cst, CST_NONE);
return cached_stats(pathname, cst, false, false);
}
int
cached_lstat(const char *pathname, struct cached_stat *cst)
{
return cached_stats(pathname, cst, CST_LSTAT);
return cached_stats(pathname, cst, true, false);
}
/* Initialize the directories module. */
@ -1127,9 +1121,8 @@ FindFileRelative(SearchPath *path, bool seenDotLast,
}
static bool
FindFileAbsolute(SearchPath *path, bool const seenDotLast,
const char *const name, const char *const base,
char **out_file)
FindFileAbsolute(SearchPath *path, bool seenDotLast,
const char *name, const char *base, char **out_file)
{
char *file;
SearchPathNode *ln;
@ -1448,7 +1441,7 @@ ResolveFullName(GNode *gn)
fullName = Dir_FindFile(gn->name, Suff_FindPath(gn));
if (fullName == NULL && gn->flags & FROM_DEPEND &&
if (fullName == NULL && gn->flags.fromDepend &&
!Lst_IsEmpty(&gn->implicitParents))
fullName = ResolveMovedDepends(gn);
@ -1471,7 +1464,7 @@ ResolveFullName(GNode *gn)
* The found file is stored in gn->path, unless the node already had a path.
*/
void
Dir_UpdateMTime(GNode *gn, bool recheck)
Dir_UpdateMTime(GNode *gn, bool forceRefresh)
{
char *fullName;
struct cached_stat cst;
@ -1488,7 +1481,7 @@ Dir_UpdateMTime(GNode *gn, bool recheck)
fullName = ResolveFullName(gn);
if (cached_stats(fullName, &cst, recheck ? CST_UPDATE : CST_NONE) < 0) {
if (cached_stats(fullName, &cst, false, forceRefresh) < 0) {
if (gn->type & OP_MEMBER) {
if (fullName != gn->path)
free(fullName);

View File

@ -1,80 +0,0 @@
/* $NetBSD: enum.c,v 1.15 2021/02/02 17:56:31 rillig Exp $ */
/*
Copyright (c) 2020 Roland Illig <rillig@NetBSD.org>
All rights reserved.
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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*/
#include "make.h"
MAKE_RCSID("$NetBSD: enum.c,v 1.15 2021/02/02 17:56:31 rillig Exp $");
/*
* Convert a bitset into a string representation, showing the names of the
* individual bits.
*
* Optionally, shortcuts for groups of bits can be added. To have an effect,
* they need to be listed before their individual bits.
*/
const char *
Enum_FlagsToString(char *buf, size_t buf_size,
int value, const EnumToStringSpec *spec)
{
const char *buf_start = buf;
const char *sep = "";
size_t sep_len = 0;
for (; spec->es_value != 0; spec++) {
size_t name_len;
if ((value & spec->es_value) != spec->es_value)
continue;
value &= ~spec->es_value;
assert(buf_size >= sep_len + 1);
memcpy(buf, sep, sep_len);
buf += sep_len;
buf_size -= sep_len;
name_len = strlen(spec->es_name);
assert(buf_size >= name_len + 1);
memcpy(buf, spec->es_name, name_len);
buf += name_len;
buf_size -= name_len;
sep = ENUM__SEP;
sep_len = sizeof ENUM__SEP - 1;
}
/* If this assertion fails, the listed enum values are incomplete. */
assert(value == 0);
if (buf == buf_start)
return "none";
assert(buf_size >= 1);
buf[0] = '\0';
return buf_start;
}

View File

@ -1,179 +0,0 @@
/* $NetBSD: enum.h,v 1.19 2021/03/15 16:00:05 rillig Exp $ */
/*
Copyright (c) 2020 Roland Illig <rillig@NetBSD.org>
All rights reserved.
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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 MAKE_ENUM_H
#define MAKE_ENUM_H
/* Generate string representations for bitmasks and simple enums. */
#include <stddef.h>
typedef struct EnumToStringSpec {
int es_value;
const char *es_name;
} EnumToStringSpec;
const char *Enum_FlagsToString(char *, size_t, int, const EnumToStringSpec *);
/* For Enum_FlagsToString, the separator between flags. */
#define ENUM__SEP "|"
/*
* Generate the string that joins all possible flags, to see how large the
* buffer must be.
*/
#define ENUM__JOIN_STR_1(v1) \
#v1
#define ENUM__JOIN_STR_2(v1, v2) \
ENUM__JOIN_STR_1(v1) ENUM__SEP \
ENUM__JOIN_STR_1(v2)
#define ENUM__JOIN_STR_4(v1, v2, v3, v4) \
ENUM__JOIN_STR_2(v1, v2) ENUM__SEP \
ENUM__JOIN_STR_2(v3, v4)
#define ENUM__JOIN_STR_8(v1, v2, v3, v4, v5, v6, v7, v8) \
ENUM__JOIN_STR_4(v1, v2, v3, v4) ENUM__SEP \
ENUM__JOIN_STR_4(v5, v6, v7, v8)
#define ENUM__JOIN_STR_16(v01, v02, v03, v04, v05, v06, v07, v08, \
v09, v10, v11, v12, v13, v14, v15, v16) \
ENUM__JOIN_STR_8(v01, v02, v03, v04, v05, v06, v07, v08) ENUM__SEP \
ENUM__JOIN_STR_8(v09, v10, v11, v12, v13, v14, v15, v16)
#define ENUM__JOIN_2(part1, part2) \
part1 ENUM__SEP part2
#define ENUM__JOIN_3(part1, part2, part3) \
part1 ENUM__SEP part2 ENUM__SEP part3
#define ENUM__JOIN_4(part1, part2, part3, part4) \
part1 ENUM__SEP part2 ENUM__SEP part3 ENUM__SEP part4
#define ENUM__JOIN_5(part1, part2, part3, part4, part5) \
part1 ENUM__SEP part2 ENUM__SEP part3 ENUM__SEP part4 ENUM__SEP part5
/* List the pairs of enum value and corresponding name. */
#define ENUM__SPEC_1(v1) \
{ v1, #v1 }
#define ENUM__SPEC_2(v1, v2) \
ENUM__SPEC_1(v1), \
ENUM__SPEC_1(v2)
#define ENUM__SPEC_4(v1, v2, v3, v4) \
ENUM__SPEC_2(v1, v2), \
ENUM__SPEC_2(v3, v4)
#define ENUM__SPEC_8(v1, v2, v3, v4, v5, v6, v7, v8) \
ENUM__SPEC_4(v1, v2, v3, v4), \
ENUM__SPEC_4(v5, v6, v7, v8)
#define ENUM__SPEC_16(v01, v02, v03, v04, v05, v06, v07, v08, \
v09, v10, v11, v12, v13, v14, v15, v16) \
ENUM__SPEC_8(v01, v02, v03, v04, v05, v06, v07, v08), \
ENUM__SPEC_8(v09, v10, v11, v12, v13, v14, v15, v16)
#define ENUM__SPECS_2(part1, part2) \
{ part1, part2, { 0, "" } }
#define ENUM__SPECS_3(part1, part2, part3) \
{ part1, part2, part3, { 0, "" } }
#define ENUM__SPECS_4(part1, part2, part3, part4) \
{ part1, part2, part3, part4, { 0, "" } }
#define ENUM__SPECS_5(part1, part2, part3, part4, part5) \
{ part1, part2, part3, part4, part5, { 0, "" } }
/* Declare the necessary data structures for calling Enum_FlagsToString. */
#define ENUM__FLAGS_RTTI(typnam, specs, joined) \
static const EnumToStringSpec typnam ## _ ## ToStringSpecs[] = specs; \
enum { typnam ## _ ## ToStringSize = sizeof (joined) }; \
MAKE_INLINE const char *typnam ## _ToString(char *buf, typnam value) \
{ return Enum_FlagsToString(buf, typnam ## _ ## ToStringSize, \
value, typnam ## _ ## ToStringSpecs); \
} \
extern void enum_flags_rtti_dummy(void)
/*
* Declare the necessary data structures for calling Enum_FlagsToString
* for an enum with 3 flags.
*/
#define ENUM_FLAGS_RTTI_3(typnam, v1, v2, v3) \
ENUM__FLAGS_RTTI(typnam, \
ENUM__SPECS_2( \
ENUM__SPEC_2(v1, v2), \
ENUM__SPEC_1(v3)), \
ENUM__JOIN_2( \
ENUM__JOIN_STR_2(v1, v2), \
ENUM__JOIN_STR_1(v3)))
/*
* Declare the necessary data structures for calling Enum_FlagsToString
* for an enum with 6 flags.
*/
#define ENUM_FLAGS_RTTI_6(typnam, v1, v2, v3, v4, v5, v6) \
ENUM__FLAGS_RTTI(typnam, \
ENUM__SPECS_2( \
ENUM__SPEC_4(v1, v2, v3, v4), \
ENUM__SPEC_2(v5, v6)), \
ENUM__JOIN_2( \
ENUM__JOIN_STR_4(v1, v2, v3, v4), \
ENUM__JOIN_STR_2(v5, v6)))
/*
* Declare the necessary data structures for calling Enum_FlagsToString
* for an enum with 9 flags.
*/
#define ENUM_FLAGS_RTTI_9(typnam, v1, v2, v3, v4, v5, v6, v7, v8, v9) \
ENUM__FLAGS_RTTI(typnam, \
ENUM__SPECS_2( \
ENUM__SPEC_8(v1, v2, v3, v4, v5, v6, v7, v8), \
ENUM__SPEC_1(v9)), \
ENUM__JOIN_2( \
ENUM__JOIN_STR_8(v1, v2, v3, v4, v5, v6, v7, v8), \
ENUM__JOIN_STR_1(v9)))
/*
* Declare the necessary data structures for calling Enum_FlagsToString
* for an enum with 31 flags.
*/
#define ENUM_FLAGS_RTTI_31(typnam, \
v01, v02, v03, v04, v05, v06, v07, v08, \
v09, v10, v11, v12, v13, v14, v15, v16, \
v17, v18, v19, v20, v21, v22, v23, v24, \
v25, v26, v27, v28, v29, v30, v31) \
ENUM__FLAGS_RTTI(typnam, \
ENUM__SPECS_5( \
ENUM__SPEC_16(v01, v02, v03, v04, v05, v06, v07, v08, \
v09, v10, v11, v12, v13, v14, v15, v16), \
ENUM__SPEC_8(v17, v18, v19, v20, v21, v22, v23, v24), \
ENUM__SPEC_4(v25, v26, v27, v28), \
ENUM__SPEC_2(v29, v30), \
ENUM__SPEC_1(v31)), \
ENUM__JOIN_5( \
ENUM__JOIN_STR_16(v01, v02, v03, v04, v05, v06, v07, v08, \
v09, v10, v11, v12, v13, v14, v15, v16), \
ENUM__JOIN_STR_8(v17, v18, v19, v20, v21, v22, v23, v24), \
ENUM__JOIN_STR_4(v25, v26, v27, v28), \
ENUM__JOIN_STR_2(v29, v30), \
ENUM__JOIN_STR_1(v31)))
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: filemon_ktrace.c,v 1.14 2021/02/01 21:34:41 rillig Exp $ */
/* $NetBSD: filemon_ktrace.c,v 1.15 2021/07/31 09:30:17 rillig Exp $ */
/*
* Copyright (c) 2019 The NetBSD Foundation, Inc.
@ -227,7 +227,6 @@ filemon_open(void)
/* Success! */
return F;
(void)fclose(F->in);
fail1: (void)close(ktrpipe[0]);
(void)close(ktrpipe[1]);
fail0: free(F);

View File

@ -1,4 +1,4 @@
/* $NetBSD: for.c,v 1.142 2021/04/03 11:08:40 rillig Exp $ */
/* $NetBSD: for.c,v 1.150 2021/12/12 15:44:41 rillig Exp $ */
/*
* Copyright (c) 1992, The Regents of the University of California.
@ -45,9 +45,9 @@
*
* After reaching the .endfor, the values from the .for line are grouped
* according to the number of variables. For each such group, the unexpanded
* body is scanned for variable expressions, and those that match the variable
* names are replaced with expressions of the form ${:U...} or $(:U...).
* After that, the body is treated like a file from an .include directive.
* body is scanned for variable expressions, and those that match the
* variable names are replaced with expressions of the form ${:U...}. After
* that, the body is treated like a file from an .include directive.
*
* Interface:
* For_Eval Evaluate the loop in the passed line.
@ -58,7 +58,7 @@
#include "make.h"
/* "@(#)for.c 8.1 (Berkeley) 6/6/93" */
MAKE_RCSID("$NetBSD: for.c,v 1.142 2021/04/03 11:08:40 rillig Exp $");
MAKE_RCSID("$NetBSD: for.c,v 1.150 2021/12/12 15:44:41 rillig Exp $");
/* One of the variables to the left of the "in" in a .for loop. */
@ -70,17 +70,13 @@ typedef struct ForVar {
typedef struct ForLoop {
Buffer body; /* Unexpanded body of the loop */
Vector /* of ForVar */ vars; /* Iteration variables */
Words items; /* Substitution items */
SubstringWords items; /* Substitution items */
Buffer curBody; /* Expanded body of the current iteration */
/* Is any of the names 1 character long? If so, when the variable values
* are substituted, the parser must handle $V expressions as well, not
* only ${V} and $(V). */
bool short_var;
unsigned int sub_next; /* Where to continue iterating */
unsigned int nextItem; /* Where to continue iterating */
} ForLoop;
static ForLoop *accumFor; /* Loop being accumulated */
static ForLoop *accumFor; /* Loop being accumulated */
static int forLevel = 0; /* Nesting level */
@ -91,11 +87,9 @@ ForLoop_New(void)
Buf_Init(&f->body);
Vector_Init(&f->vars, sizeof(ForVar));
f->items.words = NULL;
f->items.freeIt = NULL;
SubstringWords_Init(&f->items);
Buf_Init(&f->curBody);
f->short_var = false;
f->sub_next = 0;
f->nextItem = 0;
return f;
}
@ -111,7 +105,7 @@ ForLoop_Free(ForLoop *f)
}
Vector_Done(&f->vars);
Words_Free(f->items);
SubstringWords_Free(f->items);
Buf_Done(&f->curBody);
free(f);
@ -150,8 +144,6 @@ ForLoop_ParseVarnames(ForLoop *f, const char **pp)
p += 2;
break;
}
if (len == 1)
f->short_var = true;
ForLoop_AddVar(f, p, len);
p += len;
@ -178,10 +170,10 @@ ForLoop_ParseItems(ForLoop *f, const char *p)
return false;
}
f->items = Str_Words(items, false);
f->items = Substring_Words(items, false);
free(items);
if (f->items.len == 1 && f->items.words[0][0] == '\0')
if (f->items.len == 1 && Substring_IsEmpty(f->items.words[0]))
f->items.len = 0; /* .for var in ${:U} */
if (f->items.len != 0 && f->items.len % f->vars.len != 0) {
@ -285,33 +277,32 @@ For_Accum(const char *line)
static size_t
for_var_len(const char *var)
ExprLen(const char *s, const char *e)
{
char ch, var_start, var_end;
char expr_open, expr_close;
int depth;
size_t len;
const char *p;
var_start = *var;
if (var_start == '\0')
/* just escape the $ */
return 0;
if (s == e)
return 0; /* just escape the '$' */
if (var_start == '(')
var_end = ')';
else if (var_start == '{')
var_end = '}';
expr_open = s[0];
if (expr_open == '(')
expr_close = ')';
else if (expr_open == '{')
expr_close = '}';
else
return 1; /* Single char variable */
depth = 1;
for (len = 1; (ch = var[len++]) != '\0';) {
if (ch == var_start)
for (p = s + 1; p != e; p++) {
if (*p == expr_open)
depth++;
else if (ch == var_end && --depth == 0)
return len;
else if (*p == expr_close && --depth == 0)
return (size_t)(p + 1 - s);
}
/* Variable end not found, escape the $ */
/* Expression end not found, escape the $ */
return 0;
}
@ -320,12 +311,13 @@ for_var_len(const char *var)
* that characters that break this syntax must be backslash-escaped.
*/
static bool
NeedsEscapes(const char *value, char endc)
NeedsEscapes(Substring value, char endc)
{
const char *p;
for (p = value; *p != '\0'; p++) {
if (*p == ':' || *p == '$' || *p == '\\' || *p == endc)
for (p = value.start; p != value.end; p++) {
if (*p == ':' || *p == '$' || *p == '\\' || *p == endc ||
*p == '\n')
return true;
}
return false;
@ -338,34 +330,44 @@ NeedsEscapes(const char *value, char endc)
* The result is later unescaped by ApplyModifier_Defined.
*/
static void
Buf_AddEscaped(Buffer *cmds, const char *item, char endc)
Buf_AddEscaped(Buffer *cmds, Substring item, char endc)
{
const char *p;
char ch;
if (!NeedsEscapes(item, endc)) {
Buf_AddStr(cmds, item);
Buf_AddBytesBetween(cmds, item.start, item.end);
return;
}
/* Escape ':', '$', '\\' and 'endc' - these will be removed later by
* :U processing, see ApplyModifier_Defined. */
while ((ch = *item++) != '\0') {
for (p = item.start; p != item.end; p++) {
ch = *p;
if (ch == '$') {
size_t len = for_var_len(item);
size_t len = ExprLen(p + 1, item.end);
if (len != 0) {
Buf_AddBytes(cmds, item - 1, len + 1);
item += len;
/*
* XXX: Should a '\' be added here?
* See directive-for-escape.mk, ExprLen.
*/
Buf_AddBytes(cmds, p, 1 + len);
p += len;
continue;
}
Buf_AddByte(cmds, '\\');
} else if (ch == ':' || ch == '\\' || ch == endc)
Buf_AddByte(cmds, '\\');
else if (ch == '\n') {
Parse_Error(PARSE_FATAL, "newline in .for value");
ch = ' '; /* prevent newline injection */
}
Buf_AddByte(cmds, ch);
}
}
/*
* While expanding the body of a .for loop, replace the variable name of an
* When expanding the body of a .for loop, replace the variable name of an
* expression like ${i} or ${i:...} or $(i) or $(i:...) with ":Uvalue".
*/
static void
@ -376,8 +378,8 @@ ForLoop_SubstVarLong(ForLoop *f, const char **pp, const char *bodyEnd,
const char *p = *pp;
for (i = 0; i < f->vars.len; i++) {
ForVar *forVar = Vector_Get(&f->vars, i);
char *varname = forVar->name;
const ForVar *forVar = Vector_Get(&f->vars, i);
const char *varname = forVar->name;
size_t varnameLen = forVar->nameLen;
if (varnameLen >= (size_t)(bodyEnd - p))
@ -396,7 +398,7 @@ ForLoop_SubstVarLong(ForLoop *f, const char **pp, const char *bodyEnd,
Buf_AddBytesBetween(&f->curBody, *inout_mark, p);
Buf_AddStr(&f->curBody, ":U");
Buf_AddEscaped(&f->curBody,
f->items.words[f->sub_next + i], endc);
f->items.words[f->nextItem + i], endc);
p += varnameLen;
*inout_mark = p;
@ -406,18 +408,18 @@ ForLoop_SubstVarLong(ForLoop *f, const char **pp, const char *bodyEnd,
}
/*
* While expanding the body of a .for loop, replace single-character
* When expanding the body of a .for loop, replace single-character
* variable expressions like $i with their ${:U...} expansion.
*/
static void
ForLoop_SubstVarShort(ForLoop *f, const char *p, const char **inout_mark)
{
const char ch = *p;
ForVar *vars;
const ForVar *vars;
size_t i;
/* Skip $$ and stupid ones. */
if (!f->short_var || strchr("}):$", ch) != NULL)
if (ch == '}' || ch == ')' || ch == ':' || ch == '$')
return;
vars = Vector_Get(&f->vars, 0);
@ -429,10 +431,12 @@ ForLoop_SubstVarShort(ForLoop *f, const char *p, const char **inout_mark)
return;
found:
Buf_AddBytesBetween(&f->curBody, *inout_mark, p);
*inout_mark = p + 1;
/* Replace $<ch> with ${:U<value>} */
Buf_AddBytesBetween(&f->curBody, *inout_mark, p), *inout_mark = p + 1;
Buf_AddStr(&f->curBody, "{:U");
Buf_AddEscaped(&f->curBody, f->items.words[f->sub_next + i], '}');
Buf_AddEscaped(&f->curBody, f->items.words[f->nextItem + i], '}');
Buf_AddByte(&f->curBody, '}');
}
@ -446,14 +450,14 @@ ForLoop_SubstVarShort(ForLoop *f, const char *p, const char **inout_mark)
* defined, see unit-tests/varname-empty.mk for more details.
*
* The detection of substitutions of the loop control variables is naive.
* Many of the modifiers use '\' to escape '$' (not '$'), so it is possible
* to contrive a makefile where an unwanted substitution happens.
* Many of the modifiers use '\$' instead of '$$' to escape '$', so it is
* possible to contrive a makefile where an unwanted substitution happens.
*/
static void
ForLoop_SubstBody(ForLoop *f)
{
const char *p, *bodyEnd;
const char *mark; /* where the last replacement left off */
const char *mark; /* where the last substitution left off */
Buf_Empty(&f->curBody);
@ -461,9 +465,9 @@ ForLoop_SubstBody(ForLoop *f)
bodyEnd = f->body.data + f->body.len;
for (p = mark; (p = strchr(p, '$')) != NULL;) {
if (p[1] == '{' || p[1] == '(') {
char endc = p[1] == '{' ? '}' : ')';
p += 2;
ForLoop_SubstVarLong(f, &p, bodyEnd,
p[-1] == '{' ? '}' : ')', &mark);
ForLoop_SubstVarLong(f, &p, bodyEnd, endc, &mark);
} else if (p[1] != '\0') {
ForLoop_SubstVarShort(f, p + 1, &mark);
p += 2;
@ -483,7 +487,7 @@ ForReadMore(void *v_arg, size_t *out_len)
{
ForLoop *f = v_arg;
if (f->sub_next == f->items.len) {
if (f->nextItem == f->items.len) {
/* No more iterations */
ForLoop_Free(f);
return NULL;
@ -491,7 +495,7 @@ ForReadMore(void *v_arg, size_t *out_len)
ForLoop_SubstBody(f);
DEBUG1(FOR, "For: loop body:\n%s", f->curBody.data);
f->sub_next += (unsigned int)f->vars.len;
f->nextItem += (unsigned int)f->vars.len;
*out_len = f->curBody.len;
return f->curBody.data;
@ -513,5 +517,5 @@ For_Run(int lineno)
return;
}
Parse_SetInput(NULL, lineno, -1, ForReadMore, f);
Parse_PushInput(NULL, lineno, -1, ForReadMore, f);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: hash.c,v 1.64 2021/04/11 12:46:54 rillig Exp $ */
/* $NetBSD: hash.c,v 1.66 2021/12/07 21:58:01 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@ -74,7 +74,7 @@
#include "make.h"
/* "@(#)hash.c 8.1 (Berkeley) 6/6/93" */
MAKE_RCSID("$NetBSD: hash.c,v 1.64 2021/04/11 12:46:54 rillig Exp $");
MAKE_RCSID("$NetBSD: hash.c,v 1.66 2021/12/07 21:58:01 rillig Exp $");
/*
* The ratio of # entries to # buckets at which we rebuild the table to
@ -152,7 +152,7 @@ HashTable_FindEntryBySubstring(HashTable *t, Substring key, unsigned int h)
unsigned int chainlen = 0;
#ifdef DEBUG_HASH_LOOKUP
DEBUG4(HASH, "%s: %p h=%08x key=%.*s\n", __func__, t, h,
DEBUG5(HASH, "%s: %p h=%08x key=%.*s\n", __func__, t, h,
(int)Substring_Length(key), key.start);
#endif
@ -333,15 +333,6 @@ HashTable_DeleteEntry(HashTable *t, HashEntry *he)
abort();
}
/* Set things up for iterating over all entries in the hash table. */
void
HashIter_Init(HashIter *hi, HashTable *t)
{
hi->table = t;
hi->nextBucket = 0;
hi->entry = NULL;
}
/*
* Return the next entry in the hash table, or NULL if the end of the table
* is reached.

View File

@ -1,4 +1,4 @@
/* $NetBSD: hash.h,v 1.40 2021/04/11 12:46:54 rillig Exp $ */
/* $NetBSD: hash.h,v 1.41 2021/12/07 21:58:01 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@ -120,6 +120,15 @@ HashEntry_Set(HashEntry *h, void *datum)
h->value = datum;
}
/* Set things up for iterating over all entries in the hash table. */
MAKE_INLINE void
HashIter_Init(HashIter *hi, HashTable *t)
{
hi->table = t;
hi->nextBucket = 0;
hi->entry = NULL;
}
void HashTable_Init(HashTable *);
void HashTable_Done(HashTable *);
HashEntry *HashTable_FindEntry(HashTable *, const char *);

View File

@ -26,6 +26,7 @@ option_parsing() {
*=*) eval "$1"; shift;;
--) shift; break;;
-a) TARBALL=$2; shift 2;;
-d) RM=echo; shift;;
-n) ECHO=echo; shift;;
-P) PR=$2; shift 2;;
-r) REVIEWER=$2; shift 2;;
@ -55,6 +56,7 @@ TF=/tmp/.$USER.$$
Cd `dirname $0`
test -s ${TARBALL:-/dev/null} || Error need TARBALL
here=`pwd`
SB=${SB:-`dirname $here`}
# thing should match what the TARBALL contains
thing=`basename $here`
@ -66,7 +68,7 @@ esac
VERSION=`grep '^_MAKE_VERSION' VERSION | sed 's,.*=[[:space:]]*,,'`
rm -f *~
mkdir -p ../tmp
mkdir -p $SB/tmp
# new files are handled automatically
# but we need to rm if needed
@ -81,12 +83,15 @@ comm -13 $TF.adds $TF.rms > $TF.rm
if [ -z "$ECHO" ]; then
test -s $TF.rm && xargs rm -f < $TF.rm
$GIT add -A
$GIT diff --staged | tee ../tmp/bmake-import.diff
echo "$GIT tag -a vendor/NetBSD/bmake/$VERSION" > ../tmp/bmake-post.sh
echo "After you commit, run $here/../tmp/bmake-post.sh"
$GIT diff --staged | tee $SB/tmp/bmake-import.diff
{ echo "$GIT tag -a vendor/NetBSD/bmake/$VERSION"
echo "echo \"When ready do: $GIT push --follow-tags\""
} > $SB/tmp/bmake-post.sh
echo "After you commit, run $SB/tmp/bmake-post.sh"
else
comm -23 $TF.adds $TF.rms > $TF.add
test -s $TF.rm && { echo Removing:; cat $TF.rm; }
test -s $TF.add && { echo Adding:; cat $TF.add; }
$GIT diff
fi
${RM:-rm} -f $TF.*

View File

@ -1,4 +1,4 @@
/* $NetBSD: job.c,v 1.435 2021/06/16 09:47:51 rillig Exp $ */
/* $NetBSD: job.c,v 1.440 2021/11/28 19:51:06 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@ -155,7 +155,7 @@
#include "trace.h"
/* "@(#)job.c 8.2 (Berkeley) 3/19/94" */
MAKE_RCSID("$NetBSD: job.c,v 1.435 2021/06/16 09:47:51 rillig Exp $");
MAKE_RCSID("$NetBSD: job.c,v 1.440 2021/11/28 19:51:06 rillig Exp $");
/*
* A shell defines how the commands are run. All commands for a target are
@ -794,8 +794,8 @@ ShellWriter_WriteFmt(ShellWriter *wr, const char *fmt, const char *arg)
DEBUG1(JOB, fmt, arg);
(void)fprintf(wr->f, fmt, arg);
/* XXX: Is flushing needed in any case, or only if f == stdout? */
(void)fflush(wr->f);
if (wr->f == stdout)
(void)fflush(wr->f);
}
static void
@ -1097,10 +1097,20 @@ DebugFailedJob(const Job *job)
if (!DEBUG(ERROR))
return;
debug_printf("\n*** Failed target: %s\n*** Failed commands:\n",
job->node->name);
for (ln = job->node->commands.first; ln != NULL; ln = ln->next)
debug_printf("\t%s\n", (const char *)ln->datum);
debug_printf("\n");
debug_printf("*** Failed target: %s\n", job->node->name);
debug_printf("*** Failed commands:\n");
for (ln = job->node->commands.first; ln != NULL; ln = ln->next) {
const char *cmd = ln->datum;
debug_printf("\t%s\n", cmd);
if (strchr(cmd, '$') != NULL) {
char *xcmd;
(void)Var_Subst(cmd, job->node, VARE_WANTRES, &xcmd);
debug_printf("\t=> %s\n", xcmd);
free(xcmd);
}
}
}
static void
@ -1192,7 +1202,9 @@ JobFinish (Job *job, WAIT_T status)
JobClosePipes(job);
if (job->cmdFILE != NULL && job->cmdFILE != stdout) {
(void)fclose(job->cmdFILE);
if (fclose(job->cmdFILE) != 0)
Punt("Cannot write shell script for '%s': %s",
job->node->name, strerror(errno));
job->cmdFILE = NULL;
}
done = true;
@ -1384,7 +1396,7 @@ Job_CheckCommands(GNode *gn, void (*abortProc)(const char *, ...))
* this node's parents so they never get examined.
*/
if (gn->flags & FROM_DEPEND) {
if (gn->flags.fromDepend) {
if (!Job_RunTarget(".STALE", gn->fname))
fprintf(stdout,
"%s: %s, %d: ignoring stale %s for %s\n",
@ -1558,7 +1570,9 @@ JobExec(Job *job, char **argv)
watchfd(job);
if (job->cmdFILE != NULL && job->cmdFILE != stdout) {
(void)fclose(job->cmdFILE);
if (fclose(job->cmdFILE) != 0)
Punt("Cannot write shell script for '%s': %s",
job->node->name, strerror(errno));
job->cmdFILE = NULL;
}
@ -2128,7 +2142,7 @@ Job_CatchOutput(void)
JobRestartJobs();
} else if (count == 0)
Punt("unexpected eof on token pipe");
else
else if (errno != EAGAIN)
Punt("token pipe read: %s", strerror(errno));
nready--;
}
@ -2182,8 +2196,11 @@ InitShellNameAndPath(void)
return;
}
#endif
#ifdef DEFSHELL_PATH
shellPath = DEFSHELL_PATH;
#else
shellPath = str_concat3(_PATH_DEFSHELLDIR, "/", shellName);
#endif
}
void

View File

@ -1,4 +1,4 @@
/* $NetBSD: lst.h,v 1.98 2021/04/03 11:08:40 rillig Exp $ */
/* $NetBSD: lst.h,v 1.99 2021/12/05 10:11:31 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@ -142,9 +142,9 @@ ListNode *Lst_FindDatum(List *, const void *);
/* Insert a datum before the given node. */
void Lst_InsertBefore(List *, ListNode *, void *);
/* Place a datum at the front of the list. */
/* Add a datum at the front of the list. */
void Lst_Prepend(List *, void *);
/* Place a datum at the end of the list. */
/* Add a datum at the end of the list. */
void Lst_Append(List *, void *);
/* Remove the node from the list. */
void Lst_Remove(List *, ListNode *);

View File

@ -1,4 +1,4 @@
/* $NetBSD: main.c,v 1.540 2021/06/18 12:54:17 rillig Exp $ */
/* $NetBSD: main.c,v 1.541 2021/08/14 13:32:12 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@ -111,7 +111,7 @@
#include "trace.h"
/* "@(#)main.c 8.3 (Berkeley) 3/19/94" */
MAKE_RCSID("$NetBSD: main.c,v 1.540 2021/06/18 12:54:17 rillig Exp $");
MAKE_RCSID("$NetBSD: main.c,v 1.541 2021/08/14 13:32:12 rillig Exp $");
#if defined(MAKE_NATIVE) && !defined(lint)
__COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993 "
"The Regents of the University of California. "
@ -1127,7 +1127,7 @@ InitObjdir(const char *machine, const char *machine_arch)
static void
UnlimitFiles(void)
{
#if defined(MAKE_NATIVE) || (defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE))
#if defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE)
struct rlimit rl;
if (getrlimit(RLIMIT_NOFILE, &rl) != -1 &&
rl.rlim_cur != rl.rlim_max) {
@ -1685,7 +1685,7 @@ main_CleanUp(void)
static int
main_Exit(bool outOfDate)
{
if (opts.strict && (main_errors > 0 || Parse_GetFatals() > 0))
if (opts.strict && (main_errors > 0 || Parse_NumErrors() > 0))
return 2; /* Not 1 so -q can distinguish error */
return outOfDate ? 1 : 0;
}

View File

@ -59,7 +59,7 @@ do_link() {
${CC} ${LDSTATIC} ${LDFLAGS} -o "$output" "$@" ${LIBS}
}
BASE_OBJECTS="arch.o buf.o compat.o cond.o dir.o enum.o for.o getopt hash.o \
BASE_OBJECTS="arch.o buf.o compat.o cond.o dir.o for.o hash.o \
lst.o make.o make_malloc.o metachar.o parse.o sigcompat.o str.o \
suff.o targ.o trace.o var.o util.o"

View File

@ -1,4 +1,4 @@
.\" $NetBSD: make.1,v 1.296 2021/02/04 21:42:46 rillig Exp $
.\" $NetBSD: make.1,v 1.300 2021/12/12 20:45:48 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 December 22, 2020
.Dd December 12, 2021
.Dt MAKE 1
.Os
.Sh NAME
@ -1174,6 +1174,9 @@ executes.
.It Ev .SHELL
The pathname of the shell used to run target scripts.
It is read-only.
.It Ev .SUFFIXES
The list of known suffixes.
It is read-only.
.It Ev .TARGETS
The list of targets explicitly specified on the command line, if any.
.It Ev VPATH
@ -1244,8 +1247,20 @@ but selects all words which do not match
.Ar pattern .
.It Cm \&:O
Orders every word in variable alphabetically.
.It Cm \&:On
Orders every word in variable numerically.
A number followed by one of
.Ql k ,
.Ql M
or
.Ql G
is multiplied by the appropriate factor (1024 (k), 1048576 (M), or
1073741824 (G)).
Both upper- and lower-case letters are accepted.
.It Cm \&:Or
Orders every word in variable in reverse alphabetical order.
.It Cm \&:Orn
Orders every word in variable in reverse numerical order.
.It Cm \&:Ox
Shuffles the words in variable.
The results will be different each time you are referring to the

View File

@ -1,4 +1,4 @@
/* $NetBSD: make.c,v 1.244 2021/04/04 10:05:08 rillig Exp $ */
/* $NetBSD: make.c,v 1.248 2021/11/28 23:12:51 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@ -104,7 +104,7 @@
#include "job.h"
/* "@(#)make.c 8.1 (Berkeley) 6/6/93" */
MAKE_RCSID("$NetBSD: make.c,v 1.244 2021/04/04 10:05:08 rillig Exp $");
MAKE_RCSID("$NetBSD: make.c,v 1.248 2021/11/28 23:12:51 rillig Exp $");
/* Sequence # to detect recursion. */
static unsigned int checked_seqno = 1;
@ -138,35 +138,83 @@ make_abort(GNode *gn, int lineno)
abort();
}
ENUM_FLAGS_RTTI_31(GNodeType,
OP_DEPENDS, OP_FORCE, OP_DOUBLEDEP,
/* OP_OPMASK is omitted since it combines other flags */
OP_OPTIONAL, OP_USE, OP_EXEC, OP_IGNORE,
OP_PRECIOUS, OP_SILENT, OP_MAKE, OP_JOIN,
OP_MADE, OP_SPECIAL, OP_USEBEFORE, OP_INVISIBLE,
OP_NOTMAIN, OP_PHONY, OP_NOPATH, OP_WAIT,
OP_NOMETA, OP_META, OP_NOMETA_CMP, OP_SUBMAKE,
OP_TRANSFORM, OP_MEMBER, OP_LIB, OP_ARCHV,
OP_HAS_COMMANDS, OP_SAVE_CMDS, OP_DEPS_FOUND, OP_MARK);
static const char *
GNodeType_ToString(GNodeType type, void **freeIt)
{
Buffer buf;
ENUM_FLAGS_RTTI_9(GNodeFlags,
REMAKE, CHILDMADE, FORCE, DONE_WAIT,
DONE_ORDER, FROM_DEPEND, DONE_ALLSRC, CYCLE,
DONECYCLE);
Buf_InitSize(&buf, 32);
#define ADD(flag) Buf_AddFlag(&buf, (type & (flag)) != OP_NONE, #flag)
ADD(OP_DEPENDS);
ADD(OP_FORCE);
ADD(OP_DOUBLEDEP);
ADD(OP_OPTIONAL);
ADD(OP_USE);
ADD(OP_EXEC);
ADD(OP_IGNORE);
ADD(OP_PRECIOUS);
ADD(OP_SILENT);
ADD(OP_MAKE);
ADD(OP_JOIN);
ADD(OP_MADE);
ADD(OP_SPECIAL);
ADD(OP_USEBEFORE);
ADD(OP_INVISIBLE);
ADD(OP_NOTMAIN);
ADD(OP_PHONY);
ADD(OP_NOPATH);
ADD(OP_WAIT);
ADD(OP_NOMETA);
ADD(OP_META);
ADD(OP_NOMETA_CMP);
ADD(OP_SUBMAKE);
ADD(OP_TRANSFORM);
ADD(OP_MEMBER);
ADD(OP_LIB);
ADD(OP_ARCHV);
ADD(OP_HAS_COMMANDS);
ADD(OP_SAVE_CMDS);
ADD(OP_DEPS_FOUND);
ADD(OP_MARK);
#undef ADD
return buf.len == 0 ? "none" : (*freeIt = Buf_DoneData(&buf));
}
static const char *
GNodeFlags_ToString(GNodeFlags flags, void **freeIt)
{
Buffer buf;
Buf_InitSize(&buf, 32);
#define ADD(flag, name) Buf_AddFlag(&buf, flags.flag, name)
ADD(remake, "REMAKE");
ADD(childMade, "CHILDMADE");
ADD(force, "FORCE");
ADD(doneWait, "DONE_WAIT");
ADD(doneOrder, "DONE_ORDER");
ADD(fromDepend, "FROM_DEPEND");
ADD(doneAllsrc, "DONE_ALLSRC");
ADD(cycle, "CYCLE");
ADD(doneCycle, "DONECYCLE");
#undef ADD
return buf.len == 0 ? "none" : (*freeIt = Buf_DoneData(&buf));
}
void
GNode_FprintDetails(FILE *f, const char *prefix, const GNode *gn,
const char *suffix)
{
char type_buf[GNodeType_ToStringSize];
char flags_buf[GNodeFlags_ToStringSize];
void *type_freeIt = NULL;
void *flags_freeIt = NULL;
fprintf(f, "%s%s, type %s, flags %s%s",
prefix,
GNodeMade_Name(gn->made),
GNodeType_ToString(type_buf, gn->type),
GNodeFlags_ToString(flags_buf, gn->flags),
GNodeType_ToString(gn->type, &type_freeIt),
GNodeFlags_ToString(gn->flags, &flags_freeIt),
suffix);
free(type_freeIt);
free(flags_freeIt);
}
bool
@ -286,8 +334,8 @@ GNode_IsOODate(GNode *gn)
*/
DEBUG0(MAKE, ".JOIN node...");
DEBUG1(MAKE, "source %smade...",
gn->flags & CHILDMADE ? "" : "not ");
oodate = (gn->flags & CHILDMADE) != 0;
gn->flags.childMade ? "" : "not ");
oodate = gn->flags.childMade;
} else if (gn->type & (OP_FORCE | OP_EXEC | OP_PHONY)) {
/*
* A node which is the object of the force (!) operator or
@ -315,10 +363,10 @@ GNode_IsOODate(GNode *gn)
* child after it was considered made.
*/
if (DEBUG(MAKE)) {
if (gn->flags & FORCE)
if (gn->flags.force)
debug_printf("non existing child...");
}
oodate = (gn->flags & FORCE) != 0;
oodate = gn->flags.force;
}
#ifdef USE_META
@ -568,7 +616,7 @@ UpdateImplicitParentsVars(GNode *cgn, const char *cname)
for (ln = cgn->implicitParents.first; ln != NULL; ln = ln->next) {
GNode *pgn = ln->datum;
if (pgn->flags & REMAKE) {
if (pgn->flags.remake) {
Var_Set(pgn, IMPSRC, cname);
if (cpref != NULL)
Var_Set(pgn, PREFIX, cpref);
@ -585,7 +633,7 @@ IsWaitingForOrder(GNode *gn)
for (ln = gn->order_pred.first; ln != NULL; ln = ln->next) {
GNode *ogn = ln->datum;
if (GNode_IsDone(ogn) || !(ogn->flags & REMAKE))
if (GNode_IsDone(ogn) || !ogn->flags.remake)
continue;
DEBUG2(MAKE,
@ -684,13 +732,13 @@ Make_Update(GNode *cgn)
debug_printf(", unmade %d ", pgn->unmade - 1);
}
if (!(pgn->flags & REMAKE)) {
if (!pgn->flags.remake) {
/* This parent isn't needed */
DEBUG0(MAKE, "- not needed\n");
continue;
}
if (mtime == 0 && !(cgn->type & OP_WAIT))
pgn->flags |= FORCE;
pgn->flags.force = true;
/*
* If the parent has the .MADE attribute, its timestamp got
@ -707,7 +755,7 @@ Make_Update(GNode *cgn)
if (!(cgn->type & (OP_EXEC | OP_USE | OP_USEBEFORE))) {
if (cgn->made == MADE)
pgn->flags |= CHILDMADE;
pgn->flags.childMade = true;
GNode_UpdateYoungestChild(pgn, cgn);
}
@ -740,7 +788,7 @@ Make_Update(GNode *cgn)
* nodes.
*/
if (pgn->unmade != 0 && !(centurion->type & OP_WAIT)
&& !(centurion->flags & DONE_ORDER)) {
&& !centurion->flags.doneOrder) {
DEBUG0(MAKE, "- unmade children\n");
continue;
}
@ -873,7 +921,7 @@ GNode_SetLocalVars(GNode *gn)
{
GNodeListNode *ln;
if (gn->flags & DONE_ALLSRC)
if (gn->flags.doneAllsrc)
return;
UnmarkChildren(gn);
@ -887,7 +935,7 @@ GNode_SetLocalVars(GNode *gn)
if (gn->type & OP_JOIN)
Var_Set(gn, TARGET, GNode_VarAllsrc(gn));
gn->flags |= DONE_ALLSRC;
gn->flags.doneAllsrc = true;
}
static bool
@ -942,7 +990,7 @@ MakeBuildParent(GNode *pn, GNodeListNode *toBeMadeNext)
if (!MakeBuildChild(pn, toBeMadeNext)) {
/* When this node is built, reschedule its parents. */
pn->flags |= DONE_ORDER;
pn->flags.doneOrder = true;
}
}
@ -1085,7 +1133,7 @@ static void MakePrintStatusList(GNodeList *, int *);
static bool
MakePrintStatus(GNode *gn, int *errors)
{
if (gn->flags & DONECYCLE) {
if (gn->flags.doneCycle) {
/*
* We've completely processed this node before, don't do
* it again.
@ -1094,7 +1142,7 @@ MakePrintStatus(GNode *gn, int *errors)
}
if (gn->unmade == 0) {
gn->flags |= DONECYCLE;
gn->flags.doneCycle = true;
switch (gn->made) {
case UPTODATE:
printf("`%s%s' is up to date.\n", gn->name,
@ -1138,17 +1186,17 @@ MakePrintStatus(GNode *gn, int *errors)
* If printing cycles and came to one that has unmade children,
* print out the cycle by recursing on its children.
*/
if (!(gn->flags & CYCLE)) {
if (!gn->flags.cycle) {
/* First time we've seen this node, check all children */
gn->flags |= CYCLE;
gn->flags.cycle = true;
MakePrintStatusList(&gn->children, errors);
/* Mark that this node needn't be processed again */
gn->flags |= DONECYCLE;
gn->flags.doneCycle = true;
return false;
}
/* Only output the error once per node */
gn->flags |= DONECYCLE;
gn->flags.doneCycle = true;
Error("Graph cycles through `%s%s'", gn->name, gn->cohort_num);
if ((*errors)++ > 100)
/* Abandon the whole error report */
@ -1177,7 +1225,7 @@ ExamineLater(GNodeList *examine, GNodeList *toBeExamined)
for (ln = toBeExamined->first; ln != NULL; ln = ln->next) {
GNode *gn = ln->datum;
if (gn->flags & REMAKE)
if (gn->flags.remake)
continue;
if (gn->type & (OP_USE | OP_USEBEFORE))
continue;
@ -1213,10 +1261,10 @@ Make_ExpandUse(GNodeList *targs)
while (!Lst_IsEmpty(&examine)) {
GNode *gn = Lst_Dequeue(&examine);
if (gn->flags & REMAKE)
if (gn->flags.remake)
/* We've looked at this one already */
continue;
gn->flags |= REMAKE;
gn->flags.remake = true;
DEBUG2(MAKE, "Make_ExpandUse: examine %s%s\n",
gn->name, gn->cohort_num);
@ -1301,7 +1349,7 @@ Make_ProcessWait(GNodeList *targs)
*/
pgn = GNode_New(".MAIN");
pgn->flags = REMAKE;
pgn->flags.remake = true;
pgn->type = OP_PHONY | OP_DEPENDS;
/* Get it displayed in the diag dumps */
Lst_Prepend(Targ_List(), pgn);
@ -1329,9 +1377,9 @@ Make_ProcessWait(GNodeList *targs)
pgn = Lst_Dequeue(&examine);
/* We only want to process each child-list once */
if (pgn->flags & DONE_WAIT)
if (pgn->flags.doneWait)
continue;
pgn->flags |= DONE_WAIT;
pgn->flags.doneWait = true;
DEBUG1(MAKE, "Make_ProcessWait: examine %s\n", pgn->name);
if (pgn->type & OP_DOUBLEDEP)

View File

@ -1,4 +1,4 @@
/* $NetBSD: make.h,v 1.263 2021/06/21 10:33:11 rillig Exp $ */
/* $NetBSD: make.h,v 1.270 2021/11/28 23:12:51 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@ -136,25 +136,38 @@
#endif
#define MAKE_INLINE static inline MAKE_ATTR_UNUSED
/* MAKE_STATIC marks a function that may or may not be inlined. */
#if defined(lint)
/* As of 2021-07-31, NetBSD lint ignores __attribute__((unused)). */
#define MAKE_STATIC MAKE_INLINE
#else
#define MAKE_STATIC static MAKE_ATTR_UNUSED
#endif
#if __STDC_VERSION__ >= 199901L || defined(lint) || defined(USE_C99_BOOLEAN)
#include <stdbool.h>
#elif defined(__bool_true_false_are_defined)
/*
* All files of make must be compiled with the same definition of bool.
* Since one of the files includes <stdbool.h>, that means the header is
* available on this platform. Recompile everything with -DUSE_C99_BOOLEAN.
*/
#error "<stdbool.h> is included in pre-C99 mode"
#elif defined(bool) || defined(true) || defined(false)
/*
* In pre-C99 mode, make does not expect that bool is already defined.
* You need to ensure that all translation units use the same definition for
* bool.
*/
#error "bool/true/false is defined in pre-C99 mode"
#else
#ifndef bool
typedef unsigned int Boolean;
#define bool Boolean
#endif
#ifndef true
typedef unsigned char bool;
#define true 1
#endif
#ifndef false
#define false 0
#endif
#endif
#include "lst.h"
#include "enum.h"
#include "make_malloc.h"
#include "str.h"
#include "hash.h"
@ -324,26 +337,25 @@ typedef enum GNodeType {
OP_NOTARGET = OP_NOTMAIN | OP_USE | OP_EXEC | OP_TRANSFORM
} GNodeType;
typedef enum GNodeFlags {
GNF_NONE = 0,
typedef struct GNodeFlags {
/* this target needs to be (re)made */
REMAKE = 1 << 0,
bool remake:1;
/* children of this target were made */
CHILDMADE = 1 << 1,
bool childMade:1;
/* children don't exist, and we pretend made */
FORCE = 1 << 2,
bool force:1;
/* Set by Make_ProcessWait() */
DONE_WAIT = 1 << 3,
bool doneWait:1;
/* Build requested by .ORDER processing */
DONE_ORDER = 1 << 4,
bool doneOrder:1;
/* Node created from .depend */
FROM_DEPEND = 1 << 5,
bool fromDepend:1;
/* We do it once only */
DONE_ALLSRC = 1 << 6,
bool doneAllsrc:1;
/* Used by MakePrintStatus */
CYCLE = 1 << 12,
bool cycle:1;
/* Used by MakePrintStatus */
DONECYCLE = 1 << 13
bool doneCycle:1;
} GNodeFlags;
typedef struct List StringList;
@ -583,7 +595,7 @@ void debug_printf(const char *, ...) MAKE_ATTR_PRINTFLIKE(1, 2);
do { \
if (DEBUG(module)) \
debug_printf args; \
} while (/*CONSTCOND*/false)
} while (false)
#define DEBUG0(module, text) \
DEBUG_IMPL(module, ("%s", text))
@ -710,7 +722,7 @@ bool GNode_ShouldExecute(GNode *gn);
MAKE_INLINE bool
GNode_IsTarget(const GNode *gn)
{
return (gn->type & OP_OPMASK) != 0;
return (gn->type & OP_OPMASK) != OP_NONE;
}
MAKE_INLINE const char *
@ -722,7 +734,7 @@ GNode_Path(const GNode *gn)
MAKE_INLINE bool
GNode_IsWaitingFor(const GNode *gn)
{
return (gn->flags & REMAKE) && gn->made <= REQUESTED;
return gn->flags.remake && gn->made <= REQUESTED;
}
MAKE_INLINE bool
@ -758,16 +770,13 @@ GNode_VarArchive(GNode *gn) { return GNode_ValueDirect(gn, ARCHIVE); }
MAKE_INLINE const char *
GNode_VarMember(GNode *gn) { return GNode_ValueDirect(gn, MEMBER); }
#if defined(__GNUC__) && __STDC_VERSION__ >= 199901L
#define UNCONST(ptr) ({ \
union __unconst { \
const void *__cp; \
void *__p; \
} __d; \
__d.__cp = ptr, __d.__p; })
#else
#define UNCONST(ptr) (void *)(ptr)
#endif
MAKE_INLINE void *
UNCONST(const void *ptr)
{
void *ret;
memcpy(&ret, &ptr, sizeof(ret));
return ret;
}
/* At least GNU/Hurd systems lack hardcoded MAXPATHLEN/PATH_MAX */
#ifdef HAVE_LIMITS_H
@ -833,6 +842,16 @@ pp_skip_hspace(char **pp)
# define MAKE_RCSID(id) extern void do_not_define_rcsid(void)
#elif defined(MAKE_NATIVE)
# include <sys/cdefs.h>
# ifndef __IDSTRING
# define __IDSTRING(name,string) \
static const char name[] MAKE_ATTR_UNUSED = string
# endif
# ifndef __RCSID
# define __RCSID(s) __IDSTRING(rcsid,s)
# endif
# ifndef __COPYRIGHT
# define __COPYRIGHT(s) __IDSTRING(copyright,s)
# endif
# define MAKE_RCSID(id) __RCSID(id)
#elif defined(MAKE_ALL_IN_ONE) && defined(__COUNTER__)
# define MAKE_RCSID_CONCAT(x, y) CONCAT(x, y)

View File

@ -1,4 +1,4 @@
/* $NetBSD: meta.c,v 1.181 2021/04/04 10:05:08 rillig Exp $ */
/* $NetBSD: meta.c,v 1.185 2021/11/27 22:04:02 rillig Exp $ */
/*
* Implement 'meta' mode.
@ -98,6 +98,9 @@ extern char **environ;
#if !defined(HAVE_STRSEP)
# define strsep(s, d) stresep((s), (d), '\0')
#endif
#if !defined(HAVE_STRESEP)
char * stresep(char **, const char *, int);
#endif
/*
* Filemon is a kernel module which snoops certain syscalls.
@ -149,11 +152,11 @@ meta_open_filemon(BuildMon *pbm)
else
pbm->mon_fd = mkTempFile("filemon.XXXXXX", NULL, 0);
if ((dupfd = dup(pbm->mon_fd)) == -1) {
err(1, "Could not dup filemon output!");
Punt("Could not dup filemon output: %s", strerror(errno));
}
(void)fcntl(dupfd, F_SETFD, FD_CLOEXEC);
if (filemon_setfd(pbm->filemon, dupfd) == -1) {
err(1, "Could not set filemon file descriptor!");
Punt("Could not set filemon file descriptor: %s", strerror(errno));
}
/* we don't need these once we exec */
(void)fcntl(pbm->mon_fd, F_SETFD, FD_CLOEXEC);
@ -191,7 +194,9 @@ filemon_read(FILE *mfp, int fd)
error = EIO;
}
}
fflush(mfp);
if (fflush(mfp) != 0)
Punt("Cannot write filemon data to meta file: %s",
strerror(errno));
if (close(fd) < 0)
error = errno;
return error;
@ -248,8 +253,8 @@ meta_name(char *mname, size_t mnamelen,
const char *cwd)
{
char buf[MAXPATHLEN];
char *rp;
char *cp;
char *rp, *cp;
const char *tname_base;
char *tp;
char *dtp;
size_t ldname;
@ -261,13 +266,13 @@ meta_name(char *mname, size_t mnamelen,
* So we use realpath() just to get the dirname, and leave the
* basename as given to us.
*/
if ((cp = strrchr(tname, '/')) != NULL) {
if ((tname_base = strrchr(tname, '/')) != NULL) {
if (cached_realpath(tname, buf) != NULL) {
if ((rp = strrchr(buf, '/')) != NULL) {
rp++;
cp++;
if (strcmp(cp, rp) != 0)
strlcpy(rp, cp, sizeof buf - (size_t)(rp - buf));
tname_base++;
if (strcmp(tname_base, rp) != 0)
strlcpy(rp, tname_base, sizeof buf - (size_t)(rp - buf));
}
tname = buf;
} else {
@ -325,8 +330,7 @@ is_submake(const char *cmd, GNode *gn)
static const char *p_make = NULL;
static size_t p_len;
char *mp = NULL;
char *cp;
char *cp2;
const char *cp, *cp2;
bool rc = false;
if (p_make == NULL) {
@ -412,7 +416,7 @@ printCMDs(GNode *gn, FILE *fp)
} \
return false; \
} \
} while (/*CONSTCOND*/false)
} while (false)
/*
@ -523,7 +527,7 @@ meta_create(BuildMon *pbm, GNode *gn)
#endif
if ((fp = fopen(fname, "w")) == NULL)
err(1, "Could not open meta file '%s'", fname);
Punt("Could not open meta file '%s': %s", fname, strerror(errno));
fprintf(fp, "# Meta data file %s\n", fname);
@ -541,7 +545,9 @@ meta_create(BuildMon *pbm, GNode *gn)
}
fprintf(fp, "-- command output --\n");
fflush(fp);
if (fflush(fp) != 0)
Punt("Cannot write expanded command to meta file: %s",
strerror(errno));
Global_Append(".MAKE.META.FILES", fname);
Global_Append(".MAKE.META.CREATED", fname);
@ -557,9 +563,9 @@ meta_create(BuildMon *pbm, GNode *gn)
}
static bool
boolValue(char *s)
boolValue(const char *s)
{
switch(*s) {
switch (*s) {
case '0':
case 'N':
case 'n':
@ -594,7 +600,7 @@ void
meta_mode_init(const char *make_mode)
{
static bool once = false;
char *cp;
const char *cp;
FStr value;
useMeta = true;
@ -715,7 +721,7 @@ meta_job_child(Job *job)
pid = getpid();
if (filemon_setpid_child(pbm->filemon, pid) == -1) {
err(1, "Could not set filemon pid!");
Punt("Could not set filemon pid: %s", strerror(errno));
}
}
}
@ -855,8 +861,10 @@ meta_cmd_finish(void *pbmp)
if (pbm->filemon != NULL) {
while (filemon_process(pbm->filemon) > 0)
continue;
if (filemon_close(pbm->filemon) == -1)
if (filemon_close(pbm->filemon) == -1) {
error = errno;
Punt("filemon failed: %s", strerror(errno));
}
x = filemon_read(pbm->mfp, pbm->mon_fd);
if (error == 0 && x != 0)
error = x;
@ -1710,7 +1718,7 @@ meta_compat_parent(pid_t child)
fflush(stdout);
buf[nread] = '\0';
meta_job_output(NULL, buf, "");
} while (/*CONSTCOND*/false);
} while (false);
if (metafd != -1 && FD_ISSET(metafd, &readfds) != 0) {
if (meta_job_event(NULL) <= 0)
metafd = -1;

View File

@ -1,4 +1,4 @@
/* $NetBSD: metachar.c,v 1.9 2021/01/19 20:51:46 rillig Exp $ */
/* $NetBSD: metachar.c,v 1.10 2021/06/21 18:54:41 rillig Exp $ */
/*
* Copyright (c) 2015 The NetBSD Foundation, Inc.
@ -39,7 +39,7 @@
#include "metachar.h"
MAKE_RCSID("$NetBSD: metachar.c,v 1.9 2021/01/19 20:51:46 rillig Exp $");
MAKE_RCSID("$NetBSD: metachar.c,v 1.10 2021/06/21 18:54:41 rillig Exp $");
/*
* The following array is used to make a fast determination of which
@ -48,7 +48,7 @@ MAKE_RCSID("$NetBSD: metachar.c,v 1.9 2021/01/19 20:51:46 rillig Exp $");
* directly by us.
*/
unsigned char _metachar[128] = {
const 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 */

View File

@ -1,4 +1,4 @@
/* $NetBSD: metachar.h,v 1.16 2021/04/03 11:08:40 rillig Exp $ */
/* $NetBSD: metachar.h,v 1.17 2021/06/21 18:54:41 rillig Exp $ */
/*
* Copyright (c) 2015 The NetBSD Foundation, Inc.
@ -33,9 +33,13 @@
#include "make.h"
extern unsigned char _metachar[];
extern const unsigned char _metachar[];
#define is_shell_metachar(c) (_metachar[(c) & 0x7f] != 0)
MAKE_INLINE bool
is_shell_metachar(char c)
{
return _metachar[c & 0x7f] != 0;
}
MAKE_INLINE bool
needshell(const char *cmd)

View File

@ -1,3 +1,107 @@
2021-12-12 Simon J Gerraty <sjg@beast.crufty.net>
* sys.mk: simplify; include meta.sys.mk if MK_META_MODE is yes.
* meta.sys.mk: do not check for /dev/filemon if .MAKE.PATH_FILEMON
is something else.
* meta.autodep.mk: we can now reference ${.SUFFIXES}
* meta2deps.py: derive a list of dirdep extensions from
TARGET_SPEC to trim from dirdeps.
* dirdeps.mk: flip the computation of qualified vs unqualified
dirdeps - it is much simpler to check for unqualified first.
2021-12-11 Simon J Gerraty <sjg@beast.crufty.net>
* install-mk (MK_VERSION): 20211212
* auto.dep.mk: rearrange so that the trivial implementation
for recent bmake is more obvious.
2021-12-07 Simon J Gerraty <sjg@beast.crufty.net>
* install-mk (MK_VERSION): 20211207
* Ensure guard targets are .NOTMAIN
* meta.sys.mk: check for nofilemon support when we skip level 0
* auto.dep.mk: make this usable in meta mode
for platforms that cannot use meta.autodep.mk
* meta2deps.py: avoid confusion if MACHINE and another
TARGET_SPEC_VAR have same value.
2021-11-27 Simon J Gerraty <sjg@beast.crufty.net>
* dirdeps.mk: when building dirdeps.cache, minimize the amount of
data put into env, by stripping ${SRCTOP}/ from each entry.
A long sandbox name can double the amount of memory consumed and
in extreme cases cause failure.
While we are at it, strip ${SRCTOP}/ from a lot of the debug output.
2021-11-11 Simon J Gerraty <sjg@beast.crufty.net>
* install-mk (MK_VERSION): 20211111
* meta.stage.mk (LN_CP_SCRIPT): if staging to NFS cp -p can fail
so fallback to cp if necessary.
2021-10-30 Simon J Gerraty <sjg@beast.crufty.net>
* man.mk (CMT2DOC): use cmt2doc.py rather than the 30 year
old cmt2doc.pl
2021-10-24 Simon J Gerraty <sjg@beast.crufty.net>
* meta.stage.mk: stage_as_and_symlink use ${STAGE_LINK_AS_$f:U$f}
as the symlink (rare)
2021-10-16 Simon J Gerraty <sjg@beast.crufty.net>
* autoconf.mk: if AUTOCONF_GENERATED_MAKEFILE is set and has not
been read, throw an error after running configure telling user to
restart.
2021-10-13 Simon J Gerraty <sjg@beast.crufty.net>
* install-mk (MK_VERSION): 20211011
* Add support for SCO_SV
2021-10-01 Simon J Gerraty <sjg@beast.crufty.net>
* install-mk (MK_VERSION): 20211001
* man.mk: use MAN_SUFFIXES and CMT2DOC_SUFFIXES for more
flexibility
2021-09-13 Simon J Gerraty <sjg@beast.crufty.net>
* options.mk (describe-options): print options and their values
and optional description
2021-09-11 Simon J Gerraty <sjg@beast.crufty.net>
* install-mk (MK_VERSION): 20210911
* options.mk (show-options): print options and their values
2021-09-08 Simon J Gerraty <sjg@beast.crufty.net>
* install-mk (MK_VERSION): 20210909
* lib.mk: apply patch from <daniel@octaforge.org>
to fix shared libs on Linux
2021-08-08 Simon J Gerraty <sjg@beast.crufty.net>
* install-mk (MK_VERSION): 20210808
* options.mk: issue warning for WITH_*=no
2021-06-16 Simon J Gerraty <sjg@beast.crufty.net>
* install-mk (MK_VERSION): 20210616

View File

@ -54,6 +54,7 @@ sys/Linux.mk
sys/NetBSD.mk
sys/OSF1.mk
sys/OpenBSD.mk
sys/SCO_SV.mk
sys/SunOS.mk
sys/UnixWare.mk
target-flags.mk

View File

@ -1,8 +1,8 @@
#
# RCSid:
# $Id: auto.dep.mk,v 1.6 2020/08/19 17:51:53 sjg Exp $
# $Id: auto.dep.mk,v 1.10 2021/12/11 18:57:41 sjg Exp $
#
# @(#) Copyright (c) 2010, Simon J. Gerraty
# @(#) Copyright (c) 2010-2021, Simon J. Gerraty
#
# This file is provided in the hope that it will
# be of use. There is absolutely NO WARRANTY.
@ -30,39 +30,24 @@
# dep.mk will handle that itself.
#
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
# this what bmake > 20100401 will look for
.MAKE.DEPENDFILE ?= .depend
__${.PARSEFILE}__: .NOTMAIN
# set this to -MMD to ignore /usr/include
# actually it ignores <> so may not be a great idea
CFLAGS_MD ?= -MD
# -MF etc not available on all gcc versions.
.if ${COMPILER_TYPE:Ugcc} == "gcc" && ${COMPILER_VERSION:U0} < 30000
CFLAGS_MF=
.endif
CFLAGS_MF ?= -MF ${.TARGET:T}.d -MT ${.TARGET:T}
CFLAGS += ${CFLAGS_MD} ${CFLAGS_MF}
CXXFLAGS += ${CFLAGS_MD} ${CFLAGS_MF}
CLEANFILES += .depend ${.MAKE.DEPENDFILE} *.d
CLEANFILES += .depend *.d
.if ${MAKE_VERSION} < 20160218
# skip generating dependfile for misc targets
.if ${.TARGETS:Uall:M*all} != ""
.END: ${.MAKE.DEPENDFILE}
.endif
.if ${MAKE_VERSION} >= 20160218
# doing 'make depend' isn't a big win with this model
.if !target(depend)
depend: ${.MAKE.DEPENDFILE}
.endif
# this is trivial
${.MAKE.DEPENDFILE}: ${OBJS} ${POBJS} ${SOBJS}
-@for f in ${.ALLSRC:M*o:T:O:u:%=%.d}; do \
echo ".-include \"$$f\""; \
done > $@
.else
# we have .dinclude
# we have .dinclude and this is all that is required
.if empty(_SKIP_BUILD)
_all_objs = ${OBJS} ${POBJS} ${SOBJS}
.for d in ${_all_objs:M*o:T:O:u:%=%.d}
@ -70,5 +55,34 @@ _all_objs = ${OBJS} ${POBJS} ${SOBJS}
.endfor
.endif
.else # we lack .dinclude
.if ${.MAKE.MODE:Unormal:Mmeta} != ""
# ignore .MAKE.DEPENDFILE
DEPENDFILE = .depend
.else
# this what bmake > 20100401 will look for
.MAKE.DEPENDFILE ?= .depend
DEPENDFILE ?= ${.MAKE.DEPENDFILE}
.endif
CLEANFILES += ${DEPENDFILE}
# skip generating dependfile for misc targets
.if ${.TARGETS:Uall:M*all} != ""
.END: ${DEPENDFILE}
.endif
# doing 'make depend' isn't a big win with this model
.if !target(depend)
depend: ${DEPENDFILE}
.endif
# this is trivial
${DEPENDFILE}: ${OBJS} ${POBJS} ${SOBJS}
-@for f in ${.ALLSRC:M*o:T:O:u:%=%.d}; do \
echo ".-include \"$$f\""; \
done > $@
.endif
.endif

View File

@ -1,4 +1,4 @@
# $Id: autoconf.mk,v 1.10 2020/08/19 17:51:53 sjg Exp $
# $Id: autoconf.mk,v 1.16 2021/10/19 17:36:06 sjg Exp $
#
# @(#) Copyright (c) 1996-2009, Simon J. Gerraty
#
@ -13,32 +13,37 @@
# sjg@crufty.net
#
.NOPATH: config.h config.status
.NOPATH: config.h config.gen config.recheck config.status
CONFIGURE_DEPS += ${.CURDIR}/config.h.in ${.CURDIR}/configure
.if !target(config.h)
config.h: ${CONFIGURE_DEPS} config.status
config.h: .NOTMAIN ${CONFIGURE_DEPS} config.status
./config.status
.if !empty(AUTOCONF_GENERATED_MAKEFILE) && ${AUTOCONF_GENERATED_MAKEFILE:T:@m@${"${.MAKE.MAKEFILES:T:M$m}":?yes:no}@:Mno} != ""
@echo Generated ${AUTOCONF_GENERATED_MAKEFILE}, you need to restart; exit 1
.endif
.endif
.if !target(config.status)
# avoid the targets behaving differently
config.status: .NOTMAIN
.if exists(${.OBJDIR}/config.status)
config.status: config.recheck
.else
config.status: config.gen
.endif
config.recheck: ${CONFIGURE_DEPS}
config.recheck: .NOTMAIN ${CONFIGURE_DEPS} config.gen
./config.status --recheck
@touch $@
config.gen: ${CONFIGURE_DEPS}
config.gen: .NOTMAIN ${CONFIGURE_DEPS}
CC="${CC} ${CCMODE}" ${.CURDIR}/configure --no-create ${CONFIGURE_ARGS}
@touch $@ config.recheck
CLEANFILES+= config.recheck config.gen config.status *.meta
CLEANFILES+= config.recheck config.gen config.status *.meta \
${AUTOCONF_GENERATED_MAKEFILE:U}
.endif
# avoid things blowing up if these are not here...
@ -67,14 +72,14 @@ ACLOCAL += aclocal.m4
ACCONFIG += acconfig.h
.endif
config.h.in: ${.CURDIR}/configure.in ${ACCONFIG}
config.h.in: .NOTMAIN ${.CURDIR}/configure.in ${ACCONFIG}
(cd ${.CURDIR} && ${AUTOHEADER})
configure: ${.CURDIR}/configure.in ${ACLOCAL}
configure: .NOTMAIN ${.CURDIR}/configure.in ${ACLOCAL}
(cd ${.CURDIR} && ${AUTOCONF})
AUTOCONF_INPUTS += configure
autoconf-input: ${AUTOCONF_INPUTS}
autoconf-input: .NOTMAIN ${AUTOCONF_INPUTS}
.endif
.endif

View File

@ -1,6 +1,6 @@
#
# RCSid:
# $Id: autodep.mk,v 1.38 2020/08/19 17:51:53 sjg Exp $
# $Id: autodep.mk,v 1.40 2021/12/08 05:56:50 sjg Exp $
#
# @(#) Copyright (c) 1999-2010, Simon J. Gerraty
#
@ -20,7 +20,7 @@
# dependencies are normally updated as part of compilation.
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
__${.PARSEFILE}__: .NOTMAIN
DEPENDFILE?= .depend
.for d in ${DEPENDFILE:N.depend}
@ -67,6 +67,9 @@ __dependsrcs= ${__dependsrcsx:O:u}
CFLAGS_MD?=-MD
# -MF etc not available on all gcc versions.
# we "fix" the .o later
.if ${COMPILER_TYPE:Ugcc} == "gcc" && ${COMPILER_VERSION:U0} < 30000
CFLAGS_MF=
.endif
CFLAGS_MF?=-MF ${.TARGET:T:R}.d -MT ${.TARGET:T:R}.o
CFLAGS+= ${CFLAGS_MD} ${CFLAGS_MF}
RM?= rm

View File

@ -1,4 +1,4 @@
# $Id: compiler.mk,v 1.7 2020/08/19 17:51:53 sjg Exp $
# $Id: compiler.mk,v 1.10 2021/12/08 05:56:50 sjg Exp $
#
# @(#) Copyright (c) 2019, Simon J. Gerraty
#
@ -14,7 +14,7 @@
#
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
__${.PARSEFILE}__: .NOTMAIN
.if ${MACHINE} == "common"
COMPILER_TYPE = none
@ -22,12 +22,12 @@ COMPILER_VERSION = 0
.endif
.if empty(COMPILER_TYPE) || empty(COMPILER_VERSION)
# gcc does not always say gcc
_v != ${CC} --version 2> /dev/null | \
egrep -i 'clang|cc|[1-9]\.[0-9]|Free Software Foundation'
_v != (${CC} --version) 2> /dev/null | \
egrep -i 'clang|cc|[1-9]\.[0-9]|Free Software Foundation'; echo
.if empty(COMPILER_TYPE)
.if ${_v:Mclang} != ""
COMPILER_TYPE = clang
.elif ${_v:M[Gg][Cc][Cc]} != "" || ${_v:MFoundation*} != ""
.elif ${_v:M[Gg][Cc][Cc]} != "" || ${_v:MFoundation*} != "" || ${CC:T:M*gcc*} != ""
COMPILER_TYPE = gcc
.endif
.endif

View File

@ -1,7 +1,7 @@
# $Id: dep.mk,v 1.17 2014/08/04 05:12:27 sjg Exp $
# $Id: dep.mk,v 1.18 2021/12/08 05:56:50 sjg Exp $
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
__${.PARSEFILE}__: .NOTMAIN
# handle Proc*C as well...
.if defined(SRCS)

View File

@ -1,4 +1,4 @@
# $Id: dirdeps.mk,v 1.140 2021/06/20 23:42:38 sjg Exp $
# $Id: dirdeps.mk,v 1.147 2021/12/14 02:09:53 sjg Exp $
# Copyright (c) 2010-2021, Simon J. Gerraty
# Copyright (c) 2010-2018, Juniper Networks, Inc.
@ -66,6 +66,10 @@
# processing is recursive and results in .MAKE.LEVEL 0 learning the
# dependencies of the tree wrt the initial directory (_DEP_RELDIR).
#
# NOTE: given the extent of processing that DIRDEPS undergoes it
# is important that any variables in entries use :U to guard
# against surprises when undefined.
#
# TARGET_SPEC_VARS
# The default value is just MACHINE, and for most environments
# this is sufficient. The _DIRDEP_USE target actually sets
@ -399,7 +403,7 @@ DIRDEP_LOADAVG_REPORT = \
_DIRDEP_USE: .USE .MAKE
@for m in ${.MAKE.MAKEFILE_PREFERENCE}; do \
test -s ${.TARGET:R}/$$m || continue; \
echo "${TRACER}Checking ${.TARGET:S,${SRCTOP}/,,} for ${.TARGET:E} ..."; \
echo "${TRACER}Checking ${.TARGET:S,^${SRCTOP}/,,} for ${.TARGET:E} ..."; \
${DIRDEP_USE_PRELUDE} \
MACHINE_ARCH= NO_SUBDIR=1 ${DIRDEP_USE_ENV} \
TARGET_SPEC=${.TARGET:E} \
@ -562,7 +566,7 @@ ${DIRDEPS_CACHE}: .META .NOMETA_CMP
${"${DEBUG_DIRDEPS:Nno}":?DEBUG_DIRDEPS='${DEBUG_DIRDEPS}':} \
${.MAKEFLAGS:tW:S,-D ,-D,g:tw:M*WITH*} \
${.MAKEFLAGS:tW:S,-d ,-d,g:tw:M-d*} \
3>&1 1>&2 | sed 's,${SRCTOP},$${SRCTOP},g;s,_{,$${,g' >> ${.TARGET}.new && \
3>&1 1>&2 | sed 's,${SRCTOP},_{SRCTOP},g;s,_{,$${,g' >> ${.TARGET}.new && \
mv ${.TARGET}.new ${.TARGET}
.endif
@ -638,6 +642,7 @@ _build_dirs += ${_machines:@m@${_CURDIR}.$m@}
.endif
.if ${_debug_reldir}
.info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: nDIRDEPS=${DIRDEPS:[#]}
.info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: DIRDEPS='${DIRDEPS}'
.info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: _machines='${_machines}'
.endif
@ -656,11 +661,10 @@ DEP_DIRDEPS_FILTER = U
# this is what we start with
__depdirs := ${DIRDEPS:${NSkipDir}:${DEP_DIRDEPS_FILTER:ts:}:C,//+,/,g:O:u:@d@${SRCTOP}/$d@}
# some entries may be qualified with .<machine>
# the :M*/*/*.* just tries to limit the dirs we check to likely ones.
# the ${d:E:M*/*} ensures we don't consider junos/usr.sbin/mgd
__qual_depdirs := ${__depdirs:M*/*/*.*:@d@${exists($d):?:${"${d:E:M*/*}":?:${exists(${d:R}):?$d:}}}@}
__unqual_depdirs := ${__depdirs:${__qual_depdirs:Uno:${M_ListToSkip}}}
# some entries may be qualified with .<machine> or .<target_spec>
# we can tell the unqualified ones easily - because they exist
__unqual_depdirs := ${__depdirs:@d@${exists($d):?$d:}@}
__qual_depdirs := ${__depdirs:${__unqual_depdirs:Uno:${M_ListToSkip}}}
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# if it was called out - we likely need it.
@ -671,9 +675,9 @@ __qual_depdirs += ${__hostdpadd}
.if ${_debug_reldir}
.info DEP_DIRDEPS_FILTER=${DEP_DIRDEPS_FILTER:ts:}
.info depdirs=${__depdirs}
.info qualified=${__qual_depdirs}
.info unqualified=${__unqual_depdirs}
.info depdirs=${__depdirs:S,^${SRCTOP}/,,}
.info qualified=${__qual_depdirs:S,^${SRCTOP}/,,}
.info unqualified=${__unqual_depdirs:S,^${SRCTOP}/,,}
.endif
# _build_dirs is what we will feed to _DIRDEP_USE
@ -694,13 +698,14 @@ _build_all_dirs := ${_build_all_dirs:O:u}
# 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 ${.MAKEFLAGS:M-V${_V_READ_DIRDEPS:U}} == ""
.if !empty(_build_all_dirs)
.if ${BUILD_DIRDEPS_CACHE} == "yes"
x!= echo; { echo; echo '\# ${DEP_RELDIR}.${DEP_TARGET_SPEC}'; } >&3
# guard against _new_dirdeps being too big for a single command line
_new_dirdeps := ${_build_all_dirs:@x@${target($x):?:$x}@}
.export _build_xtra_dirs _new_dirdeps
_new_dirdeps := ${_build_all_dirs:@x@${target($x):?:$x}@:S,^${SRCTOP}/,,}
_cache_xtra_deps := ${_build_xtra_dirs:S,^${SRCTOP}/,,}
.export _cache_xtra_deps _new_dirdeps
.if !empty(DEP_EXPORT_VARS)
# Discouraged, but there are always exceptions.
# Handle it here rather than explain how.
@ -713,7 +718,7 @@ dirdeps: ${_build_all_dirs}
${_build_all_dirs}: _DIRDEP_USE
.if ${_debug_reldir}
.info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: needs: ${_build_dirs}
.info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: needs: ${_build_dirs:S,^${SRCTOP}/,,}
.endif
.if !empty(DEP_EXPORT_VARS)
@ -724,37 +729,37 @@ DEP_EXPORT_VARS=
# this builds the dependency graph
.for m in ${_machines}
.if ${BUILD_DIRDEPS_CACHE} == "yes" && !empty(_build_dirs)
x!= echo; { echo; echo 'DIRDEPS.${_this_dir}.$m = \'; } >&3
_cache_deps =
x!= echo; { echo; echo 'DIRDEPS.${_this_dir}.$m = \'; } >&3
.endif
# 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 ${_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}
.info ${DEP_RELDIR}.$m: graph: ${_build_dirs:M*.$q:S,^${SRCTOP}/,,}
.endif
.if ${BUILD_DIRDEPS_CACHE} == "yes"
_cache_deps += ${_build_dirs:M*.$q}
_cache_deps += ${_build_dirs:M*.$q:S,^${SRCTOP}/,,}
.else
${_this_dir}.$m: ${_build_dirs:M*.$q}
.endif
.endfor
.endif
.if ${_debug_reldir}
.info ${DEP_RELDIR}.$m: graph: ${_build_dirs:M*.$m:N${_this_dir}.$m}
.info ${DEP_RELDIR}.$m: graph: ${_build_dirs:M*.$m:N${_this_dir}.$m:S,^${SRCTOP}/,,}
.endif
.if ${BUILD_DIRDEPS_CACHE} == "yes"
.if !empty(_build_dirs)
_cache_deps += ${_build_dirs:M*.$m:N${_this_dir}.$m}
_cache_deps += ${_build_dirs:M*.$m:N${_this_dir}.$m:S,^${SRCTOP}/,,}
.if !empty(_cache_deps)
.export _cache_deps
x!= echo; for x in $$_cache_deps; do echo " $$x \\"; done >&3
x!= echo; for x in $$_cache_deps; do echo " _{SRCTOP}/$$x \\"; done >&3
.endif
# anything in _build_xtra_dirs is hooked to dirdeps: only
# anything in _{build,env}_xtra_dirs is hooked to dirdeps: only
x!= echo; { echo; echo '${_this_dir}.$m: $${DIRDEPS.${_this_dir}.$m}'; \
echo; echo 'dirdeps: ${_this_dir}.$m \'; \
for x in $$_build_xtra_dirs; do echo " $$x \\"; done; \
echo; for x in $$_new_dirdeps; do echo "$$x: _DIRDEP_USE"; done; } >&3
for x in $$_cache_xtra_deps; do echo " _{SRCTOP}/$$x \\"; done; \
echo; for x in $$_new_dirdeps; do echo "_{SRCTOP}/$$x: _DIRDEP_USE"; done; } >&3
.endif
.else
${_this_dir}.$m: ${_build_dirs:M*.$m:N${_this_dir}.$m}
@ -769,7 +774,7 @@ ${_this_dir}.$m: ${_build_dirs:M*.$m:N${_this_dir}.$m}
# once only
_dirdeps_checked.$d:
.if ${_debug_search}
.info checking $d
.info checking ${d:S,^${SRCTOP}/,,}
.endif
# Note: _build_all_dirs is fully qualifed so d:R is always the directory
.if exists(${d:R})
@ -798,7 +803,7 @@ _qm := ${_m:C;(\.depend)$;\1.${d:E};:${M_dep_qual_fixes:ts:}}
.endif
# set this "just in case"
# we can skip :tA since we computed the path above
DEP_RELDIR := ${_m:H:S,${SRCTOP}/,,}
DEP_RELDIR := ${_m:H:S,^${SRCTOP}/,,}
# and reset this
DIRDEPS =
.if ${_debug_reldir} && ${_qm} != ${_m}

View File

@ -1,7 +1,7 @@
# $Id: doc.mk,v 1.7 2019/06/09 16:22:08 sjg Exp $
# $Id: doc.mk,v 1.8 2021/12/08 05:56:50 sjg Exp $
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
__${.PARSEFILE}__: .NOTMAIN
.include <init.mk>

View File

@ -1,4 +1,4 @@
# $Id: dpadd.mk,v 1.29 2021/04/20 02:30:44 sjg Exp $
# $Id: dpadd.mk,v 1.30 2021/12/08 05:56:50 sjg Exp $
#
# @(#) Copyright (c) 2004, Simon J. Gerraty
#
@ -77,7 +77,7 @@
#
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
__${.PARSEFILE}__: .NOTMAIN
# sometimes we play games with .CURDIR etc
# _* hold the original values of .*

View File

@ -1,7 +1,7 @@
# $Id: final.mk,v 1.9 2018/01/24 22:57:11 sjg Exp $
# $Id: final.mk,v 1.10 2021/12/08 05:56:50 sjg Exp $
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
__${.PARSEFILE}__: .NOTMAIN
# provide a hook for folk who want to do scary stuff
.-include <${.CURDIR:H}/Makefile-final.inc>

View File

@ -1,4 +1,4 @@
# $Id: init.mk,v 1.25 2020/11/27 17:59:46 sjg Exp $
# $Id: init.mk,v 1.26 2021/12/08 05:56:50 sjg Exp $
#
# @(#) Copyright (c) 2002, Simon J. Gerraty
#
@ -14,7 +14,7 @@
#
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
__${.PARSEFILE}__: .NOTMAIN
.if ${MAKE_VERSION:U0} > 20100408
_this_mk_dir := ${.PARSEDIR:tA}

View File

@ -55,7 +55,7 @@
# Simon J. Gerraty <sjg@crufty.net>
# RCSid:
# $Id: install-mk,v 1.196 2021/06/19 15:30:41 sjg Exp $
# $Id: install-mk,v 1.206 2021/12/11 18:57:41 sjg Exp $
#
# @(#) Copyright (c) 1994 Simon J. Gerraty
#
@ -70,7 +70,7 @@
# sjg@crufty.net
#
MK_VERSION=20210616
MK_VERSION=20211212
OWNER=
GROUP=
MODE=444

View File

@ -1,6 +1,6 @@
#
# RCSid:
# $Id: java.mk,v 1.15 2020/08/19 17:51:53 sjg Exp $
# $Id: java.mk,v 1.16 2021/12/08 05:56:50 sjg Exp $
# @(#) Copyright (c) 1998-2001, Simon J. Gerraty
#
@ -16,7 +16,7 @@
#
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
__${.PARSEFILE}__: .NOTMAIN
.include <init.mk>

View File

@ -1,4 +1,4 @@
# $Id: ldorder.mk,v 1.25 2018/04/24 23:50:26 sjg Exp $
# $Id: ldorder.mk,v 1.26 2021/12/08 05:56:50 sjg Exp $
#
# @(#) Copyright (c) 2015, Simon J. Gerraty
#
@ -130,7 +130,7 @@ ${_ldorder}: ${_ldorders}
# it can also add to CFLAGS etc.
.for __inc in ${LDORDER_LIBS:S,$,.${LDORDER_INC},}
.if !target(__${__inc}__)
__${__inc}__:
__${__inc}__: .NOTMAIN
# make sure this is reset
LDORDER_LIBS =
_ldorders =

View File

@ -1,7 +1,7 @@
# $Id: lib.mk,v 1.71 2020/08/19 17:51:53 sjg Exp $
# $Id: lib.mk,v 1.73 2021/12/08 05:56:50 sjg Exp $
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
__${.PARSEFILE}__: .NOTMAIN
.include <init.mk>
@ -170,7 +170,7 @@ LD_solib= lib${LIB}_pic.a
.elif ${TARGET_OSNAME} == "Linux"
SHLIB_LD = ${CC}
# this is ambiguous of course
LD_shared=-shared -Wl,"-soname lib${LIB}.so.${SHLIB_MAJOR}"
LD_shared=-shared -Wl,-soname,lib${LIB}.so.${SHLIB_MAJOR}
LD_solib= -Wl,--whole-archive lib${LIB}_pic.a -Wl,--no-whole-archive
.if ${COMPILER_TYPE} == "gcc"
# Linux uses GNU ld, which is a multi-pass linker

View File

@ -1,9 +1,12 @@
# $Id: man.mk,v 1.20 2012/12/13 01:51:01 sjg Exp $
# $Id: man.mk,v 1.25 2021/10/31 03:03:14 sjg Exp $
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
__${.PARSEFILE}__: .NOTMAIN
OPTIONS_DEFAULT_NO += CMT2DOC
.include <init.mk>
.include <options.mk>
# unlike bsd.man.mk we handle 3 approaches
# 1. install unformated nroff (default)
@ -21,45 +24,38 @@ NROFF?= nroff
MANDIR?= /usr/share/man
MANDOC?= man
.SUFFIXES: .1 .2 .3 .4 .5 .6 .7 .8 .9 .cat1 .cat2 .cat3 .cat4 .cat5 .cat6 \
.cat7 .cat8 .cat9
MAN_SUFFIXES?= .1 .2 .3 .4 .5 .6 .7 .8 .9
.SUFFIXES: ${MAN_SUFFIXES}
.if ${MANTARGET} == "cat"
.SUFFIXES: ${MAN_SUFFIXES:S,.,.cat,}
.endif
.9.cat9 .8.cat8 .7.cat7 .6.cat6 .5.cat5 .4.cat4 .3.cat3 .2.cat2 .1.cat1:
${MAN_SUFFIXES:@s@$s${s:S,.,.cat,}@}:
@echo "${NROFF} -${MANDOC} ${.IMPSRC} > ${.TARGET:T}"
@${NROFF} -${MANDOC} ${.IMPSRC} > ${.TARGET:T} || ( rm -f ${.TARGET:T} ; false )
@${NROFF} -${MANDOC} ${.IMPSRC} > ${.TARGET:T}.new && \
mv ${.TARGET:T}.new ${.TARGET:T}
.if defined(MAN) && !empty(MAN)
# we use cmt2doc.pl to extract manpages from source
# this is triggered by the setting of EXTRACT_MAN or MAN being set but
# not existsing.
.if !exists(${MAN:[1]}) && !target(${MAN:[1]})
.if defined(EXTRACT_MAN) && ${EXTRACT_MAN} == "no"
MAN=
.else
.if exists(/usr/local/share/bin/cmt2doc.pl)
CMT2DOC?= cmt2doc.pl
.if ${MK_CMT2DOC} == "yes"
# use cmt2doc.py to extract manpages from source
CMT2DOC?= cmt2doc.py
CMT2DOC_OPTS?= ${CMT2DOC_ORGOPT} -pmS${.TARGET:E}
.endif
.ifdef CMT2DOC
.c.8 .c.5 .c.3 .c.4 .c.1 \
.cc.8 .cc.5 .cc.3 .cc.4 .cc.1 \
.h.8 .h.5 .h.3 .h.4 .h.1 \
.sh.8 .sh.5 .sh.3 .sh.4 .sh.1 \
.pl.8 .pl.5 .pl.3 .pl.4 .pl.1:
CMT2DOC_SUFFIXES+= .c .h .sh .pl .py
.SUFFIXES: ${CMT2DOC_SUFFIXES}
${CMT2DOC_SUFFIXES:@s@${MAN_SUFFIXES:@m@$s$m@}@}:
@echo "${CMT2DOC} ${.IMPSRC} > ${.TARGET:T}"
@${CMT2DOC} ${CMT2DOC_OPTS} ${.IMPSRC} > ${.TARGET:T} || ( rm -f ${.TARGET:T} ; false )
.else
MAN=
.endif
.endif
@${CMT2DOC} ${CMT2DOC_OPTS} ${.IMPSRC} > ${.TARGET:T}.new && \
mv ${.TARGET:T}.new ${.TARGET:T}
.endif
_mandir=${DESTDIR}${MANDIR}/${MANTARGET}`echo $$page | sed -e 's/.*\.cat/./' -e 's/.*\.//'`
.if ${MANTARGET} == "cat"
_mfromdir?=.
MANALL= ${MAN:S/.1$/.cat1/g:S/.2$/.cat2/g:S/.3$/.cat3/g:S/.4$/.cat4/g:S/.5$/.cat5/g:S/.6$/.cat6/g:S/.7$/.cat7/g:S/.8$/.cat8/g:S/.9$/.cat9/g}
MANALL= ${MAN:${MAN_SUFFIXES:S,.,,:@m@S/.$m/.cat$m/@:ts:}}
.if ${MCATEXT} == ""
_minstpage=`echo $$page | sed 's/\.cat/./'`
.else

View File

@ -1,4 +1,4 @@
# $Id: meta.autodep.mk,v 1.54 2021/03/06 17:03:18 sjg Exp $
# $Id: meta.autodep.mk,v 1.55 2021/12/13 08:12:01 sjg Exp $
#
# @(#) Copyright (c) 2010, Simon J. Gerraty
@ -23,8 +23,12 @@ __${_this}__: .NOTMAIN
PICO?= .pico
.if defined(SRCS)
.if ${MAKE_VERSION:U0} >= 20211212
OBJ_EXTENSIONS += ${.SUFFIXES:M*o}
.else
# it would be nice to be able to query .SUFFIXES
OBJ_EXTENSIONS+= .o .po .lo ${PICO}
OBJ_EXTENSIONS += .o .po .lo ${PICO}
.endif
# explicit dependencies help short-circuit .SUFFIX searches
SRCS_DEP_FILTER+= N*.[hly]
@ -163,7 +167,11 @@ _depend = .depend
# it would be nice to be able to get .SUFFIXES as ${.SUFFIXES}
# we actually only care about the .SUFFIXES of files that might be
# generated by tools like yacc.
.if ${MAKE_VERSION:U0} >= 20211212
DEPEND_SUFFIXES += ${.SUFFIXES:N.sh:N*[0-9aFfglopmnrSsty]}
.else
DEPEND_SUFFIXES += .c .h .cpp .hpp .cxx .hxx .cc .hh
.endif
.depend: .NOMETA $${.MAKE.META.CREATED} ${_this}
@echo "Updating $@: ${.OODATE:T:[1..8]}"
@egrep -i '^R .*\.(${DEPEND_SUFFIXES:tl:O:u:S,^.,,:ts|})$$' /dev/null ${.MAKE.META.FILES:T:O:u:${META_FILE_FILTER:ts:}:M*o.meta} | \

View File

@ -1,4 +1,4 @@
# $Id: meta.stage.mk,v 1.61 2021/01/31 04:43:12 sjg Exp $
# $Id: meta.stage.mk,v 1.64 2021/12/08 05:56:50 sjg Exp $
#
# @(#) Copyright (c) 2011-2017, Simon J. Gerraty
#
@ -66,7 +66,7 @@ GENDIRDEPS_FILTER += Nnot-empty-is-important \
LN_CP_SCRIPT = LnCp() { \
rm -f $$2 2> /dev/null; \
{ [ -z "$$mode" ] && ${LN:Uln} $$1 $$2 2> /dev/null; } || \
cp -p $$1 $$2; }
cp -p $$1 $$2 2> /dev/null || cp $$1 $$2; }
# a staging conflict should cause an error
# a warning is handy when bootstapping different options.
@ -264,7 +264,8 @@ CLEANFILES += ${STAGE_AS_SETS:@s@stage*$s@}
# sometimes things need to be renamed as they are staged
# each ${file} will be staged as ${STAGE_AS_${file:T}}
# one could achieve the same with SYMLINKS
# stage_as_and_symlink makes the original name a symlink to the new name
# stage_as_and_symlink makes the original name (or ${STAGE_LINK_AS_${name}})
# a symlink to the new name
# it is the same as using stage_as and stage_symlinks but ensures
# both operations happen together
.for s in ${STAGE_AS_SETS:O:u}
@ -294,7 +295,7 @@ STAGE_AS_AND_SYMLINK.$s ?= ${.ALLSRC:N.dirdep:Nstage_*}
stage_as_and_symlink: stage_as_and_symlink.$s
stage_as_and_symlink.$s: .dirdep
@${STAGE_AS_SCRIPT}; StageAs ${FLAGS.$@} ${STAGE_FILES_DIR.$s:U${STAGE_DIR.$s}:${STAGE_DIR_FILTER}} ${STAGE_AS_AND_SYMLINK.$s:O:@f@$f ${STAGE_AS_${f:tA}:U${STAGE_AS_${f:T}:U${f:T}}}@}
@${STAGE_LINKS_SCRIPT}; StageLinks -s ${STAGE_FILES_DIR.$s:U${STAGE_DIR.$s}:${STAGE_DIR_FILTER}} ${STAGE_AS_AND_SYMLINK.$s:O:@f@${STAGE_AS_${f:tA}:U${STAGE_AS_${f:T}:U${f:T}}} $f@}
@${STAGE_LINKS_SCRIPT}; StageLinks -s ${STAGE_FILES_DIR.$s:U${STAGE_DIR.$s}:${STAGE_DIR_FILTER}} ${STAGE_AS_AND_SYMLINK.$s:O:@f@${STAGE_AS_${f:tA}:U${STAGE_AS_${f:T}:U${f:T}}} ${STAGE_LINK_AS_${f}:U$f}@}
@touch $@
.endif
.endif
@ -306,7 +307,7 @@ CLEANFILES += ${STAGE_TARGETS} stage_incs stage_includes
# this lot also only makes sense the first time...
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
__${.PARSEFILE}__: .NOTMAIN
# stage_*links usually needs to follow any others.
# for non-jobs mode the order here matters

View File

@ -1,7 +1,7 @@
# $Id: meta.sys.mk,v 1.38 2020/08/19 17:51:53 sjg Exp $
# $Id: meta.sys.mk,v 1.42 2021/12/13 05:50:55 sjg Exp $
#
# @(#) Copyright (c) 2010-2020, Simon J. Gerraty
# @(#) Copyright (c) 2010-2021, Simon J. Gerraty
#
# This file is provided in the hope that it will
# be of use. There is absolutely NO WARRANTY.
@ -30,21 +30,31 @@ SYS_MK_DIR := ${_PARSEDIR}
.endif
META_MODE += meta verbose
.if ${MAKE_VERSION:U0} > 20130323 && empty(.MAKE.PATH_FILEMON)
# we do not support filemon
META_MODE += nofilemon
MKDEP_MK ?= auto.dep.mk
.endif
.MAKE.MODE ?= ${META_MODE}
.if ${.MAKE.LEVEL} == 0
_filemon := ${.MAKE.PATH_FILEMON:U/dev/filemon}
.if empty(UPDATE_DEPENDFILE)
_make_mode := ${.MAKE.MODE} ${META_MODE}
.if ${_make_mode:M*read*} != "" || ${_make_mode:M*nofilemon*} != ""
# tell everyone we are not updating Makefile.depend*
UPDATE_DEPENDFILE = NO
.export UPDATE_DEPENDFILE
.endif
.if ${UPDATE_DEPENDFILE:Uyes:tl} == "no" && !exists(/dev/filemon)
.if ${_filemon:T:Mfilemon} == "filemon"
.if ${UPDATE_DEPENDFILE:Uyes:tl} == "no" && !exists(${_filemon})
# we should not get upset
META_MODE += nofilemon
.export META_MODE
.endif
.endif
.endif
.if !defined(NO_SILENT)
.if ${MAKE_VERSION} > 20110818
@ -106,7 +116,7 @@ _metaError: .NOMETA .NOTMAIN
# Are we, after all, in meta mode?
.if ${.MAKE.MODE:Uno:Mmeta*} != ""
MKDEP_MK = meta.autodep.mk
MKDEP_MK ?= meta.autodep.mk
.if ${.MAKE.MAKEFILES:M*sys.dependfile.mk} == ""
# this does all the smarts of setting .MAKE.DEPENDFILE
@ -140,12 +150,13 @@ META_NOECHO= :
.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.
.elif ${_filemon:T} == "filemon" && !exists(${_filemon})
.error ${.newline}ERROR: The filemon module (${_filemon}) is not loaded.
.endif
.endif
.if ${.MAKE.LEVEL} == 0
.if ${MK_DIRDEPS_BUILD:Uyes} == "yes"
# make sure dirdeps target exists and do it first
all: dirdeps .WAIT
dirdeps:
@ -156,6 +167,7 @@ dirdeps:
# by default dirdeps is all we want at level0
.MAIN: dirdeps
.endif
.endif
.endif
.else

View File

@ -37,7 +37,7 @@
"""
RCSid:
$Id: meta2deps.py,v 1.38 2021/06/17 05:20:08 sjg Exp $
$Id: meta2deps.py,v 1.40 2021/12/13 19:32:46 sjg Exp $
Copyright (c) 2011-2020, Simon J. Gerraty
Copyright (c) 2011-2017, Juniper Networks, Inc.
@ -165,6 +165,19 @@ def add_trims(x):
x + '/',
x]
def target_spec_exts(target_spec):
"""return a list of dirdep extensions that could match target_spec"""
if target_spec.find(',') < 0:
return ['.'+target_spec]
w = target_spec.split(',')
n = len(w)
e = []
while n > 0:
e.append('.'+','.join(w[0:n]))
n -= 1
return e
class MetaFile:
"""class to parse meta files generated by bmake."""
@ -226,7 +239,8 @@ def __init__(self, name, conf={}):
self.machine = conf.get('MACHINE', '')
self.machine_arch = conf.get('MACHINE_ARCH', '')
self.target_spec = conf.get('TARGET_SPEC', '')
self.target_spec = conf.get('TARGET_SPEC', self.machine)
self.exts = target_spec_exts(self.target_spec)
self.curdir = conf.get('CURDIR')
self.reldir = conf.get('RELDIR')
self.dpdeps = conf.get('DPDEPS')
@ -250,7 +264,7 @@ def __init__(self, name, conf={}):
trim_list = add_trims(self.machine)
if self.machine == 'host':
trim_list += add_trims(self.host_target)
if self.target_spec:
if self.target_spec != self.machine:
trim_list += add_trims(self.target_spec)
for objroot in conf.get('OBJROOTS', []):
@ -280,6 +294,7 @@ def __init__(self, name, conf={}):
print("srctops=", self.srctops, file=self.debug_out)
print("objroots=", self.objroots, file=self.debug_out)
print("excludes=", self.excludes, file=self.debug_out)
print("ext_list=", self.exts, file=self.debug_out)
self.dirdep_re = re.compile(r'([^/]+)/(.+)')
@ -355,10 +370,10 @@ def find_obj(self, objroot, dir, path, input):
ddep = open(ddepf, 'r').readline().strip('# \n')
if self.debug > 1:
print("found %s: %s\n" % (ddepf, ddep), file=self.debug_out)
if ddep.endswith(self.machine):
ddep = ddep[0:-(1+len(self.machine))]
elif self.target_spec and ddep.endswith(self.target_spec):
ddep = ddep[0:-(1+len(self.target_spec))]
for e in self.exts:
if ddep.endswith(e):
ddep = ddep[0:-len(e)]
break
if not ddep:
# no .dirdeps, so remember that we've seen the raw input

View File

@ -1,4 +1,4 @@
# $Id: obj.mk,v 1.16 2020/08/19 17:51:53 sjg Exp $
# $Id: obj.mk,v 1.17 2021/12/08 05:56:50 sjg Exp $
#
# @(#) Copyright (c) 1999-2010, Simon J. Gerraty
#
@ -14,7 +14,7 @@
#
.if !target(__${.PARSEFILE:S,bsd.,,}__)
__${.PARSEFILE:S,bsd.,,}__:
__${.PARSEFILE:S,bsd.,,}__: .NOTMAIN
.include <init.mk>

View File

@ -1,4 +1,4 @@
# $Id: options.mk,v 1.13 2020/08/19 17:51:53 sjg Exp $
# $Id: options.mk,v 1.19 2021/10/03 16:29:51 sjg Exp $
#
# @(#) Copyright (c) 2012, Simon J. Gerraty
#
@ -26,8 +26,8 @@
# User sets WITH_* and WITHOUT_* to indicate what they want.
# We set ${OPTION_PREFIX:UMK_}* which is then all we need care about.
OPTIONS_DEFAULT_VALUES += \
${OPTIONS_DEFAULT_NO:O:u:S,$,/no,} \
${OPTIONS_DEFAULT_YES:O:u:S,$,/yes,}
${OPTIONS_DEFAULT_NO:U:O:u:S,$,/no,} \
${OPTIONS_DEFAULT_YES:U:O:u:S,$,/yes,}
OPTION_PREFIX ?= MK_
@ -36,6 +36,10 @@ OPTION_PREFIX ?= MK_
# DOMINANT_* is set to "yes"
# Otherwise WITH_* and WITHOUT_* override the default.
.for o in ${OPTIONS_DEFAULT_VALUES:M*/*}
.if defined(WITH_${o:H}) && ${WITH_${o:H}} == "no"
# a common miss-use - point out correct usage
.warning use WITHOUT_${o:H}=1 not WITH_${o:H}=no
.endif
.if defined(NO_${o:H}) || defined(NO${o:H})
# we cannot do it
${OPTION_PREFIX}${o:H} ?= no
@ -77,6 +81,32 @@ ${OPTION_PREFIX}${o:H} ?= no
${OPTION_PREFIX}${o:H} ?= ${${OPTION_PREFIX}${o:T}}
.endif
.endfor
.undef OPTIONS_DEFAULT_VALUES
# allow displaying/describing set options
.set_options := ${.set_options} \
${OPTIONS_DEFAULT_VALUES:H:N.} \
${OPTIONS_DEFAULT_DEPENDENT:U:H:N.} \
# this can be used in .info as well as target below
OPTIONS_SHOW ?= ${.set_options:O:u:@o@${OPTION_PREFIX}$o=${${OPTION_PREFIX}$o}@}
# prefix for variables describing options
OPTION_DESCRIPTION_PREFIX ?= DESCRIPTION_
OPTION_DESCRIPTION_SEPARATOR ?= ==
OPTIONS_DESCRIBE ?= ${.set_options:O:u:@o@${OPTION_PREFIX}$o=${${OPTION_PREFIX}$o}${${OPTION_DESCRIPTION_PREFIX}$o:S,^, ${OPTION_DESCRIPTION_SEPARATOR} ,1}${.newline}@}
.if !commands(show-options)
show-options: .NOTMAIN .PHONY
@echo; echo "${OPTIONS_SHOW:ts\n}"; echo
.endif
.if !commands(describe-options)
describe-options: .NOTMAIN .PHONY
@echo; echo "${OPTIONS_DESCRIBE}"; echo
.endif
# we expect to be included more than once
.undef OPTIONS_DEFAULT_DEPENDENT
.undef OPTIONS_DEFAULT_NO
.undef OPTIONS_DEFAULT_VALUES
.undef OPTIONS_DEFAULT_YES

View File

@ -1,7 +1,7 @@
# $Id: own.mk,v 1.42 2020/11/27 18:00:08 sjg Exp $
# $Id: own.mk,v 1.44 2021/12/08 05:56:50 sjg Exp $
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
__${.PARSEFILE}__: .NOTMAIN
.if !target(__init.mk__)
.include "init.mk"
@ -257,11 +257,13 @@ MK_NLS= no
.if ${MK_META_MODE:Uno} == "yes"
# should all be set by sys.mk if not default
TARGET_SPEC_VARS ?= MACHINE
.if ${MAKE_VERSION} >= 20120325
.if ${TARGET_SPEC_VARS:[#]} > 1
TARGET_SPEC_VARS_REV := ${TARGET_SPEC_VARS:[-1..1]}
.else
TARGET_SPEC_VARS_REV = ${TARGET_SPEC_VARS}
.endif
.endif
.if ${MK_STAGING} == "yes"
STAGE_ROOT?= ${OBJROOT}/stage
STAGE_OBJTOP?= ${STAGE_ROOT}/${TARGET_SPEC_VARS_REV:ts/}

View File

@ -1,4 +1,4 @@
# $Id: prlist.mk,v 1.4 2020/08/19 17:51:53 sjg Exp $
# $Id: prlist.mk,v 1.5 2021/12/08 05:56:50 sjg Exp $
#
# @(#) Copyright (c) 2006, Simon J. Gerraty
#
@ -14,7 +14,7 @@
#
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
__${.PARSEFILE}__: .NOTMAIN
# this needs to be included after all the lists it will process
# are defined - which is why it is a separate file.

View File

@ -1,7 +1,7 @@
# $Id: prog.mk,v 1.36 2020/08/19 17:51:53 sjg Exp $
# $Id: prog.mk,v 1.37 2021/12/08 05:56:50 sjg Exp $
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
__${.PARSEFILE}__: .NOTMAIN
.include <init.mk>

View File

@ -37,7 +37,7 @@
#
# RCSid:
# $Id: stage-install.sh,v 1.9 2020/08/28 01:04:13 sjg Exp $
# $Id: stage-install.sh,v 1.10 2021/11/17 07:06:31 sjg Exp $
#
# @(#) Copyright (c) 2013-2020, Simon J. Gerraty
#
@ -117,8 +117,12 @@ StageDirdep() {
t=$1
if [ -s $t.dirdep ]; then
cmp -s $_DIRDEP $t.dirdep && return
echo "ERROR: $t installed by `cat $t.dirdep` not `cat $_DIRDEP`" >&2
exit 1
case "${STAGE_CONFLICT:-error}" in
[Ee]*) STAGE_CONFLICT=ERROR action=exit;;
*) STAGE_CONFLICT=WARNING action=: ;;
esac
echo "$STAGE_CONFLICT: $t installed by `cat $t.dirdep` not `cat $_DIRDEP`" >&2
$action 1
fi
LnCp $_DIRDEP $t.dirdep || exit 1
}

View File

@ -1,4 +1,4 @@
# $Id: sys.mk,v 1.52 2020/12/22 20:44:24 sjg Exp $
# $Id: sys.mk,v 1.53 2021/12/13 05:50:13 sjg Exp $
#
# @(#) Copyright (c) 2003-2009, Simon J. Gerraty
#
@ -81,11 +81,10 @@ OPTIONS_DEFAULT_DEPENDENT += \
.-include <options.mk>
.if ${MK_DIRDEPS_BUILD:Uno} == "yes"
MK_META_MODE = yes
# :Uno incase options.mk not installed
.if ${MK_META_MODE:Uno} == "yes"
.-include <meta.sys.mk>
.elif ${MK_META_MODE:Uno} == "yes"
.MAKE.MODE = meta verbose ${META_MODE}
.MAKE.MODE ?= meta verbose {META_MODE}
.endif
# make sure we have a harmless value
.MAKE.MODE ?= normal

View File

@ -1,4 +1,4 @@
# $Id: sys.vars.mk,v 1.6 2020/10/28 20:50:04 sjg Exp $
# $Id: sys.vars.mk,v 1.7 2021/12/08 05:56:50 sjg Exp $
#
# @(#) Copyright (c) 2003-2009, Simon J. Gerraty
#
@ -19,7 +19,7 @@
#
# _this ?= ${.PARSEFILE}
# .if !target(__${_this}__)
# __${_this}__:
# __${_this}__: .NOTMAIN
#
.if ${MAKE_VERSION:U0} > 20100408
_this = ${.PARSEDIR:tA}/${.PARSEFILE}

View File

@ -0,0 +1,13 @@
# $Id: SCO_SV.mk,v 1.1 2021/10/13 16:45:52 sjg Exp $
OS = SCO_SV
OS_DEF_FLAG := -D${OS}
CC ?= gcc
CXX ?= g++
DEV_TOOLS_PREFIX ?= /usr/xdev
FC ?= gfortran
INSTALL ?= /usr/gnu/bin/install
LD ?= gcc
.include "UnixWare.mk"

View File

@ -1,16 +1,18 @@
# $Id: UnixWare.mk,v 1.7 2020/08/19 17:51:53 sjg Exp $
# $Id: UnixWare.mk,v 1.8 2021/10/13 16:45:52 sjg Exp $
# based on "Id: SunOS.5.sys.mk,v 1.6 2003/09/30 16:42:23 sjg Exp "
# $NetBSD: sys.mk,v 1.19.2.1 1994/07/26 19:58:31 cgd Exp $
# @(#)sys.mk 5.11 (Berkeley) 3/13/91
OS ?= UnixWare
OS_DEF_FLAG ?= -DUNIXWARE
unix ?= We run ${OS}.
ROOT_GROUP ?= root
DEV_TOOLS_PREFIX ?= /usr/local
# can't fine one anywhere, so just stop the dependency
# can't find one anywhere, so just stop the dependency
LIBCRT0 ?= /dev/null
PATH ?=/usr/sbin:/usr/bin:/usr/ccs/bin:/usr/ccs/lib:/usr/ucb:/usr/local/bin
PATH ?= /usr/sbin:/usr/bin:/usr/ccs/bin:/usr/ccs/lib:/usr/ucb:${DEV_TOOLS_PREFIX}/bin
.SUFFIXES: .out .a .ln .o .c ${CXX_SUFFIXES} .F .f .r .y .l .s .S .cl .p .h .sh .m4
@ -32,8 +34,8 @@ COMPILE.S ?= ${CC} ${AFLAGS} ${CPPFLAGS} -c
LINK.S ?= ${CC} ${AFLAGS} ${CPPFLAGS} ${LDFLAGS}
# at least gcc 2.95 on UnixWare has no internal macro to identify the system
.if exists(/usr/local/bin/gcc)
CC ?= gcc -pipe -DUNIXWARE
.if exists(${DEV_TOOLS_PREFIX}/bin/gcc)
CC ?= gcc -pipe ${OS_DEF_FLAG}
DBG ?= -O -g
STATIC ?= -static
.else
@ -45,8 +47,8 @@ CFLAGS ?= ${DBG}
COMPILE.c ?= ${CC} ${CFLAGS} ${CPPFLAGS} -c
LINK.c ?= ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS}
.if exists(/usr/local/bin/g++)
CXX ?= g++ -DUNIXWARE
.if exists(${DEV_TOOLS_PREFIX}/bin/g++)
CXX ?= g++ ${OS_DEF_FLAG}
.else
CXX ?= c++ # XXX: don't know about UDK compilers
.endif
@ -54,13 +56,17 @@ CXXFLAGS ?= ${CFLAGS}
COMPILE.cc ?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} -c
LINK.cc ?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS}
.if exists(${DEV_TOOLS_PREFIX}/bin/cpp)
CPP ?= cpp
.else
CPP ?= /usr/ccs/lib/cpp
.endif
.if defined(DESTDIR)
CPPFLAGS+= -nostdinc -idirafter ${DESTDIR}/usr/include
.endif
MK_DEP ?= mkdeps.sh -N
.if exists(/usr/local/bin/g77)
.if exists(${DEV_TOOLS_PREFIX}/bin/g77)
FC ?= g77
.else
FC ?= f77 # XXX: don't know about UDK compilers
@ -125,7 +131,7 @@ SIZE ?= size
TSORT ?= tsort
.if exists(/usr/local/bin/bison)
.if exists(${DEV_TOOLS_PREFIX}/bin/bison)
YACC ?= bison -y
.else
YACC ?= yacc

View File

@ -1,4 +1,4 @@
/* $NetBSD: nonints.h,v 1.213 2021/04/11 13:35:56 rillig Exp $ */
/* $NetBSD: nonints.h,v 1.217 2021/12/12 20:45:48 sjg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@ -165,9 +165,9 @@ bool Parse_IsVar(const char *, VarAssign *out_var);
void Parse_Var(VarAssign *, GNode *);
void Parse_AddIncludeDir(const char *);
void Parse_File(const char *, int);
void Parse_SetInput(const char *, int, int, ReadMoreProc, void *);
void Parse_PushInput(const char *, int, int, ReadMoreProc, void *);
void Parse_MainName(GNodeList *);
int Parse_GetFatals(void);
int Parse_NumErrors(void);
#ifndef HAVE_STRLCPY
@ -192,6 +192,7 @@ void Suff_FindDeps(GNode *);
SearchPath *Suff_FindPath(GNode *);
void Suff_SetNull(const char *);
void Suff_PrintAll(void);
const char *Suff_NamesStr(void);
/* targ.c */
void Targ_Init(void);
@ -211,7 +212,7 @@ void Targ_PrintCmds(GNode *);
void Targ_PrintNode(GNode *, int);
void Targ_PrintNodes(GNodeList *, int);
const char *Targ_FmtTime(time_t);
void Targ_PrintType(int);
void Targ_PrintType(GNodeType);
void Targ_PrintGraph(int);
void Targ_Propagate(void);
const char *GNodeMade_Name(GNodeMade);

View File

@ -17,7 +17,7 @@
# Simon J. Gerraty <sjg@crufty.net>
# RCSid:
# $Id: os.sh,v 1.56 2020/08/05 23:25:22 sjg Exp $
# $Id: os.sh,v 1.59 2021/11/14 04:18:00 sjg Exp $
#
# @(#) Copyright (c) 1994 Simon J. Gerraty
#
@ -172,7 +172,7 @@ Interix)
MACHINE=i386
MACHINE_ARCH=i386
;;
UnixWare)
UnixWare|SCO_SV)
OSREL=`uname -v`
OSMAJOR=`IFS=.; set $OSREL; echo $1`
MACHINE_ARCH=`uname -m`

View File

@ -1,4 +1,4 @@
/* $NetBSD: parse.c,v 1.560 2021/06/21 10:42:06 rillig Exp $ */
/* $NetBSD: parse.c,v 1.574 2021/12/12 15:44:41 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@ -124,7 +124,7 @@
#include "pathnames.h"
/* "@(#)parse.c 8.3 (Berkeley) 3/19/94" */
MAKE_RCSID("$NetBSD: parse.c,v 1.560 2021/06/21 10:42:06 rillig Exp $");
MAKE_RCSID("$NetBSD: parse.c,v 1.574 2021/12/12 15:44:41 rillig Exp $");
/* types and constants */
@ -139,10 +139,14 @@ typedef struct IFile {
unsigned int cond_depth; /* 'if' nesting when file opened */
bool depending; /* state of doing_depend on EOF */
/* The buffer from which the file's content is read. */
/*
* The buffer from which the file's content is read. The buffer
* always ends with '\n', the buffer is not null-terminated, that is,
* buf_end[0] is already out of bounds.
*/
char *buf_freeIt;
char *buf_ptr; /* next char to be read */
char *buf_end;
char *buf_end; /* buf_end[-1] == '\n' */
/* Function to read more data, with a single opaque argument. */
ReadMoreProc readMore;
@ -233,7 +237,7 @@ static GNode *order_pred;
/* parser state */
/* number of fatal errors */
static int fatals = 0;
static int parseErrors = 0;
/*
* Variables for doing includes
@ -276,7 +280,7 @@ SearchPath *defSysIncPath; /* default for sysIncPath */
* keyword is used as a source ("0" if the keyword isn't special as a source)
*/
static const struct {
const char *name; /* Name of keyword */
const char name[17]; /* Name of keyword */
ParseSpecial spec; /* Type when used as a target */
GNodeType op; /* Operator when used as a source */
} parseKeywords[] = {
@ -329,8 +333,6 @@ static const struct {
/* file loader */
struct loadedfile {
/* XXX: What is the lifetime of this path? Who manages the memory? */
const char *path; /* name, for error reports */
char *buf; /* contents buffer */
size_t len; /* length of contents */
bool used; /* XXX: have we used the data yet */
@ -338,12 +340,11 @@ struct loadedfile {
/* XXX: What is the lifetime of the path? Who manages the memory? */
static struct loadedfile *
loadedfile_create(const char *path, char *buf, size_t buflen)
loadedfile_create(char *buf, size_t buflen)
{
struct loadedfile *lf;
lf = bmake_malloc(sizeof *lf);
lf->path = path == NULL ? "(stdin)" : path;
lf->buf = buf;
lf->len = buflen;
lf->used = false;
@ -468,8 +469,7 @@ loadfile(const char *path, int fd)
close(fd);
{
struct loadedfile *lf = loadedfile_create(path,
buf.data, buf.len);
struct loadedfile *lf = loadedfile_create(buf.data, buf.len);
Buf_DoneData(&buf);
return lf;
}
@ -545,7 +545,7 @@ ParseIsEscaped(const char *line, const char *c)
* was first defined.
*/
static void
ParseMark(GNode *gn)
RememberLocation(GNode *gn)
{
IFile *curFile = CurFile();
gn->fname = curFile->fname;
@ -628,7 +628,7 @@ ParseVErrorInternal(FILE *f, const char *fname, size_t lineno,
goto print_stack_trace;
if (type == PARSE_WARNING && !opts.parseWarnFatal)
goto print_stack_trace;
fatals++;
parseErrors++;
if (type == PARSE_WARNING && !fatal_warning_error_printed) {
Error("parsing warnings being treated as errors");
fatal_warning_error_printed = true;
@ -797,7 +797,7 @@ TryApplyDependencyOperator(GNode *gn, GNodeType op)
cohort = Targ_NewInternalNode(gn->name);
if (doing_depend)
ParseMark(cohort);
RememberLocation(cohort);
/*
* Make the cohort invisible as well to avoid duplicating it
* into other variables. True, parents of this target won't
@ -852,7 +852,7 @@ ParseDependencySourceWait(bool isSpecial)
snprintf(wait_src, sizeof wait_src, ".WAIT_%u", ++wait_number);
gn = Targ_NewInternalNode(wait_src);
if (doing_depend)
ParseMark(gn);
RememberLocation(gn);
gn->type = OP_WAIT | OP_PHONY | OP_DEPENDS | OP_NOTMAIN;
LinkToTargets(gn, isSpecial);
@ -912,7 +912,7 @@ ParseDependencySourceOrder(const char *src)
*/
gn = Targ_GetNode(src);
if (doing_depend)
ParseMark(gn);
RememberLocation(gn);
if (order_pred != NULL) {
Lst_Append(&order_pred->order_succ, gn);
Lst_Append(&gn->order_pred, order_pred);
@ -949,7 +949,7 @@ ParseDependencySourceOther(const char *src, GNodeType tOp,
/* Find/create the 'src' node and attach to all targets */
gn = Targ_GetNode(src);
if (doing_depend)
ParseMark(gn);
RememberLocation(gn);
if (tOp != OP_NONE)
gn->type |= tOp;
else
@ -1019,7 +1019,7 @@ ParseErrorNoDependency(const char *lstart)
(strncmp(lstart, "======", 6) == 0) ||
(strncmp(lstart, ">>>>>>", 6) == 0))
Parse_Error(PARSE_FATAL,
"Makefile appears to contain unresolved cvs/rcs/??? merge conflicts");
"Makefile appears to contain unresolved CVS/RCS/??? merge conflicts");
else if (lstart[0] == '.') {
const char *dirstart = lstart + 1;
const char *dirend;
@ -1100,7 +1100,7 @@ ParseDependencyTargetSpecial(ParseSpecial *inout_specType,
case SP_INTERRUPT: {
GNode *gn = Targ_GetNode(targetName);
if (doing_depend)
ParseMark(gn);
RememberLocation(gn);
gn->type |= OP_NOTMAIN | OP_SPECIAL;
Lst_Append(targets, gn);
break;
@ -1230,7 +1230,7 @@ ParseDependencyTargetMundane(char *targetName, StringList *curTargs)
? Suff_AddTransform(targName)
: Targ_GetNode(targName);
if (doing_depend)
ParseMark(gn);
RememberLocation(gn);
Lst_Append(targets, gn);
}
@ -1612,10 +1612,8 @@ ParseDependencySourcesMundane(char *start, char *end,
* See the tests depsrc-*.mk.
*/
static void
ParseDependencySources(char *const line, char *const cp,
GNodeType const tOp,
ParseSpecial const specType,
SearchPathList ** inout_paths)
ParseDependencySources(char *line, char *cp, GNodeType tOp,
ParseSpecial specType, SearchPathList **inout_paths)
{
if (line[0] == '\0') {
ParseDependencySourcesEmpty(specType, *inout_paths);
@ -2099,7 +2097,7 @@ ParseAddCmd(GNode *gn, char *cmd)
Lst_Append(&gn->commands, cmd);
if (MaybeSubMake(cmd))
gn->type |= OP_SUBMAKE;
ParseMark(gn);
RememberLocation(gn);
} else {
#if 0
/* XXX: We cannot do this until we fix the tree */
@ -2132,7 +2130,7 @@ Parse_AddIncludeDir(const char *dir)
/*
* Handle one of the .[-ds]include directives by remembering the current file
* and pushing the included file on the stack. After the included file has
* finished, parsing continues with the including file; see Parse_SetInput
* finished, parsing continues with the including file; see Parse_PushInput
* and ParseEOF.
*
* System includes are looked up in sysIncPath, any other includes are looked
@ -2140,7 +2138,7 @@ Parse_AddIncludeDir(const char *dir)
* line options.
*/
static void
IncludeFile(char *file, bool isSystem, bool depinc, bool silent)
IncludeFile(const char *file, bool isSystem, bool depinc, bool silent)
{
struct loadedfile *lf;
char *fullname; /* full pathname of file */
@ -2239,60 +2237,63 @@ IncludeFile(char *file, bool isSystem, bool depinc, bool silent)
lf = loadfile(fullname, fd);
/* Start reading from this file next */
Parse_SetInput(fullname, 0, -1, loadedfile_readMore, lf);
Parse_PushInput(fullname, 0, -1, loadedfile_readMore, lf);
CurFile()->lf = lf;
if (depinc)
doing_depend = depinc; /* only turn it on */
/* TODO: consider free(fullname); */
}
/*
* Parse a directive like '.include' or '.-include'.
*
* .include "user-makefile.mk"
* .include <system-makefile.mk>
*/
static void
ParseInclude(char *directive)
{
char endc; /* the character which ends the file spec */
char *cp; /* current position in file spec */
char endc; /* '>' or '"' */
char *p;
bool silent = directive[0] != 'i';
char *file = directive + (silent ? 8 : 7);
FStr file;
/* Skip to delimiter character so we know where to look */
pp_skip_hspace(&file);
p = directive + (silent ? 8 : 7);
pp_skip_hspace(&p);
if (*file != '"' && *file != '<') {
if (*p != '"' && *p != '<') {
Parse_Error(PARSE_FATAL,
".include filename must be delimited by '\"' or '<'");
return;
}
/*
* Set the search path on which to find the include file based on the
* characters which bracket its name. Angle-brackets imply it's
* a system Makefile while double-quotes imply it's a user makefile
*/
if (*file == '<')
if (*p++ == '<')
endc = '>';
else
endc = '"';
file = FStr_InitRefer(p);
/* Skip to matching delimiter */
for (cp = ++file; *cp != '\0' && *cp != endc; cp++)
continue;
while (*p != '\0' && *p != endc)
p++;
if (*cp != endc) {
if (*p != endc) {
Parse_Error(PARSE_FATAL,
"Unclosed .include filename. '%c' expected", endc);
return;
}
*cp = '\0';
*p = '\0';
/*
* Substitute for any variables in the filename before trying to
* find the file.
*/
(void)Var_Subst(file, SCOPE_CMDLINE, VARE_WANTRES, &file);
/* TODO: handle errors */
if (strchr(file.str, '$') != NULL) {
char *xfile;
Var_Subst(file.str, SCOPE_CMDLINE, VARE_WANTRES, &xfile);
/* TODO: handle errors */
file = FStr_InitOwn(xfile);
}
IncludeFile(file, endc == '>', directive[0] == 'd', silent);
free(file);
IncludeFile(file.str, endc == '>', directive[0] == 'd', silent);
FStr_Done(&file);
}
/*
@ -2314,8 +2315,8 @@ SetFilenameVars(const char *filename, const char *dirvar, const char *filevar)
basename = slash + 1;
}
Global_SetExpand(dirvar, dirname.str);
Global_SetExpand(filevar, basename);
Global_Set(dirvar, dirname.str);
Global_Set(filevar, basename);
DEBUG5(PARSE, "%s: ${%s} = `%s' ${%s} = `%s'\n",
__func__, dirvar, dirname.str, filevar, basename);
@ -2418,7 +2419,7 @@ ParseTrackInput(const char *name)
* The given file is added to the includes stack.
*/
void
Parse_SetInput(const char *name, int lineno, int fd,
Parse_PushInput(const char *name, int lineno, int fd,
ReadMoreProc readMore, void *readMoreArg)
{
IFile *curFile;
@ -2431,7 +2432,7 @@ Parse_SetInput(const char *name, int lineno, int fd,
else
ParseTrackInput(name);
DEBUG3(PARSE, "Parse_SetInput: %s %s, line %d\n",
DEBUG3(PARSE, "Parse_PushInput: %s %s, line %d\n",
readMore == loadedfile_readMore ? "file" : ".for loop in",
name, lineno);
@ -2649,13 +2650,15 @@ typedef enum ParseRawLineResult {
/*
* Parse until the end of a line, taking into account lines that end with
* backslash-newline.
* backslash-newline. The resulting line goes from out_line to out_line_end;
* the line is not null-terminated.
*/
static ParseRawLineResult
ParseRawLine(IFile *curFile, char **out_line, char **out_line_end,
char **out_firstBackslash, char **out_firstComment)
{
char *line = curFile->buf_ptr;
char *buf_end = curFile->buf_end;
char *p = line;
char *line_end = line;
char *firstBackslash = NULL;
@ -2667,14 +2670,14 @@ ParseRawLine(IFile *curFile, char **out_line, char **out_line_end,
for (;;) {
char ch;
if (p == curFile->buf_end) {
if (p == buf_end) {
res = PRLR_EOF;
break;
}
ch = *p;
if (ch == '\0' ||
(ch == '\\' && p + 1 < curFile->buf_end && p[1] == '\0')) {
(ch == '\\' && p + 1 < buf_end && p[1] == '\0')) {
Parse_Error(PARSE_FATAL, "Zero byte read from file");
return PRLR_ERROR;
}
@ -2685,7 +2688,7 @@ ParseRawLine(IFile *curFile, char **out_line, char **out_line_end,
firstBackslash = p;
if (p[1] == '\n') {
curFile->lineno++;
if (p + 2 == curFile->buf_end) {
if (p + 2 == buf_end) {
line_end = p;
*line_end = '\n';
p += 2;
@ -2694,7 +2697,7 @@ ParseRawLine(IFile *curFile, char **out_line, char **out_line_end,
}
p += 2;
line_end = p;
assert(p <= curFile->buf_end);
assert(p <= buf_end);
continue;
}
@ -2904,7 +2907,7 @@ ParseForLoop(const char *line)
line = ParseGetLine(GLM_FOR_BODY);
if (line == NULL) {
Parse_Error(PARSE_FATAL,
"Unexpected end of file in for loop.");
"Unexpected end of file in .for loop");
break;
}
} while (For_Accum(line));
@ -3012,12 +3015,6 @@ ParseLine_ShellCommand(const char *p)
}
}
MAKE_INLINE bool
IsDirective(const char *dir, size_t dirlen, const char *name)
{
return dirlen == strlen(name) && memcmp(dir, name, dirlen) == 0;
}
/*
* See if the line starts with one of the known directives, and if so, handle
* the directive.
@ -3026,8 +3023,8 @@ static bool
ParseDirective(char *line)
{
char *cp = line + 1;
const char *dir, *arg;
size_t dirlen;
const char *arg;
Substring dir;
pp_skip_whitespace(&cp);
if (IsInclude(cp, false)) {
@ -3035,10 +3032,10 @@ ParseDirective(char *line)
return true;
}
dir = cp;
dir.start = cp;
while (ch_isalpha(*cp) || *cp == '-')
cp++;
dirlen = (size_t)(cp - dir);
dir.end = cp;
if (*cp != '\0' && !ch_isspace(*cp))
return false;
@ -3046,31 +3043,31 @@ ParseDirective(char *line)
pp_skip_whitespace(&cp);
arg = cp;
if (IsDirective(dir, dirlen, "undef")) {
Var_Undef(cp);
if (Substring_Equals(dir, "undef")) {
Var_Undef(arg);
return true;
} else if (IsDirective(dir, dirlen, "export")) {
} else if (Substring_Equals(dir, "export")) {
Var_Export(VEM_PLAIN, arg);
return true;
} else if (IsDirective(dir, dirlen, "export-env")) {
} else if (Substring_Equals(dir, "export-env")) {
Var_Export(VEM_ENV, arg);
return true;
} else if (IsDirective(dir, dirlen, "export-literal")) {
} else if (Substring_Equals(dir, "export-literal")) {
Var_Export(VEM_LITERAL, arg);
return true;
} else if (IsDirective(dir, dirlen, "unexport")) {
} else if (Substring_Equals(dir, "unexport")) {
Var_UnExport(false, arg);
return true;
} else if (IsDirective(dir, dirlen, "unexport-env")) {
} else if (Substring_Equals(dir, "unexport-env")) {
Var_UnExport(true, arg);
return true;
} else if (IsDirective(dir, dirlen, "info")) {
} else if (Substring_Equals(dir, "info")) {
ParseMessage(PARSE_INFO, "info", arg);
return true;
} else if (IsDirective(dir, dirlen, "warning")) {
} else if (Substring_Equals(dir, "warning")) {
ParseMessage(PARSE_WARNING, "warning", arg);
return true;
} else if (IsDirective(dir, dirlen, "error")) {
} else if (Substring_Equals(dir, "error")) {
ParseMessage(PARSE_FATAL, "error", arg);
return true;
}
@ -3251,7 +3248,7 @@ Parse_File(const char *name, int fd)
if (name == NULL)
name = "(stdin)";
Parse_SetInput(name, 0, -1, loadedfile_readMore, lf);
Parse_PushInput(name, 0, -1, loadedfile_readMore, lf);
CurFile()->lf = lf;
do {
@ -3265,7 +3262,7 @@ Parse_File(const char *name, int fd)
FinishDependencyGroup();
if (fatals != 0) {
if (parseErrors != 0) {
(void)fflush(stdout);
(void)fprintf(stderr,
"%s: Fatal errors encountered -- cannot continue",
@ -3320,7 +3317,7 @@ Parse_MainName(GNodeList *mainList)
}
int
Parse_GetFatals(void)
Parse_NumErrors(void)
{
return fatals;
return parseErrors;
}

104
contrib/bmake/sigact.h Normal file
View File

@ -0,0 +1,104 @@
/* NAME:
* sigact.h - sigaction et al
*
* SYNOPSIS:
* #include "sigact.h"
*
* DESCRIPTION:
* This header is the interface to a fake sigaction(2)
* implementation. It provides a POSIX compliant interface
* to whatever signal handling mechanisms are available.
* It also provides a Signal() function that is implemented
* in terms of sigaction().
* If not using signal(2) as part of the underlying
* implementation (USE_SIGNAL or USE_SIGMASK), and
* NO_SIGNAL is not defined, it also provides a signal()
* function that calls Signal().
*
* SEE ALSO:
* sigact.c
*/
/*
* RCSid:
* $Id: sigact.h,v 1.4 2021/10/14 19:39:17 sjg Exp $
*/
#ifndef _SIGACT_H
#define _SIGACT_H
#include <sys/cdefs.h>
/*
* most modern systems use void for signal handlers but
* not all.
*/
#ifndef SIG_HDLR
# define SIG_HDLR void
#endif
/*
* if you want to install this header as signal.h,
* modify this to pick up the original signal.h
*/
#ifndef SIGKILL
# include <signal.h>
#endif
#ifndef SIGKILL
# include <sys/signal.h>
#endif
#ifndef SIG_ERR
# define SIG_ERR (SIG_HDLR (*)())-1
#endif
#ifndef BADSIG
# define BADSIG SIG_ERR
#endif
#ifndef SA_NOCLDSTOP
/* we assume we need the fake sigaction */
/* sa_flags */
#define SA_NOCLDSTOP 1 /* don't send SIGCHLD on child stop */
#define SA_RESTART 2 /* re-start I/O */
/* sigprocmask flags */
#define SIG_BLOCK 1
#define SIG_UNBLOCK 2
#define SIG_SETMASK 4
/*
* this is a bit untidy
*/
#ifdef _SIGSET_T_
typedef _SIGSET_T_ sigset_t;
#endif
/*
* POSIX sa_handler should return void, but since we are
* implementing in terms of something else, it may
* be appropriate to use the normal SIG_HDLR return type
*/
struct sigaction
{
SIG_HDLR (*sa_handler)();
sigset_t sa_mask;
int sa_flags;
};
int sigaction ( int /*sig*/, const struct sigaction */*act*/, struct sigaction */*oact*/ );
int sigaddset ( sigset_t */*mask*/, int /*sig*/ );
int sigdelset ( sigset_t */*mask*/, int /*sig*/ );
int sigemptyset ( sigset_t */*mask*/ );
int sigfillset ( sigset_t */*mask*/ );
int sigismember ( const sigset_t */*mask*/, int /*sig*/ );
int sigpending ( sigset_t */*set*/ );
int sigprocmask ( int how, const sigset_t */*set*/, sigset_t */*oset*/ );
int sigsuspend ( sigset_t */*mask*/ );
#ifndef sigmask
# define sigmask(s) (1<<((s)-1) & (32 - 1)) /* convert SIGnum to mask */
#endif
#if !defined(NSIG) && defined(_NSIG)
# define NSIG _NSIG
#endif
#endif /* ! SA_NOCLDSTOP */
#endif /* _SIGACT_H */

397
contrib/bmake/sigaction.c Normal file
View File

@ -0,0 +1,397 @@
/* NAME:
* sigact.c - fake sigaction(2)
*
* SYNOPSIS:
* #include "sigact.h"
*
* int sigaction(int sig, struct sigaction *act,
* struct sigaction *oact);
* int sigaddset(sigset_t *mask, int sig);
* int sigdelset(sigset_t *mask, int sig);
* int sigemptyset(sigset_t *mask);
* int sigfillset(sigset_t *mask);
* int sigismember(sigset_t *mask, int sig);
* int sigpending(sigset_t *set);
* int sigprocmask(int how, sigset_t *set, sigset_t *oset);
* int sigsuspend(sigset_t *mask);
*
* SIG_HDLR (*Signal(int sig, SIG_HDLR (*disp)(int)))(int);
*
* DESCRIPTION:
* This is a fake sigaction implementation. It uses
* sigsetmask(2) et al or sigset(2) and friends if
* available, otherwise it just uses signal(2). If it
* thinks sigaction(2) really exists it compiles to "almost"
* nothing.
*
* In any case it provides a Signal() function that is
* implemented in terms of sigaction().
* If not using signal(2) as part of the underlying
* implementation (USE_SIGNAL or USE_SIGMASK), and
* NO_SIGNAL is not defined, it also provides a signal()
* function that calls Signal().
*
* The need for all this mucking about is the problems
* caused by mixing various signal handling mechanisms in
* the one process. This module allows for a consistent
* POSIX compliant interface to whatever is actually
* available.
*
* sigaction() allows the caller to examine and/or set the
* action to be associated with a given signal. "act" and
* "oact" are pointers to 'sigaction structs':
*.nf
*
* struct sigaction
* {
* SIG_HDLR (*sa_handler)();
* sigset_t sa_mask;
* int sa_flags;
* };
*.fi
*
* SIG_HDLR is normally 'void' in the POSIX implementation
* and for most current systems. On some older UNIX
* systems, signal handlers do not return 'void', so
* this implementation keeps 'sa_handler' inline with the
* hosts normal signal handling conventions.
* 'sa_mask' controls which signals will be blocked while
* the selected signal handler is active. It is not used
* in this implementation.
* 'sa_flags' controls various semantics such as whether
* system calls should be automagically restarted
* (SA_RESTART) etc. It is not used in this
* implementation.
* Either "act" or "oact" may be NULL in which case the
* appropriate operation is skipped.
*
* sigaddset() adds "sig" to the sigset_t pointed to by "mask".
*
* sigdelset() removes "sig" from the sigset_t pointed to
* by "mask".
*
* sigemptyset() makes the sigset_t pointed to by "mask" empty.
*
* sigfillset() makes the sigset_t pointed to by "mask"
* full ie. match all signals.
*
* sigismember() returns true if "sig" is found in "*mask".
*
* sigpending() is supposed to return "set" loaded with the
* set of signals that are blocked and pending for the
* calling process. It does nothing in this impementation.
*
* sigprocmask() is used to examine and/or change the
* signal mask for the calling process. Either "set" or
* "oset" may be NULL in which case the appropriate
* operation is skipped. "how" may be one of SIG_BLOCK,
* SIG_UNBLOCK or SIG_SETMASK. If this package is built
* with USE_SIGNAL, then this routine achieves nothing.
*
* sigsuspend() sets the signal mask to "*mask" and waits
* for a signal to be delivered after which the previous
* mask is restored.
*
*
* RETURN VALUE:
* 0==success, -1==failure
*
* BUGS:
* Since we fake most of this, don't expect fancy usage to
* work.
*
* AUTHOR:
* Simon J. Gerraty <sjg@crufty.net>
*/
/* COPYRIGHT:
* @(#)Copyright (c) 1992-2021, Simon J. Gerraty
*
* This is free software. It comes with NO WARRANTY.
* Permission to use, modify and distribute this source code
* is granted subject to the following conditions.
* 1/ that that the above copyright notice and this notice
* are preserved in all copies and that due credit be given
* to the author.
* 2/ that any changes to this code are clearly commented
* as such so that the author does get blamed for bugs
* other than his own.
*
* Please send copies of changes and bug-fixes to:
* sjg@crufty.net
*
*/
#ifndef lint
static char *RCSid = "$Id: sigact.c,v 1.8 2021/10/14 19:39:17 sjg Exp $";
#endif
#undef _ANSI_SOURCE /* causes problems */
#include <signal.h>
#include <sys/cdefs.h>
#ifdef HAVE_CONFIG_H
# include "config.h"
# ifdef NO_SIGSET
# undef HAVE_SIGSET
# endif
# ifndef HAVE_SIGACTION
# ifdef HAVE_SIGSETMASK
# define USE_SIGMASK
# else
# ifdef HAVE_SIGSET
# define USE_SIGSET
# else
# define USE_SIGNAL
# endif
# endif
# endif
#endif
/*
* some systems have a faulty sigaction() implementation!
* Allow us to bypass it.
* Or they may have installed sigact.h as signal.h which is why
* we have SA_NOCLDSTOP defined.
*/
#if !defined(SA_NOCLDSTOP) || defined(_SIGACT_H) || defined(USE_SIGNAL) || defined(USE_SIGSET) || defined(USE_SIGMASK)
/*
* if we haven't been told,
* try and guess what we should implement with.
*/
#if !defined(USE_SIGSET) && !defined(USE_SIGMASK) && !defined(USE_SIGNAL)
# if defined(sigmask) || defined(BSD) || defined(_BSD) && !defined(BSD41)
# define USE_SIGMASK
# else
# ifndef NO_SIGSET
# define USE_SIGSET
# else
# define USE_SIGNAL
# endif
# endif
#endif
/*
* if we still don't know, we're in trouble
*/
#if !defined(USE_SIGSET) && !defined(USE_SIGMASK) && !defined(USE_SIGNAL)
error must know what to implement with
#endif
#include "sigact.h"
/*
* in case signal() has been mapped to our Signal().
*/
#undef signal
int
sigaction(int sig,
const struct sigaction *act,
struct sigaction *oact)
{
SIG_HDLR(*oldh) ();
if (act) {
#ifdef USE_SIGSET
oldh = sigset(sig, act->sa_handler);
#else
oldh = signal(sig, act->sa_handler);
#endif
} else {
if (oact) {
#ifdef USE_SIGSET
oldh = sigset(sig, SIG_IGN);
#else
oldh = signal(sig, SIG_IGN);
#endif
if (oldh != SIG_IGN && oldh != SIG_ERR) {
#ifdef USE_SIGSET
(void) sigset(sig, oldh);
#else
(void) signal(sig, oldh);
#endif
}
}
}
if (oact) {
oact->sa_handler = oldh;
}
return 0; /* hey we're faking it */
}
#ifndef HAVE_SIGADDSET
int
sigaddset(sigset_t *mask, int sig)
{
*mask |= sigmask(sig);
return 0;
}
int
sigdelset(sigset_t *mask, int sig)
{
*mask &= ~(sigmask(sig));
return 0;
}
int
sigemptyset(sigset_t *mask)
{
*mask = 0;
return 0;
}
int
sigfillset(sigset_t *mask)
{
*mask = ~0;
return 0;
}
int
sigismember(const sigset_t *mask, int sig)
{
return ((*mask) & sigmask(sig));
}
#endif
#ifndef HAVE_SIGPENDING
int
sigpending(sigset_t *set)
{
return 0; /* faking it! */
}
#endif
#ifndef HAVE_SIGPROCMASK
int
sigprocmask(int how, const sigset_t *set, sigset_t *oset)
{
#ifdef USE_SIGSET
int i;
#endif
static sigset_t sm;
static int once = 0;
if (!once) {
/*
* initally we clear sm,
* there after, it represents the last
* thing we did.
*/
once++;
#ifdef USE_SIGMASK
sm = sigblock(0);
#else
sm = 0;
#endif
}
if (oset)
*oset = sm;
if (set) {
switch (how) {
case SIG_BLOCK:
sm |= *set;
break;
case SIG_UNBLOCK:
sm &= ~(*set);
break;
case SIG_SETMASK:
sm = *set;
break;
}
#ifdef USE_SIGMASK
(void) sigsetmask(sm);
#else
#ifdef USE_SIGSET
for (i = 1; i < NSIG; i++) {
if (how == SIG_UNBLOCK) {
if (*set & sigmask(i))
sigrelse(i);
} else
if (sm & sigmask(i)) {
sighold(i);
}
}
#endif
#endif
}
return 0;
}
#endif
#ifndef HAVE_SIGSUSPEND
int
sigsuspend(sigset_t *mask)
{
#ifdef USE_SIGMASK
sigpause(*mask);
#else
int i;
#ifdef USE_SIGSET
for (i = 1; i < NSIG; i++) {
if (*mask & sigmask(i)) {
/* not the same sigpause() as above! */
sigpause(i);
break;
}
}
#else /* signal(2) only */
SIG_HDLR(*oldh) ();
/*
* make sure that signals in mask will not
* be ignored.
*/
for (i = 1; i < NSIG; i++) {
if (*mask & sigmask(i)) {
if ((oldh = signal(i, SIG_DFL)) != SIG_ERR &&
oldh != SIG_IGN &&
oldh != SIG_DFL)
(void) signal(i, oldh); /* restore handler */
}
}
pause(); /* wait for a signal */
#endif
#endif
return 0;
}
#endif
#endif /* ! SA_NOCLDSTOP */
#if 0
#if !defined(SIG_HDLR)
#define SIG_HDLR void
#endif
#if !defined(SIG_ERR)
#define SIG_ERR (SIG_HDLR (*)())-1
#endif
#if !defined(USE_SIGNAL) && !defined(USE_SIGMASK) && !defined(NO_SIGNAL)
/*
* ensure we avoid signal mayhem
*/
extern void (*Signal (int sig, void (*handler) (int)))(int);
SIG_HDLR(*signal(int sig, SIG_HDLR(*handler)(int))
{
return (Signal(sig, handler));
}
#endif
#endif
/* This lot (for GNU-Emacs) goes at the end of the file. */
/*
* Local Variables:
* version-control:t
* comment-column:40
* End:
*/

View File

@ -1,4 +1,4 @@
/* $NetBSD: str.c,v 1.85 2021/05/30 21:16:54 rillig Exp $ */
/* $NetBSD: str.c,v 1.86 2021/06/21 16:59:18 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@ -71,7 +71,7 @@
#include "make.h"
/* "@(#)str.c 5.8 (Berkeley) 6/1/90" */
MAKE_RCSID("$NetBSD: str.c,v 1.85 2021/05/30 21:16:54 rillig Exp $");
MAKE_RCSID("$NetBSD: str.c,v 1.86 2021/06/21 16:59:18 rillig Exp $");
/* Return the concatenation of s1 and s2, freshly allocated. */
char *
@ -188,10 +188,9 @@ Substring_Words(const char *str, bool expand)
*word_end++ = '\0';
if (words_len == words_cap) {
size_t new_size;
words_cap *= 2;
new_size = (words_cap + 1) * sizeof(words[0]);
words = bmake_realloc(words, new_size);
words = bmake_realloc(words,
(words_cap + 1) * sizeof(words[0]));
}
words[words_len++] =
Substring_Init(word_start, word_end - 1);

View File

@ -1,4 +1,4 @@
/* $NetBSD: str.h,v 1.9 2021/05/30 21:16:54 rillig Exp $ */
/* $NetBSD: str.h,v 1.12 2021/12/12 13:43:47 rillig Exp $ */
/*
Copyright (c) 2021 Roland Illig <rillig@NetBSD.org>
@ -60,7 +60,6 @@ typedef struct LazyBuf {
size_t len;
size_t cap;
const char *expected;
void *freeIt;
} LazyBuf;
/* The result of splitting a string into words. */
@ -182,6 +181,14 @@ Substring_Equals(Substring sub, const char *str)
memcmp(sub.start, str, len) == 0;
}
MAKE_INLINE bool
Substring_Eq(Substring sub, Substring str)
{
size_t len = Substring_Length(sub);
return len == Substring_Length(str) &&
memcmp(sub.start, str.start, len) == 0;
}
MAKE_STATIC Substring
Substring_Sub(Substring sub, size_t start, size_t end)
{
@ -266,13 +273,12 @@ LazyBuf_Init(LazyBuf *buf, const char *expected)
buf->len = 0;
buf->cap = 0;
buf->expected = expected;
buf->freeIt = NULL;
}
MAKE_INLINE void
LazyBuf_Done(LazyBuf *buf)
{
free(buf->freeIt);
free(buf->data);
}
MAKE_STATIC void
@ -329,6 +335,11 @@ LazyBuf_Get(const LazyBuf *buf)
return Substring_Init(start, start + buf->len);
}
/*
* Returns the content of the buffer as a newly allocated string.
*
* See LazyBuf_Get to avoid unnecessary memory allocations.
*/
MAKE_STATIC FStr
LazyBuf_DoneGet(LazyBuf *buf)
{
@ -352,6 +363,14 @@ Words_Free(Words w)
SubstringWords Substring_Words(const char *, bool);
MAKE_INLINE void
SubstringWords_Init(SubstringWords *w)
{
w->words = NULL;
w->len = 0;
w->freeIt = NULL;
}
MAKE_INLINE void
SubstringWords_Free(SubstringWords w)
{

View File

@ -1,4 +1,4 @@
/* $NetBSD: suff.c,v 1.350 2021/04/04 10:05:08 rillig Exp $ */
/* $NetBSD: suff.c,v 1.357 2021/12/12 20:45:48 sjg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@ -115,7 +115,7 @@
#include "dir.h"
/* "@(#)suff.c 8.4 (Berkeley) 3/21/94" */
MAKE_RCSID("$NetBSD: suff.c,v 1.350 2021/04/04 10:05:08 rillig Exp $");
MAKE_RCSID("$NetBSD: suff.c,v 1.357 2021/12/12 20:45:48 sjg Exp $");
typedef List SuffixList;
typedef ListNode SuffixListNode;
@ -142,37 +142,6 @@ static GNodeList transforms = LST_INIT;
*/
static int sNum = 0;
typedef enum SuffixFlags {
SUFF_NONE = 0,
/*
* This suffix marks include files. Their search path ends up in the
* undocumented special variable '.INCLUDES'.
*/
SUFF_INCLUDE = 1 << 0,
/*
* This suffix marks library files. Their search path ends up in the
* undocumented special variable '.LIBS'.
*/
SUFF_LIBRARY = 1 << 1,
/*
* The empty suffix.
*
* XXX: What is the difference between the empty suffix and the null
* suffix?
*
* XXX: Why is SUFF_NULL needed at all? Wouldn't nameLen == 0 mean
* the same?
*/
SUFF_NULL = 1 << 2
} SuffixFlags;
ENUM_FLAGS_RTTI_3(SuffixFlags,
SUFF_INCLUDE, SUFF_LIBRARY, SUFF_NULL);
typedef List SuffixListList;
/*
@ -184,24 +153,45 @@ typedef struct Suffix {
char *name;
/* Length of the name, to avoid strlen calls */
size_t nameLen;
/* Type of suffix */
SuffixFlags flags;
/*
* This suffix marks include files. Their search path ends up in the
* undocumented special variable '.INCLUDES'.
*/
bool include:1;
/*
* This suffix marks library files. Their search path ends up in the
* undocumented special variable '.LIBS'.
*/
bool library:1;
/*
* The empty suffix.
*
* XXX: What is the difference between the empty suffix and the null
* suffix?
*
* XXX: Why is SUFF_NULL needed at all? Wouldn't nameLen == 0 mean
* the same?
*/
bool isNull:1;
/* The path along which files of this suffix may be found */
SearchPath *searchPath;
/* The suffix number; TODO: document the purpose of this number */
int sNum;
/* Reference count of list membership and several other places */
int refCount;
/* Suffixes we have a transformation to */
SuffixList parents;
/* Suffixes we have a transformation from */
SuffixList children;
/* Lists in which this suffix is referenced.
/*
* Lists in which this suffix is referenced.
*
* XXX: These lists are used nowhere, they are just appended to, for
* no apparent reason. They do have the side effect of increasing
* refCount though. */
* refCount though.
*/
SuffixListList ref;
} Suffix;
@ -475,7 +465,9 @@ Suffix_New(const char *name)
Lst_Init(&suff->parents);
Lst_Init(&suff->ref);
suff->sNum = sNum++;
suff->flags = SUFF_NONE;
suff->include = false;
suff->library = false;
suff->isNull = false;
suff->refCount = 1; /* XXX: why 1? It's not assigned anywhere yet. */
return suff;
@ -502,7 +494,9 @@ Suff_ClearSuffixes(void)
emptySuff = nullSuff = Suffix_New("");
SearchPath_AddAll(nullSuff->searchPath, &dirSearchPath);
nullSuff->flags = SUFF_NULL;
nullSuff->include = false;
nullSuff->library = false;
nullSuff->isNull = true;
}
/*
@ -619,6 +613,7 @@ Suff_AddTransform(const char *name)
/* TODO: Avoid the redundant parsing here. */
bool ok = ParseTransform(name, &srcSuff, &targSuff);
assert(ok);
/* LINTED 129 *//* expression has null effect */
(void)ok;
}
@ -888,12 +883,12 @@ Suff_ExtendPaths(void)
Suffix *suff = ln->datum;
if (!Lst_IsEmpty(&suff->searchPath->dirs)) {
#ifdef INCLUDES
if (suff->flags & SUFF_INCLUDE)
if (suff->include)
SearchPath_AddAll(includesPath,
suff->searchPath);
#endif
#ifdef LIBRARIES
if (suff->flags & SUFF_LIBRARY)
if (suff->library)
SearchPath_AddAll(libsPath, suff->searchPath);
#endif
SearchPath_AddAll(suff->searchPath, &dirSearchPath);
@ -926,7 +921,7 @@ Suff_AddInclude(const char *suffName)
{
Suffix *suff = FindSuffixByName(suffName);
if (suff != NULL)
suff->flags |= SUFF_INCLUDE;
suff->include = true;
}
/*
@ -940,7 +935,7 @@ Suff_AddLib(const char *suffName)
{
Suffix *suff = FindSuffixByName(suffName);
if (suff != NULL)
suff->flags |= SUFF_LIBRARY;
suff->library = true;
}
/********** Implicit Source Search Functions *********/
@ -1043,7 +1038,7 @@ CandidateList_AddCandidatesFor(CandidateList *list, Candidate *cand)
for (ln = cand->suff->children.first; ln != NULL; ln = ln->next) {
Suffix *suff = ln->datum;
if ((suff->flags & SUFF_NULL) && suff->name[0] != '\0') {
if (suff->isNull && suff->name[0] != '\0') {
/*
* If the suffix has been marked as the NULL suffix,
* also create a candidate for a file with no suffix
@ -1918,7 +1913,7 @@ FindDepsRegular(GNode *gn, CandidateSearcher *cs)
* If the suffix indicates that the target is a library, mark that in
* the node's type field.
*/
if (targ->suff->flags & SUFF_LIBRARY)
if (targ->suff->library)
gn->type |= OP_LIB;
/*
@ -2077,14 +2072,14 @@ Suff_SetNull(const char *name)
Suffix *suff = FindSuffixByName(name);
if (suff == NULL) {
Parse_Error(PARSE_WARNING,
"Desired null suffix %s not defined.",
"Desired null suffix %s not defined",
name);
return;
}
if (nullSuff != NULL)
nullSuff->flags &= ~(unsigned)SUFF_NULL;
suff->flags |= SUFF_NULL;
nullSuff->isNull = false;
suff->isNull = true;
/* XXX: Here's where the transformation mangling would take place. */
nullSuff = suff;
}
@ -2117,31 +2112,36 @@ Suff_End(void)
static void
PrintSuffNames(const char *prefix, SuffixList *suffs)
PrintSuffNames(const char *prefix, const SuffixList *suffs)
{
SuffixListNode *ln;
debug_printf("#\t%s: ", prefix);
for (ln = suffs->first; ln != NULL; ln = ln->next) {
Suffix *suff = ln->datum;
const Suffix *suff = ln->datum;
debug_printf("%s ", suff->name);
}
debug_printf("\n");
}
static void
Suffix_Print(Suffix *suff)
Suffix_Print(const Suffix *suff)
{
Buffer buf;
Buf_InitSize(&buf, 16);
Buf_AddFlag(&buf, suff->include, "SUFF_INCLUDE");
Buf_AddFlag(&buf, suff->library, "SUFF_LIBRARY");
Buf_AddFlag(&buf, suff->isNull, "SUFF_NULL");
debug_printf("# \"%s\" (num %d, ref %d)",
suff->name, suff->sNum, suff->refCount);
if (suff->flags != 0) {
char flags_buf[SuffixFlags_ToStringSize];
debug_printf(" (%s)",
SuffixFlags_ToString(flags_buf, suff->flags));
}
if (buf.len > 0)
debug_printf(" (%s)", buf.data);
debug_printf("\n");
Buf_Done(&buf);
PrintSuffNames("To", &suff->parents);
PrintSuffNames("From", &suff->children);
@ -2177,3 +2177,20 @@ Suff_PrintAll(void)
PrintTransformation(ln->datum);
}
}
const char *
Suff_NamesStr(void)
{
Buffer buf;
SuffixListNode *ln;
Suffix *suff;
Buf_InitSize(&buf, 16);
for (ln = sufflist.first; ln != NULL; ln = ln->next) {
suff = ln->datum;
if (ln != sufflist.first)
Buf_AddByte(&buf, ' ');
Buf_AddStr(&buf, suff->name);
}
return Buf_DoneData(&buf);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: targ.c,v 1.168 2021/04/03 12:01:00 rillig Exp $ */
/* $NetBSD: targ.c,v 1.173 2021/11/28 19:51:06 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@ -113,7 +113,7 @@
#include "dir.h"
/* "@(#)targ.c 8.2 (Berkeley) 3/19/94" */
MAKE_RCSID("$NetBSD: targ.c,v 1.168 2021/04/03 12:01:00 rillig Exp $");
MAKE_RCSID("$NetBSD: targ.c,v 1.173 2021/11/28 19:51:06 rillig Exp $");
/*
* All target nodes that appeared on the left-hand side of one of the
@ -187,7 +187,7 @@ GNode_New(const char *name)
gn->uname = NULL;
gn->path = NULL;
gn->type = name[0] == '-' && name[1] == 'l' ? OP_LIB : OP_NONE;
gn->flags = GNF_NONE;
memset(&gn->flags, 0, sizeof(gn->flags));
gn->made = UNMADE;
gn->unmade = 0;
gn->mtime = 0;
@ -309,7 +309,7 @@ Targ_NewInternalNode(const char *name)
Lst_Append(&allTargets, gn);
DEBUG1(TARG, "Adding \"%s\" to all targets.\n", gn->name);
if (doing_depend)
gn->flags |= FROM_DEPEND;
gn->flags.fromDepend = true;
return gn;
}
@ -416,36 +416,37 @@ Targ_FmtTime(time_t tm)
/* Print out a type field giving only those attributes the user can set. */
void
Targ_PrintType(int type)
Targ_PrintType(GNodeType type)
{
int tbit;
static const struct {
GNodeType bit;
bool internal;
const char name[10];
} names[] = {
{ OP_MEMBER, true, "MEMBER" },
{ OP_LIB, true, "LIB" },
{ OP_ARCHV, true, "ARCHV" },
{ OP_PHONY, true, "PHONY" },
{ OP_NOTMAIN, false, "NOTMAIN" },
{ OP_INVISIBLE, false, "INVISIBLE" },
{ OP_MADE, true, "MADE" },
{ OP_JOIN, false, "JOIN" },
{ OP_MAKE, false, "MAKE" },
{ OP_SILENT, false, "SILENT" },
{ OP_PRECIOUS, false, "PRECIOUS" },
{ OP_IGNORE, false, "IGNORE" },
{ OP_EXEC, false, "EXEC" },
{ OP_USE, false, "USE" },
{ OP_OPTIONAL, false, "OPTIONAL" },
};
size_t i;
type &= ~OP_OPMASK;
while (type != 0) {
tbit = 1 << (ffs(type) - 1);
type &= ~tbit;
switch (tbit) {
#define PRINTBIT(bit, attr) case bit: debug_printf(" " attr); break
#define PRINTDBIT(bit, attr) case bit: DEBUG0(TARG, " " attr); break
PRINTBIT(OP_OPTIONAL, ".OPTIONAL");
PRINTBIT(OP_USE, ".USE");
PRINTBIT(OP_EXEC, ".EXEC");
PRINTBIT(OP_IGNORE, ".IGNORE");
PRINTBIT(OP_PRECIOUS, ".PRECIOUS");
PRINTBIT(OP_SILENT, ".SILENT");
PRINTBIT(OP_MAKE, ".MAKE");
PRINTBIT(OP_JOIN, ".JOIN");
PRINTBIT(OP_INVISIBLE, ".INVISIBLE");
PRINTBIT(OP_NOTMAIN, ".NOTMAIN");
PRINTDBIT(OP_LIB, ".LIB");
PRINTDBIT(OP_MEMBER, ".MEMBER");
PRINTDBIT(OP_ARCHV, ".ARCHV");
PRINTDBIT(OP_MADE, ".MADE");
PRINTDBIT(OP_PHONY, ".PHONY");
#undef PRINTBIT
#undef PRINTDBIT
for (i = 0; i < sizeof(names) / sizeof(names[0]); i++) {
if (type & names[i].bit) {
if (names[i].internal)
DEBUG1(TARG, " .%s", names[i].name);
else
debug_printf(" .%s", names[i].name);
}
}
}
@ -480,13 +481,27 @@ GNode_OpName(const GNode *gn)
return "";
}
static bool
GNodeFlags_IsNone(GNodeFlags flags)
{
return !flags.remake
&& !flags.childMade
&& !flags.force
&& !flags.doneWait
&& !flags.doneOrder
&& !flags.fromDepend
&& !flags.doneAllsrc
&& !flags.cycle
&& !flags.doneCycle;
}
/* Print the contents of a node. */
void
Targ_PrintNode(GNode *gn, int pass)
{
debug_printf("# %s%s", gn->name, gn->cohort_num);
GNode_FprintDetails(opts.debug_file, ", ", gn, "\n");
if (gn->flags == 0)
if (GNodeFlags_IsNone(gn->flags))
return;
if (!GNode_IsTarget(gn))

View File

@ -1,4 +1,4 @@
/* $NetBSD: trace.c,v 1.28 2021/02/05 05:15:12 rillig Exp $ */
/* $NetBSD: trace.c,v 1.29 2021/09/21 23:06:18 rillig Exp $ */
/*
* Copyright (c) 2000 The NetBSD Foundation, Inc.
@ -48,13 +48,13 @@
#include "job.h"
#include "trace.h"
MAKE_RCSID("$NetBSD: trace.c,v 1.28 2021/02/05 05:15:12 rillig Exp $");
MAKE_RCSID("$NetBSD: trace.c,v 1.29 2021/09/21 23:06:18 rillig Exp $");
static FILE *trfile;
static pid_t trpid;
const char *trwd;
static const char *evname[] = {
static const char evname[][4] = {
"BEG",
"END",
"ERR",

View File

@ -1,6 +1,6 @@
# $Id: Makefile,v 1.148 2021/06/16 19:18:56 sjg Exp $
# $Id: Makefile,v 1.164 2021/12/12 22:50:00 sjg Exp $
#
# $NetBSD: Makefile,v 1.279 2021/06/16 09:39:48 rillig Exp $
# $NetBSD: Makefile,v 1.288 2021/12/12 22:16:48 rillig Exp $
#
# Unit tests for make(1)
#
@ -167,6 +167,7 @@ TESTS+= directive-for
TESTS+= directive-for-errors
TESTS+= directive-for-escape
TESTS+= directive-for-generating-endif
TESTS+= directive-for-if
TESTS+= directive-for-lines
TESTS+= directive-for-null
TESTS+= directive-hyphen-include
@ -351,13 +352,16 @@ TESTS+= varmod-indirect
TESTS+= varmod-l-name-to-value
TESTS+= varmod-localtime
TESTS+= varmod-loop
TESTS+= varmod-loop-delete
TESTS+= varmod-loop-varname
TESTS+= varmod-match
TESTS+= varmod-match-escape
TESTS+= varmod-no-match
TESTS+= varmod-order
TESTS+= varmod-order-numeric
TESTS+= varmod-order-reverse
TESTS+= varmod-order-shuffle
TESTS+= varmod-order-string
TESTS+= varmod-path
TESTS+= varmod-quote
TESTS+= varmod-quote-dollar
@ -415,6 +419,7 @@ TESTS+= varname-dot-parsedir
TESTS+= varname-dot-parsefile
TESTS+= varname-dot-path
TESTS+= varname-dot-shell
TESTS+= varname-dot-suffixes
TESTS+= varname-dot-targets
TESTS+= varname-empty
TESTS+= varname-make
@ -430,12 +435,41 @@ TESTS+= varparse-mod
TESTS+= varparse-undef-partial
TESTS+= varquote
# for now at least
.if ${.SHELL:T} == "ksh"
BROKEN_TESTS+= sh-flags
.endif
.if ${.MAKE.OS:NDarwin} == ""
BROKEN_TESTS+= shell-ksh
.endif
.if ${.MAKE.OS} == "SCO_SV"
BROKEN_TESTS+= \
opt-debug-graph[23] \
varmod-localtime \
varmod-to-separator \
.if ${.SHELL:T} == "bash"
BROKEN_TESTS+= job-output-null
.else
BROKEN_TESTS+= \
cmd-interrupt \
job-flags \
.endif
.endif
# Some tests just do not work on some platforms or environments
# so allow for some filtering.
.if !empty(BROKEN_TESTS)
.warning Skipping broken tests: ${BROKEN_TESTS:O:u}
TESTS:= ${TESTS:${BROKEN_TESTS:S,^,N,:ts:}}
.endif
# Ideas for more tests:
# char-0020-space.mk
# char-005C-backslash.mk
# escape-cond-str.mk
# escape-cond-func-arg.mk
# escape-cond-func-arg.mk
# escape-varmod.mk
# escape-varmod-define.mk
# escape-varmod-match.mk
@ -457,7 +491,7 @@ ENV.envfirst= FROM_ENV=value-from-env
ENV.varmisc= FROM_ENV=env
ENV.varmisc+= FROM_ENV_BEFORE=env
ENV.varmisc+= FROM_ENV_AFTER=env
ENV.varmod-localtime+= TZ=Europe/Berlin
ENV.varmod-localtime+= TZ=${UTC_1:UEurope/Berlin}
ENV.varname-vpath+= VPATH=varname-vpath.dir:varname-vpath.dir2
# Override make flags for some of the tests; default is -k.
@ -490,7 +524,10 @@ SED_CMDS.job-output-long-lines= \
${:D marker should always be at the beginning of the line. } \
-e '/^aa*--- job-b ---$$/d' \
-e '/^bb*--- job-a ---$$/d'
SED_CMDS.opt-chdir= -e 's,\(nonexistent\).[1-9][0-9]*,\1,'
SED_CMDS.opt-chdir= -e 's,\(nonexistent\).[1-9][0-9]*,\1,' \
-e '/name/s,file,File,' \
-e 's,no such,No such,' \
-e 's,Filename,File name,'
SED_CMDS.opt-debug-graph1= ${STD_SED_CMDS.dg1}
SED_CMDS.opt-debug-graph2= ${STD_SED_CMDS.dg2}
SED_CMDS.opt-debug-graph3= ${STD_SED_CMDS.dg3}
@ -511,11 +548,13 @@ SED_CMDS.sh-dots+= -e 's,^make: exec(\(.*\)) failed (.*)$$,<not found: \1>,'
SED_CMDS.sh-dots+= -e 's,^\(\*\*\* Error code \)[1-9][0-9]*,\1<nonzero>,'
SED_CMDS.sh-errctl= ${STD_SED_CMDS.dj}
SED_CMDS.sh-flags= ${STD_SED_CMDS.hide-from-output}
SED_CMDS.shell-csh= ${STD_SED_CMDS.white-space}
SED_CMDS.suff-main+= ${STD_SED_CMDS.dg1}
SED_CMDS.suff-main-several+= ${STD_SED_CMDS.dg1}
SED_CMDS.suff-transform-debug+= ${STD_SED_CMDS.dg1}
SED_CMDS.var-op-shell+= ${STD_SED_CMDS.shell}
SED_CMDS.var-op-shell+= -e '/command/s,No such.*,not found,'
SED_CMDS.var-op-shell+= ${STD_SED_CMDS.white-space}
SED_CMDS.vardebug+= -e 's,${.SHELL},</path/to/shell>,'
SED_CMDS.varmod-subst-regex+= ${STD_SED_CMDS.regex}
SED_CMDS.varname-dot-parsedir= -e '/in some cases/ s,^make: "[^"]*,make: "<normalized>,'
@ -523,9 +562,7 @@ SED_CMDS.varname-dot-parsefile= -e '/in some cases/ s,^make: "[^"]*,make: "<norm
SED_CMDS.varname-dot-shell= -e 's, = /[^ ]*, = (details omitted),g'
SED_CMDS.varname-dot-shell+= -e 's,"/[^" ]*","(details omitted)",g'
SED_CMDS.varname-dot-shell+= -e 's,\[/[^] ]*\],[(details omitted)],g'
SED_CMDS.varname-empty= -e 's,${.CURDIR},<curdir>,g'
SED_CMDS.varname-empty+= -e '/\.PARSEDIR/d'
SED_CMDS.varname-empty+= -e '/\.SHELL/d'
SED_CMDS.varname-empty= ${.OBJDIR .PARSEDIR .PATH .SHELL:L:@v@-e '/\\$v/d'@}
# Some tests need an additional round of postprocessing.
POSTPROC.deptgt-suffixes= awk '/^\#\*\*\* Suffixes/,/^never-stop/'
@ -541,7 +578,7 @@ unexport-env.rawout: export.mk
# Some standard sed commands, to be used in the SED_CMDS above.
# Omit details such as process IDs from the output of the -dg1 option.
STD_SED_CMDS.dg1= -e 's,${.CURDIR}$$,<curdir>,'
STD_SED_CMDS.dg1= -e '/\#.* \.$$/d'
STD_SED_CMDS.dg1+= -e '/\.MAKE.PATH_FILEMON/d'
STD_SED_CMDS.dg1+= -e '/^MAKE_VERSION/d;/^\#.*\/mk/d'
STD_SED_CMDS.dg1+= -e 's, ${DEFSYSPATH:U/usr/share/mk}$$, <defsyspath>,'
@ -597,6 +634,8 @@ STD_SED_CMDS.shell+= -e 's,^${.SHELL:T}: line [0-9][0-9]*: ,,'
STD_SED_CMDS.shell+= -e 's,^${.SHELL:T}: [0-9][0-9]*: ,,'
STD_SED_CMDS.shell+= -e 's,^${.SHELL:T}: ,,'
STD_SED_CMDS.white-space= -e 's, *, ,g' -e 's, *$$,,'
# The actual error messages for a failed regcomp or regexec differ between the
# implementations.
STD_SED_CMDS.regex= \
@ -661,7 +700,8 @@ TMPDIR:= /tmp/uid${.MAKE.UID}
x!= echo; mkdir -p ${TMPDIR}
.endif
MAKE_TEST_ENV?= MALLOC_OPTIONS="JA" # for jemalloc
MAKE_TEST_ENV= MALLOC_OPTIONS="JA" # for jemalloc 100
MAKE_TEST_ENV+= MALLOC_CONF="junk:true" # for jemalloc 510
MAKE_TEST_ENV+= TMPDIR=${TMPDIR}
.if ${.MAKE.OS} == "NetBSD"
@ -697,13 +737,22 @@ _SED_CMDS+= -e 's,^usage: ${TEST_MAKE:T:S,.,\\.,g} ,usage: make ,'
# replace anything after 'stopped in' with unit-tests
_SED_CMDS+= -e '/stopped/s, /.*, unit-tests,'
_SED_CMDS+= -e 's,${TMPDIR},TMPDIR,g'
# strip ${.CURDIR}/ from the output
_SED_CMDS+= -e 's,${.CURDIR:S,.,\\.,g}/,,g'
# canonicalize ${.OBJDIR} and ${.CURDIR}
.if ${.OBJDIR} != ${.CURDIR}
# yes this is inaccurate but none of the tests expect <objdir> anywhere
# which we get depending on how MAKEOBJDIR is set.
_SED_CMDS+= -e 's,${.OBJDIR},<curdir>,g'
.endif
_SED_CMDS+= -e 's,${.CURDIR},<curdir>,g'
_SED_CMDS+= -e 's,<curdir>/,,g'
_SED_CMDS+= -e 's,${UNIT_TESTS:S,.,\\.,g}/,,g'
# on AT&T derrived systems; false exits 255 not 1
# on AT&T derived systems: false exits 255 not 1
.if ${.MAKE.OS:N*BSD} != ""
_SED_CMDS+= -e 's,\(Error code\) 255,\1 1,'
.endif
.if ${.SHELL:T} == "ksh"
_SED_CMDS+= -e '/^set [+-]v/d'
.endif
.rawout.out:
@${TOOL_SED} ${_SED_CMDS} ${SED_CMDS.${.PREFIX:T}} \

View File

@ -1,4 +1,6 @@
# $Id: Makefile.config.in,v 1.1 2018/12/30 17:14:24 sjg Exp $
# $Id: Makefile.config.in,v 1.3 2021/10/22 07:48:57 sjg Exp $
srcdir= @srcdir@
TOOL_DIFF?= @diff@
DIFF_FLAGS?= @diff_u@
UTC_1= @UTC_1@

View File

@ -6,6 +6,10 @@ CondParser_Eval: !(${:UNaN} == NaN)
lhs = "NaN", rhs = "NaN", op = ==
CondParser_Eval: 123 ! 123
make: "cond-cmp-numeric.mk" line 34: Malformed conditional (123 ! 123)
CondParser_Eval: ${:U 123} < 124
lhs = 123.000000, rhs = 124.000000, op = <
CondParser_Eval: ${:U123 } < 124
make: "cond-cmp-numeric.mk" line 50: String comparison operator must be either == or !=
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1

View File

@ -1,4 +1,4 @@
# $NetBSD: cond-cmp-numeric.mk,v 1.4 2020/11/08 22:56:16 rillig Exp $
# $NetBSD: cond-cmp-numeric.mk,v 1.5 2021/07/29 06:31:18 rillig Exp $
#
# Tests for numeric comparisons in .if conditions.
@ -37,5 +37,21 @@
. error
.endif
# Leading spaces are allowed for numbers.
# See EvalCompare and TryParseNumber.
.if ${:U 123} < 124
.else
. error
.endif
# Trailing spaces are NOT allowed for numbers.
# See EvalCompare and TryParseNumber.
# expect+1: String comparison operator must be either == or !=
.if ${:U123 } < 124
. error
.else
. error
.endif
all:
@:;

View File

@ -1,4 +1,4 @@
# $NetBSD: cond-cmp-string.mk,v 1.14 2021/01/19 19:54:57 rillig Exp $
# $NetBSD: cond-cmp-string.mk,v 1.15 2021/12/11 09:53:53 rillig Exp $
#
# Tests for string comparisons in .if conditions.
@ -26,7 +26,7 @@
# starting point for variable expressions. Applying the :U modifier to such
# an undefined expression turns it into a defined expression.
#
# See ApplyModifier_Defined and VEF_DEF.
# See ApplyModifier_Defined and DEF_DEFINED.
.if ${:Ustr} != "str"
. error
.endif

View File

@ -1,8 +1,5 @@
side effect
make: "cond-eof.mk" line 15: Malformed conditional (0 ${SIDE_EFFECT} ${SIDE_EFFECT2})
side effect
make: "cond-eof.mk" line 17: Malformed conditional (1 ${SIDE_EFFECT} ${SIDE_EFFECT2})
side effect
make: "cond-eof.mk" line 19: Malformed conditional ((0) ${SIDE_EFFECT} ${SIDE_EFFECT2})
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests

View File

@ -1,4 +1,4 @@
# $NetBSD: cond-eof.mk,v 1.2 2020/12/14 20:28:09 rillig Exp $
# $NetBSD: cond-eof.mk,v 1.3 2021/12/10 23:12:44 rillig Exp $
#
# Tests for parsing conditions, especially the end of such conditions, which
# are represented as the token TOK_EOF.
@ -7,11 +7,11 @@ SIDE_EFFECT= ${:!echo 'side effect' 1>&2!}
SIDE_EFFECT2= ${:!echo 'side effect 2' 1>&2!}
# In the following conditions, ${SIDE_EFFECT} is the position of the first
# parse error. It is always fully evaluated, even if it were not necessary
# to expand the variable expression. This is because these syntax errors are
# an edge case that does not occur during normal operation, therefore there
# is no need to optimize for this case, and it would slow down the common
# case as well.
# parse error. Before cond.c 1.286 from 2021-12-10, it was always fully
# evaluated, even if it was not necessary to expand the variable expression.
# These syntax errors are an edge case that does not occur during normal
# operation. Still, it is easy to avoid evaluating these expressions, just in
# case they have side effects.
.if 0 ${SIDE_EFFECT} ${SIDE_EFFECT2}
.endif
.if 1 ${SIDE_EFFECT} ${SIDE_EFFECT2}

View File

@ -1,4 +1,4 @@
# $NetBSD: cond-func-defined.mk,v 1.7 2020/11/15 14:07:53 rillig Exp $
# $NetBSD: cond-func-defined.mk,v 1.8 2021/12/12 08:55:28 rillig Exp $
#
# Tests for the defined() function in .if conditions.
@ -29,7 +29,7 @@ ${:UA B}= variable name with spaces
. error
.endif
# Parse error: missing closing parenthesis; see ParseFuncArg.
# Parse error: missing closing parenthesis; see ParseWord.
.if defined(DEF
. error
.else

View File

@ -1,5 +1,5 @@
make: "cond-func-empty.mk" line 152: Unclosed variable "WORD"
make: "cond-func-empty.mk" line 152: Malformed conditional (empty(WORD)
make: "cond-func-empty.mk" line 149: Unclosed variable "WORD"
make: "cond-func-empty.mk" line 149: Malformed conditional (empty(WORD)
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1

View File

@ -1,10 +1,10 @@
# $NetBSD: cond-func-empty.mk,v 1.14 2021/04/11 13:35:56 rillig Exp $
# $NetBSD: cond-func-empty.mk,v 1.16 2021/12/11 10:41:31 rillig Exp $
#
# Tests for the empty() function in .if conditions, which tests a variable
# expression for emptiness.
#
# Note that the argument in the parentheses is indeed a variable name,
# optionally followed by variable modifiers.
# Note that the argument in the parentheses is a variable name, not a variable
# expression, optionally followed by variable modifiers.
#
.undef UNDEF
@ -25,14 +25,10 @@ WORD= word
.endif
# The :S modifier replaces the empty value with an actual word. The
# expression is now no longer empty, but it is still possible to see whether
# the expression was based on an undefined variable. The expression has the
# flag VEF_UNDEF.
#
# The expression does not have the flag VEF_DEF though, therefore it is still
# considered undefined. Yes, indeed, undefined but not empty. There are a
# few variable modifiers that turn an undefined expression into a defined
# expression, among them :U and :D, but not :S.
# expression is now no longer empty, but it is still based on an undefined
# variable (DEF_UNDEF). There are a few variable modifiers that turn an
# undefined expression into a defined expression, among them :U and :D, but
# not :S.
#
# XXX: This is hard to explain to someone who doesn't know these
# implementation details.
@ -41,19 +37,19 @@ WORD= word
. error
.endif
# The :U modifier modifies expressions based on undefined variables
# (DEF_UNDEF) by adding the DEF_DEFINED flag, which marks the expression
# as "being interesting enough to be further processed".
# The :U modifier changes the state of a previously undefined expression from
# DEF_UNDEF to DEF_DEFINED. This marks the expression as "being interesting
# enough to be further processed".
#
.if empty(UNDEF:S,^$,value,W:Ufallback)
. error
.endif
# And now to the surprising part. Applying the following :S modifier to the
# undefined expression makes it non-empty, but the marker VEF_UNDEF is
# preserved nevertheless. The :U modifier that follows only looks at the
# VEF_UNDEF flag to decide whether the variable is defined or not. This kind
# of makes sense since the :U modifier tests the _variable_, not the
# undefined expression makes it non-empty, but the expression is still in
# state DEF_UNDEF. The :U modifier that follows only looks at the state
# DEF_UNDEF to decide whether the variable is defined or not. This kind of
# makes sense since the :U modifier tests the _variable_, not the
# _expression_.
#
# But since the variable was undefined to begin with, the fallback value from
@ -78,12 +74,13 @@ WORD= word
. error
.endif
# The empty variable named "" gets a fallback value of " ", which counts as
# empty.
# The following example constructs an expression with the variable name ""
# and the value " ". This expression counts as empty since the value contains
# only whitespace.
#
# Contrary to the other functions in conditionals, the trailing space is not
# stripped off, as can be seen in the -dv debug log. If the space had been
# stripped, it wouldn't make a difference in this case.
# stripped, it wouldn't make a difference in this case, but in other cases.
#
.if !empty(:U )
. error
@ -92,8 +89,8 @@ WORD= word
# Now the variable named " " gets a non-empty value, which demonstrates that
# neither leading nor trailing spaces are trimmed in the argument of the
# function. If the spaces were trimmed, the variable name would be "" and
# that variable is indeed undefined. Since ParseEmptyArg calls Var_Parse
# without VARE_UNDEFERR, the value of the undefined variable is
# that variable is indeed undefined. Since CondParser_FuncCallEmpty calls
# Var_Parse without VARE_UNDEFERR, the value of the undefined variable is
# returned as an empty string.
${:U }= space
.if empty( )
@ -129,8 +126,8 @@ ${:U }= space
#
# If everything goes well, the argument expands to "WORD", and that variable
# is defined at the beginning of this file. The surrounding 'W' and 'D'
# ensure that the parser in ParseEmptyArg has the correct position, both
# before and after the call to Var_Parse.
# ensure that CondParser_FuncCallEmpty keeps track of the parsing position,
# both before and after the call to Var_Parse.
.if empty(W${:UOR}D)
. error
.endif
@ -155,17 +152,29 @@ ${:U WORD }= variable name with spaces
. error
.endif
# Between 2020-06-28 and var.c 1.226 from 2020-07-02, this paragraph generated
# a wrong error message "Variable VARNAME is recursive".
# Since cond.c 1.76 from 2020-06-28 and before var.c 1.226 from 2020-07-02,
# the following example generated a wrong error message "Variable VARNAME is
# recursive".
#
# The bug was that the !empty() condition was evaluated, even though this was
# not necessary since the defined() condition already evaluated to false.
# Since at least 1993, the manual page claimed that irrelevant parts of
# conditions were not evaluated, but that was wrong for a long time. The
# expressions in irrelevant parts of the condition were actually evaluated,
# they just allowed undefined variables to be used in the conditions, and the
# result of evaluating them was not used further. These unnecessary
# evaluations were fixed in several commits, starting with var.c 1.226 from
# 2020-07-02.
#
# In this example, the variable "VARNAME2" is not defined, so evaluation of
# the condition should have stopped at this point, and the rest of the
# condition should have been processed in parse-only mode. The right-hand
# side containing the '!empty' was evaluated though, as it had always been.
#
# When evaluating the !empty condition, the variable name was parsed as
# "VARNAME${:U2}", but without expanding any nested variable expression, in
# this case the ${:U2}. Therefore, the variable name came out as simply
# "VARNAME". Since this variable name should have been discarded quickly after
# parsing it, this unrealistic variable name should have done no harm.
# this case the ${:U2}. The expression '${:U2}' was replaced with an empty
# string, the resulting variable name was thus "VARNAME". This conceptually
# wrong variable name should have been discarded quickly after parsing it, to
# prevent it from doing any harm.
#
# The variable expression was expanded though, and this was wrong. The
# expansion was done without VARE_WANTRES (called VARF_WANTRES back

View File

@ -6,7 +6,7 @@ make: "cond-func.mk" line 102: A plain function name is parsed as !empty(...).
make: "cond-func.mk" line 109: A plain function name is parsed as !empty(...).
make: "cond-func.mk" line 119: Symbols may start with a function name.
make: "cond-func.mk" line 124: Symbols may start with a function name.
make: "cond-func.mk" line 130: Malformed conditional (defined()
make: "cond-func.mk" line 130: Missing closing parenthesis for defined()
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1

View File

@ -1,4 +1,7 @@
make: "cond-op-and.mk" line 43: Malformed conditional (0 &&& 0)
make: "cond-op-and.mk" line 36: Malformed conditional (0 || (${DEF} && ${UNDEF}))
make: "cond-op-and.mk" line 40: Malformed conditional (0 || (${UNDEF} && ${UNDEF}))
make: "cond-op-and.mk" line 42: Malformed conditional (0 || (!${UNDEF} && ${UNDEF}))
make: "cond-op-and.mk" line 71: Malformed conditional (0 &&& 0)
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1

View File

@ -1,4 +1,4 @@
# $NetBSD: cond-op-and.mk,v 1.5 2020/10/24 08:46:08 rillig Exp $
# $NetBSD: cond-op-and.mk,v 1.6 2021/12/10 19:14:35 rillig Exp $
#
# Tests for the && operator in .if conditions.
@ -18,11 +18,39 @@
. error
.endif
# The right-hand side is not evaluated since the left-hand side is already
# false.
.if 0 && ${UNDEF}
.endif
# When an outer condition makes the inner '&&' condition irrelevant, neither
# of its operands must be evaluated.
#
.if 1 || (${UNDEF} && ${UNDEF})
.endif
# Test combinations of outer '||' with inner '&&', to ensure that the operands
# of the inner '&&' are only evaluated if necessary.
DEF= defined
.if 0 || (${DEF} && ${UNDEF})
.endif
.if 0 || (!${DEF} && ${UNDEF})
.endif
.if 0 || (${UNDEF} && ${UNDEF})
.endif
.if 0 || (!${UNDEF} && ${UNDEF})
.endif
.if 1 || (${DEF} && ${UNDEF})
.endif
.if 1 || (!${DEF} && ${UNDEF})
.endif
.if 1 || (${UNDEF} && ${UNDEF})
.endif
.if 1 || (!${UNDEF} && ${UNDEF})
.endif
# The && operator may be abbreviated as &. This is not widely known though
# and is also not documented in the manual page.

View File

@ -1,4 +1,7 @@
make: "cond-op-or.mk" line 43: Malformed conditional (0 ||| 0)
make: "cond-op-or.mk" line 46: Malformed conditional (1 && (!${DEF} || ${UNDEF}))
make: "cond-op-or.mk" line 48: Malformed conditional (1 && (${UNDEF} || ${UNDEF}))
make: "cond-op-or.mk" line 50: Malformed conditional (1 && (!${UNDEF} || ${UNDEF}))
make: "cond-op-or.mk" line 71: Malformed conditional (0 ||| 0)
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1

View File

@ -1,4 +1,4 @@
# $NetBSD: cond-op-or.mk,v 1.6 2020/10/24 08:46:08 rillig Exp $
# $NetBSD: cond-op-or.mk,v 1.8 2021/12/10 19:14:35 rillig Exp $
#
# Tests for the || operator in .if conditions.
@ -18,11 +18,39 @@
. error
.endif
# The right-hand side is not evaluated since the left-hand side is already
# true.
.if 1 || ${UNDEF}
.endif
# When an outer condition makes the inner '||' condition irrelevant, neither
# of its operands must be evaluated. This had been wrong in cond.c 1.283 from
# 2021-12-09 and was reverted in cond.c 1.284 an hour later.
.if 0 && (!defined(UNDEF) || ${UNDEF})
.endif
# Test combinations of outer '&&' with inner '||', to ensure that the operands
# of the inner '||' is only evaluated if necessary.
DEF= defined
.if 0 && (${DEF} || ${UNDEF})
.endif
.if 0 && (!${DEF} || ${UNDEF})
.endif
.if 0 && (${UNDEF} || ${UNDEF})
.endif
.if 0 && (!${UNDEF} || ${UNDEF})
.endif
.if 1 && (${DEF} || ${UNDEF})
.endif
.if 1 && (!${DEF} || ${UNDEF})
.endif
.if 1 && (${UNDEF} || ${UNDEF})
.endif
.if 1 && (!${UNDEF} || ${UNDEF})
.endif
# The || operator may be abbreviated as |. This is not widely known though
# and is also not documented in the manual page.

View File

@ -1,20 +1,22 @@
make: "cond-op.mk" line 50: Malformed conditional ("!word" == !word)
make: "cond-op.mk" line 75: Malformed conditional (0 ${ERR::=evaluated})
make: "cond-op.mk" line 79: After detecting a parse error, the rest is evaluated.
make: "cond-op.mk" line 83: Parsing continues until here.
make: "cond-op.mk" line 86: A B C => (A || B) && C A || B && C A || (B && C)
make: "cond-op.mk" line 93: 0 0 0 => 0 0 0
make: "cond-op.mk" line 93: 0 0 1 => 0 0 0
make: "cond-op.mk" line 93: 0 1 0 => 0 0 0
make: "cond-op.mk" line 93: 0 1 1 => 1 1 1
make: "cond-op.mk" line 93: 1 0 0 => 0 1 1
make: "cond-op.mk" line 93: 1 0 1 => 1 1 1
make: "cond-op.mk" line 93: 1 1 0 => 0 1 1
make: "cond-op.mk" line 93: 1 1 1 => 1 1 1
make: "cond-op.mk" line 104: Malformed conditional (1 &&)
make: "cond-op.mk" line 112: Malformed conditional (0 &&)
make: "cond-op.mk" line 120: Malformed conditional (1 ||)
make: "cond-op.mk" line 129: Malformed conditional (0 ||)
make: "cond-op.mk" line 76: Malformed conditional (0 ${ERR::=evaluated})
make: "cond-op.mk" line 80: A misplaced expression after 0 is not evaluated.
make: "cond-op.mk" line 84: Malformed conditional (1 ${ERR::=evaluated})
make: "cond-op.mk" line 88: A misplaced expression after 1 is not evaluated.
make: "cond-op.mk" line 92: Parsing continues until here.
make: "cond-op.mk" line 95: A B C => (A || B) && C A || B && C A || (B && C)
make: "cond-op.mk" line 102: 0 0 0 => 0 0 0
make: "cond-op.mk" line 102: 0 0 1 => 0 0 0
make: "cond-op.mk" line 102: 0 1 0 => 0 0 0
make: "cond-op.mk" line 102: 0 1 1 => 1 1 1
make: "cond-op.mk" line 102: 1 0 0 => 0 1 1
make: "cond-op.mk" line 102: 1 0 1 => 1 1 1
make: "cond-op.mk" line 102: 1 1 0 => 0 1 1
make: "cond-op.mk" line 102: 1 1 1 => 1 1 1
make: "cond-op.mk" line 113: Malformed conditional (1 &&)
make: "cond-op.mk" line 121: Malformed conditional (0 &&)
make: "cond-op.mk" line 129: Malformed conditional (1 ||)
make: "cond-op.mk" line 138: Malformed conditional (0 ||)
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1

View File

@ -1,4 +1,4 @@
# $NetBSD: cond-op.mk,v 1.13 2021/01/19 18:20:30 rillig Exp $
# $NetBSD: cond-op.mk,v 1.15 2021/12/10 23:12:44 rillig Exp $
#
# Tests for operators like &&, ||, ! in .if conditions.
#
@ -58,25 +58,34 @@
. error
.endif
# As soon as the parser sees the '$', it knows that the condition will
# be malformed. Therefore there is no point in evaluating it.
# In the following malformed conditions, as soon as the parser sees the '$'
# after the '0' or the '1', it knows that the condition will be malformed.
# Therefore there is no point in evaluating the misplaced expression.
#
# As of 2021-01-20, that part of the condition is evaluated nevertheless,
# since CondParser_Or just requests the next token, without restricting
# the token to the expected tokens. If the parser were to restrict the
# valid follow tokens for the token "0" to those that can actually produce
# a correct condition (which in this case would be comparison operators,
# TOK_AND, TOK_OR or TOK_RPAREN), the variable expression would not have
# to be evaluated.
# Before cond.c 1.286 from 2021-12-10, the extra expression was evaluated
# nevertheless, since CondParser_Or and CondParser_And asked for the expanded
# next token, even though in this position of the condition, only comparison
# operators, TOK_AND, TOK_OR or TOK_RPAREN are allowed.
#
# This would add a good deal of complexity to the code though, for almost
# no benefit, especially since most expressions and conditions are side
# effect free.
#
#
#
#
#
.undef ERR
.if 0 ${ERR::=evaluated}
. error
.endif
.if ${ERR:Uundefined} == evaluated
. info After detecting a parse error, the rest is evaluated.
.if ${ERR:Uundefined} == undefined
. info A misplaced expression after 0 is not evaluated.
.endif
.undef ERR
.if 1 ${ERR::=evaluated}
. error
.endif
.if ${ERR:Uundefined} == undefined
. info A misplaced expression after 1 is not evaluated.
.endif
# Just in case that parsing should ever stop on the first error.

View File

@ -1,4 +1,4 @@
# $NetBSD: cond-short.mk,v 1.16 2021/03/14 11:49:37 rillig Exp $
# $NetBSD: cond-short.mk,v 1.18 2021/12/12 09:49:09 rillig Exp $
#
# Demonstrates that in conditions, the right-hand side of an && or ||
# is only evaluated if it can actually influence the result.
@ -12,7 +12,20 @@
# possible to skip evaluation of irrelevant variable expressions and only
# parse them. They were still evaluated though, the only difference to
# relevant variable expressions was that in the irrelevant variable
# expressions, undefined variables were allowed.
# expressions, undefined variables were allowed. This allowed for conditions
# like 'defined(VAR) && ${VAR:S,from,to,} != ""', which no longer produced an
# error message 'Malformed conditional', but it still evaluated the
# expression, even though the expression was irrelevant.
#
# Since the initial commit on 1993-03-21, the manual page has been saying that
# make 'will only evaluate a conditional as far as is necessary to determine',
# but that was wrong. The code in cond.c 1.1 from 1993-03-21 looks good since
# it calls Var_Parse(condExpr, VAR_CMD, doEval,&varSpecLen,&doFree), but the
# definition of Var_Parse does not call the third parameter 'doEval', as would
# be expected, but instead 'err', accompanied by the comment 'TRUE if
# undefined variables are an error'. This subtle difference between 'do not
# evaluate at all' and 'allow undefined variables' led to the unexpected
# evaluation.
#
# See also:
# var-eval-short.mk, for short-circuited variable modifiers
@ -211,4 +224,56 @@ x!= echo '0 || $${iV2:U2} < $${V42}: $x' >&2; echo
. error
.endif
# Ensure that irrelevant conditions do not influence the result of the whole
# condition. As of cond.c 1.302 from 2021-12-11, an irrelevant function call
# evaluates to true (see CondParser_FuncCall and CondParser_FuncCallEmpty), an
# irrelevant comparison evaluates to false (see CondParser_Comparison).
#
# An irrelevant true bubbles up to the outermost CondParser_And, where it is
# ignored. An irrelevant false bubbles up to the outermost CondParser_Or,
# where it is ignored.
#
# If the condition parser should ever be restructured, the bubbling up of the
# irrelevant evaluation results might show up accidentally. Prevent this.
DEF= defined
.undef UNDEF
.if 0 && defined(DEF)
. error
.endif
.if 1 && defined(DEF)
.else
. error
.endif
.if 0 && defined(UNDEF)
. error
.endif
.if 1 && defined(UNDEF)
. error
.endif
.if 0 || defined(DEF)
.else
. error
.endif
.if 1 || defined(DEF)
.else
. error
.endif
.if 0 || defined(UNDEF)
. error
.endif
.if 1 || defined(UNDEF)
.else
. error
.endif
all:

View File

@ -27,28 +27,35 @@ lhs = "var&&name", rhs = "var&&name", op = !=
CondParser_Eval: ${:Uvar}||name != "var||name"
lhs = "var||name", rhs = "var||name", op = !=
CondParser_Eval: bare
make: "cond-token-plain.mk" line 102: A bare word is treated like defined(...), and the variable 'bare' is not defined.
make: "cond-token-plain.mk" line 106: A bare word is treated like defined(...), and the variable 'bare' is not defined.
CondParser_Eval: VAR
make: "cond-token-plain.mk" line 107: A bare word is treated like defined(...).
make: "cond-token-plain.mk" line 111: A bare word is treated like defined(...).
CondParser_Eval: V${:UA}R
make: "cond-token-plain.mk" line 114: ok
make: "cond-token-plain.mk" line 118: ok
CondParser_Eval: V${UNDEF}AR
make: "cond-token-plain.mk" line 122: Undefined variables in bare words expand to an empty string.
make: "cond-token-plain.mk" line 126: Undefined variables in bare words expand to an empty string.
CondParser_Eval: 0${:Ux00}
make: "cond-token-plain.mk" line 130: Numbers can be composed from literals and variable expressions.
CondParser_Eval: 0${:Ux01}
make: "cond-token-plain.mk" line 134: Numbers can be composed from literals and variable expressions.
CondParser_Eval: 0${:Ux01}
make: "cond-token-plain.mk" line 138: Numbers can be composed from literals and variable expressions.
CondParser_Eval: "" ==
make: "cond-token-plain.mk" line 140: Missing right-hand-side of operator '=='
make: "cond-token-plain.mk" line 144: Missing right-hand side of operator '=='
CondParser_Eval: == ""
make: "cond-token-plain.mk" line 148: Malformed conditional (== "")
make: "cond-token-plain.mk" line 152: Malformed conditional (== "")
CondParser_Eval: \\
make: "cond-token-plain.mk" line 163: The variable '\\' is not defined.
make: "cond-token-plain.mk" line 167: The variable '\\' is not defined.
CondParser_Eval: \\
make: "cond-token-plain.mk" line 168: Now the variable '\\' is defined.
make: "cond-token-plain.mk" line 172: Now the variable '\\' is defined.
CondParser_Eval: "unquoted\"quoted" != unquoted"quoted
lhs = "unquoted"quoted", rhs = "unquoted"quoted", op = !=
CondParser_Eval: $$$$$$$$ != ""
CondParser_Eval: left == right
make: "cond-token-plain.mk" line 195: Malformed conditional (left == right)
CondParser_Eval: ${0:?:} || left == right
CondParser_Eval: 0
make: "cond-token-plain.mk" line 201: Malformed conditional (${0:?:} || left == right)
CondParser_Eval: left == right || ${0:?:}
make: "cond-token-plain.mk" line 206: Malformed conditional (left == right || ${0:?:})
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1

View File

@ -1,17 +1,18 @@
# $NetBSD: cond-token-plain.mk,v 1.10 2021/01/21 14:08:09 rillig Exp $
# $NetBSD: cond-token-plain.mk,v 1.14 2021/12/12 09:36:00 rillig Exp $
#
# Tests for plain tokens (that is, string literals without quotes)
# in .if conditions.
# in .if conditions. These are also called bare words.
.MAKEFLAGS: -dc
# The word 'value' after the '!=' is a bare word.
.if ${:Uvalue} != value
. error
.endif
# Malformed condition since comment parsing is done in an early phase
# and removes the '#' and everything behind it long before the condition
# parser gets to see it.
# Using a '#' in a string literal in a condition leads to a malformed
# condition since comment parsing is done in an early phase and removes the
# '#' and everything after it long before the condition parser gets to see it.
#
# XXX: The error message is missing for this malformed condition.
# The right-hand side of the comparison is just a '"', before unescaping.
@ -32,7 +33,10 @@
# in a very early parsing phase.
#
# See https://gnats.netbsd.org/19596 for example makefiles demonstrating the
# original problems. This workaround is probably not needed anymore.
# original problems. At that time, the parser didn't recognize the comment in
# the line '.else # comment3'. This workaround is not needed anymore since
# comments are stripped in an earlier phase. See "case '#'" in
# CondParser_Token.
#
# XXX: Missing error message for the malformed condition. The right-hand
# side before unescaping is double-quotes, backslash, backslash.
@ -152,7 +156,7 @@ VAR= defined
.endif
# The '\\' is not a line continuation. Neither is it an unquoted string
# literal. Instead, it is parsed as a function argument (ParseFuncArg),
# literal. Instead, it is parsed as a bare word (ParseWord),
# and in that context, the backslash is just an ordinary character. The
# function argument thus stays '\\' (2 backslashes). This string is passed
# to FuncDefined, and since there is no variable named '\\', the condition
@ -185,6 +189,23 @@ ${:U\\\\}= backslash
. error
.endif
# In a condition in an .if directive, the left-hand side must not be an
# unquoted string literal.
# expect+1: Malformed conditional (left == right)
.if left == right
.endif
# Before cond.c 1.276 from 2021-09-21, a variable expression containing the
# modifier ':?:' allowed unquoted string literals for the rest of the
# condition. This was an unintended implementation mistake.
# expect+1: Malformed conditional (${0:?:} || left == right)
.if ${0:?:} || left == right
.endif
# This affected only the comparisons after the expression, so the following
# was still a syntax error.
# expect+1: Malformed conditional (left == right || ${0:?:})
.if left == right || ${0:?:}
.endif
# See cond-token-string.mk for similar tests where the condition is enclosed
# in "quotes".

View File

@ -1 +1,2 @@
Default command is making 'not-a-target' from 'not-a-target'.
exit status 0

View File

@ -1,8 +1,17 @@
# $NetBSD: deptgt-default.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $
# $NetBSD: deptgt-default.mk,v 1.3 2021/12/01 23:56:29 rillig Exp $
#
# Tests for the special target .DEFAULT in dependency declarations.
# Tests for the special target .DEFAULT in dependency declarations, which
# attaches its associated commands to all targets that don't specify any way
# to create them.
# TODO: Implementation
all: test-default not-a-target
test-default: .PHONY
has-commands: .PHONY
@echo 'Making ${.TARGET} from ${.IMPSRC}.'
.DEFAULT: dependency-is-ignored
@echo "Default command is making '${.TARGET}' from '${.IMPSRC}'."
all:
@:;

View File

@ -1,4 +1,4 @@
# $NetBSD: deptgt-makeflags.mk,v 1.6 2020/11/15 20:20:58 rillig Exp $
# $NetBSD: deptgt-makeflags.mk,v 1.7 2021/11/29 00:17:10 rillig Exp $
#
# Tests for the special target .MAKEFLAGS in dependency declarations,
# which adds command line options later, at parse time.
@ -65,7 +65,7 @@
.endif
# Next try at defining another newline variable. Since whitespace around the
# variable value is trimmed, two empty variable expressions surround the
# variable value is trimmed, two empty variable expressions ${:U} surround the
# literal newline now. This prevents the newline from being skipped during
# parsing. The ':=' assignment operator expands the empty variable
# expressions, leaving only the newline as the variable value.
@ -81,6 +81,31 @@
.endif
#.MAKEFLAGS: -d0
# Now do the same for the other escape sequences; see Substring_Words.
.MAKEFLAGS: CHAR_BS:="$${:U}\b$${:U}"
.MAKEFLAGS: CHAR_FF:="$${:U}\f$${:U}"
.MAKEFLAGS: CHAR_NL:="$${:U}\n$${:U}"
.MAKEFLAGS: CHAR_CR:="$${:U}\r$${:U}"
.MAKEFLAGS: CHAR_TAB:="$${:U}\t$${:U}"
# Note: backspace is not whitespace, it is a control character.
.if ${CHAR_BS:C,^[[:cntrl:]]$,found,W} != "found"
. error
.endif
.if ${CHAR_FF:C,^[[:space:]]$,found,W} != "found"
. error
.endif
.if ${CHAR_NL:C,^[[:space:]]$,found,W} != "found"
. error
.endif
.if ${CHAR_CR:C,^[[:space:]]$,found,W} != "found"
. error
.endif
.if ${CHAR_TAB:C,^[[:space:]]$,found,W} != "found"
. error
.endif
# Unbalanced quotes produce an error message. If they occur anywhere in the
# command line, the whole command line is skipped.
.MAKEFLAGS: VAR=previous

Some files were not shown because too many files have changed in this diff Show More