Module Name: src
Committed By: rillig
Date: Fri Jun 23 04:56:54 UTC 2023
Modified Files:
src/usr.bin/make: cond.c dir.c str.c str.h var.c
src/usr.bin/make/unit-tests: cond-func-make.exp cond-func-make.mk
varmod-match-escape.exp varmod-match-escape.mk varmod-match.exp
varmod-match.mk
Log Message:
make: warn about malformed patterns in ':M', ':N' and '.if make(...)'
These patterns shouldn't occur in practice, as their results are tricky
to predict. Generate a warning for now, and maybe an error later.
Reviewed by sjg@.
To generate a diff of this commit:
cvs rdiff -u -r1.351 -r1.352 src/usr.bin/make/cond.c
cvs rdiff -u -r1.281 -r1.282 src/usr.bin/make/dir.c
cvs rdiff -u -r1.97 -r1.98 src/usr.bin/make/str.c
cvs rdiff -u -r1.16 -r1.17 src/usr.bin/make/str.h
cvs rdiff -u -r1.1057 -r1.1058 src/usr.bin/make/var.c
cvs rdiff -u -r1.2 -r1.3 src/usr.bin/make/unit-tests/cond-func-make.exp
cvs rdiff -u -r1.4 -r1.5 src/usr.bin/make/unit-tests/cond-func-make.mk
cvs rdiff -u -r1.17 -r1.18 \
src/usr.bin/make/unit-tests/varmod-match-escape.exp
cvs rdiff -u -r1.9 -r1.10 src/usr.bin/make/unit-tests/varmod-match-escape.mk \
src/usr.bin/make/unit-tests/varmod-match.exp
cvs rdiff -u -r1.14 -r1.15 src/usr.bin/make/unit-tests/varmod-match.mk
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/usr.bin/make/cond.c
diff -u src/usr.bin/make/cond.c:1.351 src/usr.bin/make/cond.c:1.352
--- src/usr.bin/make/cond.c:1.351 Wed Jun 21 04:20:20 2023
+++ src/usr.bin/make/cond.c Fri Jun 23 04:56:54 2023
@@ -1,4 +1,4 @@
-/* $NetBSD: cond.c,v 1.351 2023/06/21 04:20:20 sjg Exp $ */
+/* $NetBSD: cond.c,v 1.352 2023/06/23 04:56:54 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -92,7 +92,7 @@
#include "dir.h"
/* "@(#)cond.c 8.2 (Berkeley) 1/2/94" */
-MAKE_RCSID("$NetBSD: cond.c,v 1.351 2023/06/21 04:20:20 sjg Exp $");
+MAKE_RCSID("$NetBSD: cond.c,v 1.352 2023/06/23 04:56:54 rillig Exp $");
/*
* Conditional expressions conform to this grammar:
@@ -295,10 +295,19 @@ static bool
FuncMake(const char *targetPattern)
{
StringListNode *ln;
+ bool warned = false;
- for (ln = opts.create.first; ln != NULL; ln = ln->next)
- if (Str_Match(ln->datum, targetPattern))
+ for (ln = opts.create.first; ln != NULL; ln = ln->next) {
+ StrMatchResult res = Str_Match(ln->datum, targetPattern);
+ if (res.error != NULL && !warned) {
+ warned = true;
+ Parse_Error(PARSE_WARNING,
+ "%s in pattern argument '%s' to function 'make'",
+ res.error, targetPattern);
+ }
+ if (res.matched)
return true;
+ }
return false;
}
Index: src/usr.bin/make/dir.c
diff -u src/usr.bin/make/dir.c:1.281 src/usr.bin/make/dir.c:1.282
--- src/usr.bin/make/dir.c:1.281 Thu Jun 22 09:09:08 2023
+++ src/usr.bin/make/dir.c Fri Jun 23 04:56:54 2023
@@ -1,4 +1,4 @@
-/* $NetBSD: dir.c,v 1.281 2023/06/22 09:09:08 rillig Exp $ */
+/* $NetBSD: dir.c,v 1.282 2023/06/23 04:56:54 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -138,7 +138,7 @@
#include "job.h"
/* "@(#)dir.c 8.2 (Berkeley) 1/2/94" */
-MAKE_RCSID("$NetBSD: dir.c,v 1.281 2023/06/22 09:09:08 rillig Exp $");
+MAKE_RCSID("$NetBSD: dir.c,v 1.282 2023/06/23 04:56:54 rillig Exp $");
/*
* A search path is a list of CachedDir structures. A CachedDir has in it the
@@ -668,8 +668,10 @@ DirMatchFiles(const char *pattern, Cache
HashIter_InitSet(&hi, &dir->files);
while (HashIter_Next(&hi) != NULL) {
const char *base = hi.entry->key;
+ StrMatchResult res = Str_Match(base, pattern);
+ /* TODO: handle errors from res.error */
- if (!Str_Match(base, pattern))
+ if (!res.matched)
continue;
/*
Index: src/usr.bin/make/str.c
diff -u src/usr.bin/make/str.c:1.97 src/usr.bin/make/str.c:1.98
--- src/usr.bin/make/str.c:1.97 Thu Jun 22 16:59:17 2023
+++ src/usr.bin/make/str.c Fri Jun 23 04:56:54 2023
@@ -1,4 +1,4 @@
-/* $NetBSD: str.c,v 1.97 2023/06/22 16:59:17 rillig Exp $ */
+/* $NetBSD: str.c,v 1.98 2023/06/23 04:56:54 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -71,7 +71,7 @@
#include "make.h"
/* "@(#)str.c 5.8 (Berkeley) 6/1/90" */
-MAKE_RCSID("$NetBSD: str.c,v 1.97 2023/06/22 16:59:17 rillig Exp $");
+MAKE_RCSID("$NetBSD: str.c,v 1.98 2023/06/23 04:56:54 rillig Exp $");
static HashTable interned_strings;
@@ -316,13 +316,12 @@ in_range(char e1, char c, char e2)
* Test if a string matches a pattern like "*.[ch]". The pattern matching
* characters are '*', '?' and '[]', as in fnmatch(3).
*
- * XXX: this function does not detect or report malformed patterns.
- *
* See varmod-match.mk for examples and edge cases.
*/
-bool
+StrMatchResult
Str_Match(const char *str, const char *pat)
{
+ StrMatchResult res = { NULL, false };
const char *fixed_str, *fixed_pat;
bool asterisk, matched;
@@ -336,7 +335,7 @@ match_fixed_length:
matched = false;
for (; *pat != '\0' && *pat != '*'; str++, pat++) {
if (*str == '\0')
- return false;
+ return res;
if (*pat == '?') /* match any single character */
continue;
@@ -346,6 +345,9 @@ match_fixed_length:
pat += neg ? 2 : 1;
for (;;) {
+ if (*pat == '\0')
+ res.error =
+ "Unfinished character list";
if (*pat == ']' || *pat == '\0') {
if (neg)
break;
@@ -354,8 +356,13 @@ match_fixed_length:
if (*pat == *str)
break;
if (pat[1] == '-') {
- if (pat[2] == '\0')
- return neg;
+ if (pat[2] == '\0') {
+ res.error =
+ "Unfinished character "
+ "range";
+ res.matched = neg;
+ return res;
+ }
if (in_range(pat[0], *str, pat[2]))
break;
pat += 2;
@@ -381,9 +388,11 @@ match_fixed_length:
match_done:
if (!asterisk) {
if (!matched)
- return false;
- if (*pat == '\0')
- return *str == '\0';
+ return res;
+ if (*pat == '\0') {
+ res.matched = *str == '\0';
+ return res;
+ }
asterisk = true;
} else {
if (!matched) {
@@ -391,8 +400,10 @@ match_done:
goto match_fixed_length;
}
if (*pat == '\0') {
- if (*str == '\0')
- return true;
+ if (*str == '\0') {
+ res.matched = true;
+ return res;
+ }
fixed_str += strlen(str);
goto match_fixed_length;
}
@@ -400,8 +411,10 @@ match_done:
while (*pat == '*')
pat++;
- if (*pat == '\0')
- return true;
+ if (*pat == '\0') {
+ res.matched = true;
+ return res;
+ }
fixed_str = str;
fixed_pat = pat;
goto match_fixed_length;
Index: src/usr.bin/make/str.h
diff -u src/usr.bin/make/str.h:1.16 src/usr.bin/make/str.h:1.17
--- src/usr.bin/make/str.h:1.16 Mon Dec 5 23:41:24 2022
+++ src/usr.bin/make/str.h Fri Jun 23 04:56:54 2023
@@ -1,4 +1,4 @@
-/* $NetBSD: str.h,v 1.16 2022/12/05 23:41:24 rillig Exp $ */
+/* $NetBSD: str.h,v 1.17 2023/06/23 04:56:54 rillig Exp $ */
/*
Copyright (c) 2021 Roland Illig <[email protected]>
@@ -70,6 +70,11 @@ typedef struct SubstringWords {
void *freeIt;
} SubstringWords;
+typedef struct StrMatchResult {
+ const char *error;
+ bool matched;
+} StrMatchResult;
+
MAKE_INLINE FStr
FStr_Init(const char *str, void *freeIt)
@@ -336,7 +341,7 @@ SubstringWords_Free(SubstringWords w)
char *str_concat2(const char *, const char *);
char *str_concat3(const char *, const char *, const char *);
-bool Str_Match(const char *, const char *);
+StrMatchResult Str_Match(const char *, const char *);
void Str_Intern_Init(void);
void Str_Intern_End(void);
Index: src/usr.bin/make/var.c
diff -u src/usr.bin/make/var.c:1.1057 src/usr.bin/make/var.c:1.1058
--- src/usr.bin/make/var.c:1.1057 Thu Jun 22 08:55:33 2023
+++ src/usr.bin/make/var.c Fri Jun 23 04:56:54 2023
@@ -1,4 +1,4 @@
-/* $NetBSD: var.c,v 1.1057 2023/06/22 08:55:33 rillig Exp $ */
+/* $NetBSD: var.c,v 1.1058 2023/06/23 04:56:54 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -139,7 +139,7 @@
#include "metachar.h"
/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: var.c,v 1.1057 2023/06/22 08:55:33 rillig Exp $");
+MAKE_RCSID("$NetBSD: var.c,v 1.1058 2023/06/23 04:56:54 rillig Exp $");
/*
* Variables are defined using one of the VAR=value assignments. Their
@@ -2793,14 +2793,23 @@ ParseModifier_Match(const char **pp, con
struct ModifyWord_MatchArgs {
const char *pattern;
bool neg;
+ bool error_reported;
};
static void
ModifyWord_Match(Substring word, SepBuf *buf, void *data)
{
struct ModifyWord_MatchArgs *args = data;
+ StrMatchResult res;
assert(word.end[0] == '\0'); /* assume null-terminated word */
- if (Str_Match(word.start, args->pattern) != args->neg)
+ res = Str_Match(word.start, args->pattern);
+ if (res.error != NULL && !args->error_reported) {
+ args->error_reported = true;
+ Parse_Error(PARSE_WARNING,
+ "%s in pattern '%s' of modifier '%s'",
+ res.error, args->pattern, args->neg ? ":N" : ":M");
+ }
+ if (res.matched != args->neg)
SepBuf_AddSubstring(buf, word);
}
@@ -2817,6 +2826,7 @@ ApplyModifier_Match(const char **pp, Mod
struct ModifyWord_MatchArgs args;
args.pattern = pattern;
args.neg = mod == 'N';
+ args.error_reported = false;
ModifyWords(ch, ModifyWord_Match, &args, ch->oneBigWord);
}
Index: src/usr.bin/make/unit-tests/cond-func-make.exp
diff -u src/usr.bin/make/unit-tests/cond-func-make.exp:1.2 src/usr.bin/make/unit-tests/cond-func-make.exp:1.3
--- src/usr.bin/make/unit-tests/cond-func-make.exp:1.2 Fri Sep 25 20:11:06 2020
+++ src/usr.bin/make/unit-tests/cond-func-make.exp Fri Jun 23 04:56:54 2023
@@ -1,3 +1,4 @@
+make: "cond-func-make.mk" line 24: warning: Unfinished character list in pattern argument '[' to function 'make'
: via-cmdline
: via-dot-makeflags
exit status 0
Index: src/usr.bin/make/unit-tests/cond-func-make.mk
diff -u src/usr.bin/make/unit-tests/cond-func-make.mk:1.4 src/usr.bin/make/unit-tests/cond-func-make.mk:1.5
--- src/usr.bin/make/unit-tests/cond-func-make.mk:1.4 Thu Jun 22 09:09:08 2023
+++ src/usr.bin/make/unit-tests/cond-func-make.mk Fri Jun 23 04:56:54 2023
@@ -1,4 +1,4 @@
-# $NetBSD: cond-func-make.mk,v 1.4 2023/06/22 09:09:08 rillig Exp $
+# $NetBSD: cond-func-make.mk,v 1.5 2023/06/23 04:56:54 rillig Exp $
#
# Tests for the make() function in .if conditions, which tests whether
# the argument has been passed as a target via the command line or later
@@ -20,7 +20,7 @@
. error
.endif
-# TODO: warn about the malformed pattern
+# expect+1: warning: Unfinished character list in pattern argument '[' to function 'make'
.if make([)
. error
.endif
Index: src/usr.bin/make/unit-tests/varmod-match-escape.exp
diff -u src/usr.bin/make/unit-tests/varmod-match-escape.exp:1.17 src/usr.bin/make/unit-tests/varmod-match-escape.exp:1.18
--- src/usr.bin/make/unit-tests/varmod-match-escape.exp:1.17 Thu Jun 1 20:56:35 2023
+++ src/usr.bin/make/unit-tests/varmod-match-escape.exp Fri Jun 23 04:56:54 2023
@@ -34,6 +34,8 @@ make: "varmod-match-escape.mk" line 43:
Global: .MAKEFLAGS = -r -k -d cv -d
Global: .MAKEFLAGS = -r -k -d cv -d 0
make: "varmod-match-escape.mk" line 69: Dollar followed by nothing
+make: "varmod-match-escape.mk" line 110: warning: Unfinished character list in pattern '[A-]' of modifier ':M'
+make: "varmod-match-escape.mk" line 110: warning: Unfinished character list in pattern '[^A-]' of modifier ':M'
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
Index: src/usr.bin/make/unit-tests/varmod-match-escape.mk
diff -u src/usr.bin/make/unit-tests/varmod-match-escape.mk:1.9 src/usr.bin/make/unit-tests/varmod-match-escape.mk:1.10
--- src/usr.bin/make/unit-tests/varmod-match-escape.mk:1.9 Thu Jun 22 20:36:24 2023
+++ src/usr.bin/make/unit-tests/varmod-match-escape.mk Fri Jun 23 04:56:54 2023
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-match-escape.mk,v 1.9 2023/06/22 20:36:24 rillig Exp $
+# $NetBSD: varmod-match-escape.mk,v 1.10 2023/06/23 04:56:54 rillig Exp $
#
# As of 2020-08-01, the :M and :N modifiers interpret backslashes differently,
# depending on whether there was a variable expression somewhere before the
@@ -105,6 +105,8 @@ EXP.[^A-]]= a
EXP.[^A-]]]= a]
.for pattern in [A-] [A-]] [A-]]] [^A-] [^A-]] [^A-]]]
+# expect+2: warning: Unfinished character list in pattern '[A-]' of modifier ':M'
+# expect+1: warning: Unfinished character list in pattern '[^A-]' of modifier ':M'
. if ${WORDS:M${pattern}} != ${EXP.${pattern}}
. warning ${pattern}: ${WORDS:M${pattern}} != ${EXP.${pattern}}
. endif
Index: src/usr.bin/make/unit-tests/varmod-match.exp
diff -u src/usr.bin/make/unit-tests/varmod-match.exp:1.9 src/usr.bin/make/unit-tests/varmod-match.exp:1.10
--- src/usr.bin/make/unit-tests/varmod-match.exp:1.9 Thu Jun 22 13:02:42 2023
+++ src/usr.bin/make/unit-tests/varmod-match.exp Fri Jun 23 04:56:54 2023
@@ -10,8 +10,16 @@ CondParser_Eval: ${:Ua \$ sign:M*$$*} !=
Comparing "$" != "$"
CondParser_Eval: ${:Ua \$ sign any-asterisk:M*\$*} != "any-asterisk"
Comparing "any-asterisk" != "any-asterisk"
-make: "varmod-match.mk" line 161: Unknown modifier "]"
-make: "varmod-match.mk" line 161: Malformed conditional (${ ${:U\:} ${:U\:\:} :L:M[:]} != ":")
+make: "varmod-match.mk" line 162: warning: Unfinished character list in pattern '[' of modifier ':M'
+make: "varmod-match.mk" line 162: Unknown modifier "]"
+make: "varmod-match.mk" line 162: Malformed conditional (${ ${:U\:} ${:U\:\:} :L:M[:]} != ":")
+make: "varmod-match.mk" line 205: warning: Unfinished character list in pattern 'a[' of modifier ':M'
+make: "varmod-match.mk" line 213: warning: Unfinished character list in pattern 'a[^' of modifier ':M'
+make: "varmod-match.mk" line 221: warning: Unfinished character list in pattern '[-x1-3' of modifier ':M'
+make: "varmod-match.mk" line 229: warning: Unfinished character list in pattern '*[-x1-3' of modifier ':M'
+make: "varmod-match.mk" line 238: warning: Unfinished character list in pattern '[^-x1-3' of modifier ':M'
+make: "varmod-match.mk" line 258: warning: Unfinished character range in pattern '[x-' of modifier ':M'
+make: "varmod-match.mk" line 270: warning: Unfinished character range in pattern '[^x-' of modifier ':M'
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
Index: src/usr.bin/make/unit-tests/varmod-match.mk
diff -u src/usr.bin/make/unit-tests/varmod-match.mk:1.14 src/usr.bin/make/unit-tests/varmod-match.mk:1.15
--- src/usr.bin/make/unit-tests/varmod-match.mk:1.14 Thu Jun 22 12:59:54 2023
+++ src/usr.bin/make/unit-tests/varmod-match.mk Fri Jun 23 04:56:54 2023
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-match.mk,v 1.14 2023/06/22 12:59:54 rillig Exp $
+# $NetBSD: varmod-match.mk,v 1.15 2023/06/23 04:56:54 rillig Exp $
#
# Tests for the :M variable modifier, which filters words that match the
# given pattern.
@@ -156,6 +156,7 @@ WORDS= a\b a[\]b ab
.endif
# [:] matches never since the ':' starts the next modifier
+# expect+3: warning: Unfinished character list in pattern '[' of modifier ':M'
# expect+2: Unknown modifier "]"
# expect+1: Malformed conditional (${ ${:U\:} ${:U\:\:} :L:M[:]} != ":")
.if ${ ${:U\:} ${:U\:\:} :L:M[:]} != ":"
@@ -200,6 +201,7 @@ WORDS= - -]
# [ Incomplete empty character list, never matches.
WORDS= a a[
+# expect+1: warning: Unfinished character list in pattern 'a[' of modifier ':M'
.if ${WORDS:Ma[} != ""
. error
.endif
@@ -207,6 +209,7 @@ WORDS= a a[
# [^ Incomplete negated empty character list, matches any single
# character.
WORDS= a a[ aX
+# expect+1: warning: Unfinished character list in pattern 'a[^' of modifier ':M'
.if ${WORDS:Ma[^} != "a[ aX"
. error
.endif
@@ -214,6 +217,7 @@ WORDS= a a[ aX
# [-x1-3 Incomplete character list, matches those elements that can be
# parsed without lookahead.
WORDS= - + x xx 0 1 2 3 4 [x1-3
+# expect+1: warning: Unfinished character list in pattern '[-x1-3' of modifier ':M'
.if ${WORDS:M[-x1-3} != "- x 1 2 3"
. error
.endif
@@ -221,6 +225,7 @@ WORDS= - + x xx 0 1 2 3 4 [x1-3
# *[-x1-3 Incomplete character list after a wildcard, matches those
# words that end with one of the characters from the list.
WORDS= - + x xx 0 1 2 3 4 00 01 10 11 000 001 010 011 100 101 110 111 [x1-3
+# expect+1: warning: Unfinished character list in pattern '*[-x1-3' of modifier ':M'
.if ${WORDS:M*[-x1-3} != "- x xx 1 2 3 01 11 001 011 101 111 [x1-3"
. warning ${WORDS:M*[-x1-3}
.endif
@@ -229,6 +234,7 @@ WORDS= - + x xx 0 1 2 3 4 00 01 10 11 0
# Incomplete negated character list, matches any character
# except those elements that can be parsed without lookahead.
WORDS= - + x xx 0 1 2 3 4 [x1-3
+# expect+1: warning: Unfinished character list in pattern '[^-x1-3' of modifier ':M'
.if ${WORDS:M[^-x1-3} != "+ 0 4"
. error
.endif
@@ -248,6 +254,7 @@ WORDS= \\ \a ${:Ux\\}
# [x- Incomplete character list containing an incomplete character
# range, matches only the 'x'.
WORDS= [x- x x- y
+# expect+1: warning: Unfinished character range in pattern '[x-' of modifier ':M'
.if ${WORDS:M[x-} != "x"
. error
.endif
@@ -259,6 +266,7 @@ WORDS= [x- x x- y
# XXX: Even matches strings that are longer than a single
# character.
WORDS= [x- x x- y yyyyy
+# expect+1: warning: Unfinished character range in pattern '[^x-' of modifier ':M'
.if ${WORDS:M[^x-} != "[x- y yyyyy"
. error
.endif