1
0
mirror of https://git.FreeBSD.org/src.git synced 2026-06-02 11:24:32 +00:00

Import bmake-20260313

Intersting/relevant changes since bmake-20251111

ChangeLog since bmake-20251111

2026-03-12  Simon J Gerraty  <sjg@beast.crufty.net>

	* VERSION (_MAKE_VERSION): 20260313
	Merge with NetBSD make, pick up
	o make: ensure .MAKE.SAVE_DOLLARS is initialized so makefiles like
	sys.vars.mk can test its value to know how to deal with macros
	that need to save '$' during ':='.

	* Makefile: default MAKE_SAVE_DOLLARS_DEFAULT to "no"
	for traditional behavior.

2026-03-10  Simon J Gerraty  <sjg@beast.crufty.net>

	* VERSION (_MAKE_VERSION): 20260310
	Merge with NetBSD make, pick up
	o unit-tests ensure TEST_MAKE is absolute path
	and tests that make symlink for ${MAKE} can run in parallel.

2026-03-03  Simon J Gerraty  <sjg@beast.crufty.net>

	* VERSION (_MAKE_VERSION): 20260303
	Merge with NetBSD make, pick up
	o job.c: MaybeSubMake: Look for expansion of ${.MAKE}
	and if necessary its basename, and only match if at start of line
	or preceded by space.

2026-02-28  Simon J Gerraty  <sjg@beast.crufty.net>

	* Makefile: mark ${PROG} and ${OBJS} as .META
	MaybeSubMake will otherwise mistake them for sub-makes

	* VERSION (_MAKE_VERSION): 20260301
	Merge with NetBSD make, pick up
	o job.c: MaybeSubMake: skip control chars [@+-] at start of line
	when checking for ${MAKE}

2026-02-22  Simon J Gerraty  <sjg@beast.crufty.net>

	* VERSION (_MAKE_VERSION): 20260222
	o mk file update

2026-02-16  Simon J Gerraty  <sjg@beast.crufty.net>

	* VERSION (_MAKE_VERSION): 20260216
	Merge with NetBSD make, pick up
	o minor cleanups

2026-02-10  Simon J Gerraty  <sjg@beast.crufty.net>

	* VERSION (_MAKE_VERSION): 20260210
	Merge with NetBSD make, pick up
	o document that multiple variables can be set on command line.
	o move MaybeSubMake to job.c so it can be called on expanded
	commands for more accuracy and less overhead.
	o main.c: set .MAKE.VERSION as read-only.

	* unit-tests/opt-{chdir,where-am-i}.mk: use MAKEOBJDIRPREFIX=/
	to avoid tripping over an unreadable /usr/obj

2026-02-04  Simon J Gerraty  <sjg@beast.crufty.net>

	* unit-tests/varname-make_stack_trace.mk: for
	FreeBSD and similar set .MAKE.ALWAYS_PASS_JOB_QUEUE=no
	to ensure we get the expected errors.

	* VERSION (_MAKE_VERSION): 20260202
	Merge with NetBSD make, pick up
	o on error avoid duplicate stack trace to stderr

2026-01-11  Simon J Gerraty  <sjg@beast.crufty.net>

	* VERSION (_MAKE_VERSION): 20260111
	Merge with NetBSD make, pick up
	o var.c: add explicit check for empty re as not all
	regex libs throw an error as expected, in this case.

2026-01-10  Simon J Gerraty  <sjg@beast.crufty.net>

	* VERSION (_MAKE_VERSION): 20260110
	Merge with NetBSD make, pick up
	o minor cleanups

mk/ChangeLog since bmake-20251111

2026-03-12  Simon J Gerraty  <sjg@beast.crufty.net>

	* install-mk (MK_VERSION): 20260313

	* sys.vars.mk: use .MAKE.VERSION
	M_type can simply use '$x'

2026-02-22  Simon J Gerraty  <sjg@beast.crufty.net>

	* install-mk (MK_VERSION): 20260222

	* dirdeps.mk, sys.mk: add dependent option
	UPDATE_DIRDEPS_CACHE/DIRDEPS_CACHE.
	It can be useful to use -DWITHOUT_UPDATE_DIRDEPS_CACHE to
	temporarily treat dynamic DIRDEPS_CACHE as static.

2026-01-10  Simon J Gerraty  <sjg@beast.crufty.net>

	* meta.autodep.mk (${_DEPENDFILE}): add .NOMETA

2026-01-08  Simon J Gerraty  <sjg@beast.crufty.net>

	* rust.mk: better accommodation for RUST_LIBS.
	Set RUST_{LIBS,PROGS}_CARGO_BUILD_OUTPUT_LIST to
	simplify staging.

2025-12-08  Simon J Gerraty  <sjg@beast.crufty.net>

	* install-mk (MK_VERSION): 20251207

	* sys.vars.mk: replace MAKE_POSIX_SHELL usage with isPOSIX_SHELL
	Using ${isPOSIX_SHELL:U:Nfalse} provides a boolean for make
	and ${isPOSIX_SHELL:Ufalse} does the same for target scripts.
	Both will be false if isPOSIX_SHELL is not set or set to false.

	This has the advantage that if only POSIX shells are expected
	sys.mk (or something it includes) can simply do isPOSIX_SHELL?=:
This commit is contained in:
Simon J. Gerraty
2026-04-06 11:25:05 -07:00
parent 638c66de4a
commit fe271bdb43
74 changed files with 958 additions and 603 deletions
+82
View File
@@ -1,3 +1,85 @@
2026-03-12 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20260313
Merge with NetBSD make, pick up
o make: ensure .MAKE.SAVE_DOLLARS is initialized so makefiles like
sys.vars.mk can test its value to know how to deal with macros
that need to save '$' during ':='.
* Makefile: default MAKE_SAVE_DOLLARS_DEFAULT to "no"
for traditional behavior.
2026-03-10 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20260310
Merge with NetBSD make, pick up
o unit-tests ensure TEST_MAKE is absolute path
and tests that make symlink for ${MAKE} can run in parallel.
2026-03-03 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20260303
Merge with NetBSD make, pick up
o job.c: MaybeSubMake: Look for expansion of ${.MAKE}
and if necessary its basename, and only match if at start of line
or preceded by space.
2026-02-28 Simon J Gerraty <sjg@beast.crufty.net>
* Makefile: mark ${PROG} and ${OBJS} as .META
MaybeSubMake will otherwise mistake them for sub-makes
* VERSION (_MAKE_VERSION): 20260301
Merge with NetBSD make, pick up
o job.c: MaybeSubMake: skip control chars [@+-] at start of line
when checking for ${MAKE}
2026-02-22 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20260222
o mk file update
2026-02-16 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20260216
Merge with NetBSD make, pick up
o minor cleanups
2026-02-10 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20260210
Merge with NetBSD make, pick up
o document that multiple variables can be set on command line.
o move MaybeSubMake to job.c so it can be called on expanded
commands for more accuracy and less overhead.
o main.c: set .MAKE.VERSION as read-only.
* unit-tests/opt-{chdir,where-am-i}.mk: use MAKEOBJDIRPREFIX=/
to avoid tripping over an unreadable /usr/obj
2026-02-04 Simon J Gerraty <sjg@beast.crufty.net>
* unit-tests/varname-make_stack_trace.mk: for
FreeBSD and similar set .MAKE.ALWAYS_PASS_JOB_QUEUE=no
to ensure we get the expected errors.
* VERSION (_MAKE_VERSION): 20260202
Merge with NetBSD make, pick up
o on error avoid duplicate stack trace to stderr
2026-01-11 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20260111
Merge with NetBSD make, pick up
o var.c: add explicit check for empty re as not all
regex libs throw an error as expected, in this case.
2026-01-10 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20260110
Merge with NetBSD make, pick up
o minor cleanups
2025-11-15 Simon J Gerraty <sjg@beast.crufty.net>
* boot-strap: unset more things from env and save a copy
+2 -2
View File
@@ -2,11 +2,11 @@ The individual files in this distribution are copyright their
original contributors or assignees.
Including:
Copyright (c) 1993-2025, Simon J Gerraty
Copyright (c) 1993-2026, Simon J Gerraty
Copyright (c) 2020-2021, Roland Illig <rillig@NetBSD.org>
Copyright (c) 2009-2016, Juniper Networks, Inc.
Copyright (c) 2009, John Birrell.
Copyright (c) 1997-2025 The NetBSD Foundation, Inc.
Copyright (c) 1997-2026 The NetBSD Foundation, Inc.
Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
Copyright (c) 1989 by Berkeley Softworks
Copyright (c) 1988, 1989, 1990, 1992, 1993
+13 -6
View File
@@ -1,4 +1,4 @@
# $Id: Makefile,v 1.133 2025/03/08 20:12:56 sjg Exp $
# $Id: Makefile,v 1.137 2026/03/13 15:37:22 sjg Exp $
PROG = bmake
@@ -27,9 +27,6 @@ SRCS = \
.MAIN: all
MAN = ${PROG}.1
SRCS.${MAN} = ${srcdir}/make.1
.-include "VERSION"
.-include "Makefile.inc"
@@ -45,6 +42,9 @@ prefix ?= /usr
srcdir ?= ${.PARSEDIR}
srcdir := ${srcdir}
MAN ?= ${PROG}.1
SRCS.${MAN} ?= ${srcdir}/make.1
DEFAULT_SYS_PATH ?= ${prefix}/share/mk
CPPFLAGS += -DUSE_META
@@ -54,7 +54,13 @@ CFLAGS += -I. -I${srcdir} ${XDEFS} -DMAKE_NATIVE
CFLAGS += ${COPTS.${.ALLSRC:M*.c:T:u}}
COPTS.main.c += "-DMAKE_VERSION=\"${_MAKE_VERSION}\""
.for x in FORCE_MAKE_OS FORCE_MACHINE FORCE_MACHINE_ARCH
# bmake defaults to the traditional behavior
MAKE_SAVE_DOLLARS_DEFAULT ?= no
VARS.main += FORCE_MAKE_OS FORCE_MACHINE FORCE_MACHINE_ARCH \
MAKE_SAVE_DOLLARS_DEFAULT \
.for x in ${VARS.main}
.ifdef $x
COPTS.main.c += "-D$x=\"${$x}\""
.endif
@@ -206,7 +212,8 @@ SHAREDIR = ${SHAREDIR.bmake:U${prefix}/share}
BINDIR = ${BINDIR.bmake:U${prefix}/bin}
MANDIR = ${MANDIR.bmake:U${SHAREDIR}/man}
${OBJS}: config.h
${OBJS}: .META config.h
${PROG}: .META
# start-delete2 for bsd.after-import.mk
+1 -1
View File
@@ -1,2 +1,2 @@
# keep this compatible with sh and make
_MAKE_VERSION=20251111
_MAKE_VERSION=20260313
+46 -59
View File
@@ -1,4 +1,4 @@
.\" $NetBSD: make.1,v 1.388 2025/11/12 22:14:07 sjg Exp $
.\" $NetBSD: make.1,v 1.390 2026/02/08 11:02:03 rillig 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 November 11, 2025
.Dd February 8, 2026
.Dt BMAKE 1
.Os
.Sh NAME
@@ -49,7 +49,7 @@
.Op Fl T Ar file
.Op Fl V Ar variable
.Op Fl v Ar variable
.Op Ar variable\| Ns Cm \&= Ns Ar value
.Op Ar variable\| Ns Cm \&= Ns Ar value No ...
.Op Ar target No ...
.Sh DESCRIPTION
.Nm
@@ -1655,33 +1655,22 @@ Causes the value to be treated as a list of words.
See also
.Sq Cm \&:[@] .
.Sm off
.It Cm \&:S\| No \&/ Ar old_string\| No \&/ Ar new_string\| No \&/ Op Cm 1gW
.It Cm \&:S\| No \&/ Oo Cm \&^ Oc Ar old_string\| No Oo Cm \&$ Oc \&/ Ar new_string\| No \&/ Op Cm 1gW
.Sm on
Modifies the first occurrence of
.Ar old_string
in each word of the value, replacing it with
.Ar new_string .
If a
.Ql g
is appended to the last delimiter of the pattern,
all occurrences in each word are replaced.
If a
.Ql 1
is appended to the last delimiter of the pattern,
only the first occurrence is affected.
If a
.Ql W
is appended to the last delimiter of the pattern,
the value is treated as a single word.
.Pp
If
.Ar old_string
begins with a caret
is preceded by a caret
.Pq Ql ^ ,
.Ar old_string
is anchored at the beginning of each word.
If
.Ar old_string
ends with a dollar sign
is followed by a dollar sign
.Pq Ql \&$ ,
it is anchored at the end of each word.
Inside
@@ -1689,63 +1678,61 @@ Inside
an ampersand
.Pq Ql &
is replaced by
.Ar old_string
(without the anchoring
.Ql ^
or
.Ql \&$ ) .
Any character may be used as the delimiter for the parts of the modifier
string.
The anchoring, ampersand and delimiter characters can be escaped with a
backslash
.Pq Ql \e .
.Pp
.Ar old_string .
Both
.Ar old_string
and
.Ar new_string
may contain nested expressions.
To prevent a dollar sign from starting a nested expression,
escape it with a backslash.
.Pp
Further options:
.Bl -tag
.It Cm 1
Only the word of the first occurrence is affected.
.It Cm g
All occurrences in each affected word are replaced.
.It Cm W
The expression value is treated as a single word.
.El
.Pp
Any character may be used as the delimiter for the parts of the modifier
string.
The anchoring, ampersand, dollar and delimiter characters
can be escaped with a backslash
.Pq Ql \e .
.Sm off
.It Cm \&:C\| No \&/ Ar pattern\| No \&/ Ar replacement\| No \&/ Op Cm 1gW
.Sm on
The
.Cm \&:C
modifier works like the
.Cm \&:S
modifier except that the old and new strings, instead of being
simple strings, are an extended regular expression
Modifies the first occurrence of the extended regular expression
.Ar pattern
(see
.Xr regex 3 )
and an
in each word of the value, replacing it with
an
.Xr ed 1 Ns \-style
.Ar replacement .
Normally, the first occurrence of the pattern
.Ar pattern
in each word of the value is substituted with
.Ar replacement .
The
.Ql 1
modifier causes the substitution to apply to at most one word; the
.Ql g
modifier causes the substitution to apply to as many instances of the
search pattern
.Ar pattern
as occur in the word or words it is found in; the
.Ql W
modifier causes the value to be treated as a single word
(possibly containing embedded whitespace).
.Pp
As for the
.Cm \&:S
modifier, the
Both
.Ar pattern
and
.Ar replacement
are subjected to variable expansion before being parsed as
regular expressions.
may contain nested expressions.
.Pp
Further options:
.Bl -tag
.It Cm 1
Only the word of the first occurrence is affected.
.It Cm g
All occurrences in each affected word are replaced.
.It Cm W
The expression value is treated as a single word.
.El
.Pp
Any character may be used as the delimiter for the parts of the modifier
string.
The anchoring, ampersand, dollar and delimiter characters
can be escaped with a backslash
.Pq Ql \e .
.It Cm \&:T
Replaces each word with its last path component (basename).
.It Cm \&:u
@@ -2494,7 +2481,7 @@ Any command lines attached to this target are executed after everything
else is done successfully.
.It Ic .ERROR
Any command lines attached to this target are executed when another target fails.
See
See
.Va MAKE_PRINT_VAR_ON_ERROR
for the variables that will be set.
.It Ic .IGNORE
+37 -31
View File
@@ -7,7 +7,7 @@ SSYYNNOOPPSSIISS
bbmmaakkee [--BBeeiikkNNnnqqrrSSssttWWwwXX] [--CC _d_i_r_e_c_t_o_r_y] [--DD _v_a_r_i_a_b_l_e] [--dd _f_l_a_g_s]
[--ff _m_a_k_e_f_i_l_e] [--II _d_i_r_e_c_t_o_r_y] [--JJ _p_r_i_v_a_t_e] [--jj _m_a_x___j_o_b_s]
[--mm _d_i_r_e_c_t_o_r_y] [--TT _f_i_l_e] [--VV _v_a_r_i_a_b_l_e] [--vv _v_a_r_i_a_b_l_e]
[_v_a_r_i_a_b_l_e==_v_a_l_u_e] [_t_a_r_g_e_t ...]
[_v_a_r_i_a_b_l_e==_v_a_l_u_e ...] [_t_a_r_g_e_t ...]
DDEESSCCRRIIPPTTIIOONN
bbmmaakkee is a program designed to simplify the maintenance of other
@@ -1073,40 +1073,46 @@ VVAARRIIAABBLLEE AASSSSIIGGNNMMEENNTTSS
::ttww Causes the value to be treated as a list of words. See also `::[[@@]]'.
::SS/_o_l_d___s_t_r_i_n_g/_n_e_w___s_t_r_i_n_g/[11ggWW]
::SS/[^^]_o_l_d___s_t_r_i_n_g[$$]/_n_e_w___s_t_r_i_n_g/[11ggWW]
Modifies the first occurrence of _o_l_d___s_t_r_i_n_g in each word of the
value, replacing it with _n_e_w___s_t_r_i_n_g. If a `g' is appended to the
last delimiter of the pattern, all occurrences in each word are
replaced. If a `1' is appended to the last delimiter of the
pattern, only the first occurrence is affected. If a `W' is
appended to the last delimiter of the pattern, the value is treated
as a single word. If _o_l_d___s_t_r_i_n_g begins with a caret (`^'),
_o_l_d___s_t_r_i_n_g is anchored at the beginning of each word. If _o_l_d___s_t_r_i_n_g
ends with a dollar sign (`$'), it is anchored at the end of each
word. Inside _n_e_w___s_t_r_i_n_g, an ampersand (`&') is replaced by
_o_l_d___s_t_r_i_n_g (without the anchoring `^' or `$'). Any character may be
used as the delimiter for the parts of the modifier string. The
anchoring, ampersand and delimiter characters can be escaped with a
backslash (`\').
value, replacing it with _n_e_w___s_t_r_i_n_g.
Both _o_l_d___s_t_r_i_n_g and _n_e_w___s_t_r_i_n_g may contain nested expressions. To
prevent a dollar sign from starting a nested expression, escape it
with a backslash.
If _o_l_d___s_t_r_i_n_g is preceded by a caret (`^'), _o_l_d___s_t_r_i_n_g is anchored
at the beginning of each word. If _o_l_d___s_t_r_i_n_g is followed by a
dollar sign (`$'), it is anchored at the end of each word. Inside
_n_e_w___s_t_r_i_n_g, an ampersand (`&') is replaced by _o_l_d___s_t_r_i_n_g. Both
_o_l_d___s_t_r_i_n_g and _n_e_w___s_t_r_i_n_g may contain nested expressions.
Further options:
11 Only the word of the first occurrence is affected.
gg All occurrences in each affected word are replaced.
WW The expression value is treated as a single word.
Any character may be used as the delimiter for the parts of the
modifier string. The anchoring, ampersand, dollar and delimiter
characters can be escaped with a backslash (`\').
::CC/_p_a_t_t_e_r_n/_r_e_p_l_a_c_e_m_e_n_t/[11ggWW]
The ::CC modifier works like the ::SS modifier except that the old and
new strings, instead of being simple strings, are an extended
regular expression _p_a_t_t_e_r_n (see regex(3)) and an ed(1)-style
_r_e_p_l_a_c_e_m_e_n_t. Normally, the first occurrence of the pattern _p_a_t_t_e_r_n
in each word of the value is substituted with _r_e_p_l_a_c_e_m_e_n_t. The `1'
modifier causes the substitution to apply to at most one word; the
`g' modifier causes the substitution to apply to as many instances
of the search pattern _p_a_t_t_e_r_n as occur in the word or words it is
found in; the `W' modifier causes the value to be treated as a
single word (possibly containing embedded whitespace).
Modifies the first occurrence of the extended regular expression
_p_a_t_t_e_r_n (see regex(3)) in each word of the value, replacing it with
an ed(1)-style _r_e_p_l_a_c_e_m_e_n_t.
As for the ::SS modifier, the _p_a_t_t_e_r_n and _r_e_p_l_a_c_e_m_e_n_t are subjected to
variable expansion before being parsed as regular expressions.
Both _p_a_t_t_e_r_n and _r_e_p_l_a_c_e_m_e_n_t may contain nested expressions.
Further options:
11 Only the word of the first occurrence is affected.
gg All occurrences in each affected word are replaced.
WW The expression value is treated as a single word.
Any character may be used as the delimiter for the parts of the
modifier string. The anchoring, ampersand, dollar and delimiter
characters can be escaped with a backslash (`\').
::TT Replaces each word with its last path component (basename).
@@ -1874,4 +1880,4 @@ BBUUGGSS
attempt to suppress a cascade of unnecessary errors, can result in a
seemingly unexplained `*** Error code 6'
FreeBSD 14.3-RELEASE-p3 November 11, 2025 FreeBSD 14.3-RELEASE-p3
FreeBSD 14.3-RELEASE-p9 February 8, 2026 FreeBSD 14.3-RELEASE-p9

Before

Width:  |  Height:  |  Size: 95 KiB

After

Width:  |  Height:  |  Size: 94 KiB

+57 -2
View File
@@ -1,4 +1,4 @@
/* $NetBSD: job.c,v 1.519 2025/08/04 15:40:39 sjg Exp $ */
/* $NetBSD: job.c,v 1.528 2026/03/03 20:12:20 sjg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -137,7 +137,7 @@
#include "trace.h"
/* "@(#)job.c 8.2 (Berkeley) 3/19/94" */
MAKE_RCSID("$NetBSD: job.c,v 1.519 2025/08/04 15:40:39 sjg Exp $");
MAKE_RCSID("$NetBSD: job.c,v 1.528 2026/03/03 20:12:20 sjg Exp $");
#ifdef USE_SELECT
@@ -971,6 +971,54 @@ JobWriteSpecials(Job *job, ShellWriter *wr, const char *escCmd, bool run,
inout_cmdFlags->ignerr = false;
}
static bool
find_make(const char *cmd, const char *make, size_t len)
{
const char *p;
for (p = strstr(cmd, make); p != NULL; p = strstr(&p[1], make)) {
if (p == cmd || ch_isspace(p[-1])) {
if (p[len] == '\0' || ch_isspace(p[len])) {
DEBUG4(JOB, "find_make: matched \"%.*s\" in \"%.*s...\"\n",
(int)len, p,
(int)len + 32, cmd);
return true;
}
}
}
return false;
}
/*
* See if the command possibly calls a sub-make by checking
* for expansion of ${.MAKE} and possibly ${.MAKE:T}.
*/
bool
MaybeSubMake(const char *cmd)
{
static char *make, *make_name;
static size_t make_len, make_name_len;
if (make == NULL) {
make = Var_Subst("${.MAKE}", SCOPE_GLOBAL, VARE_EVAL);
make_len = strlen(make);
make_name = strrchr(make, '/');
if (make_name != NULL) {
make_name++;
make_name_len = strlen(make_name);
} else
make_name_len = 0;
DEBUG1(JOB, "MaybeSubMake: Looking for \"%s\"\n", make);
}
cmd += strspn(cmd, "@ \t+-");
if (find_make(cmd, make, make_len))
return true;
if (make_name_len > 0 && find_make(cmd, make_name, make_name_len))
return true;
return false;
}
/*
* Write a shell command to the job's commands file, to be run later.
*
@@ -1004,6 +1052,12 @@ JobWriteCommand(Job *job, ShellWriter *wr, StringListNode *ln, const char *ucmd)
/* TODO: handle errors */
xcmdStart = xcmd;
if (job->node->flags.doneSubmake == false
&& (job->node->type & (OP_MAKE | OP_SUBMAKE)) == 0) {
if (MaybeSubMake(xcmd))
job->node->type |= OP_SUBMAKE;
}
cmdTemplate = "%s\n";
ParseCommandFlags(&xcmd, &cmdFlags);
@@ -1106,6 +1160,7 @@ JobWriteCommands(Job *job)
JobWriteCommand(job, &wr, ln, ln->datum);
seen = true;
}
job->node->flags.doneSubmake = true;
return seen;
}
+2 -1
View File
@@ -1,4 +1,4 @@
/* $NetBSD: job.h,v 1.85 2025/07/06 07:11:31 rillig Exp $ */
/* $NetBSD: job.h,v 1.86 2026/02/10 18:53:34 sjg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -93,6 +93,7 @@ void TokenPool_Init(int, int, int);
bool TokenPool_Take(void) MAKE_ATTR_USE;
void TokenPool_Return(void);
bool MaybeSubMake(const char *);
void Job_Touch(GNode *, bool);
bool Job_CheckCommands(GNode *, void (*abortProc)(const char *, ...))
MAKE_ATTR_USE;
+13 -8
View File
@@ -1,4 +1,4 @@
/* $NetBSD: main.c,v 1.662 2025/08/09 23:13:28 rillig Exp $ */
/* $NetBSD: main.c,v 1.668 2026/03/13 04:22:03 sjg 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.662 2025/08/09 23:13:28 rillig Exp $");
MAKE_RCSID("$NetBSD: main.c,v 1.668 2026/03/13 04:22:03 sjg Exp $");
#if defined(MAKE_NATIVE)
__COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993 "
"The Regents of the University of California. "
@@ -186,8 +186,9 @@ usage(void)
(void)fprintf(stderr,
"usage: %.*s [-BeikNnqrSstWwX]\n"
" [-C directory] [-D variable] [-d flags] [-f makefile]\n"
" [-I directory] [-J private] [-j max_jobs] [-m directory] [-T file]\n"
" [-V variable] [-v variable] [variable=value] [target ...]\n",
" [-I directory] [-J private] [-j max_jobs] [-m directory]\n"
" [-T file] [-V variable] [-v variable]\n"
" [variable=value ...] [target ...]\n",
(int)prognameLen, progname);
exit(2);
}
@@ -464,8 +465,6 @@ static bool
MainParseOption(char c, const char *argvalue)
{
switch (c) {
case '\0':
break;
case 'B':
opts.compatMake = true;
Global_Append(MAKEFLAGS, "-B");
@@ -1224,7 +1223,6 @@ InitMaxJobs(void)
"Invalid internal option \"-J\" in \"%s\"; "
"see the manual page",
curdir);
PrintStackTrace(true);
return;
}
if (forceJobs || opts.compatMake ||
@@ -1316,6 +1314,10 @@ ReadFirstDefaultMakefile(void)
free(prefs);
}
#ifndef MAKE_SAVE_DOLLARS_DEFAULT
# define MAKE_SAVE_DOLLARS_DEFAULT "yes"
#endif
/*
* Initialize variables such as MAKE, MACHINE, .MAKEFLAGS.
* Initialize a few modules.
@@ -1367,6 +1369,8 @@ main_Init(int argc, char **argv)
Global_Set("MACHINE", machine);
Global_Set("MACHINE_ARCH", machine_arch);
#ifdef MAKE_VERSION
Global_Set_ReadOnly(".MAKE.VERSION", MAKE_VERSION);
/* for backwards compatibility */
Global_Set("MAKE_VERSION", MAKE_VERSION);
#endif
Global_Set_ReadOnly(".newline", "\n");
@@ -1382,6 +1386,7 @@ main_Init(int argc, char **argv)
#else
Global_Set_ReadOnly(".MAKE.JOBS.C", "no");
#endif
Global_Set(MAKE_SAVE_DOLLARS, MAKE_SAVE_DOLLARS_DEFAULT);
CmdOpts_Init();
allPrecious = false; /* Remove targets when interrupted */
@@ -1909,7 +1914,7 @@ Fatal(const char *fmt, ...)
va_end(ap);
(void)fprintf(stderr, "\n");
(void)fflush(stderr);
PrintStackTrace(true);
PrintStackTrace(stderr, true);
PrintOnError(NULL, "\n");
+46 -59
View File
@@ -1,4 +1,4 @@
.\" $NetBSD: make.1,v 1.388 2025/11/12 22:14:07 sjg Exp $
.\" $NetBSD: make.1,v 1.390 2026/02/08 11:02:03 rillig 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 November 11, 2025
.Dd February 8, 2026
.Dt MAKE 1
.Os
.Sh NAME
@@ -49,7 +49,7 @@
.Op Fl T Ar file
.Op Fl V Ar variable
.Op Fl v Ar variable
.Op Ar variable\| Ns Cm \&= Ns Ar value
.Op Ar variable\| Ns Cm \&= Ns Ar value No ...
.Op Ar target No ...
.Sh DESCRIPTION
.Nm
@@ -1655,33 +1655,22 @@ Causes the value to be treated as a list of words.
See also
.Sq Cm \&:[@] .
.Sm off
.It Cm \&:S\| No \&/ Ar old_string\| No \&/ Ar new_string\| No \&/ Op Cm 1gW
.It Cm \&:S\| No \&/ Oo Cm \&^ Oc Ar old_string\| No Oo Cm \&$ Oc \&/ Ar new_string\| No \&/ Op Cm 1gW
.Sm on
Modifies the first occurrence of
.Ar old_string
in each word of the value, replacing it with
.Ar new_string .
If a
.Ql g
is appended to the last delimiter of the pattern,
all occurrences in each word are replaced.
If a
.Ql 1
is appended to the last delimiter of the pattern,
only the first occurrence is affected.
If a
.Ql W
is appended to the last delimiter of the pattern,
the value is treated as a single word.
.Pp
If
.Ar old_string
begins with a caret
is preceded by a caret
.Pq Ql ^ ,
.Ar old_string
is anchored at the beginning of each word.
If
.Ar old_string
ends with a dollar sign
is followed by a dollar sign
.Pq Ql \&$ ,
it is anchored at the end of each word.
Inside
@@ -1689,63 +1678,61 @@ Inside
an ampersand
.Pq Ql &
is replaced by
.Ar old_string
(without the anchoring
.Ql ^
or
.Ql \&$ ) .
Any character may be used as the delimiter for the parts of the modifier
string.
The anchoring, ampersand and delimiter characters can be escaped with a
backslash
.Pq Ql \e .
.Pp
.Ar old_string .
Both
.Ar old_string
and
.Ar new_string
may contain nested expressions.
To prevent a dollar sign from starting a nested expression,
escape it with a backslash.
.Pp
Further options:
.Bl -tag
.It Cm 1
Only the word of the first occurrence is affected.
.It Cm g
All occurrences in each affected word are replaced.
.It Cm W
The expression value is treated as a single word.
.El
.Pp
Any character may be used as the delimiter for the parts of the modifier
string.
The anchoring, ampersand, dollar and delimiter characters
can be escaped with a backslash
.Pq Ql \e .
.Sm off
.It Cm \&:C\| No \&/ Ar pattern\| No \&/ Ar replacement\| No \&/ Op Cm 1gW
.Sm on
The
.Cm \&:C
modifier works like the
.Cm \&:S
modifier except that the old and new strings, instead of being
simple strings, are an extended regular expression
Modifies the first occurrence of the extended regular expression
.Ar pattern
(see
.Xr regex 3 )
and an
in each word of the value, replacing it with
an
.Xr ed 1 Ns \-style
.Ar replacement .
Normally, the first occurrence of the pattern
.Ar pattern
in each word of the value is substituted with
.Ar replacement .
The
.Ql 1
modifier causes the substitution to apply to at most one word; the
.Ql g
modifier causes the substitution to apply to as many instances of the
search pattern
.Ar pattern
as occur in the word or words it is found in; the
.Ql W
modifier causes the value to be treated as a single word
(possibly containing embedded whitespace).
.Pp
As for the
.Cm \&:S
modifier, the
Both
.Ar pattern
and
.Ar replacement
are subjected to variable expansion before being parsed as
regular expressions.
may contain nested expressions.
.Pp
Further options:
.Bl -tag
.It Cm 1
Only the word of the first occurrence is affected.
.It Cm g
All occurrences in each affected word are replaced.
.It Cm W
The expression value is treated as a single word.
.El
.Pp
Any character may be used as the delimiter for the parts of the modifier
string.
The anchoring, ampersand, dollar and delimiter characters
can be escaped with a backslash
.Pq Ql \e .
.It Cm \&:T
Replaces each word with its last path component (basename).
.It Cm \&:u
@@ -2494,7 +2481,7 @@ Any command lines attached to this target are executed after everything
else is done successfully.
.It Ic .ERROR
Any command lines attached to this target are executed when another target fails.
See
See
.Va MAKE_PRINT_VAR_ON_ERROR
for the variables that will be set.
.It Ic .IGNORE
+3 -2
View File
@@ -1,4 +1,4 @@
/* $NetBSD: make.c,v 1.273 2025/07/06 07:11:31 rillig Exp $ */
/* $NetBSD: make.c,v 1.274 2026/02/10 18:53:34 sjg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -107,7 +107,7 @@
#endif
/* "@(#)make.c 8.1 (Berkeley) 6/6/93" */
MAKE_RCSID("$NetBSD: make.c,v 1.273 2025/07/06 07:11:31 rillig Exp $");
MAKE_RCSID("$NetBSD: make.c,v 1.274 2026/02/10 18:53:34 sjg Exp $");
/* Sequence # to detect recursion. */
static unsigned checked_seqno = 1;
@@ -187,6 +187,7 @@ GNodeFlags_ToString(GNodeFlags flags)
Buf_AddFlag(&buf, flags.doneOrder, "DONE_ORDER");
Buf_AddFlag(&buf, flags.fromDepend, "FROM_DEPEND");
Buf_AddFlag(&buf, flags.doneAllsrc, "DONE_ALLSRC");
Buf_AddFlag(&buf, flags.doneSubmake, "DONE_SUBMAKE");
Buf_AddFlag(&buf, flags.cycle, "CYCLE");
Buf_AddFlag(&buf, flags.doneCycle, "DONECYCLE");
if (buf.len == 0)
+11 -5
View File
@@ -1,4 +1,4 @@
/* $NetBSD: make.h,v 1.361 2025/07/06 07:11:31 rillig Exp $ */
/* $NetBSD: make.h,v 1.365 2026/03/13 04:22:03 sjg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -419,6 +419,8 @@ typedef struct GNodeFlags {
bool fromDepend:1;
/* We do it once only */
bool doneAllsrc:1;
/* Have we checked for submake? */
bool doneSubmake:1;
/* Used by MakePrintStatus */
bool cycle:1;
/* Used by MakePrintStatus */
@@ -909,7 +911,7 @@ void Parse_End(void);
void PrintLocation(FILE *, bool, const GNode *);
const char *GetParentStackTrace(void);
char *GetStackTrace(bool);
void PrintStackTrace(bool);
void PrintStackTrace(FILE *, bool);
void Parse_Error(ParseErrorLevel, const char *, ...) MAKE_ATTR_PRINTFLIKE(2, 3);
bool Parse_VarAssign(const char *, bool, GNode *) MAKE_ATTR_USE;
void Parse_File(const char *, int);
@@ -995,14 +997,16 @@ typedef enum VarEvalMode {
VARE_EVAL,
/*
* Parse and evaluate the expression. It is an error if a
* subexpression evaluates to undefined.
* Only for Var_Parse, not for Var_Subst or Var_Expand: Parse and
* evaluate the expression. It is an error if the expression
* evaluates to undefined. Subexpressions or indirect expressions
* may evaluate to undefined, though.
*/
VARE_EVAL_DEFINED_LOUD,
/*
* Parse and evaluate the expression. It is a silent error if a
* subexpression evaluates to undefined.
* top-level expression evaluates to undefined.
*/
VARE_EVAL_DEFINED,
@@ -1052,6 +1056,8 @@ typedef enum VarExportMode {
VEM_LITERAL
} VarExportMode;
#define MAKE_SAVE_DOLLARS ".MAKE.SAVE_DOLLARS"
void Var_Delete(GNode *, const char *);
#ifdef CLEANUP
void Var_DeleteAll(GNode *scope);
+22 -55
View File
@@ -1,4 +1,4 @@
/* $NetBSD: meta.c,v 1.219 2025/08/04 18:57:20 rillig Exp $ */
/* $NetBSD: meta.c,v 1.220 2026/02/10 18:53:34 sjg Exp $ */
/*
* Implement 'meta' mode.
@@ -312,62 +312,20 @@ meta_name(char *mname, size_t mnamelen,
return mname;
}
/*
* Return true if running ${.MAKE}
* Bypassed if target is flagged .MAKE
*/
static bool
is_submake(const char *cmd, GNode *gn)
{
static const char *p_make = NULL;
static size_t p_len;
char *mp = NULL;
const char *cp2;
bool rc = false;
if (p_make == NULL) {
p_make = Var_Value(gn, ".MAKE").str;
p_len = strlen(p_make);
}
if (strchr(cmd, '$') != NULL) {
mp = Var_Subst(cmd, gn, VARE_EVAL);
/* TODO: handle errors */
cmd = mp;
}
cp2 = strstr(cmd, p_make);
if (cp2 != NULL) {
switch (cp2[p_len]) {
case '\0':
case ' ':
case '\t':
case '\n':
rc = true;
break;
}
if (cp2 > cmd && rc) {
switch (cp2[-1]) {
case ' ':
case '\t':
case '\n':
break;
default:
rc = false; /* no match */
break;
}
}
}
free(mp);
return rc;
}
static bool
any_is_submake(GNode *gn)
{
StringListNode *ln;
char *cmd;
for (ln = gn->commands.first; ln != NULL; ln = ln->next)
if (is_submake(ln->datum, gn))
for (ln = gn->commands.first; ln != NULL; ln = ln->next) {
cmd = Var_Subst(ln->datum, gn, VARE_EVAL);
if (MaybeSubMake(cmd)) {
free(cmd);
return true;
}
free(cmd);
}
return false;
}
@@ -423,6 +381,7 @@ meta_needed(GNode *gn, const char *dname,
SKIP_META_TYPE(OP_PHONY, "PHONY");
SKIP_META_TYPE(OP_SPECIAL, "SPECIAL");
SKIP_META_TYPE(OP_MAKE, "MAKE");
SKIP_META_TYPE(OP_SUBMAKE, "SUBMAKE");
}
/* Check if there are no commands to execute. */
@@ -431,11 +390,19 @@ meta_needed(GNode *gn, const char *dname,
debug_printf("Skipping meta for %s: no commands\n", gn->name);
return false;
}
if ((gn->type & (OP_META|OP_SUBMAKE)) == OP_SUBMAKE) {
/* OP_SUBMAKE is a bit too aggressive */
/*
* If called from meta_oodate, gn->flags.doneSubmake will be false.
* While OP_SUBMAKE only matters in jobs mode,
* we normally skip .meta files for sub-makes, so we want to check
* even in compat mode.
*/
if (gn->flags.doneSubmake == false
&& (gn->type & (OP_MAKE | OP_META)) == 0) {
gn->flags.doneSubmake = true;
if (any_is_submake(gn)) {
DEBUG1(META, "Skipping meta for %s: .SUBMAKE\n", gn->name);
return false;
gn->type |= OP_SUBMAKE;
SKIP_META_TYPE(OP_SUBMAKE, "SUBMAKE");
}
}
+38
View File
@@ -1,3 +1,41 @@
2026-03-12 Simon J Gerraty <sjg@beast.crufty.net>
* install-mk (MK_VERSION): 20260313
* sys.vars.mk: use .MAKE.VERSION
M_type can simply use '$x'
2026-02-22 Simon J Gerraty <sjg@beast.crufty.net>
* install-mk (MK_VERSION): 20260222
* dirdeps.mk, sys.mk: add dependent option
UPDATE_DIRDEPS_CACHE/DIRDEPS_CACHE.
It can be useful to use -DWITHOUT_UPDATE_DIRDEPS_CACHE to
temporarily treat dynamic DIRDEPS_CACHE as static.
2026-01-10 Simon J Gerraty <sjg@beast.crufty.net>
* meta.autodep.mk (${_DEPENDFILE}): add .NOMETA
2026-01-08 Simon J Gerraty <sjg@beast.crufty.net>
* rust.mk: better accommodation for RUST_LIBS.
Set RUST_{LIBS,PROGS}_CARGO_BUILD_OUTPUT_LIST to
simplify staging.
2025-12-08 Simon J Gerraty <sjg@beast.crufty.net>
* install-mk (MK_VERSION): 20251207
* sys.vars.mk: replace MAKE_POSIX_SHELL usage with isPOSIX_SHELL
Using ${isPOSIX_SHELL:U:Nfalse} provides a boolean for make
and ${isPOSIX_SHELL:Ufalse} does the same for target scripts.
Both will be false if isPOSIX_SHELL is not set or set to false.
This has the advantage that if only POSIX shells are expected
sys.mk (or something it includes) can simply do isPOSIX_SHELL?=:
2025-11-18 Simon J Gerraty <sjg@beast.crufty.net>
* sys.vars.mk: set MAKE_POSIX_SHELL to 1 if .SHELL is POSIX, 0 if not.
+6 -1
View File
@@ -1,4 +1,4 @@
# $Id: dirdeps.mk,v 1.175 2025/01/05 01:16:19 sjg Exp $
# $Id: dirdeps.mk,v 1.176 2026/02/23 21:37:10 sjg Exp $
# SPDX-License-Identifier: BSD-2-Clause
#
@@ -585,6 +585,11 @@ BUILD_DIRDEPS_MAKEFILE ?=
BUILD_DIRDEPS_OVERRIDES ?=
BUILD_DIRDEPS_TARGETS ?= ${.TARGETS}
# sometimes we temporarily want to block updating of DIRDEPS_CACHE
.if ${MK_UPDATE_DIRDEPS_CACHE:Uyes} == "no" && exists(${DIRDEPS_CACHE})
STATIC_DIRDEPS_CACHE ?= ${DIRDEPS_CACHE}
.endif
.if ${DIRDEPS_CACHE} != ${STATIC_DIRDEPS_CACHE:Uno} && ${DIRDEPS_CACHE:M${SRCTOP}/*} == ""
# export this for dirdeps-cache-update.mk
DYNAMIC_DIRDEPS_CACHE := ${DIRDEPS_CACHE}
+2 -2
View File
@@ -59,7 +59,7 @@
# Simon J. Gerraty <sjg@crufty.net>
# RCSid:
# $Id: install-mk,v 1.271 2025/11/11 18:08:02 sjg Exp $
# $Id: install-mk,v 1.274 2026/03/13 05:13:00 sjg Exp $
#
# @(#) Copyright (c) 1994-2025 Simon J. Gerraty
#
@@ -69,7 +69,7 @@
# sjg@crufty.net
#
MK_VERSION=20251111
MK_VERSION=20260313
OWNER=
GROUP=
MODE=444
+2 -2
View File
@@ -1,4 +1,4 @@
# $Id: meta.autodep.mk,v 1.71 2025/08/09 22:42:24 sjg Exp $
# $Id: meta.autodep.mk,v 1.72 2026/01/11 05:32:29 sjg Exp $
#
# @(#) Copyright (c) 2010-2025, Simon J. Gerraty
#
@@ -305,7 +305,7 @@ GENDIRDEPS_ENV += MAKESYSPATH=${_makesyspath}
GENDIRDEPS_ENV += MAKESYSPATH=${.SYSPATH:ts:}
.endif
${_DEPENDFILE}: ${_depend} ${.PARSEDIR}/gendirdeps.mk ${META2DEPS} $${.MAKE.META.CREATED}
${_DEPENDFILE}: .NOMETA ${_depend} ${.PARSEDIR}/gendirdeps.mk ${META2DEPS} $${.MAKE.META.CREATED}
@echo Checking $@: ${.OODATE:T:[1..8]}
@(cd . && ${GENDIRDEPS_ENV} \
SKIP_GENDIRDEPS='${SKIP_GENDIRDEPS:O:u}' \
+2 -7
View File
@@ -1,4 +1,4 @@
# $Id: meta.stage.mk,v 1.74 2025/11/19 17:44:15 sjg Exp $
# $Id: meta.stage.mk,v 1.75 2025/12/08 17:44:57 sjg Exp $
#
# @(#) Copyright (c) 2011-2025, Simon J. Gerraty
#
@@ -31,12 +31,7 @@ CLEANFILES+= .dirdep
@echo '${_dirdep}' > $@
.endif
.ifndef MAKE_POSIX_SHELL
MAKE_POSIX_SHELL != (echo $${PATH%:*}) > /dev/null 2>&1 && echo 1 || echo 0
.export MAKE_POSIX_SHELL
.endif
.if ${MAKE_POSIX_SHELL}
.if ${isPOSIX_SHELL:U:Nfalse}
_stage_file_basename = $${f\#\#*/}
_stage_file_dirname = $${f%/*}
_stage_target_dirname = $${t%/*}
+10 -9
View File
@@ -39,7 +39,7 @@ We only pay attention to a subset of the information in the
SPDX-License-Identifier: BSD-2-Clause
RCSid:
$Id: meta2deps.py,v 1.54 2025/07/24 16:05:48 sjg Exp $
$Id: meta2deps.py,v 1.55 2026/01/13 04:32:45 sjg Exp $
Copyright (c) 2011-2025, Simon J. Gerraty
Copyright (c) 2011-2017, Juniper Networks, Inc.
@@ -446,7 +446,7 @@ class MetaFile:
version = 0 # unknown
if name:
self.name = name;
self.name = name
if file:
f = file
cwd = self.last_dir = self.cwd
@@ -669,7 +669,7 @@ class MetaFile:
return
if os.path.isdir(path):
if op in 'RW':
self.last_dir = path;
self.last_dir = path
if self.debug > 1:
print("ldir=", self.last_dir, file=self.debug_out)
return
@@ -703,7 +703,7 @@ class MetaFile:
self.seenit(dir)
def main(argv, klass=MetaFile, xopts='', xoptf=None):
def main(argv, klass=MetaFile, xopts='', xoptf=None, conf=None):
"""Simple driver for class MetaFile.
Usage:
@@ -743,11 +743,12 @@ def main(argv, klass=MetaFile, xopts='', xoptf=None):
except:
pass
conf = {
'SRCTOPS': [],
'OBJROOTS': [],
'EXCLUDES': [],
}
if not conf:
conf = {}
for k in ['EXCLUDES', 'OBJROOTS', 'SRCTOPS']:
if k not in conf:
conf[k] = []
conf['SB'] = os.getenv('SB', '')
+3 -3
View File
@@ -77,7 +77,7 @@
# RCSid:
# $Id: meta2deps.sh,v 1.25 2025/11/11 18:08:02 sjg Exp $
# $Id: meta2deps.sh,v 1.26 2025/12/08 17:34:02 sjg Exp $
# SPDX-License-Identifier: BSD-2-Clause
#
@@ -263,8 +263,8 @@ meta2deps() {
# first a sanity check - filemon on Linux is not very reliable
# path2 should only be non-empty for op L or M
# and it should not contain spaces.
# It will also be non-empty for # Meta line
# which tells us which meta_file we are processing
# It will also be non-empty for # Meta line
# which tells us which meta_file we are processing
case "$op,$path2" in
\#*,*.meta) # new file, reset some vars
version=no epids= xpids= eof_token=no lpid=
+15 -6
View File
@@ -1,6 +1,6 @@
# $Id: rust.mk,v 1.38 2025/08/09 22:42:24 sjg Exp $
# $Id: rust.mk,v 1.40 2026/01/08 20:34:30 sjg Exp $
#
# @(#) Copyright (c) 2024, Simon J. Gerraty
# @(#) Copyright (c) 2024-2026, Simon J. Gerraty
#
# SPDX-License-Identifier: BSD-2-Clause
#
@@ -180,15 +180,24 @@ all: cargo.clippy
.if !defined(RUST_LIBS)
RUST_PROGS ?= ${RUST_PROJECT_DIR:T}
.endif
.if !empty(RUST_PROGS)
BINDIR ?= ${prefix}/bin
.if !empty(RUST_LIBS) || !empty(RUST_PROGS)
# there could be a target triple involved
RUST_CARGO_TARGET_DIR ?= ${CARGO_TARGET_DIR}
RUST_CARGO_OUTPUT_DIR ?= ${RUST_CARGO_TARGET_DIR}/${RUST_CARGO_TARGET}
RUST_CARGO_BUILD_OUTPUT_LIST := ${RUST_PROGS:S,^,${RUST_CARGO_OUTPUT_DIR}/,}
.if !empty(RUST_LIBS)
LIBDIR ?= ${prefix}/lib
RUST_LIBS_CARGO_BUILD_OUTPUT_LIST := ${RUST_LIBS:S,^,${RUST_CARGO_OUTPUT_DIR}/,}
${RUST_CARGO_BUILD_OUTPUT_LIST}: cargo.build
${RUST_LIBS_CARGO_BUILD_OUTPUT_LIST}: cargo.build
.endif
.if !empty(RUST_PROGS)
BINDIR ?= ${prefix}/bin
RUST_PROGS_CARGO_BUILD_OUTPUT_LIST := ${RUST_PROGS:S,^,${RUST_CARGO_OUTPUT_DIR}/,}
${RUST_PROGS_CARGO_BUILD_OUTPUT_LIST}: cargo.build
.endif
.endif
# for late customizations
+10 -5
View File
@@ -1,4 +1,4 @@
# $Id: sys.dirdeps.mk,v 1.16 2025/08/09 22:42:24 sjg Exp $
# $Id: sys.dirdeps.mk,v 1.17 2026/02/15 17:04:27 sjg Exp $
#
# @(#) Copyright (c) 2012-2023, Simon J. Gerraty
#
@@ -96,10 +96,15 @@ TARGET_SPEC = ${TARGET_SPEC_VARS:@v@${$v:U}@:ts,}
.if ${TARGET_SPEC_VARS:[#]} > 1
TARGET_SPEC_VARSr := ${TARGET_SPEC_VARS:[-1..1]}
# alternatives might be
# TARGET_OBJ_SPEC = ${TARGET_SPEC_VARSr:@v@${$v:U}@:ts/}
# TARGET_OBJ_SPEC = ${TARGET_SPEC_VARS:@v@${$v:U}@:ts/}
TARGET_OBJ_SPEC ?= ${TARGET_SPEC_VARS:@v@${$v:U}@:ts.}
#
# local.sys.*mk can control the format of TARGET_OBJ_SPEC
# by setting eg.
# TARGET_OBJ_SPEC_VARS = ${TARGET_SPEC_VARSr}
# TARGET_OBJ_SPEC_SEP = /
#
TARGET_OBJ_SPEC_VARS ?= ${TARGET_SPEC_VARS}
TARGET_OBJ_SPEC_SEP ?= .
TARGET_OBJ_SPEC = ${TARGET_OBJ_SPEC_VARS:@v@${$v:U}@:ts${TARGET_OBJ_SPEC_SEP}}
.else
TARGET_OBJ_SPEC ?= ${MACHINE}
.endif
+3 -2
View File
@@ -1,4 +1,4 @@
# $Id: sys.mk,v 1.66 2025/11/19 03:38:20 sjg Exp $
# $Id: sys.mk,v 1.67 2026/02/23 21:37:10 sjg Exp $
#
# @(#) Copyright (c) 2003-2023, Simon J. Gerraty
#
@@ -86,7 +86,7 @@ EGREP ?= egrep
# some options we need to know early
OPTIONS_DEFAULT_NO += \
DIRDEPS_BUILD \
DIRDEPS_CACHE
DIRDEPS_CACHE \
OPTIONS_DEFAULT_DEPENDENT += \
AUTO_OBJ/DIRDEPS_BUILD \
@@ -95,6 +95,7 @@ OPTIONS_DEFAULT_DEPENDENT += \
STAGING/DIRDEPS_BUILD \
STATIC_DIRDEPS_CACHE/DIRDEPS_CACHE \
UPDATE_DEPENDFILE/DIRDEPS_BUILD \
UPDATE_DIRDEPS_CACHE/DIRDEPS_CACHE \
.-include <options.mk>
+17 -21
View File
@@ -1,4 +1,4 @@
# $Id: sys.vars.mk,v 1.24 2025/11/19 17:44:15 sjg Exp $
# $Id: sys.vars.mk,v 1.27 2026/03/13 16:02:44 sjg Exp $
#
# @(#) Copyright (c) 2003-2023, Simon J. Gerraty
#
@@ -24,25 +24,21 @@ MAKE_VERSION ?= 0
MAKE_VERSION := ${MAKE_VERSION:[1]:C,.*-,,}
.endif
.if ${MAKE_VERSION} < 20100414
# from (20260210) .MAKE.VERSION is read-only
.MAKE.VERSION ?= ${MAKE_VERSION}
.if ${.MAKE.VERSION} < 20100414
_this = ${.PARSEDIR}/${.PARSEFILE}
.else
_this = ${.PARSEDIR:tA}/${.PARSEFILE}
.endif
# This is a boolean we can use in makefiles as below
.ifndef MAKE_POSIX_SHELL
MAKE_POSIX_SHELL != (echo $${PATH%:*}) > /dev/null 2>&1 && echo 1 || echo 0
.export MAKE_POSIX_SHELL
.endif
# This is a boolean we can use in target scripts
.ifndef isPOSIX_SHELL
.if ${MAKE_POSIX_SHELL}
isPOSIX_SHELL = :
.else
isPOSIX_SHELL = false
.endif
# This is a boolean we can use in makefiles:
# .if ${isPOSIX_SHELL:U:Nfalse}
# as well as in target scripts:
# if ${isPOSIX_SHELL:Ufalse}; then
.if empty(isPOSIX_SHELL)
isPOSIX_SHELL != (echo $${PATH%:*}) > /dev/null 2>&1 && echo : || echo false
.export isPOSIX_SHELL
.endif
@@ -66,14 +62,14 @@ _type_sh = which
.endif
# :sh1 evaluates command only once and caches the result.
.if ${MAKE_VERSION} < 20251111
.if ${.MAKE.VERSION} < 20251111
M_sh1 = sh
.else
M_sh1 = sh1
.endif
# AUTOCONF := ${autoconf:L:${M_whence}}
M_type = @x@(${_type_sh:Utype} $$x) 2> /dev/null; echo;@:${M_sh1:Ush}:[0]:N* found*:[@]:C,[()],,g
M_type = @x@(${_type_sh:Utype} $x) 2> /dev/null; echo;@:${M_sh1:Ush}:[0]:N* found*:[@]:C,[()],,g
M_whence = ${M_type}:M/*:[1]
# produce similar output to jot(1) or seq(1)
@@ -98,7 +94,7 @@ M_JOT = [1]:@x@i=1;while [ $$$$i -le $$x ]; do echo $$$$i; i=$$$$((i + 1)); done
.endif
# ${LIST:${M_RANGE}} is 1 2 3 4 5 if LIST has 5 words
.if ${MAKE_VERSION} < 20170130
.if ${.MAKE.VERSION} < 20170130
M_RANGE = [#]:${M_JOT}
.else
M_RANGE = range
@@ -108,7 +104,7 @@ M_RANGE = range
M_P2V = tu:C,[./-],_,g
# convert path to absolute
.if ${MAKE_VERSION} < 20100414
.if ${.MAKE.VERSION} < 20100414
M_tA = C,.*,('cd' & \&\& 'pwd') 2> /dev/null || echo &,:sh
.else
M_tA = tA
@@ -117,7 +113,7 @@ M_tA = tA
# absoulte path to what we are reading.
_PARSEDIR = ${.PARSEDIR:${M_tA}}
.if ${MAKE_VERSION} >= 20170130
.if ${.MAKE.VERSION} >= 20170130
# M_cmpv allows comparing dotted versions like 3.1.2
# ${3.1.2:L:${M_cmpv}} -> 3001002
# we use big jumps to handle 3 digits per dot:
@@ -132,7 +128,7 @@ M_cmpv = S,., ,g:C,^0*([0-9]),\1,:_:range:@i@+ $${_:[-$$i]} \* $${M_cmpv.units:[
M_M.M.P_VERSION = L:@v@$${MAJOR MINOR PATCH:L:@t@$${$$v_$$t_VERSION:U0}@}@:ts.
# numeric sort
.if ${MAKE_VERSION} < 20210803
.if ${.MAKE.VERSION} < 20210803
M_On = O
M_Onr = O
.else
Executable → Regular
+6 -2
View File
@@ -17,9 +17,9 @@
# Simon J. Gerraty <sjg@crufty.net>
# RCSid:
# $Id: os.sh,v 1.68 2025/08/07 21:59:54 sjg Exp $
# $Id: os.sh,v 1.70 2026/02/25 05:44:34 sjg Exp $
#
# @(#) Copyright (c) 1994 Simon J. Gerraty
# @(#) Copyright (c) 1994-2026 Simon J. Gerraty
#
# SPDX-License-Identifier: BSD-2-Clause
#
@@ -226,6 +226,10 @@ x86*64|amd64) MACHINE32_ARCH=i386;;
*) MACHINE32_ARCH=$MACHINE_ARCH;;
esac
HOST_ARCH32=${HOST_ARCH32:-$MACHINE32_ARCH}
MACHINE32=${HOST_ARCH32:-$MACHINE}
HOST_MACHINE=${HOST_MACHINE:-$MACHINE}
HOST_MACHINE32=${HOST_MACHINE32:-$MACHINE32}
export HOST_MACHINE HOST_MACHINE32
export HOST_ARCH HOST_ARCH32
# we mount server:/share/arch/$SHARE_ARCH as /usr/local
SHARE_ARCH_DEFAULT=$OS/$OSMAJOR.X/$HOST_ARCH
+6 -48
View File
@@ -1,4 +1,4 @@
/* $NetBSD: parse.c,v 1.753 2025/06/28 22:39:27 rillig Exp $ */
/* $NetBSD: parse.c,v 1.755 2026/02/10 18:53:34 sjg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -110,7 +110,7 @@
#include "pathnames.h"
/* "@(#)parse.c 8.3 (Berkeley) 3/19/94" */
MAKE_RCSID("$NetBSD: parse.c,v 1.753 2025/06/28 22:39:27 rillig Exp $");
MAKE_RCSID("$NetBSD: parse.c,v 1.755 2026/02/10 18:53:34 sjg Exp $");
/* Detects a multiple-inclusion guard in a makefile. */
typedef enum {
@@ -481,11 +481,11 @@ add_parent_stack_trace:
}
void
PrintStackTrace(bool includingInnermost)
PrintStackTrace(FILE *f, bool includingInnermost)
{
char *stackTrace = GetStackTrace(includingInnermost);
fprintf(stderr, "%s", stackTrace);
fflush(stderr);
fprintf(f, "%s", stackTrace);
fflush(f);
free(stackTrace);
}
@@ -602,7 +602,7 @@ ParseVErrorInternal(FILE *f, bool useVars, const GNode *gn,
if (level == PARSE_FATAL || DEBUG(PARSE)
|| (gn == NULL && includes.len == 0 /* see PrintLocation */))
PrintStackTrace(false);
PrintStackTrace(f, false);
}
static void MAKE_ATTR_PRINTFLIKE(3, 4)
@@ -1985,46 +1985,6 @@ Parse_Var(VarAssign *var, GNode *scope)
}
/*
* See if the command possibly calls a sub-make by using the
* expressions ${.MAKE}, ${MAKE} or the plain word "make".
*/
static bool
MaybeSubMake(const char *cmd)
{
const char *start;
for (start = cmd; *start != '\0'; start++) {
const char *p = start;
char endc;
/* XXX: What if progname != "make"? */
if (strncmp(p, "make", 4) == 0)
if (start == cmd || !ch_isalnum(p[-1]))
if (!ch_isalnum(p[4]))
return true;
if (*p != '$')
continue;
p++;
if (*p == '{')
endc = '}';
else if (*p == '(')
endc = ')';
else
continue;
p++;
if (*p == '.') /* Accept either ${.MAKE} or ${MAKE}. */
p++;
if (strncmp(p, "MAKE", 4) == 0 && p[4] == endc)
return true;
}
return false;
}
/* Append the command to the target node. */
static void
GNode_AddCommand(GNode *gn, char *cmd)
@@ -2035,8 +1995,6 @@ GNode_AddCommand(GNode *gn, char *cmd)
/* if target already supplied, ignore commands */
if (!(gn->type & OP_HAS_COMMANDS)) {
Lst_Append(&gn->commands, cmd);
if (MaybeSubMake(cmd))
gn->type |= OP_SUBMAKE;
RememberLocation(gn);
} else {
Parse_Error(PARSE_WARNING,
+28 -30
View File
@@ -1,37 +1,35 @@
/* $NetBSD: str.h,v 1.20 2024/07/07 07:50:57 rillig Exp $ */
/* $NetBSD: str.h,v 1.21 2026/01/03 19:57:38 rillig Exp $ */
/*
Copyright (c) 2021 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.
*/
/*
* Memory-efficient string handling.
* Copyright (c) 2021 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Roland Illig.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* Memory-efficient string handling. */
/* A read-only string that may need to be freed after use. */
typedef struct FStr {
+6 -6
View File
@@ -1,4 +1,4 @@
/* $NetBSD: suff.c,v 1.384 2025/05/18 06:24:27 rillig Exp $ */
/* $NetBSD: suff.c,v 1.385 2026/01/03 19:57:38 rillig 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.384 2025/05/18 06:24:27 rillig Exp $");
MAKE_RCSID("$NetBSD: suff.c,v 1.385 2026/01/03 19:57:38 rillig Exp $");
typedef List SuffixList;
typedef ListNode SuffixListNode;
@@ -1431,7 +1431,7 @@ Suff_FindPath(GNode *gn)
return suff->searchPath;
} else {
DEBUG0(SUFF, "\n");
return &dirSearchPath; /* Use default search path */
return &dirSearchPath; /* Use the default search path */
}
}
@@ -1439,8 +1439,8 @@ Suff_FindPath(GNode *gn)
* Apply a transformation rule, given the source and target nodes and
* suffixes.
*
* The source and target are linked and the commands from the transformation
* are added to the target node's commands list. The target also inherits all
* The source and target are linked, and the commands from the transformation
* are added to the target node's commands. The target also inherits all
* the sources for the transformation rule.
*
* Results:
@@ -1470,7 +1470,7 @@ ApplyTransform(GNode *tgn, GNode *sgn, Suffix *tsuff, Suffix *ssuff)
DEBUG3(SUFF, "\tapplying %s -> %s to \"%s\"\n",
ssuff->name, tsuff->name, tgn->name);
/* Record last child; Make_HandleUse may add child nodes. */
/* Record the last child; Make_HandleUse may add child nodes. */
ln = tgn->children.last;
/* Apply the rule. */
+27 -6
View File
@@ -1,6 +1,6 @@
# $Id: Makefile,v 1.251 2025/11/15 17:17:18 sjg Exp $
# $Id: Makefile,v 1.260 2026/03/10 15:45:51 sjg Exp $
#
# $NetBSD: Makefile,v 1.373 2025/11/12 22:14:08 sjg Exp $
# $NetBSD: Makefile,v 1.383 2026/03/10 15:38:26 sjg Exp $
#
# Unit tests for make(1)
#
@@ -629,6 +629,9 @@ SED_CMDS.opt-chdir= -e 's,\(nonexistent\).[1-9][0-9]*,\1,' \
-e 's,no such,No such,' \
-e 's,Filename,File name,'
SED_CMDS.gnode-submake= ${STD_SED_CMDS.dj}
SED_CMDS.gnode-submake= ${STD_SED_CMDS.dg2}
# meta line numbers can vary based on filemon implementation
SED_CMDS.meta-ignore= -e 's,\(\.meta:\)[1-9][0-9]*:,\1<line>:,'
@@ -642,6 +645,7 @@ SED_CMDS.opt-debug-lint+= ${STD_SED_CMDS.regex}
SED_CMDS.opt-jobs-no-action= ${STD_SED_CMDS.hide-from-output}
SED_CMDS.opt-no-action-runflags= ${STD_SED_CMDS.hide-from-output}
SED_CMDS.opt-where-am-i= -e '/usr.obj/d'
SED_CMDS.opt-where-am-i+= -e '/\/\//d'
# For Compat_RunCommand, useShell == false.
SED_CMDS.sh-dots= -e 's,^.*\.\.\.:.*,<not found: ...>,'
# For Compat_RunCommand, useShell == true.
@@ -662,6 +666,7 @@ 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-mtime+= -e "s,\(mtime for .*\): .*,\1: <ENOENT>,"
SED_CMDS.varmod-subst+= ${STD_SED_CMDS.regex}
SED_CMDS.varmod-subst-regex+= ${STD_SED_CMDS.regex}
SED_CMDS.varparse-errors+= ${STD_SED_CMDS.timestamp}
SED_CMDS.varname-dot-make-meta-ignore_filter+= ${SED_CMDS.meta-ignore}
@@ -677,7 +682,10 @@ SED_CMDS.varname-empty= ${.OBJDIR .PARSEDIR .PATH .SHELL .SYSPATH:L:@v@-e '/\\$
# Some tests need an additional round of postprocessing.
POSTPROC.depsrc-wait= sed -e '/^---/d' -e 's,^\(: Making 3[abc]\)[123]$$,\1,'
POSTPROC.deptgt-suffixes= awk '/^\#\*\*\* Suffixes/,/^never-stop/'
POSTPROC.gnode-submake= awk '/Begin input graph/, /^$$/'
POSTPROC.gnode-submake= \
awk '/Begin input graph/, /^\# \.END/ { \
if (/made,/) print $$0 \
}'
POSTPROC.varname-dot-make-mode= sed 's,^\(: Making [abc]\)[123]$$,\1,'
# Some tests reuse other tests, which makes them unnecessarily fragile.
@@ -700,6 +708,7 @@ STD_SED_CMDS.dg1= -e '/\#.* \.$$/d'
STD_SED_CMDS.dg1+= -e '/\.MAKE.PATH_FILEMON/d'
STD_SED_CMDS.dg1+= -e '/^\#.*\/mk/d'
STD_SED_CMDS.dg1+= -e 's, ${DEFSYSPATH:U/usr/share/mk}$$, <defsyspath>,'
STD_SED_CMDS.dg1+= -e '/^\.MAKE\.PATH_FILEMON/d'
STD_SED_CMDS.dg1+= -e 's,^\(\.MAKE *=\) .*,\1 <details omitted>,'
STD_SED_CMDS.dg1+= -e 's,^\(\.MAKE\.[A-Z_]* *=\) .*,\1 <details omitted>,'
STD_SED_CMDS.dg1+= -e 's,^\(\.MAKE\.JOBS\.C *=\) .*,\1 <details omitted>,'
@@ -710,6 +719,7 @@ STD_SED_CMDS.dg1+= -e '/\.SYSPATH/d'
STD_SED_CMDS.dg2= ${STD_SED_CMDS.dg1}
STD_SED_CMDS.dg2+= -e 's,\(last modified\) ..:..:.. ... ..\, ....,\1 <timestamp>,'
STD_SED_CMDS.dg3= ${STD_SED_CMDS.dg2}
# Omit details such as process IDs from the output of the -dj option.
@@ -792,6 +802,16 @@ clean:
rm -f ${CLEANFILES}
TEST_MAKE?= ${.MAKE}
.if ${TEST_MAKE:M/*} == ""
# we want an absolute path for TEST_MAKE
tm!= for d in ${PATH:S,:, ,g:M/*}; do \
test -x $$d/${TEST_MAKE} || continue; \
echo $$d/${TEST_MAKE}; break; done
.if ${tm:M/*}
TEST_MAKE:= ${tm}
.endif
.endif
TOOL_SED?= sed
TOOL_TR?= tr
TOOL_DIFF?= diff
@@ -831,7 +851,7 @@ LIMIT_RESOURCES?= :
# each other, and because they use different environment variables and
# command line options.
.SUFFIXES: .mk .rawout .out
.mk.rawout:
.mk.rawout: .META
@${_MKMSG_TEST:Uecho '# test '} ${.PREFIX}
@set -eu; \
${LIMIT_RESOURCES}; \
@@ -873,7 +893,8 @@ _SED_CMDS+= -e 's,^usage: ${TEST_MAKE:T:S,.,\\.,g} ,usage: make ,'
_SED_CMDS+= -e 's,${TEST_MAKE:T:S,.,\\.,g}\(\[[1-9][0-9]*\][: ]\),make\1,'
_SED_CMDS+= -e 's,<curdir>/,,g'
_SED_CMDS+= -e 's,${UNIT_TESTS:S,.,\\.,g}/,,g'
_SED_CMDS+= -e '/MAKE_VERSION/d'
_SED_CMDS+= -e 's,\(\.make\)[1-9][0-9]*,\1,g'
_SED_CMDS+= -e '/MAKE.VERSION/d'
_SED_CMDS+= -e '/EGREP=/d'
# on AT&T derived systems: false exits 255 not 1
@@ -886,7 +907,7 @@ SED_CMDS.opt-debug-jobs+= -e 's,Command: ksh -v,Command: <shell>,'
SED_CMDS.opt-debug-jobs+= -e 's,Command: <shell> -v,Command: <shell>,'
.endif
.rawout.out:
.rawout.out: .META
@${TOOL_SED} ${_SED_CMDS} ${SED_CMDS.${.PREFIX:T}} ${_SED_CMDS_LAST} \
< ${.IMPSRC} > ${.TARGET}.tmp
@${POSTPROC.${.PREFIX:T}:D \
+6 -6
View File
@@ -9,34 +9,34 @@ end undefined-indirect with status 0
begin parse-error-direct
make: Unclosed variable "UNCLOSED"
in command ": unexpected $@-${UNCLOSED"
in target "parse-error-unclosed-expression"
in target "parse-error-unclosed-expression" from cmd-errors-jobs.mk:42
in make[1] in directory "<curdir>"
make: Unclosed expression, expecting "}"
while evaluating variable "UNCLOSED" with value ""
in command ": unexpected $@-${UNCLOSED:"
in target "parse-error-unclosed-modifier"
in target "parse-error-unclosed-modifier" from cmd-errors-jobs.mk:45
in make[1] in directory "<curdir>"
make: Unknown modifier ":Z"
while evaluating variable "UNKNOWN" with value ""
in command ": unexpected $@-${UNKNOWN:Z}-eol"
in target "parse-error-unknown-modifier"
in target "parse-error-unknown-modifier" from cmd-errors-jobs.mk:48
in make[1] in directory "<curdir>"
end parse-error-direct with status 2
begin parse-error-indirect
make: Unclosed variable "UNCLOSED"
in command ": unexpected $@-${UNCLOSED"
in target "parse-error-unclosed-expression"
in target "parse-error-unclosed-expression" from cmd-errors-jobs.mk:42
in make[1] in directory "<curdir>"
make: Unclosed expression, expecting "}"
while evaluating variable "UNCLOSED" with value ""
in command ": unexpected $@-${UNCLOSED:"
in target "parse-error-unclosed-modifier"
in target "parse-error-unclosed-modifier" from cmd-errors-jobs.mk:45
in make[1] in directory "<curdir>"
make: Unknown modifier ":Z"
while evaluating variable "UNKNOWN" with value ""
in command ": unexpected $@-${UNKNOWN:Z}-eol"
in target "parse-error-unknown-modifier"
in target "parse-error-unknown-modifier" from cmd-errors-jobs.mk:48
in make[1] in directory "<curdir>"
end parse-error-indirect with status 2
+3 -3
View File
@@ -1,14 +1,14 @@
: undefined
make: Unclosed variable "UNCLOSED"
in command ": $@ ${UNCLOSED"
in target "unclosed-expression"
in target "unclosed-expression" from cmd-errors-lint.mk:19
make: Unclosed expression, expecting "}"
while evaluating variable "UNCLOSED" with value ""
in command ": $@ ${UNCLOSED:"
in target "unclosed-modifier"
in target "unclosed-modifier" from cmd-errors-lint.mk:24
make: Unknown modifier ":Z"
while evaluating variable "UNKNOWN" with value ""
in command ": $@ ${UNKNOWN:Z}"
in target "unknown-modifier"
in target "unknown-modifier" from cmd-errors-lint.mk:29
: end
exit status 2
+3 -3
View File
@@ -1,14 +1,14 @@
: undefined--eol
make: Unclosed variable "UNCLOSED"
in command ": $@-${UNCLOSED"
in target "unclosed-expression"
in target "unclosed-expression" from cmd-errors.mk:17
make: Unclosed expression, expecting "}"
while evaluating variable "UNCLOSED" with value ""
in command ": $@-${UNCLOSED:"
in target "unclosed-modifier"
in target "unclosed-modifier" from cmd-errors.mk:22
make: Unknown modifier ":Z"
while evaluating variable "UNKNOWN" with value ""
in command ": $@-${UNKNOWN:Z}-eol"
in target "unknown-modifier"
in target "unknown-modifier" from cmd-errors.mk:27
: end-eol
exit status 2
+14 -2
View File
@@ -1,4 +1,4 @@
# $NetBSD: cond-func-exists.mk,v 1.8 2025/01/10 23:00:38 rillig Exp $
# $NetBSD: cond-func-exists.mk,v 1.9 2026/03/02 21:49:37 rillig Exp $
#
# Tests for the exists() function in .if conditions.
@@ -52,5 +52,17 @@ _!= > cond-func-exists.just-created
.endif
_!= rm cond-func-exists.just-created
# The exists function aims at source and target files, but not at makefiles.
# In particular, the file is not searched in ${.PARSEDIR}.
_!= mkdir -p cond-func-exists && \
printf '%s\n' \
'.if exists(file.inc)' \
'. error' \
'.endif' \
> cond-func-exists/file.inc
.include "cond-func-exists/file.inc"
_!= rm -f cond-func-exists/file.inc
all:
@:;
+2 -2
View File
@@ -1,4 +1,4 @@
# $NetBSD: cond-undef-lint.mk,v 1.8 2025/01/11 21:21:33 rillig Exp $
# $NetBSD: cond-undef-lint.mk,v 1.9 2026/02/13 03:16:15 lukem Exp $
#
# Tests for defined and undefined variables in .if conditions, in lint mode.
#
@@ -51,7 +51,7 @@ DEF= defined
# Variables that are referenced indirectly may be undefined in a condition.
#
# A practical example for this is CFLAGS, which consists of CWARNS, COPTS
# A practical example for this is CFLAGS, which consists of CWARNFLAGS, COPTS
# and a few others. Just because these nested variables are not defined,
# this does not make the condition invalid.
#
+1 -1
View File
@@ -1,4 +1,4 @@
# $NetBSD: directive-dinclude.mk,v 1.5 2025/06/28 22:39:28 rillig Exp $
# $NetBSD: directive-dinclude.mk,v 1.6 2025/11/16 16:43:56 sjg Exp $
#
# Tests for the .dinclude directive, which includes another file,
# silently skipping it if it cannot be opened. This is primarily used for
+10 -1
View File
@@ -1,4 +1,4 @@
# $NetBSD: directive-export-gmake.mk,v 1.10 2025/06/28 22:39:28 rillig Exp $
# $NetBSD: directive-export-gmake.mk,v 1.11 2026/01/02 14:21:46 rillig Exp $
#
# Tests for the export directive (without leading dot), as in GNU make.
@@ -104,3 +104,12 @@ export ${INDIRECT_NAME}=${INDIRECT_VALUE}
.if ${:!env!:MI_NAME=*}
. error
.endif
# Quotes and other special characters are preserved.
export DQUOT="dquot"
export SQUOT='squot'
export PLAIN=plain
.if ${:!echo "\$DQUOT \$SQUOT \$PLAIN"!} != "\"dquot\" 'squot' plain"
. error
.endif
+1 -1
View File
@@ -1,4 +1,4 @@
# $NetBSD: directive-hyphen-include.mk,v 1.5 2025/06/28 22:39:28 rillig Exp $
# $NetBSD: directive-hyphen-include.mk,v 1.6 2025/11/16 16:43:57 sjg Exp $
#
# Tests for the .-include directive, which includes another file,
# silently skipping it if it cannot be opened.
+1 -1
View File
@@ -1,4 +1,4 @@
# $NetBSD: directive-include-guard.mk,v 1.19 2025/04/11 17:21:31 rillig Exp $
# $NetBSD: directive-include-guard.mk,v 1.20 2025/11/16 16:43:57 sjg Exp $
#
# Tests for multiple-inclusion guards in makefiles.
#
+1 -1
View File
@@ -1,4 +1,4 @@
# $NetBSD: directive-include.mk,v 1.20 2025/06/28 22:39:28 rillig Exp $
# $NetBSD: directive-include.mk,v 1.21 2025/11/16 16:43:57 sjg Exp $
#
# Tests for the .include directive, which includes another file.
+1 -1
View File
@@ -1,4 +1,4 @@
# $NetBSD: directive-sinclude.mk,v 1.7 2025/06/28 22:39:28 rillig Exp $
# $NetBSD: directive-sinclude.mk,v 1.8 2025/11/16 16:43:57 sjg Exp $
#
# Tests for the .sinclude directive, which includes another file,
# silently skipping it if it cannot be opened.
+10 -10
View File
@@ -1,11 +1,11 @@
#*** Begin input graph for pass 1 in <curdir>:
# all, unmade, type OP_DEPENDS, flags none
# makeinfo, unmade, type OP_DEPENDS|OP_HAS_COMMANDS, flags none
# make-index, unmade, type OP_DEPENDS|OP_SUBMAKE|OP_HAS_COMMANDS, flags none
# braces-dot, unmade, type OP_DEPENDS|OP_SUBMAKE|OP_HAS_COMMANDS, flags none
# braces-no-dot, unmade, type OP_DEPENDS|OP_SUBMAKE|OP_HAS_COMMANDS, flags none
# braces-no-dot-modifier, unmade, type OP_DEPENDS|OP_HAS_COMMANDS, flags none
# parentheses-dot, unmade, type OP_DEPENDS|OP_SUBMAKE|OP_HAS_COMMANDS, flags none
# parentheses-no-dot, unmade, type OP_DEPENDS|OP_SUBMAKE|OP_HAS_COMMANDS, flags none
# .MAIN, made, type OP_DEPENDS|OP_PHONY, flags REMAKE|CHILDMADE|FORCE|DONE_WAIT|DONE_ALLSRC
# all, made, type OP_DEPENDS|OP_DEPS_FOUND|OP_MARK, flags REMAKE|CHILDMADE|FORCE|DONE_WAIT|DONE_ALLSRC|DONECYCLE
# makeinfo, made, type OP_DEPENDS|OP_HAS_COMMANDS|OP_DEPS_FOUND|OP_MARK, flags REMAKE|DONE_WAIT|DONE_ALLSRC|DONE_SUBMAKE
# make-index, made, type OP_DEPENDS|OP_HAS_COMMANDS|OP_DEPS_FOUND|OP_MARK, flags REMAKE|DONE_WAIT|DONE_ALLSRC|DONE_SUBMAKE
# braces-dot, made, type OP_DEPENDS|OP_SUBMAKE|OP_HAS_COMMANDS|OP_DEPS_FOUND|OP_MARK, flags REMAKE|DONE_WAIT|DONE_ALLSRC|DONE_SUBMAKE
# braces-no-dot, made, type OP_DEPENDS|OP_SUBMAKE|OP_HAS_COMMANDS|OP_DEPS_FOUND|OP_MARK, flags REMAKE|DONE_WAIT|DONE_ALLSRC|DONE_SUBMAKE
# braces-no-dot-modifier, made, type OP_DEPENDS|OP_SUBMAKE|OP_HAS_COMMANDS|OP_DEPS_FOUND|OP_MARK, flags REMAKE|DONE_WAIT|DONE_ALLSRC|DONE_SUBMAKE
# parentheses-dot, made, type OP_DEPENDS|OP_SUBMAKE|OP_HAS_COMMANDS|OP_DEPS_FOUND|OP_MARK, flags REMAKE|DONE_WAIT|DONE_ALLSRC|DONE_SUBMAKE
# parentheses-no-dot, made, type OP_DEPENDS|OP_SUBMAKE|OP_HAS_COMMANDS|OP_DEPS_FOUND|OP_MARK, flags REMAKE|DONE_WAIT|DONE_ALLSRC|DONE_SUBMAKE
# .END, unmade, type OP_SPECIAL, flags none
exit status 0
+2 -2
View File
@@ -1,4 +1,4 @@
# $NetBSD: gnode-submake.mk,v 1.1 2020/11/07 23:25:06 rillig Exp $
# $NetBSD: gnode-submake.mk,v 1.2 2026/02/10 18:53:34 sjg Exp $
#
# Test whether OP_SUBMAKE is determined correctly. If it is, this node's
# shell commands are connected to the make process via pipes, to coordinate
@@ -8,7 +8,7 @@
# parsed. This information is only used in parallel mode, but the result
# from parsing is available in compat mode as well.
.MAKEFLAGS: -n -dg1
.MAKEFLAGS: -dg2 -j1
all: makeinfo make-index
all: braces-dot braces-no-dot
+1 -1
View File
@@ -1,5 +1,5 @@
make: In the :@ modifier, the variable name "${:Ubar:S,b,v,}" must not contain a dollar
while evaluating variable "VAR" with value "value"
in command "@echo ${VAR:Uvalue:@${:Ubar:S,b,v,}@x${var}y@:Q}"
in target "mod-loop-varname"
in target "mod-loop-varname" from lint.mk:22
exit status 2
+40 -40
View File
@@ -1,173 +1,173 @@
make: Unknown modifier ":Z"
while evaluating variable "VAR" with value "TheVariable"
in command "@echo 'VAR:Z=before-${VAR:Z}-after'"
in target "mod-unknown-direct"
in target "mod-unknown-direct" from moderrs.mk:29
make: Unknown modifier ":Z"
while evaluating indirect modifiers "Z"
while evaluating variable "VAR" with value "TheVariable"
in command "@echo 'VAR:${MOD_UNKN}=before-${VAR:${MOD_UNKN}:inner}-after'"
in target "mod-unknown-indirect"
in target "mod-unknown-indirect" from moderrs.mk:33
make: Unclosed expression, expecting "}" for modifier "S,V,v,"
while evaluating variable "VAR" with value "Thevariable"
in command "@echo VAR:S,V,v,=${VAR:S,V,v,"
in target "unclosed-direct"
in target "unclosed-direct" from moderrs.mk:37
make: Unclosed expression after indirect modifier, expecting "}"
while evaluating variable "VAR" with value "Thevariable"
in command "@echo VAR:${MOD_TERM},=${VAR:${MOD_S}"
in target "unclosed-indirect"
in target "unclosed-indirect" from moderrs.mk:41
make: Unfinished modifier after "v", expecting ","
while evaluating indirect modifiers "S,V,v"
while evaluating variable "VAR" with value "TheVariable"
in command "-@echo "VAR:${MOD_TERM}=${VAR:${MOD_TERM}}""
in target "unfinished-indirect"
in target "unfinished-indirect" from moderrs.mk:45
make: Unfinished modifier after "var}", expecting "@"
while evaluating variable "UNDEF" with value "1 2 3"
in command "@echo ${UNDEF:U1 2 3:@var}"
in target "unfinished-loop-1"
in target "unfinished-loop-1" from moderrs.mk:49
make: Unfinished modifier after "...}", expecting "@"
while evaluating variable "UNDEF" with value "1 2 3"
in command "@echo ${UNDEF:U1 2 3:@var@...}"
in target "unfinished-loop-2"
in target "unfinished-loop-2" from moderrs.mk:52
1 2 3
make: Unclosed expression, expecting "}" for modifier "@var@${var}}...@"
while evaluating variable "UNDEF" with value "1}... 2}... 3}..."
in command "@echo ${UNDEF:U1 2 3:@var@${var}}...@"
in target "loop-close-1"
in target "loop-close-1" from moderrs.mk:64
1}... 2}... 3}...
make: Unfinished modifier after "}", expecting "]"
while evaluating variable "UNDEF" with value "1 2 3"
in command "@echo ${UNDEF:U1 2 3:[}"
in target "words-1"
in target "words-1" from moderrs.mk:70
make: Unfinished modifier after "#}", expecting "]"
while evaluating variable "UNDEF" with value "1 2 3"
in command "@echo ${UNDEF:U1 2 3:[#}"
in target "words-2"
in target "words-2" from moderrs.mk:73
13=
make: Invalid modifier ":[123451234512345123451234512345]"
while evaluating variable "UNDEF" with value "1 2 3"
in command "@echo 12345=${UNDEF:U1 2 3:[123451234512345123451234512345]:S,^$,ok,:S,^3$,ok,}"
in target "words-3"
in target "words-3" from moderrs.mk:96
make: Unfinished modifier after "echo}", expecting "!"
while evaluating variable "VARNAME" with value ""
in command "@echo ${VARNAME:!echo}"
in target "exclam-1"
in target "exclam-1" from moderrs.mk:100
make: Unfinished modifier after "=exclam}", expecting "!"
while evaluating variable "!" with value "!"
in command "@echo ${!:L:!=exclam}"
in target "exclam-2"
in target "exclam-2" from moderrs.mk:107
make: Missing delimiter for modifier ":S"
while evaluating variable "VAR" with value "TheVariable"
in command "@echo 1: ${VAR:S"
in target "mod-subst-delimiter-1"
in target "mod-subst-delimiter-1" from moderrs.mk:111
make: Unfinished modifier after "", expecting ","
while evaluating variable "VAR" with value "TheVariable"
in command "@echo 2: ${VAR:S,"
in target "mod-subst-delimiter-2"
in target "mod-subst-delimiter-2" from moderrs.mk:114
make: Unfinished modifier after "from", expecting ","
while evaluating variable "VAR" with value "TheVariable"
in command "@echo 3: ${VAR:S,from"
in target "mod-subst-delimiter-3"
in target "mod-subst-delimiter-3" from moderrs.mk:117
make: Unfinished modifier after "", expecting ","
while evaluating variable "VAR" with value "TheVariable"
in command "@echo 4: ${VAR:S,from,"
in target "mod-subst-delimiter-4"
in target "mod-subst-delimiter-4" from moderrs.mk:120
make: Unfinished modifier after "to", expecting ","
while evaluating variable "VAR" with value "TheVariable"
in command "@echo 5: ${VAR:S,from,to"
in target "mod-subst-delimiter-5"
in target "mod-subst-delimiter-5" from moderrs.mk:123
make: Unclosed expression, expecting "}" for modifier "S,from,to,"
while evaluating variable "VAR" with value "TheVariable"
in command "@echo 6: ${VAR:S,from,to,"
in target "mod-subst-delimiter-6"
in target "mod-subst-delimiter-6" from moderrs.mk:126
7: TheVariable
make: Missing delimiter for modifier ":C"
while evaluating variable "VAR" with value "TheVariable"
in command "@echo 1: ${VAR:C"
in target "mod-regex-delimiter-1"
in target "mod-regex-delimiter-1" from moderrs.mk:132
make: Unfinished modifier after "", expecting ","
while evaluating variable "VAR" with value "TheVariable"
in command "@echo 2: ${VAR:C,"
in target "mod-regex-delimiter-2"
in target "mod-regex-delimiter-2" from moderrs.mk:135
make: Unfinished modifier after "from", expecting ","
while evaluating variable "VAR" with value "TheVariable"
in command "@echo 3: ${VAR:C,from"
in target "mod-regex-delimiter-3"
in target "mod-regex-delimiter-3" from moderrs.mk:138
make: Unfinished modifier after "", expecting ","
while evaluating variable "VAR" with value "TheVariable"
in command "@echo 4: ${VAR:C,from,"
in target "mod-regex-delimiter-4"
in target "mod-regex-delimiter-4" from moderrs.mk:141
make: Unfinished modifier after "to", expecting ","
while evaluating variable "VAR" with value "TheVariable"
in command "@echo 5: ${VAR:C,from,to"
in target "mod-regex-delimiter-5"
in target "mod-regex-delimiter-5" from moderrs.mk:144
make: Unclosed expression, expecting "}" for modifier "C,from,to,"
while evaluating variable "VAR" with value "TheVariable"
in command "@echo 6: ${VAR:C,from,to,"
in target "mod-regex-delimiter-6"
in target "mod-regex-delimiter-6" from moderrs.mk:147
7: TheVariable
112358132134
15152535558513521534
make: Unknown modifier ":ts\65oct"
while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34"
in command "@echo ${FIB:ts\65oct} # bad modifier"
in target "mod-ts-parse-3"
in target "mod-ts-parse-3" from moderrs.mk:157
make: Unknown modifier ":ts\65oct"
while evaluating "${:U${FIB}:ts\65oct} # bad modifier, variable name is """ with value "1 1 2 3 5 8 13 21 34"
in command "@echo ${:U${FIB}:ts\65oct} # bad modifier, variable name is """
in target "mod-ts-parse-4"
in target "mod-ts-parse-4" from moderrs.mk:160
make: Unknown modifier ":tsxy"
while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34"
in command "@echo ${FIB:tsxy} # modifier too long"
in target "mod-ts-parse-5"
in target "mod-ts-parse-5" from moderrs.mk:163
make: Unknown modifier ":t"
while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34"
in command "@echo ${FIB:t"
in target "mod-t-parse-1"
in target "mod-t-parse-1" from moderrs.mk:167
make: Unknown modifier ":txy"
while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34"
in command "@echo ${FIB:txy}"
in target "mod-t-parse-2"
in target "mod-t-parse-2" from moderrs.mk:170
make: Unknown modifier ":t"
while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34"
in command "@echo ${FIB:t}"
in target "mod-t-parse-3"
in target "mod-t-parse-3" from moderrs.mk:173
make: Unknown modifier ":t"
while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34"
in command "@echo ${FIB:t:M*}"
in target "mod-t-parse-4"
in target "mod-t-parse-4" from moderrs.mk:176
make: Unfinished modifier after "", expecting ":"
while evaluating then-branch of condition "FIB"
in command "@echo ${FIB:?"
in target "mod-ifelse-parse-1"
in target "mod-ifelse-parse-1" from moderrs.mk:180
make: Unfinished modifier after "then", expecting ":"
while evaluating then-branch of condition "FIB"
in command "@echo ${FIB:?then"
in target "mod-ifelse-parse-2"
in target "mod-ifelse-parse-2" from moderrs.mk:183
make: Unfinished modifier after "", expecting "}"
while evaluating else-branch of condition "FIB"
in command "@echo ${FIB:?then:"
in target "mod-ifelse-parse-3"
in target "mod-ifelse-parse-3" from moderrs.mk:186
make: Unfinished modifier after "else", expecting "}"
while evaluating else-branch of condition "FIB"
in command "@echo ${FIB:?then:else"
in target "mod-ifelse-parse-4"
in target "mod-ifelse-parse-4" from moderrs.mk:189
then
1 1 2 3 5 8 13 21 34
make: Unknown modifier ":__"
while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34"
in command "@echo ${FIB:__} # modifier name too long"
in target "mod-remember-parse"
in target "mod-remember-parse" from moderrs.mk:196
make: Unknown modifier ":3"
while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34"
in command "@echo ${FIB:3"
in target "mod-sysv-parse-1"
in target "mod-sysv-parse-1" from moderrs.mk:200
make: Unfinished modifier after "", expecting "}"
while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34"
in command "@echo ${FIB:3="
in target "mod-sysv-parse-2"
in target "mod-sysv-parse-2" from moderrs.mk:203
make: Unfinished modifier after "x3", expecting "}"
while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34"
in command "@echo ${FIB:3=x3"
in target "mod-sysv-parse-3"
in target "mod-sysv-parse-3" from moderrs.mk:206
1 1 2 x3 5 8 1x3 21 34
exit status 2
+4 -2
View File
@@ -1,4 +1,4 @@
# $NetBSD: opt-chdir.mk,v 1.7 2024/04/02 11:11:00 rillig Exp $
# $NetBSD: opt-chdir.mk,v 1.8 2026/02/10 21:22:13 sjg Exp $
#
# Tests for the -C command line option, which changes the directory at the
# beginning.
@@ -13,8 +13,10 @@ all: chdir-nonexistent
# Changing to another directory is possible via the command line.
# In this test, it is the root directory since almost any other directory
# is not guaranteed to exist on every platform.
# Force MAKEOBJDIRPREFIX=/ to avoid looking elsewhere for .OBJDIR
chdir-root: .PHONY .IGNORE
@MAKE_OBJDIR_CHECK_WRITABLE=no ${MAKE} -C / -V 'cwd: $${.CURDIR}'
@MAKE_OBJDIR_CHECK_WRITABLE=no MAKEOBJDIRPREFIX=/ \
${MAKE} -C / -V 'cwd: $${.CURDIR}'
# Trying to change to a nonexistent directory exits immediately.
# Note: just because the whole point of /nonexistent is that it should
+1
View File
@@ -29,6 +29,7 @@
.MAKE.OS = <details omitted>
.MAKE.PID = <details omitted>
.MAKE.PPID = <details omitted>
.MAKE.SAVE_DOLLARS = <details omitted>
.MAKE.UID = <details omitted>
.MAKEFLAGS = -r -k -d g1
.MAKEOVERRIDES = # (empty)
+1
View File
@@ -63,6 +63,7 @@ all : made-target error-target aborted-target
.MAKE.OS = <details omitted>
.MAKE.PID = <details omitted>
.MAKE.PPID = <details omitted>
.MAKE.SAVE_DOLLARS = <details omitted>
.MAKE.UID = <details omitted>
.MAKEFLAGS = -r -k -d g2
.MAKEOVERRIDES = # (empty)
+1
View File
@@ -63,6 +63,7 @@ all : made-target error-target aborted-target
.MAKE.OS = <details omitted>
.MAKE.PID = <details omitted>
.MAKE.PPID = <details omitted>
.MAKE.SAVE_DOLLARS = <details omitted>
.MAKE.UID = <details omitted>
.MAKEFLAGS = -r -k -d g3
.MAKEOVERRIDES = # (empty)
+1
View File
@@ -1,6 +1,7 @@
job_pipe -1 -1, maxjobs 1, tokens 1, compat 0
TokenPool_Take: pid <pid>, aborting NONE, running 0
TokenPool_Take: pid <pid> took a token
MaybeSubMake: Looking for "make"
echo ": expanded expression"
{ : expanded expression
} || exit $?
+4 -4
View File
@@ -3,12 +3,12 @@ make: error: invalid internal option "-J garbage" in "<curdir>"
make: warning: Invalid internal option "-J" in "<curdir>"; see the manual page
in make[2] in directory "<curdir>"
direct-open: mode=compat
make: warning: Invalid internal option "-J" in "<curdir>"; see the manual page
in make[2] in directory "<curdir>"
.make[2]: warning: Invalid internal option "-J" in "<curdir>"; see the manual page
in .make[2] in directory "<curdir>"
indirect-open: mode=compat
indirect-expr: mode=parallel
make: warning: Invalid internal option "-J" in "<curdir>"; see the manual page
in make[2] in directory "<curdir>"
.make[2]: warning: Invalid internal option "-J" in "<curdir>"; see the manual page
in .make[2] in directory "<curdir>"
indirect-comment: mode=compat
indirect-silent-comment: mode=parallel
indirect-expr-empty: mode=parallel
+17 -10
View File
@@ -1,9 +1,12 @@
# $NetBSD: opt-jobs-internal.mk,v 1.6 2025/05/23 21:05:56 rillig Exp $
# $NetBSD: opt-jobs-internal.mk,v 1.10 2026/03/10 05:02:00 sjg Exp $
#
# Tests for the (intentionally undocumented) internal -J command line option.
.if ${DEBUG_TEST:U:M${.PARSEFILE:R}} != ""
.MAKEFLAGS: -djg2
.endif
# This test expects
.MAKE.ALWAYS_PASS_JOB_QUEUE= no
_make ?= .make${.MAKE.PID}
.export _make
all: .PHONY
@${MAKE} -f ${MAKEFILE} -j1 direct
@@ -14,6 +17,7 @@ all: .PHONY
@${MAKE} -f ${MAKEFILE} -j1 indirect-comment
@${MAKE} -f ${MAKEFILE} -j1 indirect-silent-comment
@${MAKE} -f ${MAKEFILE} -j1 indirect-expr-empty
@rm -f ${_make}
detect-mode: .PHONY
@mode=parallel
@@ -33,8 +37,8 @@ direct-open: .PHONY
@${MAKE} -f ${MAKEFILE} -J 31,32 detect-mode HEADING=${.TARGET}
# expect: indirect-open: mode=compat
indirect-open: .PHONY
@${MAKE:U} -f ${MAKEFILE} detect-mode HEADING=${.TARGET}
indirect-open: .PHONY ${_make}
@./${_make} -f ${MAKEFILE} detect-mode HEADING=${.TARGET}
# When a command in its unexpanded form contains the expression "${MAKE}"
# without any modifiers, the file descriptors get passed around.
@@ -45,9 +49,9 @@ indirect-expr: .PHONY
# The "# make" comment starts directly after the leading tab and is thus not
# considered a shell command line. No file descriptors are passed around.
# expect: indirect-comment: mode=compat
indirect-comment: .PHONY
indirect-comment: .PHONY ${_make}
# make
@${MAKE:U} -f ${MAKEFILE} detect-mode HEADING=${.TARGET}
@./${_make} -f ${MAKEFILE} detect-mode HEADING=${.TARGET}
# When the "# make" comment is prefixed with "@", it becomes a shell command.
# As that shell command contains the plain word "make", the file descriptors
@@ -57,9 +61,12 @@ indirect-silent-comment: .PHONY
@# make
@${MAKE:U} -f ${MAKEFILE} detect-mode HEADING=${.TARGET}
# When a command in its unexpanded form contains the plain word "make", the
# file descriptors get passed around.
# expect: indirect-expr-empty: mode=parallel
indirect-expr-empty: .PHONY
@${:D make}
@${MAKE:U} -f ${MAKEFILE} detect-mode HEADING=${.TARGET}
${_make}:
@ln -s ${MAKE} ${.TARGET}
# This test expects
.MAKE.ALWAYS_PASS_JOB_QUEUE= no
+4 -2
View File
@@ -1,4 +1,4 @@
# $NetBSD: opt-where-am-i.mk,v 1.4 2022/01/27 02:24:46 sjg Exp $
# $NetBSD: opt-where-am-i.mk,v 1.5 2026/02/10 22:33:36 sjg Exp $
#
# Tests for the -w command line option, which outputs the current directory
# at the beginning and end of running make. This is useful when building
@@ -6,9 +6,11 @@
# The first "Entering directory" is missing since the below .MAKEFLAGS comes
# too late for it.
# We force MAKEOBJDIRPREFIX=/ to avoid looking elsewhere for .OBJDIR
.MAKEFLAGS: -w
all:
.if ${.CURDIR} != "/"
@MAKE_OBJDIR_CHECK_WRITABLE=no ${MAKE} -r -f ${MAKEFILE:tA} -C /
@MAKE_OBJDIR_CHECK_WRITABLE=no MAKEOBJDIRPREFIX=/ \
${MAKE} -r -f ${MAKEFILE:tA} -C /
.endif
+8 -6
View File
@@ -1,11 +1,12 @@
make -r -f /dev/null -V MAKEFLAGS
-r -k -d 0
make -r -f /dev/null -V 'begin ${MAKEFLAGS} end'
begin -r -k -d 0 end
make -:
usage: make [-BeikNnqrSstWwX]
[-C directory] [-D variable] [-d flags] [-f makefile]
[-I directory] [-J private] [-j max_jobs] [-m directory] [-T file]
[-V variable] [-v variable] [variable=value] [target ...]
[-I directory] [-J private] [-j max_jobs] [-m directory]
[-T file] [-V variable] [-v variable]
[variable=value ...] [target ...]
*** Error code 2 (ignored)
make -r -f /dev/null -- -VAR=value -f /dev/null
@@ -19,8 +20,9 @@ make: stopped making "-f /dev/null" in unit-tests
make -?
usage: make [-BeikNnqrSstWwX]
[-C directory] [-D variable] [-d flags] [-f makefile]
[-I directory] [-J private] [-j max_jobs] [-m directory] [-T file]
[-V variable] [-v variable] [variable=value] [target ...]
[-I directory] [-J private] [-j max_jobs] [-m directory]
[-T file] [-V variable] [-v variable]
[variable=value ...] [target ...]
*** Error code 2 (ignored)
exit status 0
+2 -2
View File
@@ -1,4 +1,4 @@
# $NetBSD: opt.mk,v 1.7 2023/02/25 00:07:08 rillig Exp $
# $NetBSD: opt.mk,v 1.8 2026/02/08 11:02:03 rillig Exp $
#
# Tests for the command line options.
@@ -8,7 +8,7 @@ all: .IGNORE
# The options from the top-level make are passed to the sub-makes via
# the environment variable MAKEFLAGS. This is where the " -r -k -d 0"
# comes from. See MainParseOption.
${MAKE} -r -f /dev/null -V MAKEFLAGS
${MAKE} -r -f /dev/null -V 'begin $${MAKEFLAGS} end'
@echo
# Just to see how the custom argument parsing code reacts to a syntax
+1
View File
@@ -1,6 +1,7 @@
job_pipe -1 -1, maxjobs 1, tokens 1, compat 0
TokenPool_Take: pid <pid>, aborting NONE, running 0
TokenPool_Take: pid <pid> took a token
MaybeSubMake: Looking for "make"
# echo off
echo silent
# echo on
+1
View File
@@ -94,6 +94,7 @@ ParseDependency(.MAKEFLAGS: -d0 -dg1)
.MAKE.OS = <details omitted>
.MAKE.PID = <details omitted>
.MAKE.PPID = <details omitted>
.MAKE.SAVE_DOLLARS = <details omitted>
.MAKE.UID = <details omitted>
.MAKEFLAGS = -r -k -d mps -d 0 -d g1
.MAKEOVERRIDES = # (empty)
+1
View File
@@ -20,6 +20,7 @@
.MAKE.OS = <details omitted>
.MAKE.PID = <details omitted>
.MAKE.PPID = <details omitted>
.MAKE.SAVE_DOLLARS = <details omitted>
.MAKE.UID = <details omitted>
.MAKEFLAGS = -r -k -d g1
.MAKEOVERRIDES = # (empty)
+1 -1
View File
@@ -23,7 +23,7 @@ sub-exit status 1
make: Variable VAR is recursive.
while evaluating variable "VAR" with value "${VAR}"
in command ": recursive-line-before <${VAR}> recursive-line-after"
in target "runtime"
in target "runtime" from var-recursive.mk:56
in make[1] in directory "<curdir>"
sub-exit status 2
exit status 0
+10
View File
@@ -67,5 +67,15 @@ Making var-scope-local-default.o with make 'global' and env 'global'.
Making var-scope-local-subst.o with make 'global+local' and env 'global+local'.
Making var-scope-local-shell.o with make 'output' and env 'output'.
Making .USE var-scope-local-use.o with make 'global' and env 'global'.
begin pr-59073 compat
$@ is pr-59073/file.o59703
$< is pr-59073/file.c59703
$* is pr-59073/file
end pr-59073 compat
begin pr-59073 parallel
$@ is pr-59073/file.o59703
$< is pr-59073/file.c59703
$* is file
end pr-59073 parallel
: all overwritten
exit status 0
+46 -1
View File
@@ -1,4 +1,4 @@
# $NetBSD: var-scope-local.mk,v 1.11 2024/03/05 23:07:58 rillig Exp $
# $NetBSD: var-scope-local.mk,v 1.12 2026/01/05 22:44:14 rillig Exp $
#
# Tests for target-local variables, such as ${.TARGET} or $@. These variables
# are relatively short-lived as they are created just before making the
@@ -138,7 +138,9 @@ dir/subdir/inference-rule-chain.ir-gen-from: .PHONY
# Custom local variables
#
# Additional target-local variables may be defined in dependency lines.
.if !make(pr-59703-mode)
.MAKEFLAGS: -dv
.endif
# In the following line, the ':=' may either be interpreted as an assignment
# operator or as the dependency operator ':', followed by an empty variable
# name and the assignment operator '='. It is the latter since in an
@@ -154,7 +156,9 @@ one two:=three
# word.
# expect: Global: one two = three
${:Uone two}:=three
.if !make(pr-59703-mode)
.MAKEFLAGS: -d0
.endif
.SUFFIXES: .c .o
@@ -268,3 +272,44 @@ a_use: .USE VAR=use
all: var-scope-local-use.o
var-scope-local-use.o: a_use
# begin https://gnats.netbsd.org/59073
# make(1) sets $* / $(.PREFIX) wrong in -j mode
all: pr-59073
# expect: begin pr-59073 compat
# expect: $@ is pr-59073/file.o59703
# expect: $< is pr-59073/file.c59703
# expect: $* is pr-59073/file
# expect: end pr-59073 compat
# expect: begin pr-59073 parallel
# expect: $@ is pr-59073/file.o59703
# expect: $< is pr-59073/file.c59703
# FIXME: The subdirectory is missing.
# expect: $* is file
# expect: end pr-59073 parallel
pr-59073: .PHONY
# This has to be an actual file; using a memory-only target
# generates the correct value for "$*".
@mkdir -p pr-59073 && touch pr-59073/file.c59703
@echo begin pr-59073 compat
@MAKEFLAGS= ${MAKE} -r -f ${MAKEFILE} pr-59703-mode
@echo end pr-59073 compat
@echo begin pr-59073 parallel
@MAKEFLAGS= ${MAKE} -r -f ${MAKEFILE} -j1 pr-59703-mode
@echo end pr-59073 parallel
@rm -rf pr-59073
pr-59703-mode: pr-59073/file.o59703
.SUFFIXES: .c59703 .o59703
.c59703.o59703:
@echo '$$@ is $@'
@echo '$$< is $<'
@echo '$$* is $*'
# end https://gnats.netbsd.org/59073
+9 -9
View File
@@ -46,36 +46,36 @@ parse-dynamic: parse-dynamic parse-dynamic after
varerror-unclosed-1:begin
make: Unclosed variable ""
in command "@echo $("
in target "varerror-unclosed-2"
in target "varerror-unclosed-2" from varmisc.mk:195
make: Unclosed variable "UNCLOSED"
in command "@echo $(UNCLOSED"
in target "varerror-unclosed-3"
in target "varerror-unclosed-3" from varmisc.mk:198
make: Unclosed variable "UNCLOSED"
in command "@echo ${UNCLOSED"
in target "varerror-unclosed-4"
in target "varerror-unclosed-4" from varmisc.mk:201
make: Unclosed variable "PATTERN"
while evaluating variable "UNCLOSED" with value ""
in command "@echo ${UNCLOSED:M${PATTERN"
in target "varerror-unclosed-5"
in target "varerror-unclosed-5" from varmisc.mk:204
make: Unclosed expression, expecting "}" for modifier "M${PATTERN"
while evaluating variable "UNCLOSED" with value ""
in command "@echo ${UNCLOSED:M${PATTERN"
in target "varerror-unclosed-5"
in target "varerror-unclosed-5" from varmisc.mk:204
make: Unclosed variable "param"
in command "@echo ${UNCLOSED.${param"
in target "varerror-unclosed-6"
in target "varerror-unclosed-6" from varmisc.mk:208
make: Unclosed variable "UNCLOSED."
in command "@echo ${UNCLOSED.${param"
in target "varerror-unclosed-6"
in target "varerror-unclosed-6" from varmisc.mk:208
make: Unclosed variable "UNCLOSED.1"
in command "@echo ${UNCLOSED.${:U1}"
in target "varerror-unclosed-7"
in target "varerror-unclosed-7" from varmisc.mk:213
make: Unclosed variable "UNCLOSED_ORIG"
while evaluating variable "UNCLOSED_INDIR_1" with value "${UNCLOSED_ORIG"
while evaluating variable "UNCLOSED_INDIR_2" with value "${UNCLOSED_INDIR_1}"
in command "@echo ${UNCLOSED_INDIR_2}"
in target "varerror-unclosed-8"
in target "varerror-unclosed-8" from varmisc.mk:217
target1-flags: we have: one two
target2-flags: we have: one two three four
exit status 2
+6 -6
View File
@@ -40,30 +40,30 @@ Global: .MAKEFLAGS = -r -k -d v -d 0 -d v -d 0
make: Invalid attempt to assign "value" to variable "" via modifier "::="
while evaluating "${::=value}" with value ""
in command "@echo $@: ${::=value}"
in target "mod-assign-empty-1"
in target "mod-assign-empty-1" from varmod-assign.mk:78
make: Invalid attempt to assign "overwritten" to variable "" via modifier "::="
while evaluating "${:Uvalue::=overwritten}" with value "value"
in command "@echo $@: ${:Uvalue::=overwritten}"
in target "mod-assign-empty-2"
in target "mod-assign-empty-2" from varmod-assign.mk:84
make: Invalid attempt to assign "appended" to variable "" via modifier "::+="
while evaluating "${:Uvalue::+=appended}" with value "value"
in command "@echo $@: ${:Uvalue::+=appended}"
in target "mod-assign-empty-3"
in target "mod-assign-empty-3" from varmod-assign.mk:90
mod-assign-empty-4: VAR=overwritten
make: Unknown modifier "::x"
while evaluating variable "ASSIGN" with value ""
in command "@echo ${ASSIGN::x}"
in target "mod-assign-parse-1"
in target "mod-assign-parse-1" from varmod-assign.mk:103
sysv:y
make: Unfinished modifier after "value # missing closing brace", expecting "}"
while evaluating variable "ASSIGN" with value ""
in command "@echo ${ASSIGN::=value # missing closing brace"
in target "mod-assign-parse-3"
in target "mod-assign-parse-3" from varmod-assign.mk:112
ok=word
make: warning: Command " echo word; (exit 13) " exited with status 13
while evaluating variable "SH_ERR" with value "previous"
in command "@${SH_ERR::!= echo word; (exit 13) } echo err=${SH_ERR}"
in target "mod-assign-shell-error"
in target "mod-assign-shell-error" from varmod-assign.mk:120
err=previous
Command: TARGET_CMD_VAR = cmd-value
Global: TARGET_GLOBAL_VAR = global-value
+3 -3
View File
@@ -1,15 +1,15 @@
make: Unknown modifier ":has"
while evaluating variable "12345" with value "12345"
in command "@echo ${12345:L:has} # modifier name too short"
in target "step-1"
in target "step-1" from varmod-hash.mk:61
26bb0f5f
12345
make: Unknown modifier ":hasX"
while evaluating variable "12345" with value "12345"
in command "@echo ${12345:L:hasX} # misspelled"
in target "step-4"
in target "step-4" from varmod-hash.mk:67
make: Unknown modifier ":hashed"
while evaluating variable "12345" with value "12345"
in command "@echo ${12345:L:hashed} # modifier name too long"
in target "step-5"
in target "step-5" from varmod-hash.mk:69
exit status 2
+9 -3
View File
@@ -1,6 +1,12 @@
make: varmod-loop-delete.mk:20: Cannot delete variable "VAR" while it is used
make -f varmod-loop-delete.mk delete-active-variable || true
make: varmod-loop-delete.mk:31: Cannot delete variable "VAR" while it is used
while evaluating "${:U:@VAR@@} rest of the value" with value ""
while evaluating variable "VAR" with value "${:U:@VAR@@} rest of the value"
in make[1] in directory "<curdir>"
make: Fatal errors encountered -- cannot continue
make: stopped making "all" in unit-tests
exit status 1
make: stopped making "delete-active-variable" in unit-tests
make -f varmod-loop-delete.mk delete-active-variable-in-target || true
: delete-active-variable-in-target: ' rest of the value'
exit status 0
+44 -4
View File
@@ -1,4 +1,4 @@
# $NetBSD: varmod-loop-delete.mk,v 1.7 2024/08/29 20:20:36 rillig Exp $
# $NetBSD: varmod-loop-delete.mk,v 1.9 2026/02/09 22:04:54 rillig Exp $
#
# Tests for the variable modifier ':@', which as a side effect allows to
# delete an arbitrary variable.
@@ -11,6 +11,17 @@
#
# See Var_Parse, comment 'the value of the variable must not change'.
all: .PHONY
${MAKE} -f ${MAKEFILE} delete-active-variable || true
@echo
${MAKE} -f ${MAKEFILE} delete-active-variable-in-target || true
@echo
# Disabled since the details of the crash depend on the execution
# environment.
#${MAKE} -f ${MAKEFILE} use-after-free
delete-active-variable: .PHONY
.if make(delete-active-variable)
# Set up the variable that deletes itself when it is evaluated.
VAR= ${:U:@VAR@@} rest of the value
@@ -18,12 +29,16 @@ VAR= ${:U:@VAR@@} rest of the value
# defined in the global scope, it deletes itself.
# expect+1: Cannot delete variable "VAR" while it is used
EVAL:= ${VAR}
.if ${EVAL} != " rest of the value"
. error
. if ${EVAL} != " rest of the value"
. error
. endif
.endif
delete-active-variable-in-target: .PHONY
.if make(delete-active-variable-in-target)
VAR= ${:U:@VAR@@} rest of the value
all: .PHONY
delete-active-variable-in-target:
# In the command that is associated with a target, the scope is the
# one from the target. That scope only contains a few variables like
# '.TARGET', '.ALLSRC', '.IMPSRC'. Make does not expect that these
@@ -32,3 +47,28 @@ all: .PHONY
# There is no variable named 'VAR' in the local scope, so nothing
# happens.
: $@: '${VAR}'
# expect: : delete-active-variable-in-target: ' rest of the value'
.endif
# On NetBSD 11.99.x with jemalloc and MALLOC_CONF=junk:true, the output is:
# make: varmod-loop-delete.mk:72: Unknown modifier ":Z2"
# while evaluating "${:U 333 :@v@...${:Z1}@:Z2}" with value "...${:Z1}"
# while evaluating variable "INNER.1" with value "${:U 333 :@v@...${:Z1}@:Z2}"
# while evaluating variable "ZZZZZZZZZZZZ...${:Z1}" with value "ZZZZZZZZ"
# while evaluating "${:U 111 222 :@v@${v:S,^,${INNER.1},}@}" with value " 111 222 "
# while evaluating variable "OUTER" with value "${:U 111 222 :@v@${v:S,^,${INNER.1},}@}"
# in make in directory "<curdir>"
# Modifier part: ""
# ModifyWords: split "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" into 1 word
# Result of ${ZZZZZZZZZZZZ:S,^,${INNER.1},} is "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" (eval-keep-undefined, regular)
# Segmentation fault (core dumped)
use-after-free: .PHONY
.if make(use-after-free)
OUTER= ${:U 111 222 :@v@${v:S,^,${INNER.1},}@}
INNER.1= ${:U 333 :@v@...${:Z1}@:Z2}
.MAKEFLAGS: -dcpv
_:= ${OUTER}
.MAKEFLAGS: -d0
.endif
+12 -12
View File
@@ -1,7 +1,7 @@
make: Invalid modifier ":[]"
while evaluating variable "LIST" with value "one two three four five six"
in command "@echo 'LIST:[]="${LIST:[]}" is an error'"
in target "mod-squarebrackets-empty"
in target "mod-squarebrackets-empty" from varmod-select-words.mk:54
LIST:[0]="one two three four five six"
LIST:[0x0]="one two three four five six"
LIST:[000]="one two three four five six"
@@ -42,11 +42,11 @@ LIST:[1]="one"
make: Invalid modifier ":[1.]"
while evaluating variable "LIST" with value "one two three four five six"
in command "@echo 'LIST:[1.]="${LIST:[1.]}" is an error'"
in target "mod-squarebrackets-n-error-1"
in target "mod-squarebrackets-n-error-1" from varmod-select-words.mk:100
make: Extra text after "[1]"
while evaluating variable "LIST" with value "one two three four five six"
in command "@echo 'LIST:[1].="${LIST:[1].}" is an error'"
in target "mod-squarebrackets-n-error-2"
in target "mod-squarebrackets-n-error-2" from varmod-select-words.mk:103
LIST:[2]="two"
LIST:[6]="six"
LIST:[7]=""
@@ -54,11 +54,11 @@ LIST:[999]=""
make: Invalid modifier ":[-]"
while evaluating variable "LIST" with value "one two three four five six"
in command "@echo 'LIST:[-]="${LIST:[-]}" is an error'"
in target "mod-squarebrackets-n-error-3"
in target "mod-squarebrackets-n-error-3" from varmod-select-words.mk:111
make: Invalid modifier ":[--]"
while evaluating variable "LIST" with value "one two three four five six"
in command "@echo 'LIST:[--]="${LIST:[--]}" is an error'"
in target "mod-squarebrackets-n-error-4"
in target "mod-squarebrackets-n-error-4" from varmod-select-words.mk:114
LIST:[-1]="six"
LIST:[-2]="five"
LIST:[-6]="one"
@@ -80,20 +80,20 @@ LONGLIST:[012..0x12]="10 11 12 13 14 15 16 17 18"
make: Invalid modifier ":[1.]"
while evaluating variable "LIST" with value "one two three four five six"
in command "@echo 'LIST:[1.]="${LIST:[1.]}" is an error'"
in target "mod-squarebrackets-start-end-error-1"
in target "mod-squarebrackets-start-end-error-1" from varmod-select-words.mk:137
make: Invalid modifier ":[1..]"
while evaluating variable "LIST" with value "one two three four five six"
in command "@echo 'LIST:[1..]="${LIST:[1..]}" is an error'"
in target "mod-squarebrackets-start-end-error-2"
in target "mod-squarebrackets-start-end-error-2" from varmod-select-words.mk:140
make: Invalid modifier ":[1.. ]"
while evaluating variable "LIST" with value "one two three four five six"
in command "@echo 'LIST:[1.. ]="${LIST:[1.. ]}" is an error'"
in target "mod-squarebrackets-start-end-error-3"
in target "mod-squarebrackets-start-end-error-3" from varmod-select-words.mk:143
LIST:[1..1]="one"
make: Invalid modifier ":[1..1.]"
while evaluating variable "LIST" with value "one two three four five six"
in command "@echo 'LIST:[1..1.]="${LIST:[1..1.]}" is an error'"
in target "mod-squarebrackets-start-end-error-4"
in target "mod-squarebrackets-start-end-error-4" from varmod-select-words.mk:148
LIST:[1..2]="one two"
LIST:[2..1]="two one"
LIST:[3..-2]="three four five"
@@ -101,11 +101,11 @@ LIST:[-4..4]="three four"
make: Invalid modifier ":[0..1]"
while evaluating variable "LIST" with value "one two three four five six"
in command "@echo 'LIST:[0..1]="${LIST:[0..1]}" is an error'"
in target "mod-squarebrackets-start-end-error-5"
in target "mod-squarebrackets-start-end-error-5" from varmod-select-words.mk:156
make: Invalid modifier ":[-1..0]"
while evaluating variable "LIST" with value "one two three four five six"
in command "@echo 'LIST:[-1..0]="${LIST:[-1..0]}" is an error'"
in target "mod-squarebrackets-start-end-error-6"
in target "mod-squarebrackets-start-end-error-6" from varmod-select-words.mk:159
LIST:[-1..1]="six five four three two one"
LIST:[0..0]="one two three four five six"
LIST:[3..99]="three four five six"
@@ -122,7 +122,7 @@ LIST:[${AT}]="one two three four five six"
make: Invalid modifier ":[]"
while evaluating variable "LIST" with value "one two three four five six"
in command "@echo 'LIST:[$${EMPTY}]="${LIST:[${EMPTY}]}" is an error'"
in target "mod-squarebrackets-nested-error-1"
in target "mod-squarebrackets-nested-error-1" from varmod-select-words.mk:178
LIST:[${LONGLIST:[21]:S/2//}]="one"
LIST:[${LIST:[#]}]="six"
LIST:[${LIST:[${HASH}]}]="six"
+15 -15
View File
@@ -1,67 +1,67 @@
make: Regex compilation error: (details omitted)
while evaluating "${:Uword1 word2:C,****,____,g:C,word,____,:Q}." with value "word1 word2"
in command "@echo $@: ${:Uword1 word2:C,****,____,g:C,word,____,:Q}."
in target "mod-regex-compile-error"
in target "mod-regex-compile-error" from varmod-subst-regex.mk:154
make: No subexpression \1
while evaluating "${:U1 23 456:C,..,\1\1,:Q}" with value "1 23 456"
in command "@echo $@:11-missing:${:U1 23 456:C,..,\1\1,:Q}"
in target "mod-regex-limits-1"
in target "mod-regex-limits-1" from varmod-subst-regex.mk:159
make: No subexpression \1
while evaluating "${:U1 23 456:C,..,\1\1,:Q}" with value "1 23 456"
in command "@echo $@:11-missing:${:U1 23 456:C,..,\1\1,:Q}"
in target "mod-regex-limits-1"
in target "mod-regex-limits-1" from varmod-subst-regex.mk:159
make: No subexpression \1
while evaluating "${:U1 23 456:C,..,\1\1,:Q}" with value "1 23 456"
in command "@echo $@:11-missing:${:U1 23 456:C,..,\1\1,:Q}"
in target "mod-regex-limits-1"
in target "mod-regex-limits-1" from varmod-subst-regex.mk:159
make: No subexpression \1
while evaluating "${:U1 23 456:C,..,\1\1,:Q}" with value "1 23 456"
in command "@echo $@:11-missing:${:U1 23 456:C,..,\1\1,:Q}"
in target "mod-regex-limits-1"
in target "mod-regex-limits-1" from varmod-subst-regex.mk:159
mod-regex-limits-2:11-ok:1 22 446
make: No subexpression \2
while evaluating "${:U1 23 456:C,..,\2\2,:Q}" with value "1 23 456"
in command "@echo $@:22-missing:${:U1 23 456:C,..,\2\2,:Q}"
in target "mod-regex-limits-3"
in target "mod-regex-limits-3" from varmod-subst-regex.mk:163
make: No subexpression \2
while evaluating "${:U1 23 456:C,..,\2\2,:Q}" with value "1 23 456"
in command "@echo $@:22-missing:${:U1 23 456:C,..,\2\2,:Q}"
in target "mod-regex-limits-3"
in target "mod-regex-limits-3" from varmod-subst-regex.mk:163
make: No subexpression \2
while evaluating "${:U1 23 456:C,..,\2\2,:Q}" with value "1 23 456"
in command "@echo $@:22-missing:${:U1 23 456:C,..,\2\2,:Q}"
in target "mod-regex-limits-3"
in target "mod-regex-limits-3" from varmod-subst-regex.mk:163
make: No subexpression \2
while evaluating "${:U1 23 456:C,..,\2\2,:Q}" with value "1 23 456"
in command "@echo $@:22-missing:${:U1 23 456:C,..,\2\2,:Q}"
in target "mod-regex-limits-3"
in target "mod-regex-limits-3" from varmod-subst-regex.mk:163
make: No subexpression \2
while evaluating "${:U1 23 456:C,(.).,\2\2,:Q}" with value "1 23 456"
in command "@echo $@:22-missing:${:U1 23 456:C,(.).,\2\2,:Q}"
in target "mod-regex-limits-4"
in target "mod-regex-limits-4" from varmod-subst-regex.mk:165
make: No subexpression \2
while evaluating "${:U1 23 456:C,(.).,\2\2,:Q}" with value "1 23 456"
in command "@echo $@:22-missing:${:U1 23 456:C,(.).,\2\2,:Q}"
in target "mod-regex-limits-4"
in target "mod-regex-limits-4" from varmod-subst-regex.mk:165
make: No subexpression \2
while evaluating "${:U1 23 456:C,(.).,\2\2,:Q}" with value "1 23 456"
in command "@echo $@:22-missing:${:U1 23 456:C,(.).,\2\2,:Q}"
in target "mod-regex-limits-4"
in target "mod-regex-limits-4" from varmod-subst-regex.mk:165
make: No subexpression \2
while evaluating "${:U1 23 456:C,(.).,\2\2,:Q}" with value "1 23 456"
in command "@echo $@:22-missing:${:U1 23 456:C,(.).,\2\2,:Q}"
in target "mod-regex-limits-4"
in target "mod-regex-limits-4" from varmod-subst-regex.mk:165
mod-regex-limits-5:22-ok:1 33 556
mod-regex-limits-6:capture:ihgfedcbaabcdefghijABCDEFGHIJa0a1a2rest
make: Regex compilation error: (details omitted)
while evaluating variable "UNDEF" with value "value"
in command "@echo $@: ${UNDEF:Uvalue:C,[,,}"
in target "mod-regex-errors-1"
in target "mod-regex-errors-1" from varmod-subst-regex.mk:174
make: Unknown modifier ":Z"
while evaluating "${:U:Z}y,W}" with value ""
while evaluating variable "word" with value "word"
in command "@echo $@: ${word:L:C,.*,x${:U:Z}y,W}"
in target "mod-regex-errors-2"
in target "mod-regex-errors-2" from varmod-subst-regex.mk:179
unmatched-subexpression.ok: one one 2 3 5 8 one3 2one 34
make: No match for subexpression \2
unmatched-subexpression.1: ()()
+31 -16
View File
@@ -1,6 +1,6 @@
# $NetBSD: varmod-subst-regex.mk,v 1.12 2024/07/20 11:05:12 rillig Exp $
# $NetBSD: varmod-subst-regex.mk,v 1.13 2026/01/03 22:40:38 rillig Exp $
#
# Tests for the :C,from,to, variable modifier.
# Tests for the :C,from,to, modifier.
# report unmatched subexpressions
.MAKEFLAGS: -dL
@@ -23,7 +23,7 @@ all: unmatched-subexpression
. error
.endif
# The 'W' modifier treats the whole variable value as a single big word,
# The 'W' modifier treats the whole expression value as a single big word,
# containing whitespace. This big word matches the regular expression,
# therefore it gets replaced. Whitespace is preserved after replacing.
.if ${:Ua b b c:C,a b,,W} != " b c"
@@ -60,14 +60,16 @@ all: unmatched-subexpression
# The modifier '1' applies the replacement at most once, across the whole
# expression value, no matter whether it is a single big word or many small
# words.
#
# Up to 2020-08-28, the manual page said that the modifiers '1' and 'g'
# were orthogonal, which was wrong. It doesn't make sense to specify both
# 'g' and '1' at the same time.
.if ${:U12345 12345:C,.,\0\0,1} != "112345 12345"
. error
.endif
# When both '1' and 'g' are given, this means to replace all occurrences,
# but only in the first word where they are found, not in any remaining words.
.if ${:U 11111 22222 22222 :C,2,0,g1} != "11111 00000 22222"
. error
.endif
# A regular expression that matches the empty string applies before every
# single character of the word.
# XXX: Most other places where regular expression are used match at the end
@@ -129,16 +131,30 @@ all: unmatched-subexpression
.endif
# Just as in the ":S" modifier and the sed(1) utility, an "&" in the
# replacement part stands for the whole matched string. It can be escaped
# using a backslash.
.if ${:U 123 234 345 :C,2,&\&&,} != "12&23 2&234 345"
. error
.endif
# When the ":C" modifier uses "&" as the delimiter for its parts, the "&"
# needs to be escaped. To get a literal "&" in the replacement, it needs
# to be written as "\\\&". When parsing the modifier part, the "\\" and "\&"
# result in "\" and "&", which then form the replacement "\&", and that is
# interpreted as a literal "&".
.if ${:U 123 234 345 :C&2&\&\\\&\&&} != "12&23 2&234 345"
. error
.endif
# Multiple asterisks form an invalid regular expression. This produces an
# error message and (as of 2020-08-28) stops parsing in the middle of the
# expression. The unparsed part of the expression is then copied
# verbatim to the output, which is unexpected and can lead to strange shell
# commands being run.
# error message, and due to this error message, the shell command is not run.
mod-regex-compile-error:
@echo $@: ${:Uword1 word2:C,****,____,g:C,word,____,:Q}.
# These tests generate error messages but as of 2020-08-28 just continue
# parsing and execution as if nothing bad had happened.
# These tests generate error messages for the missing capturing groups.
# Due to these error messages, the echo commands are not executed.
mod-regex-limits-1:
@echo $@:11-missing:${:U1 23 456:C,..,\1\1,:Q}
mod-regex-limits-2:
@@ -158,9 +174,8 @@ mod-regex-errors-1:
@echo $@: ${UNDEF:Uvalue:C,[,,}
mod-regex-errors-2:
# If the replacement pattern produces a parse error because of an
# unknown modifier, the parse error is ignored in ParseModifierPart
# and the faulty expression expands to "".
# If the replacement pattern produces a parse error due to an
# unknown modifier, the faulty expression expands to "".
@echo $@: ${word:L:C,.*,x${:U:Z}y,W}
# In regular expressions with alternatives, not all capturing groups are
+6 -1
View File
@@ -43,12 +43,17 @@ mod-subst-delimiter:
1 two 3 vertical line
1 two 3 right curly bracket
1 two 3 tilde
123 two34 345 circumflex accent
make: Regex compilation error: (details omitted)
while evaluating "${:U 123 234 345 :C^^2^two^:Q} circumflex accent" with value " 123 234 345 "
in command "@echo ${:U 123 234 345 :C^^2^two^:Q} circumflex accent"
in target "mod-subst-delimiter-circumflex" from varmod-subst.mk:250
mod-subst-chain:
A B c.
make: Unknown modifier ":i"
while evaluating "${:Uvalue:S,a,x,i}." with value "vxlue"
in command "@echo ${:Uvalue:S,a,x,i}."
in target "mod-subst-chain"
in target "mod-subst-chain" from varmod-subst.mk:268
mod-subst-dollar:$1:
mod-subst-dollar:$2:
mod-subst-dollar:$3:
+15 -3
View File
@@ -1,9 +1,10 @@
# $NetBSD: varmod-subst.mk,v 1.17 2025/03/29 19:08:53 rillig Exp $
# $NetBSD: varmod-subst.mk,v 1.18 2026/01/03 20:48:35 rillig Exp $
#
# Tests for the :S,from,to, variable modifier.
all: mod-subst
all: mod-subst-delimiter
all: mod-subst-delimiter-circumflex
all: mod-subst-chain
all: mod-subst-dollar
@@ -237,11 +238,22 @@ mod-subst-delimiter:
@echo ${:U1 2 3:S}2}two}:Q} right curly bracket
@echo ${:U1 2 3:S~2~two~:Q} tilde
# When the ":S" modifier uses "^" to separate its parts, and when the first
# part starts with another "^", that "^" is interpreted as an anchor, not as
# the delimiter between the parts.
mod-subst-delimiter-circumflex: .PHONY
@echo ${:U 123 234 345 :S^^2^two^:Q} circumflex accent
# In the ":C" modifier, the "^" is not interpreted as an anchor,
# instead it is interpreted as the delimiter of the regular
# expression, thus making the regular expression empty and invalid.
@echo ${:U 123 234 345 :C^^2^two^:Q} circumflex accent
# The :S and :C modifiers can be chained without a separating ':'.
# This is not documented in the manual page.
# It works because ApplyModifier_Subst scans for the known modifiers g1W
# and then just returns to ApplyModifiers. There, the colon is optionally
# skipped (see the *st.next == ':' at the end of the loop).
# and then just returns to ApplySingleModifier. There, the colon is skipped.
#
# Most other modifiers cannot be chained since their parsers skip until
# the next ':' or '}' or ')'.
+6 -6
View File
@@ -1,4 +1,4 @@
# $NetBSD: varname-dot-make-save_dollars.mk,v 1.7 2021/12/03 18:43:52 rillig Exp $
# $NetBSD: varname-dot-make-save_dollars.mk,v 1.8 2026/03/13 04:22:03 sjg Exp $
#
# Tests for the special .MAKE.SAVE_DOLLARS variable, which controls whether
# the assignment operator ':=' converts '$$' to a single '$' or keeps it
@@ -8,11 +8,11 @@
# var-op-expand.mk for ':=' in general
# varmisc.mk for parsing the boolean values
# Initially, the variable .MAKE.SAVE_DOLLARS is undefined. At this point the
# behavior of the assignment operator ':=' depends. NetBSD's usr.bin/make
# preserves the '$$' as-is, while the bmake distribution replaces '$$' with
# '$'.
.if ${.MAKE.SAVE_DOLLARS:Uundefined} != "undefined"
# The variable .MAKE.SAVE_DOLLARS is a boolean that controls the handling
# of '$$' during ':='
# If "yes" (default for NetBSD's usr.bin/make) '$$' is left as-is.
# If "no" (default for bmake), '$$' is replaced with '$'.
.if ${.MAKE.SAVE_DOLLARS:Uundefined} == "undefined"
. error
.endif
+16 -6
View File
@@ -1,7 +1,7 @@
make: Unknown modifier ":Z"
while evaluating "${:Z}" with value ""
in command "@echo ${:Z}"
in target "provoke-error"
in target "provoke-error" from varname-make_stack_trace.mk:42
in make[2] in directory "<curdir>"
*** Error code 2 (continuing)
@@ -10,7 +10,7 @@ make: stopped making "disabled-compat" in unit-tests
make: Unknown modifier ":Z"
while evaluating "${:Z}" with value ""
in command "@echo ${:Z}"
in target "provoke-error"
in target "provoke-error" from varname-make_stack_trace.mk:42
in make[2] in directory "<curdir>"
*** [disabled-parallel] Error code 2
@@ -18,10 +18,10 @@ make: stopped making "disabled-parallel" in unit-tests
make: Unknown modifier ":Z"
while evaluating "${:Z}" with value ""
in command "@echo ${:Z}"
in target "provoke-error"
in target "provoke-error" from varname-make_stack_trace.mk:42
in make[2] in directory "<curdir>"
in command "make -f varname-make_stack_trace.mk provoke-error"
in target "enabled-compat"
in target "enabled-compat" from varname-make_stack_trace.mk:35
in make[1] in directory "<curdir>"
*** Error code 2 (continuing)
@@ -30,11 +30,21 @@ make: stopped making "enabled-compat" in unit-tests
make: Unknown modifier ":Z"
while evaluating "${:Z}" with value ""
in command "@echo ${:Z}"
in target "provoke-error"
in target "provoke-error" from varname-make_stack_trace.mk:42
in make[2] in directory "<curdir>"
in target "enabled-parallel"
in target "enabled-parallel" from varname-make_stack_trace.mk:39
in make[1] in directory "<curdir>"
*** [enabled-parallel] Error code 2
make: stopped making "enabled-parallel" in unit-tests
.make[5]: warning: Invalid internal option "-J" in "<curdir>"; see the manual page
in .make[5] in directory "<curdir>"
in target "multi-stage-4" from varname-make_stack_trace.mk:56
in make[4] in directory "<curdir>"
in target "multi-stage-3" from varname-make_stack_trace.mk:54
in make[3] in directory "<curdir>"
in target "multi-stage-2" from varname-make_stack_trace.mk:52
in make[2] in directory "<curdir>"
in target "multi-stage-1" from varname-make_stack_trace.mk:50
in make[1] in directory "<curdir>"
exit status 0
+31 -5
View File
@@ -1,4 +1,4 @@
# $NetBSD: varname-make_stack_trace.mk,v 1.1 2025/06/13 03:51:18 rillig Exp $
# $NetBSD: varname-make_stack_trace.mk,v 1.8 2026/03/10 05:02:00 sjg Exp $
#
# Tests for the MAKE_STACK_TRACE environment variable, which controls whether
# to print inter-process stack traces that are useful to narrow down where an
@@ -11,27 +11,53 @@
# with the space for the command line arguments, and long command lines are
# already written to a temporary file by Cmd_Exec to not overwhelm this space.
_make ?= .make${.MAKE.PID}
.export _make
all: .PHONY
@${MAKE} -f ${MAKEFILE} disabled-compat || :
@${MAKE} -f ${MAKEFILE} -j1 disabled-parallel || :
@MAKE_STACK_TRACE=yes ${MAKE} -f ${MAKEFILE} enabled-compat || :
@MAKE_STACK_TRACE=yes ${MAKE} -f ${MAKEFILE} -j1 enabled-parallel || :
@MAKE_STACK_TRACE=yes ${MAKE} -f ${MAKEFILE} -j1 multi-stage-1
@rm -f ${_make}
# expect-not: in target "disabled-compat"
# expect-not-matches: in target "disabled%-compat"
disabled-compat: .PHONY
@${MAKE} -f ${MAKEFILE} provoke-error
# expect-not: in target "disabled-parallel"
# expect-not-matches: in target "disabled%-parallel"
disabled-parallel: .PHONY
@${MAKE} -f ${MAKEFILE} provoke-error
# expect: in target "enabled-compat"
# expect: in target "enabled-compat" from varname-make_stack_trace.mk:35
enabled-compat: .PHONY
@${MAKE} -f ${MAKEFILE} provoke-error
# expect: in target "enabled-parallel"
# expect: in target "enabled-parallel" from varname-make_stack_trace.mk:39
enabled-parallel: .PHONY
@${MAKE} -f ${MAKEFILE} provoke-error
provoke-error: .PHONY
@echo ${:Z}
# The stack trace must be printed exactly once.
# expect: in target "multi-stage-4" from varname-make_stack_trace.mk:56
# expect: in target "multi-stage-1" from varname-make_stack_trace.mk:50
# expect-not-matches: in target "multi%-stage%-4"
# expect-not-matches: in target "multi%-stage%-1"
multi-stage-1: .PHONY ${_make}
@${MAKE} -f ${MAKEFILE} -j1 multi-stage-2
multi-stage-2: .PHONY
@${MAKE} -f ${MAKEFILE} -j1 multi-stage-3
multi-stage-3: .PHONY
@${MAKE} -f ${MAKEFILE} -j1 multi-stage-4
multi-stage-4: .PHONY
@./${_make} -f ${MAKEFILE} -j1 multi-stage-5
multi-stage-5: .PHONY
${_make}:
@ln -s ${MAKE} ${.TARGET}
# for FreeBSD and similar make sure we get the expected errors.
.MAKE.ALWAYS_PASS_JOB_QUEUE= no
+40 -30
View File
@@ -1,4 +1,4 @@
/* $NetBSD: var.c,v 1.1173 2025/11/12 22:14:07 sjg Exp $ */
/* $NetBSD: var.c,v 1.1179 2026/03/13 04:22:03 sjg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -93,7 +93,9 @@
* Var_Value Return the unexpanded value of a variable, or NULL if
* the variable is undefined.
*
* Var_Subst Substitute all expressions in a string.
* Var_Subst Copy a string, expanding expressions on the way.
*
* Var_Expand Expand all expressions in a string, in-place.
*
* Var_Parse Parse an expression such as ${VAR:Mpattern}.
*
@@ -143,7 +145,7 @@
#endif
/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */
MAKE_RCSID("$NetBSD: var.c,v 1.1173 2025/11/12 22:14:07 sjg Exp $");
MAKE_RCSID("$NetBSD: var.c,v 1.1179 2026/03/13 04:22:03 sjg Exp $");
/*
* Variables are defined using one of the VAR=value assignments. Their
@@ -319,31 +321,26 @@ static char varUndefined[] = "";
* Traditionally this make consumed $$ during := like any other expansion.
* Other make's do not, and this make follows straight since 2016-01-09.
*
* This knob allows controlling the behavior:
* This knob (.MAKE.SAVE_DOLLARS) allows controlling the behavior:
* false to consume $$ during := assignment.
* true to preserve $$ during := assignment.
*/
#define MAKE_SAVE_DOLLARS ".MAKE.SAVE_DOLLARS"
static bool save_dollars = false;
/*
* A scope collects variable names and their values.
*
* The main scope is SCOPE_GLOBAL, which contains the variables that are set
* in the makefiles. SCOPE_INTERNAL acts as a fallback for SCOPE_GLOBAL and
* contains some internal make variables. These internal variables can thus
* be overridden, they can also be restored by undefining the overriding
* variable.
* Each target has its own scope, containing the 7 target-local variables
* .TARGET, .ALLSRC, etc. Variables set on dependency lines also go in
* this scope.
*
* SCOPE_CMDLINE contains variables from the command line arguments. These
* override variables from SCOPE_GLOBAL.
*
* SCOPE_GLOBAL contains the variables that are set in the makefiles.
*
* There is no scope for environment variables, these are generated on-the-fly
* whenever they are referenced.
*
* Each target has its own scope, containing the 7 target-local variables
* .TARGET, .ALLSRC, etc. Variables set on dependency lines also go in
* this scope.
*/
GNode *SCOPE_CMDLINE;
@@ -415,6 +412,7 @@ EvalStack_Details(Buffer *buf)
const char* value = elem->value != NULL
&& (kind == VSK_VARNAME || kind == VSK_EXPR)
? elem->value->str : NULL;
const GNode *gn;
Buf_AddStr(buf, "\t");
Buf_AddStr(buf, descr[kind]);
@@ -424,7 +422,16 @@ EvalStack_Details(Buffer *buf)
Buf_AddStr(buf, "\" with value \"");
Buf_AddStr(buf, value);
}
Buf_AddStr(buf, "\"\n");
if (kind == VSK_TARGET
&& (gn = Targ_FindNode(elem->str)) != NULL
&& gn->fname != NULL) {
Buf_AddStr(buf, "\" from ");
Buf_AddStr(buf, gn->fname);
Buf_AddStr(buf, ":");
Buf_AddInt(buf, (int)gn->lineno);
Buf_AddStr(buf, "\n");
} else
Buf_AddStr(buf, "\"\n");
}
return evalStack.len > 0;
}
@@ -1282,12 +1289,8 @@ Var_Exists(GNode *scope, const char *name)
}
/*
* See if the given variable exists, in the given scope or in other
* fallback scopes.
*
* Input:
* scope scope in which to start search
* name name of the variable to find, is expanded once
* See if the given variable exists, in the given scope or in other fallback
* scopes. The variable name is expanded once.
*/
bool
Var_ExistsExpand(GNode *scope, const char *name)
@@ -2138,12 +2141,12 @@ typedef enum ApplyModifierResult {
* backslashes.
*/
static bool
IsEscapedModifierPart(const char *p, char end1, char end2,
IsEscapedModifierPart(const char *p, char delim1, char delim2,
struct ModifyWord_SubstArgs *subst)
{
if (p[0] != '\\' || p[1] == '\0')
return false;
if (p[1] == end1 || p[1] == end2 || p[1] == '\\' || p[1] == '$')
if (p[1] == delim1 || p[1] == delim2 || p[1] == '\\' || p[1] == '$')
return true;
return p[1] == '&' && subst != NULL;
}
@@ -2224,10 +2227,10 @@ ParseModifierPart(
* For the first part of the ':S' modifier, set anchorEnd if the last
* character of the pattern is a $.
*/
PatternFlags *out_pflags,
PatternFlags *pflags,
/*
* For the second part of the ':S' modifier, allow ampersands to be
* escaped and replace unescaped ampersands with subst->lhs.
* For the second part of the ':S' modifier, allow '&' to be
* escaped and replace each unescaped '&' with subst->lhs.
*/
struct ModifyWord_SubstArgs *subst
)
@@ -2246,8 +2249,8 @@ ParseModifierPart(
LazyBuf_Add(part, *p);
p++;
} else if (p[1] == end2) { /* Unescaped '$' at end */
if (out_pflags != NULL)
out_pflags->anchorEnd = true;
if (pflags != NULL)
pflags->anchorEnd = true;
else
LazyBuf_Add(part, *p);
p++;
@@ -3044,9 +3047,16 @@ ApplyModifier_Regex(const char **pp, ModChain *ch)
if (!ModChain_ShouldEval(ch))
goto done;
if (re.str[0] == '\0') {
/* not all regcomp() fail on this */
Parse_Error(PARSE_FATAL, "Regex compilation error: empty");
goto re_err;
}
error = regcomp(&args.re, re.str, REG_EXTENDED);
if (error != 0) {
RegexError(error, &args.re, "Regex compilation error");
re_err:
LazyBuf_Done(&replaceBuf);
FStr_Done(&re);
return AMR_CLEANUP;
@@ -3829,7 +3839,7 @@ ApplyModifier_SunShell1(const char **pp, ModChain *ch)
v = VarFind(cache_varname, SCOPE_GLOBAL, false);
if (v == NULL) {
char *output, *error;
output = Cmd_Exec(Expr_Str(expr), &error);
if (error != NULL) {
Parse_Error(PARSE_WARNING, "%s", error);
@@ -3846,7 +3856,7 @@ ApplyModifier_SunShell1(const char **pp, ModChain *ch)
return AMR_OK;
}
/*
* In cases where the evaluation mode and the definedness are the "standard"