diff options
33 files changed, 187 insertions, 198 deletions
diff --git a/build2/algorithm b/build2/algorithm index 9a91781..ad52fe1 100644 --- a/build2/algorithm +++ b/build2/algorithm @@ -44,7 +44,7 @@ namespace build2 const dir_path& dir, const dir_path& out, const string& name, - const string* ext, + const optional<string>& ext, scope*, const optional<string>& proj = nullopt); @@ -55,7 +55,7 @@ namespace build2 search (const dir_path& dir, const dir_path& out, const string& name, - const string* ext, + const optional<string>& ext, scope*); // Search for a target identified by the name. The semantics is "as if" we diff --git a/build2/algorithm.cxx b/build2/algorithm.cxx index 78af195..22633bb 100644 --- a/build2/algorithm.cxx +++ b/build2/algorithm.cxx @@ -37,8 +37,8 @@ namespace build2 target& search (name n, scope& s) { - const string* e; - const target_type* tt (s.find_target_type (n, e)); + optional<string> ext; + const target_type* tt (s.find_target_type (n, ext)); if (tt == nullptr) fail << "unknown target type " << n.type << " in name " << n; @@ -49,7 +49,7 @@ namespace build2 // @@ OUT: for now we assume the prerequisite's out is undetermined. // Would need to pass a pair of names. // - return search (*tt, n.dir, dir_path (), n.value, e, &s, n.proj); + return search (*tt, n.dir, dir_path (), n.value, ext, &s, n.proj); } pair<const rule*, match_result> @@ -333,7 +333,7 @@ namespace build2 // Target is in the out tree, so out directory is empty. // - fsdir* r (&search<fsdir> (d, dir_path (), string (), nullptr, nullptr)); + fsdir* r (&search<fsdir> (d, dir_path (), string (), nullopt, nullptr)); match (a, *r); t.prerequisite_targets.emplace_back (r); return r; diff --git a/build2/algorithm.ixx b/build2/algorithm.ixx index 84b0ee7..90a0789 100644 --- a/build2/algorithm.ixx +++ b/build2/algorithm.ixx @@ -30,7 +30,7 @@ namespace build2 const dir_path& dir, const dir_path& out, const string& name, - const string* ext, + const optional<string>& ext, scope* scope, const optional<string>& proj) { @@ -43,7 +43,7 @@ namespace build2 search (const dir_path& dir, const dir_path& out, const string& name, - const string* ext, + const optional<string>& ext, scope* scope) { return static_cast<T&> ( diff --git a/build2/b.cxx b/build2/b.cxx index bd77a02..ca8c15b 100644 --- a/build2/b.cxx +++ b/build2/b.cxx @@ -967,7 +967,9 @@ main (int argc, char* argv[]) // scope& bs (scopes.find (ts.out_base)); - const string* e; + // Find the target type and extract the extension. + // + optional<string> e; const target_type* ti (bs.find_target_type (tn, e)); if (ti == nullptr) diff --git a/build2/bin/rule.cxx b/build2/bin/rule.cxx index 70ad7df..ede2c85 100644 --- a/build2/bin/rule.cxx +++ b/build2/bin/rule.cxx @@ -75,7 +75,7 @@ namespace build2 if (a) { if (t.a == nullptr) - t.a = &search<liba> (t.dir, t.out, t.name, nullptr, nullptr); + t.a = &search<liba> (t.dir, t.out, t.name, nullopt, nullptr); match_only (act, *t.a); } @@ -83,7 +83,7 @@ namespace build2 if (s) { if (t.s == nullptr) - t.s = &search<libs> (t.dir, t.out, t.name, nullptr, nullptr); + t.s = &search<libs> (t.dir, t.out, t.name, nullopt, nullptr); match_only (act, *t.s); } diff --git a/build2/bin/target.cxx b/build2/bin/target.cxx index 9086369..e9ef81e 100644 --- a/build2/bin/target.cxx +++ b/build2/bin/target.cxx @@ -17,10 +17,10 @@ namespace build2 dir_path dir, dir_path out, string n, - const string* ext) + optional<string> ext) { obj* o (targets.find<obj> (dir, out, n)); - obje* e (new obje (move (dir), move (out), move (n), ext)); + obje* e (new obje (move (dir), move (out), move (n), move (ext))); if ((e->group = o)) o->e = e; @@ -44,10 +44,10 @@ namespace build2 dir_path dir, dir_path out, string n, - const string* ext) + optional<string> ext) { obj* o (targets.find<obj> (dir, out, n)); - obja* a (new obja (move (dir), move (out), move (n), ext)); + obja* a (new obja (move (dir), move (out), move (n), move (ext))); if ((a->group = o)) o->a = a; @@ -71,10 +71,10 @@ namespace build2 dir_path dir, dir_path out, string n, - const string* ext) + optional<string> ext) { obj* o (targets.find<obj> (dir, out, n)); - objs* s (new objs (move (dir), move (out), move (n), ext)); + objs* s (new objs (move (dir), move (out), move (n), move (ext))); if ((s->group = o)) o->s = s; @@ -98,13 +98,13 @@ namespace build2 dir_path dir, dir_path out, string n, - const string* ext) + optional<string> ext) { obje* e (targets.find<obje> (dir, out, n)); obja* a (targets.find<obja> (dir, out, n)); objs* s (targets.find<objs> (dir, out, n)); - obj* o (new obj (move (dir), move (out), move (n), ext)); + obj* o (new obj (move (dir), move (out), move (n), move (ext))); if ((o->e = e)) e->group = o; @@ -134,12 +134,12 @@ namespace build2 dir_path d, dir_path o, string n, - const string* ext) + optional<string> ext) { // Only link-up to the group if the types match exactly. // lib* l (t == liba::static_type ? targets.find<lib> (d, o, n) : nullptr); - liba* a (new liba (move (d), move (o), move (n), ext)); + liba* a (new liba (move (d), move (o), move (n), move (ext))); if ((a->group = l)) l->a = a; @@ -175,12 +175,12 @@ namespace build2 dir_path d, dir_path o, string n, - const string* ext) + optional<string> ext) { // Only link-up to the group if the types match exactly. // lib* l (t == libs::static_type ? targets.find<lib> (d, o, n) : nullptr); - libs* s (new libs (move (d), move (o), move (n), ext)); + libs* s (new libs (move (d), move (o), move (n), move (ext))); if ((s->group = l)) l->s = s; @@ -215,12 +215,12 @@ namespace build2 dir_path d, dir_path o, string n, - const string* ext) + optional<string> ext) { liba* a (targets.find<liba> (d, o, n)); libs* s (targets.find<libs> (d, o, n)); - lib* l (new lib (move (d), move (o), move (n), ext)); + lib* l (new lib (move (d), move (o), move (n), move (ext))); if ((l->a = a)) a->group = l; diff --git a/build2/cc/common.cxx b/build2/cc/common.cxx index 86d998e..6429a38 100644 --- a/build2/cc/common.cxx +++ b/build2/cc/common.cxx @@ -408,7 +408,7 @@ namespace build2 { // This is import. // - const string* ext; + optional<string> ext; const target_type* tt (s.find_target_type (n, ext)); // Changes name. if (tt == nullptr) @@ -455,7 +455,7 @@ namespace build2 // Windows. // bool l (p.is_a<lib> ()); - const string* ext (l ? nullptr : p.tk.ext); // Only for liba/libs. + const optional<string>& ext (l ? nullopt : p.tk.ext); // Only liba/libs. // Then figure out what we need to search for. // @@ -464,7 +464,7 @@ namespace build2 // liba // path an; - const string* ae (nullptr); + optional<string> ae; if (l || p.is_a<liba> ()) { @@ -494,10 +494,7 @@ namespace build2 e = "a"; } - ae = ext == nullptr - ? &extension_pool.find (e) - : ext; - + ae = ext ? ext : string (e); if (!ae->empty ()) { an += '.'; @@ -508,7 +505,7 @@ namespace build2 // libs // path sn; - const string* se (nullptr); + optional<string> se; if (l || p.is_a<libs> ()) { @@ -528,10 +525,7 @@ namespace build2 else e = "so"; } - se = ext == nullptr - ? &extension_pool.find (e) - : ext; - + se = ext ? ext : string (e); if (!se->empty ()) { sn += '.'; @@ -574,7 +568,7 @@ namespace build2 // if (tclass == "windows") { - s = &targets.insert<libs> (d, dir_path (), name, nullptr, trace); + s = &targets.insert<libs> (d, dir_path (), name, nullopt, trace); if (s->member == nullptr) { @@ -606,7 +600,7 @@ namespace build2 s->mtime (mt); } } - else if (ext == nullptr && tsys == "mingw32") + else if (!ext && tsys == "mingw32") { // Above we searched for the import library (.dll.a) but if it's // not found, then we also search for the .dll (unless the @@ -614,7 +608,7 @@ namespace build2 // directly. Note also that the resulting libs{} would end up // being the .dll. // - se = &extension_pool.find ("dll"); + se = string ("dll"); f = f.base (); // Remove .a from .dll.a. mt = file_mtime (f); @@ -762,7 +756,7 @@ namespace build2 // lib& lt ( targets.insert<lib> ( - *pd, dir_path (), name, l ? p.tk.ext : nullptr, trace)); + *pd, dir_path (), name, l ? p.tk.ext : nullopt, trace)); // It should automatically link-up to the members we have found. // diff --git a/build2/cc/compile.cxx b/build2/cc/compile.cxx index 23499ad..f837765 100644 --- a/build2/cc/compile.cxx +++ b/build2/cc/compile.cxx @@ -415,12 +415,11 @@ namespace build2 // only use the target type and name from the target key so we can // pass bogus values for the rest. // - const string* dummy (nullptr); - target_key tk {&tt, nullptr, nullptr, &n, dummy}; + target_key tk {&tt, nullptr, nullptr, &n, target_key::nullext}; // This is like prerequisite search. // - if (const string* de = tt.extension (tk, s, true)) + if (optional<string> de = tt.extension (tk, s, true)) if (*de == e) return true; @@ -913,7 +912,7 @@ namespace build2 // dir_path d (f.directory ()); string n (f.leaf ().base ().string ()); - const string* e (&extension_pool.find (f.extension ())); + string e (f.extension ()); // Determine the target type. // @@ -935,7 +934,7 @@ namespace build2 scope& bs (scopes.find (d)); if (scope* rs = bs.root_scope ()) { - tt = map_extension (bs, n, *e); + tt = map_extension (bs, n, e); if (bs.out_path () != bs.src_path () && d.sub (bs.src_path ())) out = out_src (d, *rs); diff --git a/build2/cc/link.cxx b/build2/cc/link.cxx index 8010598..e1dac16 100644 --- a/build2/cc/link.cxx +++ b/build2/cc/link.cxx @@ -337,7 +337,7 @@ namespace build2 if (t.member != nullptr) // Might already be there. assert (t.member->type () == tt); else - t.member = &search (tt, t.dir, t.out, t.name, nullptr, nullptr); + t.member = &search (tt, t.dir, t.out, t.name, nullopt, nullptr); file& r (static_cast<file&> (*t.member)); r.recipe (a, group_recipe); @@ -519,7 +519,7 @@ namespace build2 // obj*{} is always in the out tree. // target& ot ( - search (tt, d, dir_path (), *cp.tk.name, nullptr, cp.scope)); + search (tt, d, dir_path (), *cp.tk.name, nullopt, cp.scope)); // If we are cleaning, check that this target is in the same or // a subdirectory of our project root. diff --git a/build2/cc/msvc.cxx b/build2/cc/msvc.cxx index 5ce2f2a..4ac82a0 100644 --- a/build2/cc/msvc.cxx +++ b/build2/cc/msvc.cxx @@ -231,7 +231,7 @@ namespace build2 // tracer trace (mod, "msvc_search_library"); - const string* ext (p.tk.ext); + const optional<string>& ext (p.tk.ext); const string& name (*p.tk.name); // Assemble the file path. @@ -249,10 +249,9 @@ namespace build2 if (*sfx != '\0') f += sfx; - const string& e ( - ext == nullptr || p.is_a<lib> () // Only for liba/libs. - ? extension_pool.find ("lib") - : *ext); + const string& e (!ext || p.is_a<lib> () // Only for liba/libs. + ? string ("lib") + : *ext); if (!e.empty ()) { @@ -268,7 +267,7 @@ namespace build2 { // Enter the target. // - T& t (targets.insert<T> (d, dir_path (), name, &e, trace)); + T& t (targets.insert<T> (d, dir_path (), name, e, trace)); if (t.path ().empty ()) t.path (move (f)); @@ -323,7 +322,7 @@ namespace build2 msvc_search_library<libi> (x, ld, d, p, otype::s, pf, sf)) { r = &targets.insert<libs> ( - d, dir_path (), *p.tk.name, nullptr, trace); + d, dir_path (), *p.tk.name, nullopt, trace); if (r->member == nullptr) { diff --git a/build2/cc/pkgconfig.cxx b/build2/cc/pkgconfig.cxx index f8d35af..6c8159f 100644 --- a/build2/cc/pkgconfig.cxx +++ b/build2/cc/pkgconfig.cxx @@ -417,10 +417,11 @@ namespace build2 // dir_path out; string name (l, 2); // Sans -l. - const string* ext (nullptr); prerequisite_key pk { - nullopt, {&lib::static_type, &out, &out, &name, ext}, &s}; + nullopt, + {&lib::static_type, &out, &out, &name, target_key::nullext}, + &s}; if (lib* lt = static_cast<lib*> (search_library (sysd, usrd, pk))) { diff --git a/build2/cli/rule.cxx b/build2/cli/rule.cxx index b97bea2..d457e6d 100644 --- a/build2/cli/rule.cxx +++ b/build2/cli/rule.cxx @@ -88,15 +88,15 @@ namespace build2 // if (t.h == nullptr) { - t.h = &search<cxx::hxx> (t.dir, t.out, t.name, nullptr, nullptr); + t.h = &search<cxx::hxx> (t.dir, t.out, t.name, nullopt, nullptr); t.h->group = &t; - t.c = &search<cxx::cxx> (t.dir, t.out, t.name, nullptr, nullptr); + t.c = &search<cxx::cxx> (t.dir, t.out, t.name, nullopt, nullptr); t.c->group = &t; if (!find_option ("--suppress-inline", t, "cli.options")) { - t.i = &search<cxx::ixx> (t.dir, t.out, t.name, nullptr, nullptr); + t.i = &search<cxx::ixx> (t.dir, t.out, t.name, nullopt, nullptr); t.i->group = &t; } } @@ -211,7 +211,7 @@ namespace build2 const char* option, const char* default_extension) { - assert (t.ext != nullptr); // Should have been figured out in apply(). + assert (t.ext); // Should have been figured out in apply(). if (*t.ext != default_extension) { diff --git a/build2/cli/target b/build2/cli/target index 0160ef3..0cc448d 100644 --- a/build2/cli/target +++ b/build2/cli/target @@ -49,8 +49,8 @@ namespace build2 //using mtime_target::mtime_target; // @@ GCC 4.8 - cli_cxx (dir_path d, dir_path o, string n, const string* e) - : mtime_target (move (d), move (o), move (n), e) + cli_cxx (dir_path d, dir_path o, string n, optional<string> e) + : mtime_target (move (d), move (o), move (n), move (e)) { m[0] = m[1] = m[2] = nullptr; } diff --git a/build2/cli/target.cxx b/build2/cli/target.cxx index 5e12a04..3f09d30 100644 --- a/build2/cli/target.cxx +++ b/build2/cli/target.cxx @@ -53,7 +53,7 @@ namespace build2 dir_path d, dir_path o, string n, - const string* e) + optional<string> e) { tracer trace ("cli::cli_cxx_factory"); @@ -66,7 +66,7 @@ namespace build2 targets.insert<cxx::cxx> (d, o, n, trace); targets.insert<cxx::ixx> (d, o, n, trace); - return new cli_cxx (move (d), move (o), move (n), e); + return new cli_cxx (move (d), move (o), move (n), move (e)); } const target_type cli_cxx::static_type diff --git a/build2/config/operation.cxx b/build2/config/operation.cxx index 3370c2c..68b61c3 100644 --- a/build2/config/operation.cxx +++ b/build2/config/operation.cxx @@ -570,7 +570,7 @@ namespace build2 root.out_path (), dir_path (), // Out tree. "", - nullptr, + nullopt, trace).first); if (!quiet) diff --git a/build2/context b/build2/context index cb83105..1dd9daf 100644 --- a/build2/context +++ b/build2/context @@ -16,8 +16,6 @@ namespace build2 { class file; - extern string_pool extension_pool; - // Current action (meta/operation). // // The names unlike info are available during boot but may not yet be diff --git a/build2/context.cxx b/build2/context.cxx index a21de2a..ba6629c 100644 --- a/build2/context.cxx +++ b/build2/context.cxx @@ -23,8 +23,6 @@ using namespace butl; namespace build2 { - string_pool extension_pool; - const string* current_mname; const string* current_oname; @@ -56,8 +54,6 @@ namespace build2 scopes.clear (); var_pool.clear (); - extension_pool.clear (); - // Reset meta/operation tables. Note that the order should match the id // constants in <build2/operation>. // diff --git a/build2/dist/operation.cxx b/build2/dist/operation.cxx index 47e188c..9535566 100644 --- a/build2/dist/operation.cxx +++ b/build2/dist/operation.cxx @@ -160,7 +160,7 @@ namespace build2 move (d), move (out), p.leaf ().base ().string (), - &extension_pool.find (p.extension ()), // Specified. + p.extension (), // Specified. trace); } }; diff --git a/build2/file.cxx b/build2/file.cxx index 9e957a9..2889cf7 100644 --- a/build2/file.cxx +++ b/build2/file.cxx @@ -1112,8 +1112,11 @@ namespace build2 { path n (*tk.dir); n /= *tk.name; - if (tk.ext != nullptr) + if (tk.ext) + { + n += '.'; n += *tk.ext; + } process_path pp (process::try_path_search (n, true)); @@ -1126,9 +1129,9 @@ namespace build2 targets.insert<exe> ( tt, p.directory (), - dir_path (), // No out (out of project). + dir_path (), // No out (out of project). p.leaf ().base ().string (), - &extension_pool.find (p.extension ()), // Specified. + p.extension (), // Always specified. trace)); if (t.path ().empty ()) diff --git a/build2/parser.cxx b/build2/parser.cxx index 6025082..9ce916e 100644 --- a/build2/parser.cxx +++ b/build2/parser.cxx @@ -91,7 +91,7 @@ namespace build2 tracer& tr) : p_ (&p), t_ (p.target_) { - const string* e; + optional<string> e; const target_type* ti (p.scope_->find_target_type (n, e)); if (ti == nullptr) @@ -131,7 +131,7 @@ namespace build2 // Find or insert. // p.target_ = &targets.insert ( - *ti, move (d), move (out), move (n.value), e, tr).first; + *ti, move (d), move (out), move (n.value), move (e), tr).first; } ~enter_target () @@ -642,7 +642,7 @@ namespace build2 for (auto& pn: pns) { - const string* e; + optional<string> e; const target_type* ti (scope_->find_target_type (pn, e)); if (ti == nullptr) @@ -672,7 +672,7 @@ namespace build2 move (pn.dir), dir_path (), move (pn.value), - e, + move (e), *scope_, trace).first); @@ -3560,7 +3560,7 @@ namespace build2 scope_->out_path (), dir_path (), // Out tree target. "", - nullptr, + nullopt, trace) != targets.end ()) return; @@ -3573,7 +3573,7 @@ namespace build2 scope_->out_path (), dir_path (), "", - nullptr, + nullopt, trace).first); prerequisite& p ( @@ -3608,7 +3608,7 @@ namespace build2 move (d), move (out), p.leaf ().base ().string (), - &extension_pool.find (p.extension ()), // Always specified. + p.extension (), // Always specified. trace); } diff --git a/build2/prerequisite b/build2/prerequisite index b259557..5dfd1aa 100644 --- a/build2/prerequisite +++ b/build2/prerequisite @@ -31,11 +31,11 @@ namespace build2 target_key tk; // .dir and .out can be relative. mutable scope_type* scope; // Can be NULL if tk.dir is absolute. + static const optional<string> nullproj; + template <typename T> bool is_a () const {return tk.is_a<T> ();} bool is_a (const target_type& tt) const {return tk.is_a (tt);} - - static const optional<string> nullproj; }; inline bool @@ -90,14 +90,14 @@ namespace build2 // const optional<string> proj; const target_type_type& type; - const dir_path dir; // Normalized absolute or relative (to scope). - const dir_path out; // Empty, normalized absolute, or relative. + const dir_path dir; // Normalized absolute or relative (to scope). + const dir_path out; // Empty, normalized absolute, or relative. const string name; - const string* ext; // NULL if unspecified. + const optional<string> ext; // Absent if unspecified. scope_type& scope; - target_type* target; // NULL if not yet resolved. Note that this should - // always be the "primary target", not a member of - // a target group. + target_type* target; // NULL if not yet resolved. Note that this + // should always be the "primary target", not + // a member of a target group. public: prerequisite (optional<string> p, @@ -105,14 +105,14 @@ namespace build2 dir_path d, dir_path o, string n, - const string* e, + optional<string> e, scope_type& s) : proj (move (p)), type (t), dir (move (d)), out (move (o)), name (move (n)), - ext (e), + ext (move (e)), scope (s), target (nullptr) {} @@ -188,7 +188,7 @@ namespace build2 dir_path dir, dir_path out, string name, - const string* ext, + optional<string> ext, scope&, tracer&); diff --git a/build2/prerequisite.cxx b/build2/prerequisite.cxx index 82d6ea2..bcd4123 100644 --- a/build2/prerequisite.cxx +++ b/build2/prerequisite.cxx @@ -56,7 +56,7 @@ namespace build2 dir_path dir, dir_path out, string name, - const string* ext, + optional<string> ext, scope& s, tracer& trace) -> pair<prerequisite&, bool> { @@ -66,8 +66,13 @@ namespace build2 // Find or insert. // - auto r ( - emplace (move (proj), tt, move (dir), move (out), move (name), ext, s)); + auto r (emplace (move (proj), + tt, + move (dir), + move (out), + move (name), + ext, // Note: cannot move. + s)); prerequisite& p (const_cast<prerequisite&> (*r.first)); // Update extension if the existing prerequisite has it unspecified. @@ -78,7 +83,7 @@ namespace build2 diag_record r (trace); r << "assuming prerequisite " << p << " is the same as the " << "one with "; - if (ext == nullptr) + if (!ext) r << "unspecified extension"; else if (ext->empty ()) r << "no extension"; @@ -86,8 +91,8 @@ namespace build2 r << "extension " << *ext; }); - if (ext != nullptr) - p.ext = ext; + if (ext) + const_cast<optional<string>&> (p.ext) = move (ext); } return pair<prerequisite&, bool> (p, r.second); diff --git a/build2/scope b/build2/scope index 6b5af22..f22383a 100644 --- a/build2/scope +++ b/build2/scope @@ -218,7 +218,7 @@ namespace build2 // necessarily normalized). Return NULL if not found. // const target_type* - find_target_type (name&, const string*& ext) const; + find_target_type (name&, optional<string>& ext) const; // Dynamically derive a new target type from an existing one. Return the // reference to the target type and an indicator of whether it was diff --git a/build2/scope.cxx b/build2/scope.cxx index 9950042..8d0841b 100644 --- a/build2/scope.cxx +++ b/build2/scope.cxx @@ -547,9 +547,9 @@ namespace build2 static const string file_tt ("file"); const target_type* scope:: - find_target_type (name& n, const string*& ext) const + find_target_type (name& n, optional<string>& ext) const { - ext = nullptr; + ext = nullopt; string& v (n.value); @@ -613,7 +613,7 @@ namespace build2 if (j != string::npos) { - ext = &extension_pool.find (v.c_str () + j + 1); + ext = string (v.c_str () + j + 1); v.resize (j); } } @@ -626,7 +626,7 @@ namespace build2 dir_path d, dir_path o, string n, - const string* e) + optional<string> e) { // Pass our type to the base factory so that it can detect that it is // being called to construct a derived target. This can be used, for @@ -639,7 +639,7 @@ namespace build2 const target_type* bt (t.base); for (; bt->factory == &derived_tt_factory; bt = bt->base) ; - target* r (bt->factory (t, move (d), move (o), move (n), e)); + target* r (bt->factory (t, move (d), move (o), move (n), move (e))); r->derived_type = &t; return r; } diff --git a/build2/search.cxx b/build2/search.cxx index 75d94a0..50318a7 100644 --- a/build2/search.cxx +++ b/build2/search.cxx @@ -8,6 +8,7 @@ #include <build2/scope> #include <build2/target> +#include <build2/context> #include <build2/prerequisite> #include <build2/diagnostics> @@ -76,14 +77,14 @@ namespace build2 // Figure out the extension. Pretty similar logic to file::derive_path(). // - const string* ext (ctk.ext); + optional<string> ext (ctk.ext); - if (ext == nullptr) + if (!ext) { if (auto f = ctk.type->extension) - ext = f (ctk, *cpk.scope, true); // Already from the pool. + ext = f (ctk, *cpk.scope, true); - if (ext == nullptr) + if (!ext) { // What should we do here, fail or say we didn't find anything? // Current think is that if the target type couldn't find the default diff --git a/build2/target b/build2/target index 48c5ebc..421c20a 100644 --- a/build2/target +++ b/build2/target @@ -144,10 +144,10 @@ namespace build2 // when src == out). We also treat out of project targets as being in the // out tree. // - const dir_path dir; // Absolute and normalized. - const dir_path out; // Empty or absolute and normalized. - const string name; - const string* ext; // Extension. NULL - unspecified, empty - no extension. + const dir_path dir; // Absolute and normalized. + const dir_path out; // Empty or absolute and normalized. + const string name; + optional<string> ext; // Absent - unspecified, empty - no extension. const dir_path& out_dir () const {return out.empty () ? dir : out;} @@ -259,8 +259,8 @@ namespace build2 target (const target&) = delete; target& operator= (const target&) = delete; - target (dir_path d, dir_path o, string n, const string* e) - : dir (move (d)), out (move (o)), name (move (n)), ext (e) {} + target (dir_path d, dir_path o, string n, optional<string> e) + : dir (move (d)), out (move (o)), name (move (n)), ext (move (e)) {} // Reset the target before matching it to a rule. The default // implementation clears the auxilary data and prerequisite_targets. @@ -986,7 +986,7 @@ namespace build2 const dir_path& dir, const dir_path& out, const string& name, - const string* ext, + const optional<string>& ext, tracer& trace) const { return find (target_key {&type, &dir, &out, &name, ext}, trace); @@ -1000,7 +1000,7 @@ namespace build2 find (const dir_path& dir, const dir_path& out, const string& name) const { auto i (map_.find ( - target_key {&T::static_type, &dir, &out, &name, nullptr})); + target_key {&T::static_type, &dir, &out, &name, nullopt})); return i != map_.end () ? static_cast<T*> (i->second.get ()) : nullptr; } @@ -1012,7 +1012,7 @@ namespace build2 dir_path dir, dir_path out, string name, - const string* ext, + optional<string> ext, tracer&); template <typename T> @@ -1021,11 +1021,11 @@ namespace build2 dir_path dir, dir_path out, string name, - const string* ext, + optional<string> ext, tracer& t) { return static_cast<T&> ( - insert (tt, move (dir), move (out), move (name), ext, t).first); + insert (tt, move (dir), move (out), move (name), move (ext), t).first); } template <typename T> @@ -1033,7 +1033,7 @@ namespace build2 insert (const dir_path& dir, const dir_path& out, const string& name, - const string* ext, + const optional<string>& ext, tracer& t) { return static_cast<T&> ( @@ -1048,7 +1048,7 @@ namespace build2 tracer& t) { return static_cast<T&> ( - insert (T::static_type, dir, out, name, nullptr, t).first); + insert (T::static_type, dir, out, name, nullopt, t).first); } void @@ -1344,32 +1344,32 @@ namespace build2 dir_path d, dir_path o, string n, - const string* e) + optional<string> e) { - return new T (move (d), move (o), move (n), e); + return new T (move (d), move (o), move (n), move (e)); } // Return fixed target extension. // template <const char* ext> - const string* + optional<string> target_extension_fix (const target_key&, scope&, bool); // Get the extension from the variable or use the default if none set. If // the default is NULL, then return NULL. // template <const char* var, const char* def> - const string* + optional<string> target_extension_var (const target_key&, scope&, bool); // Always return NULL extension. // - const string* + optional<string> target_extension_null (const target_key&, scope&, bool); // Assert if called. // - const string* + optional<string> target_extension_assert (const target_key&, scope&, bool); // Target print functions. diff --git a/build2/target-key b/build2/target-key index f0ea80b..7905f8a 100644 --- a/build2/target-key +++ b/build2/target-key @@ -26,7 +26,9 @@ namespace build2 const dir_path* const dir; // Can be relative if part of prerequisite_key. const dir_path* const out; // Can be relative if part of prerequisite_key. const string* const name; - const string* const& ext; + const optional<string>& ext; + + static const optional<string> nullext; template <typename T> bool is_a () const {return type->is_a<T> ();} @@ -47,15 +49,14 @@ namespace build2 inline bool operator== (const target_key& x, const target_key& y) { - // Unspecified and specified extension are assumed equal. The extension - // strings are from the pool, so we can just compare pointers. + // Unspecified and specified extension are assumed equal. // return x.type == y.type && *x.dir == *y.dir && *x.out == *y.out && *x.name == *y.name && - (x.ext == nullptr || y.ext == nullptr || x.ext == y.ext); + (!x.ext || !y.ext || *x.ext == *y.ext); } inline bool diff --git a/build2/target-type b/build2/target-type index 3bbc73c..cddb9e2 100644 --- a/build2/target-type +++ b/build2/target-type @@ -41,8 +41,8 @@ namespace build2 const char* name; const target_type* base; target* (*factory) ( - const target_type&, dir_path, dir_path, string, const string*); - const string* (*extension) (const target_key&, scope&, bool search); + const target_type&, dir_path, dir_path, string, optional<string>); + optional<string> (*extension) (const target_key&, scope&, bool search); void (*print) (ostream&, const target_key&); target* (*search) (const prerequisite_key&); bool see_through; // A group with the default "see through" semantics. diff --git a/build2/target.cxx b/build2/target.cxx index d083f22..40967c3 100644 --- a/build2/target.cxx +++ b/build2/target.cxx @@ -15,6 +15,10 @@ using namespace std; namespace build2 { + // target_key + // + const optional<string> target_key::nullext = nullopt; + // target_type // bool target_type:: @@ -207,13 +211,13 @@ namespace build2 // Update the extension if the existing target has it unspecified. // - const string* ext (k.ext); + const optional<string>& ext (k.ext); if (t.ext != ext) { l5 ([&]{ diag_record r (trace); r << "assuming target " << t << " is the same as the one with "; - if (ext == nullptr) + if (!ext) r << "unspecified extension"; else if (ext->empty ()) r << "no extension"; @@ -221,7 +225,7 @@ namespace build2 r << "extension " << *ext; }); - if (ext != nullptr) + if (ext) t.ext = ext; } } @@ -234,7 +238,7 @@ namespace build2 dir_path dir, dir_path out, string name, - const string* ext, + optional<string> ext, tracer& trace) { iterator i (find (target_key {&tt, &dir, &out, &name, ext}, trace)); @@ -243,7 +247,7 @@ namespace build2 if (r) { unique_ptr<target> pt ( - tt.factory (tt, move (dir), move (out), move (name), ext)); + tt.factory (tt, move (dir), move (out), move (name), move (ext))); i = map_.emplace ( make_pair (target_key {&tt, &pt->dir, &pt->out, &pt->name, pt->ext}, move (pt))).first; @@ -285,13 +289,13 @@ namespace build2 // it if there is one. For 2 we print 'foo.?' if it hasn't yet been // assigned and 'foo.' if it is assigned as "no extension" (empty). // - if (ev > 0 && (ev > 1 || (k.ext != nullptr && !k.ext->empty ()))) + if (ev > 0 && (ev > 1 || (k.ext && !k.ext->empty ()))) { - os << '.' << (k.ext != nullptr ? *k.ext : "?"); + os << '.' << (k.ext ? *k.ext : "?"); } } else - assert (k.ext == nullptr); + assert (!k.ext); } else os << *k.dir; @@ -338,7 +342,7 @@ namespace build2 // assert (de == nullptr || type ().extension != nullptr); - if (ext == nullptr) + if (!ext) { // If the target type has the extension function then try that first. // The reason for preferring it over what's been provided by the caller @@ -346,12 +350,12 @@ namespace build2 // the user can use to override extensions. // if (auto f = type ().extension) - ext = f (key (), base_scope (), search); // Already from the pool. + ext = f (key (), base_scope (), search); - if (ext == nullptr) + if (!ext) { if (de != nullptr) - ext = &extension_pool.find (de); + ext = de; else fail << "no default extension for target " << *this; } @@ -452,13 +456,13 @@ namespace build2 return t; } - const string* + optional<string> target_extension_null (const target_key&, scope&, bool) { - return nullptr; + return nullopt; } - const string* + optional<string> target_extension_assert (const target_key&, scope&, bool) { assert (false); // Attempt to obtain the default extension. @@ -521,7 +525,7 @@ namespace build2 dir_path d, dir_path o, string n, - const string* e) + optional<string> e) { // A generic file target type doesn't imply any extension while a very // specific one (say man1) may have a fixed extension. So if one wasn't @@ -533,9 +537,9 @@ namespace build2 move (d), move (o), move (n), - (e != nullptr || ext == nullptr || tt.factory != &file_factory<T, ext> - ? e - : &extension_pool.find (ext))); + (e || ext == nullptr || tt.factory != &file_factory<T, ext> + ? move (e) + : string (ext))); } extern const char file_ext_var[] = "extension"; // VC14 rejects constexpr. @@ -585,7 +589,7 @@ namespace build2 false }; - static const string* + static optional<string> exe_extension (const target_key&, scope&, bool search) { // If we are searching for an executable that is not a target, then @@ -593,14 +597,14 @@ namespace build2 // a target, then we expect the rule to use target machine extension. // return search - ? &extension_pool.find ( + ? optional<string> ( #ifdef _WIN32 "exe" #else "" #endif ) - : nullptr; + : nullopt; } const target_type exe::static_type @@ -619,21 +623,21 @@ namespace build2 dir_path d, dir_path o, string n, - const string* e) + optional<string> e) { - if (e == nullptr) - e = &extension_pool.find (n == "buildfile" ? "" : "build"); + if (!e) + e = (n == "buildfile" ? string () : "build"); - return new buildfile (move (d), move (o), move (n), e); + return new buildfile (move (d), move (o), move (n), move (e)); } - static const string* + static optional<string> buildfile_target_extension (const target_key& tk, scope&, bool) { // If the name is special 'buildfile', then there is no extension, // otherwise it is .build. // - return &extension_pool.find (*tk.name == "buildfile" ? "" : "build"); + return *tk.name == "buildfile" ? string () : "build"; } const target_type buildfile::static_type @@ -663,12 +667,12 @@ namespace build2 dir_path d, dir_path o, string n, - const string* e) + optional<string> e) { - if (e == nullptr) + if (!e) fail << "man target '" << n << "' must include extension (man section)"; - return new man (move (d), move (o), move (n), e); + return new man (move (d), move (o), move (n), move (e)); } const target_type man::static_type diff --git a/build2/target.txx b/build2/target.txx index bc63c75..66acfb8 100644 --- a/build2/target.txx +++ b/build2/target.txx @@ -3,7 +3,6 @@ // license : MIT; see accompanying LICENSE file #include <build2/scope> -#include <build2/context> // extension_pool #include <build2/diagnostics> #include <build2/prerequisite> @@ -34,14 +33,14 @@ namespace build2 // // template <const char* ext> - const string* + optional<string> target_extension_fix (const target_key&, scope&, bool) { - return &extension_pool.find (ext); + return string (ext); } template <const char* var, const char* def> - const string* + optional<string> target_extension_var (const target_key& tk, scope& s, bool) { // Include target type/pattern-specific variables. @@ -51,10 +50,9 @@ namespace build2 // Help the user here and strip leading '.' from the extension. // const string& e (cast<string> (l)); - return &extension_pool.find ( - !e.empty () && e.front () == '.' ? string (e, 1) : e); + return !e.empty () && e.front () == '.' ? string (e, 1) : e; } - return def != nullptr ? &extension_pool.find (def) : nullptr; + return def != nullptr ? optional<string> (def) : nullopt; } } diff --git a/build2/test/target.cxx b/build2/test/target.cxx index af3c89b..44f65aa 100644 --- a/build2/test/target.cxx +++ b/build2/test/target.cxx @@ -16,21 +16,21 @@ namespace build2 dir_path d, dir_path o, string n, - const string* e) + optional<string> e) { - if (e == nullptr) - e = &extension_pool.find (n == "testscript" ? "" : "test"); + if (!e) + e = (n == "testscript" ? string () : "test"); - return new testscript (move (d), move (o), move (n), e); + return new testscript (move (d), move (o), move (n), move (e)); } - static const string* + static optional<string> testscript_target_extension (const target_key& tk, scope&, bool) { // If the name is special 'testscript', then there is no extension, // otherwise it is .test. // - return &extension_pool.find (*tk.name == "testscript" ? "" : "test"); + return *tk.name == "testscript" ? string () : "test"; } const target_type testscript::static_type diff --git a/build2/utility b/build2/utility index 464c1fe..b162a9d 100644 --- a/build2/utility +++ b/build2/utility @@ -437,17 +437,6 @@ namespace build2 unsigned int to_version (const string&); - // Pools (@@ perhaps move into a separate header). - // - struct string_pool: std::unordered_set<std::string> - { - const std::string& - find (const char* s) {return *emplace (s).first;} - - const std::string& - find (const std::string& s) {return *emplace (s).first;} - }; - // Initialize build2 global state (verbosity, home/work directories, etc). // Should be called early in main() once. // diff --git a/unit-tests/test/script/parser/driver.cxx b/unit-tests/test/script/parser/driver.cxx index e167505..271fd2c 100644 --- a/unit-tests/test/script/parser/driver.cxx +++ b/unit-tests/test/script/parser/driver.cxx @@ -9,7 +9,7 @@ #include <build2/utility> #include <build2/target> -#include <build2/context> +#include <build2/context> // reset() #include <build2/scheduler> #include <build2/test/target> @@ -186,16 +186,15 @@ namespace build2 targets.insert<file> (work, dir_path (), "driver", - &extension_pool.find (""), + string (), trace)); testscript& st ( - targets.insert<testscript> ( - work, - dir_path (), - name.leaf ().base ().string (), - &extension_pool.find (name.leaf ().extension ()), - trace)); + targets.insert<testscript> (work, + dir_path (), + name.leaf ().base ().string (), + name.leaf ().extension (), + trace)); tt.path (path ("driver")); st.path (name); |