aboutsummaryrefslogtreecommitdiff
path: root/libbuild2
diff options
context:
space:
mode:
Diffstat (limited to 'libbuild2')
-rw-r--r--libbuild2/test/script/parser+redirect.test.testscript86
-rw-r--r--libbuild2/test/script/parser.cxx47
-rw-r--r--libbuild2/test/script/parser.hxx3
3 files changed, 132 insertions, 4 deletions
diff --git a/libbuild2/test/script/parser+redirect.test.testscript b/libbuild2/test/script/parser+redirect.test.testscript
index a8691da..49fa89b 100644
--- a/libbuild2/test/script/parser+redirect.test.testscript
+++ b/libbuild2/test/script/parser+redirect.test.testscript
@@ -167,6 +167,92 @@
}
}
}
+
+ : overriding
+ :
+ {
+ : literal
+ :
+ {
+ : with
+ :
+ {
+ : string
+ :
+ $* <<EOI >>EOO
+ cmd >>EOF >bar
+ foo
+ EOF
+ EOI
+ cmd >bar
+ EOO
+
+ : regex
+ :
+ $* <<EOI >>EOO
+ cmd >>FOO >>~/BAR/
+ foo
+ FOO
+ bar
+ BAR
+ EOI
+ cmd >>~/BAR/
+ bar
+ BAR
+ EOO
+
+ : self
+ :
+ $* <<EOI >>EOO
+ cmd >>EOF >>EOF
+ foo
+ EOF
+ EOI
+ cmd >>EOF
+ foo
+ EOF
+ EOO
+
+ : different-modifiers
+ :
+ $* <<EOI 2>>EOE != 0
+ cmd >>EOF >>/EOF
+ foo
+ EOF
+ EOI
+ testscript:1:14: error: different modifiers for shared here-document 'EOF'
+ EOE
+ }
+ }
+
+ : shared
+ :
+ {
+ : after-sharing
+ :
+ $* <<EOI >>EOO
+ cmd >>EOF 2>>EOF >bar
+ foo
+ EOF
+ EOI
+ cmd >bar 2>>EOF
+ foo
+ EOF
+ EOO
+
+ : before-sharing
+ :
+ $* <<EOI >>EOO
+ cmd >>EOF >bar 2>>EOF
+ foo
+ EOF
+ EOI
+ cmd >bar 2>>EOF
+ foo
+ EOF
+ EOO
+ }
+ }
}
: file
diff --git a/libbuild2/test/script/parser.cxx b/libbuild2/test/script/parser.cxx
index 8b8f705..bc06ce8 100644
--- a/libbuild2/test/script/parser.cxx
+++ b/libbuild2/test/script/parser.cxx
@@ -1657,7 +1657,7 @@ namespace build2
// Parse the redirect operator.
//
auto parse_redirect =
- [&c, &expr, &p, &mod, this] (token& t, const location& l)
+ [&c, &expr, &p, &mod, &hd, this] (token& t, const location& l)
{
// Our semantics is the last redirect seen takes effect.
//
@@ -1774,6 +1774,8 @@ namespace build2
}
redirect& r (fd == 0 ? c.in : fd == 1 ? c.out : c.err);
+ redirect_type overriden (r.type);
+
r = redirect (rt);
// Don't move as still may be used for pending here-document end
@@ -1848,6 +1850,37 @@ namespace build2
case redirect_type::here_doc_ref: assert (false); break;
}
+
+ // If we are overriding a here-document, then remove the reference
+ // to this command redirect from the corresponding here_doc object.
+ //
+ if (!pre_parse_ &&
+ (overriden == redirect_type::here_doc_literal ||
+ overriden == redirect_type::here_doc_regex))
+ {
+ size_t e (expr.size () - 1);
+ size_t p (expr.back ().pipe.size ());
+ int f (static_cast<int> (fd));
+
+ for (here_doc& d: hd)
+ {
+ small_vector<here_redirect, 2>& rs (d.redirects);
+
+ auto i (find_if (rs.begin (), rs.end (),
+ [e, p, f] (const here_redirect& r)
+ {
+ return r.expr == e &&
+ r.pipe == p &&
+ r.fd == f;
+ }));
+
+ if (i != rs.end ())
+ {
+ rs.erase (i);
+ break;
+ }
+ }
+ }
};
// Set pending cleanup type.
@@ -2483,9 +2516,11 @@ namespace build2
parsed_doc v (
parse_here_document (t, tt, h.end, h.modifiers, h.regex));
- if (!pre_parse_)
+ // If all the here-document redirects are overridden, then we just
+ // drop the fragment.
+ //
+ if (!pre_parse_ && !h.redirects.empty ())
{
- assert (!h.redirects.empty ());
auto i (h.redirects.cbegin ());
command& c (p.first[i->expr].pipe[i->pipe]);
@@ -2493,11 +2528,17 @@ namespace build2
if (v.re)
{
+ assert (r.type == redirect_type::here_doc_regex);
+
r.regex = move (v.regex);
r.regex.flags = move (h.regex_flags);
}
else
+ {
+ assert (r.type == redirect_type::here_doc_literal);
+
r.str = move (v.str);
+ }
r.end = move (h.end);
r.end_line = v.end_line;
diff --git a/libbuild2/test/script/parser.hxx b/libbuild2/test/script/parser.hxx
index e4d1f3a..4d3fa49 100644
--- a/libbuild2/test/script/parser.hxx
+++ b/libbuild2/test/script/parser.hxx
@@ -122,7 +122,8 @@ namespace build2
struct here_doc
{
// Redirects that share here_doc. Most of the time we will have no
- // more than 2 (2 - for the roundtrip test cases).
+ // more than 2 (2 - for the roundtrip test cases). Doesn't refer
+ // overridden redirects and thus can be empty.
//
small_vector<here_redirect, 2> redirects;