diff options
Diffstat (limited to 'libbuild2/variable.hxx')
-rw-r--r-- | libbuild2/variable.hxx | 198 |
1 files changed, 131 insertions, 67 deletions
diff --git a/libbuild2/variable.hxx b/libbuild2/variable.hxx index 9f1eee6..bfe3b87 100644 --- a/libbuild2/variable.hxx +++ b/libbuild2/variable.hxx @@ -148,9 +148,9 @@ namespace build2 // A variable. // // A variable can be public, project-private, or script-private, which - // corresponds to the variable pool it belongs to. The two variables from - // the same pool are considered the same if they have the same name. The - // variable access (public/private) rules are: + // corresponds to the variable pool it belongs to (see variable_pool). The + // two variables from the same pool are considered the same if they have the + // same name. The variable access (public/private) rules are: // // - Qualified variable are by default public while unqualified -- private. // @@ -1248,7 +1248,9 @@ namespace build2 // The shared versions (as in, context or project-wide) are protected by the // phase mutex and thus can only be modified during the load phase. // - class variable_pool + class variable_patterns; + + class LIBBUILD2_SYMEXPORT variable_pool { public: // Find existing (assert exists). @@ -1352,9 +1354,10 @@ namespace build2 // Overridable aliased variables are most likely a bad idea: without a // significant effort, the overrides will only be applied along the alias // names (i.e., there would be no cross-alias overriding). So for now we - // don't allow this (use the common variable mechanism instead). + // don't allow this (manually handle multiple names by merging their + // values instead). // - LIBBUILD2_SYMEXPORT const variable& + const variable& insert_alias (const variable& var, string name); // Iteration. @@ -1368,61 +1371,39 @@ namespace build2 const_iterator begin () const {return const_iterator (map_.begin ());} const_iterator end () const {return const_iterator (map_.end ());} - // Variable patterns. + // Construction. // - public: - // Insert a variable pattern. Any variable that matches this pattern will - // have the specified type, visibility, and overridability. If match is - // true, then individual insertions of the matching variable must match - // the specified type/visibility/overridability. Otherwise, individual - // insertions can provide alternative values and the pattern values are a - // fallback (if you specify false you better be very clear about what you - // are trying to achieve). - // - // The pattern must be in the form [<prefix>.](*|**)[.<suffix>] where '*' - // matches single component stems (i.e., 'foo' but not 'foo.bar') and '**' - // matches single and multi-component stems. Note that only multi- - // component variables are considered for pattern matching (so just '*' - // won't match anything). + // There are three specific variable pool instances: // - // The patterns are matched in the more-specific-first order where the - // pattern is considered more specific if it has a greater sum of its - // prefix and suffix lengths. If the prefix and suffix are equal, then the - // '*' pattern is considered more specific than '**'. If neither is more - // specific, then they are matched in the reverse order of insertion. + // shared outer + // ---------------- + // true null -- public variable pool in context + // true not null -- project-private pool in scope::root_extra + // with outer pointing to context::var_pool + // false null -- script-private pool in script::environment // - // If retro is true then a newly inserted pattern is also applied - // retrospectively to all the existing variables that match but only - // if no more specific pattern already exists (which is then assumed - // to have been applied). So if you use this functionality, watch out - // for the insertion order (you probably want more specific first). + // Notice that the script-private pool doesn't rely on outer and does + // its own pool chaining. So currently we assume that if outer is not + // NULL, then this is a project-private pool. // - LIBBUILD2_SYMEXPORT void - insert_pattern (const string& pattern, - optional<const value_type*> type, - optional<bool> overridable, - optional<variable_visibility>, - bool retro = false, - bool match = true); + private: + friend class context; + friend void setup_root_extra (scope&, optional<bool>&); - template <typename T> - void - insert_pattern (const string& p, - optional<bool> overridable, - optional<variable_visibility> v, - bool retro = false, - bool match = true) - { - insert_pattern ( - p, &value_traits<T>::value_type, overridable, v, retro, match); - } + // Shared pool (public or project-private). The shared argument is + // flag/context. + // + variable_pool (context* shared, + variable_pool* outer, + const variable_patterns* patterns) + : shared_ (shared), outer_ (outer), patterns_ (patterns) {} public: - // Create a private pool. + // Script-private pool. // explicit - variable_pool (variable_pool* outer = nullptr) - : variable_pool (nullptr /* shared */, outer) {} + variable_pool (const variable_patterns* patterns = nullptr) + : shared_ (nullptr), outer_ (nullptr), patterns_ (patterns) {} variable_pool (variable_pool&&) = delete; variable_pool& operator= (variable_pool&&) = delete; @@ -1430,6 +1411,7 @@ namespace build2 variable_pool (const variable_pool&) = delete; variable_pool& operator= (const variable_pool&) = delete; + public: // RW access (only for shared pools). // variable_pool& @@ -1451,14 +1433,14 @@ namespace build2 // Note that in insert() NULL overridable is interpreted as false unless // overridden by a pattern while in update() NULL overridable is ignored. // - LIBBUILD2_SYMEXPORT pair<variable&, bool> + pair<variable&, bool> insert (string name, const value_type*, const variable_visibility*, const bool* overridable, bool pattern = true); - LIBBUILD2_SYMEXPORT void + void update (variable&, const value_type*, const variable_visibility*, @@ -1484,10 +1466,100 @@ namespace build2 return r; } + private: + friend class variable_patterns; + + context* shared_; + variable_pool* outer_; + const variable_patterns* patterns_; map map_; + }; - // Patterns. + // Variable patterns. + // + // This mechanism is used to assign variable types/visibility/overridability + // based on the variable name pattern. This mechanism can only be used for + // qualified variables and is thus only provided for the public variable + // pool. + // + // Similar to variable_pool, the shared versions are protected by the phase + // mutex and thus can only be modified during the load phase. + // + class LIBBUILD2_SYMEXPORT variable_patterns + { + public: + // Insert a variable pattern. Any variable that matches this pattern will + // have the specified type, visibility, and overridability. If match is + // true, then individual insertions of the matching variable must match + // the specified type/visibility/overridability. Otherwise, individual + // insertions can provide alternative values and the pattern values are a + // fallback (if you specify false you better be very clear about what you + // are trying to achieve). + // + // The pattern must be in the form [<prefix>.](*|**)[.<suffix>] where '*' + // matches single component stems (i.e., 'foo' but not 'foo.bar') and '**' + // matches single and multi-component stems. Note that only multi- + // component variables are considered for pattern matching (so just '*' + // won't match anything). + // + // The patterns are matched in the more-specific-first order where the + // pattern is considered more specific if it has a greater sum of its + // prefix and suffix lengths. If the prefix and suffix are equal, then the + // '*' pattern is considered more specific than '**'. If neither is more + // specific, then they are matched in the reverse order of insertion. + // + // If retro is true then a newly inserted pattern is also applied + // retrospectively to all the existing variables that match but only + // if no more specific pattern already exists (which is then assumed + // to have been applied). So if you use this functionality, watch out + // for the insertion order (you probably want more specific first). + // + void + insert (const string& pattern, + optional<const value_type*> type, + optional<bool> overridable, + optional<variable_visibility>, + bool retro = false, + bool match = true); + + template <typename T> + void + insert (const string& p, + optional<bool> overridable, + optional<variable_visibility> v, + bool retro = false, + bool match = true) + { + insert (p, &value_traits<T>::value_type, overridable, v, retro, match); + } + + public: + // The shared argument is flag/context. The pool argument is for + // retrospective pattern application. // + explicit + variable_patterns (context* shared, variable_pool* pool) + : shared_ (shared), pool_ (pool) {} + + variable_patterns (variable_patterns&&) = delete; + variable_patterns& operator= (variable_patterns&&) = delete; + + variable_patterns (const variable_patterns&) = delete; + variable_patterns& operator= (const variable_patterns&) = delete; + + public: + // RW access (only for shared pools). + // + variable_patterns& + rw () const + { + assert (shared_->phase == run_phase::load); + return const_cast<variable_patterns&> (*this); + } + + variable_patterns& + rw (scope&) const {return const_cast<variable_patterns&> (*this);} + public: struct pattern { @@ -1515,19 +1587,11 @@ namespace build2 }; private: - multiset<pattern> patterns_; - - // Shared pool flag/context. - // - private: - friend class context; - friend void setup_root_extra (scope&, optional<bool>&); + friend class variable_pool; - variable_pool (context* shared, variable_pool* outer) - : shared_ (shared), outer_ (outer) {} - - context* shared_; - variable_pool* outer_; + context* shared_; + variable_pool* pool_; + multiset<pattern> patterns_; }; } |