From d1f436049f0fba43ed1d5e5d8e490b7873009403 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 6 Apr 2022 14:39:34 +0200 Subject: Add support for specifying custom ad hoc pattern rule names Besides diagnostics, this allows us to use name in the rule hint, for example: [rule_name=hello.link] exe{~'/(.*)/'}: obje{~'/\1/'} {{ $cxx.path -o $path($>) $path($<[0]) }} [rule_hint=hello] exe{hello}: obje{hello} obje{hello}: c{hello-c} --- libbuild2/parser.cxx | 60 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 7 deletions(-) (limited to 'libbuild2/parser.cxx') diff --git a/libbuild2/parser.cxx b/libbuild2/parser.cxx index f91e85e..c97e19e 100644 --- a/libbuild2/parser.cxx +++ b/libbuild2/parser.cxx @@ -868,9 +868,6 @@ namespace build2 // if (ns[0].pattern && ns.size () == (ns[0].pair ? 2 : 1)) { - if (!as.empty ()) - fail (as.loc) << "attributes before target type/pattern"; - name& n (ns[0]); if (n.qualified ()) @@ -936,6 +933,10 @@ namespace build2 nloc); next_after_newline (t, tt); + + if (!as.empty ()) + fail (as.loc) << "attributes before target type/pattern"; + continue; // Just a target type/pattern-specific var assignment. } @@ -987,12 +988,47 @@ namespace build2 if (!ans.empty ()) fail (ans[0].loc) << "ad hoc member in target type/pattern"; + if (!as.empty ()) + fail (as.loc) << "attributes before target type/pattern"; + continue; } } // Ok, this is an ad hoc pattern rule. // + // First process the attributes. + // + string rn; + { + const location& l (as.loc); + + for (auto& a: as) + { + const string& n (a.name); + value& v (a.value); + + // rule_name= + // + if (n == "rule_name") + { + try + { + rn = convert (move (v)); + + if (rn.empty ()) + throw invalid_argument ("empty name"); + } + catch (const invalid_argument& e) + { + fail (l) << "invalid " << n << " attribute value: " << e; + } + } + else + fail (l) << "unknown ad hoc pattern rule attribute " << a; + } + } + // What should we do if we have neither prerequisites nor recipes? // While such a declaration doesn't make much sense, it can happen, // for example, with an empty variable expansion: @@ -1089,14 +1125,18 @@ namespace build2 } } - // Derive the rule name. It must be unique in this scope. + // Derive the rule name unless specified explicitly. It must be + // unique in this scope. // // It would have been nice to include the location but unless we // include the absolute path to the buildfile (which would be // unwieldy), it could be ambigous. // - string rn ("adhoc_rules.size () + 1) + '>'); + // NOTE: we rely on the <...> format in dump. + // + if (rn.empty ()) + rn = "adhoc_rules.size () + 1) + '>'; auto& ars (scope_->adhoc_rules); @@ -1109,7 +1149,9 @@ namespace build2 const target_type* ttype (nullptr); if (i != ars.end ()) { - // @@ TODO: append ad hoc members, prereqs. + // @@ TODO: append ad hoc members, prereqs (we now have + // [rule_name=] which we can use to reference the same + // rule). // ttype = &(*i)->type; assert (false); @@ -1711,6 +1753,10 @@ namespace build2 // location loc (get_location (st)); + // @@ We could add an attribute (name= or recipe_name=) to allow + // the user specify a friendly name for diagnostics, similar + // to rule_name. + shared_ptr ar; if (!lang) { -- cgit v1.1