aboutsummaryrefslogtreecommitdiff
path: root/build2/test/script/parser.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2016-11-25 11:19:40 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2016-11-25 11:19:40 +0200
commita3dad2118fb3925ef4f9baa90cea0dfd44ca93c6 (patch)
tree54748b5d85cab7bfb70a7baf66fe902c82cf3d66 /build2/test/script/parser.cxx
parent28f8338ded34f160e0083da9be4679bc778be7ca (diff)
Allow here-document end marker to be wholly quoted
Diffstat (limited to 'build2/test/script/parser.cxx')
-rw-r--r--build2/test/script/parser.cxx41
1 files changed, 39 insertions, 2 deletions
diff --git a/build2/test/script/parser.cxx b/build2/test/script/parser.cxx
index a116873..7655ba9 100644
--- a/build2/test/script/parser.cxx
+++ b/build2/test/script/parser.cxx
@@ -1652,8 +1652,45 @@ namespace build2
//
next (t, tt);
- if (tt != type::word || t.qtype != quote_type::unquoted)
- fail (l) << "expected here-document end marker";
+ // We require the end marker to be an unquoted or completely
+ // quoted word. The complete quoting becomes important for
+ // cases like foo"$bar" (where we will see word 'foo').
+ //
+ // For good measure we could have also required it to be
+ // separated from the following token, but out grammar
+ // allows one to write >>EOO;. The problematic sequence
+ // would be >>FOO$bar -- on reparse it will be expanded
+ // as a single word.
+ //
+ if (tt != type::word)
+ fail (t) << "expected here-document end marker";
+
+ peek ();
+ const token& p (peeked ());
+ if (!p.separated)
+ {
+ switch (p.type)
+ {
+ case type::dollar:
+ case type::lparen:
+ fail (p) << "here-document end marker must be literal";
+ }
+ }
+
+ quote_type qt (t.qtype);
+ switch (qt)
+ {
+ case quote_type::unquoted:
+ qt = quote_type::single; // Treat as single-quoted.
+ break;
+ case quote_type::single:
+ case quote_type::double_:
+ if (t.qcomp)
+ break;
+ // Fall through.
+ case quote_type::mixed:
+ fail (t) << "partially-quoted here-document end marker";
+ }
hd.push_back (here_doc {0, 0, 0, move (t.value), nn});
break;