aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build2/parser.cxx33
-rw-r--r--build2/parser.hxx3
-rw-r--r--doc/manual.cli20
-rw-r--r--tests/name/pattern.test7
4 files changed, 35 insertions, 28 deletions
diff --git a/build2/parser.cxx b/build2/parser.cxx
index caf970e..ceae594 100644
--- a/build2/parser.cxx
+++ b/build2/parser.cxx
@@ -3153,11 +3153,6 @@ namespace build2
<< " pattern";
}
- // Figure out if this is a pattern.
- //
- bool p (v.find_first_of ("*?") != string::npos);
- assert (p || !first); // First must be a pattern.
-
// Factor non-empty extension back into the name for searching.
//
// Note that doing it at this stage means we don't support extension
@@ -3172,15 +3167,10 @@ namespace build2
try
{
if (s == '+')
- {
- if (p)
- include_pattern (move (v), move (e), a);
- else
- include_match (move (v), move (e), a);
- }
+ include_pattern (move (v), move (e), a);
else
{
- if (p)
+ if (v.find_first_of ("*?") != string::npos)
exclude_pattern (move (v));
else
exclude_match (move (v));
@@ -3300,11 +3290,13 @@ namespace build2
t, tt,
r,
pmode == pattern_mode::expand ? pattern_mode::detect : pmode,
- false,
+ false /* chunk */,
what,
separators,
0, // Handled by the splice_names() call below.
- pp, dp, tp, false).pattern);
+ pp, dp, tp,
+ false /* cross */,
+ true /* curly */).pattern);
if (tt != type::rcbrace)
fail (t) << "expected '}' instead of " << t;
@@ -3420,7 +3412,8 @@ namespace build2
const optional<project_name>& pp,
const dir_path* dp,
const string* tp,
- bool cross) -> parse_names_result
+ bool cross,
+ bool curly) -> parse_names_result
{
// Note that support for pre-parsing is partial, it does not handle
// groups ({}).
@@ -3906,11 +3899,15 @@ namespace build2
// See if this is a wildcard pattern.
//
+ // It should either contain a wildcard character or, in a curly
+ // context, start with unquoted '+'.
+ //
if (pmode != pattern_mode::ignore &&
!*pp1 && // Cannot be project-qualified.
t.qtype == quote_type::unquoted && // Cannot be quoted.
((dp != nullptr && dp->absolute ()) || pbase_ != nullptr) &&
- val.find_first_of ("*?") != string::npos)
+ ((val.find_first_of ("*?") != string::npos) ||
+ (curly && val[0] == '+')))
{
// Resolve the target if there is one. If we fail, then this is not
// a pattern.
@@ -4482,6 +4479,10 @@ namespace build2
pair<char, bool> p (lexer_->peek_char ());
char c (p.first);
+ // @@ Just checking for leading '+' is not sufficient, for example:
+ //
+ // print +foo
+ //
return c == '\n' || c == '\0' || c == '(' ||
(p.second && c != '=' && c != '+');
}
diff --git a/build2/parser.hxx b/build2/parser.hxx
index acd0845..dfb4c6b 100644
--- a/build2/parser.hxx
+++ b/build2/parser.hxx
@@ -310,7 +310,8 @@ namespace build2
const optional<project_name>& prj = nullopt,
const dir_path* dir = nullptr,
const string* type = nullptr,
- bool cross = true);
+ bool cross = true,
+ bool curly = false);
size_t
parse_names_trailer (token&, token_type&,
diff --git a/doc/manual.cli b/doc/manual.cli
index eafe14d..713cd63 100644
--- a/doc/manual.cli
+++ b/doc/manual.cli
@@ -76,24 +76,26 @@ 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
-regularity, the first pattern can also start with the plus sign. For example:
+with leading pluses and minuses not having any special meaning. For regularity
+as well as to allow patterns without wildcards, the first pattern can also
+start with the plus sign. 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* -foo} # Exclude foo if exists.
+exe{hello}: cxx{f* +bar} # Include bar if exists.
+exe{hello}: cxx{f* -fo?} # Exclude foo and fox if exist.
+exe{hello}: cxx{f* +b* -foo -bar} # Exclude foo and bar if exist.
exe{hello}: cxx{+f* +b* -foo -bar} # Same as above.
+exe{hello}: cxx{+foo} # Pattern without wildcards.
exe{hello}: cxx{f* b* -z*} # Names matching three patterns.
\
Inclusions and exclusions are applied in the order specified and only to the
result produced up to that point. The order of names in the result is
-unspecified. However, it is guaranteed not to contain duplicates. The
+unspecified. However, it is guaranteed not to contain duplicates. The first
pattern and the following inclusions/exclusions must be consistent with
-regards to the type of filesystem entry they match. That is, they should
-all match either files or directories. For example:
+regards to the type of filesystem entry they match. That is, they should all
+match either files or directories. For example:
\
exe{hello}: cxx{f* -foo +*oo} # Exclusion has no effect.
diff --git a/tests/name/pattern.test b/tests/name/pattern.test
index fad8478..8d8840c 100644
--- a/tests/name/pattern.test
+++ b/tests/name/pattern.test
@@ -107,7 +107,7 @@ EOI
$* <'print d*/*.txt' >/'dir/foo.txt' : multi-pattern
touch foo.txt bar.txt;
- $* <'print {*.txt -bar.txt}' >'foo.txt' : exclude-match
+ $* <'print {*.txt -bar.txt}' >'foo.txt' : exclude-non-pattern
mkdir baz;
touch foo.txt bar.txt baz/fox.txt baz/box.txt;
@@ -117,7 +117,7 @@ EOI
$* <'print {*.txt -{*z.txt bar.txt}}' >'foo.txt' : exclude-group
touch bar.txt;
- $* <'print {f*.txt +bar.txt}' >'bar.txt' : include-match
+ $* <'print {f*.txt +bar.txt}' >'bar.txt' : include-non-wildcard
touch bar.txt;
$* <'print {f*.txt +b*.txt}' >'bar.txt' : include-pattern
@@ -127,6 +127,9 @@ EOI
touch foo.txt fox.txt;
$* <'print {*.txt -f*.txt +*x.txt}' >'fox.txt' : include-exclude-order
+
+ touch foo.txt;
+ $* <'print {+foo.txt} {+bar.txt}' >'foo.txt' : non-wildcard
}
: target-type