From e222cbabb84b5a6357242e47196f7e0eeb69a44f Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 20 May 2020 15:00:09 +0200 Subject: Implement build script variable hashing --- libbuild2/build/script/parser.cxx | 40 ++++++++++++++++++++++++++++++++++++--- libbuild2/build/script/script.hxx | 14 +++++++++++++- 2 files changed, 50 insertions(+), 4 deletions(-) (limited to 'libbuild2/build') diff --git a/libbuild2/build/script/parser.cxx b/libbuild2/build/script/parser.cxx index 6649777..86019ba 100644 --- a/libbuild2/build/script/parser.cxx +++ b/libbuild2/build/script/parser.cxx @@ -16,6 +16,12 @@ namespace build2 { using type = token_type; + static inline bool + special_variable (const string& name) + { + return name == ">" || name == "<"; + } + // // Pre-parse. // @@ -96,9 +102,9 @@ namespace build2 case line_type::var: { // Check if we are trying to modify any of the special variables - // ($>). + // ($>, $<). // - if (t.value == ">") + if (special_variable (t.value)) fail (t) << "attempt to set '" << t.value << "' variable"; // We don't pre-enter variables. @@ -327,13 +333,41 @@ namespace build2 lookup parser:: lookup_variable (name&& qual, string&& name, const location& loc) { + // In the pre-parse mode collect the referenced variable names for the + // script semantics change tracking. + // if (pre_parse_) + { + // Add the variable name skipping special variables and suppressing + // duplicates. + // + if (!name.empty () && !special_variable (name)) + { + auto& vars (script_->vars); + + if (find (vars.begin (), vars.end (), name) == vars.end ()) + vars.push_back (move (name)); + } + return lookup (); + } if (!qual.empty ()) fail (loc) << "qualified variable name"; - return environment_->lookup (name); + lookup r (environment_->lookup (name)); + + // Fail if non-script-local variable with an untracked name. + // + if (r.defined () && !r.belongs (*environment_)) + { + const auto& vars (script_->vars); + + if (find (vars.begin (), vars.end (), name) == vars.end ()) + fail (loc) << "use of untracked variable '" << name << "'"; + } + + return r; } } } diff --git a/libbuild2/build/script/script.hxx b/libbuild2/build/script/script.hxx index 1540ed8..29d62aa 100644 --- a/libbuild2/build/script/script.hxx +++ b/libbuild2/build/script/script.hxx @@ -40,7 +40,19 @@ namespace build2 // Note that the variables are not pre-entered into a pool during the // parsing phase, so the line variable pointers are NULL. // - build2::script::lines lines; + build2::script::lines lines; + + // Referenced ordinary (non-special) variables. + // + // Used for the script semantics change tracking. The variable list is + // filled during the pre-parsing phase and is checked against during + // the execution phase. If during execution some non-script-local + // variable is not found in the list (may happen for a computed name), + // then the execution fails since the script semantics may not be + // properly tracked (the variable value change will not trigger the + // target rebuild). + // + small_vector vars; location start_loc; location end_loc; -- cgit v1.1