aboutsummaryrefslogtreecommitdiff
path: root/build2/test/script/script.cxx
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2016-10-25 16:47:00 +0300
committerBoris Kolpackov <boris@codesynthesis.com>2016-11-04 09:26:35 +0200
commitb61e9e2ba8e625a598427cc2990806b69d104a18 (patch)
tree2e4b492a2ec00b325f52753ffa456f6f90eb78f2 /build2/test/script/script.cxx
parente3ff4880273746c34d07e641110abaf38a1f1fca (diff)
Add support of file redirects to testscript parser
Diffstat (limited to 'build2/test/script/script.cxx')
-rw-r--r--build2/test/script/script.cxx132
1 files changed, 127 insertions, 5 deletions
diff --git a/build2/test/script/script.cxx b/build2/test/script/script.cxx
index 6f303d5..ac11546 100644
--- a/build2/test/script/script.cxx
+++ b/build2/test/script/script.cxx
@@ -14,6 +14,8 @@ namespace build2
{
namespace script
{
+ // Utility functions
+ //
// Quote if empty or contains spaces or any of the special characters.
//
// @@ What if it contains quotes, escapes?
@@ -37,8 +39,7 @@ namespace build2
size_t n (string::traits_type::length (prefix));
assert (n > 0);
- const string& v (r.value);
- bool nl (!v.empty () && v.back () == '\n');
+ char d (prefix[n - 1]); // Redirect direction.
switch (r.type)
{
@@ -48,6 +49,9 @@ namespace build2
case redirect_type::here_string:
{
+ const string& v (r.str);
+ bool nl (!v.empty () && v.back () == '\n');
+
if (!nl)
o << ':';
@@ -56,10 +60,22 @@ namespace build2
}
case redirect_type::here_document:
{
+ const string& v (r.doc.doc);
+ bool nl (!v.empty () && v.back () == '\n');
+
// Add another '>' or '<'. Note that here end marker never
// needs to be quoted.
//
- o << prefix[n - 1] << (nl ? "" : ":") << r.here_end;
+ o << d << (nl ? "" : ":") << r.doc.end;
+ break;
+ }
+ case redirect_type::file:
+ {
+ using build2::operator<<;
+
+ // Add '>>' or '<<' (and so make it '<<<' or '>>>').
+ //
+ o << d << d << (r.file.append ? "&" : "") << r.file.path;
break;
}
}
@@ -67,9 +83,9 @@ namespace build2
auto print_doc = [&o] (const redirect& r)
{
- const string& v (r.value);
+ const string& v (r.doc.doc);
bool nl (!v.empty () && v.back () == '\n');
- o << endl << v << (nl ? "" : "\n") << r.here_end;
+ o << endl << v << (nl ? "" : "\n") << r.doc.end;
};
if ((m & command_to_stream::header) == command_to_stream::header)
@@ -114,6 +130,108 @@ namespace build2
}
}
+ // redirect
+ //
+ redirect::
+ redirect (redirect_type t)
+ : type (t)
+ {
+ switch (type)
+ {
+ case redirect_type::none:
+ case redirect_type::pass:
+ case redirect_type::null: break;
+
+ case redirect_type::here_string: new (&str) string (); break;
+ case redirect_type::here_document: new (&doc) doc_type (); break;
+ case redirect_type::file: new (&file) file_type (); break;
+ }
+ }
+
+ redirect::
+ redirect (redirect&& r)
+ : type (r.type)
+ {
+ switch (type)
+ {
+ case redirect_type::none:
+ case redirect_type::pass:
+ case redirect_type::null: break;
+
+ case redirect_type::here_string:
+ {
+ new (&str) string (move (r.str));
+ break;
+ }
+ case redirect_type::here_document:
+ {
+ new (&doc) doc_type (move (r.doc));
+ break;
+ }
+ case redirect_type::file:
+ {
+ new (&file) file_type (move (r.file));
+ break;
+ }
+ }
+ }
+
+ redirect::
+ redirect (const redirect& r)
+ : type (r.type)
+ {
+ switch (type)
+ {
+ case redirect_type::none:
+ case redirect_type::pass:
+ case redirect_type::null: break;
+
+ case redirect_type::here_string: new (&str) string (r.str); break;
+ case redirect_type::here_document: new (&doc) doc_type (r.doc); break;
+ case redirect_type::file:
+ {
+ new (&file) file_type (r.file);
+ break;
+ }
+ }
+ }
+
+ redirect::
+ ~redirect ()
+ {
+ switch (type)
+ {
+ case redirect_type::none:
+ case redirect_type::pass:
+ case redirect_type::null: break;
+
+ case redirect_type::here_string: str.~string (); break;
+ case redirect_type::here_document: doc.~doc_type (); break;
+ case redirect_type::file: file.~file_type (); break;
+ }
+ }
+
+ redirect& redirect::
+ operator= (redirect&& r)
+ {
+ if (this != &r)
+ {
+ this->~redirect ();
+ new (this) redirect (move (r)); // Assume noexcept move-constructor.
+ }
+ return *this;
+ }
+
+ redirect& redirect::
+ operator= (const redirect& r)
+ {
+ if (this != &r)
+ *this = redirect (r); // Reduce to move-assignment.
+ return *this;
+ }
+
+ // scope
+ //
scope::
scope (const string& id, scope* p)
: parent (p),
@@ -143,6 +261,8 @@ namespace build2
const_cast<dir_path&> (wd_path) = dir_path (p->wd_path) /= id;
}
+ // script_base
+ //
script_base::
script_base ()
: // Enter the test* variables with the same variable types as in
@@ -156,6 +276,8 @@ namespace build2
wd_var (var_pool.insert<dir_path> ("~")),
id_var (var_pool.insert<path> ("@")) {}
+ // script
+ //
static inline string
script_id (const path& p)
{