From 7996c2bfc2d7e998e2f9f1236d457ec7bea8ad8a Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 1 Dec 2015 13:39:09 +0200 Subject: Implement support for definition target type aliases For example: define cli=file Currently, the semantics is that of a real alias with only name differences that are used for display. See tests/define/buildfile for more use cases. --- build/parser.cxx | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) (limited to 'build/parser.cxx') diff --git a/build/parser.cxx b/build/parser.cxx index bc6caa9..4981347 100644 --- a/build/parser.cxx +++ b/build/parser.cxx @@ -12,6 +12,9 @@ #include // make_move_iterator() #include +#include +#include + #include #include @@ -130,6 +133,11 @@ namespace build using_ (t, tt); continue; } + else if (n == "define") + { + define (t, tt); + continue; + } } // ': foo' is equvalent to '{}: foo' and to 'dir{}: foo'. @@ -343,7 +351,7 @@ namespace build const target_type* ti ( n.untyped () ? &target::static_type - : scope_->find_target_type (n.type.c_str ())); + : scope_->find_target_type (n.type)); if (ti == nullptr) fail (nloc) << "unknown target type " << n.type; @@ -799,6 +807,72 @@ namespace build fail (t) << "expected newline instead of " << t; } + static target* + alias_factory (const target_type& tt, dir_path d, string n, const string* e) + { + assert (tt.origin != nullptr); + target* r (tt.origin->factory (*tt.origin, move (d), move (n), e)); + r->alias_type = &tt; + return r; + } + + void parser:: + define (token& t, token_type& tt) + { + // define = + // + // See tests/define/buildfile. + // + if (next (t, tt) != type::name) + fail (t) << "expected name instead of " << t << " in target type " + << "definition"; + + string a (move (t.value)); + const location al (get_location (t, &path_)); + + if (next (t, tt) != type::equal) + fail (t) << "expected '=' instead of " << t << " in target type " + << "definition"; + + next (t, tt); + + if (tt == type::name) + { + // Alias. + // + const string& n (t.value); + const target_type* ntt (scope_->find_target_type (n)); + + if (ntt == nullptr) + fail (t) << "unknown target type " << n; + + unique_ptr att (new target_type (*ntt)); + att->factory = &alias_factory; + att->origin = ntt->origin != nullptr ? ntt->origin : ntt; + + target_type& ratt (*att); // Save non-const reference to the object. + + auto pr (scope_->target_types.emplace (a, target_type_ref (move (att)))); + + if (!pr.second) + fail (al) << "target type " << a << " already define in this scope"; + + // Patch the alias name to use the map's key storage. + // + ratt.name = pr.first->first.c_str (); + + next (t, tt); // Get newline. + } + else + fail (t) << "expected name instead of " << t << " in target type " + << "definition"; + + if (tt == type::newline) + next (t, tt); + else if (tt != type::eos) + fail (t) << "expected newline instead of " << t; + } + void parser:: print (token& t, token_type& tt) { -- cgit v1.1