425 lines
12 KiB
C++
425 lines
12 KiB
C++
// Filename: dconfig.h
|
|
// Created by: cary (14Jul98)
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
#ifndef DCONFIG_H
|
|
#define DCONFIG_H
|
|
|
|
#include <dtoolbase.h>
|
|
|
|
#include "config_setup.h"
|
|
#include "config_dconfig.h"
|
|
#include "configTable.h"
|
|
#include "executionEnvironment.h"
|
|
|
|
#include <vector>
|
|
#include <map>
|
|
#include <time.h>
|
|
|
|
namespace Config {
|
|
|
|
// Config is, itself, configurable. The things that can be set are:
|
|
// path separator ( ': ' ) [pathsep]
|
|
// filename separator ( / ) [filesep]
|
|
// config filename ( Configrc ) [configname]
|
|
// config file suffix ( ) [configsuffix]
|
|
// config file path ( $CONFIG_PATH ) [configpath]
|
|
// (can be multiple of these)
|
|
// config file comment ( '#' ) [configcmt]
|
|
// 'args' suffix ( _ARGS ) [argsuffix]
|
|
// command arg env ( CONFIG + _____ ) [commandstub]
|
|
// debugging output ( false ) [configdbg]
|
|
// read commandline ( true ) [readargs]
|
|
// read environment ( true ) [readenv]
|
|
// all of these can be set from the one unconfigurable thing in config, the
|
|
// environment variable called CONFIG_CONFIG. The format is:
|
|
// separator_char{{field_id}={field_value}separator_char}*
|
|
|
|
// Call these functions to get stats on how Config is spending its
|
|
// time.
|
|
EXPCL_DTOOL INLINE double get_total_time_config_init();
|
|
EXPCL_DTOOL INLINE double get_total_time_external_init();
|
|
EXPCL_DTOOL INLINE double get_total_num_get();
|
|
|
|
// These globals are intended for internal bookkeeping by Config to
|
|
// compute the above functions' return values.
|
|
EXPCL_DTOOL extern clock_t total_time_config_init;
|
|
EXPCL_DTOOL extern clock_t total_time_external_init;
|
|
EXPCL_DTOOL extern int total_num_get;
|
|
|
|
template <class GetConfig>
|
|
class Config {
|
|
protected:
|
|
static void ConfigFunc(void);
|
|
static void Flag(bool);
|
|
public:
|
|
Config(void);
|
|
~Config(void);
|
|
static bool AmInitializing(void);
|
|
static ConfigString Name(void);
|
|
static bool Flag(void);
|
|
static void Init(void);
|
|
static bool Defined(const ConfigString& sym);
|
|
static ConfigString Get(const ConfigString sym);
|
|
static ConfigTable::Symbol& GetAll(const ConfigString,
|
|
ConfigTable::Symbol&);
|
|
static bool GetBool(const ConfigString sym, bool def = false);
|
|
static int GetInt(const ConfigString sym, int def = 0);
|
|
static float GetFloat(const ConfigString sym, float def = 0.);
|
|
static double GetDouble(const ConfigString sym, double def = 0.);
|
|
static ConfigString GetString(const ConfigString sym,
|
|
const ConfigString def = "");
|
|
};
|
|
|
|
// Implementation follows
|
|
|
|
template<class GetConfig>
|
|
void Config<GetConfig>::ConfigFunc(void)
|
|
{
|
|
GetConfig::config_func();
|
|
}
|
|
|
|
template<class GetConfig>
|
|
bool Config<GetConfig>::AmInitializing(void)
|
|
{
|
|
ConfigTable* tab = ConfigTable::Instance();
|
|
if (tab == (ConfigTable *)0L)
|
|
return Flag();
|
|
return tab->AmInitializing();
|
|
}
|
|
|
|
template<class GetConfig>
|
|
ConfigString Config<GetConfig>::Name(void)
|
|
{
|
|
return GetConfig::get_name();
|
|
}
|
|
|
|
template<class GetConfig>
|
|
bool Config<GetConfig>::Flag(void)
|
|
{
|
|
return GetConfig::_flag;
|
|
}
|
|
|
|
template<class GetConfig>
|
|
void Config<GetConfig>::Flag(bool f)
|
|
{
|
|
GetConfig::_flag = f;
|
|
}
|
|
|
|
template<class GetConfig>
|
|
void Config<GetConfig>::Init(void)
|
|
{
|
|
if (Flag())
|
|
return;
|
|
total_time_config_init -= clock();
|
|
Flag(true);
|
|
ConfigTable::Instance();
|
|
|
|
if (Defined("notify-level-config")) {
|
|
ConfigString s = Get("notify-level-config");
|
|
NotifySeverity sev = Notify::string_severity(s);
|
|
if (sev != NS_unspecified) {
|
|
microconfig_cat->set_severity(sev);
|
|
dconfig_cat->set_severity(sev);
|
|
} else {
|
|
microconfig_cat->set_severity(NS_info);
|
|
dconfig_cat->set_severity(NS_info);
|
|
}
|
|
} else {
|
|
microconfig_cat->set_severity(NS_info);
|
|
dconfig_cat->set_severity(NS_info);
|
|
}
|
|
|
|
total_time_config_init += clock();
|
|
total_time_external_init -= clock();
|
|
|
|
if (dconfig_cat->is_spam())
|
|
dconfig_cat->spam() << "calling ConfigFunc for '" << Name() << "'"
|
|
<< endl;
|
|
ConfigFunc();
|
|
if (dconfig_cat->is_spam())
|
|
dconfig_cat->spam() << "back from ConfigFunc for '" << Name() << "'"
|
|
<< endl;
|
|
total_time_external_init += clock();
|
|
}
|
|
|
|
template<class GetConfig>
|
|
Config<GetConfig>::Config(void)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
template<class GetConfig>
|
|
Config<GetConfig>::~Config(void)
|
|
{
|
|
}
|
|
|
|
template<class GetConfig>
|
|
bool Config<GetConfig>::Defined(const ConfigString& sym)
|
|
{
|
|
Init();
|
|
ConfigTable* tab = ConfigTable::Instance();
|
|
if (tab->Defined(sym, Name()))
|
|
return true;
|
|
else if (tab->Defined(sym, ExecutionEnvironment::get_binary_name()))
|
|
return true;
|
|
else if (tab->Defined(sym))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
template<class GetConfig>
|
|
ConfigString Config<GetConfig>::Get(ConfigString sym)
|
|
{
|
|
Init();
|
|
ConfigTable* tab = ConfigTable::Instance();
|
|
if (tab->Defined(sym, Name()))
|
|
return (tab->Get(sym, Name())).Val();
|
|
else if (tab->Defined(sym, ExecutionEnvironment::get_binary_name()))
|
|
return (tab->Get(sym, ExecutionEnvironment::get_binary_name())).Val();
|
|
else if (tab->Defined(sym))
|
|
return (tab->Get(sym)).Val();
|
|
else
|
|
return "";
|
|
}
|
|
|
|
template<class GetConfig>
|
|
ConfigTable::Symbol& Config<GetConfig>::GetAll(const ConfigString sym,
|
|
ConfigTable::Symbol& s)
|
|
{
|
|
Init();
|
|
ConfigTable* tab = ConfigTable::Instance();
|
|
if (tab->Defined(sym, Name())) {
|
|
const ConfigTable::Symbol& tsym = tab->GetSym(sym, Name());
|
|
s.insert(s.end(), tsym.begin(), tsym.end());
|
|
}
|
|
if (tab->Defined(sym, ExecutionEnvironment::get_binary_name())) {
|
|
const ConfigTable::Symbol& tsym = tab->GetSym(sym, ExecutionEnvironment::get_binary_name());
|
|
s.insert(s.end(), tsym.begin(), tsym.end());
|
|
}
|
|
if (tab->Defined(sym)) {
|
|
const ConfigTable::Symbol& tsym = tab->GetSym(sym);
|
|
s.insert(s.end(), tsym.begin(), tsym.end());
|
|
}
|
|
return s;
|
|
}
|
|
|
|
template<class GetConfig>
|
|
bool Config<GetConfig>::GetBool(const ConfigString sym, bool def)
|
|
{
|
|
Init();
|
|
if (Defined(sym)) {
|
|
ConfigString s = Get(sym);
|
|
bool ret = ConfigTable::TrueOrFalse(s, def);
|
|
if (dconfig_cat->is_spam())
|
|
dconfig_cat->spam() << "symbol '" << sym << "' defined, returning: "
|
|
<< (ret?"true":"false") << endl;
|
|
return ret;
|
|
} else {
|
|
if (dconfig_cat->is_spam())
|
|
dconfig_cat->spam()
|
|
<< "symbol '" << sym
|
|
<< "' is not defined, returning provided default: "
|
|
<< (def?"true":"false") << endl;
|
|
return def;
|
|
}
|
|
}
|
|
|
|
template<class GetConfig>
|
|
int Config<GetConfig>::GetInt(const ConfigString sym, int def)
|
|
{
|
|
Init();
|
|
if (Defined(sym)) {
|
|
ConfigString v = Get(sym);
|
|
istringstream s(v);
|
|
int i;
|
|
s >> i;
|
|
if (dconfig_cat->is_spam())
|
|
dconfig_cat->spam() << "symbol '" << sym << "' defined, returning: "
|
|
<< i << endl;
|
|
return i;
|
|
} else {
|
|
if (dconfig_cat->is_spam())
|
|
dconfig_cat->spam()
|
|
<< "symbol '" << sym
|
|
<< "' is not defined, returning provided default: " << def << endl;
|
|
return def;
|
|
}
|
|
}
|
|
|
|
template<class GetConfig>
|
|
float Config<GetConfig>::GetFloat(const ConfigString sym, float def)
|
|
{
|
|
Init();
|
|
if (Defined(sym)) {
|
|
ConfigString v = Get(sym);
|
|
istringstream s(v);
|
|
float f;
|
|
s >> f;
|
|
if (dconfig_cat->is_spam())
|
|
dconfig_cat->spam() << "symbol '" << sym << "' defined, returning: "
|
|
<< f << endl;
|
|
return f;
|
|
} else {
|
|
if (dconfig_cat->is_spam())
|
|
dconfig_cat->spam()
|
|
<< "symbol '" << sym
|
|
<< "' is not defined, returning provided default: " << def << endl;
|
|
return def;
|
|
}
|
|
}
|
|
|
|
template<class GetConfig>
|
|
double Config<GetConfig>::GetDouble(const ConfigString sym, double def)
|
|
{
|
|
Init();
|
|
if (Defined(sym)) {
|
|
ConfigString v = Get(sym);
|
|
istringstream s(v);
|
|
double d;
|
|
s >> d;
|
|
if (dconfig_cat->is_spam())
|
|
dconfig_cat->spam() << "symbol '" << sym << "' defined, returning: "
|
|
<< d << endl;
|
|
return d;
|
|
} else {
|
|
if (dconfig_cat->is_spam())
|
|
dconfig_cat->spam()
|
|
<< "symbol '" << sym
|
|
<< "' is not defined, returning provided default: " << def << endl;
|
|
return def;
|
|
}
|
|
}
|
|
|
|
template<class GetConfig>
|
|
ConfigString Config<GetConfig>::GetString(const ConfigString sym,
|
|
const ConfigString def)
|
|
{
|
|
Init();
|
|
if (Defined(sym)) {
|
|
ConfigString ret = Get(sym);
|
|
if (dconfig_cat->is_spam())
|
|
dconfig_cat->spam() << "symbol '" << sym << "' defined, returning: '"
|
|
<< ret << "'" << endl;
|
|
return ret;
|
|
} else {
|
|
if (dconfig_cat->is_spam())
|
|
dconfig_cat->spam()
|
|
<< "symbol '" << sym
|
|
<< "' is not defined, returning provided default: '" << def
|
|
<< "'" << endl;
|
|
return def;
|
|
}
|
|
}
|
|
|
|
#include "dconfig.I"
|
|
|
|
} // close Config namespace
|
|
|
|
|
|
// Finally, here is a set of handy macros to define and reference a
|
|
// Configure object in each package.
|
|
|
|
// This macro defines an external reference to a suitable Configure
|
|
// object; it should appear in the config_*.h file. The config object
|
|
// will be named name.
|
|
|
|
#if defined(WIN32_VC) && !defined(CPPPARSER)
|
|
|
|
#define ConfigureDecl(name, expcl, exptp) \
|
|
class expcl ConfigureGetConfig_ ## name { \
|
|
public: \
|
|
static const char *get_name(); \
|
|
static void config_func(); \
|
|
static bool _flag; \
|
|
}; \
|
|
exptp template class expcl Config::Config<ConfigureGetConfig_ ## name>; \
|
|
extern expcl Config::Config<ConfigureGetConfig_ ## name> name;
|
|
|
|
#else // WIN32_VC
|
|
|
|
#define ConfigureDecl(name, expcl, exptp) \
|
|
class expcl ConfigureGetConfig_ ## name { \
|
|
public: \
|
|
static const char *get_name(); \
|
|
static void config_func(); \
|
|
static bool _flag; \
|
|
}; \
|
|
extern expcl Config::Config<ConfigureGetConfig_ ## name> name;
|
|
|
|
#endif // WIN32_VC
|
|
|
|
// This macro defines the actual declaration of the Configure object
|
|
// defined above; it should appear in the config_*.C file.
|
|
|
|
#if defined(PENV_OSX)
|
|
#define ConfigureDef(name) \
|
|
Config::Config<ConfigureGetConfig_ ## name> name; \
|
|
bool ConfigureGetConfig_ ## name::_flag = false; \
|
|
int FILE_SYM_NAME = 0; \
|
|
const char *ConfigureGetConfig_ ## name:: \
|
|
get_name() { \
|
|
return #name; \
|
|
}
|
|
#else /* PENV_OSX */
|
|
#define ConfigureDef(name) \
|
|
Config::Config<ConfigureGetConfig_ ## name> name; \
|
|
bool ConfigureGetConfig_ ## name::_flag = false; \
|
|
const char *ConfigureGetConfig_ ## name:: \
|
|
get_name() { \
|
|
return #name; \
|
|
}
|
|
#endif /* PENV_OSX */
|
|
|
|
// This macro can be used in lieu of the above two when the Configure
|
|
// object does not need to be visible outside of the current C file.
|
|
|
|
#if defined(PENV_OSX)
|
|
#define Configure(name) \
|
|
class ConfigureGetConfig_ ## name { \
|
|
public: \
|
|
static const char *get_name(); \
|
|
static void config_func(); \
|
|
static bool _flag; \
|
|
}; \
|
|
static Config::Config<ConfigureGetConfig_ ## name> name; \
|
|
bool ConfigureGetConfig_ ## name::_flag = false; \
|
|
int FILE_SYM_NAME = 0; \
|
|
const char *ConfigureGetConfig_ ## name:: \
|
|
get_name() { \
|
|
return #name; \
|
|
}
|
|
#else /* PENV_OSX */
|
|
#define Configure(name) \
|
|
class ConfigureGetConfig_ ## name { \
|
|
public: \
|
|
static const char *get_name(); \
|
|
static void config_func(); \
|
|
static bool _flag; \
|
|
}; \
|
|
static Config::Config<ConfigureGetConfig_ ## name> name; \
|
|
bool ConfigureGetConfig_ ## name::_flag = false; \
|
|
const char *ConfigureGetConfig_ ## name:: \
|
|
get_name() { \
|
|
return #name; \
|
|
}
|
|
#endif /* PENV_OSX */
|
|
|
|
// This one defines a block of code that will be executed at static
|
|
// init time. It must always be defined (in the C file), even if no
|
|
// code is to be executed.
|
|
|
|
#define ConfigureFn(name) \
|
|
void ConfigureGetConfig_ ## name::config_func()
|
|
|
|
#if defined(PENV_OSX)
|
|
// This is a hack to provide a unique locatable symbol in each lib.
|
|
#define ConfigureLibSym \
|
|
char LIB_SYMBOL_NAME[] = ALL_FILE_SYMS_NAME ;
|
|
#else
|
|
#define ConfigureLibSym
|
|
#endif /* PENV_OSX */
|
|
|
|
#endif /* __CONFIG_H__ */
|