diff options
-rw-r--r-- | build2/parser.cxx | 23 | ||||
-rw-r--r-- | doc/manual.cli | 9 | ||||
-rw-r--r-- | tests/name/pattern.test | 13 |
3 files changed, 32 insertions, 13 deletions
diff --git a/build2/parser.cxx b/build2/parser.cxx index 86f45cd..96694c5 100644 --- a/build2/parser.cxx +++ b/build2/parser.cxx @@ -3159,12 +3159,23 @@ namespace build2 // Resolve the target if there is one. If we fail, then this is not // a pattern. // - const target_type* tt (tp != nullptr && scope_ != nullptr - ? scope_->find_target_type (*tp) - : nullptr); + const target_type* ttp (tp != nullptr && scope_ != nullptr + ? scope_->find_target_type (*tp) + : nullptr); - if (tp == nullptr || tt != nullptr) + if (tp == nullptr || ttp != nullptr) { + // Reset the detect pattern mode to expand if the pattern is not + // followed by the inclusion/exclusion pattern/match. Note that + // if it is '}' (i.e., the end of the group), then it is a single + // pattern and the expansion is what we want. + // + char c; + if (pmode == pattern_mode::detect && + (tt != type::word || + ((c = peeked ().value[0]) != '+' && c != '-'))) + pmode = pattern_mode::expand; + if (pmode == pattern_mode::expand) { count = expand_name_pattern (get_location (t), @@ -3172,7 +3183,7 @@ namespace build2 ns, what, pairn, - dp, tp, tt); + dp, tp, ttp); continue; } @@ -3187,7 +3198,7 @@ namespace build2 dp = nullptr; tp = nullptr; pmode = pattern_mode::ignore; - rpat = tt; + rpat = ttp; // Fall through. } diff --git a/doc/manual.cli b/doc/manual.cli index 437c1e5..f89fa23 100644 --- a/doc/manual.cli +++ b/doc/manual.cli @@ -71,15 +71,18 @@ exe{hello}: cxx{**} # All C++ source files recursively. A group-enclosed (\c{{\}}) pattern value may be followed by inclusion/exclusion patterns/matches. A subsequent value is treated as an -inclusion if it starts with a plus sign (\c{+}) and as an exclusion if it -starts with a minus (\c{-}). A subsequent value that does not start with -either of these signs is illegal. For example: +inclusion or exclusion if it starts with a literal, unquoted plus (\c{+}) or +minus (\c{-}) sign, respectively. In this case the remaining group values, if +any, must all be inclusions or exclusions. If the second value doesn't start +with a plus or minus, then all the group values are considered independent +with leading pluses and minuses not having any special meaning. For example: \ exe{hello}: cxx{f* -foo} # Exclude foo if present. exe{hello}: cxx{f* +foo} # Include foo if not present. exe{hello}: cxx{f* -fo?} # Exclude foo and fox if present. exe{hello}: cxx{f* +b* -foo -bar} # Exclude foo and bar if present. +exe{hello}: cxx{f* b* -z*} # Names matching three patterns. \ Inclusions and exclusions are applied in the order specified and only to the diff --git a/tests/name/pattern.test b/tests/name/pattern.test index 9eff855..b5b0bea 100644 --- a/tests/name/pattern.test +++ b/tests/name/pattern.test @@ -28,6 +28,11 @@ EOI touch foo.txt; $* <'print {foo *.txt}' >'foo foo.txt' + : independent-patterns + : + touch foo.txt -bar; + $* <'print {*.txt foo* -b*}' >'foo.txt foo.txt -bar' + : second-inclusion : touch foo.txt bar.txt; @@ -39,14 +44,14 @@ EOI { : simple : - $* <'print {*.txt file{foo}}' 2>>EOE != 0 - <stdin>:1:8: error: invalid 'file{foo}' in name pattern + $* <'print {*.txt +foo file{bar}}' 2>>EOE != 0 + <stdin>:1:8: error: invalid 'file{bar}' in name pattern EOE : inclusion-exclusion-sign : - $* <'print {*.txt foo}' 2>>EOE != 0 - <stdin>:1:8: error: missing leading +/- in 'foo' name pattern + $* <'print {*.txt -foo bar}' 2>>EOE != 0 + <stdin>:1:8: error: missing leading +/- in 'bar' name pattern EOE : empty-inclusion-exclusion |