Squashed 'third_party/gflags/' changes from f0523f1..7e70988

7e70988 fix: PVS Studio warnings
754d332 fix: No extern template declaration for MSVC <12.0
82456f2 fix: Declare FlagRegisterer c’tor explicit template instanations as extern in header
3e2e349 fix: Declare FALGS_no##name variables as static
c0b1add fix: Import with GFLAGS_USE_TARGET_NAMESPACE=ON
f1ea012 fix: Import with or without gflags:: namespace
b0c4cd2 fix: Define both 'gflags' and 'gflags::gflags' alias targets
04c8ce7 fix: Indentation, use spaces instead of real tabs
d4a050d Merge pull request #247 from Mizux/master
48677f9 fix missing-field-initializers warnings on gcc
6e53655 Fix V728 excessive check
cad38c9 Set postfixes for generated libraries based on buildtype
2c49763 Fix build on some clang variants
660603a doc: Update documentation on how to use Bazel
518267d Remove installation guide's recommendation to use Bazel's bind().
f7228d7 Use CMake namespace gflags:: for export and alias target
8b39845 Remove uneeded enable_test()
9ab4d11 Add VERSION to project
e292e04 Use += for appends
6d1c363 Add Bazel-on-Windows support
7759264 repair wrong namespace problem
2334846 Removed unused functions.
60784b5 Remove using ::fLS::clstring;
57ceb0e enh: Move CMake defines to separate header, unused by Bazel
7d36353 Fix typo in BUILD
aa2d0f7 fix: Remove obsolete and unused CleanFileName code
4663c80 cmake: Add convenience uninstall target (#221)
46f73f8 Release v2.2.1
66d4386 enh: AppVeyor builds with different toolchains (copied from gtest project)
6348ea9 fix: Check HAVE_STDINT_H or HAVE_INTTYPES_H for older MSVC versions
3d5bc48 git: Ignore symbolic links created by Bazel build tool
74603f5 fix: Static code analyzer error regarding strncmp with empty kRootDir string
4a694e8 Use inttypes.h on VC++ 2013 and up
21c7bcd Fix CMake macro special variable usage (#216)
95ffb27 Fix static initialization order fiasco caused by global registry lock (#215)
80ebb42 Install dll's to correct path (#213)
652651b Fix statically linked gflags library with MSVC
9314597 Mark single argument constructors in mutex.h as explicit.
30dbc81 Changed include directory in bazel build
8935ef4 enh: Link to online documentation in README
20858a4 fix: Enable language C for older CMake versions when needed (#196)
ac6834e fix: Remove unused program_name variable
22ed2ce fix: Include utils by file instead of CMAKE_MODULE_PATH search
f8a0efe Release v2.2.0
2f336a2 doc: //external:gflags_nothreads Bazel target
c6b9377 git: Ignore builds/ subdirectory
84ab952 doc: Update use of gflags with Bazel documentation
b872d6b enh: Bazel BUILD, add WORKSPACE file (#192)
37c4c58 add: Bazel WORKSPACE file
37e2867 enh: Refactored Bazel BUILD rules
8f2c22a Revert "enh: Rename private sources, include public headers with rel path"
ea6144e enh: Rename private sources, include public headers with rel path
86d67a3 fix: Add -lpthread to link Bazel BUILD options (#189)
c94a60e enh: Configure and install pkg-config .pc file
3e7ef74 enh: Set GFLAGS_IS_A_DLL in INTERFACE_COMPILE_DEFINITIONS
1846983 fix: Ensure installation path uses forward slashes
3886da5 enh: Add option to add installation to CMake’s package registry
6c0ee00 fix: Copy missing IMPORTED_IMPLIB_<CONFIG> gflags target property
3064f63 enh: Avoid use of install(EXPORTS) FILE option
14c0e93 Convert dashes to underscores for unknown flags (#177)
cce68f0 Fix error messages to not truncate to 255 characters (#175)
f4eace1 fix: Validate modified flags only once (#173)
408061b fix make error for lacking namespace (#170)
7d31c02 Fix unsigned comparison error in gflags_reporting.cc (#168)
a69b254 Fix Windows linker errors and warnings. (#166)
15394d3 Add shared library build to the AppVeyor CI config. (#167)
e58e530 Remove filter for excluded tests from AppVeyor config. (#165)
435f949 test: Travis CI build static+shared in Release+Debug (#164)
22e4a53 fix: Run strip_flags_binary test only for release configurations (#163)
c713d2e test: Run AppVeyor build via cmake --build and run tests. (#162)
b16653e fix: Typo in gflags_strip_flags_test.cmake script
ec4b5da doc: Add AppVeyor status badge to README
f0be9c8 Add initial AppVeyor config. (#161)
78cab6c doc: Add Travis CI status badge to README
4667f41 Enable Travis CI for Linux and OSX builds (#160)
a5a1b28 Merge pull request #158 from dreamer-dead/use-type-name-enum
7ba9921 Fix wrong type comparison and outdated OfType() usage.
3051942 Fix indentation and remove outdated assert.
3c0ad4f Extract common code from FlagRegisterer to reduce size.
a1e461d Change template FlagValue::OfType() to Type() getter.
46ea10f Do not pass flag type as a char literal when registering a new flag.
fe57e5a Merge pull request #156 from dreamer-dead/fix-flag-value-typename
fa26638 Fix unittests expectations related to uint32.
5ef4c3c Fix uint32 type name.
2e4159f Merge pull request #155 from dreamer-dead/add-missing-reference
3e946c9 Add missing reference symbol to a function parameter.
546819b Merge pull request #152 from Liuchang0812/master
0c17f1e fix bug about LRLF
ac1a925 fix #151: Ubuntu package name in INSTALL instructions
d701cea Merge pull request #150 from LuminateWireless/fix-bazel-build
7ae23fd Add gendir to the include path so that building with bazel doesn't complain config.h can't be found.
8de80b9 Merge pull request #149 from hevy-CC4477/master
eff38cb fix test compilation
9353bca Merge pull request #147 from bazineta/master
81d8a92 Correct FV_MAX_INDEX
eaf0534 Support uint32 as flag type
74bcd20 Merge PR #137 with change of SOVERSION to <major>.<minor>
4534195 fix: Change SOVERSION to <major>.<minor> for 2.x release versions
5e30706 Merge pull request #143 from schuhschuh/fix-bazel-bulid-osx
687b2c5 fix #133: Use awk instead of sed which would require different options on OS X
5844199 Merge pull request #142 from schuhschuh/master
1c8285f mod: Update doc with new find_package COMPONENTS or subproject use
12d810d Merge pull request #141 from schuhschuh/master
389ef3f Merge branch 'master' of github.com:gflags/gflags
752c632 fix: Include order of config.h and gflags.h in unit test
f9e69b3 Merge pull request #140 from schuhschuh/enh-#117-gflags-subproject-support
7a21c16 cmake: Rename targets to gflags[_nothreads]_(static|shared), support find_package COMPONENTS
a4382e5 cmake: Require CMake 2.8.12 in NC tests
2de6bf3 cmake: Change CMake package configuration variable name prefix to GFLAGS_
91e16ee cmake: Add CMake variable to cache only when gflags is not a subproject
b686469 git: Add CMakeLists.txt.user Qt Creator configuration to ignore list
e50698c Merge pull request #139 from schuhschuh/master
18cb422 fix: Require CMake version 2.8.12 in test project
799e910 fix: Include private config.h in gflags_unittest.cc
abe4b10 fix: Package URLs
221f327 Revert "#136 Move test binaries to Testing/bin"
2a3454c fix: DLL import/export defines for unit tests, remove obsolete config_for_unittests.h
545e9df fix: Add missing include guards to gflags/config.h
6bd636c cmake: Clean up static library filename suffix code from PR #126
dd48d70 Merge pull request #126 from hevy-CC4477/master
9ef0d52 enh: Add usage of DEFINE_validator to test project
02f3189 #136 Move test binaries to Testing/bin
92865ce #51 #138 Use std::string instead const char * for global "constants"
8ac4bc4 fix: Pass std::string directly, no need for c_str() call
b90a325 properly export the .so minor version
3ae911f mod: Update doc
762f9cb #51 Call ShutDownCommandLineFlags for (manual) valgrind test
7a69001 #51 Use static StringFlagDestructor to destruct string objects allocated by placement new
3f968fc Merge pull request #133 from earhart/master
40b85b1 Add bazel support
f9fa305 Merge pull request #131 from sbc100/no_threads
b572a72 Define NO_THREADS in when building without threads
03bebcb Merge pull request #129 from Nazg-Gul/master
366e9d3 Fix some compilation warnings with MSVC 2015
4f100cb Resolve several missing declarations warnings
d78b00d handle generation of dynamic and static library on windows.
9db8289 #125 Fix unused typedef/variable warning for static assertion
4e61c45 #124 Remove using namespace from mutex.h

Change-Id: I61f02738b43ce97c825345375af77a44231165f4
git-subtree-dir: third_party/gflags
git-subtree-split: 7e709881881c2663569cd49a93e5c8d9228d868e
diff --git a/src/gflags.cc b/src/gflags.cc
index 285050f..e0171fe 100644
--- a/src/gflags.cc
+++ b/src/gflags.cc
@@ -88,7 +88,7 @@
 // are, similarly, mostly hooks into the functionality described above.
 
 #include "config.h"
-#include "gflags.h"
+#include "gflags/gflags.h"
 
 #include <assert.h>
 #include <ctype.h>
@@ -96,6 +96,7 @@
 #if defined(HAVE_FNMATCH_H)
 #  include <fnmatch.h>
 #elif defined(HAVE_SHLWAPI_H)
+#  define NO_SHLWAPI_ISOS
 #  include <shlwapi.h>
 #endif
 #include <stdarg.h> // For va_list and related operations
@@ -111,6 +112,9 @@
 #include "mutex.h"
 #include "util.h"
 
+using namespace MUTEX_NAMESPACE;
+
+
 // 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"
@@ -167,12 +171,10 @@
 
 // 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);
+  vfprintf(stderr, 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);
 }
@@ -188,34 +190,41 @@
 class CommandLineFlag;
 class FlagValue {
  public:
-  FlagValue(void* valbuf, const char* type, bool transfer_ownership_of_value);
+  enum ValueType {
+    FV_BOOL = 0,
+    FV_INT32 = 1,
+    FV_UINT32 = 2,
+    FV_INT64 = 3,
+    FV_UINT64 = 4,
+    FV_DOUBLE = 5,
+    FV_STRING = 6,
+    FV_MAX_INDEX = 6,
+  };
+
+  template <typename FlagType>
+  FlagValue(FlagType* valbuf, bool transfer_ownership_of_value);
   ~FlagValue();
 
   bool ParseFrom(const char* spec);
   string ToString() const;
 
+  ValueType Type() const { return static_cast<ValueType>(type_); }
+
  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);
+  template <typename T> friend T GetFromEnv(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,
-  };
+  template <typename FlagType>
+  struct FlagValueTraits;
+
   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
@@ -223,14 +232,33 @@
   // (*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
+  void* const value_buffer_;          // points to the buffer holding our data
+  const int8 type_;                   // how to interpret value_
+  const bool owns_value_;             // whether to free value on destruct
 
   FlagValue(const FlagValue&);   // no copying!
   void operator=(const FlagValue&);
 };
 
+// Map the given C++ type to a value of the ValueType enum at compile time.
+#define DEFINE_FLAG_TRAITS(type, value)        \
+  template <>                                  \
+  struct FlagValue::FlagValueTraits<type> {    \
+    static const ValueType kValueType = value; \
+  }
+
+// Define full template specializations of the FlagValueTraits template
+// for all supported flag types.
+DEFINE_FLAG_TRAITS(bool, FV_BOOL);
+DEFINE_FLAG_TRAITS(int32, FV_INT32);
+DEFINE_FLAG_TRAITS(uint32, FV_UINT32);
+DEFINE_FLAG_TRAITS(int64, FV_INT64);
+DEFINE_FLAG_TRAITS(uint64, FV_UINT64);
+DEFINE_FLAG_TRAITS(double, FV_DOUBLE);
+DEFINE_FLAG_TRAITS(std::string, FV_STRING);
+
+#undef DEFINE_FLAG_TRAITS
+
 
 // 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.
@@ -238,16 +266,12 @@
 #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,
+template <typename FlagType>
+FlagValue::FlagValue(FlagType* valbuf,
                      bool transfer_ownership_of_value)
     : value_buffer_(valbuf),
+      type_(FlagValueTraits<FlagType>::kValueType),
       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() {
@@ -257,6 +281,7 @@
   switch (type_) {
     case FV_BOOL: delete reinterpret_cast<bool*>(value_buffer_); break;
     case FV_INT32: delete reinterpret_cast<int32*>(value_buffer_); break;
+    case FV_UINT32: delete reinterpret_cast<uint32*>(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;
@@ -305,6 +330,16 @@
       SET_VALUE_AS(int32, static_cast<int32>(r));
       return true;
     }
+    case FV_UINT32: {
+      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
+        if (static_cast<uint32>(r) != r)  // worked, but number out of range
+        return false;
+      SET_VALUE_AS(uint32, static_cast<uint32>(r));
+      return true;
+    }
     case FV_INT64: {
       const int64 r = strto64(value, &end, base);
       if (errno || end != value + strlen(value))  return false;  // bad parse
@@ -340,6 +375,9 @@
     case FV_INT32:
       snprintf(intbuf, sizeof(intbuf), "%" PRId32, VALUE_AS(int32));
       return intbuf;
+    case FV_UINT32:
+      snprintf(intbuf, sizeof(intbuf), "%" PRIu32, VALUE_AS(uint32));
+      return intbuf;
     case FV_INT64:
       snprintf(intbuf, sizeof(intbuf), "%" PRId64, VALUE_AS(int64));
       return intbuf;
@@ -366,6 +404,9 @@
     case FV_INT32:
       return reinterpret_cast<bool (*)(const char*, int32)>(
           validate_fn_proto)(flagname, VALUE_AS(int32));
+    case FV_UINT32:
+      return reinterpret_cast<bool (*)(const char*, uint32)>(
+          validate_fn_proto)(flagname, VALUE_AS(uint32));
     case FV_INT64:
       return reinterpret_cast<bool (*)(const char*, int64)>(
           validate_fn_proto)(flagname, VALUE_AS(int64));
@@ -388,6 +429,7 @@
   static const char types[] =
       "bool\0xx"
       "int32\0x"
+      "uint32\0"
       "int64\0x"
       "uint64\0"
       "double\0"
@@ -406,6 +448,7 @@
   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_UINT32: return VALUE_AS(uint32) == OTHER_VALUE_AS(x, uint32);
     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);
@@ -415,14 +458,14 @@
 }
 
 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);
+    case FV_BOOL:   return new FlagValue(new bool(false), true);
+    case FV_INT32:  return new FlagValue(new int32(0), true);
+    case FV_UINT32: return new FlagValue(new uint32(0), true);
+    case FV_INT64:  return new FlagValue(new int64(0), true);
+    case FV_UINT64: return new FlagValue(new uint64(0), true);
+    case FV_DOUBLE: return new FlagValue(new double(0.0), true);
+    case FV_STRING: return new FlagValue(new string, true);
     default: assert(false); return NULL;  // unknown type
   }
 }
@@ -432,6 +475,7 @@
   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_UINT32: SET_VALUE_AS(uint32, OTHER_VALUE_AS(x, uint32));  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;
@@ -440,22 +484,6 @@
   }
 }
 
-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,
@@ -484,11 +512,14 @@
   ValidateFnProto validate_function() const { return validate_fn_proto_; }
   const void* flag_ptr() const { return current_->value_buffer_; }
 
+  FlagValue::ValueType Type() const { return defvalue_->Type(); }
+
   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_); }
+  bool Modified() const { return modified_; }
 
  private:
   // for SetFlagLocked() and setting flags_by_ptr_
@@ -531,26 +562,14 @@
 }
 
 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;
+  // This function has been used to strip off a common prefix from
+  // flag source file names. Because flags can be defined in different
+  // shared libraries, there may not be a single common prefix.
+  // Further, this functionality hasn't been active for many years.
+  // Need a better way to produce more user friendly help output or
+  // "anonymize" file paths in help output, respectively.
+  // Follow issue at: https://github.com/gflags/gflags/issues/86
+  return filename();
 }
 
 void CommandLineFlag::FillCommandLineFlagInfo(
@@ -661,7 +680,7 @@
 
  private:
   friend class GFLAGS_NAMESPACE::FlagSaverImpl;  // reads all the flags in order to copy them
-  friend class CommandLineFlagParser;    // for ValidateAllFlags
+  friend class CommandLineFlagParser;    // for ValidateUnmodifiedFlags
   friend void GFLAGS_NAMESPACE::GetAllFlags(vector<CommandLineFlagInfo>*);
 
   // The map from name to flag, for FindFlagLocked().
@@ -677,7 +696,6 @@
   static FlagRegistry* global_registry_;   // a singleton registry
 
   Mutex lock_;
-  static Mutex global_registry_lock_;
 
   static void InitGlobalRegistry();
 
@@ -722,7 +740,12 @@
 CommandLineFlag* FlagRegistry::FindFlagLocked(const char* name) {
   FlagConstIterator i = flags_.find(name);
   if (i == flags_.end()) {
-    return NULL;
+    // If the name has dashes in it, try again after replacing with
+    // underscores.
+    if (strchr(name, '-') == NULL) return NULL;
+    string name_rep = name;
+    std::replace(name_rep.begin(), name_rep.end(), '-', '_');
+    return FindFlagLocked(name_rep.c_str());
   } else {
     return i->second;
   }
@@ -774,7 +797,7 @@
                                     kError, key->c_str());
       return NULL;
     }
-    if (strcmp(flag->type_name(), "bool") != 0) {
+    if (flag->Type() != FlagValue::FV_BOOL) {
       // '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",
@@ -788,7 +811,7 @@
   }
 
   // Assign a value if this is a boolean flag
-  if (*v == NULL && strcmp(flag->type_name(), "bool") == 0) {
+  if (*v == NULL && flag->Type() == FlagValue::FV_BOOL) {
     *v = "1";    // the --nox case was already handled, so this is the --x case
   }
 
@@ -875,10 +898,10 @@
 
 // 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_);
+  static Mutex lock(Mutex::LINKER_INITIALIZED);
+  MutexLock acquire_lock(&lock);
   if (!global_registry_) {
     global_registry_ = new FlagRegistry;
   }
@@ -917,8 +940,9 @@
   // In gflags_reporting.cc:HandleCommandLineHelpFlags().
 
   // Stage 3: validate all the commandline flags that have validators
-  // registered.
-  void ValidateAllFlags();
+  // registered and were not set/modified by ParseNewCommandLineFlags.
+  void ValidateFlags(bool all);
+  void ValidateUnmodifiedFlags();
 
   // Stage 4: report any errors and return true if any were found.
   bool ReportErrors();
@@ -1005,9 +1029,6 @@
 
 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();
@@ -1015,17 +1036,15 @@
     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
+    if (arg[0] != '-' || arg[1] == '\0') {	// must be a program argument: "-" 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 '--'
+    arg++;                     // skip leading '-'
+    if (arg[0] == '-') arg++;  // or leading '--'
 
     // -- alone means what it does for GNU: stop options parsing
     if (*arg == '\0') {
@@ -1047,7 +1066,7 @@
 
     if (value == NULL) {
       // Boolean options are always assigned a value by SplitArgumentLocked()
-      assert(strcmp(flag->type_name(), "bool") != 0);
+      assert(flag->Type() != FlagValue::FV_BOOL);
       if (i+1 >= first_nonopt) {
         // This flag needs a value, but there is nothing available
         error_flags_[key] = (string(kError) + "flag '" + (*argv)[i] + "'"
@@ -1072,7 +1091,7 @@
         // "-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
+            && flag->Type() == FlagValue::FV_STRING
             && (strstr(flag->help(), "true")
                 || strstr(flag->help(), "false"))) {
           LOG(WARNING) << "Did you really mean to set flag '"
@@ -1137,8 +1156,8 @@
     }
 
     const string envname = string("FLAGS_") + string(flagname);
-	string envval;
-	if (!SafeGetEnv(envname.c_str(), envval)) {
+    string envval;
+    if (!SafeGetEnv(envname.c_str(), envval)) {
       if (errors_are_fatal) {
         error_flags_[flagname] = (string(kError) + envname +
                                   " not found in environment\n");
@@ -1184,23 +1203,31 @@
   return msg;
 }
 
-void CommandLineFlagParser::ValidateAllFlags() {
+void CommandLineFlagParser::ValidateFlags(bool all) {
   FlagRegistryLock frl(registry_);
   for (FlagRegistry::FlagConstIterator i = registry_->flags_.begin();
        i != registry_->flags_.end(); ++i) {
-    if (!i->second->ValidateCurrent()) {
+    if ((all || !i->second->Modified()) && !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())
+      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";
+            " must be set on the commandline";
+        if (!i->second->Modified()) {
+          error_flags_[i->second->name()] += " (default value fails validation)";
+        }
+        error_flags_[i->second->name()] += "\n";
+      }
     }
   }
 }
 
+void CommandLineFlagParser::ValidateUnmodifiedFlags() {
+  ValidateFlags(false);
+}
+
 bool CommandLineFlagParser::ReportErrors() {
   // error_flags_ indicates errors we saw while parsing.
   // But we ignore undefined-names if ok'ed by --undef_ok
@@ -1252,7 +1279,11 @@
   for (; line_end; flagfile_contents = line_end + 1) {
     while (*flagfile_contents && isspace(*flagfile_contents))
       ++flagfile_contents;
-    line_end = strchr(flagfile_contents, '\n');
+    // Windows uses "\r\n"
+    line_end = strchr(flagfile_contents, '\r');
+    if (line_end == NULL)
+        line_end = strchr(flagfile_contents, '\n');
+
     size_t len = line_end ? line_end - flagfile_contents
                           : strlen(flagfile_contents);
     string line(flagfile_contents, len);
@@ -1332,14 +1363,14 @@
 // --------------------------------------------------------------------
 
 template<typename T>
-T GetFromEnv(const char *varname, const char* type, T dflt) {
+T GetFromEnv(const char *varname, T dflt) {
   std::string valstr;
   if (SafeGetEnv(varname, valstr)) {
-    FlagValue ifv(new T, type, true);
+    FlagValue ifv(new T, 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;
 }
@@ -1386,22 +1417,48 @@
 //    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) {
+namespace {
+void RegisterCommandLineFlag(const char* name,
+                             const char* help,
+                             const char* filename,
+                             FlagValue* current,
+                             FlagValue* defvalue) {
   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
+  CommandLineFlag* flag =
+      new CommandLineFlag(name, help, filename, current, defvalue);
+  FlagRegistry::GlobalRegistry()->RegisterFlag(flag);  // default registry
 }
+}
+
+template <typename FlagType>
+FlagRegisterer::FlagRegisterer(const char* name,
+                               const char* help,
+                               const char* filename,
+                               FlagType* current_storage,
+                               FlagType* defvalue_storage) {
+  FlagValue* const current = new FlagValue(current_storage, false);
+  FlagValue* const defvalue = new FlagValue(defvalue_storage, false);
+  RegisterCommandLineFlag(name, help, filename, current, defvalue);
+}
+
+// Force compiler to generate code for the given template specialization.
+#define INSTANTIATE_FLAG_REGISTERER_CTOR(type)                  \
+  template GFLAGS_DLL_DECL FlagRegisterer::FlagRegisterer(      \
+      const char* name, const char* help, const char* filename, \
+      type* current_storage, type* defvalue_storage)
+
+// Do this for all supported flag types.
+INSTANTIATE_FLAG_REGISTERER_CTOR(bool);
+INSTANTIATE_FLAG_REGISTERER_CTOR(int32);
+INSTANTIATE_FLAG_REGISTERER_CTOR(uint32);
+INSTANTIATE_FLAG_REGISTERER_CTOR(int64);
+INSTANTIATE_FLAG_REGISTERER_CTOR(uint64);
+INSTANTIATE_FLAG_REGISTERER_CTOR(double);
+INSTANTIATE_FLAG_REGISTERER_CTOR(std::string);
+
+#undef INSTANTIATE_FLAG_REGISTERER_CTOR
 
 // --------------------------------------------------------------------
 // GetAllFlags()
@@ -1451,65 +1508,58 @@
 
 // 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 string argv0("UNKNOWN");  // just the program name
+static string cmdline;           // the entire command-line
+static string program_usage;
 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;
-
+  if (called_set_argv) 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);
+  assert(argc > 0); // every program has at least a name
+  argv0 = argv[0];
 
-  string cmdline_string;       // easier than doing strcats
+  cmdline.clear();
   for (int i = 0; i < argc; i++) {
-    if (i != 0) {
-      cmdline_string += " ";
-    }
-    cmdline_string += argv[i];
+    if (i != 0) cmdline += " ";
+    cmdline += 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 = 0;
+  for (string::const_iterator c = cmdline.begin(); c != cmdline.end(); ++c) {
     argv_sum += *c;
+  }
 }
 
 const vector<string>& GetArgvs() { return argvs; }
-const char* GetArgv()            { return cmdline; }
-const char* GetArgv0()           { return argv0; }
+const char* GetArgv()            { return cmdline.c_str(); }
+const char* GetArgv0()           { return argv0.c_str(); }
 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, '/');
+  size_t pos = argv0.rfind('/');
 #ifdef OS_WINDOWS
-  if (!slash)  slash = strrchr(argv0, '\\');
+  if (pos == string::npos) pos = argv0.rfind('\\');
 #endif
-  return slash ? slash + 1 : argv0;
+  return (pos == string::npos ? argv0.c_str() : (argv0.c_str() + pos + 1));
 }
 
 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
+  program_usage = usage;
 }
 
 const char* ProgramUsage() {
-  if (program_usage) {
-    return program_usage;
+  if (program_usage.empty()) {
+    return "Warning: SetUsageMessage() never called";
   }
-  return "Warning: SetUsageMessage() never called";
+  return program_usage.c_str();
 }
 
 // --------------------------------------------------------------------
@@ -1517,16 +1567,14 @@
 // VersionString()
 // --------------------------------------------------------------------
 
-static const char* version_string = NULL;
+static string version_string;
 
 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
+  version_string = version;
 }
 
 const char* VersionString() {
-  return version_string ? version_string : "";
+  return version_string.c_str();
 }
 
 
@@ -1787,6 +1835,7 @@
 // --------------------------------------------------------------------
 // BoolFromEnv()
 // Int32FromEnv()
+// Uint32FromEnv()
 // Int64FromEnv()
 // Uint64FromEnv()
 // DoubleFromEnv()
@@ -1798,19 +1847,22 @@
 // --------------------------------------------------------------------
 
 bool BoolFromEnv(const char *v, bool dflt) {
-  return GetFromEnv(v, "bool", dflt);
+  return GetFromEnv(v, dflt);
 }
 int32 Int32FromEnv(const char *v, int32 dflt) {
-  return GetFromEnv(v, "int32", dflt);
+  return GetFromEnv(v, dflt);
+}
+uint32 Uint32FromEnv(const char *v, uint32 dflt) {
+  return GetFromEnv(v, dflt);
 }
 int64 Int64FromEnv(const char *v, int64 dflt)    {
-  return GetFromEnv(v, "int64", dflt);
+  return GetFromEnv(v, dflt);
 }
 uint64 Uint64FromEnv(const char *v, uint64 dflt) {
-  return GetFromEnv(v, "uint64", dflt);
+  return GetFromEnv(v, dflt);
 }
 double DoubleFromEnv(const char *v, double dflt) {
-  return GetFromEnv(v, "double", dflt);
+  return GetFromEnv(v, dflt);
 }
 
 #ifdef _MSC_VER
@@ -1846,6 +1898,10 @@
                            bool (*validate_fn)(const char*, int32)) {
   return AddFlagValidator(flag, reinterpret_cast<ValidateFnProto>(validate_fn));
 }
+bool RegisterFlagValidator(const uint32* flag,
+                           bool (*validate_fn)(const char*, uint32)) {
+  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));
@@ -1901,7 +1957,7 @@
     HandleCommandLineHelpFlags();   // may cause us to exit on --help, etc.
 
   // See if any of the unset flags fail their validation checks
-  parser.ValidateAllFlags();
+  parser.ValidateUnmodifiedFlags();
 
   if (parser.ReportErrors())        // may cause us to exit on illegal flags
     gflags_exitfunc(1);