00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "configVariableCore.h"
00016 #include "configDeclaration.h"
00017 #include "configPage.h"
00018 #include "pset.h"
00019 #include "pnotify.h"
00020 #include "config_prc.h"
00021
00022
00023 #include "prc_parameters.h"
00024
00025 #include <algorithm>
00026
00027
00028
00029
00030
00031
00032
00033
00034 ConfigVariableCore::
00035 ConfigVariableCore(const string &name) :
00036 _name(name),
00037 _is_used(false),
00038 _value_type(VT_undefined),
00039 _flags(0),
00040 _default_value(NULL),
00041 _local_value(NULL),
00042 _declarations_sorted(true),
00043 _value_queried(false)
00044 {
00045 #if defined(PRC_INC_TRUST_LEVEL) && PRC_INC_TRUST_LEVEL != 0
00046 _flags = (_flags & ~F_trust_level_mask) | ((_flags & F_trust_level_mask) + PRC_INC_TRUST_LEVEL);
00047 #endif // PRC_INC_TRUST_LEVEL
00048 }
00049
00050
00051
00052
00053
00054
00055
00056
00057 ConfigVariableCore::
00058 ConfigVariableCore(const ConfigVariableCore &templ, const string &name) :
00059 _name(name),
00060 _is_used(templ._is_used),
00061 _value_type(templ._value_type),
00062 _description(templ._description),
00063 _flags(templ._flags),
00064 _default_value(NULL),
00065 _local_value(NULL),
00066 _declarations_sorted(false),
00067 _value_queried(false)
00068 {
00069 if (templ._default_value != (ConfigDeclaration *)NULL) {
00070 set_default_value(templ._default_value->get_string_value());
00071 }
00072 }
00073
00074
00075
00076
00077
00078
00079
00080
00081 ConfigVariableCore::
00082 ~ConfigVariableCore() {
00083 prc_cat->error()
00084 << "Internal error--ConfigVariableCore destructor called!\n";
00085 }
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 void ConfigVariableCore::
00096 set_value_type(ConfigVariableCore::ValueType value_type) {
00097 if (_value_queried && _value_type != value_type) {
00098 if ((_flags & F_dconfig) != 0) {
00099
00100
00101
00102
00103
00104 } else {
00105 prc_cat->warning()
00106 << "changing type for ConfigVariable "
00107 << get_name() << " from " << _value_type << " to "
00108 << value_type << ".\n";
00109 }
00110 }
00111
00112 _value_type = value_type;
00113 }
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124 void ConfigVariableCore::
00125 set_flags(int flags) {
00126 if ((flags & F_dconfig) != 0) {
00127 flags = (flags & ~F_trust_level_mask) | PRC_DCONFIG_TRUST_LEVEL;
00128 }
00129
00130 #if defined(PRC_INC_TRUST_LEVEL) && PRC_INC_TRUST_LEVEL != 0
00131 flags = (flags & ~F_trust_level_mask) | ((flags & F_trust_level_mask) + PRC_INC_TRUST_LEVEL);
00132 #endif // PRC_INC_TRUST_LEVEL
00133
00134 if (_value_queried) {
00135 int bits_changed = (_flags ^ flags);
00136 if ((bits_changed & F_trust_level_mask) != 0) {
00137 prc_cat->warning()
00138 << "changing trust level for ConfigVariable "
00139 << get_name() << " from " << (_flags & F_trust_level_mask) << " to "
00140 << (flags & F_trust_level_mask) << ".\n";
00141 }
00142 if ((bits_changed & ~(F_trust_level_mask | F_dconfig)) != 0) {
00143 prc_cat->warning()
00144 << "changing flags for ConfigVariable "
00145 << get_name() << " from " << hex
00146 << (_flags & ~F_trust_level_mask) << " to "
00147 << (flags & ~F_trust_level_mask) << dec << ".\n";
00148 }
00149 }
00150
00151 _flags = flags;
00152
00153
00154
00155 _declarations_sorted = false;
00156 }
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166 void ConfigVariableCore::
00167 set_description(const string &description) {
00168 if (_value_queried && _description != description) {
00169 if ((_flags & F_dconfig) != 0) {
00170
00171
00172
00173 return;
00174 }
00175 if (description == "DConfig") {
00176
00177
00178
00179 if (_description.empty()) {
00180 _description = description;
00181 }
00182 return;
00183 }
00184
00185 if (description.empty()) {
00186
00187 return;
00188 }
00189
00190 if (_description.empty()) {
00191
00192 _description = description;
00193 return;
00194 }
00195
00196 prc_cat->warning()
00197 << "changing description for ConfigVariable "
00198 << get_name() << ".\n";
00199 }
00200
00201 _description = description;
00202 }
00203
00204
00205
00206
00207
00208
00209
00210 void ConfigVariableCore::
00211 set_default_value(const string &default_value) {
00212 if (_default_value == (ConfigDeclaration *)NULL) {
00213
00214 ConfigPage *default_page = ConfigPage::get_default_page();
00215 _default_value = default_page->make_declaration(this, default_value);
00216
00217 } else {
00218
00219
00220
00221
00222
00223
00224 string orig_default_value = _default_value->get_string_value();
00225 _default_value->set_string_value(default_value);
00226
00227 if (orig_default_value != default_value) {
00228 if ((_flags & F_dconfig) != 0) {
00229
00230
00231
00232
00233
00234 } else {
00235 prc_cat->warning()
00236 << "changing default value for ConfigVariable "
00237 << get_name() << " from '" << orig_default_value
00238 << "' to '" << default_value << "'.\n";
00239 }
00240 }
00241 }
00242 }
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257 ConfigDeclaration *ConfigVariableCore::
00258 make_local_value() {
00259 if (_local_value == (ConfigDeclaration *)NULL) {
00260 ConfigPage *local_page = ConfigPage::get_local_page();
00261 string string_value = get_declaration(0)->get_string_value();
00262 _local_value = local_page->make_declaration(this, string_value);
00263
00264 if (is_closed()) {
00265 prc_cat.warning()
00266 << "Assigning a local value to a \"closed\" ConfigVariable. "
00267 "This is legal in a development build, but illegal in a release "
00268 "build and may result in a compilation error or exception.\n";
00269 }
00270 }
00271
00272 return _local_value;
00273 }
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285 bool ConfigVariableCore::
00286 clear_local_value() {
00287 if (_local_value != (ConfigDeclaration *)NULL) {
00288 ConfigPage::get_local_page()->delete_declaration(_local_value);
00289 _local_value = (ConfigDeclaration *)NULL;
00290 invalidate_cache();
00291 return true;
00292 }
00293
00294 return false;
00295 }
00296
00297
00298
00299
00300
00301
00302
00303
00304 bool ConfigVariableCore::
00305 has_value() const {
00306 if (has_local_value()) {
00307 return true;
00308 }
00309 check_sort_declarations();
00310 return (!_trusted_declarations.empty());
00311 }
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321 int ConfigVariableCore::
00322 get_num_declarations() const {
00323 if (has_local_value()) {
00324 return 1;
00325 }
00326 check_sort_declarations();
00327 if (!_trusted_declarations.empty()) {
00328 return _trusted_declarations.size();
00329 }
00330
00331
00332 return 1;
00333 }
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345 const ConfigDeclaration *ConfigVariableCore::
00346 get_declaration(int n) const {
00347 ((ConfigVariableCore *)this)->_value_queried = true;
00348 if (_default_value == (ConfigDeclaration *)NULL) {
00349 prc_cat->warning()
00350 << "value queried before default value set for "
00351 << get_name() << ".\n";
00352 ((ConfigVariableCore *)this)->set_default_value("");
00353 }
00354
00355 if (has_local_value()) {
00356 return _local_value;
00357 }
00358 check_sort_declarations();
00359 if (n >= 0 && n < (int)_trusted_declarations.size()) {
00360 return _trusted_declarations[n];
00361 }
00362 return _default_value;
00363 }
00364
00365
00366
00367
00368
00369
00370 void ConfigVariableCore::
00371 output(ostream &out) const {
00372 out << get_declaration(0)->get_string_value();
00373 }
00374
00375
00376
00377
00378
00379
00380 void ConfigVariableCore::
00381 write(ostream &out) const {
00382 out << "ConfigVariable " << get_name() << ":\n";
00383
00384 check_sort_declarations();
00385
00386 if (has_local_value()) {
00387 out << " " << *_local_value << " (defined locally)\n";
00388 }
00389
00390 Declarations::const_iterator di;
00391 for (di = _trusted_declarations.begin();
00392 di != _trusted_declarations.end();
00393 ++di) {
00394 out << " " << *(*di)
00395 << " (from " << (*di)->get_page()->get_name() << ")\n";
00396 }
00397
00398 if (_default_value != (ConfigDeclaration *)NULL) {
00399 out << " " << *_default_value << " (default value)\n";
00400 }
00401
00402 for (di = _untrusted_declarations.begin();
00403 di != _untrusted_declarations.end();
00404 ++di) {
00405 out << " " << *(*di)
00406 << " (from " << (*di)->get_page()->get_name() << ", untrusted)\n";
00407 }
00408
00409 if (!_description.empty()) {
00410 out << "\n" << _description << "\n";
00411 }
00412 }
00413
00414
00415
00416
00417
00418
00419
00420
00421 void ConfigVariableCore::
00422 add_declaration(ConfigDeclaration *decl) {
00423 _declarations.push_back(decl);
00424
00425 _declarations_sorted = false;
00426 }
00427
00428
00429
00430
00431
00432
00433
00434
00435 void ConfigVariableCore::
00436 remove_declaration(ConfigDeclaration *decl) {
00437 Declarations::iterator di;
00438 for (di = _declarations.begin(); di != _declarations.end(); ++di) {
00439 if ((*di) == decl) {
00440
00441
00442
00443 Declarations::iterator di2 = _declarations.end();
00444 di2--;
00445 (*di) = (*di2);
00446 _declarations.erase(di2);
00447 _declarations_sorted = false;
00448 return;
00449 }
00450 }
00451
00452
00453 }
00454
00455
00456 class CompareConfigDeclarations {
00457 public:
00458 bool operator () (const ConfigDeclaration *a, const ConfigDeclaration *b) const {
00459 return (*a) < (*b);
00460 }
00461 };
00462
00463
00464
00465
00466
00467
00468
00469
00470 void ConfigVariableCore::
00471 sort_declarations() {
00472 sort(_declarations.begin(), _declarations.end(), CompareConfigDeclarations());
00473 Declarations::iterator di;
00474
00475
00476
00477 #ifdef PRC_RESPECT_TRUST_LEVEL
00478
00479
00480
00481 _trusted_declarations.clear();
00482 _untrusted_declarations.clear();
00483 for (di = _declarations.begin(); di != _declarations.end(); ++di) {
00484 const ConfigDeclaration *decl = (*di);
00485 if (!is_closed() &&
00486 get_trust_level() <= decl->get_page()->get_trust_level()) {
00487 _trusted_declarations.push_back(decl);
00488 } else {
00489 _untrusted_declarations.push_back(decl);
00490 }
00491 }
00492
00493 #else // PRC_RESPECT_TRUST_LEVEL
00494
00495
00496 _trusted_declarations = _declarations;
00497 _untrusted_declarations.clear();
00498
00499 #endif // PRC_RESPECT_TRUST_LEVEL
00500
00501
00502
00503
00504
00505 _unique_declarations.clear();
00506
00507 init_system_type_handles();
00508 pset<string> already_added;
00509 for (di = _trusted_declarations.begin();
00510 di != _trusted_declarations.end();
00511 ++di) {
00512 const ConfigDeclaration *decl = (*di);
00513 if (already_added.insert(decl->get_string_value()).second) {
00514 _unique_declarations.push_back(decl);
00515 }
00516 }
00517
00518 _declarations_sorted = true;
00519 }