summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCraig Silverstein <csilvers+gflags@google.com>2011-07-29 04:26:49 +0000
committerCraig Silverstein <csilvers+gflags@google.com>2011-07-29 04:26:49 +0000
commit917f4e7bf3c36b4c56a77faca639758d3aca2a92 (patch)
tree65ee3102df263ae4da6d6fd57ac0326775a11b4c /src
parentb7ea0659625be5cf8c9c3954ea2fe28f39300f81 (diff)
downloadgflags-917f4e7bf3c36b4c56a77faca639758d3aca2a92.tar.gz
gflags-917f4e7bf3c36b4c56a77faca639758d3aca2a92.tar.bz2
gflags-917f4e7bf3c36b4c56a77faca639758d3aca2a92.zip
Some reorganization that results from a new method I'm moving to to
maintaining this opensource tree. Some of this reorganization is entirely a result of reorganization: blank lines in a few different places, etc. Here are the others: 1) I've added a new file, util.h, with lots of new, helpful routines, most notably StringPrintf (printf returning a string). I've also moved some routines from the .cc and unittest.cc file here, such as the CHECK macros, testing framework, and #ifdefs for 16-bit ints. Quite a bit of code was rewritten to use these new routines. 2) I noticed that the special-case setenv() code was only needed for windows systems, so I moved it to port.h/cc. 3) I also had to add a new vsnprintf wrapper in port.h/cc, to support StringPrintf. 4) A few places I used an old name, commandlineflags, instead of gflags. Most or all of these should be fixed now. 5) Some of my copyright dates weren't quite right. Fixed them up. 6) In some .cc files, I added using directives to not have to use std:: so much. 7) I've added a minor new test, adding 10000 or so flags to see how the system scales. 8) Some compile-warning fixes, such as int -> size_t when appropriate, and better protected #defines in mutex.h 9) The .h files gained some logic defining GFLAGS_DLL_DECL. This is true even for .h files outside the windows directory, which will never have these dll issues. But one big advantage of my new organization is auto-generating the windows versions of these files from the unix versions, so there's some unnecessary (but harmless) duplication as a result. 10) Fixed a bug in rpm.sh which would cause an unnecessary crash when dpkg was missing. git-svn-id: https://gflags.googlecode.com/svn/trunk@52 6586e3c6-dcc4-952a-343f-ff74eb82781d
Diffstat (limited to 'src')
-rw-r--r--src/config.h.in9
-rw-r--r--src/config_for_unittests.h1
-rw-r--r--src/gflags.cc271
-rw-r--r--src/gflags/gflags.h.in184
-rw-r--r--src/gflags/gflags_completions.h.in28
-rw-r--r--src/gflags/gflags_declare.h.in88
-rw-r--r--src/gflags_completions.cc109
-rwxr-xr-xsrc/gflags_completions.sh10
-rw-r--r--src/gflags_nc.cc3
-rw-r--r--src/gflags_reporting.cc69
-rw-r--r--src/gflags_strip_flags_test.cc11
-rwxr-xr-xsrc/gflags_strip_flags_test.sh22
-rw-r--r--src/gflags_unittest.cc345
-rwxr-xr-xsrc/gflags_unittest.sh65
-rw-r--r--src/mutex.h13
-rw-r--r--src/util.h319
-rw-r--r--src/windows/gflags/gflags.h205
-rw-r--r--src/windows/gflags/gflags_completions.h21
-rw-r--r--src/windows/gflags/gflags_declare.h84
-rw-r--r--src/windows/port.cc39
-rw-r--r--src/windows/port.h22
21 files changed, 1138 insertions, 780 deletions
diff --git a/src/config.h.in b/src/config.h.in
index e7bd4d0..28dfa37 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -28,12 +28,6 @@
/* Define if you have POSIX threads libraries and header files. */
#undef HAVE_PTHREAD
-/* Define to 1 if you have the `putenv' function. */
-#undef HAVE_PUTENV
-
-/* Define to 1 if you have the `setenv' function. */
-#undef HAVE_SETENV
-
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
@@ -83,9 +77,6 @@
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
-/* Define to the home page for this package. */
-#undef PACKAGE_URL
-
/* Define to the version of this package. */
#undef PACKAGE_VERSION
diff --git a/src/config_for_unittests.h b/src/config_for_unittests.h
index d287e86..ac0df4c 100644
--- a/src/config_for_unittests.h
+++ b/src/config_for_unittests.h
@@ -30,7 +30,6 @@
// ---
// All Rights Reserved.
//
-// Author: Craig Silverstein
//
// This file is needed for windows -- unittests are not part of the
// gflags dll, but still want to include config.h just like the
diff --git a/src/gflags.cc b/src/gflags.cc
index 460d427..63cee62 100644
--- a/src/gflags.cc
+++ b/src/gflags.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006, Google Inc.
+// Copyright (c) 1999, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -28,7 +28,6 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ---
-// Author: Ray Sidney
// Revamped and reorganized by Craig Silverstein
//
// This file contains the implementation of all our command line flags
@@ -88,63 +87,35 @@
// other hand, hooks into CommandLineFlagParser. Other API functions
// are, similarly, mostly hooks into the functionality described above.
-#include "config.h"
// This comes first to ensure we define __STDC_FORMAT_MACROS in time.
-#ifdef HAVE_INTTYPES_H
-#ifndef __STDC_FORMAT_MACROS
+#include <config.h>
+#if defined(HAVE_INTTYPES_H) && !defined(__STDC_FORMAT_MACROS)
# define __STDC_FORMAT_MACROS 1 // gcc requires this to get PRId64, etc.
#endif
-#include <inttypes.h>
-#endif // HAVE_INTTYPES_H
-#include <stdio.h> // for snprintf
+
+#include <gflags/gflags.h>
+#include <assert.h>
#include <ctype.h>
#include <errno.h>
-#include <stdio.h>
+#ifdef HAVE_FNMATCH_H
+# include <fnmatch.h>
+#endif
#include <stdarg.h> // For va_list and related operations
+#include <stdio.h>
#include <string.h>
-#include <assert.h>
-#ifdef HAVE_FNMATCH_H
-#include <fnmatch.h>
-#endif // HAVE_FNMATCH_H
-#include <string>
+
+#include <algorithm>
#include <map>
-#include <vector>
+#include <string>
#include <utility> // for pair<>
-#include <algorithm>
-#include <gflags/gflags.h>
+#include <vector>
#include "mutex.h"
+#include "util.h"
#ifndef PATH_SEPARATOR
#define PATH_SEPARATOR '/'
#endif
-// Work properly if either strtoll or strtoq is on this system
-#ifdef HAVE_STRTOLL
-# define strtoint64 strtoll
-# define strtouint64 strtoull
-#elif HAVE_STRTOQ
-# define strtoint64 strtoq
-# define strtouint64 strtouq
-#else
-// Neither strtoll nor strtoq are defined. I hope strtol works!
-# define strtoint64 strtol
-# define strtouint64 strtoul
-#endif
-
-// If we have inttypes.h, it will have defined PRId32/etc for us. If
-// not, take our best guess.
-#ifndef PRId32
-# define PRId32 "d"
-#endif
-#ifndef PRId64
-# define PRId64 "lld"
-#endif
-#ifndef PRIu64
-# define PRIu64 "llu"
-#endif
-
-typedef signed char int8;
-typedef unsigned char uint8;
// Special flags, type 1: the 'recursive' flags. They set another flag's val.
DEFINE_string(flagfile, "",
@@ -170,20 +141,21 @@ using std::sort;
using std::string;
using std::vector;
+// This is used by the unittest to test error-exit code
+void GFLAGS_DLL_DECL (*gflags_exitfunc)(int) = &exit; // from stdlib.h
+
+
// The help message indicating that the commandline flag has been
// 'stripped'. It will not show up when doing "-help" and its
// variants. The flag is stripped if STRIP_FLAG_HELP is set to 1
-// before including gflags/gflags.h.
+// before including base/gflags.h
-// This is used by this file, and also in commandlineflags_reporting.cc
+// This is used by this file, and also in gflags_reporting.cc
const char kStrippedFlagHelp[] = "\001\002\003\004 (unknown) \004\003\002\001";
-// This is used by the unittest to test error-exit code
-void GFLAGS_DLL_DECL (*commandlineflags_exitfunc)(int) = &exit; // from stdlib.h
-
namespace {
-// There are also 'reporting' flags, in commandlineflags_reporting.cc.
+// There are also 'reporting' flags, in gflags_reporting.cc.
static const char kError[] = "ERROR: ";
@@ -205,12 +177,13 @@ enum DieWhenReporting { DIE, DO_NOT_DIE };
// Report Error and exit if requested.
static void ReportError(DieWhenReporting should_die, const char* format, ...) {
+ char error_message[255];
va_list ap;
va_start(ap, format);
- vfprintf(stderr, format, ap);
+ vsnprintf(error_message, sizeof(error_message), format, ap);
va_end(ap);
- if (should_die == DIE)
- commandlineflags_exitfunc(1); // almost certainly exit()
+ fprintf(stderr, "%s", error_message);
+ if (should_die == DIE) gflags_exitfunc(1);
}
@@ -304,6 +277,7 @@ bool FlagValue::ParseFrom(const char* value) {
if (type_ == FV_BOOL) {
const char* kTrue[] = { "1", "t", "true", "y", "yes" };
const char* kFalse[] = { "0", "f", "false", "n", "no" };
+ COMPILE_ASSERT(sizeof(kTrue) == sizeof(kFalse), true_false_equal);
for (size_t i = 0; i < sizeof(kTrue)/sizeof(*kTrue); ++i) {
if (strcasecmp(value, kTrue[i]) == 0) {
SET_VALUE_AS(bool, true);
@@ -333,7 +307,7 @@ bool FlagValue::ParseFrom(const char* value) {
switch (type_) {
case FV_INT32: {
- const int64 r = strtoint64(value, &end, base);
+ const int64 r = strto64(value, &end, base);
if (errno || end != value + strlen(value)) return false; // bad parse
if (static_cast<int32>(r) != r) // worked, but number out of range
return false;
@@ -341,7 +315,7 @@ bool FlagValue::ParseFrom(const char* value) {
return true;
}
case FV_INT64: {
- const int64 r = strtoint64(value, &end, base);
+ const int64 r = strto64(value, &end, base);
if (errno || end != value + strlen(value)) return false; // bad parse
SET_VALUE_AS(int64, r);
return true;
@@ -349,7 +323,7 @@ bool FlagValue::ParseFrom(const char* value) {
case FV_UINT64: {
while (*value == ' ') value++;
if (*value == '-') return false; // negative number
- const uint64 r = strtouint64(value, &end, base);
+ const uint64 r = strtou64(value, &end, base);
if (errno || end != value + strlen(value)) return false; // bad parse
SET_VALUE_AS(uint64, r);
return true;
@@ -570,7 +544,6 @@ const char* CommandLineFlag::CleanFileName() const {
// 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,
- // e.g. "myproject"
if (sizeof(kRootDir)-1 == 0) // no prefix to strip
return filename();
@@ -579,8 +552,7 @@ const char* CommandLineFlag::CleanFileName() const {
while ( clean_name > filename() ) {
if (*clean_name == PATH_SEPARATOR) {
if (strncmp(clean_name, kRootDir, sizeof(kRootDir)-1) == 0) {
- // ".../myproject/base/logging.cc" ==> "base/logging.cc"
- clean_name += sizeof(kRootDir)-1; // past "/myproject/"
+ clean_name += sizeof(kRootDir)-1; // past root-dir
break;
}
}
@@ -621,6 +593,7 @@ void CommandLineFlag::CopyFrom(const CommandLineFlag& src) {
}
bool CommandLineFlag::Validate(const FlagValue& value) const {
+
if (validate_function() == NULL)
return true;
else
@@ -644,10 +617,14 @@ struct StringCmp { // Used by the FlagRegistry map class to compare char*'s
}
};
+
class FlagRegistry {
public:
- FlagRegistry() { }
+ FlagRegistry() {
+ }
~FlagRegistry() {
+ // Not using STLDeleteElements as that resides in util and this
+ // class is base.
for (FlagMap::iterator p = flags_.begin(), e = flags_.end(); p != e; ++p) {
CommandLineFlag* flag = p->second;
delete flag;
@@ -659,12 +636,12 @@ class FlagRegistry {
global_registry_ = NULL;
}
- void Lock() { lock_.Lock(); }
- void Unlock() { lock_.Unlock(); }
-
// Store a flag in this registry. Takes ownership of the given pointer.
void RegisterFlag(CommandLineFlag* flag);
+ void Lock() { lock_.Lock(); }
+ void Unlock() { lock_.Unlock(); }
+
// Returns the flag object for the specified name, or NULL if not found.
CommandLineFlag* FindFlagLocked(const char* name);
@@ -705,26 +682,26 @@ class FlagRegistry {
typedef map<const void*, CommandLineFlag*> FlagPtrMap;
FlagPtrMap flags_by_ptr_;
+ static FlagRegistry* global_registry_; // a singleton registry
+
Mutex lock_;
+ static Mutex global_registry_lock_;
- static FlagRegistry* global_registry_; // a singleton registry
- static Mutex global_registry_lock_; // guards creation of global_registry_
+ static void InitGlobalRegistry();
// Disallow
FlagRegistry(const FlagRegistry&);
FlagRegistry& operator=(const FlagRegistry&);
};
-FlagRegistry* FlagRegistry::global_registry_ = NULL;
-Mutex FlagRegistry::global_registry_lock_(Mutex::LINKER_INITIALIZED);
+class FlagRegistryLock {
+ public:
+ explicit FlagRegistryLock(FlagRegistry* fr) : fr_(fr) { fr_->Lock(); }
+ ~FlagRegistryLock() { fr_->Unlock(); }
+ private:
+ FlagRegistry *const fr_;
+};
-FlagRegistry* FlagRegistry::GlobalRegistry() {
- MutexLock acquire_lock(&global_registry_lock_);
- if (!global_registry_) {
- global_registry_ = new FlagRegistry;
- }
- return global_registry_;
-}
void FlagRegistry::RegisterFlag(CommandLineFlag* flag) {
Lock();
@@ -794,22 +771,22 @@ CommandLineFlag* FlagRegistry::SplitArgumentLocked(const char* arg,
// In that case, we want to return flag 'x'.
if (!(flag_name[0] == 'n' && flag_name[1] == 'o')) {
// flag-name is not 'nox', so we're not in the exception case.
- *error_message = (string(kError) +
- "unknown command line flag '" + *key + "'\n");
+ *error_message = StringPrintf("%sunknown command line flag '%s'\n",
+ kError, key->c_str());
return NULL;
}
flag = FindFlagLocked(flag_name+2);
if (flag == NULL) {
// No flag named 'x' exists, so we're not in the exception case.
- *error_message = (string(kError) +
- "unknown command line flag '" + *key + "'\n");
+ *error_message = StringPrintf("%sunknown command line flag '%s'\n",
+ kError, key->c_str());
return NULL;
}
if (strcmp(flag->type_name(), "bool") != 0) {
// 'x' exists but is not boolean, so we're not in the exception case.
- *error_message = (string(kError) +
- "boolean value (" + *key + ") specified for " +
- flag->type_name() + " command line flag\n");
+ *error_message = StringPrintf(
+ "%sboolean value (%s) specified for %s command line flag\n",
+ kError, key->c_str(), flag->type_name());
return NULL;
}
// We're in the exception case!
@@ -832,25 +809,27 @@ bool TryParseLocked(const CommandLineFlag* flag, FlagValue* flag_value,
FlagValue* tentative_value = flag_value->New();
if (!tentative_value->ParseFrom(value)) {
if (msg) {
- *msg += (string(kError) + "illegal value '" + value +
- + "' specified for " + flag->type_name() + " flag '"
- + flag->name() + "'\n");
+ StringAppendF(msg,
+ "%sillegal value '%s' specified for %s flag '%s'\n",
+ kError, value,
+ flag->type_name(), flag->name());
}
delete tentative_value;
return false;
} else if (!flag->Validate(*tentative_value)) {
if (msg) {
- *msg += (string(kError) + "failed validation of new value "
- + "'" + tentative_value->ToString() + "' for flag '" +
- + flag->name() + "'\n");
+ StringAppendF(msg,
+ "%sfailed validation of new value '%s' for flag '%s'\n",
+ kError, tentative_value->ToString().c_str(),
+ flag->name());
}
delete tentative_value;
return false;
} else {
flag_value->CopyFrom(*tentative_value);
if (msg) {
- *msg += (string(flag->name()) + " set to " + flag_value->ToString()
- + "\n");
+ StringAppendF(msg, "%s set to %s\n",
+ flag->name(), flag_value->ToString().c_str());
}
delete tentative_value;
return true;
@@ -877,7 +856,8 @@ bool FlagRegistry::SetFlagLocked(CommandLineFlag* flag,
return false;
flag->modified_ = true;
} else {
- *msg = string(flag->name()) + " set to " + flag->current_value();
+ *msg = StringPrintf("%s set to %s",
+ flag->name(), flag->current_value().c_str());
}
break;
}
@@ -901,13 +881,17 @@ bool FlagRegistry::SetFlagLocked(CommandLineFlag* flag,
return true;
}
-class FlagRegistryLock {
- public:
- explicit FlagRegistryLock(FlagRegistry* fr) : fr_(fr) { fr_->Lock(); }
- ~FlagRegistryLock() { fr_->Unlock(); }
- private:
- FlagRegistry *const fr_;
-};
+// Get the singleton FlagRegistry object
+FlagRegistry* FlagRegistry::global_registry_ = NULL;
+Mutex FlagRegistry::global_registry_lock_(Mutex::LINKER_INITIALIZED);
+
+FlagRegistry* FlagRegistry::GlobalRegistry() {
+ MutexLock acquire_lock(&global_registry_lock_);
+ if (!global_registry_) {
+ global_registry_ = new FlagRegistry;
+ }
+ return global_registry_;
+}
// --------------------------------------------------------------------
// CommandLineFlagParser
@@ -989,12 +973,12 @@ class CommandLineFlagParser {
static void ParseFlagList(const char* value, vector<string>* flags) {
for (const char *p = value; p && *p; value = p) {
p = strchr(value, ',');
- int len;
+ size_t len;
if (p) {
- len = static_cast<int>(p - value);
+ len = p - value;
p++;
} else {
- len = static_cast<int>(strlen(value));
+ len = strlen(value);
}
if (len == 0)
@@ -1010,7 +994,7 @@ static void ParseFlagList(const char* value, vector<string>* flags) {
// can do all the I/O in one place and not worry about it everywhere.
// Plus, it's convenient to have the whole file contents at hand.
// Adds a newline at the end of the file.
-#define PFATAL(s) do { perror(s); commandlineflags_exitfunc(1); } while (0)
+#define PFATAL(s) do { perror(s); gflags_exitfunc(1); } while (0)
static string ReadFileIntoString(const char* filename) {
const int kBufSize = 8092;
@@ -1099,9 +1083,9 @@ uint32 CommandLineFlagParser::ParseNewCommandLineFlags(int* argc, char*** argv,
&& strcmp(flag->type_name(), "string") == 0
&& (strstr(flag->help(), "true")
|| strstr(flag->help(), "false"))) {
- fprintf(stderr, "Did you really mean to set flag '%s'"
- " to the value '%s'?\n",
- flag->name(), value);
+ LOG(WARNING) << "Did you really mean to set flag '"
+ << flag->name() << "' to the value '"
+ << value << "'?";
}
}
}
@@ -1152,9 +1136,10 @@ string CommandLineFlagParser::ProcessFromenvLocked(const string& flagval,
const char* flagname = flaglist[i].c_str();
CommandLineFlag* flag = registry_->FindFlagLocked(flagname);
if (flag == NULL) {
- error_flags_[flagname] = (string(kError) + "unknown command line flag"
- + " '" + flagname + "'"
- + " (via --fromenv or --tryfromenv)\n");
+ error_flags_[flagname] =
+ StringPrintf("%sunknown command line flag '%s' "
+ "(via --fromenv or --tryfromenv)\n",
+ kError, flagname);
undefined_names_[flagname] = "";
continue;
}
@@ -1172,8 +1157,9 @@ string CommandLineFlagParser::ProcessFromenvLocked(const string& flagval,
// Avoid infinite recursion.
if ((strcmp(envval, "fromenv") == 0) ||
(strcmp(envval, "tryfromenv") == 0)) {
- error_flags_[flagname] = (string(kError) + "infinite recursion on " +
- "environment flag '" + envval + "'\n");
+ error_flags_[flagname] =
+ StringPrintf("%sinfinite recursion on environment flag '%s'\n",
+ kError, envval);
continue;
}
@@ -1276,7 +1262,7 @@ string CommandLineFlagParser::ProcessOptionsFromStringLocked(
while (*flagfile_contents && isspace(*flagfile_contents))
++flagfile_contents;
line_end = strchr(flagfile_contents, '\n');
- size_t len = line_end ? static_cast<size_t>(line_end - flagfile_contents)
+ size_t len = line_end ? line_end - flagfile_contents
: strlen(flagfile_contents);
string line(flagfile_contents, len);
@@ -1327,17 +1313,17 @@ string CommandLineFlagParser::ProcessOptionsFromStringLocked(
space = word + strlen(word);
const string glob(word, space - word);
// We try matching both against the full argv0 and basename(argv0)
+ if (glob == ProgramInvocationName() // small optimization
+ || glob == ProgramInvocationShortName()
#ifdef HAVE_FNMATCH_H
- if (fnmatch(glob.c_str(),
- ProgramInvocationName(),
- FNM_PATHNAME) == 0 ||
- fnmatch(glob.c_str(),
- ProgramInvocationShortName(),
- FNM_PATHNAME) == 0) {
-#else // !HAVE_FNMATCH_H
- if ((glob == ProgramInvocationName()) ||
- (glob == ProgramInvocationShortName())) {
-#endif // HAVE_FNMATCH_H
+ || fnmatch(glob.c_str(),
+ ProgramInvocationName(),
+ FNM_PATHNAME) == 0
+ || fnmatch(glob.c_str(),
+ ProgramInvocationShortName(),
+ FNM_PATHNAME) == 0
+#endif
+ ) {
flags_are_relevant = true;
}
}
@@ -1378,14 +1364,14 @@ bool AddFlagValidator(const void* flag_ptr, ValidateFnProto validate_fn_proto) {
// This is the CommandLineFlag whose current_->value_buffer_ == flag
CommandLineFlag* flag = registry->FindFlagViaPtrLocked(flag_ptr);
if (!flag) {
- // WARNING << "Ignoring RegisterValidateFunction() for flag pointer "
- // << flag_ptr << ": no flag found at that address";
+ LOG(WARNING) << "Ignoring RegisterValidateFunction() for flag pointer "
+ << flag_ptr << ": no flag found at that address";
return false;
} else if (validate_fn_proto == flag->validate_function()) {
return true; // ok to register the same function over and over again
} else if (validate_fn_proto != NULL && flag->validate_function() != NULL) {
- // WARNING << "Ignoring RegisterValidateFunction() for flag '"
- // << flag->name() << "': validate-fn already registered";
+ LOG(WARNING) << "Ignoring RegisterValidateFunction() for flag '"
+ << flag->name() << "': validate-fn already registered";
return false;
} else {
flag->validate_fn_proto_ = validate_fn_proto;
@@ -1467,12 +1453,9 @@ void GetAllFlags(vector<CommandLineFlagInfo>* OUTPUT) {
// ProgramInvocationShortName()
// SetUsageMessage()
// ProgramUsage()
-// SetVersionString()
-// VersionString()
// Functions to set and get argv. Typically the setter is called
// by ParseCommandLineFlags. Also can get the ProgramUsage string,
-// set by SetUsageMessage, and the version string, set by
-// SetVersionString.
+// set by SetUsageMessage.
// --------------------------------------------------------------------
// These values are not protected by a Mutex because they are normally
@@ -1482,7 +1465,6 @@ static const char* cmdline = ""; // the entire command-line
static vector<string> argvs;
static uint32 argv_sum = 0;
static const char* program_usage = NULL;
-static const char* version_string = NULL;
void SetArgv(int argc, const char** argv) {
static bool called_set_argv = false;
@@ -1532,12 +1514,6 @@ void SetUsageMessage(const string& usage) {
program_usage = strdup(usage.c_str()); // small memory leak
}
-void SetVersionString(const string& version) {
- if (version_string != NULL)
- ReportError(DIE, "ERROR: SetVersionString() called twice\n");
- version_string = strdup(version.c_str()); // small memory leak
-}
-
const char* ProgramUsage() {
if (program_usage) {
return program_usage;
@@ -1545,10 +1521,24 @@ const char* ProgramUsage() {
return "Warning: SetUsageMessage() never called";
}
+// --------------------------------------------------------------------
+// SetVersionString()
+// VersionString()
+// --------------------------------------------------------------------
+
+static const char* version_string = NULL;
+
+void SetVersionString(const string& version) {
+ if (version_string != NULL)
+ ReportError(DIE, "ERROR: SetVersionString() called twice\n");
+ version_string = strdup(version.c_str()); // small memory leak
+}
+
const char* VersionString() {
return version_string ? version_string : "";
}
+
// --------------------------------------------------------------------
// GetCommandLineOption()
// GetCommandLineFlagInfo()
@@ -1602,7 +1592,7 @@ CommandLineFlagInfo GetCommandLineFlagInfoOrDie(const char* name) {
CommandLineFlagInfo info;
if (!GetCommandLineFlagInfo(name, &info)) {
fprintf(stderr, "FATAL ERROR: flag name '%s' doesn't exist\n", name);
- commandlineflags_exitfunc(1); // almost certainly exit()
+ gflags_exitfunc(1); // almost certainly gflags_exitfunc()
}
return info;
}
@@ -1617,10 +1607,7 @@ string SetCommandLineOptionWithMode(const char* name, const char* value,
CommandLineFlagParser parser(registry);
result = parser.ProcessSingleOptionLocked(flag, value, set_mode);
if (!result.empty()) { // in the error case, we've already logged
- // You could consider logging this change, if you wanted to know it:
- //fprintf(stderr, "%sFLAGS_%s\n",
- // (set_mode == SET_FLAGS_DEFAULT ? "default value of " : ""),
- // result);
+ // Could consider logging this change
}
}
// The API of this function is that we return empty string on error
@@ -1766,7 +1753,7 @@ bool ReadFlagsFromString(const string& flagfilecontents,
if (parser.ReportErrors()) {
// Error. Restore all global flags to their previous values.
if (errors_are_fatal)
- commandlineflags_exitfunc(1); // almost certainly exit()
+ gflags_exitfunc(1);
saved_states.RestoreToRegistry();
return false;
}
@@ -1918,7 +1905,7 @@ static uint32 ParseCommandLineFlagsInternal(int* argc, char*** argv,
parser.ValidateAllFlags();
if (parser.ReportErrors()) // may cause us to exit on illegal flags
- commandlineflags_exitfunc(1); // almost certainly exit()
+ gflags_exitfunc(1);
return r;
}
diff --git a/src/gflags/gflags.h.in b/src/gflags/gflags.h.in
index 2eaec2b..154ae82 100644
--- a/src/gflags/gflags.h.in
+++ b/src/gflags/gflags.h.in
@@ -28,7 +28,6 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ---
-// Author: Ray Sidney
// Revamped and reorganized by Craig Silverstein
//
// This is the file that should be included by any file which declares
@@ -52,8 +51,8 @@
// if (FLAGS_verbose) printf("Records %d-%d\n", FLAGS_start, FLAGS_end);
// }
//
-// Then, at the command-line:
-// ./foo --noverbose --start=5 --end=100
+// Then, at the command-line:
+// ./foo --noverbose --start=5 --end=100
//
// For more details, see
// doc/gflags.html
@@ -76,15 +75,23 @@
// other thread is writing to the variable or calling non-const
// methods of this class.
-#ifndef GOOGLE_GFLAGS_H_
-#define GOOGLE_GFLAGS_H_
+#ifndef BASE_COMMANDLINEFLAGS_H_
+#define BASE_COMMANDLINEFLAGS_H_
#include <string>
#include <vector>
#include <gflags/gflags_declare.h> // IWYU pragma: export
-
@ac_google_start_namespace@
+//
+// NOTE: all functions below MUST have an explicit 'extern' before
+// them. Our automated opensourcing tools use this as a signal to do
+// appropriate munging for windows, which needs to add GFLAGS_DLL_DECL.
+//
+#ifdef SWIG // it apparently can't see the define in gflags_declare.h
+# define GFLAGS_DLL_DECL /**/
+#endif
+
// --------------------------------------------------------------------
// To actually define a flag in a file, use DEFINE_bool,
// DEFINE_string, etc. at the bottom of this file. You may also find
@@ -114,18 +121,19 @@
// Returns true if successfully registered, false if not (because the
// first argument doesn't point to a command-line flag, or because a
// validator is already registered for this flag).
-bool RegisterFlagValidator(const bool* flag,
- bool (*validate_fn)(const char*, bool));
-bool RegisterFlagValidator(const int32* flag,
- bool (*validate_fn)(const char*, int32));
-bool RegisterFlagValidator(const int64* flag,
- bool (*validate_fn)(const char*, int64));
-bool RegisterFlagValidator(const uint64* flag,
- bool (*validate_fn)(const char*, uint64));
-bool RegisterFlagValidator(const double* flag,
- bool (*validate_fn)(const char*, double));
-bool RegisterFlagValidator(const std::string* flag,
- bool (*validate_fn)(const char*, const std::string&));
+extern bool RegisterFlagValidator(const bool* flag,
+ bool (*validate_fn)(const char*, bool));
+extern bool RegisterFlagValidator(const int32* flag,
+ bool (*validate_fn)(const char*, int32));
+extern bool RegisterFlagValidator(const int64* flag,
+ bool (*validate_fn)(const char*, int64));
+extern bool RegisterFlagValidator(const uint64* flag,
+ bool (*validate_fn)(const char*, uint64));
+extern bool RegisterFlagValidator(const double* flag,
+ bool (*validate_fn)(const char*, double));
+extern bool RegisterFlagValidator(const std::string* flag,
+ bool (*validate_fn)(const char*,
+ const std::string&));
// --------------------------------------------------------------------
@@ -139,21 +147,21 @@ bool RegisterFlagValidator(const std::string* flag,
// name) and argv (the entire commandline), which we sock away a copy of.
// These variables are static, so you should only set them once.
-struct CommandLineFlagInfo {
- std::string name; // the name of the flag
- std::string type; // the type of the flag: int32, etc
- std::string description; // the "help text" associated with the flag
- std::string current_value; // the current value, as a string
- std::string default_value; // the default value, as a string
- std::string filename; // 'cleaned' version of filename holding the flag
- bool has_validator_fn; // true if RegisterFlagValidator called on flag
- bool is_default; // true if the flag has the default value and
- // has not been set explicitly from the cmdline
- // or via SetCommandLineOption
+struct GFLAGS_DLL_DECL CommandLineFlagInfo {
+ std::string name; // the name of the flag
+ std::string type; // the type of the flag: int32, etc
+ std::string description; // the "help text" associated with the flag
+ std::string current_value; // the current value, as a string
+ std::string default_value; // the default value, as a string
+ std::string filename; // 'cleaned' version of filename holding the flag
+ bool has_validator_fn; // true if RegisterFlagValidator called on this flag
+ bool is_default; // true if the flag has the default value and
+ // has not been set explicitly from the cmdline
+ // or via SetCommandLineOption
};
// Using this inside of a validator is a recipe for a deadlock.
-// TODO(wojtekm) Fix locking when validators are running, to make it safe to
+// TODO(user) Fix locking when validators are running, to make it safe to
// call validators during ParseAllFlags.
// Also make sure then to uncomment the corresponding unit test in
// gflags_unittest.sh
@@ -168,20 +176,26 @@ extern std::string DescribeOneFlag(const CommandLineFlagInfo& flag);
// Thread-hostile; meant to be called before any threads are spawned.
extern void SetArgv(int argc, const char** argv);
+
// The following functions are thread-safe as long as SetArgv() is
// only called before any threads start.
-extern const std::vector<std::string>& GetArgvs(); // all of argv as a vector
-extern const char* GetArgv(); // all of argv as a string
-extern const char* GetArgv0(); // only argv0
-extern uint32 GetArgvSum(); // simple checksum of argv
-extern const char* ProgramInvocationName(); // argv0, or "UNKNOWN" if not set
+extern const std::vector<std::string>& GetArgvs();
+extern const char* GetArgv(); // all of argv as a string
+extern const char* GetArgv0(); // only argv0
+extern uint32 GetArgvSum(); // simple checksum of argv
+extern const char* ProgramInvocationName(); // argv0, or "UNKNOWN" if not set
extern const char* ProgramInvocationShortName(); // basename(argv0)
-// ProgramUsage() and VersionString() are thread-safe as long as
-// SetUsageMessage() and SetVersionString() are only called before any
-// threads start.
-extern const char* ProgramUsage(); // string set by SetUsageMessage()
+
+// ProgramUsage() is thread-safe as long as SetUsageMessage() is only
+// called before any threads start.
+extern const char* ProgramUsage(); // string set by SetUsageMessage()
+
+// VersionString() is thread-safe as long as SetVersionString() is only
+// called before any threads start.
extern const char* VersionString(); // string set by SetVersionString()
+
+
// --------------------------------------------------------------------
// Normally you access commandline flags by just saying "if (FLAGS_foo)"
// or whatever, and set them by calling "FLAGS_foo = bar" (or, more
@@ -204,7 +218,7 @@ extern bool GetCommandLineFlagInfo(const char* name,
// if (GetCommandLineFlagInfoOrDie("foo").is_default) ...
extern CommandLineFlagInfo GetCommandLineFlagInfoOrDie(const char* name);
-enum FlagSettingMode {
+enum GFLAGS_DLL_DECL FlagSettingMode {
// update the flag's value (can call this multiple times).
SET_FLAGS_VALUE,
// update the flag's value, but *only if* it has not yet been updated
@@ -226,7 +240,7 @@ enum FlagSettingMode {
// SetCommandLineOption uses set_mode == SET_FLAGS_VALUE (the common case)
extern std::string SetCommandLineOption(const char* name, const char* value);
extern std::string SetCommandLineOptionWithMode(const char* name, const char* value,
- FlagSettingMode set_mode);
+ FlagSettingMode set_mode);
// --------------------------------------------------------------------
@@ -247,14 +261,14 @@ extern std::string SetCommandLineOptionWithMode(const char* name, const char* va
// // without worrying about restoring the FLAG values.
// }
//
-// Note: This class is marked with __attribute__((unused)) because all the
+// Note: This class is marked with ATTRIBUTE_UNUSED because all the
// work is done in the constructor and destructor, so in the standard
// usage example above, the compiler would complain that it's an
// unused variable.
//
// This class is thread-safe.
-class FlagSaver {
+class GFLAGS_DLL_DECL FlagSaver {
public:
FlagSaver();
~FlagSaver();
@@ -264,7 +278,8 @@ class FlagSaver {
FlagSaver(const FlagSaver&); // no copying!
void operator=(const FlagSaver&);
-} @ac_cv___attribute__unused@;
+}
+@ac_cv___attribute__unused@;
// --------------------------------------------------------------------
// Some deprecated or hopefully-soon-to-be-deprecated functions.
@@ -274,12 +289,11 @@ extern std::string CommandlineFlagsIntoString();
// Usually where this is used, a FlagSaver should be used instead.
extern bool ReadFlagsFromString(const std::string& flagfilecontents,
const char* prog_name,
- bool errors_are_fatal); // uses SET_FLAGS_VALUE
+ bool errors_are_fatal); // uses SET_FLAGS_VALUE
// These let you manually implement --flagfile functionality.
// DEPRECATED.
extern bool AppendFlagsIntoFile(const std::string& filename, const char* prog_name);
-extern bool SaveCommandFlags(); // actually defined in google.cc !
extern bool ReadFromFlagsFile(const std::string& filename, const char* prog_name,
bool errors_are_fatal); // uses SET_FLAGS_VALUE
@@ -301,7 +315,7 @@ extern const char *StringFromEnv(const char *varname, const char *defval);
// --------------------------------------------------------------------
-// The next two functions parse commandlineflags from main():
+// The next two functions parse gflags from main():
// Set the "usage" message for this program. For example:
// string usage("This program does nothing. Sample usage:\n");
@@ -316,6 +330,7 @@ extern void SetUsageMessage(const std::string& usage);
// Thread-hostile; meant to be called before any threads are spawned.
extern void SetVersionString(const std::string& version);
+
// Looks for flags in argv and parses them. Rearranges argv to put
// flags first, or removes them entirely if remove_flags is true.
// If a flag is defined more than once in the command line or flag
@@ -323,8 +338,7 @@ extern void SetVersionString(const std::string& version);
// of the first non-flag argument.
// See top-of-file for more details on this function.
#ifndef SWIG // In swig, use ParseCommandLineFlagsScript() instead.
-extern uint32 ParseCommandLineFlags(int *argc, char*** argv,
- bool remove_flags);
+extern uint32 ParseCommandLineFlags(int *argc, char*** argv, bool remove_flags);
#endif
@@ -362,11 +376,12 @@ extern void ReparseCommandLineNonHelpFlags();
// Clean up memory allocated by flags. This is only needed to reduce
// the quantity of "potentially leaked" reports emitted by memory
// debugging tools such as valgrind. It is not required for normal
-// operation, or for the perftools heap-checker. It must only be called
-// when the process is about to exit, and all threads that might
-// access flags are quiescent. Referencing flags after this is called
-// will have unexpected consequences. This is not safe to run when
-// multiple threads might be running: the function is thread-hostile.
+// operation, or for the google perftools heap-checker. It must only
+// be called when the process is about to exit, and all threads that
+// might access flags are quiescent. Referencing flags after this is
+// called will have unexpected consequences. This is not safe to run
+// when multiple threads might be running: the function is
+// thread-hostile.
extern void ShutDownCommandLineFlags();
@@ -407,15 +422,13 @@ extern void ShutDownCommandLineFlags();
// people can't DECLARE_int32 something that they DEFINE_bool'd
// elsewhere.
-class FlagRegisterer {
+class GFLAGS_DLL_DECL FlagRegisterer {
public:
FlagRegisterer(const char* name, const char* type,
const char* help, const char* filename,
void* current_storage, void* defvalue_storage);
};
-extern bool FlagsTypeWarn(const char *name);
-
// 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
@@ -429,7 +442,8 @@ extern const char kStrippedFlagHelp[];
#if defined(STRIP_FLAG_HELP) && STRIP_FLAG_HELP > 0
// Need this construct to avoid the 'defined but not used' warning.
-#define MAYBE_STRIPPED_HELP(txt) (false ? (txt) : @ac_google_namespace@::kStrippedFlagHelp)
+#define MAYBE_STRIPPED_HELP(txt) \
+ (false ? (txt) : @ac_google_namespace@::kStrippedFlagHelp)
#else
#define MAYBE_STRIPPED_HELP(txt) txt
#endif
@@ -445,15 +459,16 @@ extern const char kStrippedFlagHelp[];
// FLAGS_no<name>. This serves the second purpose of assuring a
// compile error if someone tries to define a flag named no<name>
// which is illegal (--foo and --nofoo both affect the "foo" flag).
-#define DEFINE_VARIABLE(type, shorttype, name, value, help) \
- namespace fL##shorttype { \
- static const type FLAGS_nono##name = value; \
- type FLAGS_##name = FLAGS_nono##name; \
- type FLAGS_no##name = FLAGS_nono##name; \
- static @ac_google_namespace@::FlagRegisterer o_##name( \
- #name, #type, MAYBE_STRIPPED_HELP(help), __FILE__, \
- &FLAGS_##name, &FLAGS_no##name); \
- } \
+#define DEFINE_VARIABLE(type, shorttype, name, value, help) \
+ namespace fL##shorttype { \
+ 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 @ac_google_namespace@::FlagRegisterer o_##name( \
+ #name, #type, MAYBE_STRIPPED_HELP(help), __FILE__, \
+ &FLAGS_##name, &FLAGS_no##name); \
+ } \
using fL##shorttype::FLAGS_##name
// For DEFINE_bool, we want to do the extra check that the passed-in
@@ -463,32 +478,39 @@ extern const char kStrippedFlagHelp[];
// We'll use 'sizeof(IsBool(val))' to distinguish. This code requires
// that the compiler have different sizes for bool & double. Since
// this is not guaranteed by the standard, we check it with a
-// compile-time assert (msg[-1] will give a compile-time error).
+// COMPILE_ASSERT.
namespace fLB {
struct CompileAssert {};
typedef CompileAssert expected_sizeof_double_neq_sizeof_bool[
(sizeof(double) != sizeof(bool)) ? 1 : -1];
-template<typename From> double IsBoolFlag(const From& from);
-bool IsBoolFlag(bool from);
+template<typename From> double GFLAGS_DLL_DECL IsBoolFlag(const From& from);
+GFLAGS_DLL_DECL bool IsBoolFlag(bool from);
} // namespace fLB
// Here are the actual DEFINE_*-macros. The respective DECLARE_*-macros
// are in a separate include, gflags_declare.h, for reducing
// the physical transitive size for DECLARE use.
-#define DEFINE_bool(name, val, txt) \
- namespace fLB { \
- typedef ::fLB::CompileAssert FLAG_##name##_value_is_not_a_bool[ \
+#define DEFINE_bool(name, val, txt) \
+ namespace fLB { \
+ typedef ::fLB::CompileAssert FLAG_##name##_value_is_not_a_bool[ \
(sizeof(::fLB::IsBoolFlag(val)) != sizeof(double)) ? 1 : -1]; \
- } \
+ } \
DEFINE_VARIABLE(bool, B, name, val, txt)
-#define DEFINE_int32(name,val,txt) DEFINE_VARIABLE(@ac_google_namespace@::int32, I, name, val, txt)
+#define DEFINE_int32(name, val, txt) \
+ DEFINE_VARIABLE(@ac_google_namespace@::int32, I, \
+ name, val, txt)
-#define DEFINE_int64(name,val,txt) DEFINE_VARIABLE(@ac_google_namespace@::int64, I64, name, val, txt)
+#define DEFINE_int64(name, val, txt) \
+ DEFINE_VARIABLE(@ac_google_namespace@::int64, I64, \
+ name, val, txt)
-#define DEFINE_uint64(name,val,txt) DEFINE_VARIABLE(@ac_google_namespace@::uint64, U64, name, val, txt)
+#define DEFINE_uint64(name,val, txt) \
+ DEFINE_VARIABLE(@ac_google_namespace@::uint64, U64, \
+ name, val, txt)
-#define DEFINE_double(name, val, txt) DEFINE_VARIABLE(double, D, name, val, txt)
+#define DEFINE_double(name, val, txt) \
+ DEFINE_VARIABLE(double, D, name, val, txt)
// Strings are trickier, because they're not a POD, so we can't
// construct them at static-initialization time (instead they get
@@ -525,10 +547,10 @@ inline clstring* dont_pass0toDEFINE_string(char *stringspot,
clstring* const FLAGS_no##name = ::fLS:: \
dont_pass0toDEFINE_string(s_##name[0].s, \
val); \
- static @ac_google_namespace@::FlagRegisterer o_##name( \
+ static @ac_google_namespace@::FlagRegisterer o_##name( \
#name, "string", MAYBE_STRIPPED_HELP(txt), __FILE__, \
s_##name[0].s, new (s_##name[1].s) clstring(*FLAGS_no##name)); \
- extern clstring& FLAGS_##name; \
+ extern GFLAGS_DLL_DEFINE_FLAG clstring& FLAGS_##name; \
using fLS::FLAGS_##name; \
clstring& FLAGS_##name = *FLAGS_no##name; \
} \
@@ -536,4 +558,4 @@ inline clstring* dont_pass0toDEFINE_string(char *stringspot,
#endif // SWIG
-#endif // GOOGLE_GFLAGS_H_
+#endif // BASE_COMMANDLINEFLAGS_H_
diff --git a/src/gflags/gflags_completions.h.in b/src/gflags/gflags_completions.h.in
index b4ca6a8..13b380e 100644
--- a/src/gflags/gflags_completions.h.in
+++ b/src/gflags/gflags_completions.h.in
@@ -28,7 +28,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// ---
-// Author: Dave Nicponski
+
//
// Implement helpful bash-style command line flag completions
//
@@ -88,8 +88,8 @@
// file would be (your path to gflags_completions.sh file may differ):
/*
-$ complete -o bashdefault -o default -o nospace -C \
- '/usr/local/bin/gflags_completions.sh --tab_completion_columns $COLUMNS' \
+$ complete -o bashdefault -o default -o nospace -C \
+ '/home/build/eng/bash/bash_completions.sh --tab_completion_columns $COLUMNS' \
time env binary_name another_binary [...]
*/
@@ -109,13 +109,27 @@ $ complete -o bashdefault -o default -o nospace -C \
// produce the expected completion output.
-#ifndef GOOGLE_GFLAGS_COMPLETIONS_H_
-#define GOOGLE_GFLAGS_COMPLETIONS_H_
+#ifndef BASE_COMMANDLINEFLAGS_COMPLETIONS_H_
+#define BASE_COMMANDLINEFLAGS_COMPLETIONS_H_
+
+// Annoying stuff for windows -- makes sure clients can import these functions
+//
+// NOTE: all functions below MUST have an explicit 'extern' before
+// them. Our automated opensourcing tools use this as a signal to do
+// appropriate munging for windows, which needs to add GFLAGS_DLL_DECL.
+//
+#ifndef GFLAGS_DLL_DECL
+# ifdef _WIN32
+# define GFLAGS_DLL_DECL __declspec(dllimport)
+# else
+# define GFLAGS_DLL_DECL /**/
+# endif
+#endif
@ac_google_start_namespace@
-void HandleCommandLineCompletions(void);
+extern void HandleCommandLineCompletions(void);
@ac_google_end_namespace@
-#endif // GOOGLE_GFLAGS_COMPLETIONS_H_
+#endif // BASE_COMMANDLINEFLAGS_COMPLETIONS_H_
diff --git a/src/gflags/gflags_declare.h.in b/src/gflags/gflags_declare.h.in
index 1fc2827..01feba5 100644
--- a/src/gflags/gflags_declare.h.in
+++ b/src/gflags/gflags_declare.h.in
@@ -1,4 +1,4 @@
-// Copyright (c) 2011, Google Inc.
+// Copyright (c) 1999, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -28,7 +28,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ---
-// Author: Ray Sidney
+//
// Revamped and reorganized by Craig Silverstein
//
// This is the file that should be included by any file which declares
@@ -38,35 +38,17 @@
#define BASE_COMMANDLINEFLAGS_DECLARE_H_
#include <string>
-
-// We care a lot about number of bits things take up. Unfortunately,
-// systems define their bit-specific ints in a lot of different ways.
-// We use our own way, and have a typedef to get there.
-// Note: these commands below may look like "#if 1" or "#if 0", but
-// that's because they were constructed that way at ./configure time.
-// Look at gflags.h.in to see how they're calculated (based on your config).
#if @ac_cv_have_stdint_h@
-#include <stdint.h> // the normal place uint16_t is defined
+#include <stdint.h> // the normal place uint16_t is defined
#endif
#if @ac_cv_have_systypes_h@
-#include <sys/types.h> // the normal place u_int16_t is defined
+#include <sys/types.h> // the normal place u_int16_t is defined
#endif
#if @ac_cv_have_inttypes_h@
-#include <inttypes.h> // a third place for uint16_t or u_int16_t
+#include <inttypes.h> // a third place for uint16_t or u_int16_t
#endif
-namespace fLS {
-
-// The meaning of "string" might be different between now and when the
-// macros below get invoked (e.g., if someone is experimenting with
-// other string implementations that get defined after this file is
-// included). Save the current meaning now and use it in the macros.
-typedef std::string clstring;
-
-}
-
@ac_google_start_namespace@
-
#if @ac_cv_have_uint16_t@ // the C99 format
typedef int32_t int32;
typedef uint32_t uint32;
@@ -85,22 +67,66 @@ typedef unsigned __int64 uint64;
#else
#error Do not know how to define a 32-bit integer quantity on your system
#endif
-
@ac_google_end_namespace@
+
+// Annoying stuff for windows -- makes sure clients can import these functions
+#if defined(_WIN32)
+# ifndef GFLAGS_DLL_DECL
+# define GFLAGS_DLL_DECL __declspec(dllimport)
+# endif
+# ifndef GFLAGS_DLL_DECLARE_FLAG
+# define GFLAGS_DLL_DECLARE_FLAG __declspec(dllimport)
+# endif
+# ifndef GFLAGS_DLL_DEFINE_FLAG
+# define GFLAGS_DLL_DEFINE_FLAG __declspec(dllexport)
+# endif
+#else
+# ifndef GFLAGS_DLL_DECL
+# define GFLAGS_DLL_DECL /**/
+# endif
+# ifndef GFLAGS_DLL_DECLARE_FLAG
+# define GFLAGS_DLL_DECLARE_FLAG /**/
+# endif
+# ifndef GFLAGS_DLL_DEFINE_FLAG
+# define GFLAGS_DLL_DEFINE_FLAG /**/
+# endif
+#endif
+
+namespace fLS {
+
+// The meaning of "string" might be different between now and when the
+// macros below get invoked (e.g., if someone is experimenting with
+// other string implementations that get defined after this file is
+// included). Save the current meaning now and use it in the macros.
+typedef std::string clstring;
+
+}
+
#define DECLARE_VARIABLE(type, shorttype, name) \
- namespace fL##shorttype { extern type FLAGS_##name; } \
+ /* We always want to import declared variables, dll or no */ \
+ namespace fL##shorttype { extern GFLAGS_DLL_DECLARE_FLAG type FLAGS_##name; } \
using fL##shorttype::FLAGS_##name
-#define DECLARE_bool(name) DECLARE_VARIABLE(bool, B, name)
-#define DECLARE_int32(name) DECLARE_VARIABLE(@ac_google_namespace@::int32, I, name)
-#define DECLARE_int64(name) DECLARE_VARIABLE(@ac_google_namespace@::int64, I64, name)
-#define DECLARE_uint64(name) DECLARE_VARIABLE(@ac_google_namespace@::uint64, U64, name)
-#define DECLARE_double(name) DECLARE_VARIABLE(double, D, name)
+#define DECLARE_bool(name) \
+ DECLARE_VARIABLE(bool, B, name)
+
+#define DECLARE_int32(name) \
+ DECLARE_VARIABLE(@ac_google_namespace@::int32, I, name)
+
+#define DECLARE_int64(name) \
+ DECLARE_VARIABLE(@ac_google_namespace@::int64, I64, name)
+
+#define DECLARE_uint64(name) \
+ DECLARE_VARIABLE(@ac_google_namespace@::uint64, U64, name)
+
+#define DECLARE_double(name) \
+ DECLARE_VARIABLE(double, D, name)
+
#define DECLARE_string(name) \
namespace fLS { \
using ::fLS::clstring; \
- extern ::fLS::clstring& FLAGS_##name; \
+ extern GFLAGS_DLL_DECLARE_FLAG ::fLS::clstring& FLAGS_##name; \
} \
using fLS::FLAGS_##name
diff --git a/src/gflags_completions.cc b/src/gflags_completions.cc
index 92ab4f3..17439dd 100644
--- a/src/gflags_completions.cc
+++ b/src/gflags_completions.cc
@@ -28,8 +28,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// ---
-// Author: Dave Nicponski
-//
+
// Bash-style command line flag completion for C++ binaries
//
// This module implements bash-style completions. It achieves this
@@ -48,7 +47,7 @@
// 5b) Trim most flag's descriptions to fit on a single terminal line
-#include "config.h"
+#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // for strlen
@@ -59,6 +58,11 @@
#include <vector>
#include <gflags/gflags.h>
+#include "util.h"
+
+using std::set;
+using std::string;
+using std::vector;
#ifndef PATH_SEPARATOR
#define PATH_SEPARATOR '/'
@@ -74,11 +78,6 @@ DEFINE_int32(tab_completion_columns, 80,
_START_GOOGLE_NAMESPACE_
namespace {
-
-using std::set;
-using std::string;
-using std::vector;
-
// Function prototypes and Type forward declarations. Code may be
// more easily understood if it is roughly ordered according to
// control flow, rather than by C's "declare before use" ordering
@@ -210,12 +209,12 @@ static void PrintFlagCompletionInfo(void) {
&canonical_token,
&options);
- //VLOG(1) << "Identified canonical_token: '" << canonical_token << "'";
+ DVLOG(1) << "Identified canonical_token: '" << canonical_token << "'";
vector<CommandLineFlagInfo> all_flags;
set<const CommandLineFlagInfo *> matching_flags;
GetAllFlags(&all_flags);
- //VLOG(2) << "Found " << all_flags.size() << " flags overall";
+ DVLOG(2) << "Found " << all_flags.size() << " flags overall";
string longest_common_prefix;
FindMatchingFlags(
@@ -224,28 +223,28 @@ static void PrintFlagCompletionInfo(void) {
canonical_token,
&matching_flags,
&longest_common_prefix);
- //VLOG(1) << "Identified " << matching_flags.size() << " matching flags";
- //VLOG(1) << "Identified " << longest_common_prefix
- // << " as longest common prefix.";
+ DVLOG(1) << "Identified " << matching_flags.size() << " matching flags";
+ DVLOG(1) << "Identified " << longest_common_prefix
+ << " as longest common prefix.";
if (longest_common_prefix.size() > canonical_token.size()) {
// There's actually a shared common prefix to all matching flags,
// so may as well output that and quit quickly.
- //VLOG(1) << "The common prefix '" << longest_common_prefix
- // << "' was longer than the token '" << canonical_token
- // << "'. Returning just this prefix for completion.";
+ DVLOG(1) << "The common prefix '" << longest_common_prefix
+ << "' was longer than the token '" << canonical_token
+ << "'. Returning just this prefix for completion.";
fprintf(stdout, "--%s", longest_common_prefix.c_str());
return;
}
if (matching_flags.empty()) {
- //VLOG(1) << "There were no matching flags, returning nothing.";
+ VLOG(1) << "There were no matching flags, returning nothing.";
return;
}
string module;
string package_dir;
TryFindModuleAndPackageDir(all_flags, &module, &package_dir);
- //VLOG(1) << "Identified module: '" << module << "'";
- //VLOG(1) << "Identified package_dir: '" << package_dir << "'";
+ DVLOG(1) << "Identified module: '" << module << "'";
+ DVLOG(1) << "Identified package_dir: '" << package_dir << "'";
NotableFlags notable_flags;
CategorizeAllMatchingFlags(
@@ -254,12 +253,12 @@ static void PrintFlagCompletionInfo(void) {
module,
package_dir,
&notable_flags);
- //VLOG(2) << "Categorized matching flags:";
- //VLOG(2) << " perfect_match: " << notable_flags.perfect_match_flag.size();
- //VLOG(2) << " module: " << notable_flags.module_flags.size();
- //VLOG(2) << " package: " << notable_flags.package_flags.size();
- //VLOG(2) << " most common: " << notable_flags.most_common_flags.size();
- //VLOG(2) << " subpackage: " << notable_flags.subpackage_flags.size();
+ DVLOG(2) << "Categorized matching flags:";
+ DVLOG(2) << " perfect_match: " << notable_flags.perfect_match_flag.size();
+ DVLOG(2) << " module: " << notable_flags.module_flags.size();
+ DVLOG(2) << " package: " << notable_flags.package_flags.size();
+ DVLOG(2) << " most common: " << notable_flags.most_common_flags.size();
+ DVLOG(2) << " subpackage: " << notable_flags.subpackage_flags.size();
vector<string> completions;
FinalizeCompletionOutput(
@@ -271,13 +270,13 @@ static void PrintFlagCompletionInfo(void) {
if (options.force_no_update)
completions.push_back("~");
- //VLOG(1) << "Finalized with " << completions.size()
- // << " chosen completions";
+ DVLOG(1) << "Finalized with " << completions.size()
+ << " chosen completions";
for (vector<string>::const_iterator it = completions.begin();
it != completions.end();
++it) {
- //VLOG(9) << " Completion entry: '" << *it << "'";
+ DVLOG(9) << " Completion entry: '" << *it << "'";
fprintf(stdout, "%s\n", it->c_str());
}
}
@@ -397,7 +396,7 @@ static bool DoesSingleFlagMatch(
flag.filename.find(match_token) != string::npos)
return true;
- // TODO(daven): All searches should probably be case-insensitive
+ // TODO(user): All searches should probably be case-insensitive
// (especially this one...)
if (options.flag_description_substring_search &&
flag.description.find(match_token) != string::npos)
@@ -426,8 +425,8 @@ static void CategorizeAllMatchingFlags(
all_matches.begin();
it != all_matches.end();
++it) {
- //VLOG(2) << "Examining match '" << (*it)->name << "'";
- //VLOG(7) << " filename: '" << (*it)->filename << "'";
+ DVLOG(2) << "Examining match '" << (*it)->name << "'";
+ DVLOG(7) << " filename: '" << (*it)->filename << "'";
string::size_type pos = string::npos;
if (!package_dir.empty())
pos = (*it)->filename.find(package_dir);
@@ -440,36 +439,34 @@ static void CategorizeAllMatchingFlags(
if ((*it)->name == search_token) {
// Exact match on some flag's name
notable_flags->perfect_match_flag.insert(*it);
- //VLOG(3) << "Result: perfect match";
+ DVLOG(3) << "Result: perfect match";
} else if (!module.empty() && (*it)->filename == module) {
// Exact match on module filename
notable_flags->module_flags.insert(*it);
- //VLOG(3) << "Result: module match";
+ DVLOG(3) << "Result: module match";
} else if (!package_dir.empty() &&
pos != string::npos && slash == string::npos) {
// In the package, since there was no slash after the package portion
notable_flags->package_flags.insert(*it);
- //VLOG(3) << "Result: package match";
+ DVLOG(3) << "Result: package match";
} else if (false) {
// In the list of the XXX most commonly supplied flags overall
- // TODO(daven): Compile this list.
- //VLOG(3) << "Result: most-common match";
+ // TODO(user): Compile this list.
+ DVLOG(3) << "Result: most-common match";
} else if (!package_dir.empty() &&
pos != string::npos && slash != string::npos) {
// In a subdirectory of the package
notable_flags->subpackage_flags.insert(*it);
- //VLOG(3) << "Result: subpackage match";
+ DVLOG(3) << "Result: subpackage match";
}
- //VLOG(3) << "Result: not special match";
+ DVLOG(3) << "Result: not special match";
}
}
static void PushNameWithSuffix(vector<string>* suffixes, const char* suffix) {
- string s("/");
- s += ProgramInvocationShortName();
- s += suffix;
- suffixes->push_back(s);
+ suffixes->push_back(
+ StringPrintf("/%s%s", ProgramInvocationShortName(), suffix));
}
static void TryFindModuleAndPackageDir(
@@ -480,7 +477,7 @@ static void TryFindModuleAndPackageDir(
package_dir->clear();
vector<string> suffixes;
- // TODO(daven): There's some inherant ambiguity here - multiple directories
+ // TODO(user): There's some inherant ambiguity here - multiple directories
// could share the same trailing folder and file structure (and even worse,
// same file names), causing us to be unsure as to which of the two is the
// actual package for this binary. In this case, we'll arbitrarily choose.
@@ -499,7 +496,7 @@ static void TryFindModuleAndPackageDir(
for (vector<string>::const_iterator suffix = suffixes.begin();
suffix != suffixes.end();
++suffix) {
- // TODO(daven): Make sure the match is near the end of the string
+ // TODO(user): Make sure the match is near the end of the string
if (it->filename.find(*suffix) != string::npos) {
*module = it->filename;
string::size_type sep = it->filename.rfind(PATH_SEPARATOR);
@@ -696,12 +693,14 @@ static void OutputSingleGroupWithLimit(
static string GetShortFlagLine(
const string &line_indentation,
const CommandLineFlagInfo &info) {
- string prefix =
- line_indentation + "--" + info.name + " [" +
- (info.type == "string" ?
- ("'" + info.default_value + "'") :
- info.default_value)
- + "] ";
+ string prefix;
+ bool is_string = (info.type == "string");
+ SStringPrintf(&prefix, "%s--%s [%s%s%s] ",
+ line_indentation.c_str(),
+ info.name.c_str(),
+ (is_string ? "'" : ""),
+ info.default_value.c_str(),
+ (is_string ? "'" : ""));
int remainder =
FLAGS_tab_completion_columns - static_cast<int>(prefix.size());
string suffix;
@@ -731,8 +730,12 @@ static string GetLongFlagLine(
static const char kNewlineWithIndent[] = "\n ";
output.replace(output.find(" type:"), 1, string(kNewlineWithIndent));
output.replace(output.find(" default:"), 1, string(kNewlineWithIndent));
- output = line_indentation + " Details for '--" + info.name + "':\n" +
- output + " defined: " + info.filename;
+ output = StringPrintf("%s Details for '--%s':\n"
+ "%s defined: %s",
+ line_indentation.c_str(),
+ info.name.c_str(),
+ output.c_str(),
+ info.filename.c_str());
// Eliminate any doubled newlines that crept in. Specifically, if
// DescribeOneFlag() decided to break the line just before "type"
@@ -759,7 +762,7 @@ static string GetLongFlagLine(
void HandleCommandLineCompletions(void) {
if (FLAGS_tab_completion_word.empty()) return;
PrintFlagCompletionInfo();
- exit(0);
+ gflags_exitfunc(0);
}
_END_GOOGLE_NAMESPACE_
diff --git a/src/gflags_completions.sh b/src/gflags_completions.sh
index 2291b59..c5fb7e6 100755
--- a/src/gflags_completions.sh
+++ b/src/gflags_completions.sh
@@ -50,12 +50,12 @@
completion_word_index="$(($# - 1))"
completion_word="${!completion_word_index}"
-# TODO(daven): Replace this once commandlineflags_completions.cc has
+# TODO(user): Replace this once gflags_completions.cc has
# a bool parameter indicating unambiguously to hijack the process for
# completion purposes.
if [ -z "$completion_word" ]; then
# Until an empty value for the completion word stops being misunderstood
- # by google3 binaries, don't actuall execute the binary or the process
+ # by binaries, don't actually execute the binary or the process
# won't be hijacked!
exit 0
fi
@@ -74,12 +74,10 @@ binary="${!binary_index}"
# places this in the $COMP_LINE variable.
if [ "$binary" == "time" ] || [ "$binary" == "env" ]; then
# we'll assume that the first 'argument' is actually the
- # binary to be run, if we think it looks like a google3
# binary
- # TODO(daven): Decide what 'looks' like a google3 binary. =)
- # TODO(daven): This is not perfect - the 'env' command, for instance,
+ # TODO(user): This is not perfect - the 'env' command, for instance,
# is allowed to have options between the 'env' and 'the command to
# be executed'. For example, consider:
# $ env FOO="bar" bin/do_something --help<TAB>
@@ -105,7 +103,7 @@ for ((i=1; i<=$(($# - 3)); ++i)); do
done
params="$params --tab_completion_word \"$completion_word\""
-# TODO(daven): Perhaps stash the output in a temporary file somewhere
+# TODO(user): Perhaps stash the output in a temporary file somewhere
# in /tmp, and only cat it to stdout if the command returned a success
# code, to prevent false positives
diff --git a/src/gflags_nc.cc b/src/gflags_nc.cc
index 582b684..e72800d 100644
--- a/src/gflags_nc.cc
+++ b/src/gflags_nc.cc
@@ -28,9 +28,8 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ---
-// Author: Roberto Bayardo
//
-// A negative compile test for commandlineflags.
+// A negative comiple test for gflags.
#include <gflags/gflags.h>
diff --git a/src/gflags_reporting.cc b/src/gflags_reporting.cc
index 289bb6e..8afcb95 100644
--- a/src/gflags_reporting.cc
+++ b/src/gflags_reporting.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006, Google Inc.
+// Copyright (c) 1999, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -28,7 +28,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ---
-// Author: Ray Sidney
+//
// Revamped and reorganized by Craig Silverstein
//
// This file contains code for handling the 'reporting' flags. These
@@ -40,7 +40,7 @@
// HandleCommandLineHelpFlags(). (Well, actually, ShowUsageWithFlags(),
// ShowUsageWithFlagsRestrict(), and DescribeOneFlag() can be called
// externally too, but there's little need for it.) These are all
-// declared in the main commandlineflags.h header file.
+// declared in the main gflags.h header file.
//
// HandleCommandLineHelpFlags() will check what 'reporting' flags have
// been defined, if any -- the "help" part of the function name is a
@@ -48,7 +48,7 @@
// called after all flag-values have been assigned, that is, after
// parsing the command-line.
-#include "config.h"
+#include <config.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
@@ -57,12 +57,13 @@
#include <vector>
#include <gflags/gflags.h>
#include <gflags/gflags_completions.h>
+#include "util.h"
#ifndef PATH_SEPARATOR
#define PATH_SEPARATOR '/'
#endif
-// The 'reporting' flags. They all call exit().
+// The 'reporting' flags. They all call gflags_exitfunc().
DEFINE_bool(help, false,
"show help on all flags [tip: all flags can have two dashes]");
DEFINE_bool(helpfull, false,
@@ -85,11 +86,12 @@ _START_GOOGLE_NAMESPACE_
using std::string;
using std::vector;
+
// --------------------------------------------------------------------
// DescribeOneFlag()
// DescribeOneFlagInXML()
// Routines that pretty-print info about a flag. These use
-// a CommandLineFlagInfo, which is the way the commandlineflags
+// a CommandLineFlagInfo, which is the way the gflags
// API exposes static info about a flag.
// --------------------------------------------------------------------
@@ -114,17 +116,19 @@ static string PrintStringFlagsWithQuotes(const CommandLineFlagInfo& flag,
const char* c_string = (current ? flag.current_value.c_str() :
flag.default_value.c_str());
if (strcmp(flag.type.c_str(), "string") == 0) { // add quotes for strings
- return text + ": \"" + c_string + "\"";
+ return StringPrintf("%s: \"%s\"", text.c_str(), c_string);
} else {
- return text + ": " + c_string;
+ return StringPrintf("%s: %s", text.c_str(), c_string);
}
}
// Create a descriptive string for a flag.
// Goes to some trouble to make pretty line breaks.
string DescribeOneFlag(const CommandLineFlagInfo& flag) {
- string main_part = (string(" -") + flag.name +
- " (" + flag.description + ')');
+ string main_part;
+ SStringPrintf(&main_part, " -%s (%s)",
+ flag.name.c_str(),
+ flag.description.c_str());
const char* c_string = main_part.c_str();
int chars_left = static_cast<int>(main_part.length());
string final_string = "";
@@ -164,7 +168,7 @@ string DescribeOneFlag(const CommandLineFlagInfo& flag) {
}
if (*c_string == '\0')
break;
- final_string += "\n ";
+ StringAppendF(&final_string, "\n ");
chars_in_line = 6;
}
@@ -173,7 +177,7 @@ string DescribeOneFlag(const CommandLineFlagInfo& flag) {
// The listed default value will be the actual default from the flag
// definition in the originating source file, unless the value has
// subsequently been modified using SetCommandLineOptionWithMode() with mode
- // SET_FLAGS_DEFAULT, or by setting FLAGS_foo = bar before initializing.
+ // SET_FLAGS_DEFAULT, or by setting FLAGS_foo = bar before ParseCommandLineFlags().
AddString(PrintStringFlagsWithQuotes(flag, "default", false), &final_string,
&chars_in_line);
if (!flag.is_default) {
@@ -181,7 +185,7 @@ string DescribeOneFlag(const CommandLineFlagInfo& flag) {
&final_string, &chars_in_line);
}
- final_string += '\n';
+ StringAppendF(&final_string, "\n");
return final_string;
}
@@ -196,15 +200,10 @@ static string XMLText(const string& txt) {
}
static void AddXMLTag(string* r, const char* tag, const string& txt) {
- *r += ('<');
- *r += (tag);
- *r += ('>');
- *r += (XMLText(txt));
- *r += ("</");
- *r += (tag);
- *r += ('>');
+ StringAppendF(r, "<%s>%s</%s>", tag, XMLText(txt).c_str(), tag);
}
+
static string DescribeOneFlagInXML(const CommandLineFlagInfo& flag) {
// The file and flagname could have been attributes, but default
// and meaning need to avoid attribute normalization. This way it
@@ -265,9 +264,9 @@ static bool FileMatchesSubstring(const string& filename,
// Show help for every filename which matches any of the target substrings.
// If substrings is empty, shows help for every file. If a flag's help message
-// has been stripped (e.g. by adding '#define STRIP_FLAG_HELP 1' before
-// including gflags/gflags.h), then this flag will not be displayed by
-// '--help' and its variants.
+// has been stripped (e.g. by adding '#define STRIP_FLAG_HELP 1'
+// before including gflags/gflags.h), then this flag will not be displayed
+// by '--help' and its variants.
static void ShowUsageWithFlagsMatching(const char *argv0,
const vector<string> &substrings) {
fprintf(stdout, "%s: %s\n", Basename(argv0), ProgramUsage());
@@ -354,7 +353,6 @@ static void ShowVersion() {
} else {
fprintf(stdout, "%s\n", ProgramInvocationShortName());
}
-
# if !defined(NDEBUG)
fprintf(stdout, "Debug build (NDEBUG not #defined)\n");
# endif
@@ -379,7 +377,6 @@ static void AppendPrognameStrings(vector<string>* substrings,
void HandleCommandLineHelpFlags() {
const char* progname = ProgramInvocationShortName();
- extern void (*commandlineflags_exitfunc)(int); // in gflags.cc
HandleCommandLineCompletions();
@@ -390,21 +387,21 @@ void HandleCommandLineHelpFlags() {
// show only flags related to this binary:
// E.g. for fileutil.cc, want flags containing ... "/fileutil." cc
ShowUsageWithFlagsMatching(progname, substrings);
- commandlineflags_exitfunc(1); // almost certainly exit()
+ gflags_exitfunc(1);
} else if (FLAGS_help || FLAGS_helpfull) {
// show all options
ShowUsageWithFlagsRestrict(progname, ""); // empty restrict
- commandlineflags_exitfunc(1);
+ gflags_exitfunc(1);
} else if (!FLAGS_helpon.empty()) {
string restrict = "/" + FLAGS_helpon + ".";
ShowUsageWithFlagsRestrict(progname, restrict.c_str());
- commandlineflags_exitfunc(1);
+ gflags_exitfunc(1);
} else if (!FLAGS_helpmatch.empty()) {
ShowUsageWithFlagsRestrict(progname, FLAGS_helpmatch.c_str());
- commandlineflags_exitfunc(1);
+ gflags_exitfunc(1);
} else if (FLAGS_helppackage) {
// Shows help for all files in the same directory as main(). We
@@ -423,27 +420,27 @@ void HandleCommandLineHelpFlags() {
const string package = Dirname(flag->filename) + "/";
if (package != last_package) {
ShowUsageWithFlagsRestrict(progname, package.c_str());
+ VLOG(7) << "Found package: " << package;
if (!last_package.empty()) { // means this isn't our first pkg
- fprintf(stderr, "WARNING: Multiple packages contain a file=%s\n",
- progname);
+ LOG(WARNING) << "Multiple packages contain a file=" << progname;
}
last_package = package;
}
}
if (last_package.empty()) { // never found a package to print
- fprintf(stderr, "WARNING: Unable to find a package for file=%s\n",
- progname);
+ LOG(WARNING) << "Unable to find a package for file=" << progname;
}
- commandlineflags_exitfunc(1);
+ gflags_exitfunc(1);
} else if (FLAGS_helpxml) {
ShowXMLOfFlags(progname);
- commandlineflags_exitfunc(1);
+ gflags_exitfunc(1);
} else if (FLAGS_version) {
ShowVersion();
// Unlike help, we may be asking for version in a script, so return 0
- commandlineflags_exitfunc(0);
+ gflags_exitfunc(0);
+
}
}
diff --git a/src/gflags_strip_flags_test.cc b/src/gflags_strip_flags_test.cc
index 77234e2..001ccd3 100644
--- a/src/gflags_strip_flags_test.cc
+++ b/src/gflags_strip_flags_test.cc
@@ -28,20 +28,22 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// ---
-// Author: Craig Silverstein
+// Author: csilvers@google.com (Craig Silverstein)
//
// A simple program that uses STRIP_FLAG_HELP. We'll have a shell
// script that runs 'strings' over this program and makes sure
// that the help string is not in there.
#include "config_for_unittests.h"
-#include <stdio.h>
#define STRIP_FLAG_HELP 1
-#include "gflags/gflags.h"
+#include <gflags/gflags.h>
+
+#include <stdio.h>
using GOOGLE_NAMESPACE::SetUsageMessage;
using GOOGLE_NAMESPACE::ParseCommandLineFlags;
+
DEFINE_bool(test, true, "This text should be stripped out");
int main(int argc, char** argv) {
@@ -53,6 +55,7 @@ int main(int argc, char** argv) {
// under a different name. We need the 'real' executable name to run
// 'strings' on it, so we construct this binary to print the real
// name (argv[0]) on stdout when run.
- printf("%s\n", argv[0]);
+ puts(argv[0]);
+
return 0;
}
diff --git a/src/gflags_strip_flags_test.sh b/src/gflags_strip_flags_test.sh
index d3810db..9ebb457 100755
--- a/src/gflags_strip_flags_test.sh
+++ b/src/gflags_strip_flags_test.sh
@@ -30,14 +30,12 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# ---
-# Author: Craig Silverstein
+# Author: csilvers@google.com (Craig Silverstein)
-if [ -z "$1" ]
-then
- echo "USAGE: $0 <unittest exe>"
- exit 1
+if [ -z "$1" ]; then
+ echo "USAGE: $0 <unittest exe>"
+ exit 1
fi
-
BINARY="$1"
# Make sure the binary exists...
@@ -57,15 +55,15 @@ fi
# Make sure the stripped text isn't in the binary at all.
if strings --help >/dev/null 2>&1 # make sure the binary exists
then
- # Unfortunately, for us, libtool can replace executables with a shell
- # script that does some work before calling the 'real' executable
- # under a different name. We need the 'real' executable name to run
- # 'strings' on it, so we construct this binary to print the real
- # name (argv[0]) on stdout when run.
+ # Unfortunately, for us, libtool can replace executables with a
+ # shell script that does some work before calling the 'real'
+ # executable under a different name. We need the 'real'
+ # executable name to run 'strings' on it, so we construct this
+ # binary to print the real name (argv[0]) on stdout when run.
REAL_BINARY=`"$BINARY"`
# On cygwin, we may need to add a '.exe' extension by hand.
[ -f "$REAL_BINARY.exe" ] && REAL_BINARY="$REAL_BINARY.exe"
- if strings "$REAL_BINARY" | grep "This text should be stripped out" >/dev/null 2>&1
+ if strings "$REAL_BINARY" | grep "This text should be stripped" >/dev/null 2>&1
then
echo "Text not stripped from binary like it should be: $BINARY"
exit 1
diff --git a/src/gflags_unittest.cc b/src/gflags_unittest.cc
index 3f82b45..d64febb 100644
--- a/src/gflags_unittest.cc
+++ b/src/gflags_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006, Google Inc.
+// Copyright (c) 2005, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -28,27 +28,26 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ---
-// Author: Marius Eriksen
//
// For now, this unit test does not cover all features of
// gflags.cc
#include "config_for_unittests.h"
+#include <gflags/gflags.h>
+
+#include <math.h> // for isinf() and isnan()
#include <stdio.h>
-#include <stdlib.h> // for &exit
-#include <assert.h>
+#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
-#include <unistd.h> // for unlink()
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h> // for mkdir()
-#endif
-#include <math.h> // for isinf() and isnan()
+# include <unistd.h>
+#endif // for unlink()
#include <vector>
#include <string>
+#include "util.h"
+TEST_INIT
+EXPECT_DEATH_INIT
-#include <gflags/gflags.h>
// I don't actually use this header file, but #include it under the
// old location to make sure that the include-header-forwarding
// works. But don't bother on windows; the windows port is so new
@@ -58,6 +57,8 @@
void (*unused_fn)() = &GOOGLE_NAMESPACE::HandleCommandLineCompletions;
#endif
+using std::string;
+using std::vector;
using GOOGLE_NAMESPACE::int32;
using GOOGLE_NAMESPACE::FlagRegisterer;
using GOOGLE_NAMESPACE::StringFromEnv;
@@ -65,33 +66,6 @@ using GOOGLE_NAMESPACE::RegisterFlagValidator;
using GOOGLE_NAMESPACE::CommandLineFlagInfo;
using GOOGLE_NAMESPACE::GetAllFlags;
-// Returns the number of elements in an array.
-#define GET_ARRAY_SIZE(arr) (sizeof(arr)/sizeof(*(arr)))
-
-#if !defined(HAVE_SETENV) && defined(HAVE_PUTENV) // mingw, at least
-void setenv(const char* name, const char* value, int) {
- // In windows, it's impossible to set a variable to the empty string.
- // We handle this by setting it to "0" and the NUL-ing out the \0.
- // cf http://svn.apache.org/viewvc/stdcxx/trunk/tests/src/environ.cpp?r1=611451&r2=637508&pathrev=637508
- static const char* const kFakeZero = "0";
- if (*value == '\0')
- value = kFakeZero;
- // Apparently the semantics of putenv() is that the input
- // must live forever, so we leak memory here. :-(
- const int nameval_len = strlen(name) + 1 + strlen(value) + 1;
- char* nameval = reinterpret_cast<char*>(malloc(nameval_len));
- snprintf(nameval, nameval_len, "%s=%s", name, value);
- putenv(nameval);
- if (value == kFakeZero) {
- nameval[nameval_len - 2] = '\0'; // works when putenv() makes no copy
- if (*getenv(name) != '\0')
- *getenv(name) = '\0'; // works when putenv() copies nameval
- }
-}
-#endif
-
-DECLARE_string(tryfromenv); // in gflags.cc
-
DEFINE_string(test_tmpdir, "/tmp/gflags_unittest", "Dir we use for temp files");
#ifdef _MSC_VER // in MSVC, we run from the vsprojects directory
DEFINE_string(srcdir, "..\\..",
@@ -101,6 +75,8 @@ DEFINE_string(srcdir, StringFromEnv("SRCDIR", "."),
"Source-dir root, needed to find gflags_unittest_flagfile");
#endif
+DECLARE_string(tryfromenv); // in gflags.cc
+
DEFINE_bool(test_bool, false, "tests bool-ness");
DEFINE_int32(test_int32, -1, "");
DEFINE_int64(test_int64, -2, "");
@@ -131,7 +107,7 @@ static int changeable_bool_var = 8008;
DEFINE_bool(changeable_bool_var, ++changeable_bool_var == 8009, "");
static int changeable_string_var = 0;
-static std::string ChangeableString() {
+static string ChangeableString() {
char r[] = {static_cast<char>('0' + ++changeable_string_var), '\0'};
return r;
}
@@ -154,14 +130,16 @@ DEFINE_bool(changed_bool2, false, "changed");
static bool AlwaysFail(const char* flag, bool value) { return value == false; }
DEFINE_bool(always_fail, false, "will fail to validate when you set it");
-static bool dummy = RegisterFlagValidator(&FLAGS_always_fail, AlwaysFail);
+namespace {
+bool dummy = RegisterFlagValidator(&FLAGS_always_fail, AlwaysFail);
+}
-// See the comment by GetAllFlags in commandlineflags.h
+// See the comment by GetAllFlags in gflags.h
static bool DeadlockIfCantLockInValidators(const char* flag, bool value) {
if (!value) {
return true;
}
- std::vector<CommandLineFlagInfo> dummy;
+ vector<CommandLineFlagInfo> dummy;
GetAllFlags(&dummy);
return true;
}
@@ -169,8 +147,61 @@ DEFINE_bool(deadlock_if_cant_lock,
false,
"will deadlock if set to true and "
"if locking of registry in validators fails.");
-static bool dummy1 = RegisterFlagValidator(&FLAGS_deadlock_if_cant_lock,
- DeadlockIfCantLockInValidators);
+namespace {
+bool dummy1 = RegisterFlagValidator(&FLAGS_deadlock_if_cant_lock,
+ DeadlockIfCantLockInValidators);
+}
+
+#define MAKEFLAG(x) DEFINE_int32(test_flag_num##x, x, "Test flag")
+
+// Define 10 flags
+#define MAKEFLAG10(x) \
+ MAKEFLAG(x##0); \
+ MAKEFLAG(x##1); \
+ MAKEFLAG(x##2); \
+ MAKEFLAG(x##3); \
+ MAKEFLAG(x##4); \
+ MAKEFLAG(x##5); \
+ MAKEFLAG(x##6); \
+ MAKEFLAG(x##7); \
+ MAKEFLAG(x##8); \
+ MAKEFLAG(x##9)
+
+// Define 100 flags
+#define MAKEFLAG100(x) \
+ MAKEFLAG10(x##0); \
+ MAKEFLAG10(x##1); \
+ MAKEFLAG10(x##2); \
+ MAKEFLAG10(x##3); \
+ MAKEFLAG10(x##4); \
+ MAKEFLAG10(x##5); \
+ MAKEFLAG10(x##6); \
+ MAKEFLAG10(x##7); \
+ MAKEFLAG10(x##8); \
+ MAKEFLAG10(x##9)
+
+// Define a bunch of command-line flags. Each occurrence of the MAKEFLAG100
+// macro defines 100 integer flags. This lets us test the effect of having
+// many flags on startup time.
+MAKEFLAG100(1);
+MAKEFLAG100(2);
+MAKEFLAG100(3);
+MAKEFLAG100(4);
+MAKEFLAG100(5);
+MAKEFLAG100(6);
+MAKEFLAG100(7);
+MAKEFLAG100(8);
+MAKEFLAG100(9);
+MAKEFLAG100(10);
+MAKEFLAG100(11);
+MAKEFLAG100(12);
+MAKEFLAG100(13);
+MAKEFLAG100(14);
+MAKEFLAG100(15);
+
+#undef MAKEFLAG100
+#undef MAKEFLAG10
+#undef MAKEFLAG
// This is a pseudo-flag -- we want to register a flag with a filename
// at the top level, but there is no way to do this except by faking
@@ -199,119 +230,7 @@ using fLI::FLAGS_tldflag2;
_START_GOOGLE_NAMESPACE_
-using std::string;
-using std::vector;
-
-// The following is some bare-bones testing infrastructure
-
-#define EXPECT_TRUE(cond) \
- do { \
- if (!(cond)) { \
- fprintf(stderr, "Check failed: %s\n", #cond); \
- exit(1); \
- } \
- } while (0)
-
-#define EXPECT_FALSE(cond) EXPECT_TRUE(!(cond))
-
-#define EXPECT_OP(op, val1, val2) \
- do { \
- if (!((val1) op (val2))) { \
- fprintf(stderr, "Check failed: %s %s %s\n", #val1, #op, #val2); \
- exit(1); \
- } \
- } while (0)
-
-#define EXPECT_EQ(val1, val2) EXPECT_OP(==, val1, val2)
-#define EXPECT_NE(val1, val2) EXPECT_OP(!=, val1, val2)
-#define EXPECT_GT(val1, val2) EXPECT_OP(>, val1, val2)
-#define EXPECT_LT(val1, val2) EXPECT_OP(<, val1, val2)
-
-// C99 declares isnan and isinf should be macros, so the #ifdef test
-// should be reliable everywhere. Of course, it's not, but these
-// are testing pertty marginal functionality anyway, so it's ok to
-// not-run them even in situations they might, with effort, be made to work.
-#ifdef isnan // Some compilers, like sun's for Solaris 10, don't define this
-#define EXPECT_NAN(arg) \
- do { \
- if (!isnan(arg)) { \
- fprintf(stderr, "Check failed: isnan(%s)\n", #arg); \
- exit(1); \
- } \
- } while (0)
-#else
-#define EXPECT_NAN(arg)
-#endif
-
-#ifdef isinf // Some compilers, like sun's for Solaris 10, don't define this
-#define EXPECT_INF(arg) \
- do { \
- if (!isinf(arg)) { \
- fprintf(stderr, "Check failed: isinf(%s)\n", #arg); \
- exit(1); \
- } \
- } while (0)
-#else
-#define EXPECT_INF(arg)
-#endif
-
-#define EXPECT_DOUBLE_EQ(val1, val2) \
- do { \
- if (((val1) < (val2) - 0.001 || (val1) > (val2) + 0.001)) { \
- fprintf(stderr, "Check failed: %s == %s\n", #val1, #val2); \
- exit(1); \
- } \
- } while (0)
-
-#define EXPECT_STREQ(val1, val2) \
- do { \
- if (strcmp((val1), (val2)) != 0) { \
- fprintf(stderr, "Check failed: streq(%s, %s)\n", #val1, #val2); \
- exit(1); \
- } \
- } while (0)
-
-static bool g_called_exit;
-static void CalledExit(int) { g_called_exit = true; }
-extern GFLAGS_DLL_DECL void (*commandlineflags_exitfunc)(int); // in gflags.cc
-
-#define EXPECT_DEATH(fn, msg) \
- do { \
- g_called_exit = false; \
- commandlineflags_exitfunc = &CalledExit; \
- fn; \
- commandlineflags_exitfunc = &exit; /* set back to its default */ \
- if (!g_called_exit) { \
- fprintf(stderr, "Function didn't die (%s): %s\n", msg, #fn); \
- exit(1); \
- } \
- } while (0)
-
-
-vector<void (*)()> g_testlist; // the tests to run
-
-#define TEST(a, b) \
- struct Test_##a##_##b { \
- Test_##a##_##b() { g_testlist.push_back(&Run); } \
- static void Run() { \
- FlagSaver fs; \
- fprintf(stderr, "Running test %s/%s\n", #a, #b); \
- RunTest(); \
- } \
- static void RunTest(); \
- }; \
- static Test_##a##_##b g_test_##a##_##b; \
- void Test_##a##_##b::RunTest()
-
-
-static int RUN_ALL_TESTS() {
- vector<void (*)()>::const_iterator it;
- for (it = g_testlist.begin(); it != g_testlist.end(); ++it) {
- (*it)();
- }
- fprintf(stderr, "Passed %d tests\n\nPASS\n", (int)g_testlist.size());
- return 0;
-}
+namespace {
static string TmpFile(const string& basename) {
@@ -323,6 +242,7 @@ static string TmpFile(const string& basename) {
}
// Returns the definition of the --flagfile flag to be used in the tests.
+// Must be called after ParseCommandLineFlags().
static const char* GetFlagFileFlag() {
#ifdef _MSC_VER
static const string flagfile = FLAGS_srcdir + "\\src\\gflags_unittest_flagfile";
@@ -359,9 +279,10 @@ TEST(FlagTypes, FlagTypes) {
AssertIsType<string>(FLAGS_test_string);
}
+#ifdef GTEST_HAS_DEATH_TEST
// Death tests for "help" options.
//
-// The help system automatically calls exit(1) when you specify any of
+// The help system automatically calls gflags_exitfunc(1) when you specify any of
// the help-related flags ("-helpmatch", "-helpxml") so we can't test
// those mainline.
@@ -377,6 +298,7 @@ TEST(ReadFlagsFromStringDeathTest, HelpXml) {
EXPECT_DEATH(ReadFlagsFromString("-helpxml", GetArgv0(), true),
"");
}
+#endif
// A subroutine needed for testing reading flags from a string.
@@ -484,7 +406,7 @@ TEST(FlagFileTest, FilenamesOurfileFirst) {
-1.0);
}
-#ifdef HAVE_FNMATCH_H // otherwise glob isn't supported
+#ifdef HAVE_FNMATCH_H // otherwise glob isn't supported
TEST(FlagFileTest, FilenamesOurfileGlob) {
FLAGS_test_string = "initial";
FLAGS_test_bool = false;
@@ -536,7 +458,7 @@ TEST(FlagFileTest, FilenamesOurfileInBigList) {
1,
-1.0);
}
-#endif
+#endif // ifdef HAVE_FNMATCH_H
// Tests that a failed flag-from-string read keeps flags at default values
TEST(FlagFileTest, FailReadFlagsFromString) {
@@ -773,6 +695,7 @@ TEST(FromEnvTest, LegalValues) {
EXPECT_STREQ("unknown", StringFromEnv("STRING_VAL_UNKNOWN", "unknown"));
}
+#ifdef GTEST_HAS_DEATH_TEST
// Tests that the FooFromEnv dies on parse-error
TEST(FromEnvDeathTest, IllegalValues) {
setenv("BOOL_BAD1", "so true!", 1);
@@ -810,6 +733,8 @@ TEST(FromEnvDeathTest, IllegalValues) {
EXPECT_DEATH(DoubleFromEnv("DOUBLE_BAD1", 40.0), "error parsing env variable");
EXPECT_DEATH(DoubleFromEnv("DOUBLE_BAD2", 40.0), "error parsing env variable");
}
+#endif
+
// Tests that FlagSaver can save the states of string flags.
TEST(FlagSaverTest, CanSaveStringFlagStates) {
@@ -948,7 +873,7 @@ TEST(ShowUsageWithFlagsRestrictTest, BaseTest) {
}
// Note: all these argv-based tests depend on SetArgv being called
-// before ParseCommandLineFlags() in Main(), below.
+// before ParseCommandLineFlags() in main(), below.
TEST(GetArgvsTest, BaseTest) {
vector<string> argvs = GetArgvs();
EXPECT_EQ(4, argvs.size());
@@ -982,7 +907,7 @@ TEST(ProgramInvocationShortNameTest, BaseTest) {
EXPECT_STREQ("gflags_unittest", ProgramInvocationShortName());
}
-TEST(ProgramUsageTest, BaseTest) { // Depends on arg to SetUsageMessage()
+TEST(ProgramUsageTest, BaseTest) { // Depends on 1st arg to ParseCommandLineFlags()
EXPECT_STREQ("/test/argv/for/gflags_unittest: "
"<useless flag> [...]\nDoes something useless.\n",
ProgramUsage());
@@ -1138,10 +1063,12 @@ TEST(GetCommandLineFlagInfoOrDieTest, FlagExistsAndWasAssigned) {
EXPECT_FALSE(info.has_validator_fn);
}
+#ifdef GTEST_HAS_DEATH_TEST
TEST(GetCommandLineFlagInfoOrDieDeathTest, FlagDoesNotExist) {
EXPECT_DEATH(GetCommandLineFlagInfoOrDie("test_int3210"),
".*: flag test_int3210 does not exist");
}
+#endif
// These are lightly tested because they're deprecated. Basically,
@@ -1190,7 +1117,7 @@ TEST(DeprecatedFunctionsTest, ReadFromFlagsFile) {
r = ReadFromFlagsFile(filename, GetArgv0(), true);
EXPECT_TRUE(r);
EXPECT_EQ(-10, FLAGS_test_int32);
-}
+} // unnamed namespace
TEST(DeprecatedFunctionsTest, ReadFromFlagsFileFailure) {
FLAGS_test_int32 = -20;
@@ -1215,7 +1142,7 @@ TEST(FlagsSetBeforeInitTest, TryFromEnv) {
// ParseCommandLineNonHelpFlags() uses the last definition of a flag
// in case it's defined more than once.
-DEFINE_int32(test_flag, -1, "used for testing commandlineflags.cc");
+DEFINE_int32(test_flag, -1, "used for testing gflags.cc");
// Parses and returns the --test_flag flag.
// If with_help is true, calls ParseCommandLineFlags; otherwise calls
@@ -1248,8 +1175,8 @@ TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
NULL,
};
- EXPECT_EQ(2, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
- EXPECT_EQ(2, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
+ EXPECT_EQ(2, ParseTestFlag(true, arraysize(argv) - 1, argv));
+ EXPECT_EQ(2, ParseTestFlag(false, arraysize(argv) - 1, argv));
}
TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
@@ -1260,8 +1187,8 @@ TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
NULL,
};
- EXPECT_EQ(2, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
- EXPECT_EQ(2, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
+ EXPECT_EQ(2, ParseTestFlag(true, arraysize(argv) - 1, argv));
+ EXPECT_EQ(2, ParseTestFlag(false, arraysize(argv) - 1, argv));
}
TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
@@ -1273,8 +1200,8 @@ TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
NULL,
};
- EXPECT_EQ(2, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
- EXPECT_EQ(2, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
+ EXPECT_EQ(2, ParseTestFlag(true, arraysize(argv) - 1, argv));
+ EXPECT_EQ(2, ParseTestFlag(false, arraysize(argv) - 1, argv));
}
TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
@@ -1286,8 +1213,8 @@ TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
NULL,
};
- EXPECT_EQ(3, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
- EXPECT_EQ(3, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
+ EXPECT_EQ(3, ParseTestFlag(true, arraysize(argv) - 1, argv));
+ EXPECT_EQ(3, ParseTestFlag(false, arraysize(argv) - 1, argv));
}
TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
@@ -1300,8 +1227,8 @@ TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
NULL,
};
- EXPECT_EQ(3, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
- EXPECT_EQ(3, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
+ EXPECT_EQ(3, ParseTestFlag(true, arraysize(argv) - 1, argv));
+ EXPECT_EQ(3, ParseTestFlag(false, arraysize(argv) - 1, argv));
}
TEST(ParseCommandLineFlagsAndDashArgs, TwoDashArgFirst) {
@@ -1312,8 +1239,8 @@ TEST(ParseCommandLineFlagsAndDashArgs, TwoDashArgFirst) {
NULL,
};
- EXPECT_EQ(-1, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
- EXPECT_EQ(-1, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
+ EXPECT_EQ(-1, ParseTestFlag(true, arraysize(argv) - 1, argv));
+ EXPECT_EQ(-1, ParseTestFlag(false, arraysize(argv) - 1, argv));
}
TEST(ParseCommandLineFlagsAndDashArgs, TwoDashArgMiddle) {
@@ -1325,8 +1252,8 @@ TEST(ParseCommandLineFlagsAndDashArgs, TwoDashArgMiddle) {
NULL,
};
- EXPECT_EQ(7, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
- EXPECT_EQ(7, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
+ EXPECT_EQ(7, ParseTestFlag(true, arraysize(argv) - 1, argv));
+ EXPECT_EQ(7, ParseTestFlag(false, arraysize(argv) - 1, argv));
}
TEST(ParseCommandLineFlagsAndDashArgs, OneDashArg) {
@@ -1337,10 +1264,11 @@ TEST(ParseCommandLineFlagsAndDashArgs, OneDashArg) {
NULL,
};
- EXPECT_EQ(0, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
- EXPECT_EQ(0, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
+ EXPECT_EQ(0, ParseTestFlag(true, arraysize(argv) - 1, argv));
+ EXPECT_EQ(0, ParseTestFlag(false, arraysize(argv) - 1, argv));
}
+#ifdef GTEST_HAS_DEATH_TEST
TEST(ParseCommandLineFlagsUnknownFlagDeathTest,
FlagIsCompletelyUnknown) {
const char* argv[] = {
@@ -1349,9 +1277,9 @@ TEST(ParseCommandLineFlagsUnknownFlagDeathTest,
NULL,
};
- EXPECT_DEATH(ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv),
+ EXPECT_DEATH(ParseTestFlag(true, arraysize(argv) - 1, argv),
"unknown command line flag.*");
- EXPECT_DEATH(ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv),
+ EXPECT_DEATH(ParseTestFlag(false, arraysize(argv) - 1, argv),
"unknown command line flag.*");
}
@@ -1363,9 +1291,9 @@ TEST(ParseCommandLineFlagsUnknownFlagDeathTest,
NULL,
};
- EXPECT_DEATH(ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv),
+ EXPECT_DEATH(ParseTestFlag(true, arraysize(argv) - 1, argv),
"unknown command line flag.*");
- EXPECT_DEATH(ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv),
+ EXPECT_DEATH(ParseTestFlag(false, arraysize(argv) - 1, argv),
"unknown command line flag.*");
}
@@ -1377,11 +1305,12 @@ TEST(ParseCommandLineFlagsUnknownFlagDeathTest,
NULL,
};
- EXPECT_DEATH(ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv),
+ EXPECT_DEATH(ParseTestFlag(true, arraysize(argv) - 1, argv),
"boolean value .* specified for .* command line flag");
- EXPECT_DEATH(ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv),
+ EXPECT_DEATH(ParseTestFlag(false, arraysize(argv) - 1, argv),
"boolean value .* specified for .* command line flag");
}
+#endif
TEST(ParseCommandLineFlagsWrongFields,
DescriptionIsInvalid) {
@@ -1418,7 +1347,7 @@ TEST(FlagsValidator, ValidFlagViaArgv) {
NULL,
};
EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5));
- EXPECT_EQ(5, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
+ EXPECT_EQ(5, ParseTestFlag(true, arraysize(argv) - 1, argv));
// Undo the flag validator setting
EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL));
}
@@ -1443,6 +1372,7 @@ TEST(FlagsValidator, ValidFlagViaSetValue) {
EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL));
}
+#ifdef GTEST_HAS_DEATH_TEST
TEST(FlagsValidatorDeathTest, InvalidFlagViaArgv) {
const char* argv[] = {
"my_test",
@@ -1450,10 +1380,11 @@ TEST(FlagsValidatorDeathTest, InvalidFlagViaArgv) {
NULL,
};
EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5));
- EXPECT_DEATH(ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv),
+ EXPECT_DEATH(ParseTestFlag(true, arraysize(argv) - 1, argv),
"ERROR: failed validation of new value '50' for flag 'test_flag'");
EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL));
}
+#endif
TEST(FlagsValidator, InvalidFlagViaSetDefault) {
EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5));
@@ -1477,6 +1408,7 @@ TEST(FlagsValidator, InvalidFlagViaSetValue) {
EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL));
}
+#ifdef GTEST_HAS_DEATH_TEST
TEST(FlagsValidatorDeathTest, InvalidFlagNeverSet) {
// If a flag keeps its default value, and that default value is
// invalid, we should die at argv-parse time.
@@ -1485,9 +1417,10 @@ TEST(FlagsValidatorDeathTest, InvalidFlagNeverSet) {
NULL,
};
EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5));
- EXPECT_DEATH(ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv),
+ EXPECT_DEATH(ParseTestFlag(true, arraysize(argv) - 1, argv),
"ERROR: --test_flag must be set on the commandline");
}
+#endif
TEST(FlagsValidator, InvalidFlagPtr) {
int32 dummy;
@@ -1538,13 +1471,15 @@ TEST(FlagsValidator, FlagSaver) {
}
-static int Main(int argc, char **argv) {
- // We need to call SetArgv before SetUsage, so our "test" argv will
+} // unnamed namespace
+
+int main(int argc, char **argv) {
+ // We need to call SetArgv before parsing flags, so our "test" argv will
// win out over this executable's real argv. That makes running this
// test with a real --help flag kinda annoying, unfortunately.
const char* test_argv[] = { "/test/argv/for/gflags_unittest",
"argv 2", "3rd argv", "argv #4" };
- SetArgv(GET_ARRAY_SIZE(test_argv), test_argv);
+ SetArgv(arraysize(test_argv), test_argv);
// The first arg is the usage message, also important for testing.
string usage_message = (string(GetArgv0()) +
@@ -1558,35 +1493,23 @@ static int Main(int argc, char **argv) {
// Modify flag values from declared default value in two ways.
// The recommended way:
SetCommandLineOptionWithMode("changed_bool1", "true", SET_FLAGS_DEFAULT);
+
// The non-recommended way:
FLAGS_changed_bool2 = true;
SetUsageMessage(usage_message.c_str());
SetVersionString("test_version");
ParseCommandLineFlags(&argc, &argv, true);
+ MakeTmpdir(&FLAGS_test_tmpdir);
-#if defined(__MINGW32__)
- // I had trouble creating a directory in /tmp from mingw
- FLAGS_test_tmpdir = "./gflags_unittest_testdir";
- mkdir(FLAGS_test_tmpdir.c_str()); // mingw has a weird one-arg mkdir
-#elif defined(_MSC_VER)
- char tmppath_buffer[1024];
- int tmppath_len = GetTempPathA(sizeof(tmppath_buffer), tmppath_buffer);
- assert(tmppath_len > 0 && tmppath_len < sizeof(tmppath_buffer));
- assert(tmppath_buffer[tmppath_len - 1] == '\\'); // API guarantees it
- FLAGS_test_tmpdir = string(tmppath_buffer) + "gflags_unittest_testdir";
- _mkdir(FLAGS_test_tmpdir.c_str());
-#else
- mkdir(FLAGS_test_tmpdir.c_str(), 0755);
-#endif
-
- return RUN_ALL_TESTS();
+ const int exit_status = RUN_ALL_TESTS();
+ ShutDownCommandLineFlags();
+ return exit_status;
}
_END_GOOGLE_NAMESPACE_
int main(int argc, char** argv) {
- const int exit_status = GOOGLE_NAMESPACE::Main(argc, argv);
- GOOGLE_NAMESPACE::ShutDownCommandLineFlags();
- return exit_status;
+ return GOOGLE_NAMESPACE::main(argc, argv);
}
+
diff --git a/src/gflags_unittest.sh b/src/gflags_unittest.sh
index 20c84a0..39b03c5 100755
--- a/src/gflags_unittest.sh
+++ b/src/gflags_unittest.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
# Copyright (c) 2006, Google Inc.
# All rights reserved.
@@ -32,21 +32,17 @@
# ---
# Author: Craig Silverstein
#
-# Just tries to run gflags_unittest with various flags defined in
-# gflags.cc, and make sure they give the appropriate exit
-# status and appropriate error message.
-
-if [ -z "$1" ]
-then
- echo "USAGE: $0 <unittest exe> [top_srcdir] [tmpdir]"
- exit 1
-fi
-
+# Just tries to run the gflags_unittest with various flags
+# defined in gflags.cc, and make sure they give the
+# appropriate exit status and appropriate error message.
+
+if [ -z "$1" ]; then
+ echo "USAGE: $0 <unittest exe> [top_srcdir] [tmpdir]"
+ exit 1
+fi
EXE="$1"
SRCDIR="${2:-./}"
TMPDIR="${3:-/tmp/gflags}"
-
-# Executables built with the main source file suffixed with "-main" and "_main".
EXE2="${EXE}2" # eg, gflags_unittest2
EXE3="${EXE}3" # eg, gflags_unittest3
@@ -65,8 +61,9 @@ ExpectExe() {
local unexpected_output="$1"
shift
- # We always add --srcdir=$SRCDIR because it's needed for correctness
- "$executable" --srcdir="$SRCDIR" "$@" > "$TMPDIR/test.$line_number" 2>&1
+ # We always add --srcdir because it's needed for correctness
+ "$executable" --srcdir="$SRCDIR" "$@" > "$TMPDIR/test.$line_number" 2>&1
+
local actual_rc=$?
if [ $actual_rc != $expected_rc ]; then
echo "Test on line $line_number failed:" \
@@ -111,7 +108,7 @@ export FLAGS_help=false
# First, just make sure the unittest works as-is
Expect $LINENO 0 "PASS" ""
-# --help should show all flags, including flags from gflags_reporting.cc
+# --help should show all flags, including flags from gflags_reporting
Expect $LINENO 1 "/gflags_reporting.cc" "" --help
# Make sure --help reflects flag changes made before flag-parsing
@@ -133,17 +130,18 @@ Expect $LINENO 0 "PASS" "" --help=false
Expect $LINENO 1 "/gflags_reporting.cc" "" -helpfull
# --helpshort should show only flags from the unittest itself
-Expect $LINENO 1 "/gflags_unittest.cc" "/gflags_reporting.cc" --helpshort
+Expect $LINENO 1 "/gflags_unittest.cc" \
+ "/gflags_reporting.cc" --helpshort
# --helpshort should show the tldflag we created in the unittest dir
Expect $LINENO 1 "tldflag1" "/google.cc" --helpshort
Expect $LINENO 1 "tldflag2" "/google.cc" --helpshort
# --helpshort should work if the main source file is suffixed with [_-]main
-ExpectExe "$EXE2" $LINENO 1 "/gflags_unittest-main.cc" "/gflags_reporting.cc" \
- --helpshort
-ExpectExe "$EXE3" $LINENO 1 "/gflags_unittest_main.cc" "/gflags_reporting.cc" \
- --helpshort
+ExpectExe "$EXE2" $LINENO 1 "/gflags_unittest-main.cc" \
+ "/gflags_reporting.cc" --helpshort
+ExpectExe "$EXE3" $LINENO 1 "/gflags_unittest_main.cc" \
+ "/gflags_reporting.cc" --helpshort
# --helpon needs an argument
Expect $LINENO 1 \
@@ -151,20 +149,22 @@ Expect $LINENO 1 \
"" --helpon
# --helpon argument indicates what file we'll show args from
-Expect $LINENO 1 "/gflags.cc" "/gflags_unittest.cc" --helpon=gflags
+Expect $LINENO 1 "/gflags.cc" "/gflags_unittest.cc" \
+ --helpon=gflags
# another way of specifying the argument
-Expect $LINENO 1 "/gflags.cc" "/gflags_unittest.cc" --helpon gflags
+Expect $LINENO 1 "/gflags.cc" "/gflags_unittest.cc" \
+ --helpon gflags
# test another argument
Expect $LINENO 1 "/gflags_unittest.cc" "/gflags.cc" \
- --helpon gflags_unittest
+ --helpon=gflags_unittest
# helpmatch is like helpon but takes substrings
-Expect $LINENO 1 "/gflags_reporting.cc" "/gflags_unittest.cc" \
- -helpmatch reporting
-Expect $LINENO 1 "/gflags_unittest.cc" "/gflags.cc" \
- -helpmatch=unittest
+Expect $LINENO 1 "/gflags_reporting.cc" \
+ "/gflags_unittest.cc" -helpmatch reporting
+Expect $LINENO 1 "/gflags_unittest.cc" \
+ "/gflags.cc" -helpmatch=unittest
# if no flags are found with helpmatch or helpon, suggest --help
Expect $LINENO 1 "No modules matched" "/gflags_unittest.cc" \
@@ -202,8 +202,10 @@ Expect $LINENO 0 "PASS" "" --flagfile="$TMPDIR/flagfile.2"
Expect $LINENO 0 "PASS" "" --flagfile="$TMPDIR/flagfile.3"
# Also try to load flags from the environment
-Expect $LINENO 0 "gflags_unittest" "gflags_unittest.cc" --fromenv=version
-Expect $LINENO 0 "gflags_unittest" "gflags_unittest.cc" --tryfromenv=version
+Expect $LINENO 0 "gflags_unittest" "gflags_unittest.cc" \
+ --fromenv=version
+Expect $LINENO 0 "gflags_unittest" "gflags_unittest.cc" \
+ --tryfromenv=version
Expect $LINENO 0 "PASS" "" --fromenv=help
Expect $LINENO 0 "PASS" "" --tryfromenv=help
Expect $LINENO 1 "helpfull not found in environment" "" --fromenv=helpfull
@@ -221,10 +223,11 @@ Expect $LINENO 0 "gflags_unittest" "gflags_unittest.cc" \
# Make sure -- by itself stops argv processing
Expect $LINENO 0 "PASS" "" -- --help
+
# And we should die if the flag value doesn't pass the validator
Expect $LINENO 1 "ERROR: failed validation of new value 'true' for flag 'always_fail'" "" --always_fail
-# TODO(wojtekm) And if locking in validators fails.
+# TODO(user) And if locking in validators fails.
# Expect $LINENO 0 "PASS" "" --deadlock_if_cant_lock
echo "PASS"
diff --git a/src/mutex.h b/src/mutex.h
index 6e1e897..7c3c060 100644
--- a/src/mutex.h
+++ b/src/mutex.h
@@ -28,7 +28,6 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// ---
-// Author: Craig Silverstein.
//
// A simple mutex wrapper, supporting locks and read-write locks.
// You should assume the locks are *not* re-entrant.
@@ -117,7 +116,12 @@
#if defined(NO_THREADS)
typedef int MutexType; // to keep a lock-count
#elif defined(_WIN32) || defined(__CYGWIN32__) || defined(__CYGWIN64__)
-# define WIN32_LEAN_AND_MEAN // We only need minimal includes
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN // We only need minimal includes
+# endif
+# ifndef NOMINMAX
+# define NOMINMAX // Don't want windows to override min()/max()
+# endif
# ifdef GMUTEX_TRYLOCK
// We need Windows NT or later for TryEnterCriticalSection(). If you
// don't need that functionality, you can remove these _WIN32_WINNT
@@ -134,7 +138,10 @@
// *does* cause problems for FreeBSD, or MacOSX, but isn't needed
// for locking there.)
# ifdef __linux__
-# define _XOPEN_SOURCE 500 // may be needed to get the rwlock calls
+# if _XOPEN_SOURCE < 500 // including not being defined at all
+# undef _XOPEN_SOURCE
+# define _XOPEN_SOURCE 500 // may be needed to get the rwlock calls
+# endif
# endif
# include <pthread.h>
typedef pthread_rwlock_t MutexType;
diff --git a/src/util.h b/src/util.h
new file mode 100644
index 0000000..8170c0a
--- /dev/null
+++ b/src/util.h
@@ -0,0 +1,319 @@
+// Copyright (c) 2011, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// ---
+//
+// Some generically useful utility routines that in google-land would
+// be their own projects. We make a shortened version here.
+
+#ifndef GFLAGS_UTIL_H_
+#define GFLAGS_UTIL_H_
+
+#include <assert.h>
+#include <config.h>
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#include <stdarg.h> // for va_*
+#include <stdlib.h>
+#include <stdio.h>
+#include <iostream>
+#include <string>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif // for mkdir()
+
+_START_GOOGLE_NAMESPACE_
+
+// This is used for unittests for death-testing. It is defined in gflags.cc.
+extern GFLAGS_DLL_DECL void (*gflags_exitfunc)(int);
+
+// Work properly if either strtoll or strtoq is on this system
+#ifdef HAVE_STRTOLL
+# define strto64 strtoll
+# define strtou64 strtoull
+#elif HAVE_STRTOQ
+# define strto64 strtoq
+# define strtou64 strtouq
+#else
+// Neither strtoll nor strtoq are defined. I hope strtol works!
+# define strto64 strtol
+# define strtou64 strtoul
+#endif
+
+// If we have inttypes.h, it will have defined PRId32/etc for us. If
+// not, take our best guess.
+#ifndef PRId32
+# define PRId32 "d"
+#endif
+#ifndef PRId64
+# define PRId64 "lld"
+#endif
+#ifndef PRIu64
+# define PRIu64 "llu"
+#endif
+
+typedef signed char int8;
+typedef unsigned char uint8;
+
+// -- utility macros ---------------------------------------------------------
+
+template <bool> struct CompileAssert {};
+#define COMPILE_ASSERT(expr, msg) \
+ typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]
+
+// Returns the number of elements in an array.
+#define arraysize(arr) (sizeof(arr)/sizeof(*(arr)))
+
+
+// -- logging and testing ---------------------------------------------------
+
+// For now, we ignore the level for logging, and don't show *VLOG's at
+// all, except by hand-editing the lines below
+#define LOG(level) std::cerr
+#define VLOG(level) if (true) {} else std::cerr
+#define DVLOG(level) if (true) {} else std::cerr
+
+// CHECK dies with a fatal error if condition is not true. It is *not*
+// controlled by NDEBUG, so the check will be executed regardless of
+// compilation mode. Therefore, it is safe to do things like:
+// CHECK(fp->Write(x) == 4)
+// We allow stream-like objects after this for debugging, but they're ignored.
+#define EXPECT_TRUE(condition) \
+ if (true) { \
+ if (!(condition)) { \
+ fprintf(stderr, "Check failed: %s\n", #condition); \
+ exit(1); \
+ } \
+ } else std::cerr << ""
+
+#define EXPECT_OP(op, val1, val2) \
+ if (true) { \
+ if (!((val1) op (val2))) { \
+ fprintf(stderr, "Check failed: %s %s %s\n", #val1, #op, #val2); \
+ exit(1); \
+ } \
+ } else std::cerr << ""
+
+#define EXPECT_EQ(val1, val2) EXPECT_OP(==, val1, val2)
+#define EXPECT_NE(val1, val2) EXPECT_OP(!=, val1, val2)
+#define EXPECT_LE(val1, val2) EXPECT_OP(<=, val1, val2)
+#define EXPECT_LT(val1, val2) EXPECT_OP(< , val1, val2)
+#define EXPECT_GE(val1, val2) EXPECT_OP(>=, val1, val2)
+#define EXPECT_GT(val1, val2) EXPECT_OP(> , val1, val2)
+#define EXPECT_FALSE(cond) EXPECT_TRUE(!(cond))
+
+// C99 declares isnan and isinf should be macros, so the #ifdef test
+// should be reliable everywhere. Of course, it's not, but these
+// are testing pertty marginal functionality anyway, so it's ok to
+// not-run them even in situations they might, with effort, be made to work.
+#ifdef isnan // Some compilers, like sun's for Solaris 10, don't define this
+#define EXPECT_NAN(arg) \
+ do { \
+ if (!isnan(arg)) { \
+ fprintf(stderr, "Check failed: isnan(%s)\n", #arg); \
+ exit(1); \
+ } \
+ } while (0)
+#else
+#define EXPECT_NAN(arg)
+#endif
+
+#ifdef isinf // Some compilers, like sun's for Solaris 10, don't define this
+#define EXPECT_INF(arg) \
+ do { \
+ if (!isinf(arg)) { \
+ fprintf(stderr, "Check failed: isinf(%s)\n", #arg); \
+ exit(1); \
+ } \
+ } while (0)
+#else
+#define EXPECT_INF(arg)
+#endif
+
+#define EXPECT_DOUBLE_EQ(val1, val2) \
+ do { \
+ if (((val1) < (val2) - 0.001 || (val1) > (val2) + 0.001)) { \
+ fprintf(stderr, "Check failed: %s == %s\n", #val1, #val2); \
+ exit(1); \
+ } \
+ } while (0)
+
+#define EXPECT_STREQ(val1, val2) \
+ do { \
+ if (strcmp((val1), (val2)) != 0) { \
+ fprintf(stderr, "Check failed: streq(%s, %s)\n", #val1, #val2); \
+ exit(1); \
+ } \
+ } while (0)
+
+// Call this in a .cc file where you will later call RUN_ALL_TESTS in main().
+#define TEST_INIT \
+ static std::vector<void (*)()> g_testlist; /* the tests to run */ \
+ static int RUN_ALL_TESTS() { \
+ std::vector<void (*)()>::const_iterator it; \
+ for (it = g_testlist.begin(); it != g_testlist.end(); ++it) { \
+ (*it)(); /* The test will error-exit if there's a problem. */ \
+ } \
+ fprintf(stderr, "\nPassed %d tests\n\nPASS\n", \
+ static_cast<int>(g_testlist.size())); \
+ return 0; \
+ }
+
+// Note that this macro uses a FlagSaver to keep tests isolated.
+#define TEST(a, b) \
+ struct Test_##a##_##b { \
+ Test_##a##_##b() { g_testlist.push_back(&Run); } \
+ static void Run() { \
+ FlagSaver fs; \
+ fprintf(stderr, "Running test %s/%s\n", #a, #b); \
+ RunTest(); \
+ } \
+ static void RunTest(); \
+ }; \
+ static Test_##a##_##b g_test_##a##_##b; \
+ void Test_##a##_##b::RunTest()
+
+// This is a dummy class that eases the google->opensource transition.
+namespace testing {
+class Test {};
+}
+
+// Call this in a .cc file where you will later call EXPECT_DEATH
+#define EXPECT_DEATH_INIT \
+ static bool g_called_exit; \
+ static void CalledExit(int) { g_called_exit = true; }
+
+#define EXPECT_DEATH(fn, msg) \
+ do { \
+ g_called_exit = false; \
+ gflags_exitfunc = &CalledExit; \
+ fn; \
+ gflags_exitfunc = &exit; /* set back to its default */ \
+ if (!g_called_exit) { \
+ fprintf(stderr, "Function didn't die (%s): %s\n", msg, #fn); \
+ exit(1); \
+ } \
+ } while (0)
+
+#define GTEST_HAS_DEATH_TEST 1
+
+// -- path routines ----------------------------------------------------------
+
+// Tries to create the directory path as a temp-dir. If it fails,
+// changes path to some directory it *can* create.
+inline void MakeTmpdir(std::string* path) {
+#if defined(__MINGW32__)
+ // I had trouble creating a directory in /tmp from mingw
+ *path = "./gflags_unittest_testdir";
+ mkdir(path->c_str()); // mingw has a weird one-arg mkdir
+#elif defined(_MSC_VER)
+ char tmppath_buffer[1024];
+ int tmppath_len = GetTempPathA(sizeof(tmppath_buffer), tmppath_buffer);
+ assert(tmppath_len > 0 && tmppath_len < sizeof(tmppath_buffer));
+ assert(tmppath_buffer[tmppath_len - 1] == '\\'); // API guarantees it
+ *path = std::string(tmppath_buffer) + "gflags_unittest_testdir";
+ _mkdir(path->c_str());
+#else
+ mkdir(path->c_str(), 0755);
+#endif
+}
+
+// -- string routines --------------------------------------------------------
+
+inline void InternalStringPrintf(std::string* output, const char* format,
+ va_list ap) {
+ char space[128]; // try a small buffer and hope it fits
+
+ // It's possible for methods that use a va_list to invalidate
+ // the data in it upon use. The fix is to make a copy
+ // of the structure before using it and use that copy instead.
+ va_list backup_ap;
+ va_copy(backup_ap, ap);
+ int bytes_written = vsnprintf(space, sizeof(space), format, backup_ap);
+ va_end(backup_ap);
+
+ if ((bytes_written >= 0) && (bytes_written < sizeof(space))) {
+ output->append(space, bytes_written);
+ return;
+ }
+
+ // Repeatedly increase buffer size until it fits.
+ int length = sizeof(space);
+ while (true) {
+ if (bytes_written < 0) {
+ // Older snprintf() behavior. :-( Just try doubling the buffer size
+ length *= 2;
+ } else {
+ // We need exactly "bytes_written+1" characters
+ length = bytes_written+1;
+ }
+ char* buf = new char[length];
+
+ // Restore the va_list before we use it again
+ va_copy(backup_ap, ap);
+ bytes_written = vsnprintf(buf, length, format, backup_ap);
+ va_end(backup_ap);
+
+ if ((bytes_written >= 0) && (bytes_written < length)) {
+ output->append(space, bytes_written);
+ delete[] buf;
+ return;
+ }
+ delete[] buf;
+ }
+}
+
+// Clears output before writing to it.
+inline void SStringPrintf(std::string* output, const char* format, ...) {
+ va_list ap;
+ va_start(ap, format);
+ output->clear();
+ InternalStringPrintf(output, format, ap);
+ va_end(ap);
+}
+
+inline void StringAppendF(std::string* output, const char* format, ...) {
+ va_list ap;
+ va_start(ap, format);
+ InternalStringPrintf(output, format, ap);
+ va_end(ap);
+}
+
+inline std::string StringPrintf(const char* format, ...) {
+ va_list ap;
+ va_start(ap, format);
+ std::string output;
+ InternalStringPrintf(&output, format, ap);
+ va_end(ap);
+ return output;
+}
+
+_END_GOOGLE_NAMESPACE_
+
+#endif // GFLAGS_UTIL_H_
diff --git a/src/windows/gflags/gflags.h b/src/windows/gflags/gflags.h
index 1c72456..0e9cc76 100644
--- a/src/windows/gflags/gflags.h
+++ b/src/windows/gflags/gflags.h
@@ -28,7 +28,6 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ---
-// Author: Ray Sidney
// Revamped and reorganized by Craig Silverstein
//
// This is the file that should be included by any file which declares
@@ -52,8 +51,8 @@
// if (FLAGS_verbose) printf("Records %d-%d\n", FLAGS_start, FLAGS_end);
// }
//
-// Then, at the command-line:
-// ./foo --noverbose --start=5 --end=100
+// Then, at the command-line:
+// ./foo --noverbose --start=5 --end=100
//
// For more details, see
// doc/gflags.html
@@ -76,38 +75,23 @@
// other thread is writing to the variable or calling non-const
// methods of this class.
-#ifndef GOOGLE_GFLAGS_H_
-#define GOOGLE_GFLAGS_H_
+#ifndef BASE_COMMANDLINEFLAGS_H_
+#define BASE_COMMANDLINEFLAGS_H_
#include <string>
#include <vector>
#include <gflags/gflags_declare.h> // IWYU pragma: export
+namespace google {
-// Annoying stuff for windows -- makes sure clients can import these functions
-#if defined(_WIN32)
-# ifndef GFLAGS_DLL_DECL
-# define GFLAGS_DLL_DECL __declspec(dllimport)
-# endif
-# ifndef GFLAGS_DLL_DECLARE_FLAG
-# define GFLAGS_DLL_DECLARE_FLAG __declspec(dllimport)
-# endif
-# ifndef GFLAGS_DLL_DEFINE_FLAG
-# define GFLAGS_DLL_DEFINE_FLAG __declspec(dllexport)
-# endif
-#else
-# ifndef GFLAGS_DLL_DECL
-# define GFLAGS_DLL_DECL
-# endif
-# ifndef GFLAGS_DLL_DECLARE_FLAG
-# define GFLAGS_DLL_DECLARE_FLAG
-# endif
-# ifndef GFLAGS_DLL_DEFINE_FLAG
-# define GFLAGS_DLL_DEFINE_FLAG
-# endif
+//
+// NOTE: all functions below MUST have an explicit 'extern' before
+// them. Our automated opensourcing tools use this as a signal to do
+// appropriate munging for windows, which needs to add GFLAGS_DLL_DECL.
+//
+#ifdef SWIG // it apparently can't see the define in gflags_declare.h
+# define GFLAGS_DLL_DECL /**/
#endif
-namespace google {
-
// --------------------------------------------------------------------
// To actually define a flag in a file, use DEFINE_bool,
// DEFINE_string, etc. at the bottom of this file. You may also find
@@ -137,18 +121,19 @@ namespace google {
// Returns true if successfully registered, false if not (because the
// first argument doesn't point to a command-line flag, or because a
// validator is already registered for this flag).
-GFLAGS_DLL_DECL bool RegisterFlagValidator(const bool* flag,
- bool (*validate_fn)(const char*, bool));
-GFLAGS_DLL_DECL bool RegisterFlagValidator(const int32* flag,
- bool (*validate_fn)(const char*, int32));
-GFLAGS_DLL_DECL bool RegisterFlagValidator(const int64* flag,
- bool (*validate_fn)(const char*, int64));
-GFLAGS_DLL_DECL bool RegisterFlagValidator(const uint64* flag,
- bool (*validate_fn)(const char*, uint64));
-GFLAGS_DLL_DECL bool RegisterFlagValidator(const double* flag,
- bool (*validate_fn)(const char*, double));
-GFLAGS_DLL_DECL bool RegisterFlagValidator(const std::string* flag,
- bool (*validate_fn)(const char*, const std::string&));
+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 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));
+extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const std::string* flag,
+ bool (*validate_fn)(const char*,
+ const std::string&));
// --------------------------------------------------------------------
@@ -163,20 +148,20 @@ GFLAGS_DLL_DECL bool RegisterFlagValidator(const std::string* flag,
// These variables are static, so you should only set them once.
struct GFLAGS_DLL_DECL CommandLineFlagInfo {
- std::string name; // the name of the flag
- std::string type; // the type of the flag: int32, etc
- std::string description; // the "help text" associated with the flag
- std::string current_value; // the current value, as a string
- std::string default_value; // the default value, as a string
- std::string filename; // 'cleaned' version of filename holding the flag
- bool has_validator_fn; // true if RegisterFlagValidator called on flag
- bool is_default; // true if the flag has the default value and
- // has not been set explicitly from the cmdline
- // or via SetCommandLineOption
+ std::string name; // the name of the flag
+ std::string type; // the type of the flag: int32, etc
+ std::string description; // the "help text" associated with the flag
+ std::string current_value; // the current value, as a string
+ std::string default_value; // the default value, as a string
+ std::string filename; // 'cleaned' version of filename holding the flag
+ bool has_validator_fn; // true if RegisterFlagValidator called on this flag
+ bool is_default; // true if the flag has the default value and
+ // has not been set explicitly from the cmdline
+ // or via SetCommandLineOption
};
// Using this inside of a validator is a recipe for a deadlock.
-// TODO(wojtekm) Fix locking when validators are running, to make it safe to
+// TODO(user) Fix locking when validators are running, to make it safe to
// call validators during ParseAllFlags.
// Also make sure then to uncomment the corresponding unit test in
// gflags_unittest.sh
@@ -191,20 +176,26 @@ extern GFLAGS_DLL_DECL std::string DescribeOneFlag(const CommandLineFlagInfo& fl
// Thread-hostile; meant to be called before any threads are spawned.
extern GFLAGS_DLL_DECL void SetArgv(int argc, const char** argv);
+
// The following functions are thread-safe as long as SetArgv() is
// only called before any threads start.
-extern GFLAGS_DLL_DECL const std::vector<std::string>& GetArgvs(); // all of argv as a vector
-extern GFLAGS_DLL_DECL const char* GetArgv(); // all of argv as a string
-extern GFLAGS_DLL_DECL const char* GetArgv0(); // only argv0
-extern GFLAGS_DLL_DECL uint32 GetArgvSum(); // simple checksum of argv
-extern GFLAGS_DLL_DECL const char* ProgramInvocationName(); // argv0, or "UNKNOWN" if not set
+extern GFLAGS_DLL_DECL const std::vector<std::string>& GetArgvs();
+extern GFLAGS_DLL_DECL const char* GetArgv(); // all of argv as a string
+extern GFLAGS_DLL_DECL const char* GetArgv0(); // only argv0
+extern GFLAGS_DLL_DECL uint32 GetArgvSum(); // simple checksum of argv
+extern GFLAGS_DLL_DECL const char* ProgramInvocationName(); // argv0, or "UNKNOWN" if not set
extern GFLAGS_DLL_DECL const char* ProgramInvocationShortName(); // basename(argv0)
-// ProgramUsage() and VersionString() are thread-safe as long as
-// SetUsageMessage() and SetVersionString() are only called before any
-// threads start.
-extern GFLAGS_DLL_DECL const char* ProgramUsage(); // string set by SetUsageMessage()
+
+// ProgramUsage() is thread-safe as long as SetUsageMessage() is only
+// called before any threads start.
+extern GFLAGS_DLL_DECL const char* ProgramUsage(); // string set by SetUsageMessage()
+
+// VersionString() is thread-safe as long as SetVersionString() is only
+// called before any threads start.
extern GFLAGS_DLL_DECL const char* VersionString(); // string set by SetVersionString()
+
+
// --------------------------------------------------------------------
// Normally you access commandline flags by just saying "if (FLAGS_foo)"
// or whatever, and set them by calling "FLAGS_foo = bar" (or, more
@@ -249,7 +240,7 @@ enum GFLAGS_DLL_DECL FlagSettingMode {
// SetCommandLineOption uses set_mode == SET_FLAGS_VALUE (the common case)
extern GFLAGS_DLL_DECL std::string SetCommandLineOption(const char* name, const char* value);
extern GFLAGS_DLL_DECL std::string SetCommandLineOptionWithMode(const char* name, const char* value,
- FlagSettingMode set_mode);
+ FlagSettingMode set_mode);
// --------------------------------------------------------------------
@@ -270,7 +261,7 @@ extern GFLAGS_DLL_DECL std::string SetCommandLineOptionWithMode(const char* name
// // without worrying about restoring the FLAG values.
// }
//
-// Note: This class is marked with __attribute__((unused)) because all the
+// Note: This class is marked with ATTRIBUTE_UNUSED because all the
// work is done in the constructor and destructor, so in the standard
// usage example above, the compiler would complain that it's an
// unused variable.
@@ -287,7 +278,8 @@ class GFLAGS_DLL_DECL FlagSaver {
FlagSaver(const FlagSaver&); // no copying!
void operator=(const FlagSaver&);
-} ;
+}
+;
// --------------------------------------------------------------------
// Some deprecated or hopefully-soon-to-be-deprecated functions.
@@ -297,12 +289,11 @@ extern GFLAGS_DLL_DECL std::string CommandlineFlagsIntoString();
// Usually where this is used, a FlagSaver should be used instead.
extern GFLAGS_DLL_DECL bool ReadFlagsFromString(const std::string& flagfilecontents,
const char* prog_name,
- bool errors_are_fatal); // uses SET_FLAGS_VALUE
+ bool errors_are_fatal); // uses SET_FLAGS_VALUE
// These let you manually implement --flagfile functionality.
// DEPRECATED.
extern GFLAGS_DLL_DECL bool AppendFlagsIntoFile(const std::string& filename, const char* prog_name);
-extern GFLAGS_DLL_DECL bool SaveCommandFlags(); // actually defined in google.cc !
extern GFLAGS_DLL_DECL bool ReadFromFlagsFile(const std::string& filename, const char* prog_name,
bool errors_are_fatal); // uses SET_FLAGS_VALUE
@@ -324,7 +315,7 @@ extern GFLAGS_DLL_DECL const char *StringFromEnv(const char *varname, const char
// --------------------------------------------------------------------
-// The next two functions parse commandlineflags from main():
+// The next two functions parse gflags from main():
// Set the "usage" message for this program. For example:
// string usage("This program does nothing. Sample usage:\n");
@@ -337,7 +328,8 @@ extern GFLAGS_DLL_DECL void SetUsageMessage(const std::string& usage);
// Sets the version string, which is emitted with --version.
// For instance: SetVersionString("1.3");
// Thread-hostile; meant to be called before any threads are spawned.
-extern void SetVersionString(const std::string& version);
+extern GFLAGS_DLL_DECL void SetVersionString(const std::string& version);
+
// Looks for flags in argv and parses them. Rearranges argv to put
// flags first, or removes them entirely if remove_flags is true.
@@ -346,8 +338,7 @@ extern void SetVersionString(const std::string& version);
// of the first non-flag argument.
// See top-of-file for more details on this function.
#ifndef SWIG // In swig, use ParseCommandLineFlagsScript() instead.
-extern GFLAGS_DLL_DECL uint32 ParseCommandLineFlags(int *argc, char*** argv,
- bool remove_flags);
+extern GFLAGS_DLL_DECL uint32 ParseCommandLineFlags(int *argc, char*** argv, bool remove_flags);
#endif
@@ -385,11 +376,12 @@ extern GFLAGS_DLL_DECL void ReparseCommandLineNonHelpFlags();
// Clean up memory allocated by flags. This is only needed to reduce
// the quantity of "potentially leaked" reports emitted by memory
// debugging tools such as valgrind. It is not required for normal
-// operation, or for the perftools heap-checker. It must only be called
-// when the process is about to exit, and all threads that might
-// access flags are quiescent. Referencing flags after this is called
-// will have unexpected consequences. This is not safe to run when
-// multiple threads might be running: the function is thread-hostile.
+// operation, or for the google perftools heap-checker. It must only
+// be called when the process is about to exit, and all threads that
+// might access flags are quiescent. Referencing flags after this is
+// called will have unexpected consequences. This is not safe to run
+// when multiple threads might be running: the function is
+// thread-hostile.
extern GFLAGS_DLL_DECL void ShutDownCommandLineFlags();
@@ -437,14 +429,12 @@ class GFLAGS_DLL_DECL FlagRegisterer {
void* current_storage, void* defvalue_storage);
};
-extern bool FlagsTypeWarn(const char *name);
-
// 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
// somewhat, and may also be useful for security reasons.
-extern const char kStrippedFlagHelp[];
+extern GFLAGS_DLL_DECL const char kStrippedFlagHelp[];
}
@@ -452,7 +442,8 @@ extern const char kStrippedFlagHelp[];
#if defined(STRIP_FLAG_HELP) && STRIP_FLAG_HELP > 0
// Need this construct to avoid the 'defined but not used' warning.
-#define MAYBE_STRIPPED_HELP(txt) (false ? (txt) : ::google::kStrippedFlagHelp)
+#define MAYBE_STRIPPED_HELP(txt) \
+ (false ? (txt) : ::google::kStrippedFlagHelp)
#else
#define MAYBE_STRIPPED_HELP(txt) txt
#endif
@@ -468,16 +459,16 @@ extern const char kStrippedFlagHelp[];
// FLAGS_no<name>. This serves the second purpose of assuring a
// compile error if someone tries to define a flag named no<name>
// which is illegal (--foo and --nofoo both affect the "foo" flag).
-#define DEFINE_VARIABLE(type, shorttype, name, value, help) \
- namespace fL##shorttype { \
- 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 ::google::FlagRegisterer o_##name( \
- #name, #type, MAYBE_STRIPPED_HELP(help), __FILE__, \
- &FLAGS_##name, &FLAGS_no##name); \
- } \
+#define DEFINE_VARIABLE(type, shorttype, name, value, help) \
+ namespace fL##shorttype { \
+ 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 ::google::FlagRegisterer o_##name( \
+ #name, #type, MAYBE_STRIPPED_HELP(help), __FILE__, \
+ &FLAGS_##name, &FLAGS_no##name); \
+ } \
using fL##shorttype::FLAGS_##name
// For DEFINE_bool, we want to do the extra check that the passed-in
@@ -487,32 +478,39 @@ extern const char kStrippedFlagHelp[];
// We'll use 'sizeof(IsBool(val))' to distinguish. This code requires
// that the compiler have different sizes for bool & double. Since
// this is not guaranteed by the standard, we check it with a
-// compile-time assert (msg[-1] will give a compile-time error).
+// COMPILE_ASSERT.
namespace fLB {
struct CompileAssert {};
typedef CompileAssert expected_sizeof_double_neq_sizeof_bool[
(sizeof(double) != sizeof(bool)) ? 1 : -1];
-template<typename From> GFLAGS_DLL_DECL double IsBoolFlag(const From& from);
+template<typename From> double GFLAGS_DLL_DECL IsBoolFlag(const From& from);
GFLAGS_DLL_DECL bool IsBoolFlag(bool from);
} // namespace fLB
// Here are the actual DEFINE_*-macros. The respective DECLARE_*-macros
// are in a separate include, gflags_declare.h, for reducing
// the physical transitive size for DECLARE use.
-#define DEFINE_bool(name, val, txt) \
- namespace fLB { \
- typedef ::fLB::CompileAssert FLAG_##name##_value_is_not_a_bool[ \
+#define DEFINE_bool(name, val, txt) \
+ namespace fLB { \
+ typedef ::fLB::CompileAssert FLAG_##name##_value_is_not_a_bool[ \
(sizeof(::fLB::IsBoolFlag(val)) != sizeof(double)) ? 1 : -1]; \
- } \
+ } \
DEFINE_VARIABLE(bool, B, name, val, txt)
-#define DEFINE_int32(name,val,txt) DEFINE_VARIABLE(::google::int32, I, name, val, txt)
+#define DEFINE_int32(name, val, txt) \
+ DEFINE_VARIABLE(::google::int32, I, \
+ name, val, txt)
-#define DEFINE_int64(name,val,txt) DEFINE_VARIABLE(::google::int64, I64, name, val, txt)
+#define DEFINE_int64(name, val, txt) \
+ DEFINE_VARIABLE(::google::int64, I64, \
+ name, val, txt)
-#define DEFINE_uint64(name,val,txt) DEFINE_VARIABLE(::google::uint64, U64, name, val, txt)
+#define DEFINE_uint64(name,val, txt) \
+ DEFINE_VARIABLE(::google::uint64, U64, \
+ name, val, txt)
-#define DEFINE_double(name, val, txt) DEFINE_VARIABLE(double, D, name, val, txt)
+#define DEFINE_double(name, val, txt) \
+ DEFINE_VARIABLE(double, D, name, val, txt)
// Strings are trickier, because they're not a POD, so we can't
// construct them at static-initialization time (instead they get
@@ -539,6 +537,9 @@ inline clstring* dont_pass0toDEFINE_string(char *stringspot,
// --string and --nostring. And we need a temporary place to put val
// so we don't have to evaluate it twice. Two great needs that go
// great together!
+// The weird 'using' + 'extern' inside the fLS namespace is to work around
+// an unknown compiler bug/issue with the gcc 4.2.1 on SUSE 10. See
+// http://code.google.com/p/google-gflags/issues/detail?id=20
#define DEFINE_string(name, val, txt) \
namespace fLS { \
using ::fLS::clstring; \
@@ -546,13 +547,15 @@ inline clstring* dont_pass0toDEFINE_string(char *stringspot,
clstring* const FLAGS_no##name = ::fLS:: \
dont_pass0toDEFINE_string(s_##name[0].s, \
val); \
- static ::google::FlagRegisterer o_##name( \
+ static ::google::FlagRegisterer o_##name( \
#name, "string", MAYBE_STRIPPED_HELP(txt), __FILE__, \
s_##name[0].s, new (s_##name[1].s) clstring(*FLAGS_no##name)); \
- GFLAGS_DLL_DEFINE_FLAG clstring& FLAGS_##name = *FLAGS_no##name; \
+ extern GFLAGS_DLL_DEFINE_FLAG clstring& FLAGS_##name; \
+ using fLS::FLAGS_##name; \
+ clstring& FLAGS_##name = *FLAGS_no##name; \
} \
using fLS::FLAGS_##name
#endif // SWIG
-#endif // GOOGLE_GFLAGS_H_
+#endif // BASE_COMMANDLINEFLAGS_H_
diff --git a/src/windows/gflags/gflags_completions.h b/src/windows/gflags/gflags_completions.h
index e97de5b..772cff3 100644
--- a/src/windows/gflags/gflags_completions.h
+++ b/src/windows/gflags/gflags_completions.h
@@ -28,7 +28,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// ---
-// Author: Dave Nicponski
+
//
// Implement helpful bash-style command line flag completions
//
@@ -88,8 +88,8 @@
// file would be (your path to gflags_completions.sh file may differ):
/*
-$ complete -o bashdefault -o default -o nospace -C \
- '/usr/local/bin/gflags_completions.sh --tab_completion_columns $COLUMNS' \
+$ complete -o bashdefault -o default -o nospace -C \
+ '/home/build/eng/bash/bash_completions.sh --tab_completion_columns $COLUMNS' \
time env binary_name another_binary [...]
*/
@@ -109,22 +109,27 @@ $ complete -o bashdefault -o default -o nospace -C \
// produce the expected completion output.
-#ifndef GOOGLE_GFLAGS_COMPLETIONS_H_
-#define GOOGLE_GFLAGS_COMPLETIONS_H_
+#ifndef BASE_COMMANDLINEFLAGS_COMPLETIONS_H_
+#define BASE_COMMANDLINEFLAGS_COMPLETIONS_H_
// Annoying stuff for windows -- makes sure clients can import these functions
+//
+// NOTE: all functions below MUST have an explicit 'extern' before
+// them. Our automated opensourcing tools use this as a signal to do
+// appropriate munging for windows, which needs to add GFLAGS_DLL_DECL.
+//
#ifndef GFLAGS_DLL_DECL
# ifdef _WIN32
# define GFLAGS_DLL_DECL __declspec(dllimport)
# else
-# define GFLAGS_DLL_DECL
+# define GFLAGS_DLL_DECL /**/
# endif
#endif
namespace google {
-GFLAGS_DLL_DECL void HandleCommandLineCompletions(void);
+extern GFLAGS_DLL_DECL void HandleCommandLineCompletions(void);
}
-#endif // GOOGLE_GFLAGS_COMPLETIONS_H_
+#endif // BASE_COMMANDLINEFLAGS_COMPLETIONS_H_
diff --git a/src/windows/gflags/gflags_declare.h b/src/windows/gflags/gflags_declare.h
index 8c84676..fffe66b 100644
--- a/src/windows/gflags/gflags_declare.h
+++ b/src/windows/gflags/gflags_declare.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011, Google Inc.
+// Copyright (c) 1999, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -28,7 +28,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ---
-// Author: Ray Sidney
+//
// Revamped and reorganized by Craig Silverstein
//
// This is the file that should be included by any file which declares
@@ -38,36 +38,17 @@
#define BASE_COMMANDLINEFLAGS_DECLARE_H_
#include <string>
-
-// We care a lot about number of bits things take up. Unfortunately,
-// systems define their bit-specific ints in a lot of different ways.
-// We use our own way, and have a typedef to get there.
-// Note: these commands below may look like "#if 1" or "#if 0", but
-// that's because they were constructed that way at ./configure time.
-// Look at gflags.h.in to see how they're calculated (based on your config).
#if 0
-#include <stdint.h> // the normal place uint16_t is defined
+#include <stdint.h> // the normal place uint16_t is defined
#endif
#if 1
-#include <sys/types.h> // the normal place u_int16_t is defined
+#include <sys/types.h> // the normal place u_int16_t is defined
#endif
#if 0
-#include <inttypes.h> // a third place for uint16_t or u_int16_t
+#include <inttypes.h> // a third place for uint16_t or u_int16_t
#endif
namespace google {
-
-namespace fLS {
-
-// The meaning of "string" might be different between now and when the
-// macros below get invoked (e.g., if someone is experimenting with
-// other string implementations that get defined after this file is
-// included). Save the current meaning now and use it in the macros.
-typedef std::string clstring;
-
-}
-
-
#if 0 // the C99 format
typedef int32_t int32;
typedef uint32_t uint32;
@@ -78,7 +59,7 @@ typedef int32_t int32;
typedef u_int32_t uint32;
typedef int64_t int64;
typedef u_int64_t uint64;
-#elif 1 // the windows (vc7) format
+#elif 1 // the windows (vc7) format
typedef __int32 int32;
typedef unsigned __int32 uint32;
typedef __int64 int64;
@@ -86,6 +67,39 @@ typedef unsigned __int64 uint64;
#else
#error Do not know how to define a 32-bit integer quantity on your system
#endif
+}
+
+
+// Annoying stuff for windows -- makes sure clients can import these functions
+#if defined(_WIN32)
+# ifndef GFLAGS_DLL_DECL
+# define GFLAGS_DLL_DECL __declspec(dllimport)
+# endif
+# ifndef GFLAGS_DLL_DECLARE_FLAG
+# define GFLAGS_DLL_DECLARE_FLAG __declspec(dllimport)
+# endif
+# ifndef GFLAGS_DLL_DEFINE_FLAG
+# define GFLAGS_DLL_DEFINE_FLAG __declspec(dllexport)
+# endif
+#else
+# ifndef GFLAGS_DLL_DECL
+# define GFLAGS_DLL_DECL /**/
+# endif
+# ifndef GFLAGS_DLL_DECLARE_FLAG
+# define GFLAGS_DLL_DECLARE_FLAG /**/
+# endif
+# ifndef GFLAGS_DLL_DEFINE_FLAG
+# define GFLAGS_DLL_DEFINE_FLAG /**/
+# endif
+#endif
+
+namespace fLS {
+
+// The meaning of "string" might be different between now and when the
+// macros below get invoked (e.g., if someone is experimenting with
+// other string implementations that get defined after this file is
+// included). Save the current meaning now and use it in the macros.
+typedef std::string clstring;
}
@@ -94,11 +108,21 @@ typedef unsigned __int64 uint64;
namespace fL##shorttype { extern GFLAGS_DLL_DECLARE_FLAG type FLAGS_##name; } \
using fL##shorttype::FLAGS_##name
-#define DECLARE_bool(name) DECLARE_VARIABLE(bool, B, name)
-#define DECLARE_int32(name) DECLARE_VARIABLE(google::int32, I, name)
-#define DECLARE_int64(name) DECLARE_VARIABLE(google::int64, I64, name)
-#define DECLARE_uint64(name) DECLARE_VARIABLE(google::uint64, U64, name)
-#define DECLARE_double(name) DECLARE_VARIABLE(double, D, name)
+#define DECLARE_bool(name) \
+ DECLARE_VARIABLE(bool, B, name)
+
+#define DECLARE_int32(name) \
+ DECLARE_VARIABLE(::google::int32, I, name)
+
+#define DECLARE_int64(name) \
+ DECLARE_VARIABLE(::google::int64, I64, name)
+
+#define DECLARE_uint64(name) \
+ DECLARE_VARIABLE(::google::uint64, U64, name)
+
+#define DECLARE_double(name) \
+ DECLARE_VARIABLE(double, D, name)
+
#define DECLARE_string(name) \
namespace fLS { \
using ::fLS::clstring; \
diff --git a/src/windows/port.cc b/src/windows/port.cc
index bdc9a34..cbe1307 100644
--- a/src/windows/port.cc
+++ b/src/windows/port.cc
@@ -37,20 +37,49 @@
#include <config.h>
#include <string.h> // for strlen(), memset(), memcmp()
+#include <stdlib.h> // for _putenv, etc.
#include <assert.h>
#include <stdarg.h> // for va_list, va_start, va_end
#include <windows.h>
#include "port.h"
-#ifndef HAVE_SNPRINTF
-int snprintf(char *str, size_t size, const char *format, ...) {
+// These call the windows _vsnprintf, but always NUL-terminate.
+#if !defined(__MINGW32__) && !defined(__MINGW64__) /* mingw already defines */
+int safe_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
if (size == 0) // not even room for a \0?
return -1; // not what C99 says to do, but what windows does
+ str[size-1] = '\0';
+ return _vsnprintf(str, size-1, format, ap);
+}
+
+int snprintf(char *str, size_t size, const char *format, ...) {
+ int r;
va_list ap;
va_start(ap, format);
- const int r = _vsnprintf(str, size-1, format, ap);
+ r = vsnprintf(str, size, format, ap);
va_end(ap);
- str[size-1] = '\0';
return r;
}
-#endif
+#endif /* #if !defined(__MINGW32__) && !defined(__MINGW64__) */
+
+void setenv(const char* name, const char* value, int) {
+ // In windows, it's impossible to set a variable to the empty string.
+ // We handle this by setting it to "0" and the NUL-ing out the \0.
+ // That is, we putenv("FOO=0") and then find out where in memory the
+ // putenv wrote "FOO=0", and change it in-place to "FOO=\0".
+ // c.f. http://svn.apache.org/viewvc/stdcxx/trunk/tests/src/environ.cpp?r1=611451&r2=637508&pathrev=637508
+ static const char* const kFakeZero = "0";
+ if (*value == '\0')
+ value = kFakeZero;
+ // Apparently the semantics of putenv() is that the input
+ // must live forever, so we leak memory here. :-(
+ const int nameval_len = strlen(name) + 1 + strlen(value) + 1;
+ char* nameval = reinterpret_cast<char*>(malloc(nameval_len));
+ snprintf(nameval, nameval_len, "%s=%s", name, value);
+ _putenv(nameval);
+ if (value == kFakeZero) {
+ nameval[nameval_len - 2] = '\0'; // works when putenv() makes no copy
+ if (*getenv(name) != '\0')
+ *getenv(name) = '\0'; // works when putenv() copies nameval
+ }
+}
diff --git a/src/windows/port.h b/src/windows/port.h
index b0b64eb..be8eb1f 100644
--- a/src/windows/port.h
+++ b/src/windows/port.h
@@ -54,15 +54,23 @@
#include <windows.h>
#include <direct.h> /* for mkdir */
#include <stdio.h> /* need this to override stdio's snprintf */
+#include <stdarg.h> /* util.h uses va_copy */
+#include <string.h> /* for _stricmp */
-#define putenv _putenv
-
-// ----------------------------------- STRING ROUTINES
-
-// We can't just use _snprintf as a drop-in-replacement, because it
-// doesn't always NUL-terminate. :-(
+/* We can't just use _vsnprintf and _snprintf as drop-in-replacements,
+ * because they don't always NUL-terminate. :-( We also can't use the
+ * name vsnprintf, since windows defines that (but not snprintf (!)).
+ */
+#if !defined(__MINGW32__) && !defined(__MINGW64__) /* mingw already defines */
extern GFLAGS_DLL_DECL int snprintf(char *str, size_t size,
- const char *format, ...);
+ 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 /* #if !defined(__MINGW32__) && !defined(__MINGW64__) */
+
+extern void GFLAGS_DLL_DECL setenv(const char* name, const char* value, int);
#define strcasecmp _stricmp