diff options
-rw-r--r-- | build2/test/script/parser.cxx | 66 | ||||
-rw-r--r-- | build2/test/script/script | 2 | ||||
-rw-r--r-- | build2/test/script/script.cxx | 27 | ||||
-rw-r--r-- | unit-tests/test/script/lexer/command-line.test | 10 | ||||
-rw-r--r-- | unit-tests/test/script/lexer/script-line.test | 9 | ||||
-rw-r--r-- | unit-tests/test/script/parser/buildfile | 4 | ||||
-rw-r--r-- | unit-tests/test/script/parser/cleanup.test | 35 |
7 files changed, 125 insertions, 28 deletions
diff --git a/build2/test/script/parser.cxx b/build2/test/script/parser.cxx index a3f2f00..152f1f0 100644 --- a/build2/test/script/parser.cxx +++ b/build2/test/script/parser.cxx @@ -581,7 +581,8 @@ namespace build2 err_merge, err_string, err_document, - err_file + err_file, + clean }; pending p (pending::program); bool nn (false); // True if pending here-{str,doc} is "no-newline". @@ -632,23 +633,30 @@ namespace build2 hd.push_back (here_doc {&r, move (w), nn}); }; - auto add_file = - [&app, &l, this] (redirect& r, const char* n, string&& w) + auto parse_path = [&l, this] (const char* n, string&& w) { try { - r.file.path = path (move (w)); + path p (move (w)); - if (r.file.path.empty ()) - fail (l) << "empty " << n << " redirect file path"; + if (!p.empty ()) + return p; + error (l) << "empty " << n; } catch (const invalid_path& e) { - fail (l) << "invalid " << n << " redirect file path '" << e.path - << "'"; + error (l) << "invalid " << n << " '" << e.path << "'"; } + throw failed (); + }; + + auto add_file = + [&app, &parse_path] (redirect& r, string n, string&& w) + { + n += " redirect file path"; + r.file.path = parse_path (n.c_str (), move (w)); r.file.append = app; }; @@ -657,17 +665,7 @@ namespace build2 case pending::none: c.arguments.push_back (move (w)); break; case pending::program: { - try - { - c.program = path (move (w)); - - if (c.program.empty ()) - fail (l) << "empty program path"; - } - catch (const invalid_path& e) - { - fail (l) << "invalid program path '" << e.path << "'"; - } + c.program = parse_path ("program path", move (w)); break; } @@ -685,6 +683,12 @@ namespace build2 case pending::in_file: add_file (c.in, "stdin", move (w)); break; case pending::out_file: add_file (c.out, "stdout", move (w)); break; case pending::err_file: add_file (c.err, "stderr", move (w)); break; + + case pending::clean: + { + c.cleanups.push_back (parse_path ("cleanup path", move (w))); + break; + } } p = pending::none; @@ -713,6 +717,7 @@ namespace build2 case pending::err_string: what = "stderr here-string"; break; case pending::err_document: what = "stderr here-document end"; break; case pending::err_file: what = "stderr file"; break; + case pending::clean: what = "cleanup path"; break; } if (what != nullptr) @@ -902,6 +907,8 @@ namespace build2 case type::in_file: case type::out_file: case type::out_file_app: + + case type::clean: { if (pre_parse_) { @@ -966,12 +973,21 @@ namespace build2 case type::in_file: case type::out_file: case type::out_file_app: + { + parse_redirect (t, l); + break; + } - parse_redirect (t, l); - next (t, tt); - break; + case type::clean: + { + p = pending::clean; + break; + } + + default: assert (false); break; } + next (t, tt); break; } default: @@ -1115,6 +1131,12 @@ namespace build2 break; } + case type::clean: + { + p = pending::clean; + break; + } + case type::in_doc: case type::out_doc: diff --git a/build2/test/script/script b/build2/test/script/script index a21f0c6..a841d6c 100644 --- a/build2/test/script/script +++ b/build2/test/script/script @@ -121,6 +121,8 @@ namespace build2 redirect out; redirect err; + paths cleanups; + command_exit exit {exit_comparison::eq, 0}; }; diff --git a/build2/test/script/script.cxx b/build2/test/script/script.cxx index 8de023f..bf53595 100644 --- a/build2/test/script/script.cxx +++ b/build2/test/script/script.cxx @@ -4,6 +4,8 @@ #include <build2/test/script/script> +#include <sstream> + #include <build2/target> using namespace std; @@ -32,7 +34,19 @@ namespace build2 void to_stream (ostream& o, const command& c, command_to_stream m) { - auto print_redirect = [&o] (const redirect& r, const char* prefix) + auto print_path = [&o] (const path& p) + { + using build2::operator<<; + + ostringstream s; + stream_verb (s, stream_verb (o)); + s << p; + + to_stream_q (o, s.str ()); + }; + + auto print_redirect = + [&o, print_path] (const redirect& r, const char* prefix) { o << ' ' << prefix; @@ -72,11 +86,10 @@ namespace build2 } case redirect_type::file: { - using build2::operator<<; - // Add '>>' or '<<' (and so make it '<<<' or '>>>'). // - o << d << d << (r.file.append ? "&" : "") << r.file.path; + o << d << d << (r.file.append ? "&" : ""); + print_path (r.file.path); break; } } @@ -109,6 +122,12 @@ namespace build2 if (c.out.type != redirect_type::none) print_redirect (c.out, ">"); if (c.err.type != redirect_type::none) print_redirect (c.err, "2>"); + for (const auto& p: c.cleanups) + { + o << " &"; + print_path (p); + } + if (c.exit.comparison != exit_comparison::eq || c.exit.status != 0) { switch (c.exit.comparison) diff --git a/unit-tests/test/script/lexer/command-line.test b/unit-tests/test/script/lexer/command-line.test index 4a71d46..bc791dc 100644 --- a/unit-tests/test/script/lexer/command-line.test +++ b/unit-tests/test/script/lexer/command-line.test @@ -117,3 +117,13 @@ $* <:"1>>>&a b" >>EOO # out-file-app-redirect >>>& 'a b' EOO + +$* <:"&file" >>EOO # file-cleanup +& +'file' +EOO + +$* <:"&dir/" >>EOO # dir-cleanup +& +'dir/' +EOO diff --git a/unit-tests/test/script/lexer/script-line.test b/unit-tests/test/script/lexer/script-line.test index 36d440c..6c5038a 100644 --- a/unit-tests/test/script/lexer/script-line.test +++ b/unit-tests/test/script/lexer/script-line.test @@ -92,3 +92,12 @@ $* <"cmd <<<in >>>out 2>>>&err" >>EOO # file-redirect 'err' <newline> EOO + +$* <"cmd &file &dir/" >>EOO # cleanup +'cmd' +& +'file' +& +'dir/' +<newline> +EOO diff --git a/unit-tests/test/script/parser/buildfile b/unit-tests/test/script/parser/buildfile index b053971..e64159e 100644 --- a/unit-tests/test/script/parser/buildfile +++ b/unit-tests/test/script/parser/buildfile @@ -11,7 +11,7 @@ filesystem config/{utility init operation} dump types-parsers \ test/{target script/{token lexer parser script}} exe{driver}: cxx{driver} ../../../../build2/cxx{$src} $libs \ -test{pre-parse expansion redirect here-document command-re-parse scope \ - setup-teardown} +test{cleanup command-re-parse expansion here-document pre-parse redirect \ + scope setup-teardown} include ../../../../build2/ diff --git a/unit-tests/test/script/parser/cleanup.test b/unit-tests/test/script/parser/cleanup.test new file mode 100644 index 0000000..7fe746d --- /dev/null +++ b/unit-tests/test/script/parser/cleanup.test @@ -0,0 +1,35 @@ +$* <<EOI >>EOO # file-dir +cmd &file &dir/ +EOI +cmd &file &dir/ +EOO + +$* <<EOI >>EOO # quote-file-dir +cmd &"f ile" &"d ir/" +EOI +cmd &"f ile" &"d ir/" +EOO + +$* <<EOI >>EOO # dup-file +cmd &file &file +EOI +cmd &file &file +EOO + +$* <<EOI 2>>EOE != 0 # file-fail1 +cmd & >file +EOI +testscript:1:7: error: missing cleanup path +EOE + +$* <<EOI 2>>EOE != 0 # file-fail2 +cmd & +EOI +testscript:1:6: error: missing cleanup path +EOE + +$* <<EOI 2>>EOE != 0 # file-fail3 +cmd &"" +EOI +testscript:1:6: error: empty cleanup path +EOE |