diff options
Diffstat (limited to 'libbuild2/in')
-rw-r--r-- | libbuild2/in/init.cxx | 5 | ||||
-rw-r--r-- | libbuild2/in/rule.cxx | 45 | ||||
-rw-r--r-- | libbuild2/in/rule.hxx | 13 |
3 files changed, 49 insertions, 14 deletions
diff --git a/libbuild2/in/init.cxx b/libbuild2/in/init.cxx index 6cd2f96..18071f8 100644 --- a/libbuild2/in/init.cxx +++ b/libbuild2/in/init.cxx @@ -59,6 +59,11 @@ namespace build2 // unknown substitutions as is. // vp.insert<string> ("in.substitution"); + + // Fallback value to use for NULL value substitutions. If unspecified, + // NULL substitutions are an error. + // + vp.insert<string> ("in.null"); } // Register target types. diff --git a/libbuild2/in/rule.cxx b/libbuild2/in/rule.cxx index 16747ab..b64541c 100644 --- a/libbuild2/in/rule.cxx +++ b/libbuild2/in/rule.cxx @@ -116,6 +116,14 @@ namespace build2 fail << "invalid substitution mode '" << *s << "'"; } + // NULL substitutions. + // + optional<string> null; + if (const string* s = cast_null<string> (t["in.null"])) + null = *s; + else + null = null_; + // Determine if anything needs to be updated. // timestamp mt (t.load_mtime ()); @@ -220,7 +228,7 @@ namespace build2 // can be overriden with custom substitution semantics. // optional<string> v ( - substitute (location (ip, ln), a, t, n, strict)); + substitute (location (ip, ln), a, t, n, strict, null)); assert (v); // Rule semantics change without version increment? @@ -360,7 +368,8 @@ namespace build2 // pointing to the opening symbol and e -- to the closing. // string name (s, b + 1, e - b -1); - if (optional<string> val = substitute (l, a, t, name, strict)) + if (optional<string> val = + substitute (l, a, t, name, strict, null)) { // Save in depdb. // @@ -429,11 +438,26 @@ namespace build2 } string rule:: - lookup (const location& l, action, const target& t, const string& n) const + lookup (const location& loc, + action, + const target& t, + const string& n, + const optional<string>& null) const { - if (auto x = t[n]) + auto l (t[n]); + + if (l.defined ()) { - value v (*x); + value v (*l); + + if (v.null) + { + if (null) + return *null; + else + fail (loc) << "null value in variable '" << n << "'" << + info << "use in.null to specify null value substiution string"; + } // For typed values call string() for conversion. // @@ -445,16 +469,16 @@ namespace build2 : t.ctx.functions.call (&t.base_scope (), "string", vector_view<value> (&v, 1), - l)); + loc)); } catch (const invalid_argument& e) { - fail (l) << e << + fail (loc) << e << info << "while substituting '" << n << "'" << endf; } } else - fail (l) << "undefined variable '" << n << "'" << endf; + fail (loc) << "undefined variable '" << n << "'" << endf; } optional<string> rule:: @@ -462,7 +486,8 @@ namespace build2 action a, const target& t, const string& n, - bool strict) const + bool strict, + const optional<string>& null) const { // In the lax mode scan the fragment to make sure it is a variable name // (that is, it can be expanded in a buildfile as just $<name>; see @@ -486,7 +511,7 @@ namespace build2 } } - return lookup (l, a, t, n); + return lookup (l, a, t, n, null); } } } diff --git a/libbuild2/in/rule.hxx b/libbuild2/in/rule.hxx index cf67060..2fa1305 100644 --- a/libbuild2/in/rule.hxx +++ b/libbuild2/in/rule.hxx @@ -33,11 +33,13 @@ namespace build2 rule (string rule_id, string program, char symbol = '$', - bool strict = true) + bool strict = true, + optional<string> null = nullopt) : rule_id_ (move (rule_id)), program_ (move (program)), symbol_ (symbol), - strict_ (strict) {} + strict_ (strict), + null_ (move (null)) {} virtual bool match (action, target&, const string&) const override; @@ -65,7 +67,8 @@ namespace build2 lookup (const location&, action, const target&, - const string& name) const; + const string& name, + const optional<string>& null) const; // Perform variable substitution. Return nullopt if it should be // ignored. @@ -75,13 +78,15 @@ namespace build2 action, const target&, const string& name, - bool strict) const; + bool strict, + const optional<string>& null) const; protected: const string rule_id_; const string program_; char symbol_; bool strict_; + optional<string> null_; }; } } |