diff options
Diffstat (limited to 'libbuild2/build/script/parser.test.cxx')
-rw-r--r-- | libbuild2/build/script/parser.test.cxx | 225 |
1 files changed, 175 insertions, 50 deletions
diff --git a/libbuild2/build/script/parser.test.cxx b/libbuild2/build/script/parser.test.cxx index 7f2840d..97eac22 100644 --- a/libbuild2/build/script/parser.test.cxx +++ b/libbuild2/build/script/parser.test.cxx @@ -1,7 +1,6 @@ // file : libbuild2/build/script/parser.test.cxx -*- C++ -*- // license : MIT; see accompanying LICENSE file -#include <cassert> #include <iostream> #include <libbuild2/types.hxx> @@ -10,11 +9,15 @@ #include <libbuild2/target.hxx> #include <libbuild2/context.hxx> #include <libbuild2/scheduler.hxx> +#include <libbuild2/file-cache.hxx> #include <libbuild2/build/script/script.hxx> // line #include <libbuild2/build/script/parser.hxx> #include <libbuild2/build/script/runner.hxx> +#undef NDEBUG +#include <cassert> + using namespace std; namespace build2 @@ -26,35 +29,58 @@ namespace build2 class print_runner: public runner { public: - print_runner (bool line): line_ (line) {} + print_runner (bool line, bool iterations): + line_ (line), + iterations_ (iterations) {} virtual void enter (environment&, const location&) override {} virtual void - run (environment&, + run (environment& env, const command_expr& e, - size_t i, - const location&) override + const iteration_index* ii, size_t i, + const function<command_function>& cf, + const location& ll) override { + // If the functions is specified, then just execute it with an empty + // stdin so it can perform the housekeeping (stop replaying tokens, + // increment line index, etc). + // + if (cf != nullptr) + { + assert (e.size () == 1 && !e[0].pipe.empty ()); + + const command& c (e[0].pipe.back ()); + + // Must be enforced by the caller. + // + assert (!c.out && !c.err && !c.exit); + + cf (env, c.arguments, + fdopen_null (), nullptr /* pipe */, + nullopt /* deadline */, + ll); + } + cout << e; - if (line_) - cout << " # " << i; + if (line_ || iterations_) + print_line_info (ii, i); cout << endl; } virtual bool - run_if (environment&, - const command_expr& e, - size_t i, - const location&) override + run_cond (environment&, + const command_expr& e, + const iteration_index* ii, size_t i, + const location&) override { cout << "? " << e; - if (line_) - cout << " # " << i; + if (line_ || iterations_) + print_line_info (ii, i); cout << endl; @@ -65,37 +91,75 @@ namespace build2 leave (environment&, const location&) override {} private: + void + print_line_info (const iteration_index* ii, size_t i) const + { + cout << " #"; + + if (line_) + cout << ' ' << i; + + if (iterations_ && ii != nullptr) + { + string s; + for (const iteration_index* i (ii); i != nullptr; i = i->prev) + s.insert (0, " i" + to_string (i->index)); + + cout << s; + } + } + + private: bool line_; + bool iterations_; }; // Usages: // - // argv[0] [-l] - // argv[0] -d - // argv[0] -p - // argv[0] -g [<diag-name>] + // argv[0] [-l] [-r] + // argv[0] -b [-t] + // argv[0] -d [-t] + // argv[0] -g [-t] [<diag-name>] + // argv[0] -q // // In the first form read the script from stdin and trace the script - // execution to stdout using the custom print runner. + // body execution to stdout using the custom print runner. // // In the second form read the script from stdin, parse it and dump the - // resulting lines to stdout. + // script body lines to stdout. // - // In the third form read the script from stdin, parse it and print - // line tokens quoting information to stdout. + // In the third form read the script from stdin, parse it and dump the + // depdb preamble lines to stdout. // // In the forth form read the script from stdin, parse it and print the // low-verbosity script diagnostics name or custom low-verbosity // diagnostics to stdout. If the script doesn't deduce any of them, then // print the diagnostics and exit with non-zero code. // + // In the fifth form read the script from stdin, parse it and print + // line tokens quoting information to stdout. + // // -l // Print the script line number for each executed expression. // + // -r + // Print the loop iteration numbers for each executed expression. + // + // -b + // Dump the parsed script body to stdout. + // // -d - // Dump the parsed script to sdout. + // Dump the parsed script depdb preamble to stdout. + // + // -g + // Dump the low-verbosity script diagnostics name or custom + // low-verbosity diagnostics to stdout. + // + // -t + // Print true if the body (-b), depdb preamble (-d), or diag preamble + // (-g) references the temporary directory and false otherwise. // - // -p + // -q // Print the parsed script tokens quoting information to sdout. If a // token is quoted follow its representation with its quoting // information in the [<quoting>/<completeness>] form, where: @@ -103,10 +167,6 @@ namespace build2 // <quoting> := 'S' | 'D' | 'M' // <completeness> := 'C' | 'P' // - // -g - // Dump the low-verbosity script diagnostics name or custom - // low-verbosity diagnostics to stdout. - // int main (int argc, char* argv[]) { @@ -115,13 +175,16 @@ namespace build2 enum class mode { run, - dump, - print, - diag + body, + depdb_preamble, + diag, + quoting } m (mode::run); bool print_line (false); + bool print_iterations (false); optional<string> diag_name; + bool temp_dir (false); for (int i (1); i != argc; ++i) { @@ -129,12 +192,23 @@ namespace build2 if (a == "-l") print_line = true; + else if (a == "-r") + print_iterations = true; + else if (a == "-b") + m = mode::body; else if (a == "-d") - m = mode::dump; - else if (a == "-p") - m = mode::print; + m = mode::depdb_preamble; else if (a == "-g") m = mode::diag; + else if (a == "-t") + { + assert (m == mode::body || + m == mode::depdb_preamble || + m == mode::diag); + temp_dir = true; + } + else if (a == "-q") + m = mode::quoting; else { if (m == mode::diag) @@ -147,19 +221,21 @@ namespace build2 } } - assert (!print_line || m == mode::run); - assert (!diag_name || m == mode::diag); + assert (!print_line || m == mode::run || m == mode::diag); + assert (!print_iterations || m == mode::run || m == mode::diag); + assert (!diag_name || m == mode::diag); // Fake build system driver, default verbosity. // init_diag (1); - init (nullptr, argv[0]); + init (nullptr, argv[0], true); // Serial execution. // scheduler sched (1); global_mutexes mutexes (1); - context ctx (sched, mutexes); + file_cache fcache (true); + context ctx (sched, mutexes, fcache); try { @@ -179,12 +255,16 @@ namespace build2 tt.path (path ("driver")); + const scope& bs (tt.base_scope ()); + + small_vector<action, 1> acts {perform_update_id}; + // Parse and run. // parser p (ctx); path_name nm ("buildfile"); - script s (p.pre_parse (tt, + script s (p.pre_parse (bs, tt.type (), acts, cin, nm, 11 /* line */, (m != mode::diag @@ -196,9 +276,29 @@ namespace build2 { case mode::run: { - environment e (perform_update_id, tt, false /* temp_dir */); - print_runner r (print_line); - p.execute (ctx.global_scope, ctx.global_scope, e, s, r); + environment e (perform_update_id, tt, bs, false /* temp_dir */); + print_runner r (print_line, print_iterations); + + bool exec_diag (!s.diag_preamble.empty ()); + + if (exec_diag) + { + if (s.diag_preamble_temp_dir) + e.set_temp_dir_variable (); + + p.execute_diag_preamble (ctx.global_scope, ctx.global_scope, + e, s, r, + false /* diag */, + true /* enter */, + false /* leave */); + } + + if (s.body_temp_dir && !s.diag_preamble_temp_dir) + e.set_temp_dir_variable (); + + p.execute_body (ctx.global_scope, ctx.global_scope, + e, s, r, + !exec_diag /* enter */); break; } case mode::diag: @@ -209,26 +309,51 @@ namespace build2 } else { - assert (s.diag_line); + if (!temp_dir) + { + environment e (perform_update_id, + tt, + bs, + s.diag_preamble_temp_dir); - environment e (perform_update_id, tt, false /* temp_dir */); + print_runner r (print_line, print_iterations); - cout << "diag: " << p.execute_special (ctx.global_scope, + names diag (p.execute_diag_preamble (ctx.global_scope, ctx.global_scope, - e, - *s.diag_line) << endl; + e, s, r, + true /* diag */, + true /* enter */, + true /* leave */).first); + + cout << "diag: " << diag << endl; + } + else + cout << (s.diag_preamble_temp_dir ? "true" : "false") << endl; } break; } - case mode::dump: + case mode::body: { - dump (cout, "", s.lines); + if (!temp_dir) + dump (cout, "", s.body); + else + cout << (s.body_temp_dir ? "true" : "false") << endl; + + break; + } + case mode::depdb_preamble: + { + if (!temp_dir) + dump (cout, "", s.depdb_preamble); + else + cout << (s.depdb_preamble_temp_dir ? "true" : "false") << endl; + break; } - case mode::print: + case mode::quoting: { - for (const line& l: s.lines) + for (const line& l: s.body) { for (const replay_token& rt: l.tokens) { |