| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373 |
- /**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University. All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license. You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file configVariableManager.cxx
- * @author drose
- * @date 2004-10-15
- */
- #include "configVariableManager.h"
- #include "configVariableCore.h"
- #include "configDeclaration.h"
- #include "configPage.h"
- #include "config_prc.h"
- using std::string;
- ConfigVariableManager *ConfigVariableManager::_global_ptr = nullptr;
- /**
- * The constructor is private (actually, just protected, but only to avoid a
- * gcc compiler warning) because it should not be explicitly constructed.
- * There is only one ConfigVariableManager, and it constructs itself.
- */
- ConfigVariableManager::
- ConfigVariableManager() {
- init_memory_hook();
- }
- /**
- * The ConfigVariableManager destructor should never be called, because this
- * is a global object that is never freed.
- */
- ConfigVariableManager::
- ~ConfigVariableManager() {
- prc_cat->error()
- << "Internal error--ConfigVariableManager destructor called!\n";
- }
- /**
- * Creates and returns a new, undefined ConfigVariableCore with the indicated
- * name; or if a variable with this name has already been created, returns
- * that one instead.
- */
- ConfigVariableCore *ConfigVariableManager::
- make_variable(const string &name) {
- VariablesByName::iterator ni;
- ni = _variables_by_name.find(name);
- if (ni != _variables_by_name.end()) {
- return (*ni).second;
- }
- ConfigVariableCore *variable = nullptr;
- // See if there's a template that matches this name.
- VariableTemplates::const_iterator ti;
- for (ti = _variable_templates.begin();
- ti != _variable_templates.end() && variable == nullptr;
- ++ti) {
- const GlobPattern &pattern = (*ti).first;
- ConfigVariableCore *templ = (*ti).second;
- if (pattern.matches(name)) {
- variable = new ConfigVariableCore(*templ, name);
- }
- }
- if (variable == nullptr) {
- variable = new ConfigVariableCore(name);
- }
- _variables_by_name[name] = variable;
- _variables.push_back(variable);
- return variable;
- }
- /**
- * Defines a variable "template" to match against dynamically-defined
- * variables that may or may not be created in the future.
- *
- * The template consists of a glob pattern, e.g. `notify-level-*`, which will
- * be tested against any config variable passed to a future call to
- * make_variable(). If the pattern matches, the returned ConfigVariableCore
- * is copied to define the new variable, instead of creating a default, empty
- * one.
- *
- * This is useful to pre-specify default values for a family of variables that
- * all have similar properties, and all may not be created at the same time.
- * It is especially useful to avoid cluttering up the list of available
- * variables with user-declared variables that have not been defined yet by
- * the application (e.g. `egg-object-type-*`).
- *
- * This method basically pre-defines all variables that match the specified
- * glob pattern.
- */
- ConfigVariableCore *ConfigVariableManager::
- make_variable_template(const string &pattern,
- ConfigFlags::ValueType value_type,
- const string &default_value,
- const string &description, int flags) {
- ConfigVariableCore *core;
- GlobPattern gp(pattern);
- VariableTemplates::const_iterator ti = _variable_templates.find(gp);
- if (ti != _variable_templates.end()) {
- core = (*ti).second;
- } else {
- core = new ConfigVariableCore(pattern);
- _variable_templates[gp] = core;
- }
- if (value_type != ConfigFlags::VT_undefined) {
- core->set_value_type(value_type);
- }
- if (!default_value.empty() ||
- core->get_default_value() == nullptr) {
- core->set_default_value(default_value);
- }
- if (!description.empty()) {
- core->set_description(description);
- }
- if (flags != 0) {
- core->set_flags(flags);
- }
- core->set_used();
- // Also apply the same changes to any previously-defined variables that
- // match the pattern.
- Variables::iterator vi;
- for (vi = _variables.begin(); vi != _variables.end(); ++vi) {
- ConfigVariableCore *variable = (*vi);
- if (gp.matches(variable->get_name())) {
- if (value_type != ConfigFlags::VT_undefined) {
- variable->set_value_type(value_type);
- }
- if (!default_value.empty() ||
- variable->get_default_value() == nullptr) {
- variable->set_default_value(default_value);
- }
- if (!description.empty()) {
- variable->set_description(description);
- }
- if (flags != 0) {
- variable->set_flags(flags);
- }
- variable->set_used();
- }
- }
- return core;
- }
- /**
- * Returns the name of the nth active ConfigVariable in the list.
- */
- string ConfigVariableManager::
- get_variable_name(size_t n) const {
- if (n < _variables.size()) {
- return _variables[n]->get_name();
- }
- return string();
- }
- /**
- * Returns true if the nth active ConfigVariable in the list has been used by
- * code, false otherwise.
- */
- bool ConfigVariableManager::
- is_variable_used(size_t n) const {
- if (n < _variables.size()) {
- return _variables[n]->is_used();
- }
- return false;
- }
- /**
- *
- */
- void ConfigVariableManager::
- output(std::ostream &out) const {
- out << "ConfigVariableManager, " << _variables.size() << " variables.";
- }
- /**
- *
- */
- void ConfigVariableManager::
- write(std::ostream &out) const {
- VariablesByName::const_iterator ni;
- for (ni = _variables_by_name.begin();
- ni != _variables_by_name.end();
- ++ni) {
- ConfigVariableCore *variable = (*ni).second;
- if (variable->get_num_trusted_references() != 0 ||
- variable->has_local_value()) {
- list_variable(variable, false);
- }
- }
- }
- /**
- * Writes all of the prc-set config variables, as they appear in a prc file
- * somewhere, one per line, very concisely. This lists the dominant value in
- * the prc file; it does not list shadowed values, and it does not list
- * locally-set values.
- *
- * This is mainly intended for generating a hash of the input config file
- * state.
- */
- void ConfigVariableManager::
- write_prc_variables(std::ostream &out) const {
- VariablesByName::const_iterator ni;
- for (ni = _variables_by_name.begin();
- ni != _variables_by_name.end();
- ++ni) {
- ConfigVariableCore *variable = (*ni).second;
- if (variable->get_num_trusted_references() != 0) {
- if (variable->get_value_type() == ConfigVariableCore::VT_list ||
- variable->get_value_type() == ConfigVariableCore::VT_search_path) {
- // List all of the values for a "list" variable.
- size_t num_references = variable->get_num_trusted_references();
- for (size_t i = 0; i < num_references; ++i) {
- out << variable->get_name() << " "
- << variable->get_trusted_reference(i)->get_string_value()
- << "\n";
- }
- } else {
- // List just the one value for a non-list variable.
- out << variable->get_name() << " "
- << variable->get_trusted_reference(0)->get_string_value()
- << "\n";
- }
- }
- }
- }
- /**
- * Writes a list of all the variables that have been defined in a prc file
- * without having been declared somewhere in code.
- */
- void ConfigVariableManager::
- list_unused_variables() const {
- VariablesByName::const_iterator ni;
- for (ni = _variables_by_name.begin();
- ni != _variables_by_name.end();
- ++ni) {
- ConfigVariableCore *variable = (*ni).second;
- if (!variable->is_used()) {
- nout << variable->get_name() << "\n";
- size_t num_references = variable->get_num_references();
- for (size_t i = 0; i < num_references; i++) {
- nout << " " << variable->get_reference(i)->get_page()->get_name()
- << "\n";
- }
- }
- }
- }
- /**
- * Writes a list of all the variables that have been declared somewhere in
- * code, along with a brief description.
- */
- void ConfigVariableManager::
- list_variables() const {
- VariablesByName::const_iterator ni;
- for (ni = _variables_by_name.begin();
- ni != _variables_by_name.end();
- ++ni) {
- const ConfigVariableCore *variable = (*ni).second;
- if (variable->is_used() && !variable->is_dynamic()) {
- list_variable(variable, true);
- }
- }
- }
- /**
- * Writes a list of all the "dynamic" variables that have been declared
- * somewhere in code, along with a brief description. This is a (usually
- * large) list of config variables that are declared with a generated variable
- * name.
- */
- void ConfigVariableManager::
- list_dynamic_variables() const {
- VariablesByName::const_iterator ni;
- for (ni = _variables_by_name.begin();
- ni != _variables_by_name.end();
- ++ni) {
- const ConfigVariableCore *variable = (*ni).second;
- if (variable->is_used() && variable->is_dynamic()) {
- list_variable(variable, false);
- }
- }
- }
- /**
- *
- */
- ConfigVariableManager *ConfigVariableManager::
- get_global_ptr() {
- if (_global_ptr == nullptr) {
- _global_ptr = new ConfigVariableManager;
- }
- return _global_ptr;
- }
- /**
- * Lists a single variable and its value.
- */
- void ConfigVariableManager::
- list_variable(const ConfigVariableCore *variable,
- bool include_descriptions) const {
- if (!variable->is_used()) {
- // If the variable is unused, just show its name.
- nout << variable->get_name() << " not used";
- if (variable->get_num_references() > 0) {
- nout << " (referenced in "
- << variable->get_reference(0)->get_page()->get_name()
- << ")";
- }
- nout << "\n";
- } else {
- // If the variable is used--it's been defined somewhere--show its name,
- // its type, its current and default values, and if available, its
- // description.
- nout << variable->get_name() << " "
- << variable->get_value_type() << "\n";
- const ConfigDeclaration *decl;
- if (variable->get_value_type() == ConfigVariableCore::VT_list ||
- variable->get_value_type() == ConfigVariableCore::VT_search_path) {
- // We treat a "list" variable as a special case: list all of its values.
- nout << " current value:\n";
- size_t num_references = variable->get_num_trusted_references();
- for (size_t i = 0; i < num_references; ++i) {
- decl = variable->get_trusted_reference(i);
- nout << " " << decl->get_string_value()
- << " (from " << decl->get_page()->get_name() << ")\n";
- }
- } else {
- // An ordinary, non-list variable gets one line for its current value
- // (if it has one) and another line for its default value.
- decl = variable->get_declaration(0);
- if (decl != variable->get_default_value()) {
- nout << " current value = " << decl->get_string_value();
- if (!decl->get_page()->is_special()) {
- nout << " (from " << decl->get_page()->get_name() << ")\n";
- } else {
- nout << " (defined locally)\n";
- }
- }
- decl = variable->get_default_value();
- if (decl != nullptr) {
- nout << " default value = " << decl->get_string_value() << "\n";
- }
- }
- if (!variable->get_description().empty() && include_descriptions) {
- nout << " " << variable->get_description() << "\n";
- }
- }
- nout << "\n";
- }
|