mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-11-07 04:36:52 -10:00
Import bmake-20260704
Intersting/relevant changes since bmake-20260508 ChangeLog since bmake-20260508 2026-07-04 Simon J Gerraty <[email protected]> * VERSION (_MAKE_VERSION): 20260704 2026-07-03 Simon J Gerraty <[email protected]> * VERSION (_MAKE_VERSION): 20260703 Merge with NetBSD make, pick up o meta.c: do a better job of resolving relative paths o var.c: add alternation support to :M eg. :M*{Makefile*,.mk} matches any *Makefile* or *.mk 2026-07-02 Simon J Gerraty <[email protected]> * VERSION (_MAKE_VERSION): 20260702 Merge with NetBSD make, pick up o meta.c: .MAKE.META.FILTER can be used to more generally filter relevant content of .meta file in meta_oodate. 2026-06-19 Simon J Gerraty <[email protected]> * VERSION (_MAKE_VERSION): 20260619 Merge with NetBSD make, pick up o make.1: fix description of .MADE it is a source not a target. * update mk files 2026-06-10 Simon J Gerraty <[email protected]> * VERSION (_MAKE_VERSION): 20260609 Merge with NetBSD make, pick up o parse.c: allow semicolons and parentheses in dependency line expressions mk/ChangeLog since bmake-20260508 2026-07-04 Simon J Gerraty <[email protected]> * install-mk (MK_VERSION): 20260704 2026-07-03 Simon J Gerraty <[email protected]> * dirdeps.mk: make use of alternation support in latest bmake when setting .MAKE.META.IGNORE_FILTER so we can get both Makefile.depend* and *.mk to make cache out-of-date. 2026-07-02 Simon J Gerraty <[email protected]> * meta2deps.py: detect corrupted filemon data on Linux, caused by lost newlines. 2026-06-21 Simon J Gerraty <[email protected]> * install-mk (MK_VERSION): 20260621 * gendirdeps.mk: more debug output * meta.autodep.mk: remove extra } from GENDIRDEPS_ENV 2026-06-19 Simon J Gerraty <[email protected]> * install-mk (MK_VERSION): 20260619 * install-new.mk: for POSIX_SHELL we need .new* rather than just .new 2026-05-21 Simon J Gerraty <[email protected]> * meta2deps.{py,sh}: skip pathnames with spaces - not worth the pain.
This commit is contained in:
1 parent
ef402bba84
commit
e988c5eab5
25 files changed
+648
-203
No files matched your search
@@ -1,3 +1,37 @@
|
||||
2026-07-04 Simon J Gerraty <[email protected]>
|
||||
|
||||
* VERSION (_MAKE_VERSION): 20260704
|
||||
|
||||
2026-07-03 Simon J Gerraty <[email protected]>
|
||||
|
||||
* VERSION (_MAKE_VERSION): 20260703
|
||||
Merge with NetBSD make, pick up
|
||||
o meta.c: do a better job of resolving relative paths
|
||||
o var.c: add alternation support to :M
|
||||
eg. :M*{Makefile*,.mk} matches any *Makefile* or *.mk
|
||||
|
||||
2026-07-02 Simon J Gerraty <[email protected]>
|
||||
|
||||
* VERSION (_MAKE_VERSION): 20260702
|
||||
Merge with NetBSD make, pick up
|
||||
o meta.c: .MAKE.META.FILTER can be used to more generally filter
|
||||
relevant content of .meta file in meta_oodate.
|
||||
|
||||
2026-06-19 Simon J Gerraty <[email protected]>
|
||||
|
||||
* VERSION (_MAKE_VERSION): 20260619
|
||||
Merge with NetBSD make, pick up
|
||||
o make.1: fix description of .MADE it is a source not a target.
|
||||
|
||||
* update mk files
|
||||
|
||||
2026-06-10 Simon J Gerraty <[email protected]>
|
||||
|
||||
* VERSION (_MAKE_VERSION): 20260609
|
||||
Merge with NetBSD make, pick up
|
||||
o parse.c: allow semicolons and parentheses in dependency line
|
||||
expressions
|
||||
|
||||
2026-05-08 Simon J Gerraty <[email protected]>
|
||||
|
||||
* VERSION (_MAKE_VERSION): 20260508
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
# keep this compatible with sh and make
|
||||
_MAKE_VERSION=20260508
|
||||
_MAKE_VERSION=20260704
|
||||
@@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: make.1,v 1.391 2026/05/08 16:11:21 sjg Exp $
|
||||
.\" $NetBSD: make.1,v 1.394 2026/07/03 15:31:34 sjg Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
@@ -29,7 +29,7 @@
|
||||
.\"
|
||||
.\" from: @(#)make.1 8.4 (Berkeley) 3/19/94
|
||||
.\"
|
||||
.Dd May 8, 2026
|
||||
.Dd July 3, 2026
|
||||
.Dt BMAKE 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -1038,11 +1038,26 @@ the current target is considered out-of-date.
|
||||
.It Va .MAKE.META.CMP_FILTER
|
||||
In
|
||||
.Dq meta
|
||||
mode, it can (very rarely!) be useful to filter command
|
||||
mode, it can sometimes be useful to filter command
|
||||
lines before comparison.
|
||||
This variable can be set to a set of modifiers that are applied to
|
||||
each line of the old and new command that differ, if the filtered
|
||||
commands still differ, the target is considered out-of-date.
|
||||
This variable can contain a list of modifiers that will be joined with
|
||||
.Ql \&:
|
||||
and applied to each line of the old and new command that differ.
|
||||
If the filtered commands still differ,
|
||||
the target is considered out-of-date.
|
||||
.It Va .MAKE.META.FILTER
|
||||
In
|
||||
.Dq meta
|
||||
mode, it can be useful to filter most of the data in a meta file.
|
||||
For example, when a pre-built tree is relocated or cloned,
|
||||
all the targets would be considered out-of-date without a filter
|
||||
to replace the old location with the new.
|
||||
This variable is similar to
|
||||
.Va .MAKE.META.CMP_FILTER
|
||||
but is appliled to commands, cwd and the syscall records from filemon.
|
||||
In the case of commands, this is done prior to any
|
||||
.Va .MAKE.META.CMP_FILTER
|
||||
modifiers are applied during comparison.
|
||||
.It Va .MAKE.META.CREATED
|
||||
In
|
||||
.Dq meta
|
||||
@@ -1506,7 +1521,16 @@ and
|
||||
.Ql \&[] )
|
||||
may
|
||||
be used.
|
||||
The wildcard characters may be escaped with a backslash
|
||||
Braces can be used to list alternate patterns.
|
||||
For example,
|
||||
.Ql ${.ALLSRC:M*{Makefile*,.mk}}
|
||||
could be used to match any
|
||||
.Ql *Makefile*
|
||||
or
|
||||
.Ql *.mk
|
||||
in
|
||||
.Va .ALLSRC .
|
||||
The wildcard characters and braces may be escaped with a backslash
|
||||
.Pq Ql \e .
|
||||
As a consequence of the way values are split into words, matched,
|
||||
and then joined, the construct
|
||||
@@ -2317,7 +2341,7 @@ as if they all were preceded by a dash
|
||||
.\" .It Ic .JOIN
|
||||
.\" XXX
|
||||
.It Ic .MADE
|
||||
Mark all sources of this target as being up to date.
|
||||
Mark the target(s) up to date.
|
||||
.It Ic .MAKE
|
||||
Execute the commands associated with this target even if the
|
||||
.Fl n
|
||||
|
||||
+25
-12
@@ -675,11 +675,21 @@ VVAARRIIAABBLLEE AASSSSIIGGNNMMEENNTTSS
|
||||
current target is considered out-of-date.
|
||||
|
||||
_._M_A_K_E_._M_E_T_A_._C_M_P___F_I_L_T_E_R
|
||||
In "meta" mode, it can (very rarely!) be useful to filter command
|
||||
lines before comparison. This variable can be set to a set of
|
||||
modifiers that are applied to each line of the old and new
|
||||
command that differ, if the filtered commands still differ, the
|
||||
target is considered out-of-date.
|
||||
In "meta" mode, it can sometimes be useful to filter command
|
||||
lines before comparison. This variable can contain a list of
|
||||
modifiers that will be joined with `:' and applied to each line
|
||||
of the old and new command that differ. If the filtered commands
|
||||
still differ, the target is considered out-of-date.
|
||||
|
||||
_._M_A_K_E_._M_E_T_A_._F_I_L_T_E_R
|
||||
In "meta" mode, it can be useful to filter most of the data in a
|
||||
meta file. For example, when a pre-built tree is relocated or
|
||||
cloned, all the targets would be considered out-of-date without a
|
||||
filter to replace the old location with the new. This variable
|
||||
is similar to _._M_A_K_E_._M_E_T_A_._C_M_P___F_I_L_T_E_R but is appliled to commands,
|
||||
cwd and the syscall records from filemon. In the case of
|
||||
commands, this is done prior to any _._M_A_K_E_._M_E_T_A_._C_M_P___F_I_L_T_E_R
|
||||
modifiers are applied during comparison.
|
||||
|
||||
_._M_A_K_E_._M_E_T_A_._C_R_E_A_T_E_D
|
||||
In "meta" mode, this variable contains a list of all the meta
|
||||
@@ -978,11 +988,14 @@ VVAARRIIAABBLLEE AASSSSIIGGNNMMEENNTTSS
|
||||
|
||||
::MM_p_a_t_t_e_r_n
|
||||
Selects only those words that match _p_a_t_t_e_r_n. The standard shell
|
||||
wildcard characters (`*', `?', and `[]') may be used. The wildcard
|
||||
characters may be escaped with a backslash (`\'). As a consequence
|
||||
of the way values are split into words, matched, and then joined,
|
||||
the construct `${VAR:M*}' removes all leading and trailing
|
||||
whitespace and normalizes the inter-word spacing to a single space.
|
||||
wildcard characters (`*', `?', and `[]') may be used. Braces can be
|
||||
used to list alternate patterns. For example,
|
||||
`${.ALLSRC:M*{Makefile*,.mk}}' could be used to match any
|
||||
`*Makefile*' or `*.mk' in _._A_L_L_S_R_C. The wildcard characters and
|
||||
braces may be escaped with a backslash (`\'). As a consequence of
|
||||
the way values are split into words, matched, and then joined, the
|
||||
construct `${VAR:M*}' removes all leading and trailing whitespace
|
||||
and normalizes the inter-word spacing to a single space.
|
||||
|
||||
::NN_p_a_t_t_e_r_n
|
||||
This is the opposite of `::MM', selecting all words which do _n_o_t match
|
||||
@@ -1489,7 +1502,7 @@ SSPPEECCIIAALL SSOOUURRCCEESS ((AATTTTRRIIBBUUTTEESS))
|
||||
..IIGGNNOORREE Ignore any errors from the commands associated with this
|
||||
target, exactly as if they all were preceded by a dash (`-').
|
||||
|
||||
..MMAADDEE Mark all sources of this target as being up to date.
|
||||
..MMAADDEE Mark the target(s) up to date.
|
||||
|
||||
..MMAAKKEE Execute the commands associated with this target even if the --nn
|
||||
or --tt options were specified. Normally used to mark recursive
|
||||
@@ -1882,4 +1895,4 @@ BBUUGGSS
|
||||
attempt to suppress a cascade of unnecessary errors, can result in a
|
||||
seemingly unexplained `*** Error code 6'
|
||||
|
||||
FreeBSD 14.3-RELEASE-p9 May 8, 2026 FreeBSD 14.3-RELEASE-p9
|
||||
FreeBSD 14.4-RELEASE-p3 July 3, 2026 BMAKE(1)
|
||||
|
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 96 KiB |
@@ -1,4 +1,4 @@
|
||||
/* $NetBSD: dir.c,v 1.298 2026/04/06 17:13:54 rillig Exp $ */
|
||||
/* $NetBSD: dir.c,v 1.299 2026/07/03 15:31:34 sjg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
|
||||
@@ -89,6 +89,9 @@
|
||||
* Returns true if the name given it needs to
|
||||
* be wildcard-expanded.
|
||||
*
|
||||
* ExpandCurly
|
||||
* Expand a pattern containing braces to a StringList.
|
||||
*
|
||||
* SearchPath_Expand
|
||||
* Expand a filename pattern to find all matching files
|
||||
* from the search path.
|
||||
@@ -132,7 +135,7 @@
|
||||
#include "job.h"
|
||||
|
||||
/* "@(#)dir.c 8.2 (Berkeley) 1/2/94" */
|
||||
MAKE_RCSID("$NetBSD: dir.c,v 1.298 2026/04/06 17:13:54 rillig Exp $");
|
||||
MAKE_RCSID("$NetBSD: dir.c,v 1.299 2026/07/03 15:31:34 sjg Exp $");
|
||||
|
||||
/*
|
||||
* A search path is a list of CachedDir structures. A CachedDir has in it the
|
||||
@@ -752,8 +755,8 @@ concat3(const char *a, size_t a_len, const char *b, size_t b_len,
|
||||
/*
|
||||
* Expand curly braces like the C shell. Brace expansion by itself is purely
|
||||
* textual, the expansions are not looked up in the file system. But if an
|
||||
* expanded word contains wildcard characters, it is expanded further,
|
||||
* matching only the actually existing files.
|
||||
* expanded word contains wildcard characters, and path is provided,
|
||||
* it is expanded further, matching only the actually existing files.
|
||||
*
|
||||
* Example: "{a{b,c}}" expands to "ab" and "ac".
|
||||
* Example: "{a}" expands to "a".
|
||||
@@ -762,11 +765,11 @@ concat3(const char *a, size_t a_len, const char *b, size_t b_len,
|
||||
* Input:
|
||||
* word Entire word to expand
|
||||
* brace First curly brace in it
|
||||
* path Search path to use
|
||||
* path Search path to use (NULL to skip wildcard expansion)
|
||||
* expansions Place to store the expansions
|
||||
*/
|
||||
static void
|
||||
DirExpandCurly(const char *word, const char *brace, SearchPath *path,
|
||||
void
|
||||
ExpandCurly(const char *word, const char *brace, SearchPath *path,
|
||||
StringList *expansions)
|
||||
{
|
||||
const char *prefix, *middle, *piece, *middle_end, *suffix;
|
||||
@@ -796,7 +799,7 @@ DirExpandCurly(const char *word, const char *brace, SearchPath *path,
|
||||
char *file = concat3(prefix, prefix_len, piece, piece_len,
|
||||
suffix, suffix_len);
|
||||
|
||||
if (contains_wildcard(file)) {
|
||||
if (path != NULL && contains_wildcard(file)) {
|
||||
SearchPath_Expand(path, file, expansions);
|
||||
free(file);
|
||||
} else {
|
||||
@@ -898,7 +901,7 @@ SearchPath_Expand(SearchPath *path, const char *pattern, StringList *expansions)
|
||||
|
||||
brace = strchr(pattern, '{');
|
||||
if (brace != NULL) {
|
||||
DirExpandCurly(pattern, brace, path, expansions);
|
||||
ExpandCurly(pattern, brace, path, expansions);
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $NetBSD: dir.h,v 1.49 2024/07/07 07:50:57 rillig Exp $ */
|
||||
/* $NetBSD: dir.h,v 1.50 2026/07/03 15:31:34 sjg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
|
||||
@@ -86,6 +86,7 @@ void Dir_End(void);
|
||||
void Dir_SetPATH(void);
|
||||
void Dir_SetSYSPATH(void);
|
||||
bool Dir_HasWildcards(const char *) MAKE_ATTR_USE;
|
||||
void ExpandCurly(const char *, const char *, SearchPath *, StringList *);
|
||||
void SearchPath_Expand(SearchPath *, const char *, StringList *);
|
||||
char *Dir_FindFile(const char *, SearchPath *) MAKE_ATTR_USE;
|
||||
char *Dir_FindInclude(const char *, SearchPath *) MAKE_ATTR_USE;
|
||||
|
||||
+14
-1
@@ -1,4 +1,4 @@
|
||||
/* $NetBSD: filemon_dev.c,v 1.9 2022/03/04 23:17:16 sjg Exp $ */
|
||||
/* $NetBSD: filemon_dev.c,v 1.10 2026/07/03 03:34:25 sjg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2020 The NetBSD Foundation, Inc.
|
||||
@@ -123,6 +123,19 @@ filemon_close(struct filemon *F)
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
#ifdef FILEMON_FLUSH_IOCTL
|
||||
/*
|
||||
* Ask the kernel to write the footer and flush the trailing records to
|
||||
* the output file *now*, synchronously, before we close the device.
|
||||
* Otherwise finalization happens only at device release, which the
|
||||
* kernel defers until the last reference to the device is dropped; a
|
||||
* child that transiently inherited this fd across a fork->exec window
|
||||
* can hold that reference past our read of the output file, yielding a
|
||||
* truncated .meta (records + "# Bye bye" footer missing).
|
||||
*/
|
||||
(void)ioctl(F->fd, FILEMON_FLUSH_IOCTL);
|
||||
#endif
|
||||
|
||||
/* Close the filemon device fd. */
|
||||
if (close(F->fd) == -1 && error == 0)
|
||||
error = errno;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: make.1,v 1.391 2026/05/08 16:11:21 sjg Exp $
|
||||
.\" $NetBSD: make.1,v 1.394 2026/07/03 15:31:34 sjg Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
@@ -29,7 +29,7 @@
|
||||
.\"
|
||||
.\" from: @(#)make.1 8.4 (Berkeley) 3/19/94
|
||||
.\"
|
||||
.Dd May 8, 2026
|
||||
.Dd July 3, 2026
|
||||
.Dt MAKE 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -1038,11 +1038,26 @@ the current target is considered out-of-date.
|
||||
.It Va .MAKE.META.CMP_FILTER
|
||||
In
|
||||
.Dq meta
|
||||
mode, it can (very rarely!) be useful to filter command
|
||||
mode, it can sometimes be useful to filter command
|
||||
lines before comparison.
|
||||
This variable can be set to a set of modifiers that are applied to
|
||||
each line of the old and new command that differ, if the filtered
|
||||
commands still differ, the target is considered out-of-date.
|
||||
This variable can contain a list of modifiers that will be joined with
|
||||
.Ql \&:
|
||||
and applied to each line of the old and new command that differ.
|
||||
If the filtered commands still differ,
|
||||
the target is considered out-of-date.
|
||||
.It Va .MAKE.META.FILTER
|
||||
In
|
||||
.Dq meta
|
||||
mode, it can be useful to filter most of the data in a meta file.
|
||||
For example, when a pre-built tree is relocated or cloned,
|
||||
all the targets would be considered out-of-date without a filter
|
||||
to replace the old location with the new.
|
||||
This variable is similar to
|
||||
.Va .MAKE.META.CMP_FILTER
|
||||
but is appliled to commands, cwd and the syscall records from filemon.
|
||||
In the case of commands, this is done prior to any
|
||||
.Va .MAKE.META.CMP_FILTER
|
||||
modifiers are applied during comparison.
|
||||
.It Va .MAKE.META.CREATED
|
||||
In
|
||||
.Dq meta
|
||||
@@ -1506,7 +1521,16 @@ and
|
||||
.Ql \&[] )
|
||||
may
|
||||
be used.
|
||||
The wildcard characters may be escaped with a backslash
|
||||
Braces can be used to list alternate patterns.
|
||||
For example,
|
||||
.Ql ${.ALLSRC:M*{Makefile*,.mk}}
|
||||
could be used to match any
|
||||
.Ql *Makefile*
|
||||
or
|
||||
.Ql *.mk
|
||||
in
|
||||
.Va .ALLSRC .
|
||||
The wildcard characters and braces may be escaped with a backslash
|
||||
.Pq Ql \e .
|
||||
As a consequence of the way values are split into words, matched,
|
||||
and then joined, the construct
|
||||
@@ -2317,7 +2341,7 @@ as if they all were preceded by a dash
|
||||
.\" .It Ic .JOIN
|
||||
.\" XXX
|
||||
.It Ic .MADE
|
||||
Mark all sources of this target as being up to date.
|
||||
Mark the target(s) up to date.
|
||||
.It Ic .MAKE
|
||||
Execute the commands associated with this target even if the
|
||||
.Fl n
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $NetBSD: meta.c,v 1.221 2026/04/06 17:13:54 rillig Exp $ */
|
||||
/* $NetBSD: meta.c,v 1.223 2026/07/03 18:58:40 sjg Exp $ */
|
||||
|
||||
/*
|
||||
* Implement 'meta' mode.
|
||||
@@ -64,18 +64,11 @@ static char *metaBailiwickStr; /* string storage for the list */
|
||||
static StringList metaIgnorePaths = LST_INIT; /* paths we deliberately ignore */
|
||||
static char *metaIgnorePathsStr; /* string storage for the list */
|
||||
|
||||
#ifndef MAKE_META_IGNORE_PATHS
|
||||
#define MAKE_META_IGNORE_PATHS ".MAKE.META.IGNORE_PATHS"
|
||||
#endif
|
||||
#ifndef MAKE_META_IGNORE_PATTERNS
|
||||
#define MAKE_META_IGNORE_PATTERNS ".MAKE.META.IGNORE_PATTERNS"
|
||||
#endif
|
||||
#ifndef MAKE_META_IGNORE_FILTER
|
||||
#define MAKE_META_IGNORE_FILTER ".MAKE.META.IGNORE_FILTER"
|
||||
#endif
|
||||
#ifndef MAKE_META_CMP_FILTER
|
||||
#define MAKE_META_CMP_FILTER ".MAKE.META.CMP_FILTER"
|
||||
#endif
|
||||
#define MAKE_META_FILTER ".MAKE.META.FILTER"
|
||||
|
||||
bool useMeta = false;
|
||||
static bool useFilemon = false;
|
||||
@@ -88,6 +81,7 @@ static bool metaIgnoreCMDs = false; /* ignore CMDs in .meta files */
|
||||
static bool metaIgnorePatterns = false; /* do we need to do pattern matches */
|
||||
static bool metaIgnoreFilter = false; /* do we have more complex filtering? */
|
||||
static bool metaCmpFilter = false; /* do we have CMP_FILTER ? */
|
||||
static bool metaFilter = false; /* do we have FILTER */
|
||||
static bool metaCurdirOk = false; /* write .meta in .CURDIR Ok? */
|
||||
static bool metaSilent = false; /* if we have a .meta be SILENT */
|
||||
|
||||
@@ -606,6 +600,7 @@ meta_mode_init(const char *make_mode)
|
||||
metaIgnorePatterns = Var_Exists(SCOPE_GLOBAL, MAKE_META_IGNORE_PATTERNS);
|
||||
metaIgnoreFilter = Var_Exists(SCOPE_GLOBAL, MAKE_META_IGNORE_FILTER);
|
||||
metaCmpFilter = Var_Exists(SCOPE_GLOBAL, MAKE_META_CMP_FILTER);
|
||||
metaFilter = Var_Exists(SCOPE_GLOBAL, MAKE_META_FILTER);
|
||||
}
|
||||
|
||||
MAKE_INLINE BuildMon *
|
||||
@@ -1001,16 +996,86 @@ append_if_new(StringList *list, const char *str)
|
||||
Lst_Append(list, bmake_strdup(str));
|
||||
}
|
||||
|
||||
/* A "reserved" variable to store the command to be filtered */
|
||||
#define META_CMD_FILTER_VAR ".MAKE.cmd_filtered"
|
||||
/* remove any missingFiles entries that match p */
|
||||
static void
|
||||
remove_missing(StringList *missingFiles, const char *p)
|
||||
{
|
||||
StringListNode *ln = missingFiles->first;
|
||||
|
||||
while (ln != NULL) {
|
||||
StringListNode *next = ln->next;
|
||||
if (path_starts_with(ln->datum, p)) {
|
||||
free(ln->datum);
|
||||
Lst_Remove(missingFiles, ln);
|
||||
}
|
||||
ln = next;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
remove_relative_missing(StringList *missingFiles, const char *p, char *sdirs[])
|
||||
{
|
||||
char buf[MAXPATHLEN];
|
||||
char **sdp;
|
||||
|
||||
for (sdp = sdirs; *sdp != NULL; sdp++) {
|
||||
snprintf(buf, sizeof(buf), "%s/%s", *sdp, p);
|
||||
remove_missing(missingFiles, buf);
|
||||
}
|
||||
}
|
||||
|
||||
/* try to find a relative path */
|
||||
static char *
|
||||
meta_resolve_path(char *buf, size_t bufsz, const char *p,
|
||||
char *cwd, struct cached_stat *cstp, char *sdirs[])
|
||||
{
|
||||
char **sdp;
|
||||
|
||||
if (strcmp(p, ".") == 0)
|
||||
return cwd;
|
||||
|
||||
for (sdp = sdirs; *sdp != NULL; sdp++) {
|
||||
snprintf(buf, bufsz, "%s/%s", *sdp, p);
|
||||
if (cached_stat(buf, cstp) == 0)
|
||||
return buf;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update sdirs to contain a NULL terminated list of
|
||||
* unique dirs to try and resolve relative paths against.
|
||||
*/
|
||||
static void
|
||||
set_sdirs(char *sdirs[], size_t sdsz,
|
||||
char *latestdir, char *lcwd, char *cwd)
|
||||
{
|
||||
size_t i = 0;
|
||||
|
||||
sdirs[i++] = latestdir;
|
||||
if (i < sdsz && strcmp(latestdir, lcwd) != 0)
|
||||
sdirs[i++] = lcwd;
|
||||
if (i < sdsz && strcmp(lcwd, cwd) != 0)
|
||||
sdirs[i++] = cwd;
|
||||
if (i < sdsz)
|
||||
sdirs[i] = NULL;
|
||||
else
|
||||
sdirs[i - 1] = NULL; /* should never happen */
|
||||
}
|
||||
|
||||
/* A "reserved" variable to store the string to be filtered */
|
||||
#define META_FILTER_VAR ".MAKE.META._filtered_"
|
||||
|
||||
static char *
|
||||
meta_filter_cmd(GNode *gn, char *s)
|
||||
meta_filter(GNode *gn, char *s, const char *filter)
|
||||
{
|
||||
Var_Set(gn, META_CMD_FILTER_VAR, s);
|
||||
s = Var_Subst(
|
||||
"${" META_CMD_FILTER_VAR ":${" MAKE_META_CMP_FILTER ":ts:}}",
|
||||
gn, VARE_EVAL);
|
||||
char buf[sizeof(META_FILTER_VAR) + sizeof(MAKE_META_CMP_FILTER) + 24];
|
||||
|
||||
Var_Set(gn, META_FILTER_VAR, s);
|
||||
/* ":N" is a harmless do nothing */
|
||||
snprintf(buf, sizeof(buf), "${%s:${%s:UN:ts:}}",
|
||||
META_FILTER_VAR, filter);
|
||||
s = Var_Subst(buf, gn, VARE_EVAL);
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -1022,15 +1087,25 @@ meta_cmd_cmp(GNode *gn, char *a, char *b, bool filter)
|
||||
rc = strcmp(a, b);
|
||||
if (rc == 0 || !filter)
|
||||
return rc;
|
||||
a = meta_filter_cmd(gn, a);
|
||||
b = meta_filter_cmd(gn, b);
|
||||
a = meta_filter(gn, a, MAKE_META_CMP_FILTER);
|
||||
b = meta_filter(gn, b, MAKE_META_CMP_FILTER);
|
||||
rc = strcmp(a, b);
|
||||
free(a);
|
||||
free(b);
|
||||
Var_Delete(gn, META_CMD_FILTER_VAR);
|
||||
return rc;
|
||||
}
|
||||
|
||||
typedef enum MetaSection {
|
||||
META_HEADER,
|
||||
META_CMD,
|
||||
META_CWD,
|
||||
META_TARGET,
|
||||
META_OODATE,
|
||||
META_ENV,
|
||||
META_OUTPUT,
|
||||
META_FILEMON
|
||||
} MetaSection;
|
||||
|
||||
bool
|
||||
meta_oodate(GNode *gn, bool oodate)
|
||||
{
|
||||
@@ -1043,7 +1118,6 @@ meta_oodate(GNode *gn, bool oodate)
|
||||
char fname[MAXPATHLEN];
|
||||
char fname1[MAXPATHLEN];
|
||||
char fname2[MAXPATHLEN];
|
||||
char fname3[MAXPATHLEN];
|
||||
FStr dname;
|
||||
const char *tname;
|
||||
char *p;
|
||||
@@ -1054,7 +1128,6 @@ meta_oodate(GNode *gn, bool oodate)
|
||||
FILE *fp;
|
||||
bool needOODATE = false;
|
||||
StringList missingFiles;
|
||||
bool have_filemon = false;
|
||||
bool cmp_filter;
|
||||
|
||||
if (oodate)
|
||||
@@ -1063,10 +1136,10 @@ meta_oodate(GNode *gn, bool oodate)
|
||||
dname = Var_Value(gn, ".OBJDIR");
|
||||
tname = GNode_VarTarget(gn);
|
||||
|
||||
/* if this succeeds fname3 is realpath of dname */
|
||||
if (!meta_needed(gn, dname.str, fname3, false))
|
||||
/* if this succeeds fname2 is realpath of dname */
|
||||
if (!meta_needed(gn, dname.str, fname2, false))
|
||||
goto oodate_out;
|
||||
dname.str = fname3;
|
||||
dname.str = fname2;
|
||||
|
||||
Lst_Init(&missingFiles);
|
||||
|
||||
@@ -1087,12 +1160,17 @@ meta_oodate(GNode *gn, bool oodate)
|
||||
if ((fp = fopen(fname, "r")) != NULL) {
|
||||
static char *buf = NULL;
|
||||
static size_t bufsz;
|
||||
char *rp;
|
||||
char *freeit = NULL;
|
||||
char *sdirs[4];
|
||||
unsigned lineno = 0;
|
||||
int lastpid = 0;
|
||||
int pid;
|
||||
int x;
|
||||
bool found;
|
||||
StringListNode *cmdNode;
|
||||
struct cached_stat cst;
|
||||
MetaSection section = META_HEADER;
|
||||
|
||||
if (buf == NULL) {
|
||||
bufsz = 8 * BUFSIZ;
|
||||
@@ -1107,6 +1185,10 @@ meta_oodate(GNode *gn, bool oodate)
|
||||
strlcpy(lcwd, cwd, sizeof lcwd);
|
||||
strlcpy(latestdir, cwd, sizeof latestdir);
|
||||
|
||||
/* adjust this when lcwd or latestdir change */
|
||||
sdirs[0] = cwd;
|
||||
sdirs[1] = NULL;
|
||||
|
||||
if (tmpdir == NULL) {
|
||||
tmpdir = getTmpdir();
|
||||
tmplen = strlen(tmpdir);
|
||||
@@ -1115,10 +1197,14 @@ meta_oodate(GNode *gn, bool oodate)
|
||||
/* we want to track all the .meta we read */
|
||||
Global_Append(".MAKE.META.FILES", fname);
|
||||
|
||||
cmp_filter = metaCmpFilter || Var_Exists(gn, MAKE_META_CMP_FILTER);
|
||||
cmp_filter = metaFilter || metaCmpFilter || Var_Exists(gn, MAKE_META_CMP_FILTER);
|
||||
|
||||
cmdNode = gn->commands.first;
|
||||
while (!oodate && (x = fgetLine(&buf, &bufsz, 0, fp)) > 0) {
|
||||
if (freeit != NULL) {
|
||||
free(freeit);
|
||||
freeit = NULL;
|
||||
}
|
||||
lineno++;
|
||||
if (buf[x - 1] == '\n')
|
||||
buf[x - 1] = '\0';
|
||||
@@ -1129,16 +1215,37 @@ meta_oodate(GNode *gn, bool oodate)
|
||||
}
|
||||
link_src = NULL;
|
||||
move_target = NULL;
|
||||
/* Find the start of the build monitor section. */
|
||||
if (!have_filemon) {
|
||||
if (strncmp(buf, "-- filemon", 10) == 0) {
|
||||
have_filemon = true;
|
||||
continue;
|
||||
}
|
||||
if (strncmp(buf, "# buildmon", 10) == 0) {
|
||||
have_filemon = true;
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* Track which section of the meta file we are in.
|
||||
* For CMD, CWD, and FILEMON we may have to do filtering
|
||||
* the rest are of no interest here.
|
||||
*/
|
||||
switch (section) {
|
||||
case META_HEADER:
|
||||
section = META_CMD;
|
||||
continue;
|
||||
case META_CMD:
|
||||
if (strncmp(buf, "CWD", 3) == 0)
|
||||
section = META_CWD;
|
||||
break;
|
||||
case META_CWD:
|
||||
if (strncmp(buf, "TARG", 4) == 0)
|
||||
section = META_TARGET;
|
||||
break;
|
||||
case META_TARGET:
|
||||
case META_OODATE:
|
||||
case META_ENV:
|
||||
if (strncmp(buf, "-- command", 10) == 0)
|
||||
section = META_OUTPUT;
|
||||
continue;
|
||||
case META_OUTPUT:
|
||||
if (strncmp(buf, "-- filemon", 10) == 0)
|
||||
section = META_FILEMON;
|
||||
if (strncmp(buf, "# buildmon", 10) == 0)
|
||||
section = META_FILEMON;
|
||||
continue;
|
||||
case META_FILEMON:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Delimit the record type. */
|
||||
@@ -1146,8 +1253,35 @@ meta_oodate(GNode *gn, bool oodate)
|
||||
#ifdef DEBUG_META_MODE
|
||||
DEBUG3(META, "%s:%u: %s\n", fname, lineno, buf);
|
||||
#endif
|
||||
if (metaFilter) {
|
||||
switch (buf[0]) {
|
||||
case '#': /* these do not need filtering */
|
||||
case 'F':
|
||||
case 'V':
|
||||
case 'X':
|
||||
break;
|
||||
default:
|
||||
switch (section) {
|
||||
default:
|
||||
break;
|
||||
case META_CMD:
|
||||
case META_CWD:
|
||||
case META_FILEMON:
|
||||
freeit = p = meta_filter(gn, p, MAKE_META_FILTER);
|
||||
#ifdef DEBUG_META_MODE
|
||||
DEBUG3(META, "%s:%u: filtered: %s\n", fname, lineno, p);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
strsep(&p, " ");
|
||||
if (have_filemon) {
|
||||
switch (section) {
|
||||
default:
|
||||
break;
|
||||
case META_FILEMON:
|
||||
/*
|
||||
* We are in the 'filemon' output section.
|
||||
* Each record from filemon follows the general form:
|
||||
@@ -1206,6 +1340,7 @@ meta_oodate(GNode *gn, bool oodate)
|
||||
strlcpy(lcwd, ldir.str, sizeof lcwd);
|
||||
FStr_Done(&ldir);
|
||||
}
|
||||
set_sdirs(sdirs, 4, latestdir, lcwd, cwd);
|
||||
}
|
||||
/* Skip past the pid. */
|
||||
if (strsep(&p, " ") == NULL)
|
||||
@@ -1261,6 +1396,7 @@ meta_oodate(GNode *gn, bool oodate)
|
||||
DEBUG4(META, "%s:%u: cwd=%s ldir=%s\n",
|
||||
fname, lineno, cwd, lcwd);
|
||||
#endif
|
||||
set_sdirs(sdirs, 4, latestdir, lcwd, cwd);
|
||||
break;
|
||||
|
||||
case 'M': /* renaMe */
|
||||
@@ -1283,18 +1419,26 @@ meta_oodate(GNode *gn, bool oodate)
|
||||
DEQUOTE(move_target);
|
||||
/* FALLTHROUGH */
|
||||
case 'D': /* unlink */
|
||||
if (*p == '/') {
|
||||
/* remove any missingFiles entries that match p */
|
||||
StringListNode *ln = missingFiles.first;
|
||||
while (ln != NULL) {
|
||||
StringListNode *next = ln->next;
|
||||
if (path_starts_with(ln->datum, p)) {
|
||||
free(ln->datum);
|
||||
Lst_Remove(&missingFiles, ln);
|
||||
}
|
||||
ln = next;
|
||||
if (*p != '/') {
|
||||
#ifdef DEBUG_META_MODE
|
||||
DEBUG3(META, "%s:%u: looking for: %s ...\n",
|
||||
fname, lineno, p);
|
||||
#endif
|
||||
rp = meta_resolve_path(fname1, sizeof(fname1), p,
|
||||
lcwd, &cst, sdirs);
|
||||
if (rp != NULL) {
|
||||
#ifdef DEBUG_META_MODE
|
||||
DEBUG3(META, "%s:%u: found: %s\n",
|
||||
fname, lineno, rp);
|
||||
#endif
|
||||
p = rp;
|
||||
}
|
||||
}
|
||||
if (*p == '/') {
|
||||
remove_missing(&missingFiles, p);
|
||||
} else {
|
||||
remove_relative_missing(&missingFiles, p, sdirs);
|
||||
}
|
||||
if (buf[0] == 'M') {
|
||||
/* the target of the mv is a file 'W'ritten */
|
||||
#ifdef DEBUG_META_MODE
|
||||
@@ -1330,10 +1474,34 @@ meta_oodate(GNode *gn, bool oodate)
|
||||
* but outside of .OBJDIR is missing,
|
||||
* we need to do it again.
|
||||
*/
|
||||
/* ignore non-absolute paths */
|
||||
if (*p != '/')
|
||||
if (*p != '/') {
|
||||
#ifdef DEBUG_META_MODE
|
||||
DEBUG3(META, "%s:%u: looking for: %s ...\n",
|
||||
fname, lineno, p);
|
||||
#endif
|
||||
rp = meta_resolve_path(fname1, sizeof(fname1), p,
|
||||
lcwd, &cst, sdirs);
|
||||
if (rp != NULL) {
|
||||
#ifdef DEBUG_META_MODE
|
||||
DEBUG3(META, "%s:%u: found: %s\n",
|
||||
fname, lineno, rp);
|
||||
#endif
|
||||
p = rp;
|
||||
}
|
||||
}
|
||||
if (*p != '/') {
|
||||
/*
|
||||
* it is missing or we should have found it
|
||||
*/
|
||||
snprintf(fname1, sizeof(fname1), "%s/%s",
|
||||
lcwd, p);
|
||||
#ifdef DEBUG_META_MODE
|
||||
DEBUG3(META, "%s:%u: maybe missing: %s\n",
|
||||
fname, lineno, fname1);
|
||||
#endif
|
||||
append_if_new(&missingFiles, fname1);
|
||||
break;
|
||||
|
||||
}
|
||||
if (Lst_IsEmpty(&metaBailiwick))
|
||||
break;
|
||||
|
||||
@@ -1378,73 +1546,59 @@ meta_oodate(GNode *gn, bool oodate)
|
||||
|
||||
/*
|
||||
* The rest of the record is the file name.
|
||||
* Check if it's not an absolute path.
|
||||
*/
|
||||
{
|
||||
char *sdirs[4];
|
||||
char **sdp;
|
||||
int sdx = 0;
|
||||
bool found = false;
|
||||
|
||||
if (*p == '/') {
|
||||
sdirs[sdx++] = p; /* done */
|
||||
} else {
|
||||
if (strcmp(".", p) == 0)
|
||||
continue; /* no point */
|
||||
|
||||
/* Check vs latestdir */
|
||||
if (snprintf(fname1, sizeof fname1, "%s/%s", latestdir, p) < (int)(sizeof fname1))
|
||||
sdirs[sdx++] = fname1;
|
||||
|
||||
if (strcmp(latestdir, lcwd) != 0) {
|
||||
/* Check vs lcwd */
|
||||
if (snprintf(fname2, sizeof fname2, "%s/%s", lcwd, p) < (int)(sizeof fname2))
|
||||
sdirs[sdx++] = fname2;
|
||||
}
|
||||
if (strcmp(lcwd, cwd) != 0) {
|
||||
/* Check vs cwd */
|
||||
if (snprintf(fname3, sizeof fname3, "%s/%s", cwd, p) < (int)(sizeof fname3))
|
||||
sdirs[sdx++] = fname3;
|
||||
}
|
||||
}
|
||||
sdirs[sdx++] = NULL;
|
||||
|
||||
for (sdp = sdirs; *sdp != NULL && !found; sdp++) {
|
||||
#ifdef DEBUG_META_MODE
|
||||
DEBUG3(META, "%s:%u: looking for: %s\n",
|
||||
fname, lineno, *sdp);
|
||||
#endif
|
||||
if (cached_stat(*sdp, &cst) == 0) {
|
||||
found = true;
|
||||
p = *sdp;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
if (*p == '/') {
|
||||
if (cached_stat(p, &cst) == 0) {
|
||||
found = true;
|
||||
#ifdef DEBUG_META_MODE
|
||||
DEBUG3(META, "%s:%u: found: %s\n",
|
||||
fname, lineno, p);
|
||||
fname, lineno, p);
|
||||
#endif
|
||||
if (!S_ISDIR(cst.cst_mode) &&
|
||||
cst.cst_mtime > gn->mtime) {
|
||||
DEBUG3(META, "%s:%u: file '%s' is newer than the target...\n",
|
||||
fname, lineno, p);
|
||||
oodate = true;
|
||||
} else if (S_ISDIR(cst.cst_mode)) {
|
||||
/* Update the latest directory. */
|
||||
cached_realpath(p, latestdir);
|
||||
}
|
||||
} else if (errno == ENOENT && *p == '/' &&
|
||||
strncmp(p, cwd, cwdlen) != 0) {
|
||||
}
|
||||
} else {
|
||||
#ifdef DEBUG_META_MODE
|
||||
DEBUG3(META, "%s:%u: looking for: %s ...\n",
|
||||
fname, lineno, p);
|
||||
#endif
|
||||
rp = meta_resolve_path(fname1, sizeof(fname1), p,
|
||||
lcwd, &cst, sdirs);
|
||||
if (rp != NULL) {
|
||||
#ifdef DEBUG_META_MODE
|
||||
DEBUG3(META, "%s:%u: found: %s\n",
|
||||
fname, lineno, rp);
|
||||
#endif
|
||||
p = rp;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
if (!S_ISDIR(cst.cst_mode) &&
|
||||
cst.cst_mtime > gn->mtime) {
|
||||
DEBUG3(META, "%s:%u: file '%s' is newer than the target...\n",
|
||||
fname, lineno, p);
|
||||
oodate = true;
|
||||
} else if (S_ISDIR(cst.cst_mode)) {
|
||||
/* Update the latest directory. */
|
||||
cached_realpath(p, latestdir);
|
||||
set_sdirs(sdirs, 4, latestdir, lcwd, cwd);
|
||||
}
|
||||
} else if (errno == ENOENT) {
|
||||
if (*p != '/' || strncmp(p, cwd, cwdlen) != 0) {
|
||||
/*
|
||||
* A referenced file outside of CWD is missing.
|
||||
* We cannot catch every eventuality here...
|
||||
*/
|
||||
#ifdef DEBUG_META_MODE
|
||||
DEBUG3(META, "%s:%u: maybe missing: %s\n",
|
||||
fname, lineno, p);
|
||||
#endif
|
||||
append_if_new(&missingFiles, p);
|
||||
}
|
||||
}
|
||||
if (buf[0] == 'E') {
|
||||
/* previous latestdir is no longer relevant */
|
||||
strlcpy(latestdir, lcwd, sizeof latestdir);
|
||||
set_sdirs(sdirs, 4, latestdir, lcwd, cwd);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -1452,7 +1606,8 @@ meta_oodate(GNode *gn, bool oodate)
|
||||
}
|
||||
if (!oodate && buf[0] == 'L' && link_src != NULL)
|
||||
goto check_link_src;
|
||||
} else if (strcmp(buf, "CMD") == 0) {
|
||||
break;
|
||||
case META_CMD:
|
||||
/*
|
||||
* Compare the current command with the one in the
|
||||
* meta data file.
|
||||
@@ -1518,7 +1673,8 @@ meta_oodate(GNode *gn, bool oodate)
|
||||
free(cmd);
|
||||
cmdNode = cmdNode->next;
|
||||
}
|
||||
} else if (strcmp(buf, "CWD") == 0) {
|
||||
break;
|
||||
case META_CWD:
|
||||
/*
|
||||
* Check if there are extra commands now
|
||||
* that weren't in the meta data file.
|
||||
@@ -1534,8 +1690,13 @@ meta_oodate(GNode *gn, bool oodate)
|
||||
fname, lineno, p, curdir);
|
||||
oodate = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(freeit);
|
||||
|
||||
if (metaFilter || metaCmpFilter)
|
||||
Var_Delete(gn, META_FILTER_VAR);
|
||||
|
||||
fclose(fp);
|
||||
if (!Lst_IsEmpty(&missingFiles)) {
|
||||
@@ -1543,10 +1704,12 @@ meta_oodate(GNode *gn, bool oodate)
|
||||
fname, (char *)missingFiles.first->datum);
|
||||
oodate = true;
|
||||
}
|
||||
if (!oodate && !have_filemon && filemonMissing) {
|
||||
#ifdef USE_FILEMON
|
||||
if (!oodate && section != META_FILEMON && filemonMissing) {
|
||||
DEBUG1(META, "%s: missing filemon data\n", fname);
|
||||
oodate = true;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
if (writeMeta && (metaMissing || (gn->type & OP_META))) {
|
||||
const char *cp = NULL;
|
||||
|
||||
@@ -1,3 +1,37 @@
|
||||
2026-07-04 Simon J Gerraty <[email protected]>
|
||||
|
||||
* install-mk (MK_VERSION): 20260704
|
||||
|
||||
2026-07-03 Simon J Gerraty <[email protected]>
|
||||
|
||||
* dirdeps.mk: make use of alternation support in latest bmake
|
||||
when setting .MAKE.META.IGNORE_FILTER so we can get both
|
||||
Makefile.depend* and *.mk to make cache out-of-date.
|
||||
|
||||
2026-07-02 Simon J Gerraty <[email protected]>
|
||||
|
||||
* meta2deps.py: detect corrupted filemon data on Linux,
|
||||
caused by lost newlines.
|
||||
|
||||
2026-06-21 Simon J Gerraty <[email protected]>
|
||||
|
||||
* install-mk (MK_VERSION): 20260621
|
||||
|
||||
* gendirdeps.mk: more debug output
|
||||
|
||||
* meta.autodep.mk: remove extra } from GENDIRDEPS_ENV
|
||||
|
||||
2026-06-19 Simon J Gerraty <[email protected]>
|
||||
|
||||
* install-mk (MK_VERSION): 20260619
|
||||
|
||||
* install-new.mk: for POSIX_SHELL we need .new*
|
||||
rather than just .new
|
||||
|
||||
2026-05-21 Simon J Gerraty <[email protected]>
|
||||
|
||||
* meta2deps.{py,sh}: skip pathnames with spaces - not worth the pain.
|
||||
|
||||
2026-05-09 Simon J Gerraty <[email protected]>
|
||||
|
||||
* gendirdeps.mk: also apply ':S,/$,,' and ':C,/(\.[^.]*)$,\1,'
|
||||
|
||||
+5
-1
@@ -1,4 +1,4 @@
|
||||
# $Id: dirdeps.mk,v 1.178 2026/05/09 20:33:46 sjg Exp $
|
||||
# $Id: dirdeps.mk,v 1.179 2026/07/03 15:46:16 sjg Exp $
|
||||
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
#
|
||||
@@ -570,7 +570,11 @@ M_oneperline = @x@\\${.newline} $$x@
|
||||
BUILD_DIRDEPS = no
|
||||
|
||||
# ignore anything but these
|
||||
.if ${MAKE_VERSION} > 20260702
|
||||
.MAKE.META.IGNORE_FILTER = M*{/${.MAKE.DEPENDFILE_PREFIX}*,.mk}
|
||||
.else
|
||||
.MAKE.META.IGNORE_FILTER = M*/${.MAKE.DEPENDFILE_PREFIX}*
|
||||
.endif
|
||||
|
||||
dirdeps: dirdeps-cached
|
||||
dirdeps-cached: ${DIRDEPS_CACHE} .MAKE
|
||||
|
||||
+17
-3
@@ -1,4 +1,4 @@
|
||||
# $Id: gendirdeps.mk,v 1.55 2026/05/09 20:46:13 sjg Exp $
|
||||
# $Id: gendirdeps.mk,v 1.57 2026/06/21 19:04:57 sjg Exp $
|
||||
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
#
|
||||
@@ -87,6 +87,12 @@ _debug.gendirdeps = 0
|
||||
|
||||
all:
|
||||
|
||||
.if ${_debug.gendirdeps}
|
||||
.if ${DEBUG_GENDIRDEPS:M-d*}
|
||||
.MAKEFLAGS: ${DEBUG_GENDIRDEPS:M-d*}
|
||||
.endif
|
||||
.endif
|
||||
|
||||
_CURDIR ?= ${.CURDIR}
|
||||
_OBJDIR ?= ${.OBJDIR}
|
||||
_OBJTOP ?= ${OBJTOP}
|
||||
@@ -157,10 +163,12 @@ META2DEPS := ${META2DEPS}
|
||||
|
||||
.if ${_debug.gendirdeps} && ${DEBUG_GENDIRDEPS:Mmeta2d*} != ""
|
||||
_time = time
|
||||
_set_x = set -x;
|
||||
_sh_x = sh -x
|
||||
_py_d = -ddd
|
||||
.else
|
||||
_time =
|
||||
_set_x =
|
||||
_sh_x =
|
||||
_py_d =
|
||||
.endif
|
||||
@@ -238,7 +246,11 @@ x != echo; for m in $$_meta_files; do echo $$m; done > meta.list
|
||||
_meta_files_arg:= ${_meta_files}
|
||||
.endif
|
||||
|
||||
dir_list != cd ${_OBJDIR} && \
|
||||
.if ${_debug.gendirdeps}
|
||||
.info ${RELDIR}: _meta_files_arg='${_meta_files_arg}'
|
||||
.endif
|
||||
|
||||
dir_list != cd ${_OBJDIR} && ${_set_x} \
|
||||
${META2DEPS_CMD} MACHINE=${MACHINE} \
|
||||
SRCTOP=${SRCTOP} RELDIR=${RELDIR} CURDIR=${_CURDIR} \
|
||||
${META2DEPS_ARGS} \
|
||||
@@ -250,6 +262,9 @@ dir_list != cd ${_OBJDIR} && \
|
||||
.warning Skipping ${_DEPENDFILE:S,${SRCTOP}/,,}
|
||||
# we are not going to update anything
|
||||
.else
|
||||
.if ${_debug.gendirdeps}
|
||||
.info ${RELDIR}: raw_dir_list='${dir_list}'
|
||||
.endif
|
||||
dpadd_dir_list=
|
||||
.if !empty(DPADD)
|
||||
_nonlibs := ${DPADD:T:Nlib*:N*include}
|
||||
@@ -270,7 +285,6 @@ ddeps != cat ${ddep_list:O:u} | ${META2DEPS_FILTER} ${_skip_gendirdeps} \
|
||||
sed ${GENDIRDEPS_SEDCMDS}
|
||||
|
||||
.if ${_debug.gendirdeps}
|
||||
.info ${RELDIR}: raw_dir_list='${dir_list}'
|
||||
.info ${RELDIR}: ddeps='${ddeps}'
|
||||
.endif
|
||||
dir_list += ${ddeps}
|
||||
|
||||
+2
-2
@@ -59,7 +59,7 @@
|
||||
# Simon J. Gerraty <[email protected]>
|
||||
|
||||
# RCSid:
|
||||
# $Id: install-mk,v 1.275 2026/04/24 19:56:48 sjg Exp $
|
||||
# $Id: install-mk,v 1.278 2026/07/04 16:44:08 sjg Exp $
|
||||
#
|
||||
# @(#) Copyright (c) 1994-2025 Simon J. Gerraty
|
||||
#
|
||||
@@ -69,7 +69,7 @@
|
||||
# [email protected]
|
||||
#
|
||||
|
||||
MK_VERSION=20260424
|
||||
MK_VERSION=20260704
|
||||
OWNER=
|
||||
GROUP=
|
||||
MODE=444
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
# $Id: install-new.mk,v 1.9 2025/11/19 17:44:15 sjg Exp $
|
||||
# $Id: install-new.mk,v 1.10 2026/06/19 19:47:03 sjg Exp $
|
||||
#
|
||||
# @(#) Copyright (c) 2009, Simon J. Gerraty
|
||||
#
|
||||
@@ -47,7 +47,7 @@ InstallNew= ${CmpCpMv}; InstallNew() { \
|
||||
for new in "$$@"; do \
|
||||
if test $$_t $$new; then \
|
||||
if ${isPOSIX_SHELL:Ufalse}; then \
|
||||
target=$${new%.new}; \
|
||||
target=$${new%.new*}; \
|
||||
else \
|
||||
target=`expr $$new : '\(.*\).new'`; \
|
||||
fi; \
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
# $Id: meta.autodep.mk,v 1.72 2026/01/11 05:32:29 sjg Exp $
|
||||
# $Id: meta.autodep.mk,v 1.73 2026/06/21 19:01:21 sjg Exp $
|
||||
#
|
||||
# @(#) Copyright (c) 2010-2025, Simon J. Gerraty
|
||||
#
|
||||
@@ -275,7 +275,7 @@ META_FILES = ${.MAKE.META.FILES:N.depend*}
|
||||
# objects in subdirs
|
||||
META_FILE_FILTER += S,${_OBJDIR}/,,:O:u
|
||||
# we have to defer evaluation until the target script runs
|
||||
GENDIRDEPS_ENV += META_FILES="${META_FILES:${META_FILE_FILTER:O:u:ts:}}}"
|
||||
GENDIRDEPS_ENV += META_FILES="${META_FILES:${META_FILE_FILTER:O:u:ts:}}"
|
||||
|
||||
.if ${_debug.autodep}
|
||||
.info ${_DEPENDFILE:S,${SRCTOP}/,,}: ${_depend} ${.PARSEDIR}/gendirdeps.mk ${META2DEPS} xtras=${META_XTRAS}
|
||||
|
||||
+19
-1
@@ -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.55 2026/01/13 04:32:45 sjg Exp $
|
||||
$Id: meta2deps.py,v 1.57 2026/07/03 15:45:29 sjg Exp $
|
||||
|
||||
Copyright (c) 2011-2025, Simon J. Gerraty
|
||||
Copyright (c) 2011-2017, Juniper Networks, Inc.
|
||||
@@ -73,6 +73,13 @@ import re
|
||||
import sys
|
||||
import stat
|
||||
|
||||
# Attempt to match bogus filemon data that could potentitally be truncated by
|
||||
# the unreliable Linux filemon such as:
|
||||
# R 2712488 /X 2712597 0
|
||||
# or
|
||||
# R 1096904 /path/foo-linuR 1096904 /path/bar.py
|
||||
filemon_fused_re = re.compile(r'[CDEFLMRSVWX] [0-9]+ ')
|
||||
|
||||
def resolve(path, cwd, last_dir=None, debug=0, debug_out=sys.stderr):
|
||||
"""
|
||||
Return an absolute path, resolving via cwd or last_dir if needed.
|
||||
@@ -515,6 +522,17 @@ class MetaFile:
|
||||
if self.debug > 2:
|
||||
print('op={} elen={} wlen={} line="{}"'.format(w[0], elen, wlen, line.strip()), file=self.debug_out)
|
||||
if wlen != elen:
|
||||
if wlen > elen and w[0] in 'CELMRW':
|
||||
# Before assuming spaces in a pathname, make sure this
|
||||
# isn't two records fused onto one line because of
|
||||
# dropped data (unreliable Linux filemon).
|
||||
if filemon_fused_re.search(line.split(None, 2)[2]):
|
||||
raise AssertionError('corrupted filemon data: fused records (dropped newline): {} in: {}'.format(error_name, line.strip()))
|
||||
# It could just be spaces in pathname.
|
||||
# More trouble than its worth, just skip it.
|
||||
if self.debug > 0:
|
||||
print('Skipping: wrong number of words: expected {} got {} in: {}'.format(elen, wlen, line), file=self.debug_out)
|
||||
continue
|
||||
raise AssertionError('corrupted filemon data: wrong number of words: expected {} got {} in: {}'.format(elen, wlen, line))
|
||||
|
||||
pid = int(w[1])
|
||||
|
||||
+13
-2
@@ -77,7 +77,7 @@
|
||||
|
||||
|
||||
# RCSid:
|
||||
# $Id: meta2deps.sh,v 1.26 2025/12/08 17:34:02 sjg Exp $
|
||||
# $Id: meta2deps.sh,v 1.27 2026/05/22 00:33:26 sjg Exp $
|
||||
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
#
|
||||
@@ -162,6 +162,10 @@ error() {
|
||||
exit 1
|
||||
}
|
||||
|
||||
warning() {
|
||||
echo "WARNING: $@" >&2
|
||||
}
|
||||
|
||||
meta2deps() {
|
||||
DPDEPS=
|
||||
SRCTOPS=$SRCTOP
|
||||
@@ -273,8 +277,15 @@ meta2deps() {
|
||||
;;
|
||||
\#*) ;; # ok
|
||||
[LM],) error "missing path2 in: '$op $pid $path'";;
|
||||
[LMX],*" "*) error "wrong number of words in: '$op $pid $path $path2'";;
|
||||
[LMX],*" "*)
|
||||
warning "wrong number of words in: '$op $pid $path $path2'"
|
||||
continue
|
||||
;;
|
||||
*,|[LMX],*) ;; # ok
|
||||
[CELMRW],*)
|
||||
warning "wrong number of words in: '$op $pid $path $path2'"
|
||||
continue
|
||||
;;
|
||||
*) error "wrong number of words in: '$op $pid $path $path2'";;
|
||||
esac
|
||||
# we track cwd and ldir (of interest) per pid
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
# $Id: sys.dirdeps.mk,v 1.20 2026/04/24 19:56:01 sjg Exp $
|
||||
# $Id: sys.dirdeps.mk,v 1.21 2026/05/22 00:32:40 sjg Exp $
|
||||
#
|
||||
# @(#) Copyright (c) 2012-2023, Simon J. Gerraty
|
||||
#
|
||||
@@ -15,8 +15,8 @@
|
||||
# Include from [local.]sys.mk - if doing DIRDEPS_BUILD
|
||||
# we should not be here otherwise
|
||||
MK_DIRDEPS_BUILD ?= yes
|
||||
MK_META_AUTODEP ?= yes
|
||||
# these are all implied
|
||||
MK_META_AUTODEP ?= yes
|
||||
MK_AUTO_OBJ ?= yes
|
||||
MK_META_MODE ?= yes
|
||||
MK_STAGING ?= yes
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $NetBSD: parse.c,v 1.756 2026/04/06 17:13:55 rillig Exp $ */
|
||||
/* $NetBSD: parse.c,v 1.757 2026/06/09 08:27:08 rillig 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.756 2026/04/06 17:13:55 rillig Exp $");
|
||||
MAKE_RCSID("$NetBSD: parse.c,v 1.757 2026/06/09 08:27:08 rillig Exp $");
|
||||
|
||||
/* Detects a multiple-inclusion guard in a makefile. */
|
||||
typedef enum {
|
||||
@@ -2838,22 +2838,23 @@ Parse_GuardEndif(void)
|
||||
static char *
|
||||
FindSemicolon(char *p)
|
||||
{
|
||||
int depth = 0;
|
||||
if (strchr(p, ';') == NULL)
|
||||
return NULL;
|
||||
|
||||
for (; *p != '\0'; p++) {
|
||||
if (*p == '\\' && p[1] != '\0') {
|
||||
while (*p != '\0') {
|
||||
if (*p == ';')
|
||||
return p;
|
||||
if (*p == '$' && p[1] == '$')
|
||||
p += 2;
|
||||
else if (*p == '$') {
|
||||
const char *cp = p;
|
||||
FStr value = Var_Parse(&cp, SCOPE_GLOBAL, VARE_PARSE);
|
||||
FStr_Done(&value);
|
||||
p += cp - p;
|
||||
} else
|
||||
p++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*p == '$' && (p[1] == '(' || p[1] == '{'))
|
||||
depth++;
|
||||
else if (depth > 0 && (*p == ')' || *p == '}'))
|
||||
depth--;
|
||||
else if (depth == 0 && *p == ';')
|
||||
break;
|
||||
}
|
||||
return p;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2864,7 +2865,7 @@ ParseDependencyLine(char *line)
|
||||
|
||||
{
|
||||
char *semicolon = FindSemicolon(line);
|
||||
if (*semicolon != '\0') {
|
||||
if (semicolon != NULL) {
|
||||
/* Terminate the dependency list at the ';' */
|
||||
*semicolon = '\0';
|
||||
shellcmd = semicolon + 1;
|
||||
|
||||
+16
-4
@@ -1,5 +1,17 @@
|
||||
make: dep.mk:11: Inconsistent operator for only-colon
|
||||
make: dep.mk:13: Inconsistent operator for only-colon
|
||||
make: dep.mk:18: Inconsistent operator for only-colon
|
||||
in make[1] in directory "<curdir>"
|
||||
make: dep.mk:20: Inconsistent operator for only-colon
|
||||
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 "parse-only-colon" in unit-tests
|
||||
sub exit status 1
|
||||
Making renamed-parse-semicolon-in-source out of nothing.
|
||||
Making parse-semicolon-in-source from renamed-parse-semicolon-in-source.
|
||||
make: Malformed expression at "$$-rest"
|
||||
in make[1] in directory "<curdir>"
|
||||
semicolon-in-modifier.param: after semicolon
|
||||
parentheses-in-modifier.1-12-23-3: after semicolon
|
||||
var-semicolon.: after semicolon
|
||||
double-dollar.$-rest: after semicolon
|
||||
sub exit status 2
|
||||
exit status 0
|
||||
+46
-8
@@ -1,8 +1,15 @@
|
||||
# $NetBSD: dep.mk,v 1.4 2023/06/01 07:27:30 rillig Exp $
|
||||
# $NetBSD: dep.mk,v 1.6 2026/06/09 08:27:08 rillig Exp $
|
||||
#
|
||||
# Tests for dependency declarations, such as "target: sources".
|
||||
|
||||
.MAIN: all
|
||||
all: .PHONY
|
||||
@${MAKE} -f ${MAKEFILE} parse-only-colon || echo "sub exit status $$?"
|
||||
@${MAKE} -f ${MAKEFILE} parse-semicolon-in-source
|
||||
@${MAKE} -f ${MAKEFILE} parse-semicolon || echo "sub exit status $$?"
|
||||
|
||||
|
||||
.if make(parse-only-colon)
|
||||
parse-only-colon: .PHONY
|
||||
|
||||
# As soon as a target is defined using one of the dependency operators, it is
|
||||
# restricted to this dependency operator and cannot use the others anymore.
|
||||
@@ -15,16 +22,47 @@ only-colon::
|
||||
# would be another error message.
|
||||
only-colon:
|
||||
|
||||
.endif
|
||||
|
||||
|
||||
# Before parse.c 1.158 from 2009-10-07, the parser broke dependency lines at
|
||||
# the first ';', without parsing expressions as such. It interpreted the
|
||||
# first ';' as the separator between the dependency and its commands, and the
|
||||
# '^' as a shell command.
|
||||
all: for-subst
|
||||
.for file in ${.PARSEFILE}
|
||||
for-subst: ${file:S;^;./;g}
|
||||
@echo ".for with :S;... OK"
|
||||
.endfor
|
||||
.if make(parse-semicolon-in-source)
|
||||
parse-semicolon-in-source: .PHONY
|
||||
|
||||
. for file in parse-semicolon-in-source
|
||||
parse-semicolon-in-source: ${file:S;^;renamed-;g}
|
||||
@echo "Making ${.TARGET} from ${.ALLSRC}."
|
||||
renamed-parse-semicolon-in-source:
|
||||
@echo "Making ${.TARGET} out of nothing."
|
||||
. endfor
|
||||
|
||||
.endif
|
||||
|
||||
|
||||
all:
|
||||
# Before parse.c 1.757 from 2026-06-09, the parser counted "$(" and "${" as
|
||||
# opening a brace level, and ")" and "}" as closing it. It didn't count a
|
||||
# plain "(" or "{" as opening, though. This simple counting resulted in
|
||||
# parse errors on modifiers containing parentheses or braces, as well as
|
||||
# semicolons.
|
||||
.if make(parse-semicolon)
|
||||
parse-semicolon: .PHONY
|
||||
|
||||
semicolon-in-modifier.${:Utarget:S;target;param;}:; @echo '$@: after semicolon'
|
||||
parse-semicolon: semicolon-in-modifier.param
|
||||
|
||||
parentheses-in-modifier.${:U123:C;(.);\1-\1;g}:; @echo '$@: after semicolon'
|
||||
parse-semicolon: parentheses-in-modifier.1-12-23-3
|
||||
|
||||
var-semicolon.$;:; @echo '$@: after semicolon'
|
||||
parse-semicolon: var-semicolon.
|
||||
|
||||
# Using actual dollars in target names is still tricky and not recommended,
|
||||
# due to multiple levels of expansion, that's where the 8 dollars come from.
|
||||
# expect: make: Malformed expression at "$$-rest"
|
||||
double-dollar.$$$;-$$$$-rest:; @echo '$@: after semicolon'
|
||||
parse-semicolon: double-dollar.$$$$-$$$$$$$$-rest
|
||||
|
||||
.endif
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
# $NetBSD: dir.mk,v 1.11 2023/12/19 19:33:40 rillig Exp $
|
||||
# $NetBSD: dir.mk,v 1.12 2026/07/03 15:31:35 sjg Exp $
|
||||
#
|
||||
# Tests for dir.c.
|
||||
|
||||
@@ -21,7 +21,7 @@ all: {one,two,three}
|
||||
.if target({one,two,three})
|
||||
. error
|
||||
.endif
|
||||
.if ${.ALLTARGETS:M{one,two,three}} != "{one,two,three}"
|
||||
.if ${.ALLTARGETS:M\{one,two,three\}} != "{one,two,three}"
|
||||
. error
|
||||
.endif
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# $NetBSD: varmod-match.mk,v 1.32 2025/06/29 09:40:13 rillig Exp $
|
||||
# $NetBSD: varmod-match.mk,v 1.33 2026/07/03 15:31:35 sjg Exp $
|
||||
#
|
||||
# Tests for the ':M' modifier, which keeps only those words that match the
|
||||
# given pattern.
|
||||
@@ -388,3 +388,13 @@ WORDS= [x- x x- y yyyyy
|
||||
.if ${:U:${:UM\\\:\\}}
|
||||
. error
|
||||
.endif
|
||||
|
||||
# :M supports alternation
|
||||
.if ${/bin/sh ../Makefile.inc cat .../mk/sys.mk:L:M*{Makefile*,.mk}} != "../Makefile.inc .../mk/sys.mk"
|
||||
. error
|
||||
.endif
|
||||
|
||||
# :M supports alternation
|
||||
.if ${{a} one and two {o} yes:L:M\{{a,e,i,o,u}\}} != "{a} {o}"
|
||||
. error
|
||||
.endif
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $NetBSD: var.c,v 1.1180 2026/04/06 17:13:55 rillig Exp $ */
|
||||
/* $NetBSD: var.c,v 1.1181 2026/07/03 15:31:35 sjg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
@@ -145,7 +145,7 @@
|
||||
#endif
|
||||
|
||||
/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */
|
||||
MAKE_RCSID("$NetBSD: var.c,v 1.1180 2026/04/06 17:13:55 rillig Exp $");
|
||||
MAKE_RCSID("$NetBSD: var.c,v 1.1181 2026/07/03 15:31:35 sjg Exp $");
|
||||
|
||||
/*
|
||||
* Variables are defined using one of the VAR=value assignments. Their
|
||||
@@ -2822,7 +2822,7 @@ ParseModifier_Match(const char **pp, const ModChain *ch)
|
||||
}
|
||||
|
||||
struct ModifyWord_MatchArgs {
|
||||
const char *pattern;
|
||||
StringList patterns;
|
||||
bool neg;
|
||||
bool error_reported;
|
||||
};
|
||||
@@ -2831,17 +2831,25 @@ static void
|
||||
ModifyWord_Match(Substring word, SepBuf *buf, void *data)
|
||||
{
|
||||
struct ModifyWord_MatchArgs *args = data;
|
||||
StringListNode *ln;
|
||||
StrMatchResult res;
|
||||
const char *pattern;
|
||||
|
||||
assert(word.end[0] == '\0'); /* assume null-terminated word */
|
||||
res = Str_Match(word.start, args->pattern);
|
||||
if (res.error != NULL && !args->error_reported) {
|
||||
args->error_reported = true;
|
||||
Parse_Error(PARSE_FATAL,
|
||||
"%s in pattern \"%s\" of modifier \"%s\"",
|
||||
res.error, args->pattern, args->neg ? ":N" : ":M");
|
||||
for (ln = args->patterns.first; ln != NULL; ln = ln->next) {
|
||||
pattern = ln->datum;
|
||||
res = Str_Match(word.start, pattern);
|
||||
if (res.error != NULL && !args->error_reported) {
|
||||
args->error_reported = true;
|
||||
Parse_Error(PARSE_FATAL,
|
||||
"%s in pattern \"%s\" of modifier \"%s\"",
|
||||
res.error, pattern, args->neg ? ":N" : ":M");
|
||||
}
|
||||
if (res.matched != args->neg) {
|
||||
SepBuf_AddSubstring(buf, word);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (res.matched != args->neg)
|
||||
SepBuf_AddSubstring(buf, word);
|
||||
}
|
||||
|
||||
/* :Mpattern or :Npattern */
|
||||
@@ -2855,10 +2863,30 @@ ApplyModifier_Match(const char **pp, ModChain *ch)
|
||||
|
||||
if (ModChain_ShouldEval(ch)) {
|
||||
struct ModifyWord_MatchArgs args;
|
||||
args.pattern = pattern;
|
||||
const char *brace;
|
||||
|
||||
Lst_Init(&args.patterns);
|
||||
if (mod == 'N')
|
||||
brace = NULL; /* not supported */
|
||||
else
|
||||
for (brace = strchr(pattern, '{'); brace != NULL;
|
||||
brace = strchr(++brace, '{')) {
|
||||
if (brace == pattern
|
||||
|| (brace[-1] != '\\' && brace[-1] != '$'))
|
||||
break;
|
||||
}
|
||||
|
||||
if (brace)
|
||||
ExpandCurly(pattern, brace, NULL, &args.patterns);
|
||||
else
|
||||
Lst_Append(&args.patterns, pattern);
|
||||
args.neg = mod == 'N';
|
||||
args.error_reported = false;
|
||||
ModifyWords(ch, ModifyWord_Match, &args, ch->oneBigWord);
|
||||
if (brace)
|
||||
Lst_DoneFree(&args.patterns);
|
||||
else
|
||||
Lst_Done(&args.patterns);
|
||||
}
|
||||
|
||||
free(pattern);
|
||||
|
||||
Reference in new issue
Block a user