diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2022-06-28 09:50:05 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2022-06-28 11:11:55 +0200 |
commit | 17af650e17fafd4d3fa2bf0e06253e15f4e5b9c3 (patch) | |
tree | 278a64a0e34d454f5fa66f43ed3cea24e84f8ce5 /libbuild2 | |
parent | 664fc2807b6e97400c6e76aaad66a51ff0c57704 (diff) |
Add support for querying out-qualified target-specific variables
Diffstat (limited to 'libbuild2')
-rw-r--r-- | libbuild2/build/script/parser.cxx | 2 | ||||
-rw-r--r-- | libbuild2/build/script/parser.hxx | 2 | ||||
-rw-r--r-- | libbuild2/parser.cxx | 81 | ||||
-rw-r--r-- | libbuild2/parser.hxx | 10 | ||||
-rw-r--r-- | libbuild2/prerequisite.hxx | 4 | ||||
-rw-r--r-- | libbuild2/test/script/parser.cxx | 2 | ||||
-rw-r--r-- | libbuild2/test/script/parser.hxx | 2 |
7 files changed, 68 insertions, 35 deletions
diff --git a/libbuild2/build/script/parser.cxx b/libbuild2/build/script/parser.cxx index 795dc72..a27ec41 100644 --- a/libbuild2/build/script/parser.cxx +++ b/libbuild2/build/script/parser.cxx @@ -2271,7 +2271,7 @@ namespace build2 } lookup parser:: - lookup_variable (name&& qual, string&& name, const location& loc) + lookup_variable (names&& qual, string&& name, const location& loc) { // In the pre-parse mode collect the referenced variable names for the // script semantics change tracking. diff --git a/libbuild2/build/script/parser.hxx b/libbuild2/build/script/parser.hxx index 362c834..1a6c39d 100644 --- a/libbuild2/build/script/parser.hxx +++ b/libbuild2/build/script/parser.hxx @@ -229,7 +229,7 @@ namespace build2 // protected: virtual lookup - lookup_variable (name&&, string&&, const location&) override; + lookup_variable (names&&, string&&, const location&) override; virtual void lookup_function (string&&, const location&) override; diff --git a/libbuild2/parser.cxx b/libbuild2/parser.cxx index 4c6cde0..8343112 100644 --- a/libbuild2/parser.cxx +++ b/libbuild2/parser.cxx @@ -5260,17 +5260,38 @@ namespace build2 if (pre_parse_) return v; // Empty. - if (v.type != nullptr || !v || v.as<names> ().size () != 1) - fail (l) << "expected target before ':'"; - + // We used to return this as a <target>:<name> pair but that meant we + // could not handle an out-qualified target (which is represented as + // <target>@<out> pair). As a somewhat of a hack, we deal with this by + // changing the order of the name and target to be <name>:<target> with + // the qualified case becoming a "tripple pair" <name>:<target>@<out>. + // + // @@ This is actually not great since it's possible to observe such a + // tripple pair, for example with `print (file{x}@./:y)`. + // if (n.type != nullptr || !n || n.as<names> ().size () != 1 || n.as<names> ()[0].pattern) fail (nl) << "expected variable name after ':'"; - names& ns (v.as<names> ()); + names& ns (n.as<names> ()); ns.back ().pair = ':'; - ns.push_back (move (n.as<names> ().back ())); - return v; + + if (v.type == nullptr && v) + { + names& ts (v.as<names> ()); + + size_t s (ts.size ()); + if (s == 1 || (s == 2 && ts.front ().pair == '@')) + { + ns.push_back (move (ts.front ())); + if (s == 2) + ns.push_back (move (ts.back ())); + + return n; + } + } + + fail (l) << "expected target before ':'" << endf; } else { @@ -7004,7 +7025,7 @@ namespace build2 next (t, tt); loc = get_location (t); - name qual; + names qual; string name; if (t.separated) @@ -7036,8 +7057,6 @@ namespace build2 { using name_type = build2::name; - //@@ OUT will parse @-pair and do well? - // values vs (parse_eval (t, tt, pmode)); if (!pre_parse_) @@ -7059,17 +7078,26 @@ namespace build2 // we would be treating all paths as qualified variables. So // we have to do it here. // - if (n == 2 && ns[0].pair == ':') // $(foo: x) + if (n >= 2 && ns[0].pair == ':') // $(foo: x) { - qual = move (ns[0]); + // Note: name is first (see eval for details). + // + qual.push_back (move (ns[1])); - if (qual.empty ()) + if (qual.back ().empty ()) fail (loc) << "empty variable/function qualification"; + + if (n > 2) + qual.push_back (move (ns[2])); + + // Move name to the last position (see below). + // + swap (ns[0], ns[n - 1]); } else if (n == 2 && ns[0].directory ()) // $(foo/ x) { - qual = move (ns[0]); - qual.pair = '/'; + qual.push_back (move (ns[0])); + qual.back ().pair = '/'; } else if (n > 1) fail (loc) << "expected variable/function name instead of '" @@ -7093,8 +7121,8 @@ namespace build2 name = string (s, p + 1); s.resize (p + 1); - qual = name_type (dir_path (move (s))); - qual.pair = '/'; + qual.push_back (name_type (dir_path (move (s)))); + qual.back ().pair = '/'; } else name = move (ns[n - 1].value); @@ -7903,7 +7931,7 @@ namespace build2 } lookup parser:: - lookup_variable (name&& qual, string&& name, const location& loc) + lookup_variable (names&& qual, string&& name, const location& loc) { if (pre_parse_) return lookup (); @@ -7927,27 +7955,26 @@ namespace build2 } else { - switch (qual.pair) + switch (qual.front ().pair) { case '/': { - assert (qual.directory ()); - sg = enter_scope (*this, move (qual.dir)); + assert (qual.front ().directory ()); + sg = enter_scope (*this, move (qual.front ().dir)); s = scope_; break; } - case ':': + default: { - qual.pair = '\0'; + build2::name n (move (qual.front ())), o; - // @@ OUT TODO - // - tg = enter_target ( - *this, move (qual), build2::name (), true, loc, trace); + if (n.pair) + o = move (qual.back ()); + + tg = enter_target (*this, move (n), move (o), true, loc, trace); t = target_; break; } - default: assert (false); } } diff --git a/libbuild2/parser.hxx b/libbuild2/parser.hxx index 9e9f926..f806568 100644 --- a/libbuild2/parser.hxx +++ b/libbuild2/parser.hxx @@ -560,8 +560,12 @@ namespace build2 // Customization hooks. // protected: - // If qual is not empty, then its pair member should indicate the kind - // of qualification: ':' -- target, '/' -- scope. + // If qual is not empty, then firt element's pair member indicates the + // kind of qualification: + // + // '\0' -- target + // '@' -- out-qualified target + // '/' -- scope // // Note that this function is called even during pre-parse with the result // unused. In this case a valid name will only be provided for variables @@ -574,7 +578,7 @@ namespace build2 // if/when extending this and audit all the existing use-cases. // virtual lookup - lookup_variable (name&& qual, string&& name, const location&); + lookup_variable (names&& qual, string&& name, const location&); // This function is only called during pre-parse and is the continuation // of the similar logic in lookup_variable() above (including the fact diff --git a/libbuild2/prerequisite.hxx b/libbuild2/prerequisite.hxx index 476ed9d..3b64eae 100644 --- a/libbuild2/prerequisite.hxx +++ b/libbuild2/prerequisite.hxx @@ -29,7 +29,9 @@ namespace build2 using target_type_type = build2::target_type; // Note that unlike targets, for prerequisites an empty out directory - // means undetermined rather than being definitely in the out tree. + // means undetermined rather than being definitely in the out tree (but + // maybe we should make this explicit via optional<>; see the from-target + // constructor). // // It might seem natural to keep the reference to the owner target instead // of to the scope. But that's not the semantics that we have, consider: diff --git a/libbuild2/test/script/parser.cxx b/libbuild2/test/script/parser.cxx index 2cc1b65..eb7b140 100644 --- a/libbuild2/test/script/parser.cxx +++ b/libbuild2/test/script/parser.cxx @@ -1661,7 +1661,7 @@ namespace build2 } lookup parser:: - lookup_variable (name&& qual, string&& name, const location& loc) + lookup_variable (names&& qual, string&& name, const location& loc) { if (pre_parse_) return lookup (); diff --git a/libbuild2/test/script/parser.hxx b/libbuild2/test/script/parser.hxx index c63bce6..66160d9 100644 --- a/libbuild2/test/script/parser.hxx +++ b/libbuild2/test/script/parser.hxx @@ -117,7 +117,7 @@ namespace build2 // protected: virtual lookup - lookup_variable (name&&, string&&, const location&) override; + lookup_variable (names&&, string&&, const location&) override; // Insert id into the id map checking for duplicates. // |