From 69801c4e23f877359118e55ed291737f4fbece04 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 28 Mar 2016 09:45:20 +0200 Subject: Add variable cast from lookup --- build2/b.cxx | 2 +- build2/bin/rule.cxx | 4 ++-- build2/cli/module.cxx | 4 ++-- build2/cli/rule.cxx | 2 +- build2/config/operation.cxx | 6 +++--- build2/cxx/compile.cxx | 16 ++++++++-------- build2/cxx/link.cxx | 30 +++++++++++++++--------------- build2/cxx/module.cxx | 2 +- build2/cxx/utility.txx | 2 +- build2/dist/operation.cxx | 14 +++++++------- build2/file.cxx | 16 ++++++++-------- build2/install/module.cxx | 2 +- build2/install/rule.cxx | 20 ++++++++++---------- build2/target.txx | 2 +- build2/test/rule.cxx | 10 +++++----- build2/utility.cxx | 6 +++--- build2/variable | 8 +++++++- build2/variable.ixx | 14 ++++++++++++++ 18 files changed, 90 insertions(+), 70 deletions(-) diff --git a/build2/b.cxx b/build2/b.cxx index f2cb9eb..b80fe5b 100644 --- a/build2/b.cxx +++ b/build2/b.cxx @@ -555,7 +555,7 @@ main (int argc, char* argv[]) // if (auto l = rs.vars["subprojects"]) { - for (const auto& p: cast (*l)) + for (const auto& p: cast (l)) { if (out_base.sub (out_root / p.second)) fail << tn << " is in a subproject of " << out_root << diff --git a/build2/bin/rule.cxx b/build2/bin/rule.cxx index d74dd65..b5d5ca6 100644 --- a/build2/bin/rule.cxx +++ b/build2/bin/rule.cxx @@ -46,7 +46,7 @@ namespace build2 // Get the library type to build. If not set for a target, this // should be configured at the project scope by init_lib(). // - const string& type (cast (*t["bin.lib"])); + const string& type (cast (t["bin.lib"])); bool ar (type == "static" || type == "both"); bool so (type == "shared" || type == "both"); @@ -121,7 +121,7 @@ namespace build2 // prerequisite vs prerequisite_target. // // - const string& type (cast (*t["bin.lib"])); + const string& type (cast (t["bin.lib"])); bool ar (type == "static" || type == "both"); bool so (type == "shared" || type == "both"); diff --git a/build2/cli/module.cxx b/build2/cli/module.cxx index 907bd0b..4e81908 100644 --- a/build2/cli/module.cxx +++ b/build2/cli/module.cxx @@ -45,7 +45,7 @@ namespace build2 { auto l (base["cxx.loaded"]); - if (!l || !cast (*l)) + if (!l || !cast (l)) fail (loc) << "cxx module must be loaded before cli"; } @@ -90,7 +90,7 @@ namespace build2 { auto l (root["config.cli.configured"]); - if (l && !cast (*l)) + if (l && !cast (l)) return false; } diff --git a/build2/cli/rule.cxx b/build2/cli/rule.cxx index 243c6aa..de14aa1 100644 --- a/build2/cli/rule.cxx +++ b/build2/cli/rule.cxx @@ -244,7 +244,7 @@ namespace build2 path rels (relative (s->path ())); scope& rs (t.root_scope ()); - const string& cli (cast (*rs["config.cli"])); + const string& cli (cast (rs["config.cli"])); cstrings args {cli.c_str ()}; diff --git a/build2/config/operation.cxx b/build2/config/operation.cxx index 8047e61..245aed7 100644 --- a/build2/config/operation.cxx +++ b/build2/config/operation.cxx @@ -86,7 +86,7 @@ namespace build2 if (auto l = root.vars["amalgamation"]) { - const dir_path& d (cast (*l)); + const dir_path& d (cast (l)); ofs << "# Base configuration inherited from " << d << endl << "#" << endl; @@ -188,7 +188,7 @@ namespace build2 // if (auto l = root.vars["subprojects"]) { - for (auto p: cast (*l)) + for (auto p: cast (l)) { const dir_path& pd (p.second); dir_path out_nroot (out_root / pd); @@ -313,7 +313,7 @@ namespace build2 // if (auto l = root.vars["subprojects"]) { - for (auto p: cast (*l)) + for (auto p: cast (l)) { const dir_path& pd (p.second); diff --git a/build2/cxx/compile.cxx b/build2/cxx/compile.cxx index a2b00de..cf0c91c 100644 --- a/build2/cxx/compile.cxx +++ b/build2/cxx/compile.cxx @@ -130,7 +130,7 @@ namespace build2 // if (a == perform_update_id) { - const string& sys (cast (*rs["cxx.target.system"])); + const string& sys (cast (rs["cxx.target.system"])); // The cached prerequisite target should be the same as what is in // t.prerequisite_targets since we used standard search() and match() @@ -165,7 +165,7 @@ namespace build2 // Then the compiler checksum. // - if (dd.expect (cast (*rs["cxx.checksum"])) != nullptr) + if (dd.expect (cast (rs["cxx.checksum"])) != nullptr) l4 ([&]{trace << "compiler mismatch forcing update of " << t;}); // Then the options checksum. @@ -237,7 +237,7 @@ namespace build2 -> const target_type* { if (auto l = s.lookup (tt, n, var)) - if (cast (*l) == e) + if (cast (l) == e) return &tt; return nullptr; @@ -283,7 +283,7 @@ namespace build2 if (auto l = t[var]) { - const auto& v (cast (*l)); + const auto& v (cast (l)); for (auto i (v.begin ()), e (v.end ()); i != e; ++i) { @@ -461,8 +461,8 @@ namespace build2 auto init_args = [&t, &s, &rs, &args, &cxx_std] () { - const string& cxx (cast (*rs["config.cxx"])); - const string& sys (cast (*rs["cxx.target.system"])); + const string& cxx (cast (rs["config.cxx"])); + const string& sys (cast (rs["cxx.target.system"])); args.push_back (cxx.c_str ()); @@ -923,8 +923,8 @@ namespace build2 path rels (relative (s->path ())); scope& rs (t.root_scope ()); - const string& cxx (cast (*rs["config.cxx"])); - const string& sys (cast (*rs["cxx.target.system"])); + const string& cxx (cast (rs["config.cxx"])); + const string& sys (cast (rs["cxx.target.system"])); cstrings args {cxx.c_str ()}; diff --git a/build2/cxx/link.cxx b/build2/cxx/link.cxx index ea20a47..c0ea6d3 100644 --- a/build2/cxx/link.cxx +++ b/build2/cxx/link.cxx @@ -42,7 +42,7 @@ namespace build2 case type::so: var = "bin.libso.lib"; break; } - const auto& v (cast (*t[var])); + const auto& v (cast (t[var])); return v[0] == "shared" ? v.size () > 1 && v[1] == "static" ? order::so_a : order::so : v.size () > 1 && v[1] == "shared" ? order::a_so : order::a; @@ -52,7 +52,7 @@ namespace build2 link_member (bin::lib& l, order lo) { bool lso (true); - const string& at (cast (*l["bin.lib"])); // Available types. + const string& at (cast (l["bin.lib"])); // Available types. switch (lo) { @@ -92,7 +92,7 @@ namespace build2 // if (auto l = bs["cxx.loptions"]) { - const auto& v (cast (*l)); + const auto& v (cast (l)); for (auto i (v.begin ()), e (v.end ()); i != e; ++i) { @@ -123,7 +123,7 @@ namespace build2 cstrings args; string std_storage; - args.push_back (cast (*rs["config.cxx"]).c_str ()); + args.push_back (cast (rs["config.cxx"]).c_str ()); append_options (args, bs, "cxx.coptions"); append_std (args, bs, std_storage); append_options (args, bs, "cxx.loptions"); @@ -218,7 +218,7 @@ namespace build2 return p.target; scope& rs (*p.scope.root_scope ()); - const string& sys (cast (*rs["cxx.target.system"])); + const string& sys (cast (rs["cxx.target.system"])); bool l (p.is_a ()); const string* ext (l ? nullptr : p.ext); // Only for liba/libso. @@ -483,7 +483,7 @@ namespace build2 path_target& t (static_cast (xt)); scope& rs (t.root_scope ()); - const string& sys (cast (*rs["cxx.target.system"])); + const string& sys (cast (rs["cxx.target.system"])); type lt (link_type (t)); bool so (lt == type::so); @@ -510,7 +510,7 @@ namespace build2 case type::so: { auto l (t["bin.libprefix"]); - const char* p (l ? cast (*l).c_str () : "lib"); + const char* p (l ? cast (l).c_str () : "lib"); const char* e; if (lt == type::a) @@ -769,7 +769,7 @@ namespace build2 bool up (execute_prerequisites (a, t, t.mtime ())); scope& rs (t.root_scope ()); - const string& sys (cast (*rs["cxx.target.system"])); + const string& sys (cast (rs["cxx.target.system"])); // Check/update the dependency database. // @@ -793,10 +793,10 @@ namespace build2 const char* rl ( ranlib - ? cast (*rs["bin.ranlib.checksum"]).c_str () + ? cast (rs["bin.ranlib.checksum"]).c_str () : "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); - if (dd.expect (cast (*rs["bin.ar.checksum"])) != nullptr) + if (dd.expect (cast (rs["bin.ar.checksum"])) != nullptr) l4 ([&]{trace << "ar mismatch forcing update of " << t;}); if (dd.expect (rl) != nullptr) @@ -804,7 +804,7 @@ namespace build2 } else { - if (dd.expect (cast (*rs["cxx.checksum"])) != nullptr) + if (dd.expect (cast (rs["cxx.checksum"])) != nullptr) l4 ([&]{trace << "compiler mismatch forcing update of " << t;}); } @@ -877,7 +877,7 @@ namespace build2 // precedence. // if (auto l = t["bin.rpath"]) - for (const string& p: cast (*l)) + for (const string& p: cast (l)) sargs.push_back ("-Wl,-rpath," + p); // Then the paths of the shared libraries we are linking to. Unless @@ -978,12 +978,12 @@ namespace build2 if (lt == type::a) { - args[0] = cast (*rs["config.bin.ar"]).c_str (); + args[0] = cast (rs["config.bin.ar"]).c_str (); args.push_back (relt.string ().c_str ()); } else { - args[0] = cast (*rs["config.cxx"]).c_str (); + args[0] = cast (rs["config.cxx"]).c_str (); args.push_back ("-o"); args.push_back (relt.string ().c_str ()); } @@ -1048,7 +1048,7 @@ namespace build2 if (ranlib) { const char* args[] = { - cast (*ranlib).c_str (), relt.string ().c_str (), nullptr}; + cast (ranlib).c_str (), relt.string ().c_str (), nullptr}; if (verb >= 2) print_process (args); diff --git a/build2/cxx/module.cxx b/build2/cxx/module.cxx index d491079..18f9e53 100644 --- a/build2/cxx/module.cxx +++ b/build2/cxx/module.cxx @@ -46,7 +46,7 @@ namespace build2 { auto l (b["bin.loaded"]); - if (!l || !cast (*l)) + if (!l || !cast (l)) load_module (false, "bin", r, b, loc); } diff --git a/build2/cxx/utility.txx b/build2/cxx/utility.txx index c20e437..4d38513 100644 --- a/build2/cxx/utility.txx +++ b/build2/cxx/utility.txx @@ -14,7 +14,7 @@ namespace build2 { if (auto l = t["cxx.std"]) { - const string& v (cast (*l)); + const string& v (cast (l)); // Translate 11 to 0x and 14 to 1y for compatibility with older // versions of the compiler. diff --git a/build2/dist/operation.cxx b/build2/dist/operation.cxx index 4489485..cb418be 100644 --- a/build2/dist/operation.cxx +++ b/build2/dist/operation.cxx @@ -90,7 +90,7 @@ namespace build2 fail << "unknown root distribution directory" << info << "did you forget to specify config.dist.root?"; - const dir_path& dist_root (cast (*l)); + const dir_path& dist_root (cast (l)); if (!dir_exists (dist_root)) fail << "root distribution directory " << dist_root @@ -102,8 +102,8 @@ namespace build2 fail << "unknown distribution package name" << info << "did you forget to set dist.package?"; - const string& dist_package (cast (*l)); - const string& dist_cmd (cast (*rs->vars["dist.cmd"])); + const string& dist_package (cast (l)); + const string& dist_cmd (cast (rs->vars["dist.cmd"])); // Get the list of operations supported by this project. Skip // default_id. @@ -171,7 +171,7 @@ namespace build2 // if (auto l = rs->vars["subprojects"]) { - for (auto p: cast (*l)) + for (auto p: cast (l)) { const dir_path& pd (p.second); dir_path out_nroot (out_root / pd); @@ -209,7 +209,7 @@ namespace build2 // auto l ((*ft)[dist_var]); - if (l && !cast (*l)) + if (l && !cast (l)) l5 ([&]{trace << "excluding " << *ft;}); else files.push_back (ft); @@ -223,7 +223,7 @@ namespace build2 // auto l ((*ft)[dist_var]); - if (l && cast (*l)) + if (l && cast (l)) { l5 ([&]{trace << "including " << *ft;}); files.push_back (ft); @@ -295,7 +295,7 @@ namespace build2 // if (auto l = rs->vars["dist.archives"]) { - for (const string& e: cast (*l)) + for (const string& e: cast (l)) archive (dist_root, dist_package, e); } } diff --git a/build2/file.cxx b/build2/file.cxx index 30ebed4..9097703 100644 --- a/build2/file.cxx +++ b/build2/file.cxx @@ -660,7 +660,7 @@ namespace build2 if (!l) return; - const dir_path& d (cast (*l)); + const dir_path& d (cast (l)); dir_path out_root (root.out_path () / d); out_root.normalize (); @@ -712,7 +712,7 @@ namespace build2 { if (auto l = root.vars["subprojects"]) { - for (const auto& p: cast (*l)) + for (const auto& p: cast (l)) { dir_path out_root (root.out_path () / p.second); @@ -819,7 +819,7 @@ namespace build2 { // First check the amalgamation itself. // - if (r != &iroot && cast (*r->vars["project"]) == project) + if (r != &iroot && cast (r->vars["project"]) == project) { out_root = r->out_path (); break; @@ -827,7 +827,7 @@ namespace build2 if (auto l = r->vars["subprojects"]) { - const auto& m (cast (*l)); + const auto& m (cast (l)); auto i (m.find (project)); if (i != m.end ()) @@ -851,7 +851,7 @@ namespace build2 if (auto l = iroot[var]) { - out_root = cast (*l); + out_root = cast (l); if (l.belongs (*global_scope)) // A value from command line. { @@ -911,7 +911,7 @@ namespace build2 // if (auto l = root->vars["src_root"]) { - const dir_path& p (cast (*l)); + const dir_path& p (cast (l)); if (!src_root.empty () && p != src_root) fail (loc) << "bootstrapped src_root " << p << " does not match " @@ -928,12 +928,12 @@ namespace build2 // Now we know this project's name as well as all its subprojects. // - if (cast (*root->vars["project"]) == project) + if (cast (root->vars["project"]) == project) break; if (auto l = root->vars["subprojects"]) { - const auto& m (cast (*l)); + const auto& m (cast (l)); auto i (m.find (project)); if (i != m.end ()) diff --git a/build2/install/module.cxx b/build2/install/module.cxx index 8e3d6fd..3890901 100644 --- a/build2/install/module.cxx +++ b/build2/install/module.cxx @@ -154,7 +154,7 @@ namespace build2 if (first) { bool s (config::specified (r, "config.install")); - const string& n (cast (*r["project"])); + const string& n (cast (r["project"])); set_dir (s, r, "root", "", "", "755", "install"); set_dir (s, r, "data_root", "root", "644"); diff --git a/build2/install/rule.cxx b/build2/install/rule.cxx index 89463f8..25259cf 100644 --- a/build2/install/rule.cxx +++ b/build2/install/rule.cxx @@ -31,7 +31,7 @@ namespace build2 if (!l) return nullptr; - const dir_path& r (cast (*l)); + const dir_path& r (cast (l)); return r.simple () && r.string () == "false" ? nullptr : &r; } @@ -64,7 +64,7 @@ namespace build2 // auto l (pt["install"]); - if (l && cast (*l).string () == "false") + if (l && cast (l).string () == "false") { l5 ([&]{trace << "ignoring " << pt;}); continue; @@ -148,7 +148,7 @@ namespace build2 // See if the user instructed us not to install it. // auto l ((*pt)["install"]); - if (l && cast (*l).string () == "false") + if (l && cast (l).string () == "false") continue; build2::match (a, *pt); @@ -358,11 +358,11 @@ namespace build2 // if (var != nullptr) { - if (auto l = s[*var + ".sudo"]) r.sudo = cast (*l); - if (auto l = s[*var + ".cmd"]) r.cmd = cast (*l); - if (auto l = s[*var + ".mode"]) r.mode = cast (*l); - if (auto l = s[*var + ".dir_mode"]) r.dir_mode = cast (*l); - if (auto l = s[*var + ".options"]) r.options = cast (*l); + if (auto l = s[*var + ".sudo"]) r.sudo = cast (l); + if (auto l = s[*var + ".cmd"]) r.cmd = cast (l); + if (auto l = s[*var + ".mode"]) r.mode = cast (l); + if (auto l = s[*var + ".dir_mode"]) r.dir_mode = cast (l); + if (auto l = s[*var + ".options"]) r.options = cast (l); } // Set defaults for unspecified components. @@ -403,12 +403,12 @@ namespace build2 // install_dir d ( resolve (t.base_scope (), - cast (*t["install"]))); // We know it's there. + cast (t["install"]))); // We know it's there. // Override mode if one was specified. // if (auto l = t["install.mode"]) - d.mode = cast (*l); + d.mode = cast (l); install (d, ft); return (r |= target_state::changed); diff --git a/build2/target.txx b/build2/target.txx index 2cb4d2e..b7d41f2 100644 --- a/build2/target.txx +++ b/build2/target.txx @@ -26,7 +26,7 @@ namespace build2 { // Help the user here and strip leading '.' from the extension. // - const string& e (cast (*l)); + const string& e (cast (l)); return &extension_pool.find ( !e.empty () && e.front () == '.' ? string (e, 1) : e); } diff --git a/build2/test/rule.cxx b/build2/test/rule.cxx index 0b3f59f..8c89bc7 100644 --- a/build2/test/rule.cxx +++ b/build2/test/rule.cxx @@ -70,7 +70,7 @@ namespace build2 l = t.base_scope ()[ var_pool.find (string("test.") + t.type ().name)]; - r = l && cast (*l); + r = l && cast (l); } // If this is the update pre-operation, then all we really need to @@ -181,12 +181,12 @@ namespace build2 fail << "both test.roundtrip and test.input/output specified " << "for target " << t; - in = on = &cast (*rl); + in = on = &cast (rl); } else { - in = il ? &cast (*il) : nullptr; - on = ol ? &cast (*ol) : nullptr; + in = il ? &cast (il) : nullptr; + on = ol ? &cast (ol) : nullptr; } // Resolve them to targets, which normally would be existing files @@ -296,7 +296,7 @@ namespace build2 } if (l) - append_options (args, cast (*l)); + append_options (args, cast (l)); } // The format of args shall be: diff --git a/build2/utility.cxx b/build2/utility.cxx index 29e8b1e..71aed79 100644 --- a/build2/utility.cxx +++ b/build2/utility.cxx @@ -147,14 +147,14 @@ namespace build2 append_options (cstrings& args, const lookup& l) { if (l) - append_options (args, cast (*l)); + append_options (args, cast (l)); } void hash_options (sha256& csum, const lookup& l) { if (l) - hash_options (csum, cast (*l)); + hash_options (csum, cast (l)); } void @@ -181,7 +181,7 @@ namespace build2 { if (l) { - for (const string& s: cast (*l)) + for (const string& s: cast (l)) { if (s == option) return true; diff --git a/build2/variable b/build2/variable index b5a32d8..57debfa 100644 --- a/build2/variable +++ b/build2/variable @@ -21,6 +21,7 @@ namespace build2 { class value; struct variable; + template struct lookup; struct value_type { @@ -185,15 +186,20 @@ namespace build2 bool operator== (const value&, const value&); bool operator!= (const value&, const value&); - // Value cast. + // Value cast. The first three expect the value to be not NULL. The cast + // from lookup expects the value to aslo be defined. // // Why are these non-members? The cast is easier on the eyes and is also // consistent with the cast operators. The other two are for symmetry. // + // template T& cast (value&); template T&& cast (value&&); template const T& cast (const value&); + template T& cast (const lookup&); + template const T& cast (const lookup&); + // Assign value type to the value. Variable is normally only used for // diagnostics. // diff --git a/build2/variable.ixx b/build2/variable.ixx index a129835..8a03996 100644 --- a/build2/variable.ixx +++ b/build2/variable.ixx @@ -104,6 +104,20 @@ namespace build2 } template + inline T& + cast (const lookup& l) + { + return cast (*l); + } + + template + inline const T& + cast (const lookup& l) + { + return cast (*l); + } + + template inline void typify (value& v, const variable& var) { -- cgit v1.1