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/config.h b/src/config.h
new file mode 100644
index 0000000..b90b7e6
--- /dev/null
+++ b/src/config.h
@@ -0,0 +1,57 @@
+// Note: This header file is only used internally. It is not part of public interface!
+
+#ifndef GFLAGS_CONFIG_H_
+#define GFLAGS_CONFIG_H_
+
+
+// ---------------------------------------------------------------------------
+// System checks
+
+// CMake build configuration is written to defines.h file, unused by Bazel build
+#if !defined(GFLAGS_BAZEL_BUILD)
+# include "defines.h"
+#endif
+
+// gcc requires this to get PRId64, etc.
+#if defined(HAVE_INTTYPES_H) && !defined(__STDC_FORMAT_MACROS)
+# define __STDC_FORMAT_MACROS 1
+#endif
+
+// ---------------------------------------------------------------------------
+// Path separator
+#ifndef PATH_SEPARATOR
+# ifdef OS_WINDOWS
+# define PATH_SEPARATOR '\\'
+# else
+# define PATH_SEPARATOR '/'
+# endif
+#endif
+
+// ---------------------------------------------------------------------------
+// Windows
+
+// Always export symbols when compiling a shared library as this file is only
+// included by internal modules when building the gflags library itself.
+// The gflags_declare.h header file will set it to import these symbols otherwise.
+#ifndef GFLAGS_DLL_DECL
+# if GFLAGS_IS_A_DLL && defined(_MSC_VER)
+# define GFLAGS_DLL_DECL __declspec(dllexport)
+# else
+# define GFLAGS_DLL_DECL
+# endif
+#endif
+// Flags defined by the gflags library itself must be exported
+#ifndef GFLAGS_DLL_DEFINE_FLAG
+# define GFLAGS_DLL_DEFINE_FLAG GFLAGS_DLL_DECL
+#endif
+
+#ifdef OS_WINDOWS
+// The unittests import the symbols of the shared gflags library
+# if GFLAGS_IS_A_DLL && defined(_MSC_VER)
+# define GFLAGS_DLL_DECL_FOR_UNITTESTS __declspec(dllimport)
+# endif
+# include "windows_port.h"
+#endif
+
+
+#endif // GFLAGS_CONFIG_H_
diff --git a/src/config.h.in b/src/config.h.in
deleted file mode 100644
index a8708da..0000000
--- a/src/config.h.in
+++ /dev/null
@@ -1,112 +0,0 @@
-/* Generated from config.h.in during build configuration using CMake. */
-
-// Note: This header file is only used internally. It is not part of public interface!
-
-// ---------------------------------------------------------------------------
-// System checks
-
-// Define if you build this library for a MS Windows OS.
-#cmakedefine OS_WINDOWS
-
-// Define if you have the <stdint.h> header file.
-#cmakedefine HAVE_STDINT_H
-
-// Define if you have the <sys/types.h> header file.
-#cmakedefine HAVE_SYS_TYPES_H
-
-// Define if you have the <inttypes.h> header file.
-#cmakedefine HAVE_INTTYPES_H
-
-// Define if you have the <sys/stat.h> header file.
-#cmakedefine HAVE_SYS_STAT_H
-
-// Define if you have the <unistd.h> header file.
-#cmakedefine HAVE_UNISTD_H
-
-// Define if you have the <fnmatch.h> header file.
-#cmakedefine HAVE_FNMATCH_H
-
-// Define if you have the <shlwapi.h> header file (Windows 2000/XP).
-#cmakedefine HAVE_SHLWAPI_H
-
-// Define if you have the strtoll function.
-#cmakedefine HAVE_STRTOLL
-
-// Define if you have the strtoq function.
-#cmakedefine HAVE_STRTOQ
-
-// Define if you have the <pthread.h> header file.
-#cmakedefine HAVE_PTHREAD
-
-// Define if your pthread library defines the type pthread_rwlock_t
-#cmakedefine HAVE_RWLOCK
-
-// gcc requires this to get PRId64, etc.
-#if defined(HAVE_INTTYPES_H) && !defined(__STDC_FORMAT_MACROS)
-# define __STDC_FORMAT_MACROS 1
-#endif
-
-// ---------------------------------------------------------------------------
-// Package information
-
-// Name of package.
-#define PACKAGE @PROJECT_NAME@
-
-// Define to the full name of this package.
-#define PACKAGE_NAME @PACKAGE_NAME@
-
-// Define to the full name and version of this package.
-#define PACKAGE_STRING @PACKAGE_STRING@
-
-// Define to the one symbol short name of this package.
-#define PACKAGE_TARNAME @PACKAGE_TARNAME@
-
-// Define to the version of this package.
-#define PACKAGE_VERSION @PACKAGE_VERSION@
-
-// Version number of package.
-#define VERSION PACKAGE_VERSION
-
-// Define to the address where bug reports for this package should be sent.
-#define PACKAGE_BUGREPORT @PACKAGE_BUGREPORT@
-
-// ---------------------------------------------------------------------------
-// Path separator
-#ifndef PATH_SEPARATOR
-# ifdef OS_WINDOWS
-# define PATH_SEPARATOR '\\'
-# else
-# define PATH_SEPARATOR '/'
-# endif
-#endif
-
-// ---------------------------------------------------------------------------
-// Windows
-
-// Whether gflags library is a DLL.
-#ifndef GFLAGS_IS_A_DLL
-# define GFLAGS_IS_A_DLL 0
-#endif
-
-// Always export symbols when compiling a shared library as this file is only
-// included by internal modules when building the gflags library itself.
-// The gflags_declare.h header file will set it to import these symbols otherwise.
-#ifndef GFLAGS_DLL_DECL
-# if GFLAGS_IS_A_DLL && defined(_MSC_VER)
-# define GFLAGS_DLL_DECL __declspec(dllexport)
-# else
-# define GFLAGS_DLL_DECL
-# endif
-#endif
-// Flags defined by the gflags library itself must be exported
-#ifndef GFLAGS_DLL_DEFINE_FLAG
-# define GFLAGS_DLL_DEFINE_FLAG GFLAGS_DLL_DECL
-#endif
-
-#ifdef OS_WINDOWS
-// The unittests import the symbols of the shared gflags library
-# if GFLAGS_IS_A_DLL && defined(_MSC_VER)
-# define GFLAGS_DLL_DECL_FOR_UNITTESTS __declspec(dllimport)
-# endif
-# include "windows_port.h"
-#endif
diff --git a/src/defines.h.in b/src/defines.h.in
new file mode 100644
index 0000000..dfb214e
--- /dev/null
+++ b/src/defines.h.in
@@ -0,0 +1,48 @@
+/* Generated from defines.h.in during build configuration using CMake. */
+
+// Note: This header file is only used internally. It is not part of public interface!
+// Any cmakedefine is defined using the -D flag instead when Bazel is used.
+// For Bazel, this file is thus not used to avoid a private file in $(GENDIR).
+
+#ifndef GFLAGS_DEFINES_H_
+#define GFLAGS_DEFINES_H_
+
+
+// Define if you build this library for a MS Windows OS.
+#cmakedefine OS_WINDOWS
+
+// Define if you have the <stdint.h> header file.
+#cmakedefine HAVE_STDINT_H
+
+// Define if you have the <sys/types.h> header file.
+#cmakedefine HAVE_SYS_TYPES_H
+
+// Define if you have the <inttypes.h> header file.
+#cmakedefine HAVE_INTTYPES_H
+
+// Define if you have the <sys/stat.h> header file.
+#cmakedefine HAVE_SYS_STAT_H
+
+// Define if you have the <unistd.h> header file.
+#cmakedefine HAVE_UNISTD_H
+
+// Define if you have the <fnmatch.h> header file.
+#cmakedefine HAVE_FNMATCH_H
+
+// Define if you have the <shlwapi.h> header file (Windows 2000/XP).
+#cmakedefine HAVE_SHLWAPI_H
+
+// Define if you have the strtoll function.
+#cmakedefine HAVE_STRTOLL
+
+// Define if you have the strtoq function.
+#cmakedefine HAVE_STRTOQ
+
+// Define if you have the <pthread.h> header file.
+#cmakedefine HAVE_PTHREAD
+
+// Define if your pthread library defines the type pthread_rwlock_t
+#cmakedefine HAVE_RWLOCK
+
+
+#endif // GFLAGS_DEFINES_H_
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);
diff --git a/src/gflags.h.in b/src/gflags.h.in
index 0324d39..7b218b9 100644
--- a/src/gflags.h.in
+++ b/src/gflags.h.in
@@ -81,12 +81,12 @@
#include <string>
#include <vector>
-#include "gflags_declare.h" // IWYU pragma: export
+#include "gflags/gflags_declare.h" // IWYU pragma: export
// We always want to export variables defined in user code
#ifndef GFLAGS_DLL_DEFINE_FLAG
-# ifdef _MSC_VER
+# if GFLAGS_IS_A_DLL && defined(_MSC_VER)
# define GFLAGS_DLL_DEFINE_FLAG __declspec(dllexport)
# else
# define GFLAGS_DLL_DEFINE_FLAG
@@ -128,6 +128,7 @@
// validator is already registered for this flag).
extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const bool* flag, bool (*validate_fn)(const char*, bool));
extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const int32* flag, bool (*validate_fn)(const char*, int32));
+extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const uint32* flag, bool (*validate_fn)(const char*, uint32));
extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const int64* flag, bool (*validate_fn)(const char*, int64));
extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const uint64* flag, bool (*validate_fn)(const char*, uint64));
extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const double* flag, bool (*validate_fn)(const char*, double));
@@ -313,6 +314,7 @@
extern GFLAGS_DLL_DECL bool BoolFromEnv(const char *varname, bool defval);
extern GFLAGS_DLL_DECL int32 Int32FromEnv(const char *varname, int32 defval);
+extern GFLAGS_DLL_DECL uint32 Uint32FromEnv(const char *varname, uint32 defval);
extern GFLAGS_DLL_DECL int64 Int64FromEnv(const char *varname, int64 defval);
extern GFLAGS_DLL_DECL uint64 Uint64FromEnv(const char *varname, uint64 defval);
extern GFLAGS_DLL_DECL double DoubleFromEnv(const char *varname, double defval);
@@ -429,11 +431,37 @@
class GFLAGS_DLL_DECL FlagRegisterer {
public:
- FlagRegisterer(const char* name, const char* type,
+ // We instantiate this template ctor for all supported types,
+ // so it is possible to place implementation of the FlagRegisterer ctor in
+ // .cc file.
+ // Calling this constructor with unsupported type will produce linker error.
+ template <typename FlagType>
+ FlagRegisterer(const char* name,
const char* help, const char* filename,
- void* current_storage, void* defvalue_storage);
+ FlagType* current_storage, FlagType* defvalue_storage);
};
+// Force compiler to not generate code for the given template specialization.
+#if defined(_MSC_VER) && _MSC_VER < 1800 // Visual Studio 2013 version 12.0
+ #define GFLAGS_DECLARE_FLAG_REGISTERER_CTOR(type)
+#else
+ #define GFLAGS_DECLARE_FLAG_REGISTERER_CTOR(type) \
+ extern template GFLAGS_DLL_DECL FlagRegisterer::FlagRegisterer( \
+ const char* name, const char* help, const char* filename, \
+ type* current_storage, type* defvalue_storage)
+#endif
+
+// Do this for all supported flag types.
+GFLAGS_DECLARE_FLAG_REGISTERER_CTOR(bool);
+GFLAGS_DECLARE_FLAG_REGISTERER_CTOR(int32);
+GFLAGS_DECLARE_FLAG_REGISTERER_CTOR(uint32);
+GFLAGS_DECLARE_FLAG_REGISTERER_CTOR(int64);
+GFLAGS_DECLARE_FLAG_REGISTERER_CTOR(uint64);
+GFLAGS_DECLARE_FLAG_REGISTERER_CTOR(double);
+GFLAGS_DECLARE_FLAG_REGISTERER_CTOR(std::string);
+
+#undef GFLAGS_DECLARE_FLAG_REGISTERER_CTOR
+
// If your application #defines STRIP_FLAG_HELP to a non-zero value
// before #including this file, we remove the help message from the
// binary file. This can reduce the size of the resulting binary
@@ -471,9 +499,9 @@
static const type FLAGS_nono##name = value; \
/* We always want to export defined variables, dll or no */ \
GFLAGS_DLL_DEFINE_FLAG type FLAGS_##name = FLAGS_nono##name; \
- type FLAGS_no##name = FLAGS_nono##name; \
+ static type FLAGS_no##name = FLAGS_nono##name; \
static GFLAGS_NAMESPACE::FlagRegisterer o_##name( \
- #name, #type, MAYBE_STRIPPED_HELP(help), __FILE__, \
+ #name, MAYBE_STRIPPED_HELP(help), __FILE__, \
&FLAGS_##name, &FLAGS_no##name); \
} \
using fL##shorttype::FLAGS_##name
@@ -508,6 +536,10 @@
DEFINE_VARIABLE(GFLAGS_NAMESPACE::int32, I, \
name, val, txt)
+#define DEFINE_uint32(name,val, txt) \
+ DEFINE_VARIABLE(GFLAGS_NAMESPACE::uint32, U, \
+ name, val, txt)
+
#define DEFINE_int64(name, val, txt) \
DEFINE_VARIABLE(GFLAGS_NAMESPACE::int64, I64, \
name, val, txt)
@@ -538,6 +570,26 @@
}
inline clstring* dont_pass0toDEFINE_string(char *stringspot,
int value);
+
+// Auxiliary class used to explicitly call destructor of string objects
+// allocated using placement new during static program deinitialization.
+// The destructor MUST be an inline function such that the explicit
+// destruction occurs in the same compilation unit as the placement new.
+class StringFlagDestructor {
+ void *current_storage_;
+ void *defvalue_storage_;
+
+public:
+
+ StringFlagDestructor(void *current, void *defvalue)
+ : current_storage_(current), defvalue_storage_(defvalue) {}
+
+ ~StringFlagDestructor() {
+ reinterpret_cast<clstring*>(current_storage_ )->~clstring();
+ reinterpret_cast<clstring*>(defvalue_storage_)->~clstring();
+ }
+};
+
} // namespace fLS
// We need to define a var named FLAGS_no##name so people don't define
@@ -550,13 +602,15 @@
#define DEFINE_string(name, val, txt) \
namespace fLS { \
using ::fLS::clstring; \
+ using ::fLS::StringFlagDestructor; \
static union { void* align; char s[sizeof(clstring)]; } s_##name[2]; \
clstring* const FLAGS_no##name = ::fLS:: \
dont_pass0toDEFINE_string(s_##name[0].s, \
val); \
static GFLAGS_NAMESPACE::FlagRegisterer o_##name( \
- #name, "string", MAYBE_STRIPPED_HELP(txt), __FILE__, \
- s_##name[0].s, new (s_##name[1].s) clstring(*FLAGS_no##name)); \
+ #name, MAYBE_STRIPPED_HELP(txt), __FILE__, \
+ FLAGS_no##name, new (s_##name[1].s) clstring(*FLAGS_no##name)); \
+ static StringFlagDestructor d_##name(s_##name[0].s, s_##name[1].s); \
extern GFLAGS_DLL_DEFINE_FLAG clstring& FLAGS_##name; \
using fLS::FLAGS_##name; \
clstring& FLAGS_##name = *FLAGS_no##name; \
diff --git a/src/gflags_completions.cc b/src/gflags_completions.cc
index 3a47623..c53a128 100644
--- a/src/gflags_completions.cc
+++ b/src/gflags_completions.cc
@@ -46,9 +46,6 @@
// 5a) Force bash to place most-relevent groups at the top of the list
// 5b) Trim most flag's descriptions to fit on a single terminal line
-
-#include "config.h"
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // for strlen
@@ -58,7 +55,9 @@
#include <utility>
#include <vector>
-#include "gflags.h"
+#include "config.h"
+#include "gflags/gflags.h"
+#include "gflags/gflags_completions.h"
#include "util.h"
using std::set;
@@ -120,7 +119,7 @@
NotableFlags *notable_flags);
static void TryFindModuleAndPackageDir(
- const vector<CommandLineFlagInfo> all_flags,
+ const vector<CommandLineFlagInfo> &all_flags,
string *module,
string *package_dir);
@@ -180,6 +179,11 @@
bool flag_description_substring_search;
bool return_all_matching_flags;
bool force_no_update;
+ CompletionOptions(): flag_name_substring_search(false),
+ flag_location_substring_search(false),
+ flag_description_substring_search(false),
+ return_all_matching_flags(false),
+ force_no_update(false) { }
};
// Notable flags are flags that are special or preferred for some
@@ -203,7 +207,7 @@
static void PrintFlagCompletionInfo(void) {
string cursor_word = FLAGS_tab_completion_word;
string canonical_token;
- CompletionOptions options = { };
+ CompletionOptions options = CompletionOptions();
CanonicalizeCursorWordAndSearchOptions(
cursor_word,
&canonical_token,
@@ -470,7 +474,7 @@
}
static void TryFindModuleAndPackageDir(
- const vector<CommandLineFlagInfo> all_flags,
+ const vector<CommandLineFlagInfo> &all_flags,
string *module,
string *package_dir) {
module->clear();
@@ -546,8 +550,7 @@
vector<DisplayInfoGroup> output_groups;
bool perfect_match_found = false;
- if (lines_so_far < max_desired_lines &&
- !notable_flags->perfect_match_flag.empty()) {
+ if (!notable_flags->perfect_match_flag.empty()) {
perfect_match_found = true;
DisplayInfoGroup group =
{ "",
diff --git a/src/gflags_declare.h.in b/src/gflags_declare.h.in
index 279db24..752a34d 100644
--- a/src/gflags_declare.h.in
+++ b/src/gflags_declare.h.in
@@ -45,18 +45,27 @@
// ---------------------------------------------------------------------------
// Windows DLL import/export.
-// We always want to import the symbols of the gflags library
+// Whether gflags library is a DLL.
+//
+// Set to 1 by default when the shared gflags library was built on Windows.
+// Must be overwritten when this header file is used with the optionally also
+// built static library instead; set by CMake's INTERFACE_COMPILE_DEFINITIONS.
+#ifndef GFLAGS_IS_A_DLL
+# define GFLAGS_IS_A_DLL @GFLAGS_IS_A_DLL@
+#endif
+
+// We always want to import the symbols of the gflags library.
#ifndef GFLAGS_DLL_DECL
-# if @GFLAGS_IS_A_DLL@ && defined(_MSC_VER)
+# if GFLAGS_IS_A_DLL && defined(_MSC_VER)
# define GFLAGS_DLL_DECL __declspec(dllimport)
# else
# define GFLAGS_DLL_DECL
# endif
#endif
-// We always want to import variables declared in user code
+// We always want to import variables declared in user code.
#ifndef GFLAGS_DLL_DECLARE_FLAG
-# ifdef _MSC_VER
+# if GFLAGS_IS_A_DLL && defined(_MSC_VER)
# define GFLAGS_DLL_DECLARE_FLAG __declspec(dllimport)
# else
# define GFLAGS_DLL_DECLARE_FLAG
@@ -120,6 +129,9 @@
#define DECLARE_int32(name) \
DECLARE_VARIABLE(::GFLAGS_NAMESPACE::int32, I, name)
+#define DECLARE_uint32(name) \
+ DECLARE_VARIABLE(::GFLAGS_NAMESPACE::uint32, U, name)
+
#define DECLARE_int64(name) \
DECLARE_VARIABLE(::GFLAGS_NAMESPACE::int64, I64, name)
@@ -132,7 +144,6 @@
#define DECLARE_string(name) \
/* We always want to import declared variables, dll or no */ \
namespace fLS { \
- using ::fLS::clstring; \
extern GFLAGS_DLL_DECLARE_FLAG ::fLS::clstring& FLAGS_##name; \
} \
using fLS::FLAGS_##name
diff --git a/src/gflags_ns.h.in b/src/gflags_ns.h.in
index f692666..ef6ac29 100644
--- a/src/gflags_ns.h.in
+++ b/src/gflags_ns.h.in
@@ -77,6 +77,7 @@
using GFLAGS_NAMESPACE::ReadFromFlagsFile;
using GFLAGS_NAMESPACE::BoolFromEnv;
using GFLAGS_NAMESPACE::Int32FromEnv;
+using GFLAGS_NAMESPACE::Uint32FromEnv;
using GFLAGS_NAMESPACE::Int64FromEnv;
using GFLAGS_NAMESPACE::Uint64FromEnv;
using GFLAGS_NAMESPACE::DoubleFromEnv;
diff --git a/src/gflags_reporting.cc b/src/gflags_reporting.cc
index 9cc41a7..29be922 100644
--- a/src/gflags_reporting.cc
+++ b/src/gflags_reporting.cc
@@ -56,8 +56,8 @@
#include <vector>
#include "config.h"
-#include "gflags.h"
-#include "gflags_completions.h"
+#include "gflags/gflags.h"
+#include "gflags/gflags_completions.h"
#include "util.h"
@@ -126,7 +126,8 @@
string final_string = "";
int chars_in_line = 0; // how many chars in current line so far?
while (1) {
- assert(chars_left == strlen(c_string)); // Unless there's a \0 in there?
+ assert(static_cast<size_t>(chars_left)
+ == strlen(c_string)); // Unless there's a \0 in there?
const char* newline = strchr(c_string, '\n');
if (newline == NULL && chars_in_line+chars_left < kLineLength) {
// The whole remainder of the string fits on this line
@@ -295,10 +296,10 @@
}
}
-void ShowUsageWithFlagsRestrict(const char *argv0, const char *restrict) {
+void ShowUsageWithFlagsRestrict(const char *argv0, const char *restrict_) {
vector<string> substrings;
- if (restrict != NULL && *restrict != '\0') {
- substrings.push_back(restrict);
+ if (restrict_ != NULL && *restrict_ != '\0') {
+ substrings.push_back(restrict_);
}
ShowUsageWithFlagsMatching(argv0, substrings);
}
@@ -388,8 +389,8 @@
gflags_exitfunc(1);
} else if (!FLAGS_helpon.empty()) {
- string restrict = PATH_SEPARATOR + FLAGS_helpon + ".";
- ShowUsageWithFlagsRestrict(progname, restrict.c_str());
+ string restrict_ = PATH_SEPARATOR + FLAGS_helpon + ".";
+ ShowUsageWithFlagsRestrict(progname, restrict_.c_str());
gflags_exitfunc(1);
} else if (!FLAGS_helpmatch.empty()) {
diff --git a/src/mutex.h b/src/mutex.h
index 0bdd9d5..7d7c364 100644
--- a/src/mutex.h
+++ b/src/mutex.h
@@ -106,7 +106,7 @@
#ifndef GFLAGS_MUTEX_H_
#define GFLAGS_MUTEX_H_
-#include "gflags_declare.h" // to figure out pthreads support
+#include "gflags/gflags_declare.h" // to figure out pthreads support
#if defined(NO_THREADS)
typedef int MutexType; // to keep a lock-count
@@ -166,7 +166,7 @@
// It inhibits work being done by the destructor, which makes it
// safer for code that tries to acqiure this mutex in their global
// destructor.
- inline Mutex(LinkerInitialized);
+ explicit inline Mutex(LinkerInitialized);
// Destructor
inline ~Mutex();
@@ -197,7 +197,7 @@
inline void SetIsSafe() { is_safe_ = true; }
// Catch the error of writing Mutex when intending MutexLock.
- Mutex(Mutex* /*ignored*/) {}
+ explicit Mutex(Mutex* /*ignored*/) {}
// Disallow "evil" constructors
Mutex(const Mutex&);
void operator=(const Mutex&);
@@ -344,8 +344,5 @@
} // namespace MUTEX_NAMESPACE
-using namespace MUTEX_NAMESPACE;
-
-#undef MUTEX_NAMESPACE
#endif /* #define GFLAGS_MUTEX_H__ */
diff --git a/src/util.h b/src/util.h
index 366e1be..164e3cf 100644
--- a/src/util.h
+++ b/src/util.h
@@ -37,7 +37,6 @@
#include "config.h"
#include <assert.h>
-#include <config.h>
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#endif
@@ -88,9 +87,10 @@
// -- utility macros ---------------------------------------------------------
-template <bool> struct CompileAssert {};
+template <bool b> struct CompileAssert;
+template <> struct CompileAssert<true> {};
#define COMPILE_ASSERT(expr, msg) \
- typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]
+ enum { assert_##msg = sizeof(CompileAssert<bool(expr)>) }
// Returns the number of elements in an array.
#define arraysize(arr) (sizeof(arr)/sizeof(*(arr)))
diff --git a/src/windows_port.cc b/src/windows_port.cc
index 9ccb630..b5b7194 100644
--- a/src/windows_port.cc
+++ b/src/windows_port.cc
@@ -44,6 +44,7 @@
// These call the windows _vsnprintf, but always NUL-terminate.
#if !defined(__MINGW32__) && !defined(__MINGW64__) /* mingw already defines */
+#if !(defined(_MSC_VER) && _MSC_VER >= 1900) /* msvc 2015 already defines */
#ifdef _MSC_VER
# pragma warning(push)
@@ -59,8 +60,6 @@
# pragma warning(pop)
#endif
-#if _MSC_VER < 1900 // msvs 2015 finally includes snprintf
-
int snprintf(char *str, size_t size, const char *format, ...) {
int r;
va_list ap;
@@ -70,6 +69,5 @@
return r;
}
-#endif
-
+#endif /* if !(defined(_MSC_VER) && _MSC_VER >= 1900) */
#endif /* #if !defined(__MINGW32__) && !defined(__MINGW64__) */
diff --git a/src/windows_port.h b/src/windows_port.h
index c8ff24f..61cf5b7 100644
--- a/src/windows_port.h
+++ b/src/windows_port.h
@@ -63,12 +63,14 @@
* name vsnprintf, since windows defines that (but not snprintf (!)).
*/
#if !defined(__MINGW32__) && !defined(__MINGW64__) /* mingw already defines */
+#if !(defined(_MSC_VER) && _MSC_VER >= 1900) /* msvc 2015 already defines */
extern GFLAGS_DLL_DECL int snprintf(char *str, size_t size,
const char *format, ...);
extern int GFLAGS_DLL_DECL safe_vsnprintf(char *str, size_t size,
const char *format, va_list ap);
#define vsnprintf(str, size, format, ap) safe_vsnprintf(str, size, format, ap)
#define va_copy(dst, src) (dst) = (src)
+#endif
#endif /* #if !defined(__MINGW32__) && !defined(__MINGW64__) */
#ifdef _MSC_VER
@@ -107,10 +109,14 @@
#define unlink _unlink
#endif
+#if defined(_MSC_VER) && _MSC_VER >= 1800
+#include <inttypes.h>
+#else
#define PRId32 "d"
#define PRIu32 "u"
#define PRId64 "I64d"
#define PRIu64 "I64u"
+#endif
#if !defined(__MINGW32__) && !defined(__MINGW64__)
#define strtoq _strtoi64