From 9f71deeeb0f8e6fe2c29f209fc96f466fc2831b6 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 16 Mar 2020 08:06:15 +0200 Subject: Rework config::{omitted,required,optional}() into unified config_lookup() --- libbuild2/config/utility.hxx | 227 ++++++++++++++++++++++++++++--------------- 1 file changed, 148 insertions(+), 79 deletions(-) (limited to 'libbuild2/config/utility.hxx') diff --git a/libbuild2/config/utility.hxx b/libbuild2/config/utility.hxx index 493d296..bf4728f 100644 --- a/libbuild2/config/utility.hxx +++ b/libbuild2/config/utility.hxx @@ -77,116 +77,184 @@ namespace build2 config_save_module (rs, module, prio); } - // Set, if necessary, a required config.* variable. + // Lookup a config.* variable value and, if the value is defined, mark it + // as saved. + // + // The second version in addition sets the new_value argument to true if + // the value is "new" (but not to false; so it can be used to accumulate + // the result from multiple calls). A value is considered new if it was + // set to the default value (inherited or not, including overrides). We + // also treat command line overrides (inherited or not) as new. In this + // case new means either the default value was inherited or it was + // overridden. This flag is usually used to test that the new value is + // valid, print the configuration report, etc. + // + // Unlike the rest of the lookup_config() versions, this one leaves the + // unspecified value as undefined rather than setting it to a default + // value. This can be useful when we don't have a default value or if we + // want the mentioning of the variable to be omitted from persistent + // storage (e.g., a config file) if the default value is used. + // + // @@ Should we pass flags and interpret save_null_omitted to treat null + // as undefined? Sounds logical. + // + lookup + lookup_config (scope& rs, const variable&); + + lookup + lookup_config (bool& new_value, scope& rs, const variable&); + + // Note that the variable is expected to have already been entered. + // + inline lookup + lookup_config (scope& rs, const string& var) + { + return lookup_config (rs, rs.ctx.var_pool[var]); + } + + inline lookup + lookup_config (bool& new_value, scope& rs, const string& var) + { + return lookup_config (new_value, rs, rs.ctx.var_pool[var]); + } + + // Lookup a config.* variable value and, if the value is undefined, set it + // to the default. Always mark it as saved. + // + // If the default value is nullptr, then the unspecified value is set to + // NULL which can be used to distinguish between the "not yet configured", + // "configured as unspecified", and "configures as empty" cases which can + // have different semantics if the value is merged into a non-config.* + // variable. This default value is traditionally used for "optional" + // values such as command line options. + // + // The value is returned as lookup (even though it is always defined + // though potentially as NULL) in order to pass along its location (could + // be used to detect inheritance, etc). + // + // The second version in addition sets the new_value argument as described + // above. Note, however, that if the save_default_commented flag is + // specified, then the default value is never considered "new" since for + // such variables absence of a value means it is the default value. // // If override is true and the variable doesn't come from this root scope // or from the command line (i.e., it is inherited from the amalgamation), // then its value is "overridden" to the default value on this root scope. - // See save_variable() for more information on save_flags. - // - // Return the reference to the value as well as the indication of whether - // the value is "new", that is, it was set to the default value (inherited - // or not, including overrides). We also treat command line overrides - // (inherited or not) as new. This flag is usually used to test that the - // new value is valid, print report, etc. We return the value as lookup - // (always defined) to pass along its location (could be used to detect - // inheritance, etc). - // - // Note also that if save_flags has save_default_commented, then a default - // value is never considered "new" since for such variables absence of a - // value means the default value. // // @@ Should save_null_omitted be interpreted to treat null as undefined? // Sounds logical. // template - pair - required (scope& rs, - const variable&, - T&& default_value, - bool override = false, - uint64_t save_flags = 0); + lookup + lookup_config (scope& rs, + const variable&, + T&& default_value, + uint64_t save_flags = 0, + bool override = false); - // Note that the variable is expected to have already been entered. - // template - inline pair - required (scope& rs, - const string& var, - T&& default_value, - bool override = false, - uint64_t save_flags = 0) + lookup + lookup_config (bool& new_value, + scope& rs, + const variable&, + T&& default_value, + uint64_t save_flags = 0, + bool override = false); + + inline lookup + lookup_config (scope& rs, + const variable& var, + const char* default_value, + uint64_t save_flags = 0, + bool override = false) { - return required (rs, - rs.ctx.var_pool[var], - std::forward (default_value), // VC14 - override, - save_flags); + return lookup_config ( + rs, var, string (default_value), save_flags, override); } - inline pair - required (scope& rs, - const string& var, - const char* default_value, - bool override = false, - uint64_t save_flags = 0) + inline lookup + lookup_config (bool& new_value, + scope& rs, + const variable& var, + const char* default_value, + uint64_t save_flags = 0, + bool override = false) { - return required (rs, var, string (default_value), override, save_flags); + return lookup_config ( + new_value, rs, var, string (default_value), save_flags, override); } - // As above, but leave the unspecified value as undefined rather than - // setting it to the default value. - // - // This can be useful when we don't have a default value but may figure - // out some fallback. See config.bin.target for an example. - // - LIBBUILD2_SYMEXPORT pair - omitted (scope& rs, const variable&); - // Note that the variable is expected to have already been entered. // - inline pair - omitted (scope& rs, const string& var) + template + inline lookup + lookup_config (scope& rs, + const string& var, + T&& default_value, + uint64_t save_flags = 0, + bool override = false) { - return omitted (rs, rs.ctx.var_pool[var]); + return lookup_config (rs, + rs.ctx.var_pool[var], + std::forward (default_value), // VC14 + save_flags, + override); } - // Set, if necessary, an optional config.* variable. In particular, an - // unspecified variable is set to NULL which is used to distinguish - // between the "configured as unspecified" and "not yet configured" cases. - // - // Return the value (as always defined lookup), which can be NULL. - // - // @@ Rename since clashes with the optional class template. - // - // @@ Does it make sense to return the new indicator here as well, - // for consistency/generality. - // - LIBBUILD2_SYMEXPORT lookup - optional (scope& rs, const variable&); + template + inline lookup + lookup_config (bool& new_value, + scope& rs, + const string& var, + T&& default_value, + uint64_t save_flags = 0, + bool override = false) + { + return lookup_config (new_value, + rs, + rs.ctx.var_pool[var], + std::forward (default_value), // VC14 + save_flags, + override); + } + + inline lookup + lookup_config (scope& rs, + const string& var, + const char* default_value, + uint64_t save_flags = 0, + bool override = false) + { + return lookup_config ( + rs, var, string (default_value), save_flags, override); + } - // Note that the variable is expected to have already been registered. - // inline lookup - optional (scope& rs, const string& var) + lookup_config (bool& new_value, + scope& rs, + const string& var, + const char* default_value, + uint64_t save_flags = 0, + bool override = false) { - return optional (rs, rs.ctx.var_pool[var]); + return lookup_config ( + new_value, rs, var, string (default_value), save_flags, override); } - // Check whether there are any variables specified from the config + // Check whether there are any variables specified from the config. // namespace. The idea is that we can check if there are any, say, - // config.install.* values. If there are none, then we can assume - // this functionality is not (yet) used and omit writing a whole - // bunch of NULL config.install.* values to the config.build file. - // We call it omitted/delayed configuration. + // config.install.* values. If there are none, then we can assume this + // functionality is not (yet) used and omit writing a whole bunch of NULL + // config.install.* values to the config.build file. We call this + // omitted/delayed configuration. // - // Note that this function detects and ignores the special - // config.*.configured variable which may be used by a module to - // "remember" that it is unconfigured (e.g., in order to avoid re- - // running the tests, etc). + // Note that this function detects and ignores special config.* variables + // (such as config.*.configured) which may be used by a module to remember + // that it is unconfigured (e.g., in order to avoid re-running the tests, + // etc; see below). // LIBBUILD2_SYMEXPORT bool - specified (scope& rs, const string& var); + specified_config (scope& rs, const string& var); // Check if there is a false config.*.configured value. This mechanism can // be used to "remember" that the module is left unconfigured in order to @@ -204,6 +272,7 @@ namespace build2 } } +#include #include #endif // LIBBUILD2_CONFIG_UTILITY_HXX -- cgit v1.1