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 <ril...@netbsd.org> @@ -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