Squashed 'third_party/gflags/' content from commit f0523f1

Change-Id: I7b525481a9f3ec3e48e6656735d06432c25dc3b9
git-subtree-dir: third_party/gflags
git-subtree-split: f0523f14a93cbb46fff9b318508aa1c6923158c7
diff --git a/src/gflags.cc b/src/gflags.cc
new file mode 100644
index 0000000..285050f
--- /dev/null
+++ b/src/gflags.cc
@@ -0,0 +1,1957 @@
+// Copyright (c) 1999, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ---
+// Revamped and reorganized by Craig Silverstein
+//
+// This file contains the implementation of all our command line flags
+// stuff.  Here's how everything fits together
+//
+// * FlagRegistry owns CommandLineFlags owns FlagValue.
+// * FlagSaver holds a FlagRegistry (saves it at construct time,
+//     restores it at destroy time).
+// * CommandLineFlagParser lives outside that hierarchy, but works on
+//     CommandLineFlags (modifying the FlagValues).
+// * Free functions like SetCommandLineOption() work via one of the
+//     above (such as CommandLineFlagParser).
+//
+// In more detail:
+//
+// -- The main classes that hold flag data:
+//
+// FlagValue holds the current value of a flag.  It's
+// pseudo-templatized: every operation on a FlagValue is typed.  It
+// also deals with storage-lifetime issues (so flag values don't go
+// away in a destructor), which is why we need a whole class to hold a
+// variable's value.
+//
+// CommandLineFlag is all the information about a single command-line
+// flag.  It has a FlagValue for the flag's current value, but also
+// the flag's name, type, etc.
+//
+// FlagRegistry is a collection of CommandLineFlags.  There's the
+// global registry, which is where flags defined via DEFINE_foo()
+// live.  But it's possible to define your own flag, manually, in a
+// different registry you create.  (In practice, multiple registries
+// are used only by FlagSaver).
+//
+// A given FlagValue is owned by exactly one CommandLineFlag.  A given
+// CommandLineFlag is owned by exactly one FlagRegistry.  FlagRegistry
+// has a lock; any operation that writes to a FlagValue or
+// CommandLineFlag owned by that registry must acquire the
+// FlagRegistry lock before doing so.
+//
+// --- Some other classes and free functions:
+//
+// CommandLineFlagInfo is a client-exposed version of CommandLineFlag.
+// Once it's instantiated, it has no dependencies or relationships
+// with any other part of this file.
+//
+// FlagRegisterer is the helper class used by the DEFINE_* macros to
+// allow work to be done at global initialization time.
+//
+// CommandLineFlagParser is the class that reads from the commandline
+// and instantiates flag values based on that.  It needs to poke into
+// the innards of the FlagValue->CommandLineFlag->FlagRegistry class
+// hierarchy to do that.  It's careful to acquire the FlagRegistry
+// lock before doing any writing or other non-const actions.
+//
+// GetCommandLineOption is just a hook into registry routines to
+// retrieve a flag based on its name.  SetCommandLineOption, on the
+// other hand, hooks into CommandLineFlagParser.  Other API functions
+// are, similarly, mostly hooks into the functionality described above.
+
+#include "config.h"
+#include "gflags.h"
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#if defined(HAVE_FNMATCH_H)
+#  include <fnmatch.h>
+#elif defined(HAVE_SHLWAPI_H)
+#  include <shlwapi.h>
+#endif
+#include <stdarg.h> // For va_list and related operations
+#include <stdio.h>
+#include <string.h>
+
+#include <algorithm>
+#include <map>
+#include <string>
+#include <utility>     // for pair<>
+#include <vector>
+
+#include "mutex.h"
+#include "util.h"
+
+// Special flags, type 1: the 'recursive' flags.  They set another flag's val.
+DEFINE_string(flagfile,   "", "load flags from file");
+DEFINE_string(fromenv,    "", "set flags from the environment"
+                              " [use 'export FLAGS_flag1=value']");
+DEFINE_string(tryfromenv, "", "set flags from the environment if present");
+
+// Special flags, type 2: the 'parsing' flags.  They modify how we parse.
+DEFINE_string(undefok, "", "comma-separated list of flag names that it is okay to specify "
+                           "on the command line even if the program does not define a flag "
+                           "with that name.  IMPORTANT: flags in this list that have "
+                           "arguments MUST use the flag=value format");
+
+namespace GFLAGS_NAMESPACE {
+
+using std::map;
+using std::pair;
+using std::sort;
+using std::string;
+using std::vector;
+
+// This is used by the unittest to test error-exit code
+void GFLAGS_DLL_DECL (*gflags_exitfunc)(int) = &exit;  // from stdlib.h
+
+
+// The help message indicating that the commandline flag has been
+// 'stripped'. It will not show up when doing "-help" and its
+// variants. The flag is stripped if STRIP_FLAG_HELP is set to 1
+// before including base/gflags.h
+
+// This is used by this file, and also in gflags_reporting.cc
+const char kStrippedFlagHelp[] = "\001\002\003\004 (unknown) \004\003\002\001";
+
+namespace {
+
+// There are also 'reporting' flags, in gflags_reporting.cc.
+
+static const char kError[] = "ERROR: ";
+
+// Indicates that undefined options are to be ignored.
+// Enables deferred processing of flags in dynamically loaded libraries.
+static bool allow_command_line_reparsing = false;
+
+static bool logging_is_probably_set_up = false;
+
+// This is a 'prototype' validate-function.  'Real' validate
+// functions, take a flag-value as an argument: ValidateFn(bool) or
+// ValidateFn(uint64).  However, for easier storage, we strip off this
+// argument and then restore it when actually calling the function on
+// a flag value.
+typedef bool (*ValidateFnProto)();
+
+// Whether we should die when reporting an error.
+enum DieWhenReporting { DIE, DO_NOT_DIE };
+
+// Report Error and exit if requested.
+static void ReportError(DieWhenReporting should_die, const char* format, ...) {
+  char error_message[255];
+  va_list ap;
+  va_start(ap, format);
+  vsnprintf(error_message, sizeof(error_message), format, ap);
+  va_end(ap);
+  fprintf(stderr, "%s", error_message);
+  fflush(stderr);   // should be unnecessary, but cygwin's rxvt buffers stderr
+  if (should_die == DIE) gflags_exitfunc(1);
+}
+
+
+// --------------------------------------------------------------------
+// FlagValue
+//    This represent the value a single flag might have.  The major
+//    functionality is to convert from a string to an object of a
+//    given type, and back.  Thread-compatible.
+// --------------------------------------------------------------------
+
+class CommandLineFlag;
+class FlagValue {
+ public:
+  FlagValue(void* valbuf, const char* type, bool transfer_ownership_of_value);
+  ~FlagValue();
+
+  bool ParseFrom(const char* spec);
+  string ToString() const;
+
+ private:
+  friend class CommandLineFlag;  // for many things, including Validate()
+  friend class GFLAGS_NAMESPACE::FlagSaverImpl;  // calls New()
+  friend class FlagRegistry;     // checks value_buffer_ for flags_by_ptr_ map
+  template <typename T> friend T GetFromEnv(const char*, const char*, T);
+  friend bool TryParseLocked(const CommandLineFlag*, FlagValue*,
+                             const char*, string*);  // for New(), CopyFrom()
+
+  enum ValueType {
+    FV_BOOL = 0,
+    FV_INT32 = 1,
+    FV_INT64 = 2,
+    FV_UINT64 = 3,
+    FV_DOUBLE = 4,
+    FV_STRING = 5,
+    FV_MAX_INDEX = 5,
+  };
+  const char* TypeName() const;
+  bool Equal(const FlagValue& x) const;
+  FlagValue* New() const;   // creates a new one with default value
+  void CopyFrom(const FlagValue& x);
+  int ValueSize() const;
+
+  // Calls the given validate-fn on value_buffer_, and returns
+  // whatever it returns.  But first casts validate_fn_proto to a
+  // function that takes our value as an argument (eg void
+  // (*validate_fn)(bool) for a bool flag).
+  bool Validate(const char* flagname, ValidateFnProto validate_fn_proto) const;
+
+  void* value_buffer_;          // points to the buffer holding our data
+  int8 type_;                   // how to interpret value_
+  bool owns_value_;         // whether to free value on destruct
+
+  FlagValue(const FlagValue&);   // no copying!
+  void operator=(const FlagValue&);
+};
+
+
+// This could be a templated method of FlagValue, but doing so adds to the
+// size of the .o.  Since there's no type-safety here anyway, macro is ok.
+#define VALUE_AS(type)  *reinterpret_cast<type*>(value_buffer_)
+#define OTHER_VALUE_AS(fv, type)  *reinterpret_cast<type*>(fv.value_buffer_)
+#define SET_VALUE_AS(type, value)  VALUE_AS(type) = (value)
+
+FlagValue::FlagValue(void* valbuf, const char* type,
+                     bool transfer_ownership_of_value)
+    : value_buffer_(valbuf),
+      owns_value_(transfer_ownership_of_value) {
+  for (type_ = 0; type_ <= FV_MAX_INDEX; ++type_) {
+    if (!strcmp(type, TypeName())) {
+      break;
+    }
+  }
+  assert(type_ <= FV_MAX_INDEX);  // Unknown typename
+}
+
+FlagValue::~FlagValue() {
+  if (!owns_value_) {
+    return;
+  }
+  switch (type_) {
+    case FV_BOOL: delete reinterpret_cast<bool*>(value_buffer_); break;
+    case FV_INT32: delete reinterpret_cast<int32*>(value_buffer_); break;
+    case FV_INT64: delete reinterpret_cast<int64*>(value_buffer_); break;
+    case FV_UINT64: delete reinterpret_cast<uint64*>(value_buffer_); break;
+    case FV_DOUBLE: delete reinterpret_cast<double*>(value_buffer_); break;
+    case FV_STRING: delete reinterpret_cast<string*>(value_buffer_); break;
+  }
+}
+
+bool FlagValue::ParseFrom(const char* value) {
+  if (type_ == FV_BOOL) {
+    const char* kTrue[] = { "1", "t", "true", "y", "yes" };
+    const char* kFalse[] = { "0", "f", "false", "n", "no" };
+    COMPILE_ASSERT(sizeof(kTrue) == sizeof(kFalse), true_false_equal);
+    for (size_t i = 0; i < sizeof(kTrue)/sizeof(*kTrue); ++i) {
+      if (strcasecmp(value, kTrue[i]) == 0) {
+        SET_VALUE_AS(bool, true);
+        return true;
+      } else if (strcasecmp(value, kFalse[i]) == 0) {
+        SET_VALUE_AS(bool, false);
+        return true;
+      }
+    }
+    return false;   // didn't match a legal input
+
+  } else if (type_ == FV_STRING) {
+    SET_VALUE_AS(string, value);
+    return true;
+  }
+
+  // OK, it's likely to be numeric, and we'll be using a strtoXXX method.
+  if (value[0] == '\0')   // empty-string is only allowed for string type.
+    return false;
+  char* end;
+  // Leading 0x puts us in base 16.  But leading 0 does not put us in base 8!
+  // It caused too many bugs when we had that behavior.
+  int base = 10;    // by default
+  if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X'))
+    base = 16;
+  errno = 0;
+
+  switch (type_) {
+    case FV_INT32: {
+      const int64 r = strto64(value, &end, base);
+      if (errno || end != value + strlen(value))  return false;  // bad parse
+      if (static_cast<int32>(r) != r)  // worked, but number out of range
+        return false;
+      SET_VALUE_AS(int32, static_cast<int32>(r));
+      return true;
+    }
+    case FV_INT64: {
+      const int64 r = strto64(value, &end, base);
+      if (errno || end != value + strlen(value))  return false;  // bad parse
+      SET_VALUE_AS(int64, r);
+      return true;
+    }
+    case FV_UINT64: {
+      while (*value == ' ') value++;
+      if (*value == '-') return false;  // negative number
+      const uint64 r = strtou64(value, &end, base);
+      if (errno || end != value + strlen(value))  return false;  // bad parse
+      SET_VALUE_AS(uint64, r);
+      return true;
+    }
+    case FV_DOUBLE: {
+      const double r = strtod(value, &end);
+      if (errno || end != value + strlen(value))  return false;  // bad parse
+      SET_VALUE_AS(double, r);
+      return true;
+    }
+    default: {
+      assert(false);  // unknown type
+      return false;
+    }
+  }
+}
+
+string FlagValue::ToString() const {
+  char intbuf[64];    // enough to hold even the biggest number
+  switch (type_) {
+    case FV_BOOL:
+      return VALUE_AS(bool) ? "true" : "false";
+    case FV_INT32:
+      snprintf(intbuf, sizeof(intbuf), "%" PRId32, VALUE_AS(int32));
+      return intbuf;
+    case FV_INT64:
+      snprintf(intbuf, sizeof(intbuf), "%" PRId64, VALUE_AS(int64));
+      return intbuf;
+    case FV_UINT64:
+      snprintf(intbuf, sizeof(intbuf), "%" PRIu64, VALUE_AS(uint64));
+      return intbuf;
+    case FV_DOUBLE:
+      snprintf(intbuf, sizeof(intbuf), "%.17g", VALUE_AS(double));
+      return intbuf;
+    case FV_STRING:
+      return VALUE_AS(string);
+    default:
+      assert(false);
+      return "";  // unknown type
+  }
+}
+
+bool FlagValue::Validate(const char* flagname,
+                         ValidateFnProto validate_fn_proto) const {
+  switch (type_) {
+    case FV_BOOL:
+      return reinterpret_cast<bool (*)(const char*, bool)>(
+          validate_fn_proto)(flagname, VALUE_AS(bool));
+    case FV_INT32:
+      return reinterpret_cast<bool (*)(const char*, int32)>(
+          validate_fn_proto)(flagname, VALUE_AS(int32));
+    case FV_INT64:
+      return reinterpret_cast<bool (*)(const char*, int64)>(
+          validate_fn_proto)(flagname, VALUE_AS(int64));
+    case FV_UINT64:
+      return reinterpret_cast<bool (*)(const char*, uint64)>(
+          validate_fn_proto)(flagname, VALUE_AS(uint64));
+    case FV_DOUBLE:
+      return reinterpret_cast<bool (*)(const char*, double)>(
+          validate_fn_proto)(flagname, VALUE_AS(double));
+    case FV_STRING:
+      return reinterpret_cast<bool (*)(const char*, const string&)>(
+          validate_fn_proto)(flagname, VALUE_AS(string));
+    default:
+      assert(false);  // unknown type
+      return false;
+  }
+}
+
+const char* FlagValue::TypeName() const {
+  static const char types[] =
+      "bool\0xx"
+      "int32\0x"
+      "int64\0x"
+      "uint64\0"
+      "double\0"
+      "string";
+  if (type_ > FV_MAX_INDEX) {
+    assert(false);
+    return "";
+  }
+  // Directly indexing the strings in the 'types' string, each of them is 7 bytes long.
+  return &types[type_ * 7];
+}
+
+bool FlagValue::Equal(const FlagValue& x) const {
+  if (type_ != x.type_)
+    return false;
+  switch (type_) {
+    case FV_BOOL:   return VALUE_AS(bool) == OTHER_VALUE_AS(x, bool);
+    case FV_INT32:  return VALUE_AS(int32) == OTHER_VALUE_AS(x, int32);
+    case FV_INT64:  return VALUE_AS(int64) == OTHER_VALUE_AS(x, int64);
+    case FV_UINT64: return VALUE_AS(uint64) == OTHER_VALUE_AS(x, uint64);
+    case FV_DOUBLE: return VALUE_AS(double) == OTHER_VALUE_AS(x, double);
+    case FV_STRING: return VALUE_AS(string) == OTHER_VALUE_AS(x, string);
+    default: assert(false); return false;  // unknown type
+  }
+}
+
+FlagValue* FlagValue::New() const {
+  const char *type = TypeName();
+  switch (type_) {
+    case FV_BOOL:   return new FlagValue(new bool(false), type, true);
+    case FV_INT32:  return new FlagValue(new int32(0), type, true);
+    case FV_INT64:  return new FlagValue(new int64(0), type, true);
+    case FV_UINT64: return new FlagValue(new uint64(0), type, true);
+    case FV_DOUBLE: return new FlagValue(new double(0.0), type, true);
+    case FV_STRING: return new FlagValue(new string, type, true);
+    default: assert(false); return NULL;  // unknown type
+  }
+}
+
+void FlagValue::CopyFrom(const FlagValue& x) {
+  assert(type_ == x.type_);
+  switch (type_) {
+    case FV_BOOL:   SET_VALUE_AS(bool, OTHER_VALUE_AS(x, bool));      break;
+    case FV_INT32:  SET_VALUE_AS(int32, OTHER_VALUE_AS(x, int32));    break;
+    case FV_INT64:  SET_VALUE_AS(int64, OTHER_VALUE_AS(x, int64));    break;
+    case FV_UINT64: SET_VALUE_AS(uint64, OTHER_VALUE_AS(x, uint64));  break;
+    case FV_DOUBLE: SET_VALUE_AS(double, OTHER_VALUE_AS(x, double));  break;
+    case FV_STRING: SET_VALUE_AS(string, OTHER_VALUE_AS(x, string));  break;
+    default: assert(false);  // unknown type
+  }
+}
+
+int FlagValue::ValueSize() const {
+  if (type_ > FV_MAX_INDEX) {
+    assert(false);  // unknown type
+    return 0;
+  }
+  static const uint8 valuesize[] = {
+    sizeof(bool),
+    sizeof(int32),
+    sizeof(int64),
+    sizeof(uint64),
+    sizeof(double),
+    sizeof(string),
+  };
+  return valuesize[type_];
+}
+
+// --------------------------------------------------------------------
+// CommandLineFlag
+//    This represents a single flag, including its name, description,
+//    default value, and current value.  Mostly this serves as a
+//    struct, though it also knows how to register itself.
+//       All CommandLineFlags are owned by a (exactly one)
+//    FlagRegistry.  If you wish to modify fields in this class, you
+//    should acquire the FlagRegistry lock for the registry that owns
+//    this flag.
+// --------------------------------------------------------------------
+
+class CommandLineFlag {
+ public:
+  // Note: we take over memory-ownership of current_val and default_val.
+  CommandLineFlag(const char* name, const char* help, const char* filename,
+                  FlagValue* current_val, FlagValue* default_val);
+  ~CommandLineFlag();
+
+  const char* name() const { return name_; }
+  const char* help() const { return help_; }
+  const char* filename() const { return file_; }
+  const char* CleanFileName() const;  // nixes irrelevant prefix such as homedir
+  string current_value() const { return current_->ToString(); }
+  string default_value() const { return defvalue_->ToString(); }
+  const char* type_name() const { return defvalue_->TypeName(); }
+  ValidateFnProto validate_function() const { return validate_fn_proto_; }
+  const void* flag_ptr() const { return current_->value_buffer_; }
+
+  void FillCommandLineFlagInfo(struct CommandLineFlagInfo* result);
+
+  // If validate_fn_proto_ is non-NULL, calls it on value, returns result.
+  bool Validate(const FlagValue& value) const;
+  bool ValidateCurrent() const { return Validate(*current_); }
+
+ private:
+  // for SetFlagLocked() and setting flags_by_ptr_
+  friend class FlagRegistry;
+  friend class GFLAGS_NAMESPACE::FlagSaverImpl;  // for cloning the values
+  // set validate_fn
+  friend bool AddFlagValidator(const void*, ValidateFnProto);
+
+  // This copies all the non-const members: modified, processed, defvalue, etc.
+  void CopyFrom(const CommandLineFlag& src);
+
+  void UpdateModifiedBit();
+
+  const char* const name_;     // Flag name
+  const char* const help_;     // Help message
+  const char* const file_;     // Which file did this come from?
+  bool modified_;              // Set after default assignment?
+  FlagValue* defvalue_;        // Default value for flag
+  FlagValue* current_;         // Current value for flag
+  // This is a casted, 'generic' version of validate_fn, which actually
+  // takes a flag-value as an arg (void (*validate_fn)(bool), say).
+  // When we pass this to current_->Validate(), it will cast it back to
+  // the proper type.  This may be NULL to mean we have no validate_fn.
+  ValidateFnProto validate_fn_proto_;
+
+  CommandLineFlag(const CommandLineFlag&);   // no copying!
+  void operator=(const CommandLineFlag&);
+};
+
+CommandLineFlag::CommandLineFlag(const char* name, const char* help,
+                                 const char* filename,
+                                 FlagValue* current_val, FlagValue* default_val)
+    : name_(name), help_(help), file_(filename), modified_(false),
+      defvalue_(default_val), current_(current_val), validate_fn_proto_(NULL) {
+}
+
+CommandLineFlag::~CommandLineFlag() {
+  delete current_;
+  delete defvalue_;
+}
+
+const char* CommandLineFlag::CleanFileName() const {
+  // Compute top-level directory & file that this appears in
+  // search full path backwards.
+  // Stop going backwards at kRootDir; and skip by the first slash.
+  static const char kRootDir[] = "";    // can set this to root directory,
+
+  if (sizeof(kRootDir)-1 == 0)          // no prefix to strip
+    return filename();
+
+  const char* clean_name = filename() + strlen(filename()) - 1;
+  while ( clean_name > filename() ) {
+    if (*clean_name == PATH_SEPARATOR) {
+      if (strncmp(clean_name, kRootDir, sizeof(kRootDir)-1) == 0) {
+        clean_name += sizeof(kRootDir)-1;    // past root-dir
+        break;
+      }
+    }
+    --clean_name;
+  }
+  while ( *clean_name == PATH_SEPARATOR ) ++clean_name;  // Skip any slashes
+  return clean_name;
+}
+
+void CommandLineFlag::FillCommandLineFlagInfo(
+    CommandLineFlagInfo* result) {
+  result->name = name();
+  result->type = type_name();
+  result->description = help();
+  result->current_value = current_value();
+  result->default_value = default_value();
+  result->filename = CleanFileName();
+  UpdateModifiedBit();
+  result->is_default = !modified_;
+  result->has_validator_fn = validate_function() != NULL;
+  result->flag_ptr = flag_ptr();
+}
+
+void CommandLineFlag::UpdateModifiedBit() {
+  // Update the "modified" bit in case somebody bypassed the
+  // Flags API and wrote directly through the FLAGS_name variable.
+  if (!modified_ && !current_->Equal(*defvalue_)) {
+    modified_ = true;
+  }
+}
+
+void CommandLineFlag::CopyFrom(const CommandLineFlag& src) {
+  // Note we only copy the non-const members; others are fixed at construct time
+  if (modified_ != src.modified_) modified_ = src.modified_;
+  if (!current_->Equal(*src.current_)) current_->CopyFrom(*src.current_);
+  if (!defvalue_->Equal(*src.defvalue_)) defvalue_->CopyFrom(*src.defvalue_);
+  if (validate_fn_proto_ != src.validate_fn_proto_)
+    validate_fn_proto_ = src.validate_fn_proto_;
+}
+
+bool CommandLineFlag::Validate(const FlagValue& value) const {
+
+  if (validate_function() == NULL)
+    return true;
+  else
+    return value.Validate(name(), validate_function());
+}
+
+
+// --------------------------------------------------------------------
+// FlagRegistry
+//    A FlagRegistry singleton object holds all flag objects indexed
+//    by their names so that if you know a flag's name (as a C
+//    string), you can access or set it.  If the function is named
+//    FooLocked(), you must own the registry lock before calling
+//    the function; otherwise, you should *not* hold the lock, and
+//    the function will acquire it itself if needed.
+// --------------------------------------------------------------------
+
+struct StringCmp {  // Used by the FlagRegistry map class to compare char*'s
+  bool operator() (const char* s1, const char* s2) const {
+    return (strcmp(s1, s2) < 0);
+  }
+};
+
+
+class FlagRegistry {
+ public:
+  FlagRegistry() {
+  }
+  ~FlagRegistry() {
+    // Not using STLDeleteElements as that resides in util and this
+    // class is base.
+    for (FlagMap::iterator p = flags_.begin(), e = flags_.end(); p != e; ++p) {
+      CommandLineFlag* flag = p->second;
+      delete flag;
+    }
+  }
+
+  static void DeleteGlobalRegistry() {
+    delete global_registry_;
+    global_registry_ = NULL;
+  }
+
+  // Store a flag in this registry.  Takes ownership of the given pointer.
+  void RegisterFlag(CommandLineFlag* flag);
+
+  void Lock() { lock_.Lock(); }
+  void Unlock() { lock_.Unlock(); }
+
+  // Returns the flag object for the specified name, or NULL if not found.
+  CommandLineFlag* FindFlagLocked(const char* name);
+
+  // Returns the flag object whose current-value is stored at flag_ptr.
+  // That is, for whom current_->value_buffer_ == flag_ptr
+  CommandLineFlag* FindFlagViaPtrLocked(const void* flag_ptr);
+
+  // A fancier form of FindFlag that works correctly if name is of the
+  // form flag=value.  In that case, we set key to point to flag, and
+  // modify v to point to the value (if present), and return the flag
+  // with the given name.  If the flag does not exist, returns NULL
+  // and sets error_message.
+  CommandLineFlag* SplitArgumentLocked(const char* argument,
+                                       string* key, const char** v,
+                                       string* error_message);
+
+  // Set the value of a flag.  If the flag was successfully set to
+  // value, set msg to indicate the new flag-value, and return true.
+  // Otherwise, set msg to indicate the error, leave flag unchanged,
+  // and return false.  msg can be NULL.
+  bool SetFlagLocked(CommandLineFlag* flag, const char* value,
+                     FlagSettingMode set_mode, string* msg);
+
+  static FlagRegistry* GlobalRegistry();   // returns a singleton registry
+
+ private:
+  friend class GFLAGS_NAMESPACE::FlagSaverImpl;  // reads all the flags in order to copy them
+  friend class CommandLineFlagParser;    // for ValidateAllFlags
+  friend void GFLAGS_NAMESPACE::GetAllFlags(vector<CommandLineFlagInfo>*);
+
+  // The map from name to flag, for FindFlagLocked().
+  typedef map<const char*, CommandLineFlag*, StringCmp> FlagMap;
+  typedef FlagMap::iterator FlagIterator;
+  typedef FlagMap::const_iterator FlagConstIterator;
+  FlagMap flags_;
+
+  // The map from current-value pointer to flag, fo FindFlagViaPtrLocked().
+  typedef map<const void*, CommandLineFlag*> FlagPtrMap;
+  FlagPtrMap flags_by_ptr_;
+
+  static FlagRegistry* global_registry_;   // a singleton registry
+
+  Mutex lock_;
+  static Mutex global_registry_lock_;
+
+  static void InitGlobalRegistry();
+
+  // Disallow
+  FlagRegistry(const FlagRegistry&);
+  FlagRegistry& operator=(const FlagRegistry&);
+};
+
+class FlagRegistryLock {
+ public:
+  explicit FlagRegistryLock(FlagRegistry* fr) : fr_(fr) { fr_->Lock(); }
+  ~FlagRegistryLock() { fr_->Unlock(); }
+ private:
+  FlagRegistry *const fr_;
+};
+
+
+void FlagRegistry::RegisterFlag(CommandLineFlag* flag) {
+  Lock();
+  pair<FlagIterator, bool> ins =
+    flags_.insert(pair<const char*, CommandLineFlag*>(flag->name(), flag));
+  if (ins.second == false) {   // means the name was already in the map
+    if (strcmp(ins.first->second->filename(), flag->filename()) != 0) {
+      ReportError(DIE, "ERROR: flag '%s' was defined more than once "
+                  "(in files '%s' and '%s').\n",
+                  flag->name(),
+                  ins.first->second->filename(),
+                  flag->filename());
+    } else {
+      ReportError(DIE, "ERROR: something wrong with flag '%s' in file '%s'.  "
+                  "One possibility: file '%s' is being linked both statically "
+                  "and dynamically into this executable.\n",
+                  flag->name(),
+                  flag->filename(), flag->filename());
+    }
+  }
+  // Also add to the flags_by_ptr_ map.
+  flags_by_ptr_[flag->current_->value_buffer_] = flag;
+  Unlock();
+}
+
+CommandLineFlag* FlagRegistry::FindFlagLocked(const char* name) {
+  FlagConstIterator i = flags_.find(name);
+  if (i == flags_.end()) {
+    return NULL;
+  } else {
+    return i->second;
+  }
+}
+
+CommandLineFlag* FlagRegistry::FindFlagViaPtrLocked(const void* flag_ptr) {
+  FlagPtrMap::const_iterator i = flags_by_ptr_.find(flag_ptr);
+  if (i == flags_by_ptr_.end()) {
+    return NULL;
+  } else {
+    return i->second;
+  }
+}
+
+CommandLineFlag* FlagRegistry::SplitArgumentLocked(const char* arg,
+                                                   string* key,
+                                                   const char** v,
+                                                   string* error_message) {
+  // Find the flag object for this option
+  const char* flag_name;
+  const char* value = strchr(arg, '=');
+  if (value == NULL) {
+    key->assign(arg);
+    *v = NULL;
+  } else {
+    // Strip out the "=value" portion from arg
+    key->assign(arg, value-arg);
+    *v = ++value;    // advance past the '='
+  }
+  flag_name = key->c_str();
+
+  CommandLineFlag* flag = FindFlagLocked(flag_name);
+
+  if (flag == NULL) {
+    // If we can't find the flag-name, then we should return an error.
+    // The one exception is if 1) the flag-name is 'nox', 2) there
+    // exists a flag named 'x', and 3) 'x' is a boolean flag.
+    // In that case, we want to return flag 'x'.
+    if (!(flag_name[0] == 'n' && flag_name[1] == 'o')) {
+      // flag-name is not 'nox', so we're not in the exception case.
+      *error_message = StringPrintf("%sunknown command line flag '%s'\n",
+                                    kError, key->c_str());
+      return NULL;
+    }
+    flag = FindFlagLocked(flag_name+2);
+    if (flag == NULL) {
+      // No flag named 'x' exists, so we're not in the exception case.
+      *error_message = StringPrintf("%sunknown command line flag '%s'\n",
+                                    kError, key->c_str());
+      return NULL;
+    }
+    if (strcmp(flag->type_name(), "bool") != 0) {
+      // 'x' exists but is not boolean, so we're not in the exception case.
+      *error_message = StringPrintf(
+          "%sboolean value (%s) specified for %s command line flag\n",
+          kError, key->c_str(), flag->type_name());
+      return NULL;
+    }
+    // We're in the exception case!
+    // Make up a fake value to replace the "no" we stripped out
+    key->assign(flag_name+2);   // the name without the "no"
+    *v = "0";
+  }
+
+  // Assign a value if this is a boolean flag
+  if (*v == NULL && strcmp(flag->type_name(), "bool") == 0) {
+    *v = "1";    // the --nox case was already handled, so this is the --x case
+  }
+
+  return flag;
+}
+
+bool TryParseLocked(const CommandLineFlag* flag, FlagValue* flag_value,
+                    const char* value, string* msg) {
+  // Use tenative_value, not flag_value, until we know value is valid.
+  FlagValue* tentative_value = flag_value->New();
+  if (!tentative_value->ParseFrom(value)) {
+    if (msg) {
+      StringAppendF(msg,
+                    "%sillegal value '%s' specified for %s flag '%s'\n",
+                    kError, value,
+                    flag->type_name(), flag->name());
+    }
+    delete tentative_value;
+    return false;
+  } else if (!flag->Validate(*tentative_value)) {
+    if (msg) {
+      StringAppendF(msg,
+          "%sfailed validation of new value '%s' for flag '%s'\n",
+          kError, tentative_value->ToString().c_str(),
+          flag->name());
+    }
+    delete tentative_value;
+    return false;
+  } else {
+    flag_value->CopyFrom(*tentative_value);
+    if (msg) {
+      StringAppendF(msg, "%s set to %s\n",
+                    flag->name(), flag_value->ToString().c_str());
+    }
+    delete tentative_value;
+    return true;
+  }
+}
+
+bool FlagRegistry::SetFlagLocked(CommandLineFlag* flag,
+                                 const char* value,
+                                 FlagSettingMode set_mode,
+                                 string* msg) {
+  flag->UpdateModifiedBit();
+  switch (set_mode) {
+    case SET_FLAGS_VALUE: {
+      // set or modify the flag's value
+      if (!TryParseLocked(flag, flag->current_, value, msg))
+        return false;
+      flag->modified_ = true;
+      break;
+    }
+    case SET_FLAG_IF_DEFAULT: {
+      // set the flag's value, but only if it hasn't been set by someone else
+      if (!flag->modified_) {
+        if (!TryParseLocked(flag, flag->current_, value, msg))
+          return false;
+        flag->modified_ = true;
+      } else {
+        *msg = StringPrintf("%s set to %s",
+                            flag->name(), flag->current_value().c_str());
+      }
+      break;
+    }
+    case SET_FLAGS_DEFAULT: {
+      // modify the flag's default-value
+      if (!TryParseLocked(flag, flag->defvalue_, value, msg))
+        return false;
+      if (!flag->modified_) {
+        // Need to set both defvalue *and* current, in this case
+        TryParseLocked(flag, flag->current_, value, NULL);
+      }
+      break;
+    }
+    default: {
+      // unknown set_mode
+      assert(false);
+      return false;
+    }
+  }
+
+  return true;
+}
+
+// Get the singleton FlagRegistry object
+FlagRegistry* FlagRegistry::global_registry_ = NULL;
+Mutex FlagRegistry::global_registry_lock_(Mutex::LINKER_INITIALIZED);
+
+FlagRegistry* FlagRegistry::GlobalRegistry() {
+  MutexLock acquire_lock(&global_registry_lock_);
+  if (!global_registry_) {
+    global_registry_ = new FlagRegistry;
+  }
+  return global_registry_;
+}
+
+// --------------------------------------------------------------------
+// CommandLineFlagParser
+//    Parsing is done in two stages.  In the first, we go through
+//    argv.  For every flag-like arg we can make sense of, we parse
+//    it and set the appropriate FLAGS_* variable.  For every flag-
+//    like arg we can't make sense of, we store it in a vector,
+//    along with an explanation of the trouble.  In stage 2, we
+//    handle the 'reporting' flags like --help and --mpm_version.
+//    (This is via a call to HandleCommandLineHelpFlags(), in
+//    gflags_reporting.cc.)
+//    An optional stage 3 prints out the error messages.
+//       This is a bit of a simplification.  For instance, --flagfile
+//    is handled as soon as it's seen in stage 1, not in stage 2.
+// --------------------------------------------------------------------
+
+class CommandLineFlagParser {
+ public:
+  // The argument is the flag-registry to register the parsed flags in
+  explicit CommandLineFlagParser(FlagRegistry* reg) : registry_(reg) {}
+  ~CommandLineFlagParser() {}
+
+  // Stage 1: Every time this is called, it reads all flags in argv.
+  // However, it ignores all flags that have been successfully set
+  // before.  Typically this is only called once, so this 'reparsing'
+  // behavior isn't important.  It can be useful when trying to
+  // reparse after loading a dll, though.
+  uint32 ParseNewCommandLineFlags(int* argc, char*** argv, bool remove_flags);
+
+  // Stage 2: print reporting info and exit, if requested.
+  // In gflags_reporting.cc:HandleCommandLineHelpFlags().
+
+  // Stage 3: validate all the commandline flags that have validators
+  // registered.
+  void ValidateAllFlags();
+
+  // Stage 4: report any errors and return true if any were found.
+  bool ReportErrors();
+
+  // Set a particular command line option.  "newval" is a string
+  // describing the new value that the option has been set to.  If
+  // option_name does not specify a valid option name, or value is not
+  // a valid value for option_name, newval is empty.  Does recursive
+  // processing for --flagfile and --fromenv.  Returns the new value
+  // if everything went ok, or empty-string if not.  (Actually, the
+  // return-string could hold many flag/value pairs due to --flagfile.)
+  // NB: Must have called registry_->Lock() before calling this function.
+  string ProcessSingleOptionLocked(CommandLineFlag* flag,
+                                   const char* value,
+                                   FlagSettingMode set_mode);
+
+  // Set a whole batch of command line options as specified by contentdata,
+  // which is in flagfile format (and probably has been read from a flagfile).
+  // Returns the new value if everything went ok, or empty-string if
+  // not.  (Actually, the return-string could hold many flag/value
+  // pairs due to --flagfile.)
+  // NB: Must have called registry_->Lock() before calling this function.
+  string ProcessOptionsFromStringLocked(const string& contentdata,
+                                        FlagSettingMode set_mode);
+
+  // These are the 'recursive' flags, defined at the top of this file.
+  // Whenever we see these flags on the commandline, we must take action.
+  // These are called by ProcessSingleOptionLocked and, similarly, return
+  // new values if everything went ok, or the empty-string if not.
+  string ProcessFlagfileLocked(const string& flagval, FlagSettingMode set_mode);
+  // diff fromenv/tryfromenv
+  string ProcessFromenvLocked(const string& flagval, FlagSettingMode set_mode,
+                              bool errors_are_fatal);
+
+ private:
+  FlagRegistry* const registry_;
+  map<string, string> error_flags_;      // map from name to error message
+  // This could be a set<string>, but we reuse the map to minimize the .o size
+  map<string, string> undefined_names_;  // --[flag] name was not registered
+};
+
+
+// Parse a list of (comma-separated) flags.
+static void ParseFlagList(const char* value, vector<string>* flags) {
+  for (const char *p = value; p && *p; value = p) {
+    p = strchr(value, ',');
+    size_t len;
+    if (p) {
+      len = p - value;
+      p++;
+    } else {
+      len = strlen(value);
+    }
+
+    if (len == 0)
+      ReportError(DIE, "ERROR: empty flaglist entry\n");
+    if (value[0] == '-')
+      ReportError(DIE, "ERROR: flag \"%*s\" begins with '-'\n", len, value);
+
+    flags->push_back(string(value, len));
+  }
+}
+
+// Snarf an entire file into a C++ string.  This is just so that we
+// can do all the I/O in one place and not worry about it everywhere.
+// Plus, it's convenient to have the whole file contents at hand.
+// Adds a newline at the end of the file.
+#define PFATAL(s)  do { perror(s); gflags_exitfunc(1); } while (0)
+
+static string ReadFileIntoString(const char* filename) {
+  const int kBufSize = 8092;
+  char buffer[kBufSize];
+  string s;
+  FILE* fp;
+  if ((errno = SafeFOpen(&fp, filename, "r")) != 0) PFATAL(filename);
+  size_t n;
+  while ( (n=fread(buffer, 1, kBufSize, fp)) > 0 ) {
+    if (ferror(fp))  PFATAL(filename);
+    s.append(buffer, n);
+  }
+  fclose(fp);
+  return s;
+}
+
+uint32 CommandLineFlagParser::ParseNewCommandLineFlags(int* argc, char*** argv,
+                                                       bool remove_flags) {
+  const char *program_name = strrchr((*argv)[0], PATH_SEPARATOR);   // nix path
+  program_name = (program_name == NULL ? (*argv)[0] : program_name+1);
+
+  int first_nonopt = *argc;        // for non-options moved to the end
+
+  registry_->Lock();
+  for (int i = 1; i < first_nonopt; i++) {
+    char* arg = (*argv)[i];
+
+    // Like getopt(), we permute non-option flags to be at the end.
+    if (arg[0] != '-' ||           // must be a program argument
+        (arg[0] == '-' && arg[1] == '\0')) {  // "-" is an argument, not a flag
+      memmove((*argv) + i, (*argv) + i+1, (*argc - (i+1)) * sizeof((*argv)[i]));
+      (*argv)[*argc-1] = arg;      // we go last
+      first_nonopt--;              // we've been pushed onto the stack
+      i--;                         // to undo the i++ in the loop
+      continue;
+    }
+
+    if (arg[0] == '-') arg++;      // allow leading '-'
+    if (arg[0] == '-') arg++;      // or leading '--'
+
+    // -- alone means what it does for GNU: stop options parsing
+    if (*arg == '\0') {
+      first_nonopt = i+1;
+      break;
+    }
+
+    // Find the flag object for this option
+    string key;
+    const char* value;
+    string error_message;
+    CommandLineFlag* flag = registry_->SplitArgumentLocked(arg, &key, &value,
+                                                           &error_message);
+    if (flag == NULL) {
+      undefined_names_[key] = "";    // value isn't actually used
+      error_flags_[key] = error_message;
+      continue;
+    }
+
+    if (value == NULL) {
+      // Boolean options are always assigned a value by SplitArgumentLocked()
+      assert(strcmp(flag->type_name(), "bool") != 0);
+      if (i+1 >= first_nonopt) {
+        // This flag needs a value, but there is nothing available
+        error_flags_[key] = (string(kError) + "flag '" + (*argv)[i] + "'"
+                             + " is missing its argument");
+        if (flag->help() && flag->help()[0] > '\001') {
+          // Be useful in case we have a non-stripped description.
+          error_flags_[key] += string("; flag description: ") + flag->help();
+        }
+        error_flags_[key] += "\n";
+        break;    // we treat this as an unrecoverable error
+      } else {
+        value = (*argv)[++i];                   // read next arg for value
+
+        // Heuristic to detect the case where someone treats a string arg
+        // like a bool:
+        // --my_string_var --foo=bar
+        // We look for a flag of string type, whose value begins with a
+        // dash, and where the flag-name and value are separated by a
+        // space rather than an '='.
+        // To avoid false positives, we also require the word "true"
+        // or "false" in the help string.  Without this, a valid usage
+        // "-lat -30.5" would trigger the warning.  The common cases we
+        // want to solve talk about true and false as values.
+        if (value[0] == '-'
+            && strcmp(flag->type_name(), "string") == 0
+            && (strstr(flag->help(), "true")
+                || strstr(flag->help(), "false"))) {
+          LOG(WARNING) << "Did you really mean to set flag '"
+                       << flag->name() << "' to the value '"
+                       << value << "'?";
+        }
+      }
+    }
+
+    // TODO(csilvers): only set a flag if we hadn't set it before here
+    ProcessSingleOptionLocked(flag, value, SET_FLAGS_VALUE);
+  }
+  registry_->Unlock();
+
+  if (remove_flags) {   // Fix up argc and argv by removing command line flags
+    (*argv)[first_nonopt-1] = (*argv)[0];
+    (*argv) += (first_nonopt-1);
+    (*argc) -= (first_nonopt-1);
+    first_nonopt = 1;   // because we still don't count argv[0]
+  }
+
+  logging_is_probably_set_up = true;   // because we've parsed --logdir, etc.
+
+  return first_nonopt;
+}
+
+string CommandLineFlagParser::ProcessFlagfileLocked(const string& flagval,
+                                                    FlagSettingMode set_mode) {
+  if (flagval.empty())
+    return "";
+
+  string msg;
+  vector<string> filename_list;
+  ParseFlagList(flagval.c_str(), &filename_list);  // take a list of filenames
+  for (size_t i = 0; i < filename_list.size(); ++i) {
+    const char* file = filename_list[i].c_str();
+    msg += ProcessOptionsFromStringLocked(ReadFileIntoString(file), set_mode);
+  }
+  return msg;
+}
+
+string CommandLineFlagParser::ProcessFromenvLocked(const string& flagval,
+                                                   FlagSettingMode set_mode,
+                                                   bool errors_are_fatal) {
+  if (flagval.empty())
+    return "";
+
+  string msg;
+  vector<string> flaglist;
+  ParseFlagList(flagval.c_str(), &flaglist);
+
+  for (size_t i = 0; i < flaglist.size(); ++i) {
+    const char* flagname = flaglist[i].c_str();
+    CommandLineFlag* flag = registry_->FindFlagLocked(flagname);
+    if (flag == NULL) {
+      error_flags_[flagname] =
+          StringPrintf("%sunknown command line flag '%s' "
+                       "(via --fromenv or --tryfromenv)\n",
+                       kError, flagname);
+      undefined_names_[flagname] = "";
+      continue;
+    }
+
+    const string envname = string("FLAGS_") + string(flagname);
+	string envval;
+	if (!SafeGetEnv(envname.c_str(), envval)) {
+      if (errors_are_fatal) {
+        error_flags_[flagname] = (string(kError) + envname +
+                                  " not found in environment\n");
+      }
+      continue;
+    }
+
+    // Avoid infinite recursion.
+    if (envval == "fromenv" || envval == "tryfromenv") {
+      error_flags_[flagname] =
+          StringPrintf("%sinfinite recursion on environment flag '%s'\n",
+                       kError, envval.c_str());
+      continue;
+    }
+
+    msg += ProcessSingleOptionLocked(flag, envval.c_str(), set_mode);
+  }
+  return msg;
+}
+
+string CommandLineFlagParser::ProcessSingleOptionLocked(
+    CommandLineFlag* flag, const char* value, FlagSettingMode set_mode) {
+  string msg;
+  if (value && !registry_->SetFlagLocked(flag, value, set_mode, &msg)) {
+    error_flags_[flag->name()] = msg;
+    return "";
+  }
+
+  // The recursive flags, --flagfile and --fromenv and --tryfromenv,
+  // must be dealt with as soon as they're seen.  They will emit
+  // messages of their own.
+  if (strcmp(flag->name(), "flagfile") == 0) {
+    msg += ProcessFlagfileLocked(FLAGS_flagfile, set_mode);
+
+  } else if (strcmp(flag->name(), "fromenv") == 0) {
+    // last arg indicates envval-not-found is fatal (unlike in --tryfromenv)
+    msg += ProcessFromenvLocked(FLAGS_fromenv, set_mode, true);
+
+  } else if (strcmp(flag->name(), "tryfromenv") == 0) {
+    msg += ProcessFromenvLocked(FLAGS_tryfromenv, set_mode, false);
+  }
+
+  return msg;
+}
+
+void CommandLineFlagParser::ValidateAllFlags() {
+  FlagRegistryLock frl(registry_);
+  for (FlagRegistry::FlagConstIterator i = registry_->flags_.begin();
+       i != registry_->flags_.end(); ++i) {
+    if (!i->second->ValidateCurrent()) {
+      // only set a message if one isn't already there.  (If there's
+      // an error message, our job is done, even if it's not exactly
+      // the same error.)
+      if (error_flags_[i->second->name()].empty())
+        error_flags_[i->second->name()] =
+            string(kError) + "--" + i->second->name() +
+            " must be set on the commandline"
+            " (default value fails validation)\n";
+    }
+  }
+}
+
+bool CommandLineFlagParser::ReportErrors() {
+  // error_flags_ indicates errors we saw while parsing.
+  // But we ignore undefined-names if ok'ed by --undef_ok
+  if (!FLAGS_undefok.empty()) {
+    vector<string> flaglist;
+    ParseFlagList(FLAGS_undefok.c_str(), &flaglist);
+    for (size_t i = 0; i < flaglist.size(); ++i) {
+      // We also deal with --no<flag>, in case the flagname was boolean
+      const string no_version = string("no") + flaglist[i];
+      if (undefined_names_.find(flaglist[i]) != undefined_names_.end()) {
+        error_flags_[flaglist[i]] = "";    // clear the error message
+      } else if (undefined_names_.find(no_version) != undefined_names_.end()) {
+        error_flags_[no_version] = "";
+      }
+    }
+  }
+  // Likewise, if they decided to allow reparsing, all undefined-names
+  // are ok; we just silently ignore them now, and hope that a future
+  // parse will pick them up somehow.
+  if (allow_command_line_reparsing) {
+    for (map<string, string>::const_iterator it = undefined_names_.begin();
+         it != undefined_names_.end();  ++it)
+      error_flags_[it->first] = "";      // clear the error message
+  }
+
+  bool found_error = false;
+  string error_message;
+  for (map<string, string>::const_iterator it = error_flags_.begin();
+       it != error_flags_.end(); ++it) {
+    if (!it->second.empty()) {
+      error_message.append(it->second.data(), it->second.size());
+      found_error = true;
+    }
+  }
+  if (found_error)
+    ReportError(DO_NOT_DIE, "%s", error_message.c_str());
+  return found_error;
+}
+
+string CommandLineFlagParser::ProcessOptionsFromStringLocked(
+    const string& contentdata, FlagSettingMode set_mode) {
+  string retval;
+  const char* flagfile_contents = contentdata.c_str();
+  bool flags_are_relevant = true;   // set to false when filenames don't match
+  bool in_filename_section = false;
+
+  const char* line_end = flagfile_contents;
+  // We read this file a line at a time.
+  for (; line_end; flagfile_contents = line_end + 1) {
+    while (*flagfile_contents && isspace(*flagfile_contents))
+      ++flagfile_contents;
+    line_end = strchr(flagfile_contents, '\n');
+    size_t len = line_end ? line_end - flagfile_contents
+                          : strlen(flagfile_contents);
+    string line(flagfile_contents, len);
+
+    // Each line can be one of four things:
+    // 1) A comment line -- we skip it
+    // 2) An empty line -- we skip it
+    // 3) A list of filenames -- starts a new filenames+flags section
+    // 4) A --flag=value line -- apply if previous filenames match
+    if (line.empty() || line[0] == '#') {
+      // comment or empty line; just ignore
+
+    } else if (line[0] == '-') {    // flag
+      in_filename_section = false;  // instead, it was a flag-line
+      if (!flags_are_relevant)      // skip this flag; applies to someone else
+        continue;
+
+      const char* name_and_val = line.c_str() + 1;    // skip the leading -
+      if (*name_and_val == '-')
+        name_and_val++;                               // skip second - too
+      string key;
+      const char* value;
+      string error_message;
+      CommandLineFlag* flag = registry_->SplitArgumentLocked(name_and_val,
+                                                             &key, &value,
+                                                             &error_message);
+      // By API, errors parsing flagfile lines are silently ignored.
+      if (flag == NULL) {
+        // "WARNING: flagname '" + key + "' not found\n"
+      } else if (value == NULL) {
+        // "WARNING: flagname '" + key + "' missing a value\n"
+      } else {
+        retval += ProcessSingleOptionLocked(flag, value, set_mode);
+      }
+
+    } else {                        // a filename!
+      if (!in_filename_section) {   // start over: assume filenames don't match
+        in_filename_section = true;
+        flags_are_relevant = false;
+      }
+
+      // Split the line up at spaces into glob-patterns
+      const char* space = line.c_str();   // just has to be non-NULL
+      for (const char* word = line.c_str(); *space; word = space+1) {
+        if (flags_are_relevant)     // we can stop as soon as we match
+          break;
+        space = strchr(word, ' ');
+        if (space == NULL)
+          space = word + strlen(word);
+        const string glob(word, space - word);
+        // We try matching both against the full argv0 and basename(argv0)
+        if (glob == ProgramInvocationName()       // small optimization
+            || glob == ProgramInvocationShortName()
+#if defined(HAVE_FNMATCH_H)
+            || fnmatch(glob.c_str(), ProgramInvocationName(),      FNM_PATHNAME) == 0
+            || fnmatch(glob.c_str(), ProgramInvocationShortName(), FNM_PATHNAME) == 0
+#elif defined(HAVE_SHLWAPI_H)
+            || PathMatchSpec(glob.c_str(), ProgramInvocationName())
+            || PathMatchSpec(glob.c_str(), ProgramInvocationShortName())
+#endif
+            ) {
+          flags_are_relevant = true;
+        }
+      }
+    }
+  }
+  return retval;
+}
+
+// --------------------------------------------------------------------
+// GetFromEnv()
+// AddFlagValidator()
+//    These are helper functions for routines like BoolFromEnv() and
+//    RegisterFlagValidator, defined below.  They're defined here so
+//    they can live in the unnamed namespace (which makes friendship
+//    declarations for these classes possible).
+// --------------------------------------------------------------------
+
+template<typename T>
+T GetFromEnv(const char *varname, const char* type, T dflt) {
+  std::string valstr;
+  if (SafeGetEnv(varname, valstr)) {
+    FlagValue ifv(new T, type, true);
+    if (!ifv.ParseFrom(valstr.c_str())) {
+      ReportError(DIE, "ERROR: error parsing env variable '%s' with value '%s'\n",
+                  varname, valstr.c_str());
+	}
+    return OTHER_VALUE_AS(ifv, T);
+  } else return dflt;
+}
+
+bool AddFlagValidator(const void* flag_ptr, ValidateFnProto validate_fn_proto) {
+  // We want a lock around this routine, in case two threads try to
+  // add a validator (hopefully the same one!) at once.  We could use
+  // our own thread, but we need to loook at the registry anyway, so
+  // we just steal that one.
+  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
+  FlagRegistryLock frl(registry);
+  // First, find the flag whose current-flag storage is 'flag'.
+  // This is the CommandLineFlag whose current_->value_buffer_ == flag
+  CommandLineFlag* flag = registry->FindFlagViaPtrLocked(flag_ptr);
+  if (!flag) {
+    LOG(WARNING) << "Ignoring RegisterValidateFunction() for flag pointer "
+                 << flag_ptr << ": no flag found at that address";
+    return false;
+  } else if (validate_fn_proto == flag->validate_function()) {
+    return true;    // ok to register the same function over and over again
+  } else if (validate_fn_proto != NULL && flag->validate_function() != NULL) {
+    LOG(WARNING) << "Ignoring RegisterValidateFunction() for flag '"
+                 << flag->name() << "': validate-fn already registered";
+    return false;
+  } else {
+    flag->validate_fn_proto_ = validate_fn_proto;
+    return true;
+  }
+}
+
+}  // end unnamed namespaces
+
+
+// Now define the functions that are exported via the .h file
+
+// --------------------------------------------------------------------
+// FlagRegisterer
+//    This class exists merely to have a global constructor (the
+//    kind that runs before main(), that goes an initializes each
+//    flag that's been declared.  Note that it's very important we
+//    don't have a destructor that deletes flag_, because that would
+//    cause us to delete current_storage/defvalue_storage as well,
+//    which can cause a crash if anything tries to access the flag
+//    values in a global destructor.
+// --------------------------------------------------------------------
+
+FlagRegisterer::FlagRegisterer(const char* name, const char* type,
+                               const char* help, const char* filename,
+                               void* current_storage, void* defvalue_storage) {
+  if (help == NULL)
+    help = "";
+  // FlagValue expects the type-name to not include any namespace
+  // components, so we get rid of those, if any.
+  if (strchr(type, ':'))
+    type = strrchr(type, ':') + 1;
+  FlagValue* current = new FlagValue(current_storage, type, false);
+  FlagValue* defvalue = new FlagValue(defvalue_storage, type, false);
+  // Importantly, flag_ will never be deleted, so storage is always good.
+  CommandLineFlag* flag = new CommandLineFlag(name, help, filename,
+                                              current, defvalue);
+  FlagRegistry::GlobalRegistry()->RegisterFlag(flag);   // default registry
+}
+
+// --------------------------------------------------------------------
+// GetAllFlags()
+//    The main way the FlagRegistry class exposes its data.  This
+//    returns, as strings, all the info about all the flags in
+//    the main registry, sorted first by filename they are defined
+//    in, and then by flagname.
+// --------------------------------------------------------------------
+
+struct FilenameFlagnameCmp {
+  bool operator()(const CommandLineFlagInfo& a,
+                  const CommandLineFlagInfo& b) const {
+    int cmp = strcmp(a.filename.c_str(), b.filename.c_str());
+    if (cmp == 0)
+      cmp = strcmp(a.name.c_str(), b.name.c_str());  // secondary sort key
+    return cmp < 0;
+  }
+};
+
+void GetAllFlags(vector<CommandLineFlagInfo>* OUTPUT) {
+  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
+  registry->Lock();
+  for (FlagRegistry::FlagConstIterator i = registry->flags_.begin();
+       i != registry->flags_.end(); ++i) {
+    CommandLineFlagInfo fi;
+    i->second->FillCommandLineFlagInfo(&fi);
+    OUTPUT->push_back(fi);
+  }
+  registry->Unlock();
+  // Now sort the flags, first by filename they occur in, then alphabetically
+  sort(OUTPUT->begin(), OUTPUT->end(), FilenameFlagnameCmp());
+}
+
+// --------------------------------------------------------------------
+// SetArgv()
+// GetArgvs()
+// GetArgv()
+// GetArgv0()
+// ProgramInvocationName()
+// ProgramInvocationShortName()
+// SetUsageMessage()
+// ProgramUsage()
+//    Functions to set and get argv.  Typically the setter is called
+//    by ParseCommandLineFlags.  Also can get the ProgramUsage string,
+//    set by SetUsageMessage.
+// --------------------------------------------------------------------
+
+// These values are not protected by a Mutex because they are normally
+// set only once during program startup.
+static const char* argv0 = "UNKNOWN";      // just the program name
+static const char* cmdline = "";           // the entire command-line
+static vector<string> argvs;
+static uint32 argv_sum = 0;
+static const char* program_usage = NULL;
+
+void SetArgv(int argc, const char** argv) {
+  static bool called_set_argv = false;
+  if (called_set_argv)         // we already have an argv for you
+    return;
+
+  called_set_argv = true;
+
+  assert(argc > 0);            // every program has at least a progname
+  argv0 = strdup(argv[0]);     // small memory leak, but fn only called once
+  assert(argv0);
+
+  string cmdline_string;       // easier than doing strcats
+  for (int i = 0; i < argc; i++) {
+    if (i != 0) {
+      cmdline_string += " ";
+    }
+    cmdline_string += argv[i];
+    argvs.push_back(argv[i]);
+  }
+  cmdline = strdup(cmdline_string.c_str());  // another small memory leak
+  assert(cmdline);
+
+  // Compute a simple sum of all the chars in argv
+  for (const char* c = cmdline; *c; c++)
+    argv_sum += *c;
+}
+
+const vector<string>& GetArgvs() { return argvs; }
+const char* GetArgv()            { return cmdline; }
+const char* GetArgv0()           { return argv0; }
+uint32 GetArgvSum()              { return argv_sum; }
+const char* ProgramInvocationName() {             // like the GNU libc fn
+  return GetArgv0();
+}
+const char* ProgramInvocationShortName() {        // like the GNU libc fn
+  const char* slash = strrchr(argv0, '/');
+#ifdef OS_WINDOWS
+  if (!slash)  slash = strrchr(argv0, '\\');
+#endif
+  return slash ? slash + 1 : argv0;
+}
+
+void SetUsageMessage(const string& usage) {
+  if (program_usage != NULL)
+    ReportError(DIE, "ERROR: SetUsageMessage() called twice\n");
+  program_usage = strdup(usage.c_str());      // small memory leak
+}
+
+const char* ProgramUsage() {
+  if (program_usage) {
+    return program_usage;
+  }
+  return "Warning: SetUsageMessage() never called";
+}
+
+// --------------------------------------------------------------------
+// SetVersionString()
+// VersionString()
+// --------------------------------------------------------------------
+
+static const char* version_string = NULL;
+
+void SetVersionString(const string& version) {
+  if (version_string != NULL)
+    ReportError(DIE, "ERROR: SetVersionString() called twice\n");
+  version_string = strdup(version.c_str());   // small memory leak
+}
+
+const char* VersionString() {
+  return version_string ? version_string : "";
+}
+
+
+// --------------------------------------------------------------------
+// GetCommandLineOption()
+// GetCommandLineFlagInfo()
+// GetCommandLineFlagInfoOrDie()
+// SetCommandLineOption()
+// SetCommandLineOptionWithMode()
+//    The programmatic way to set a flag's value, using a string
+//    for its name rather than the variable itself (that is,
+//    SetCommandLineOption("foo", x) rather than FLAGS_foo = x).
+//    There's also a bit more flexibility here due to the various
+//    set-modes, but typically these are used when you only have
+//    that flag's name as a string, perhaps at runtime.
+//    All of these work on the default, global registry.
+//       For GetCommandLineOption, return false if no such flag
+//    is known, true otherwise.  We clear "value" if a suitable
+//    flag is found.
+// --------------------------------------------------------------------
+
+
+bool GetCommandLineOption(const char* name, string* value) {
+  if (NULL == name)
+    return false;
+  assert(value);
+
+  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
+  FlagRegistryLock frl(registry);
+  CommandLineFlag* flag = registry->FindFlagLocked(name);
+  if (flag == NULL) {
+    return false;
+  } else {
+    *value = flag->current_value();
+    return true;
+  }
+}
+
+bool GetCommandLineFlagInfo(const char* name, CommandLineFlagInfo* OUTPUT) {
+  if (NULL == name) return false;
+  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
+  FlagRegistryLock frl(registry);
+  CommandLineFlag* flag = registry->FindFlagLocked(name);
+  if (flag == NULL) {
+    return false;
+  } else {
+    assert(OUTPUT);
+    flag->FillCommandLineFlagInfo(OUTPUT);
+    return true;
+  }
+}
+
+CommandLineFlagInfo GetCommandLineFlagInfoOrDie(const char* name) {
+  CommandLineFlagInfo info;
+  if (!GetCommandLineFlagInfo(name, &info)) {
+    fprintf(stderr, "FATAL ERROR: flag name '%s' doesn't exist\n", name);
+    gflags_exitfunc(1);    // almost certainly gflags_exitfunc()
+  }
+  return info;
+}
+
+string SetCommandLineOptionWithMode(const char* name, const char* value,
+                                    FlagSettingMode set_mode) {
+  string result;
+  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
+  FlagRegistryLock frl(registry);
+  CommandLineFlag* flag = registry->FindFlagLocked(name);
+  if (flag) {
+    CommandLineFlagParser parser(registry);
+    result = parser.ProcessSingleOptionLocked(flag, value, set_mode);
+    if (!result.empty()) {   // in the error case, we've already logged
+      // Could consider logging this change
+    }
+  }
+  // The API of this function is that we return empty string on error
+  return result;
+}
+
+string SetCommandLineOption(const char* name, const char* value) {
+  return SetCommandLineOptionWithMode(name, value, SET_FLAGS_VALUE);
+}
+
+// --------------------------------------------------------------------
+// FlagSaver
+// FlagSaverImpl
+//    This class stores the states of all flags at construct time,
+//    and restores all flags to that state at destruct time.
+//    Its major implementation challenge is that it never modifies
+//    pointers in the 'main' registry, so global FLAG_* vars always
+//    point to the right place.
+// --------------------------------------------------------------------
+
+class FlagSaverImpl {
+ public:
+  // Constructs an empty FlagSaverImpl object.
+  explicit FlagSaverImpl(FlagRegistry* main_registry)
+      : main_registry_(main_registry) { }
+  ~FlagSaverImpl() {
+    // reclaim memory from each of our CommandLineFlags
+    vector<CommandLineFlag*>::const_iterator it;
+    for (it = backup_registry_.begin(); it != backup_registry_.end(); ++it)
+      delete *it;
+  }
+
+  // Saves the flag states from the flag registry into this object.
+  // It's an error to call this more than once.
+  // Must be called when the registry mutex is not held.
+  void SaveFromRegistry() {
+    FlagRegistryLock frl(main_registry_);
+    assert(backup_registry_.empty());   // call only once!
+    for (FlagRegistry::FlagConstIterator it = main_registry_->flags_.begin();
+         it != main_registry_->flags_.end();
+         ++it) {
+      const CommandLineFlag* main = it->second;
+      // Sets up all the const variables in backup correctly
+      CommandLineFlag* backup = new CommandLineFlag(
+          main->name(), main->help(), main->filename(),
+          main->current_->New(), main->defvalue_->New());
+      // Sets up all the non-const variables in backup correctly
+      backup->CopyFrom(*main);
+      backup_registry_.push_back(backup);   // add it to a convenient list
+    }
+  }
+
+  // Restores the saved flag states into the flag registry.  We
+  // assume no flags were added or deleted from the registry since
+  // the SaveFromRegistry; if they were, that's trouble!  Must be
+  // called when the registry mutex is not held.
+  void RestoreToRegistry() {
+    FlagRegistryLock frl(main_registry_);
+    vector<CommandLineFlag*>::const_iterator it;
+    for (it = backup_registry_.begin(); it != backup_registry_.end(); ++it) {
+      CommandLineFlag* main = main_registry_->FindFlagLocked((*it)->name());
+      if (main != NULL) {       // if NULL, flag got deleted from registry(!)
+        main->CopyFrom(**it);
+      }
+    }
+  }
+
+ private:
+  FlagRegistry* const main_registry_;
+  vector<CommandLineFlag*> backup_registry_;
+
+  FlagSaverImpl(const FlagSaverImpl&);  // no copying!
+  void operator=(const FlagSaverImpl&);
+};
+
+FlagSaver::FlagSaver()
+    : impl_(new FlagSaverImpl(FlagRegistry::GlobalRegistry())) {
+  impl_->SaveFromRegistry();
+}
+
+FlagSaver::~FlagSaver() {
+  impl_->RestoreToRegistry();
+  delete impl_;
+}
+
+
+// --------------------------------------------------------------------
+// CommandlineFlagsIntoString()
+// ReadFlagsFromString()
+// AppendFlagsIntoFile()
+// ReadFromFlagsFile()
+//    These are mostly-deprecated routines that stick the
+//    commandline flags into a file/string and read them back
+//    out again.  I can see a use for CommandlineFlagsIntoString,
+//    for creating a flagfile, but the rest don't seem that useful
+//    -- some, I think, are a poor-man's attempt at FlagSaver --
+//    and are included only until we can delete them from callers.
+//    Note they don't save --flagfile flags (though they do save
+//    the result of having called the flagfile, of course).
+// --------------------------------------------------------------------
+
+static string TheseCommandlineFlagsIntoString(
+    const vector<CommandLineFlagInfo>& flags) {
+  vector<CommandLineFlagInfo>::const_iterator i;
+
+  size_t retval_space = 0;
+  for (i = flags.begin(); i != flags.end(); ++i) {
+    // An (over)estimate of how much space it will take to print this flag
+    retval_space += i->name.length() + i->current_value.length() + 5;
+  }
+
+  string retval;
+  retval.reserve(retval_space);
+  for (i = flags.begin(); i != flags.end(); ++i) {
+    retval += "--";
+    retval += i->name;
+    retval += "=";
+    retval += i->current_value;
+    retval += "\n";
+  }
+  return retval;
+}
+
+string CommandlineFlagsIntoString() {
+  vector<CommandLineFlagInfo> sorted_flags;
+  GetAllFlags(&sorted_flags);
+  return TheseCommandlineFlagsIntoString(sorted_flags);
+}
+
+bool ReadFlagsFromString(const string& flagfilecontents,
+                         const char* /*prog_name*/,  // TODO(csilvers): nix this
+                         bool errors_are_fatal) {
+  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
+  FlagSaverImpl saved_states(registry);
+  saved_states.SaveFromRegistry();
+
+  CommandLineFlagParser parser(registry);
+  registry->Lock();
+  parser.ProcessOptionsFromStringLocked(flagfilecontents, SET_FLAGS_VALUE);
+  registry->Unlock();
+  // Should we handle --help and such when reading flags from a string?  Sure.
+  HandleCommandLineHelpFlags();
+  if (parser.ReportErrors()) {
+    // Error.  Restore all global flags to their previous values.
+    if (errors_are_fatal)
+      gflags_exitfunc(1);
+    saved_states.RestoreToRegistry();
+    return false;
+  }
+  return true;
+}
+
+// TODO(csilvers): nix prog_name in favor of ProgramInvocationShortName()
+bool AppendFlagsIntoFile(const string& filename, const char *prog_name) {
+  FILE *fp;
+  if (SafeFOpen(&fp, filename.c_str(), "a") != 0) {
+    return false;
+  }
+
+  if (prog_name)
+    fprintf(fp, "%s\n", prog_name);
+
+  vector<CommandLineFlagInfo> flags;
+  GetAllFlags(&flags);
+  // But we don't want --flagfile, which leads to weird recursion issues
+  vector<CommandLineFlagInfo>::iterator i;
+  for (i = flags.begin(); i != flags.end(); ++i) {
+    if (strcmp(i->name.c_str(), "flagfile") == 0) {
+      flags.erase(i);
+      break;
+    }
+  }
+  fprintf(fp, "%s", TheseCommandlineFlagsIntoString(flags).c_str());
+
+  fclose(fp);
+  return true;
+}
+
+bool ReadFromFlagsFile(const string& filename, const char* prog_name,
+                       bool errors_are_fatal) {
+  return ReadFlagsFromString(ReadFileIntoString(filename.c_str()),
+                             prog_name, errors_are_fatal);
+}
+
+
+// --------------------------------------------------------------------
+// BoolFromEnv()
+// Int32FromEnv()
+// Int64FromEnv()
+// Uint64FromEnv()
+// DoubleFromEnv()
+// StringFromEnv()
+//    Reads the value from the environment and returns it.
+//    We use an FlagValue to make the parsing easy.
+//    Example usage:
+//       DEFINE_bool(myflag, BoolFromEnv("MYFLAG_DEFAULT", false), "whatever");
+// --------------------------------------------------------------------
+
+bool BoolFromEnv(const char *v, bool dflt) {
+  return GetFromEnv(v, "bool", dflt);
+}
+int32 Int32FromEnv(const char *v, int32 dflt) {
+  return GetFromEnv(v, "int32", dflt);
+}
+int64 Int64FromEnv(const char *v, int64 dflt)    {
+  return GetFromEnv(v, "int64", dflt);
+}
+uint64 Uint64FromEnv(const char *v, uint64 dflt) {
+  return GetFromEnv(v, "uint64", dflt);
+}
+double DoubleFromEnv(const char *v, double dflt) {
+  return GetFromEnv(v, "double", dflt);
+}
+
+#ifdef _MSC_VER
+#  pragma warning(push)
+#  pragma warning(disable: 4996) // ignore getenv security warning
+#endif
+const char *StringFromEnv(const char *varname, const char *dflt) {
+  const char* const val = getenv(varname);
+  return val ? val : dflt;
+}
+#ifdef _MSC_VER
+#  pragma warning(pop)
+#endif
+
+
+// --------------------------------------------------------------------
+// RegisterFlagValidator()
+//    RegisterFlagValidator() is the function that clients use to
+//    'decorate' a flag with a validation function.  Once this is
+//    done, every time the flag is set (including when the flag
+//    is parsed from argv), the validator-function is called.
+//       These functions return true if the validator was added
+//    successfully, or false if not: the flag already has a validator,
+//    (only one allowed per flag), the 1st arg isn't a flag, etc.
+//       This function is not thread-safe.
+// --------------------------------------------------------------------
+
+bool RegisterFlagValidator(const bool* flag,
+                           bool (*validate_fn)(const char*, bool)) {
+  return AddFlagValidator(flag, reinterpret_cast<ValidateFnProto>(validate_fn));
+}
+bool RegisterFlagValidator(const int32* flag,
+                           bool (*validate_fn)(const char*, int32)) {
+  return AddFlagValidator(flag, reinterpret_cast<ValidateFnProto>(validate_fn));
+}
+bool RegisterFlagValidator(const int64* flag,
+                           bool (*validate_fn)(const char*, int64)) {
+  return AddFlagValidator(flag, reinterpret_cast<ValidateFnProto>(validate_fn));
+}
+bool RegisterFlagValidator(const uint64* flag,
+                           bool (*validate_fn)(const char*, uint64)) {
+  return AddFlagValidator(flag, reinterpret_cast<ValidateFnProto>(validate_fn));
+}
+bool RegisterFlagValidator(const double* flag,
+                           bool (*validate_fn)(const char*, double)) {
+  return AddFlagValidator(flag, reinterpret_cast<ValidateFnProto>(validate_fn));
+}
+bool RegisterFlagValidator(const string* flag,
+                           bool (*validate_fn)(const char*, const string&)) {
+  return AddFlagValidator(flag, reinterpret_cast<ValidateFnProto>(validate_fn));
+}
+
+
+// --------------------------------------------------------------------
+// ParseCommandLineFlags()
+// ParseCommandLineNonHelpFlags()
+// HandleCommandLineHelpFlags()
+//    This is the main function called from main(), to actually
+//    parse the commandline.  It modifies argc and argv as described
+//    at the top of gflags.h.  You can also divide this
+//    function into two parts, if you want to do work between
+//    the parsing of the flags and the printing of any help output.
+// --------------------------------------------------------------------
+
+static uint32 ParseCommandLineFlagsInternal(int* argc, char*** argv,
+                                            bool remove_flags, bool do_report) {
+  SetArgv(*argc, const_cast<const char**>(*argv));    // save it for later
+
+  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
+  CommandLineFlagParser parser(registry);
+
+  // When we parse the commandline flags, we'll handle --flagfile,
+  // --tryfromenv, etc. as we see them (since flag-evaluation order
+  // may be important).  But sometimes apps set FLAGS_tryfromenv/etc.
+  // manually before calling ParseCommandLineFlags.  We want to evaluate
+  // those too, as if they were the first flags on the commandline.
+  registry->Lock();
+  parser.ProcessFlagfileLocked(FLAGS_flagfile, SET_FLAGS_VALUE);
+  // Last arg here indicates whether flag-not-found is a fatal error or not
+  parser.ProcessFromenvLocked(FLAGS_fromenv, SET_FLAGS_VALUE, true);
+  parser.ProcessFromenvLocked(FLAGS_tryfromenv, SET_FLAGS_VALUE, false);
+  registry->Unlock();
+
+  // Now get the flags specified on the commandline
+  const int r = parser.ParseNewCommandLineFlags(argc, argv, remove_flags);
+
+  if (do_report)
+    HandleCommandLineHelpFlags();   // may cause us to exit on --help, etc.
+
+  // See if any of the unset flags fail their validation checks
+  parser.ValidateAllFlags();
+
+  if (parser.ReportErrors())        // may cause us to exit on illegal flags
+    gflags_exitfunc(1);
+  return r;
+}
+
+uint32 ParseCommandLineFlags(int* argc, char*** argv, bool remove_flags) {
+  return ParseCommandLineFlagsInternal(argc, argv, remove_flags, true);
+}
+
+uint32 ParseCommandLineNonHelpFlags(int* argc, char*** argv,
+                                    bool remove_flags) {
+  return ParseCommandLineFlagsInternal(argc, argv, remove_flags, false);
+}
+
+// --------------------------------------------------------------------
+// AllowCommandLineReparsing()
+// ReparseCommandLineNonHelpFlags()
+//    This is most useful for shared libraries.  The idea is if
+//    a flag is defined in a shared library that is dlopen'ed
+//    sometime after main(), you can ParseCommandLineFlags before
+//    the dlopen, then ReparseCommandLineNonHelpFlags() after the
+//    dlopen, to get the new flags.  But you have to explicitly
+//    Allow() it; otherwise, you get the normal default behavior
+//    of unrecognized flags calling a fatal error.
+// TODO(csilvers): this isn't used.  Just delete it?
+// --------------------------------------------------------------------
+
+void AllowCommandLineReparsing() {
+  allow_command_line_reparsing = true;
+}
+
+void ReparseCommandLineNonHelpFlags() {
+  // We make a copy of argc and argv to pass in
+  const vector<string>& argvs = GetArgvs();
+  int tmp_argc = static_cast<int>(argvs.size());
+  char** tmp_argv = new char* [tmp_argc + 1];
+  for (int i = 0; i < tmp_argc; ++i)
+    tmp_argv[i] = strdup(argvs[i].c_str());   // TODO(csilvers): don't dup
+
+  ParseCommandLineNonHelpFlags(&tmp_argc, &tmp_argv, false);
+
+  for (int i = 0; i < tmp_argc; ++i)
+    free(tmp_argv[i]);
+  delete[] tmp_argv;
+}
+
+void ShutDownCommandLineFlags() {
+  FlagRegistry::DeleteGlobalRegistry();
+}
+
+
+} // namespace GFLAGS_NAMESPACE