aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build2/parser.cxx23
-rw-r--r--doc/manual.cli9
-rw-r--r--tests/name/pattern.test13
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