aboutsummaryrefslogtreecommitdiff
path: root/libbuild2
diff options
context:
space:
mode:
Diffstat (limited to 'libbuild2')
-rw-r--r--libbuild2/context.cxx24
-rw-r--r--libbuild2/context.hxx3
-rw-r--r--libbuild2/file.cxx2
-rw-r--r--libbuild2/forward.hxx1
-rw-r--r--libbuild2/variable.cxx34
-rw-r--r--libbuild2/variable.hxx198
6 files changed, 168 insertions, 94 deletions
diff --git a/libbuild2/context.cxx b/libbuild2/context.cxx
index e44d79f..4cbdecb 100644
--- a/libbuild2/context.cxx
+++ b/libbuild2/context.cxx
@@ -45,6 +45,7 @@ namespace build2
scope_map scopes;
target_set targets;
variable_pool var_pool;
+ variable_patterns var_patterns;
variable_overrides var_overrides;
function_map functions;
@@ -55,7 +56,8 @@ namespace build2
data (context& c)
: scopes (c),
targets (c),
- var_pool (&c /* shared */, nullptr /* outer */) {}
+ var_pool (&c /* shared */, nullptr /* outer */, &var_patterns),
+ var_patterns (&c /* shared */, &var_pool) {}
};
context::
@@ -81,6 +83,7 @@ namespace build2
scopes (data_->scopes),
targets (data_->targets),
var_pool (data_->var_pool),
+ var_patterns (data_->var_patterns),
var_overrides (data_->var_overrides),
functions (data_->functions),
global_scope (create_global_scope (data_->scopes)),
@@ -99,6 +102,7 @@ namespace build2
scope_map& sm (data_->scopes);
variable_pool& vp (data_->var_pool);
+ variable_patterns& vpats (data_->var_patterns);
insert_builtin_functions (functions);
@@ -330,7 +334,7 @@ namespace build2
// Note that some config.config.* variables have project visibility thus
// the match argument is false.
//
- vp.insert_pattern ("config.**", nullopt, true, v_g, true, false);
+ vpats.insert ("config.**", nullopt, true, v_g, true, false);
// Parse and enter the command line variables. We do it before entering
// any other variables so that all the variables that are overriden are
@@ -548,24 +552,26 @@ namespace build2
const auto v_t (variable_visibility::target);
const auto v_q (variable_visibility::prereq);
- vp.insert_pattern<bool> ("config.**.configured", false, v_p);
+ vpats.insert<bool> ("config.**.configured", false, v_p);
- // file.cxx:import() (note: order is important; see insert_pattern()).
+ // file.cxx:import()
+ //
+ // Note: the order is important (see variable_patterns::insert()).
//
// Note that if any are overriden, they are "pre-typed" by the config.**
// pattern above and we just "add" the types.
//
- vp.insert_pattern<abs_dir_path> ("config.import.*", true, v_g, true);
- vp.insert_pattern<path> ("config.import.**", true, v_g, true);
+ vpats.insert<abs_dir_path> ("config.import.*", true, v_g, true);
+ vpats.insert<path> ("config.import.**", true, v_g, true);
// module.cxx:boot/init_module().
//
// Note that we also have the config.<module>.configured variable (see
// above).
//
- vp.insert_pattern<bool> ("**.booted", false /* overridable */, v_p);
- vp.insert_pattern<bool> ("**.loaded", false, v_p);
- vp.insert_pattern<bool> ("**.configured", false, v_p);
+ vpats.insert<bool> ("**.booted", false /* overridable */, v_p);
+ vpats.insert<bool> ("**.loaded", false, v_p);
+ vpats.insert<bool> ("**.configured", false, v_p);
var_src_root = &vp.insert<dir_path> ("src_root");
var_out_root = &vp.insert<dir_path> ("out_root");
diff --git a/libbuild2/context.hxx b/libbuild2/context.hxx
index 0747350..9cb4fb4 100644
--- a/libbuild2/context.hxx
+++ b/libbuild2/context.hxx
@@ -380,7 +380,8 @@ namespace build2
//
const scope_map& scopes;
target_set& targets;
- const variable_pool& var_pool; // Public variables.
+ const variable_pool& var_pool; // Public variables pool.
+ const variable_patterns& var_patterns; // Public variables patterns.
const variable_overrides& var_overrides; // Project and relative scope.
function_map& functions;
diff --git a/libbuild2/file.cxx b/libbuild2/file.cxx
index a2fe906..a3962d7 100644
--- a/libbuild2/file.cxx
+++ b/libbuild2/file.cxx
@@ -611,7 +611,7 @@ namespace build2
a ? alt_export_file : std_export_file,
a ? alt_src_root_file : std_src_root_file,
a ? alt_out_root_file : std_out_root_file,
- {&ctx, &ctx.var_pool.rw (root)}, /* var_pool */
+ {&ctx, &ctx.var_pool.rw (root), nullptr}, /* var_pool */
{}, /* meta_operations */
{}, /* operations */
{}, /* modules */
diff --git a/libbuild2/forward.hxx b/libbuild2/forward.hxx
index d2b8989..057ab24 100644
--- a/libbuild2/forward.hxx
+++ b/libbuild2/forward.hxx
@@ -26,6 +26,7 @@ namespace build2
struct variable;
class variable_pool;
+ class variable_patterns;
class variable_map;
struct variable_override;
using variable_overrides = vector<variable_override>;
diff --git a/libbuild2/variable.cxx b/libbuild2/variable.cxx
index 5c32d89..54bdcf6 100644
--- a/libbuild2/variable.cxx
+++ b/libbuild2/variable.cxx
@@ -1659,7 +1659,7 @@ namespace build2
}
static inline void
- merge_pattern (const variable_pool::pattern& p,
+ merge_pattern (const variable_patterns::pattern& p,
const build2::value_type*& t,
const variable_visibility*& v,
const bool*& o)
@@ -1714,16 +1714,18 @@ namespace build2
// Apply pattern.
//
+ using pattern = variable_patterns::pattern;
+
const pattern* pa (nullptr);
auto pt (t); auto pv (v); auto po (o);
- if (pat)
+ if (pat && patterns_ != nullptr)
{
if (n.find ('.') != string::npos)
{
// Reverse means from the "largest" (most specific).
//
- for (const pattern& p: reverse_iterate (patterns_))
+ for (const pattern& p: reverse_iterate (patterns_->patterns_))
{
if (match_pattern (n, p.prefix, p.suffix, p.multi))
{
@@ -1800,13 +1802,13 @@ namespace build2
return a;
}
- void variable_pool::
- insert_pattern (const string& p,
- optional<const value_type*> t,
- optional<bool> o,
- optional<variable_visibility> v,
- bool retro,
- bool match)
+ void variable_patterns::
+ insert (const string& p,
+ optional<const value_type*> t,
+ optional<bool> o,
+ optional<variable_visibility> v,
+ bool retro,
+ bool match)
{
assert (!shared_ || shared_->phase == run_phase::load);
@@ -1842,9 +1844,9 @@ namespace build2
// Apply retrospectively to existing variables.
//
- if (retro)
+ if (retro && pool_ != nullptr)
{
- for (auto& p: map_)
+ for (auto& p: pool_->map_)
{
variable& var (p.second);
@@ -1861,10 +1863,10 @@ namespace build2
}
if (j == e)
- update (var,
- t ? *t : nullptr,
- v ? &*v : nullptr,
- o ? &*o : nullptr); // Not changing the key.
+ pool_->update (var,
+ t ? *t : nullptr,
+ v ? &*v : nullptr,
+ o ? &*o : nullptr); // Not changing the key.
}
}
}
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_;
};
}