From 882583f64e517ab232edb6bbb7433631c655c9da Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 7 Nov 2019 11:12:43 +0200 Subject: Initial work on path_name use for `-` to stdin/stdout translation --- libbuild2/cc/link-rule.cxx | 2 +- libbuild2/cc/pkgconfig.cxx | 2 +- libbuild2/config/functions.cxx | 5 ++- libbuild2/config/init.cxx | 5 ++- libbuild2/config/operation.cxx | 33 +++++++++--------- libbuild2/config/operation.hxx | 2 +- libbuild2/config/utility.cxx | 6 ++-- libbuild2/context.cxx | 3 +- libbuild2/diagnostics.cxx | 2 +- libbuild2/diagnostics.hxx | 15 ++++++++ libbuild2/dist/operation.cxx | 4 +-- libbuild2/file.cxx | 7 ++-- libbuild2/lexer+comment.test.testscript | 2 +- libbuild2/lexer+eval.test.testscript | 4 +-- libbuild2/lexer.hxx | 13 ++++--- libbuild2/lexer.test.cxx | 3 +- libbuild2/parser.cxx | 4 +-- .../script/lexer+description-line.test.testscript | 2 +- .../test/script/lexer+variable.test.testscript | 2 +- libbuild2/test/script/lexer.hxx | 10 +++--- libbuild2/test/script/lexer.test.cxx | 3 +- libbuild2/test/script/parser.cxx | 8 ++--- libbuild2/test/script/runner.cxx | 8 ++--- libbuild2/types.hxx | 22 ++++++++---- libbuild2/utility.cxx | 40 +++++----------------- libbuild2/utility.hxx | 14 ++------ 26 files changed, 112 insertions(+), 109 deletions(-) diff --git a/libbuild2/cc/link-rule.cxx b/libbuild2/cc/link-rule.cxx index 8a3b493..62988c9 100644 --- a/libbuild2/cc/link-rule.cxx +++ b/libbuild2/cc/link-rule.cxx @@ -3014,7 +3014,7 @@ namespace build2 } catch (const io_error& e) { - fail << "unable to write " << f << ": " << e; + fail << "unable to write to " << f << ": " << e; } // Replace input arguments with @file. diff --git a/libbuild2/cc/pkgconfig.cxx b/libbuild2/cc/pkgconfig.cxx index 31b0770..56acafc 100644 --- a/libbuild2/cc/pkgconfig.cxx +++ b/libbuild2/cc/pkgconfig.cxx @@ -1543,7 +1543,7 @@ namespace build2 } catch (const io_error& e) { - fail << "unable to write " << p << ": " << e; + fail << "unable to write to " << p << ": " << e; } } } diff --git a/libbuild2/config/functions.cxx b/libbuild2/config/functions.cxx index 79447a4..b6ccb74 100644 --- a/libbuild2/config/functions.cxx +++ b/libbuild2/config/functions.cxx @@ -43,7 +43,10 @@ namespace build2 // Empty project set should is ok as long as inherit is false. // project_set ps; - save_config (*s, os, "config.export()", false /* inherit */, ps); + save_config (*s, + os, path_name ("config.export()"), + false /* inherit */, + ps); return os.str (); }; diff --git a/libbuild2/config/init.cxx b/libbuild2/config/init.cxx index 2d4ed20..890efa3 100644 --- a/libbuild2/config/init.cxx +++ b/libbuild2/config/init.cxx @@ -169,8 +169,11 @@ namespace build2 auto load_config_file = [&load_config] (const path& f, const location& l) { + // @@ PATH_NAME TODO + // + path_name fn (f); ifdstream ifs; - load_config (open_file_or_stdin (f, ifs), f, l); + load_config (open_file_or_stdin (fn, ifs), f /* fn */, l); }; { diff --git a/libbuild2/config/operation.cxx b/libbuild2/config/operation.cxx index c9b5ef6..14576a0 100644 --- a/libbuild2/config/operation.cxx +++ b/libbuild2/config/operation.cxx @@ -50,7 +50,7 @@ namespace build2 } catch (const io_error& e) { - fail << "unable to write " << f << ": " << e; + fail << "unable to write to " << f << ": " << e; } } @@ -79,7 +79,7 @@ namespace build2 } catch (const io_error& e) { - fail << "unable to write " << f << ": " << e; + fail << "unable to write to " << f << ": " << e; } } @@ -90,8 +90,7 @@ namespace build2 // void save_config (const scope& rs, - ostream& os, - const string& name, + ostream& os, const path_name& on, bool inherit, const project_set& projects) { @@ -100,8 +99,8 @@ namespace build2 const module* mod (rs.lookup_module (module::name)); if (mod == nullptr) - fail << "no configuration information available during this meta-" - << "operation"; + fail (on) << "no configuration information available during this " + << "meta-operation"; try { @@ -231,8 +230,8 @@ namespace build2 // then something is broken. // if (r == nullptr) - fail << name << ": inherited variable " << var << " value " - << "is not from a root scope"; + fail (on) << "inherited variable " << var << " value is not " + << "from a root scope"; // If none of the outer project's configurations use this // value, then we warn (unless we couldn't check) and save as @@ -242,8 +241,8 @@ namespace build2 if (checked && org.first == ovr.first) { diag_record dr; - dr << warn << name << ": saving previously inherited " - << "variable " << var; + dr << warn (on) << "saving previously inherited variable " + << var; dr << info << "because project " << *r << " no longer uses " << "it in its configuration"; @@ -321,7 +320,7 @@ namespace build2 } catch (const io_error& e) { - fail << "unable to write " << name << ": " << e; + fail << "unable to write to " << on << ": " << e; } } @@ -331,21 +330,23 @@ namespace build2 bool inherit, const project_set& projects) { - const string& fs (f.string () != "-" ? f.string () : ""); + path_name fn (f); + + if (f.string () == "-") + fn.name = ""; if (verb) - text << (verb >= 2 ? "cat >" : "save ") << fs; + text << (verb >= 2 ? "cat >" : "save ") << fn; try { ofdstream ofs; - ostream& os (); - save_config (rs, open_file_or_stdout (f, ofs), fs, inherit, projects); + save_config (rs, open_file_or_stdout (fn, ofs), fn, inherit, projects); ofs.close (); } catch (const io_error& e) { - fail << "unable to write " << fs << ": " << e; + fail << "unable to write to " << fn << ": " << e; } } diff --git a/libbuild2/config/operation.hxx b/libbuild2/config/operation.hxx index 9ec854a..1b4a452 100644 --- a/libbuild2/config/operation.hxx +++ b/libbuild2/config/operation.hxx @@ -36,7 +36,7 @@ namespace build2 // void save_config (const scope& rs, - ostream&, const string& name, + ostream&, const path_name&, bool inherit, const project_set&); } diff --git a/libbuild2/config/utility.cxx b/libbuild2/config/utility.cxx index 8a99a8b..56c1f79 100644 --- a/libbuild2/config/utility.cxx +++ b/libbuild2/config/utility.cxx @@ -215,7 +215,7 @@ namespace build2 } catch (const io_error& e) { - fail << "unable to write " << f << ": " << e; + fail << "unable to write to " << f << ": " << e; } } @@ -263,7 +263,7 @@ namespace build2 } catch (const io_error& e) { - fail << "unable to write " << f << ": " << e; + fail << "unable to write to " << f << ": " << e; } } @@ -287,7 +287,7 @@ namespace build2 } catch (const io_error& e) { - fail << "unable to write " << f << ": " << e; + fail << "unable to write to " << f << ": " << e; } } } diff --git a/libbuild2/context.cxx b/libbuild2/context.cxx index b4a3e93..9ed69a5 100644 --- a/libbuild2/context.cxx +++ b/libbuild2/context.cxx @@ -284,7 +284,8 @@ namespace build2 // (basically what's necessary inside a double-quoted literal plus the // single quote). // - lexer l (is, path (""), 1 /* line */, "\'\"\\$("); + path in (""); // @@ PATH_NAME: make name + lexer l (is, in, 1 /* line */, "\'\"\\$("); // At the buildfile level the scope-specific variable should be // separated from the directory with a whitespace, for example: diff --git a/libbuild2/diagnostics.cxx b/libbuild2/diagnostics.cxx index f1b8f74..8c1805c 100644 --- a/libbuild2/diagnostics.cxx +++ b/libbuild2/diagnostics.cxx @@ -109,7 +109,7 @@ namespace build2 if (!loc_.empty ()) { - r << *loc_.file << ':'; + r << loc_.file << ':'; if (!diag_no_line) { diff --git a/libbuild2/diagnostics.hxx b/libbuild2/diagnostics.hxx index 6d06dec..9008fc3 100644 --- a/libbuild2/diagnostics.hxx +++ b/libbuild2/diagnostics.hxx @@ -300,6 +300,15 @@ namespace build2 location_prologue_base (const char* type, const char* mod, const char* name, + const path_name& f, + stream_verbosity sverb) + : type_ (type), mod_ (mod), name_ (name), + loc_ (f), + sverb_ (sverb) {} + + location_prologue_base (const char* type, + const char* mod, + const char* name, path&& f, stream_verbosity sverb) : type_ (type), mod_ (mod), name_ (name), @@ -346,6 +355,12 @@ namespace build2 return location_prologue (epilogue_, type_, mod_, name_, l, sverb_ ()); } + location_prologue + operator() (const path_name& f) const + { + return location_prologue (epilogue_, type_, mod_, name_, f, sverb_ ()); + } + // fail (relative (src)) << ... // location_prologue diff --git a/libbuild2/dist/operation.cxx b/libbuild2/dist/operation.cxx index ad829df..e3dadff 100644 --- a/libbuild2/dist/operation.cxx +++ b/libbuild2/dist/operation.cxx @@ -144,7 +144,7 @@ namespace build2 // since the meta operation is dist and we know what we are doing. // values params; - const path locf (""); + const path locf (""); // @@ PATH_NAME TODO const location loc (&locf); // Dummy location. const operations& ops (rs->root_extra->operations); @@ -822,7 +822,7 @@ namespace build2 } catch (const io_error& e) { - fail << "unable to write " << cp << ": " << e; + fail << "unable to write to " << cp << ": " << e; } } diff --git a/libbuild2/file.cxx b/libbuild2/file.cxx index 974dc2b..2bc9af6 100644 --- a/libbuild2/file.cxx +++ b/libbuild2/file.cxx @@ -188,14 +188,17 @@ namespace build2 static void source (scope& root, scope& base, const path& bf, bool boot) { + path_name fn (bf); try { + // @@ PATH_NAME TODO + // ifdstream ifs; - return source (root, base, open_file_or_stdin (bf, ifs), bf, boot); + return source (root, base, open_file_or_stdin (fn, ifs), bf /* fn */, boot); } catch (const io_error& e) { - fail << "unable to read buildfile " << bf << ": " << e; + fail << "unable to read buildfile " << fn << ": " << e; } } diff --git a/libbuild2/lexer+comment.test.testscript b/libbuild2/lexer+comment.test.testscript index 6ad1202..5cc9b47 100644 --- a/libbuild2/lexer+comment.test.testscript +++ b/libbuild2/lexer+comment.test.testscript @@ -134,6 +134,6 @@ #\ comment EOI - stdin:3:1: error: unterminated multi-line comment + :3:1: error: unterminated multi-line comment EOE } diff --git a/libbuild2/lexer+eval.test.testscript b/libbuild2/lexer+eval.test.testscript index 86f804a..963f3d0 100644 --- a/libbuild2/lexer+eval.test.testscript +++ b/libbuild2/lexer+eval.test.testscript @@ -66,11 +66,11 @@ EOO : newline : $* <'x' >- 2>>EOE != 0 -stdin:1:2: error: newline in evaluation context +:1:2: error: newline in evaluation context EOE : eof : $* <:'' 2>>EOE != 0 -stdin:1:1: error: unterminated evaluation context +:1:1: error: unterminated evaluation context EOE diff --git a/libbuild2/lexer.hxx b/libbuild2/lexer.hxx index a2c7431..bd2ac74 100644 --- a/libbuild2/lexer.hxx +++ b/libbuild2/lexer.hxx @@ -84,13 +84,14 @@ namespace build2 public: // If escape is not NULL then only escape sequences with characters from // this string are considered "effective escapes" with all others passed - // through as is. Note that the escape string is not copied. + // through as is. Note that neither the name nor escape arguments are + // copied. // lexer (istream& is, const path& name, uint64_t line = 1, // Start line in the stream. const char* escapes = nullptr) - : lexer (is, name, line, escapes, true /* set_mode */) {} + : lexer (is, name, line, escapes, true /* set_mode */) {} const path& name () const {return name_;} @@ -180,13 +181,11 @@ namespace build2 // Lexer state. // protected: - lexer (istream& is, - const path& name, - uint64_t line, + lexer (istream& is, const path& name, uint64_t line, const char* escapes, bool set_mode) : char_scanner (is, true /* crlf */, line), - fail ("error", &name_), + fail ("error", &name), name_ (name), sep_ (false) { @@ -194,7 +193,7 @@ namespace build2 mode (lexer_mode::normal, '@', escapes); } - const path name_; // @@ TODO: why not shallow (like istream)? + const path& name_; std::stack state_; bool sep_; // True if we skipped spaces in peek(). diff --git a/libbuild2/lexer.test.cxx b/libbuild2/lexer.test.cxx index 84520d1..2e2f152 100644 --- a/libbuild2/lexer.test.cxx +++ b/libbuild2/lexer.test.cxx @@ -48,7 +48,8 @@ namespace build2 // Most alternative modes auto-expire so we need something underneath. // - lexer l (cin, path ("stdin")); + path in (""); // @@ PATH_NAME TODO + lexer l (cin, in); if (m != lexer_mode::normal) l.mode (m); diff --git a/libbuild2/parser.cxx b/libbuild2/parser.cxx index 533853c..7289338 100644 --- a/libbuild2/parser.cxx +++ b/libbuild2/parser.cxx @@ -1622,7 +1622,7 @@ namespace build2 }); source (is, - path (""), + path (""), // @@ PATH_NAME TODO l, false /* enter */, false /* default_target */); @@ -5382,7 +5382,7 @@ namespace build2 // normally: perform(update($identity(foo/ bar/))). // buildspec parser:: - parse_buildspec (istream& is, const path& name) + parse_buildspec (istream& is, const path& name) // @@ PATH_NAME TODO { path_ = &name; diff --git a/libbuild2/test/script/lexer+description-line.test.testscript b/libbuild2/test/script/lexer+description-line.test.testscript index bb5948a..3fa51bd 100644 --- a/libbuild2/test/script/lexer+description-line.test.testscript +++ b/libbuild2/test/script/lexer+description-line.test.testscript @@ -29,5 +29,5 @@ EOO $* <:"foo" >>EOO 2>>EOE != 0 'foo' EOO -stdin:1:4: error: expected newline at the end of description line +:1:4: error: expected newline at the end of description line EOE diff --git a/libbuild2/test/script/lexer+variable.test.testscript b/libbuild2/test/script/lexer+variable.test.testscript index 64b2bee..7c0807a 100644 --- a/libbuild2/test/script/lexer+variable.test.testscript +++ b/libbuild2/test/script/lexer+variable.test.testscript @@ -65,6 +65,6 @@ test.arguments = variable : multi-digit : $* <"10" 2>>EOE != 0 - stdin:1:1: error: multi-digit special variable name + :1:1: error: multi-digit special variable name EOE } diff --git a/libbuild2/test/script/lexer.hxx b/libbuild2/test/script/lexer.hxx index d96e91b..4083161 100644 --- a/libbuild2/test/script/lexer.hxx +++ b/libbuild2/test/script/lexer.hxx @@ -45,15 +45,15 @@ namespace build2 using base_lexer = build2::lexer; using base_mode = build2::lexer_mode; + // Note that neither the name nor escape arguments are copied. + // lexer (istream& is, const path& name, lexer_mode m, const char* escapes = nullptr) - : base_lexer (is, - name, - 1 /* line */, - nullptr /* escapes */, - false /* set_mode */) + : base_lexer (is, name, 1 /* line */, + nullptr /* escapes */, + false /* set_mode */) { mode (m, '\0', escapes); } diff --git a/libbuild2/test/script/lexer.test.cxx b/libbuild2/test/script/lexer.test.cxx index 5a421b8..fc26acc 100644 --- a/libbuild2/test/script/lexer.test.cxx +++ b/libbuild2/test/script/lexer.test.cxx @@ -53,7 +53,8 @@ namespace build2 m == lexer_mode::description_line || m == lexer_mode::variable); - lexer l (cin, path ("stdin"), u ? lexer_mode::command_line : m); + path in (""); // @@ PATH_NAME TODO + lexer l (cin, in, u ? lexer_mode::command_line : m); if (u) l.mode (m); diff --git a/libbuild2/test/script/parser.cxx b/libbuild2/test/script/parser.cxx index bc06ce8..d5e437b 100644 --- a/libbuild2/test/script/parser.cxx +++ b/libbuild2/test/script/parser.cxx @@ -2302,9 +2302,9 @@ namespace build2 // cmd $args # cmd x="foo bar" // - path name (""); istringstream is (s); - lexer lex (is, name, + path in (""); // @@ PATH_NAME TODO + lexer lex (is, in, lexer_mode::command_expansion, "\'\"\\"); @@ -2315,7 +2315,7 @@ namespace build2 // fail(t). Rather we should do fail(l). // token t (lex.next ()); - location l (build2::get_location (t, name)); + location l (build2::get_location (t, in)); t.separated = true; string w; @@ -2324,7 +2324,7 @@ namespace build2 for (; t.type != type::eos; t = lex.next ()) { type tt (t.type); - l = build2::get_location (t, name); + l = build2::get_location (t, in); // Re-lexing double-quotes will recognize $, ( inside as // tokens so we have to reverse them back. Since we don't diff --git a/libbuild2/test/script/runner.cxx b/libbuild2/test/script/runner.cxx index 520be43..e56dc41 100644 --- a/libbuild2/test/script/runner.cxx +++ b/libbuild2/test/script/runner.cxx @@ -167,7 +167,7 @@ namespace build2 } catch (const io_error& e) { - fail (ll) << "unable to write " << p << ": " << e; + fail (ll) << "unable to write to " << p << ": " << e; } } @@ -339,7 +339,7 @@ namespace build2 } catch (const io_error& e) { - fail (ll) << "unable to write " << ep << ": " << e; + fail (ll) << "unable to write to " << ep << ": " << e; } // Diff utility prints the differences to stdout. But for the @@ -1134,7 +1134,7 @@ namespace build2 value (move (ns)), *ats, token_type::assign, - path ("")); + path ("")); // @@ PATH_NAME TODO } } catch (const io_error& e) @@ -1536,7 +1536,7 @@ namespace build2 } catch (const io_error& e) { - fail (ll) << "unable to write " << p << ": " << e; + fail (ll) << "unable to write to " << p << ": " << e; } return fd; diff --git a/libbuild2/types.hxx b/libbuild2/types.hxx index b14a365..192b01f 100644 --- a/libbuild2/types.hxx +++ b/libbuild2/types.hxx @@ -227,6 +227,7 @@ namespace build2 // // using butl::path; + using butl::path_name; using butl::dir_path; using butl::path_cast; using butl::basic_path; @@ -274,13 +275,13 @@ namespace build2 using butl::sha256; // - // - // using butl::process; using butl::process_env; using butl::process_path; using butl::process_error; + // + // using butl::auto_fd; using butl::ifdstream; using butl::ofdstream; @@ -319,12 +320,16 @@ namespace build2 location (const path* f = nullptr, uint64_t l = 0, uint64_t c = 0) : file (f), line (l), column (c) {} + explicit + location (const path_name& f, uint64_t l = 0, uint64_t c = 0) + : file (f), line (l), column (c) {} + bool - empty () const {return file == nullptr;} + empty () const {return file.path == nullptr;} - const path* file; - uint64_t line; - uint64_t column; + path_name file; + uint64_t line; + uint64_t column; }; // See context. @@ -342,11 +347,14 @@ namespace build2 // namespace std { - // Path printing with trailing slash for directories. + // Path printing potentially relative with trailing slash for directories. // LIBBUILD2_SYMEXPORT ostream& operator<< (ostream&, const ::butl::path&); + LIBBUILD2_SYMEXPORT ostream& + operator<< (ostream&, const ::butl::path_name&); + // Print as recall[@effect]. // LIBBUILD2_SYMEXPORT ostream& diff --git a/libbuild2/utility.cxx b/libbuild2/utility.cxx index 7f40688..b7637f5 100644 --- a/libbuild2/utility.cxx +++ b/libbuild2/utility.cxx @@ -8,7 +8,7 @@ #include // ENOENT #include // strlen(), str[n]cmp() -#include // cin cout cerr +#include // cerr #include #include @@ -45,6 +45,12 @@ namespace std } ostream& + operator<< (ostream& os, const ::butl::path_name& pn) + { + return pn.name ? (os << *pn.name) : (os << *pn.path); + } + + ostream& operator<< (ostream& os, const ::butl::process_path& p) { using namespace build2; @@ -100,36 +106,6 @@ namespace build2 dir_path home; const dir_path* relative_base = &work; - istream& - open_file_or_stdin (const path& f, ifdstream& ifs) - { - if (f.string () != "-") - { - ifs.open (f); - return ifs; - } - else - { - cin.exceptions (ifdstream::failbit | ifdstream::badbit); - return cin; - } - } - - ostream& - open_file_or_stdout (const path& f, ofdstream& ofs) - { - if (f.string () != "-") - { - ofs.open (f); - return ofs; - } - else - { - cout.exceptions (ofdstream::failbit | ofdstream::badbit); - return cout; - } - } - path relative (const path_target& t) { @@ -141,7 +117,7 @@ namespace build2 string diag_relative (const path& p, bool cur) { - if (p.string () == "-") + if (p.string () == "-") // @@ PATH_NAME: remove return ""; const path& b (*relative_base); diff --git a/libbuild2/utility.hxx b/libbuild2/utility.hxx index 8cd33cf..23ad19b 100644 --- a/libbuild2/utility.hxx +++ b/libbuild2/utility.hxx @@ -88,18 +88,10 @@ namespace build2 using butl::eof; - // Open a file or, if the file name is `-`, stdin/stdout. + // // - // Note that ofdstream::close() should be called explicitly if not stdout - // (but harmless to call even if it is). Also note that our overload of - // operator<<(path) always translats `-` to `` so care must be taken - // when issuing diagnostics. - // - istream& - open_file_or_stdin (const path&, ifdstream&); - - ostream& - open_file_or_stdout (const path&, ofdstream&); + using butl::open_file_or_stdin; + using butl::open_file_or_stdout; // Diagnostics state (verbosity level, etc; see ). // -- cgit v1.1