1 // Copyright (c) 2006, Google Inc. 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are 6 // met: 7 // 8 // * Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // * Redistributions in binary form must reproduce the above 11 // copyright notice, this list of conditions and the following disclaimer 12 // in the documentation and/or other materials provided with the 13 // distribution. 14 // * Neither the name of Google Inc. nor the names of its 15 // contributors may be used to endorse or promote products derived from 16 // this software without specific prior written permission. 17 // 18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 30 // --- 31 // Author: Ray Sidney 32 // Revamped and reorganized by Craig Silverstein 33 // 34 // This file contains the implementation of all our command line flags 35 // stuff. Here's how everything fits together 36 // 37 // * FlagRegistry owns CommandLineFlags owns FlagValue. 38 // * FlagSaver holds a FlagRegistry (saves it at construct time, 39 // restores it at destroy time). 40 // * CommandLineFlagParser lives outside that hierarchy, but works on 41 // CommandLineFlags (modifying the FlagValues). 42 // * Free functions like SetCommandLineOption() work via one of the 43 // above (such as CommandLineFlagParser). 44 // 45 // In more detail: 46 // 47 // -- The main classes that hold flag data: 48 // 49 // FlagValue holds the current value of a flag. It's 50 // pseudo-templatized: every operation on a FlagValue is typed. It 51 // also deals with storage-lifetime issues (so flag values don't go 52 // away in a destructor), which is why we need a whole class to hold a 53 // variable's value. 54 // 55 // CommandLineFlag is all the information about a single command-line 56 // flag. It has a FlagValue for the flag's current value, but also 57 // the flag's name, type, etc. 58 // 59 // FlagRegistry is a collection of CommandLineFlags. There's the 60 // global registry, which is where flags defined via DEFINE_foo() 61 // live. But it's possible to define your own flag, manually, in a 62 // different registry you create. (In practice, multiple registries 63 // are used only by FlagSaver). 64 // 65 // A given FlagValue is owned by exactly one CommandLineFlag. A given 66 // CommandLineFlag is owned by exactly one FlagRegistry. FlagRegistry 67 // has a lock; any operation that writes to a FlagValue or 68 // CommandLineFlag owned by that registry must acquire the 69 // FlagRegistry lock before doing so. 70 // 71 // --- Some other classes and free functions: 72 // 73 // CommandLineFlagInfo is a client-exposed version of CommandLineFlag. 74 // Once it's instantiated, it has no dependencies or relationships 75 // with any other part of this file. 76 // 77 // FlagRegisterer is the helper class used by the DEFINE_* macros to 78 // allow work to be done at global initialization time. 79 // 80 // CommandLineFlagParser is the class that reads from the commandline 81 // and instantiates flag values based on that. It needs to poke into 82 // the innards of the FlagValue->CommandLineFlag->FlagRegistry class 83 // hierarchy to do that. It's careful to acquire the FlagRegistry 84 // lock before doing any writing or other non-const actions. 85 // 86 // GetCommandLineOption is just a hook into registry routines to 87 // retrieve a flag based on its name. SetCommandLineOption, on the 88 // other hand, hooks into CommandLineFlagParser. Other API functions 89 // are, similarly, mostly hooks into the functionality described above. 90 91 #include "config.h" 92 // This comes first to ensure we define __STDC_FORMAT_MACROS in time. 93 #ifdef HAVE_INTTYPES_H 94 #ifndef __STDC_FORMAT_MACROS 95 # define __STDC_FORMAT_MACROS 1 // gcc requires this to get PRId64, etc. 96 #endif 97 #include <inttypes.h> 98 #endif // HAVE_INTTYPES_H 99 #include <ctype.h> 100 #include <errno.h> 101 #include <stdio.h> 102 #include <stdarg.h> // For va_list and related operations 103 #include <string.h> 104 #include <assert.h> 105 #ifdef HAVE_FNMATCH_H 106 #include <fnmatch.h> 107 #endif // HAVE_FNMATCH_H 108 #include <iostream> // for cerr 109 #include <string> 110 #include <map> 111 #include <vector> 112 #include <utility> // for pair<> 113 #include <algorithm> 114 #include "gflags/gflags.h" 115 #include "mutex.h" 116 117 #ifndef PATH_SEPARATOR 118 #define PATH_SEPARATOR '/' 119 #endif 120 121 // Work properly if either strtoll or strtoq is on this system 122 #ifdef HAVE_STRTOLL 123 # define strtoint64 strtoll 124 # define strtouint64 strtoull 125 #elif HAVE_STRTOQ 126 # define strtoint64 strtoq 127 # define strtouint64 strtouq 128 #else 129 // Neither strtoll nor strtoq are defined. I hope strtol works! 130 # define strtoint64 strtol 131 # define strtouint64 strtoul 132 #endif 133 134 // If we have inttypes.h, it will have defined PRId32/etc for us. If 135 // not, take our best guess. 136 #ifndef PRId32 137 # define PRId32 "d" 138 #endif 139 #ifndef PRId64 140 # define PRId64 "lld" 141 #endif 142 #ifndef PRIu64 143 # define PRIu64 "llu" 144 #endif 145 146 using std::map; 147 using std::vector; 148 using std::pair; 149 using std::cerr; 150 using std::sort; 151 152 // Special flags, type 1: the 'recursive' flags. They set another flag's val. 153 DEFINE_string(flagfile, "", 154 "load flags from file"); 155 DEFINE_string(fromenv, "", 156 "set flags from the environment" 157 " [use 'export FLAGS_flag1=value']"); 158 DEFINE_string(tryfromenv, "", 159 "set flags from the environment if present"); 160 161 // Special flags, type 2: the 'parsing' flags. They modify how we parse. 162 DEFINE_string(undefok, "", 163 "comma-separated list of flag names that it is okay to specify " 164 "on the command line even if the program does not define a flag " 165 "with that name. IMPORTANT: flags in this list that have " 166 "arguments MUST use the flag=value format"); 167 168 namespace google { 169 170 using std::string; 171 172 // The help message indicating that the commandline flag has been 173 // 'stripped'. It will not show up when doing "-help" and its 174 // variants. The flag is stripped if STRIP_FLAG_HELP is set to 1 175 // before including gflags/gflags.h. 176 177 // This is used by this file, and also in commandlineflags_reporting.cc 178 const char kStrippedFlagHelp[] = "\001\002\003\004 (unknown) \004\003\002\001"; 179 180 // This is used by the unittest to test error-exit code 181 void (*commandlineflags_exitfunc)(int) = &exit; // from stdlib.h 182 183 namespace { 184 185 // There are also 'reporting' flags, in commandlineflags_reporting.cc. 186 187 static const char kError[] = "ERROR: "; 188 189 // Indicates that undefined options are to be ignored. 190 // Enables deferred processing of flags in dynamically loaded libraries. 191 static bool allow_command_line_reparsing = false; 192 193 static bool logging_is_probably_set_up = false; 194 195 // This is a 'prototype' validate-function. 'Real' validate 196 // functions, take a flag-value as an argument: ValidateFn(bool) or 197 // ValidateFn(uint64). However, for easier storage, we strip off this 198 // argument and then restore it when actually calling the function on 199 // a flag value. 200 typedef bool (*ValidateFnProto)(); 201 202 // Whether we should die when reporting an error. 203 enum DieWhenReporting { DIE, DO_NOT_DIE }; 204 205 // Report Error and exit if requested. 206 static void ReportError(DieWhenReporting should_die, const char* format, ...) { 207 va_list ap; 208 va_start(ap, format); 209 vfprintf(stderr, format, ap); 210 va_end(ap); 211 if (should_die == DIE) 212 commandlineflags_exitfunc(1); // almost certainly exit() 213 } 214 215 216 // -------------------------------------------------------------------- 217 // FlagValue 218 // This represent the value a single flag might have. The major 219 // functionality is to convert from a string to an object of a 220 // given type, and back. Thread-compatible. 221 // -------------------------------------------------------------------- 222 223 class CommandLineFlag; 224 class FlagValue { 225 public: 226 FlagValue(void* valbuf, const char* type); 227 ~FlagValue(); 228 229 bool ParseFrom(const char* spec); 230 string ToString() const; 231 232 private: 233 friend class CommandLineFlag; // for many things, including Validate() 234 friend class ::google::FlagSaverImpl; // calls New() 235 friend class FlagRegistry; // checks value_buffer_ for flags_by_ptr_ map 236 template <typename T> friend T GetFromEnv(const char*, const char*, T); 237 friend bool TryParseLocked(const CommandLineFlag*, FlagValue*, 238 const char*, string*); // for New(), CopyFrom() 239 240 enum ValueType {FV_BOOL, FV_INT32, FV_INT64, FV_UINT64, FV_DOUBLE, FV_STRING}; 241 242 const char* TypeName() const; 243 bool Equal(const FlagValue& x) const; 244 FlagValue* New() const; // creates a new one with default value 245 void CopyFrom(const FlagValue& x); 246 247 // Calls the given validate-fn on value_buffer_, and returns 248 // whatever it returns. But first casts validate_fn_proto to a 249 // function that takes our value as an argument (eg void 250 // (*validate_fn)(bool) for a bool flag). 251 bool Validate(const char* flagname, ValidateFnProto validate_fn_proto) const; 252 253 void* value_buffer_; // points to the buffer holding our data 254 ValueType type_; // how to interpret value_ 255 256 FlagValue(const FlagValue&); // no copying! 257 void operator=(const FlagValue&); 258 }; 259 260 261 // This could be a templated method of FlagValue, but doing so adds to the 262 // size of the .o. Since there's no type-safety here anyway, macro is ok. 263 #define VALUE_AS(type) *reinterpret_cast<type*>(value_buffer_) 264 #define OTHER_VALUE_AS(fv, type) *reinterpret_cast<type*>(fv.value_buffer_) 265 #define SET_VALUE_AS(type, value) VALUE_AS(type) = (value) 266 267 FlagValue::FlagValue(void* valbuf, const char* type) : value_buffer_(valbuf) { 268 if (strcmp(type, "bool") == 0) type_ = FV_BOOL; 269 else if (strcmp(type, "int32") == 0) type_ = FV_INT32; 270 else if (strcmp(type, "int64") == 0) type_ = FV_INT64; 271 else if (strcmp(type, "uint64") == 0) type_ = FV_UINT64; 272 else if (strcmp(type, "double") == 0) type_ = FV_DOUBLE; 273 else if (strcmp(type, "string") == 0) type_ = FV_STRING; 274 else assert(false); // Unknown typename 275 } 276 277 FlagValue::~FlagValue() { 278 switch (type_) { 279 case FV_BOOL: delete reinterpret_cast<bool*>(value_buffer_); break; 280 case FV_INT32: delete reinterpret_cast<int32*>(value_buffer_); break; 281 case FV_INT64: delete reinterpret_cast<int64*>(value_buffer_); break; 282 case FV_UINT64: delete reinterpret_cast<uint64*>(value_buffer_); break; 283 case FV_DOUBLE: delete reinterpret_cast<double*>(value_buffer_); break; 284 case FV_STRING: delete reinterpret_cast<string*>(value_buffer_); break; 285 } 286 } 287 288 bool FlagValue::ParseFrom(const char* value) { 289 if (type_ == FV_BOOL) { 290 const char* kTrue[] = { "1", "t", "true", "y", "yes" }; 291 const char* kFalse[] = { "0", "f", "false", "n", "no" }; 292 for (size_t i = 0; i < sizeof(kTrue)/sizeof(*kTrue); ++i) { 293 if (strcasecmp(value, kTrue[i]) == 0) { 294 SET_VALUE_AS(bool, true); 295 return true; 296 } else if (strcasecmp(value, kFalse[i]) == 0) { 297 SET_VALUE_AS(bool, false); 298 return true; 299 } 300 } 301 return false; // didn't match a legal input 302 303 } else if (type_ == FV_STRING) { 304 SET_VALUE_AS(string, value); 305 return true; 306 } 307 308 // OK, it's likely to be numeric, and we'll be using a strtoXXX method. 309 if (value[0] == '\0') // empty-string is only allowed for string type. 310 return false; 311 char* end; 312 // Leading 0x puts us in base 16. But leading 0 does not put us in base 8! 313 // It caused too many bugs when we had that behavior. 314 int base = 10; // by default 315 if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X')) 316 base = 16; 317 errno = 0; 318 319 switch (type_) { 320 case FV_INT32: { 321 const int64 r = strtoint64(value, &end, base); 322 if (errno || end != value + strlen(value)) return false; // bad parse 323 if (static_cast<int32>(r) != r) // worked, but number out of range 324 return false; 325 SET_VALUE_AS(int32, static_cast<int32>(r)); 326 return true; 327 } 328 case FV_INT64: { 329 const int64 r = strtoint64(value, &end, base); 330 if (errno || end != value + strlen(value)) return false; // bad parse 331 SET_VALUE_AS(int64, r); 332 return true; 333 } 334 case FV_UINT64: { 335 while (*value == ' ') value++; 336 if (*value == '-') return false; // negative number 337 const uint64 r = strtouint64(value, &end, base); 338 if (errno || end != value + strlen(value)) return false; // bad parse 339 SET_VALUE_AS(uint64, r); 340 return true; 341 } 342 case FV_DOUBLE: { 343 const double r = strtod(value, &end); 344 if (errno || end != value + strlen(value)) return false; // bad parse 345 SET_VALUE_AS(double, r); 346 return true; 347 } 348 default: { 349 assert(false); // unknown type 350 return false; 351 } 352 } 353 } 354 355 string FlagValue::ToString() const { 356 char intbuf[64]; // enough to hold even the biggest number 357 switch (type_) { 358 case FV_BOOL: 359 return VALUE_AS(bool) ? "true" : "false"; 360 case FV_INT32: 361 snprintf(intbuf, sizeof(intbuf), "%"PRId32, VALUE_AS(int32)); 362 return intbuf; 363 case FV_INT64: 364 snprintf(intbuf, sizeof(intbuf), "%"PRId64, VALUE_AS(int64)); 365 return intbuf; 366 case FV_UINT64: 367 snprintf(intbuf, sizeof(intbuf), "%"PRIu64, VALUE_AS(uint64)); 368 return intbuf; 369 case FV_DOUBLE: 370 snprintf(intbuf, sizeof(intbuf), "%.17g", VALUE_AS(double)); 371 return intbuf; 372 case FV_STRING: 373 return VALUE_AS(string); 374 default: 375 assert(false); 376 return ""; // unknown type 377 } 378 } 379 380 bool FlagValue::Validate(const char* flagname, 381 ValidateFnProto validate_fn_proto) const { 382 switch (type_) { 383 case FV_BOOL: 384 return reinterpret_cast<bool (*)(const char*, bool)>( 385 validate_fn_proto)(flagname, VALUE_AS(bool)); 386 case FV_INT32: 387 return reinterpret_cast<bool (*)(const char*, int32)>( 388 validate_fn_proto)(flagname, VALUE_AS(int32)); 389 case FV_INT64: 390 return reinterpret_cast<bool (*)(const char*, int64)>( 391 validate_fn_proto)(flagname, VALUE_AS(int64)); 392 case FV_UINT64: 393 return reinterpret_cast<bool (*)(const char*, uint64)>( 394 validate_fn_proto)(flagname, VALUE_AS(uint64)); 395 case FV_DOUBLE: 396 return reinterpret_cast<bool (*)(const char*, double)>( 397 validate_fn_proto)(flagname, VALUE_AS(double)); 398 case FV_STRING: 399 return reinterpret_cast<bool (*)(const char*, const string&)>( 400 validate_fn_proto)(flagname, VALUE_AS(string)); 401 default: 402 assert(false); // unknown type 403 return false; 404 } 405 } 406 407 const char* FlagValue::TypeName() const { 408 switch (type_) { 409 case FV_BOOL: return "bool"; 410 case FV_INT32: return "int32"; 411 case FV_INT64: return "int64"; 412 case FV_UINT64: return "uint64"; 413 case FV_DOUBLE: return "double"; 414 case FV_STRING: return "string"; 415 default: assert(false); return ""; // unknown type 416 } 417 } 418 419 bool FlagValue::Equal(const FlagValue& x) const { 420 if (type_ != x.type_) 421 return false; 422 switch (type_) { 423 case FV_BOOL: return VALUE_AS(bool) == OTHER_VALUE_AS(x, bool); 424 case FV_INT32: return VALUE_AS(int32) == OTHER_VALUE_AS(x, int32); 425 case FV_INT64: return VALUE_AS(int64) == OTHER_VALUE_AS(x, int64); 426 case FV_UINT64: return VALUE_AS(uint64) == OTHER_VALUE_AS(x, uint64); 427 case FV_DOUBLE: return VALUE_AS(double) == OTHER_VALUE_AS(x, double); 428 case FV_STRING: return VALUE_AS(string) == OTHER_VALUE_AS(x, string); 429 default: assert(false); return false; // unknown type 430 } 431 } 432 433 FlagValue* FlagValue::New() const { 434 switch (type_) { 435 case FV_BOOL: return new FlagValue(new bool(false), "bool"); 436 case FV_INT32: return new FlagValue(new int32(0), "int32"); 437 case FV_INT64: return new FlagValue(new int64(0), "int64"); 438 case FV_UINT64: return new FlagValue(new uint64(0), "uint64"); 439 case FV_DOUBLE: return new FlagValue(new double(0.0), "double"); 440 case FV_STRING: return new FlagValue(new string, "string"); 441 default: assert(false); return NULL; // unknown type 442 } 443 } 444 445 void FlagValue::CopyFrom(const FlagValue& x) { 446 assert(type_ == x.type_); 447 switch (type_) { 448 case FV_BOOL: SET_VALUE_AS(bool, OTHER_VALUE_AS(x, bool)); break; 449 case FV_INT32: SET_VALUE_AS(int32, OTHER_VALUE_AS(x, int32)); break; 450 case FV_INT64: SET_VALUE_AS(int64, OTHER_VALUE_AS(x, int64)); break; 451 case FV_UINT64: SET_VALUE_AS(uint64, OTHER_VALUE_AS(x, uint64)); break; 452 case FV_DOUBLE: SET_VALUE_AS(double, OTHER_VALUE_AS(x, double)); break; 453 case FV_STRING: SET_VALUE_AS(string, OTHER_VALUE_AS(x, string)); break; 454 default: assert(false); // unknown type 455 } 456 } 457 458 // -------------------------------------------------------------------- 459 // CommandLineFlag 460 // This represents a single flag, including its name, description, 461 // default value, and current value. Mostly this serves as a 462 // struct, though it also knows how to register itself. 463 // All CommandLineFlags are owned by a (exactly one) 464 // FlagRegistry. If you wish to modify fields in this class, you 465 // should acquire the FlagRegistry lock for the registry that owns 466 // this flag. 467 // -------------------------------------------------------------------- 468 469 class CommandLineFlag { 470 public: 471 // Note: we take over memory-ownership of current_val and default_val. 472 CommandLineFlag(const char* name, const char* help, const char* filename, 473 FlagValue* current_val, FlagValue* default_val); 474 ~CommandLineFlag(); 475 476 const char* name() const { return name_; } 477 const char* help() const { return help_; } 478 const char* filename() const { return file_; } 479 const char* CleanFileName() const; // nixes irrelevant prefix such as homedir 480 string current_value() const { return current_->ToString(); } 481 string default_value() const { return defvalue_->ToString(); } 482 const char* type_name() const { return defvalue_->TypeName(); } 483 ValidateFnProto validate_function() const { return validate_fn_proto_; } 484 485 void FillCommandLineFlagInfo(struct CommandLineFlagInfo* result); 486 487 // If validate_fn_proto_ is non-NULL, calls it on value, returns result. 488 bool Validate(const FlagValue& value) const; 489 bool ValidateCurrent() const { return Validate(*current_); } 490 491 private: 492 // for SetFlagLocked() and setting flags_by_ptr_ 493 friend class FlagRegistry; 494 friend class ::google::FlagSaverImpl; // for cloning the values 495 friend bool GetCommandLineOption(const char*, string*, bool*); 496 // set validate_fn 497 friend bool AddFlagValidator(const void*, ValidateFnProto); 498 499 // This copies all the non-const members: modified, processed, defvalue, etc. 500 void CopyFrom(const CommandLineFlag& src); 501 502 void UpdateModifiedBit(); 503 504 const char* const name_; // Flag name 505 const char* const help_; // Help message 506 const char* const file_; // Which file did this come from? 507 bool modified_; // Set after default assignment? 508 FlagValue* defvalue_; // Default value for flag 509 FlagValue* current_; // Current value for flag 510 // This is a casted, 'generic' version of validate_fn, which actually 511 // takes a flag-value as an arg (void (*validate_fn)(bool), say). 512 // When we pass this to current_->Validate(), it will cast it back to 513 // the proper type. This may be NULL to mean we have no validate_fn. 514 ValidateFnProto validate_fn_proto_; 515 516 CommandLineFlag(const CommandLineFlag&); // no copying! 517 void operator=(const CommandLineFlag&); 518 }; 519 520 CommandLineFlag::CommandLineFlag(const char* name, const char* help, 521 const char* filename, 522 FlagValue* current_val, FlagValue* default_val) 523 : name_(name), help_(help), file_(filename), modified_(false), 524 defvalue_(default_val), current_(current_val), validate_fn_proto_(NULL) { 525 } 526 527 CommandLineFlag::~CommandLineFlag() { 528 delete current_; 529 delete defvalue_; 530 } 531 532 const char* CommandLineFlag::CleanFileName() const { 533 // Compute top-level directory & file that this appears in 534 // search full path backwards. 535 // Stop going backwards at kRootDir; and skip by the first slash. 536 static const char kRootDir[] = ""; // can set this to root directory, 537 // e.g. "myproject" 538 539 if (sizeof(kRootDir)-1 == 0) // no prefix to strip 540 return filename(); 541 542 const char* clean_name = filename() + strlen(filename()) - 1; 543 while ( clean_name > filename() ) { 544 if (*clean_name == PATH_SEPARATOR) { 545 if (strncmp(clean_name, kRootDir, sizeof(kRootDir)-1) == 0) { 546 // ".../myproject/base/logging.cc" ==> "base/logging.cc" 547 clean_name += sizeof(kRootDir)-1; // past "/myproject/" 548 break; 549 } 550 } 551 --clean_name; 552 } 553 while ( *clean_name == PATH_SEPARATOR ) ++clean_name; // Skip any slashes 554 return clean_name; 555 } 556 557 void CommandLineFlag::FillCommandLineFlagInfo( 558 CommandLineFlagInfo* result) { 559 result->name = name(); 560 result->type = type_name(); 561 result->description = help(); 562 result->current_value = current_value(); 563 result->default_value = default_value(); 564 result->filename = CleanFileName(); 565 UpdateModifiedBit(); 566 result->is_default = !modified_; 567 result->has_validator_fn = validate_function() != NULL; 568 } 569 570 void CommandLineFlag::UpdateModifiedBit() { 571 // Update the "modified" bit in case somebody bypassed the 572 // Flags API and wrote directly through the FLAGS_name variable. 573 if (!modified_ && !current_->Equal(*defvalue_)) { 574 modified_ = true; 575 } 576 } 577 578 void CommandLineFlag::CopyFrom(const CommandLineFlag& src) { 579 // Note we only copy the non-const members; others are fixed at construct time 580 if (modified_ != src.modified_) modified_ = src.modified_; 581 if (!current_->Equal(*src.current_)) current_->CopyFrom(*src.current_); 582 if (!defvalue_->Equal(*src.defvalue_)) defvalue_->CopyFrom(*src.defvalue_); 583 if (validate_fn_proto_ != src.validate_fn_proto_) 584 validate_fn_proto_ = src.validate_fn_proto_; 585 } 586 587 bool CommandLineFlag::Validate(const FlagValue& value) const { 588 if (validate_function() == NULL) 589 return true; 590 else 591 return value.Validate(name(), validate_function()); 592 } 593 594 595 // -------------------------------------------------------------------- 596 // FlagRegistry 597 // A FlagRegistry singleton object holds all flag objects indexed 598 // by their names so that if you know a flag's name (as a C 599 // string), you can access or set it. If the function is named 600 // FooLocked(), you must own the registry lock before calling 601 // the function; otherwise, you should *not* hold the lock, and 602 // the function will acquire it itself if needed. 603 // -------------------------------------------------------------------- 604 605 struct StringCmp { // Used by the FlagRegistry map class to compare char*'s 606 bool operator() (const char* s1, const char* s2) const { 607 return (strcmp(s1, s2) < 0); 608 } 609 }; 610 611 class FlagRegistry { 612 public: 613 FlagRegistry() { } 614 615 void Lock() { lock_.Lock(); } 616 void Unlock() { lock_.Unlock(); } 617 618 // Store a flag in this registry. Takes ownership of the given pointer. 619 void RegisterFlag(CommandLineFlag* flag); 620 621 // Returns the flag object for the specified name, or NULL if not found. 622 CommandLineFlag* FindFlagLocked(const char* name); 623 624 // Returns the flag object whose current-value is stored at flag_ptr. 625 // That is, for whom current_->value_buffer_ == flag_ptr 626 CommandLineFlag* FindFlagViaPtrLocked(const void* flag_ptr); 627 628 // A fancier form of FindFlag that works correctly if name is of the 629 // form flag=value. In that case, we set key to point to flag, and 630 // modify v to point to the value (if present), and return the flag 631 // with the given name. If the flag does not exist, returns NULL 632 // and sets error_message. 633 CommandLineFlag* SplitArgumentLocked(const char* argument, 634 string* key, const char** v, 635 string* error_message); 636 637 // Set the value of a flag. If the flag was successfully set to 638 // value, set msg to indicate the new flag-value, and return true. 639 // Otherwise, set msg to indicate the error, leave flag unchanged, 640 // and return false. msg can be NULL. 641 bool SetFlagLocked(CommandLineFlag* flag, const char* value, 642 FlagSettingMode set_mode, string* msg); 643 644 static FlagRegistry* GlobalRegistry(); // returns a singleton registry 645 646 private: 647 friend class ::google::FlagSaverImpl; // reads all the flags in order to copy them 648 friend class CommandLineFlagParser; // for ValidateAllFlags 649 friend void ::google::GetAllFlags(vector<CommandLineFlagInfo>*); 650 651 // The map from name to flag, for FindFlagLocked(). 652 typedef map<const char*, CommandLineFlag*, StringCmp> FlagMap; 653 typedef FlagMap::iterator FlagIterator; 654 typedef FlagMap::const_iterator FlagConstIterator; 655 FlagMap flags_; 656 657 // The map from current-value pointer to flag, fo FindFlagViaPtrLocked(). 658 typedef map<const void*, CommandLineFlag*> FlagPtrMap; 659 FlagPtrMap flags_by_ptr_; 660 661 Mutex lock_; 662 663 static FlagRegistry* global_registry_; // a singleton registry 664 static Mutex global_registry_lock_; // guards creation of global_registry_ 665 666 // Disallow 667 FlagRegistry(const FlagRegistry&); 668 FlagRegistry& operator=(const FlagRegistry&); 669 }; 670 671 FlagRegistry* FlagRegistry::global_registry_ = NULL; 672 Mutex FlagRegistry::global_registry_lock_; 673 674 FlagRegistry* FlagRegistry::GlobalRegistry() { 675 MutexLock acquire_lock(&global_registry_lock_); 676 if (!global_registry_) { 677 global_registry_ = new FlagRegistry; 678 } 679 return global_registry_; 680 } 681 682 void FlagRegistry::RegisterFlag(CommandLineFlag* flag) { 683 Lock(); 684 pair<FlagIterator, bool> ins = 685 flags_.insert(pair<const char*, CommandLineFlag*>(flag->name(), flag)); 686 if (ins.second == false) { // means the name was already in the map 687 if (strcmp(ins.first->second->filename(), flag->filename()) != 0) { 688 ReportError(DIE, "ERROR: flag '%s' was defined more than once " 689 "(in files '%s' and '%s').\n", 690 flag->name(), 691 ins.first->second->filename(), 692 flag->filename()); 693 } else { 694 ReportError(DIE, "ERROR: something wrong with flag '%s' in file '%s'. " 695 "One possibility: file '%s' is being linked both statically " 696 "and dynamically into this executable.\n", 697 flag->name(), 698 flag->filename(), flag->filename()); 699 } 700 } 701 // Also add to the flags_by_ptr_ map. 702 flags_by_ptr_[flag->current_->value_buffer_] = flag; 703 Unlock(); 704 } 705 706 CommandLineFlag* FlagRegistry::FindFlagLocked(const char* name) { 707 FlagConstIterator i = flags_.find(name); 708 if (i == flags_.end()) { 709 return NULL; 710 } else { 711 return i->second; 712 } 713 } 714 715 CommandLineFlag* FlagRegistry::FindFlagViaPtrLocked(const void* flag_ptr) { 716 FlagPtrMap::const_iterator i = flags_by_ptr_.find(flag_ptr); 717 if (i == flags_by_ptr_.end()) { 718 return NULL; 719 } else { 720 return i->second; 721 } 722 } 723 724 CommandLineFlag* FlagRegistry::SplitArgumentLocked(const char* arg, 725 string* key, 726 const char** v, 727 string* error_message) { 728 // Find the flag object for this option 729 const char* flag_name; 730 const char* value = strchr(arg, '='); 731 if (value == NULL) { 732 key->assign(arg); 733 *v = NULL; 734 } else { 735 // Strip out the "=value" portion from arg 736 key->assign(arg, value-arg); 737 *v = ++value; // advance past the '=' 738 } 739 flag_name = key->c_str(); 740 741 CommandLineFlag* flag = FindFlagLocked(flag_name); 742 743 if (flag == NULL) { 744 // If we can't find the flag-name, then we should return an error. 745 // The one exception is if 1) the flag-name is 'nox', 2) there 746 // exists a flag named 'x', and 3) 'x' is a boolean flag. 747 // In that case, we want to return flag 'x'. 748 if (!(flag_name[0] == 'n' && flag_name[1] == 'o')) { 749 // flag-name is not 'nox', so we're not in the exception case. 750 *error_message = (string(kError) + 751 "unknown command line flag '" + *key + "'\n"); 752 return NULL; 753 } 754 flag = FindFlagLocked(flag_name+2); 755 if (flag == NULL) { 756 // No flag named 'x' exists, so we're not in the exception case. 757 *error_message = (string(kError) + 758 "unknown command line flag '" + *key + "'\n"); 759 return NULL; 760 } 761 if (strcmp(flag->type_name(), "bool") != 0) { 762 // 'x' exists but is not boolean, so we're not in the exception case. 763 *error_message = (string(kError) + 764 "boolean value (" + *key + ") specified for " + 765 flag->type_name() + " command line flag\n"); 766 return NULL; 767 } 768 // We're in the exception case! 769 // Make up a fake value to replace the "no" we stripped out 770 key->assign(flag_name+2); // the name without the "no" 771 *v = "0"; 772 } 773 774 // Assign a value if this is a boolean flag 775 if (*v == NULL && strcmp(flag->type_name(), "bool") == 0) { 776 *v = "1"; // the --nox case was already handled, so this is the --x case 777 } 778 779 return flag; 780 } 781 782 bool TryParseLocked(const CommandLineFlag* flag, FlagValue* flag_value, 783 const char* value, string* msg) { 784 // Use tenative_value, not flag_value, until we know value is valid. 785 FlagValue* tentative_value = flag_value->New(); 786 if (!tentative_value->ParseFrom(value)) { 787 if (msg) { 788 *msg += (string(kError) + "illegal value '" + value + 789 + "' specified for " + flag->type_name() + " flag '" 790 + flag->name() + "'\n"); 791 } 792 delete tentative_value; 793 return false; 794 } else if (!flag->Validate(*tentative_value)) { 795 if (msg) { 796 *msg += (string(kError) + "failed validation of new value " 797 + "'" + tentative_value->ToString() + "' for flag '" + 798 + flag->name() + "'\n"); 799 } 800 delete tentative_value; 801 return false; 802 } else { 803 flag_value->CopyFrom(*tentative_value); 804 if (msg) { 805 *msg += (string(flag->name()) + " set to " + flag_value->ToString() 806 + "\n"); 807 } 808 delete tentative_value; 809 return true; 810 } 811 } 812 813 bool FlagRegistry::SetFlagLocked(CommandLineFlag* flag, 814 const char* value, 815 FlagSettingMode set_mode, 816 string* msg) { 817 flag->UpdateModifiedBit(); 818 switch (set_mode) { 819 case SET_FLAGS_VALUE: { 820 // set or modify the flag's value 821 if (!TryParseLocked(flag, flag->current_, value, msg)) 822 return false; 823 flag->modified_ = true; 824 break; 825 } 826 case SET_FLAG_IF_DEFAULT: { 827 // set the flag's value, but only if it hasn't been set by someone else 828 if (!flag->modified_) { 829 if (!TryParseLocked(flag, flag->current_, value, msg)) 830 return false; 831 flag->modified_ = true; 832 } else { 833 *msg = string(flag->name()) + " set to " + flag->current_value(); 834 } 835 break; 836 } 837 case SET_FLAGS_DEFAULT: { 838 // modify the flag's default-value 839 if (!TryParseLocked(flag, flag->defvalue_, value, msg)) 840 return false; 841 if (!flag->modified_) { 842 // Need to set both defvalue *and* current, in this case 843 TryParseLocked(flag, flag->current_, value, NULL); 844 } 845 break; 846 } 847 default: { 848 // unknown set_mode 849 assert(false); 850 return false; 851 } 852 } 853 854 return true; 855 } 856 857 class FlagRegistryLock { 858 public: 859 explicit FlagRegistryLock(FlagRegistry* fr) : fr_(fr) { fr_->Lock(); } 860 ~FlagRegistryLock() { fr_->Unlock(); } 861 private: 862 FlagRegistry *const fr_; 863 }; 864 865 // -------------------------------------------------------------------- 866 // CommandLineFlagParser 867 // Parsing is done in two stages. In the first, we go through 868 // argv. For every flag-like arg we can make sense of, we parse 869 // it and set the appropriate FLAGS_* variable. For every flag- 870 // like arg we can't make sense of, we store it in a vector, 871 // along with an explanation of the trouble. In stage 2, we 872 // handle the 'reporting' flags like --help and --mpm_version. 873 // (This is via a call to HandleCommandLineHelpFlags(), in 874 // gflags_reporting.cc.) 875 // An optional stage 3 prints out the error messages. 876 // This is a bit of a simplification. For instance, --flagfile 877 // is handled as soon as it's seen in stage 1, not in stage 2. 878 // -------------------------------------------------------------------- 879 880 class CommandLineFlagParser { 881 public: 882 // The argument is the flag-registry to register the parsed flags in 883 explicit CommandLineFlagParser(FlagRegistry* reg) : registry_(reg) {} 884 ~CommandLineFlagParser() {} 885 886 // Stage 1: Every time this is called, it reads all flags in argv. 887 // However, it ignores all flags that have been successfully set 888 // before. Typically this is only called once, so this 'reparsing' 889 // behavior isn't important. It can be useful when trying to 890 // reparse after loading a dll, though. 891 uint32 ParseNewCommandLineFlags(int* argc, char*** argv, bool remove_flags); 892 893 // Stage 2: print reporting info and exit, if requested. 894 // In gflags_reporting.cc:HandleCommandLineHelpFlags(). 895 896 // Stage 3: validate all the commandline flags that have validators 897 // registered. 898 void ValidateAllFlags(); 899 900 // Stage 4: report any errors and return true if any were found. 901 bool ReportErrors(); 902 903 // Set a particular command line option. "newval" is a string 904 // describing the new value that the option has been set to. If 905 // option_name does not specify a valid option name, or value is not 906 // a valid value for option_name, newval is empty. Does recursive 907 // processing for --flagfile and --fromenv. Returns the new value 908 // if everything went ok, or empty-string if not. (Actually, the 909 // return-string could hold many flag/value pairs due to --flagfile.) 910 // NB: Must have called registry_->Lock() before calling this function. 911 string ProcessSingleOptionLocked(CommandLineFlag* flag, 912 const char* value, 913 FlagSettingMode set_mode); 914 915 // Set a whole batch of command line options as specified by contentdata, 916 // which is in flagfile format (and probably has been read from a flagfile). 917 // Returns the new value if everything went ok, or empty-string if 918 // not. (Actually, the return-string could hold many flag/value 919 // pairs due to --flagfile.) 920 // NB: Must have called registry_->Lock() before calling this function. 921 string ProcessOptionsFromStringLocked(const string& contentdata, 922 FlagSettingMode set_mode); 923 924 // These are the 'recursive' flags, defined at the top of this file. 925 // Whenever we see these flags on the commandline, we must take action. 926 // These are called by ProcessSingleOptionLocked and, similarly, return 927 // new values if everything went ok, or the empty-string if not. 928 string ProcessFlagfileLocked(const string& flagval, FlagSettingMode set_mode); 929 // diff fromenv/tryfromenv 930 string ProcessFromenvLocked(const string& flagval, FlagSettingMode set_mode, 931 bool errors_are_fatal); 932 933 private: 934 FlagRegistry* const registry_; 935 map<string, string> error_flags_; // map from name to error message 936 // This could be a set<string>, but we reuse the map to minimize the .o size 937 map<string, string> undefined_names_; // --[flag] name was not registered 938 }; 939 940 941 // Parse a list of (comma-separated) flags. 942 static void ParseFlagList(const char* value, vector<string>* flags) { 943 for (const char *p = value; p && *p; value = p) { 944 p = strchr(value, ','); 945 int len; 946 if (p) { 947 len = static_cast<int>(p - value); 948 p++; 949 } else { 950 len = static_cast<int>(strlen(value)); 951 } 952 953 if (len == 0) 954 ReportError(DIE, "ERROR: empty flaglist entry\n"); 955 if (value[0] == '-') 956 ReportError(DIE, "ERROR: flag \"%*s\" begins with '-'\n", len, value); 957 958 flags->push_back(string(value, len)); 959 } 960 } 961 962 // Snarf an entire file into a C++ string. This is just so that we 963 // can do all the I/O in one place and not worry about it everywhere. 964 // Plus, it's convenient to have the whole file contents at hand. 965 // Adds a newline at the end of the file. 966 #define PFATAL(s) do { perror(s); commandlineflags_exitfunc(1); } while (0) 967 968 static string ReadFileIntoString(const char* filename) { 969 const int kBufSize = 8092; 970 char buffer[kBufSize]; 971 string s; 972 FILE* fp = fopen(filename, "r"); 973 if (!fp) PFATAL(filename); 974 size_t n; 975 while ( (n=fread(buffer, 1, kBufSize, fp)) > 0 ) { 976 if (ferror(fp)) PFATAL(filename); 977 s.append(buffer, n); 978 } 979 fclose(fp); 980 return s; 981 } 982 983 uint32 CommandLineFlagParser::ParseNewCommandLineFlags(int* argc, char*** argv, 984 bool remove_flags) { 985 const char *program_name = strrchr((*argv)[0], PATH_SEPARATOR); // nix path 986 program_name = (program_name == NULL ? (*argv)[0] : program_name+1); 987 988 int first_nonopt = *argc; // for non-options moved to the end 989 990 registry_->Lock(); 991 for (int i = 1; i < first_nonopt; i++) { 992 char* arg = (*argv)[i]; 993 994 // Like getopt(), we permute non-option flags to be at the end. 995 if (arg[0] != '-' || // must be a program argument 996 (arg[0] == '-' && arg[1] == '\0')) { // "-" is an argument, not a flag 997 memmove((*argv) + i, (*argv) + i+1, (*argc - (i+1)) * sizeof((*argv)[i])); 998 (*argv)[*argc-1] = arg; // we go last 999 first_nonopt--; // we've been pushed onto the stack 1000 i--; // to undo the i++ in the loop 1001 continue; 1002 } 1003 1004 if (arg[0] == '-') arg++; // allow leading '-' 1005 if (arg[0] == '-') arg++; // or leading '--' 1006 1007 // -- alone means what it does for GNU: stop options parsing 1008 if (*arg == '\0') { 1009 first_nonopt = i+1; 1010 break; 1011 } 1012 1013 // Find the flag object for this option 1014 string key; 1015 const char* value; 1016 string error_message; 1017 CommandLineFlag* flag = registry_->SplitArgumentLocked(arg, &key, &value, 1018 &error_message); 1019 if (flag == NULL) { 1020 undefined_names_[key] = ""; // value isn't actually used 1021 error_flags_[key] = error_message; 1022 continue; 1023 } 1024 1025 if (value == NULL) { 1026 // Boolean options are always assigned a value by SplitArgumentLocked() 1027 assert(strcmp(flag->type_name(), "bool") != 0); 1028 if (i+1 >= first_nonopt) { 1029 // This flag needs a value, but there is nothing available 1030 error_flags_[key] = (string(kError) + "flag '" + (*argv)[i] + "'" 1031 + " is missing its argument"); 1032 if (flag->help() && flag->help()[0] > '\001') { 1033 // Be useful in case we have a non-stripped description. 1034 error_flags_[key] += string("; flag description: ") + flag->help(); 1035 } 1036 error_flags_[key] += "\n"; 1037 break; // we treat this as an unrecoverable error 1038 } else { 1039 value = (*argv)[++i]; // read next arg for value 1040 1041 // Heuristic to detect the case where someone treats a string arg 1042 // like a bool: 1043 // --my_string_var --foo=bar 1044 // We look for a flag of string type, whose value begins with a 1045 // dash, and where the flag-name and value are separated by a 1046 // space rather than an '='. 1047 // To avoid false positives, we also require the word "true" 1048 // or "false" in the help string. Without this, a valid usage 1049 // "-lat -30.5" would trigger the warning. The common cases we 1050 // want to solve talk about true and false as values. 1051 if (value[0] == '-' 1052 && strcmp(flag->type_name(), "string") == 0 1053 && (strstr(flag->help(), "true") 1054 || strstr(flag->help(), "false"))) { 1055 fprintf(stderr, "Did you really mean to set flag '%s'" 1056 " to the value '%s'?\n", 1057 flag->name(), value); 1058 } 1059 } 1060 } 1061 1062 // TODO(csilvers): only set a flag if we hadn't set it before here 1063 ProcessSingleOptionLocked(flag, value, SET_FLAGS_VALUE); 1064 } 1065 registry_->Unlock(); 1066 1067 if (remove_flags) { // Fix up argc and argv by removing command line flags 1068 (*argv)[first_nonopt-1] = (*argv)[0]; 1069 (*argv) += (first_nonopt-1); 1070 (*argc) -= (first_nonopt-1); 1071 first_nonopt = 1; // because we still don't count argv[0] 1072 } 1073 1074 logging_is_probably_set_up = true; // because we've parsed --logdir, etc. 1075 1076 return first_nonopt; 1077 } 1078 1079 string CommandLineFlagParser::ProcessFlagfileLocked(const string& flagval, 1080 FlagSettingMode set_mode) { 1081 if (flagval.empty()) 1082 return ""; 1083 1084 string msg; 1085 vector<string> filename_list; 1086 ParseFlagList(flagval.c_str(), &filename_list); // take a list of filenames 1087 for (size_t i = 0; i < filename_list.size(); ++i) { 1088 const char* file = filename_list[i].c_str(); 1089 msg += ProcessOptionsFromStringLocked(ReadFileIntoString(file), set_mode); 1090 } 1091 return msg; 1092 } 1093 1094 string CommandLineFlagParser::ProcessFromenvLocked(const string& flagval, 1095 FlagSettingMode set_mode, 1096 bool errors_are_fatal) { 1097 if (flagval.empty()) 1098 return ""; 1099 1100 string msg; 1101 vector<string> flaglist; 1102 ParseFlagList(flagval.c_str(), &flaglist); 1103 1104 for (size_t i = 0; i < flaglist.size(); ++i) { 1105 const char* flagname = flaglist[i].c_str(); 1106 CommandLineFlag* flag = registry_->FindFlagLocked(flagname); 1107 if (flag == NULL) { 1108 error_flags_[flagname] = (string(kError) + "unknown command line flag" 1109 + " '" + flagname + "'" 1110 + " (via --fromenv or --tryfromenv)\n"); 1111 undefined_names_[flagname] = ""; 1112 continue; 1113 } 1114 1115 const string envname = string("FLAGS_") + string(flagname); 1116 const char* envval = getenv(envname.c_str()); 1117 if (!envval) { 1118 if (errors_are_fatal) { 1119 error_flags_[flagname] = (string(kError) + envname + 1120 " not found in environment\n"); 1121 } 1122 continue; 1123 } 1124 1125 // Avoid infinite recursion. 1126 if ((strcmp(envval, "fromenv") == 0) || 1127 (strcmp(envval, "tryfromenv") == 0)) { 1128 error_flags_[flagname] = (string(kError) + "infinite recursion on " + 1129 "environment flag '" + envval + "'\n"); 1130 continue; 1131 } 1132 1133 msg += ProcessSingleOptionLocked(flag, envval, set_mode); 1134 } 1135 return msg; 1136 } 1137 1138 string CommandLineFlagParser::ProcessSingleOptionLocked( 1139 CommandLineFlag* flag, const char* value, FlagSettingMode set_mode) { 1140 string msg; 1141 if (value && !registry_->SetFlagLocked(flag, value, set_mode, &msg)) { 1142 error_flags_[flag->name()] = msg; 1143 return ""; 1144 } 1145 1146 // The recursive flags, --flagfile and --fromenv and --tryfromenv, 1147 // must be dealt with as soon as they're seen. They will emit 1148 // messages of their own. 1149 if (strcmp(flag->name(), "flagfile") == 0) { 1150 msg += ProcessFlagfileLocked(FLAGS_flagfile, set_mode); 1151 1152 } else if (strcmp(flag->name(), "fromenv") == 0) { 1153 // last arg indicates envval-not-found is fatal (unlike in --tryfromenv) 1154 msg += ProcessFromenvLocked(FLAGS_fromenv, set_mode, true); 1155 1156 } else if (strcmp(flag->name(), "tryfromenv") == 0) { 1157 msg += ProcessFromenvLocked(FLAGS_tryfromenv, set_mode, false); 1158 } 1159 1160 return msg; 1161 } 1162 1163 void CommandLineFlagParser::ValidateAllFlags() { 1164 FlagRegistryLock frl(registry_); 1165 for (FlagRegistry::FlagConstIterator i = registry_->flags_.begin(); 1166 i != registry_->flags_.end(); ++i) { 1167 if (!i->second->ValidateCurrent()) { 1168 // only set a message if one isn't already there. (If there's 1169 // an error message, our job is done, even if it's not exactly 1170 // the same error.) 1171 if (error_flags_[i->second->name()].empty()) 1172 error_flags_[i->second->name()] = 1173 string(kError) + "--" + i->second->name() + 1174 " must be set on the commandline" 1175 " (default value fails validation)\n"; 1176 } 1177 } 1178 } 1179 1180 bool CommandLineFlagParser::ReportErrors() { 1181 // error_flags_ indicates errors we saw while parsing. 1182 // But we ignore undefined-names if ok'ed by --undef_ok 1183 if (!FLAGS_undefok.empty()) { 1184 vector<string> flaglist; 1185 ParseFlagList(FLAGS_undefok.c_str(), &flaglist); 1186 for (size_t i = 0; i < flaglist.size(); ++i) { 1187 // We also deal with --no<flag>, in case the flagname was boolean 1188 const string no_version = string("no") + flaglist[i]; 1189 if (undefined_names_.find(flaglist[i]) != undefined_names_.end()) { 1190 error_flags_[flaglist[i]] = ""; // clear the error message 1191 } else if (undefined_names_.find(no_version) != undefined_names_.end()) { 1192 error_flags_[no_version] = ""; 1193 } 1194 } 1195 } 1196 // Likewise, if they decided to allow reparsing, all undefined-names 1197 // are ok; we just silently ignore them now, and hope that a future 1198 // parse will pick them up somehow. 1199 if (allow_command_line_reparsing) { 1200 for (map<string, string>::const_iterator it = undefined_names_.begin(); 1201 it != undefined_names_.end(); ++it) 1202 error_flags_[it->first] = ""; // clear the error message 1203 } 1204 1205 bool found_error = false; 1206 string error_message; 1207 for (map<string, string>::const_iterator it = error_flags_.begin(); 1208 it != error_flags_.end(); ++it) { 1209 if (!it->second.empty()) { 1210 error_message.append(it->second.data(), it->second.size()); 1211 found_error = true; 1212 } 1213 } 1214 if (found_error) 1215 ReportError(DO_NOT_DIE, "%s", error_message.c_str()); 1216 return found_error; 1217 } 1218 1219 string CommandLineFlagParser::ProcessOptionsFromStringLocked( 1220 const string& contentdata, FlagSettingMode set_mode) { 1221 string retval; 1222 const char* flagfile_contents = contentdata.c_str(); 1223 bool flags_are_relevant = true; // set to false when filenames don't match 1224 bool in_filename_section = false; 1225 1226 const char* line_end = flagfile_contents; 1227 // We read this file a line at a time. 1228 for (; line_end; flagfile_contents = line_end + 1) { 1229 while (*flagfile_contents && isspace(*flagfile_contents)) 1230 ++flagfile_contents; 1231 line_end = strchr(flagfile_contents, '\n'); 1232 size_t len = line_end ? static_cast<size_t>(line_end - flagfile_contents) 1233 : strlen(flagfile_contents); 1234 string line(flagfile_contents, len); 1235 1236 // Each line can be one of four things: 1237 // 1) A comment line -- we skip it 1238 // 2) An empty line -- we skip it 1239 // 3) A list of filenames -- starts a new filenames+flags section 1240 // 4) A --flag=value line -- apply if previous filenames match 1241 if (line.empty() || line[0] == '#') { 1242 // comment or empty line; just ignore 1243 1244 } else if (line[0] == '-') { // flag 1245 in_filename_section = false; // instead, it was a flag-line 1246 if (!flags_are_relevant) // skip this flag; applies to someone else 1247 continue; 1248 1249 const char* name_and_val = line.c_str() + 1; // skip the leading - 1250 if (*name_and_val == '-') 1251 name_and_val++; // skip second - too 1252 string key; 1253 const char* value; 1254 string error_message; 1255 CommandLineFlag* flag = registry_->SplitArgumentLocked(name_and_val, 1256 &key, &value, 1257 &error_message); 1258 // By API, errors parsing flagfile lines are silently ignored. 1259 if (flag == NULL) { 1260 // "WARNING: flagname '" + key + "' not found\n" 1261 } else if (value == NULL) { 1262 // "WARNING: flagname '" + key + "' missing a value\n" 1263 } else { 1264 retval += ProcessSingleOptionLocked(flag, value, set_mode); 1265 } 1266 1267 } else { // a filename! 1268 if (!in_filename_section) { // start over: assume filenames don't match 1269 in_filename_section = true; 1270 flags_are_relevant = false; 1271 } 1272 1273 // Split the line up at spaces into glob-patterns 1274 const char* space = line.c_str(); // just has to be non-NULL 1275 for (const char* word = line.c_str(); *space; word = space+1) { 1276 if (flags_are_relevant) // we can stop as soon as we match 1277 break; 1278 space = strchr(word, ' '); 1279 if (space == NULL) 1280 space = word + strlen(word); 1281 const string glob(word, space - word); 1282 // We try matching both against the full argv0 and basename(argv0) 1283 #ifdef HAVE_FNMATCH_H 1284 if (fnmatch(glob.c_str(), 1285 ProgramInvocationName(), 1286 FNM_PATHNAME) == 0 || 1287 fnmatch(glob.c_str(), 1288 ProgramInvocationShortName(), 1289 FNM_PATHNAME) == 0) { 1290 #else // !HAVE_FNMATCH_H 1291 if ((glob == ProgramInvocationName()) || 1292 (glob == ProgramInvocationShortName())) { 1293 #endif // HAVE_FNMATCH_H 1294 flags_are_relevant = true; 1295 } 1296 } 1297 } 1298 } 1299 return retval; 1300 } 1301 1302 // -------------------------------------------------------------------- 1303 // GetFromEnv() 1304 // AddFlagValidator() 1305 // These are helper functions for routines like BoolFromEnv() and 1306 // RegisterFlagValidator, defined below. They're defined here so 1307 // they can live in the unnamed namespace (which makes friendship 1308 // declarations for these classes possible). 1309 // -------------------------------------------------------------------- 1310 1311 template<typename T> 1312 T GetFromEnv(const char *varname, const char* type, T dflt) { 1313 const char* const valstr = getenv(varname); 1314 if (!valstr) 1315 return dflt; 1316 FlagValue ifv(new T, type); 1317 if (!ifv.ParseFrom(valstr)) 1318 ReportError(DIE, "ERROR: error parsing env variable '%s' with value '%s'\n", 1319 varname, valstr); 1320 return OTHER_VALUE_AS(ifv, T); 1321 } 1322 1323 bool AddFlagValidator(const void* flag_ptr, ValidateFnProto validate_fn_proto) { 1324 // We want a lock around this routine, in case two threads try to 1325 // add a validator (hopefully the same one!) at once. We could use 1326 // our own thread, but we need to loook at the registry anyway, so 1327 // we just steal that one. 1328 FlagRegistry* const registry = FlagRegistry::GlobalRegistry(); 1329 FlagRegistryLock frl(registry); 1330 // First, find the flag whose current-flag storage is 'flag'. 1331 // This is the CommandLineFlag whose current_->value_buffer_ == flag 1332 CommandLineFlag* flag = registry->FindFlagViaPtrLocked(flag_ptr); 1333 if (!flag) { 1334 // WARNING << "Ignoring RegisterValidateFunction() for flag pointer " 1335 // << flag_ptr << ": no flag found at that address"; 1336 return false; 1337 } else if (validate_fn_proto == flag->validate_function()) { 1338 return true; // ok to register the same function over and over again 1339 } else if (validate_fn_proto != NULL && flag->validate_function() != NULL) { 1340 // WARNING << "Ignoring RegisterValidateFunction() for flag '" 1341 // << flag->name() << "': validate-fn already registered"; 1342 return false; 1343 } else { 1344 flag->validate_fn_proto_ = validate_fn_proto; 1345 return true; 1346 } 1347 } 1348 1349 } // end unnamed namespaces 1350 1351 1352 // Now define the functions that are exported via the .h file 1353 1354 // -------------------------------------------------------------------- 1355 // FlagRegisterer 1356 // This class exists merely to have a global constructor (the 1357 // kind that runs before main(), that goes an initializes each 1358 // flag that's been declared. Note that it's very important we 1359 // don't have a destructor that deletes flag_, because that would 1360 // cause us to delete current_storage/defvalue_storage as well, 1361 // which can cause a crash if anything tries to access the flag 1362 // values in a global destructor. 1363 // -------------------------------------------------------------------- 1364 1365 // TODO(csilvers): When we're ready to have this error be a fatal one, 1366 // change this to give a compilation error (via COMPILE_ASSERT(false)). 1367 bool FlagsTypeWarn(const char *name) { 1368 cerr << "Flag " << name << " is of type bool, but its default" 1369 << " value is not a boolean. NOTE: This will soon be a" 1370 << " compilations error!"; 1371 return false; 1372 } 1373 1374 FlagRegisterer::FlagRegisterer(const char* name, const char* type, 1375 const char* help, const char* filename, 1376 void* current_storage, void* defvalue_storage) { 1377 if (help == NULL) 1378 help = ""; 1379 // FlagValue expects the type-name to not include any namespace 1380 // components, so we get rid of those, if any. 1381 if (strchr(type, ':')) 1382 type = strrchr(type, ':') + 1; 1383 FlagValue* current = new FlagValue(current_storage, type); 1384 FlagValue* defvalue = new FlagValue(defvalue_storage, type); 1385 // Importantly, flag_ will never be deleted, so storage is always good. 1386 CommandLineFlag* flag = new CommandLineFlag(name, help, filename, 1387 current, defvalue); 1388 FlagRegistry::GlobalRegistry()->RegisterFlag(flag); // default registry 1389 } 1390 1391 // -------------------------------------------------------------------- 1392 // GetAllFlags() 1393 // The main way the FlagRegistry class exposes its data. This 1394 // returns, as strings, all the info about all the flags in 1395 // the main registry, sorted first by filename they are defined 1396 // in, and then by flagname. 1397 // -------------------------------------------------------------------- 1398 1399 struct FilenameFlagnameCmp { 1400 bool operator()(const CommandLineFlagInfo& a, 1401 const CommandLineFlagInfo& b) const { 1402 int cmp = strcmp(a.filename.c_str(), b.filename.c_str()); 1403 if (cmp == 0) 1404 cmp = strcmp(a.name.c_str(), b.name.c_str()); // secondary sort key 1405 return cmp < 0; 1406 } 1407 }; 1408 1409 void GetAllFlags(vector<CommandLineFlagInfo>* OUTPUT) { 1410 FlagRegistry* const registry = FlagRegistry::GlobalRegistry(); 1411 registry->Lock(); 1412 for (FlagRegistry::FlagConstIterator i = registry->flags_.begin(); 1413 i != registry->flags_.end(); ++i) { 1414 CommandLineFlagInfo fi; 1415 i->second->FillCommandLineFlagInfo(&fi); 1416 OUTPUT->push_back(fi); 1417 } 1418 registry->Unlock(); 1419 // Now sort the flags, first by filename they occur in, then alphabetically 1420 sort(OUTPUT->begin(), OUTPUT->end(), FilenameFlagnameCmp()); 1421 } 1422 1423 // -------------------------------------------------------------------- 1424 // SetArgv() 1425 // GetArgvs() 1426 // GetArgv() 1427 // GetArgv0() 1428 // ProgramInvocationName() 1429 // ProgramInvocationShortName() 1430 // SetUsageMessage() 1431 // ProgramUsage() 1432 // Functions to set and get argv. Typically the setter is called 1433 // by ParseCommandLineFlags. Also can get the ProgramUsage string, 1434 // set by SetUsageMessage. 1435 // -------------------------------------------------------------------- 1436 1437 // These values are not protected by a Mutex because they are normally 1438 // set only once during program startup. 1439 static const char* argv0 = "UNKNOWN"; // just the program name 1440 static const char* cmdline = ""; // the entire command-line 1441 static vector<string> argvs; 1442 static uint32 argv_sum = 0; 1443 static const char* program_usage = NULL; 1444 1445 void SetArgv(int argc, const char** argv) { 1446 static bool called_set_argv = false; 1447 if (called_set_argv) // we already have an argv for you 1448 return; 1449 1450 called_set_argv = true; 1451 1452 assert(argc > 0); // every program has at least a progname 1453 argv0 = strdup(argv[0]); // small memory leak, but fn only called once 1454 assert(argv0); 1455 1456 string cmdline_string; // easier than doing strcats 1457 for (int i = 0; i < argc; i++) { 1458 if (i != 0) { 1459 cmdline_string += " "; 1460 } 1461 cmdline_string += argv[i]; 1462 argvs.push_back(argv[i]); 1463 } 1464 cmdline = strdup(cmdline_string.c_str()); // another small memory leak 1465 assert(cmdline); 1466 1467 // Compute a simple sum of all the chars in argv 1468 for (const char* c = cmdline; *c; c++) 1469 argv_sum += *c; 1470 } 1471 1472 const vector<string>& GetArgvs() { return argvs; } 1473 const char* GetArgv() { return cmdline; } 1474 const char* GetArgv0() { return argv0; } 1475 uint32 GetArgvSum() { return argv_sum; } 1476 const char* ProgramInvocationName() { // like the GNU libc fn 1477 return GetArgv0(); 1478 } 1479 const char* ProgramInvocationShortName() { // like the GNU libc fn 1480 const char* slash = strrchr(argv0, '/'); 1481 #ifdef OS_WINDOWS 1482 if (!slash) slash = strrchr(argv0, '\\'); 1483 #endif 1484 return slash ? slash + 1 : argv0; 1485 } 1486 1487 void SetUsageMessage(const string& usage) { 1488 if (program_usage != NULL) 1489 ReportError(DIE, "ERROR: SetUsageMessage() called twice\n"); 1490 program_usage = strdup(usage.c_str()); // small memory leak 1491 } 1492 1493 const char* ProgramUsage() { 1494 if (program_usage) { 1495 return program_usage; 1496 } 1497 return "Warning: SetUsageMessage() never called"; 1498 } 1499 1500 // -------------------------------------------------------------------- 1501 // GetCommandLineOption() 1502 // GetCommandLineFlagInfo() 1503 // GetCommandLineFlagInfoOrDie() 1504 // SetCommandLineOption() 1505 // SetCommandLineOptionWithMode() 1506 // The programmatic way to set a flag's value, using a string 1507 // for its name rather than the variable itself (that is, 1508 // SetCommandLineOption("foo", x) rather than FLAGS_foo = x). 1509 // There's also a bit more flexibility here due to the various 1510 // set-modes, but typically these are used when you only have 1511 // that flag's name as a string, perhaps at runtime. 1512 // All of these work on the default, global registry. 1513 // For GetCommandLineOption, return false if no such flag 1514 // is known, true otherwise. We clear "value" if a suitable 1515 // flag is found. 1516 // -------------------------------------------------------------------- 1517 1518 1519 bool GetCommandLineOption(const char* name, string* value) { 1520 if (NULL == name) 1521 return false; 1522 assert(value); 1523 1524 FlagRegistry* const registry = FlagRegistry::GlobalRegistry(); 1525 FlagRegistryLock frl(registry); 1526 CommandLineFlag* flag = registry->FindFlagLocked(name); 1527 if (flag == NULL) { 1528 return false; 1529 } else { 1530 *value = flag->current_value(); 1531 return true; 1532 } 1533 } 1534 1535 bool GetCommandLineFlagInfo(const char* name, CommandLineFlagInfo* OUTPUT) { 1536 if (NULL == name) return false; 1537 FlagRegistry* const registry = FlagRegistry::GlobalRegistry(); 1538 FlagRegistryLock frl(registry); 1539 CommandLineFlag* flag = registry->FindFlagLocked(name); 1540 if (flag == NULL) { 1541 return false; 1542 } else { 1543 assert(OUTPUT); 1544 flag->FillCommandLineFlagInfo(OUTPUT); 1545 return true; 1546 } 1547 } 1548 1549 CommandLineFlagInfo GetCommandLineFlagInfoOrDie(const char* name) { 1550 CommandLineFlagInfo info; 1551 if (!GetCommandLineFlagInfo(name, &info)) { 1552 fprintf(stderr, "FATAL ERROR: flag name '%s' doesn't exit", name); 1553 commandlineflags_exitfunc(1); // almost certainly exit() 1554 } 1555 return info; 1556 } 1557 1558 string SetCommandLineOptionWithMode(const char* name, const char* value, 1559 FlagSettingMode set_mode) { 1560 string result; 1561 FlagRegistry* const registry = FlagRegistry::GlobalRegistry(); 1562 FlagRegistryLock frl(registry); 1563 CommandLineFlag* flag = registry->FindFlagLocked(name); 1564 if (flag) { 1565 CommandLineFlagParser parser(registry); 1566 result = parser.ProcessSingleOptionLocked(flag, value, set_mode); 1567 if (!result.empty()) { // in the error case, we've already logged 1568 // You could consider logging this change, if you wanted to know it: 1569 //fprintf(stderr, "%sFLAGS_%s\n", 1570 // (set_mode == SET_FLAGS_DEFAULT ? "default value of " : ""), 1571 // result); 1572 } 1573 } 1574 // The API of this function is that we return empty string on error 1575 return result; 1576 } 1577 1578 string SetCommandLineOption(const char* name, const char* value) { 1579 return SetCommandLineOptionWithMode(name, value, SET_FLAGS_VALUE); 1580 } 1581 1582 // -------------------------------------------------------------------- 1583 // FlagSaver 1584 // FlagSaverImpl 1585 // This class stores the states of all flags at construct time, 1586 // and restores all flags to that state at destruct time. 1587 // Its major implementation challenge is that it never modifies 1588 // pointers in the 'main' registry, so global FLAG_* vars always 1589 // point to the right place. 1590 // -------------------------------------------------------------------- 1591 1592 class FlagSaverImpl { 1593 public: 1594 // Constructs an empty FlagSaverImpl object. 1595 explicit FlagSaverImpl(FlagRegistry* main_registry) 1596 : main_registry_(main_registry) { } 1597 ~FlagSaverImpl() { 1598 // reclaim memory from each of our CommandLineFlags 1599 vector<CommandLineFlag*>::const_iterator it; 1600 for (it = backup_registry_.begin(); it != backup_registry_.end(); ++it) 1601 delete *it; 1602 } 1603 1604 // Saves the flag states from the flag registry into this object. 1605 // It's an error to call this more than once. 1606 // Must be called when the registry mutex is not held. 1607 void SaveFromRegistry() { 1608 FlagRegistryLock frl(main_registry_); 1609 assert(backup_registry_.empty()); // call only once! 1610 for (FlagRegistry::FlagConstIterator it = main_registry_->flags_.begin(); 1611 it != main_registry_->flags_.end(); 1612 ++it) { 1613 const CommandLineFlag* main = it->second; 1614 // Sets up all the const variables in backup correctly 1615 CommandLineFlag* backup = new CommandLineFlag( 1616 main->name(), main->help(), main->filename(), 1617 main->current_->New(), main->defvalue_->New()); 1618 // Sets up all the non-const variables in backup correctly 1619 backup->CopyFrom(*main); 1620 backup_registry_.push_back(backup); // add it to a convenient list 1621 } 1622 } 1623 1624 // Restores the saved flag states into the flag registry. We 1625 // assume no flags were added or deleted from the registry since 1626 // the SaveFromRegistry; if they were, that's trouble! Must be 1627 // called when the registry mutex is not held. 1628 void RestoreToRegistry() { 1629 FlagRegistryLock frl(main_registry_); 1630 vector<CommandLineFlag*>::const_iterator it; 1631 for (it = backup_registry_.begin(); it != backup_registry_.end(); ++it) { 1632 CommandLineFlag* main = main_registry_->FindFlagLocked((*it)->name()); 1633 if (main != NULL) { // if NULL, flag got deleted from registry(!) 1634 main->CopyFrom(**it); 1635 } 1636 } 1637 } 1638 1639 private: 1640 FlagRegistry* const main_registry_; 1641 vector<CommandLineFlag*> backup_registry_; 1642 1643 FlagSaverImpl(const FlagSaverImpl&); // no copying! 1644 void operator=(const FlagSaverImpl&); 1645 }; 1646 1647 FlagSaver::FlagSaver() 1648 : impl_(new FlagSaverImpl(FlagRegistry::GlobalRegistry())) { 1649 impl_->SaveFromRegistry(); 1650 } 1651 1652 FlagSaver::~FlagSaver() { 1653 impl_->RestoreToRegistry(); 1654 delete impl_; 1655 } 1656 1657 1658 // -------------------------------------------------------------------- 1659 // CommandlineFlagsIntoString() 1660 // ReadFlagsFromString() 1661 // AppendFlagsIntoFile() 1662 // ReadFromFlagsFile() 1663 // These are mostly-deprecated routines that stick the 1664 // commandline flags into a file/string and read them back 1665 // out again. I can see a use for CommandlineFlagsIntoString, 1666 // for creating a flagfile, but the rest don't seem that useful 1667 // -- some, I think, are a poor-man's attempt at FlagSaver -- 1668 // and are included only until we can delete them from callers. 1669 // Note they don't save --flagfile flags (though they do save 1670 // the result of having called the flagfile, of course). 1671 // -------------------------------------------------------------------- 1672 1673 static string TheseCommandlineFlagsIntoString( 1674 const vector<CommandLineFlagInfo>& flags) { 1675 vector<CommandLineFlagInfo>::const_iterator i; 1676 1677 size_t retval_space = 0; 1678 for (i = flags.begin(); i != flags.end(); ++i) { 1679 // An (over)estimate of how much space it will take to print this flag 1680 retval_space += i->name.length() + i->current_value.length() + 5; 1681 } 1682 1683 string retval; 1684 retval.reserve(retval_space); 1685 for (i = flags.begin(); i != flags.end(); ++i) { 1686 retval += "--"; 1687 retval += i->name; 1688 retval += "="; 1689 retval += i->current_value; 1690 retval += "\n"; 1691 } 1692 return retval; 1693 } 1694 1695 string CommandlineFlagsIntoString() { 1696 vector<CommandLineFlagInfo> sorted_flags; 1697 GetAllFlags(&sorted_flags); 1698 return TheseCommandlineFlagsIntoString(sorted_flags); 1699 } 1700 1701 bool ReadFlagsFromString(const string& flagfilecontents, 1702 const char* /*prog_name*/, // TODO(csilvers): nix this 1703 bool errors_are_fatal) { 1704 FlagRegistry* const registry = FlagRegistry::GlobalRegistry(); 1705 FlagSaverImpl saved_states(registry); 1706 saved_states.SaveFromRegistry(); 1707 1708 CommandLineFlagParser parser(registry); 1709 registry->Lock(); 1710 parser.ProcessOptionsFromStringLocked(flagfilecontents, SET_FLAGS_VALUE); 1711 registry->Unlock(); 1712 // Should we handle --help and such when reading flags from a string? Sure. 1713 HandleCommandLineHelpFlags(); 1714 if (parser.ReportErrors()) { 1715 // Error. Restore all global flags to their previous values. 1716 if (errors_are_fatal) 1717 commandlineflags_exitfunc(1); // almost certainly exit() 1718 saved_states.RestoreToRegistry(); 1719 return false; 1720 } 1721 return true; 1722 } 1723 1724 // TODO(csilvers): nix prog_name in favor of ProgramInvocationShortName() 1725 bool AppendFlagsIntoFile(const string& filename, const char *prog_name) { 1726 FILE *fp = fopen(filename.c_str(), "a"); 1727 if (!fp) { 1728 return false; 1729 } 1730 1731 if (prog_name) 1732 fprintf(fp, "%s\n", prog_name); 1733 1734 vector<CommandLineFlagInfo> flags; 1735 GetAllFlags(&flags); 1736 // But we don't want --flagfile, which leads to weird recursion issues 1737 vector<CommandLineFlagInfo>::iterator i; 1738 for (i = flags.begin(); i != flags.end(); ++i) { 1739 if (strcmp(i->name.c_str(), "flagfile") == 0) { 1740 flags.erase(i); 1741 break; 1742 } 1743 } 1744 fprintf(fp, "%s", TheseCommandlineFlagsIntoString(flags).c_str()); 1745 1746 fclose(fp); 1747 return true; 1748 } 1749 1750 bool ReadFromFlagsFile(const string& filename, const char* prog_name, 1751 bool errors_are_fatal) { 1752 return ReadFlagsFromString(ReadFileIntoString(filename.c_str()), 1753 prog_name, errors_are_fatal); 1754 } 1755 1756 1757 // -------------------------------------------------------------------- 1758 // BoolFromEnv() 1759 // Int32FromEnv() 1760 // Int64FromEnv() 1761 // Uint64FromEnv() 1762 // DoubleFromEnv() 1763 // StringFromEnv() 1764 // Reads the value from the environment and returns it. 1765 // We use an FlagValue to make the parsing easy. 1766 // Example usage: 1767 // DEFINE_bool(myflag, BoolFromEnv("MYFLAG_DEFAULT", false), "whatever"); 1768 // -------------------------------------------------------------------- 1769 1770 bool BoolFromEnv(const char *v, bool dflt) { 1771 return GetFromEnv(v, "bool", dflt); 1772 } 1773 int32 Int32FromEnv(const char *v, int32 dflt) { 1774 return GetFromEnv(v, "int32", dflt); 1775 } 1776 int64 Int64FromEnv(const char *v, int64 dflt) { 1777 return GetFromEnv(v, "int64", dflt); 1778 } 1779 uint64 Uint64FromEnv(const char *v, uint64 dflt) { 1780 return GetFromEnv(v, "uint64", dflt); 1781 } 1782 double DoubleFromEnv(const char *v, double dflt) { 1783 return GetFromEnv(v, "double", dflt); 1784 } 1785 const char *StringFromEnv(const char *varname, const char *dflt) { 1786 const char* const val = getenv(varname); 1787 return val ? val : dflt; 1788 } 1789 1790 1791 // -------------------------------------------------------------------- 1792 // RegisterFlagValidator() 1793 // RegisterFlagValidator() is the function that clients use to 1794 // 'decorate' a flag with a validation function. Once this is 1795 // done, every time the flag is set (including when the flag 1796 // is parsed from argv), the validator-function is called. 1797 // These functions return true if the validator was added 1798 // successfully, or false if not: the flag already has a validator, 1799 // (only one allowed per flag), the 1st arg isn't a flag, etc. 1800 // This function is not thread-safe. 1801 // -------------------------------------------------------------------- 1802 1803 bool RegisterFlagValidator(const bool* flag, 1804 bool (*validate_fn)(const char*, bool)) { 1805 return AddFlagValidator(flag, reinterpret_cast<ValidateFnProto>(validate_fn)); 1806 } 1807 bool RegisterFlagValidator(const int32* flag, 1808 bool (*validate_fn)(const char*, int32)) { 1809 return AddFlagValidator(flag, reinterpret_cast<ValidateFnProto>(validate_fn)); 1810 } 1811 bool RegisterFlagValidator(const int64* flag, 1812 bool (*validate_fn)(const char*, int64)) { 1813 return AddFlagValidator(flag, reinterpret_cast<ValidateFnProto>(validate_fn)); 1814 } 1815 bool RegisterFlagValidator(const uint64* flag, 1816 bool (*validate_fn)(const char*, uint64)) { 1817 return AddFlagValidator(flag, reinterpret_cast<ValidateFnProto>(validate_fn)); 1818 } 1819 bool RegisterFlagValidator(const double* flag, 1820 bool (*validate_fn)(const char*, double)) { 1821 return AddFlagValidator(flag, reinterpret_cast<ValidateFnProto>(validate_fn)); 1822 } 1823 bool RegisterFlagValidator(const string* flag, 1824 bool (*validate_fn)(const char*, const string&)) { 1825 return AddFlagValidator(flag, reinterpret_cast<ValidateFnProto>(validate_fn)); 1826 } 1827 1828 1829 // -------------------------------------------------------------------- 1830 // ParseCommandLineFlags() 1831 // ParseCommandLineNonHelpFlags() 1832 // HandleCommandLineHelpFlags() 1833 // This is the main function called from main(), to actually 1834 // parse the commandline. It modifies argc and argv as described 1835 // at the top of gflags.h. You can also divide this 1836 // function into two parts, if you want to do work between 1837 // the parsing of the flags and the printing of any help output. 1838 // -------------------------------------------------------------------- 1839 1840 static uint32 ParseCommandLineFlagsInternal(int* argc, char*** argv, 1841 bool remove_flags, bool do_report) { 1842 SetArgv(*argc, const_cast<const char**>(*argv)); // save it for later 1843 1844 FlagRegistry* const registry = FlagRegistry::GlobalRegistry(); 1845 CommandLineFlagParser parser(registry); 1846 1847 // When we parse the commandline flags, we'll handle --flagfile, 1848 // --tryfromenv, etc. as we see them (since flag-evaluation order 1849 // may be important). But sometimes apps set FLAGS_tryfromenv/etc. 1850 // manually before calling ParseCommandLineFlags. We want to evaluate 1851 // those too, as if they were the first flags on the commandline. 1852 registry->Lock(); 1853 parser.ProcessFlagfileLocked(FLAGS_flagfile, SET_FLAGS_VALUE); 1854 // Last arg here indicates whether flag-not-found is a fatal error or not 1855 parser.ProcessFromenvLocked(FLAGS_fromenv, SET_FLAGS_VALUE, true); 1856 parser.ProcessFromenvLocked(FLAGS_tryfromenv, SET_FLAGS_VALUE, false); 1857 registry->Unlock(); 1858 1859 // Now get the flags specified on the commandline 1860 const int r = parser.ParseNewCommandLineFlags(argc, argv, remove_flags); 1861 1862 if (do_report) 1863 HandleCommandLineHelpFlags(); // may cause us to exit on --help, etc. 1864 1865 // See if any of the unset flags fail their validation checks 1866 parser.ValidateAllFlags(); 1867 1868 if (parser.ReportErrors()) // may cause us to exit on illegal flags 1869 commandlineflags_exitfunc(1); // almost certainly exit() 1870 return r; 1871 } 1872 1873 uint32 ParseCommandLineFlags(int* argc, char*** argv, bool remove_flags) { 1874 return ParseCommandLineFlagsInternal(argc, argv, remove_flags, true); 1875 } 1876 1877 uint32 ParseCommandLineNonHelpFlags(int* argc, char*** argv, 1878 bool remove_flags) { 1879 return ParseCommandLineFlagsInternal(argc, argv, remove_flags, false); 1880 } 1881 1882 // -------------------------------------------------------------------- 1883 // AllowCommandLineReparsing() 1884 // ReparseCommandLineNonHelpFlags() 1885 // This is most useful for shared libraries. The idea is if 1886 // a flag is defined in a shared library that is dlopen'ed 1887 // sometime after main(), you can ParseCommandLineFlags before 1888 // the dlopen, then ReparseCommandLineNonHelpFlags() after the 1889 // dlopen, to get the new flags. But you have to explicitly 1890 // Allow() it; otherwise, you get the normal default behavior 1891 // of unrecognized flags calling a fatal error. 1892 // TODO(csilvers): this isn't used. Just delete it? 1893 // -------------------------------------------------------------------- 1894 1895 void AllowCommandLineReparsing() { 1896 allow_command_line_reparsing = true; 1897 } 1898 1899 uint32 ReparseCommandLineNonHelpFlags() { 1900 // We make a copy of argc and argv to pass in 1901 const vector<string>& argvs = GetArgvs(); 1902 int tmp_argc = static_cast<int>(argvs.size()); 1903 char** tmp_argv = new char* [tmp_argc + 1]; 1904 for (int i = 0; i < tmp_argc; ++i) 1905 tmp_argv[i] = strdup(argvs[i].c_str()); // TODO(csilvers): don't dup 1906 1907 const int retval = ParseCommandLineNonHelpFlags(&tmp_argc, &tmp_argv, false); 1908 1909 for (int i = 0; i < tmp_argc; ++i) 1910 free(tmp_argv[i]); 1911 delete[] tmp_argv; 1912 1913 return retval; 1914 } 1915 1916 } // namespace google 1917