diff options
author | Craig Silverstein <csilvers+gflags@google.com> | 2008-03-27 20:11:07 +0000 |
---|---|---|
committer | Craig Silverstein <csilvers+gflags@google.com> | 2008-03-27 20:11:07 +0000 |
commit | 83911c12f3a570c86c6d2c957ddd49be3bcb07ac (patch) | |
tree | c4a25768c4a24108e226d54011a1e31806e4705d /src | |
parent | 585a44a0c0a99af1256941f3718eade36b6941e7 (diff) | |
download | gflags-83911c12f3a570c86c6d2c957ddd49be3bcb07ac.tar.gz gflags-83911c12f3a570c86c6d2c957ddd49be3bcb07ac.tar.bz2 gflags-83911c12f3a570c86c6d2c957ddd49be3bcb07ac.zip |
Wed Mar 26 15:20:18 2008 Google Inc. <opensource@google.com>
* google-gflags: version 0.8
* Export DescribeOneFlag() in the API
* Add support for automatic line wrapping at 80 cols for gflags.py
* Bugfix: do not treat an isolated "-" the same as an isolated "--"
* Update rpm spec to point to Google Code rather than sourceforge (!)
* Improve documentation (including documenting thread-safety)
* Improve #include hygiene
* Improve testing
git-svn-id: https://gflags.googlecode.com/svn/trunk@21 6586e3c6-dcc4-952a-343f-ff74eb82781d
Diffstat (limited to 'src')
-rw-r--r-- | src/gflags.cc | 31 | ||||
-rw-r--r-- | src/gflags_reporting.cc | 10 | ||||
-rw-r--r-- | src/gflags_unittest.cc | 41 | ||||
-rw-r--r-- | src/google/gflags.h.in | 38 |
4 files changed, 94 insertions, 26 deletions
diff --git a/src/gflags.cc b/src/gflags.cc index c14e120..78aad91 100644 --- a/src/gflags.cc +++ b/src/gflags.cc @@ -40,7 +40,6 @@ #include <errno.h> #include <string.h> #include <assert.h> -#include <pthread.h> #include <fnmatch.h> #include <pthread.h> #include <string> @@ -96,8 +95,7 @@ static const char kError[] = "ERROR: "; // The help message indicating that the commandline flag has been // 'stripped'. It will not show up when doing "-help" and its // variants. The flag is stripped if STRIP_FLAG_HELP is set to 1 -// before including base/commandlineflags.h (or in -// base/global_strip_options.h). +// before including google/gflags.h. const char kStrippedFlagHelp[] = "\001\002\003\004 (unknown) \004\003\002\001"; @@ -105,7 +103,7 @@ const char kStrippedFlagHelp[] = "\001\002\003\004 (unknown) \004\003\002\001"; // Enables deferred processing of flags in dynamically loaded libraries. static bool allow_command_line_reparsing = false; -static bool logging_is_probably_set_up = false; // google3-specific +static bool logging_is_probably_set_up = false; // This is used by the unittest to test error-exit code void (*commandlineflags_exitfunc)(int) = &exit; // from stdlib.h @@ -114,7 +112,7 @@ void (*commandlineflags_exitfunc)(int) = &exit; // from stdlib.h // FlagValue // This represent the value a single flag might have. The major // functionality is to convert from a string to an object of a -// given type, and back. +// given type, and back. Thread-compatible. // -------------------------------------------------------------------- class FlagValue { @@ -375,21 +373,19 @@ CommandLineFlag::~CommandLineFlag() { const char* CommandLineFlag::CleanFileName() const { // Compute top-level directory & file that this appears in // search full path backwards. - // Stop going backwards at kGoogle; and skip by the first slash. - // E.g. - // filename_where_defined = "froogle/wrapping/autowrap/clustering/**.cc" - // filename_where_defined = "file/util/fileutil.cc" - static const char kGoogle[] = ""; // can set this to whatever + // 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(kGoogle)-1 == 0) // no prefix to strip + if (sizeof(kRootDir)-1 == 0) // no prefix to strip return filename(); const char* clean_name = filename() + strlen(filename()) - 1; while ( clean_name > filename() ) { if (*clean_name == PATH_SEPARATOR) { - if (strncmp(clean_name, kGoogle, sizeof(kGoogle)-1) == 0) { - // ".../google/base/logging.cc" ==> "base/logging.cc" - clean_name += sizeof(kGoogle)-1; // past "/google/" + if (strncmp(clean_name, kRootDir, sizeof(kRootDir)-1) == 0) { + // ".../myproject/base/logging.cc" ==> "base/logging.cc" + clean_name += sizeof(kRootDir)-1; // past "/myproject/" break; } } @@ -790,7 +786,7 @@ const char* ProgramInvocationName() { // like the GNU libc fn } const char* ProgramInvocationShortName() { // like the GNU libc fn const char* slash = strrchr(argv0, '/'); -#ifdef OS_WINDOWS +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) if (!slash) slash = strrchr(argv0, '\\'); #endif return slash ? slash + 1 : argv0; @@ -939,7 +935,8 @@ uint32 CommandLineFlagParser::ParseNewCommandLineFlags(int* argc, char*** argv, char* arg = (*argv)[i]; // Like getopt(), we permute non-option flags to be at the end. - if (arg[0] != '-') { // must be a program argument + if (arg[0] != '-' || // must be a program argument + (arg[0] == '-' && arg[1] == '\0')) { // "-" is an argument, not a flag memmove((*argv) + i, (*argv) + i+1, (*argc - (i+1)) * sizeof((*argv)[i])); (*argv)[*argc-1] = arg; // we go last first_nonopt--; // we've been pushed onto the stack @@ -950,7 +947,7 @@ uint32 CommandLineFlagParser::ParseNewCommandLineFlags(int* argc, char*** argv, if (arg[0] == '-') arg++; // allow leading '-' if (arg[0] == '-') arg++; // or leading '--' - // - and -- alone mean what they do for GNU: stop options parsing + // -- alone means what it does for GNU: stop options parsing if (*arg == '\0') { first_nonopt = i+1; break; diff --git a/src/gflags_reporting.cc b/src/gflags_reporting.cc index 981dccd..e8099fb 100644 --- a/src/gflags_reporting.cc +++ b/src/gflags_reporting.cc @@ -37,8 +37,8 @@ // reporting flags, but we also have flags like --helpxml, etc. // // There's only one function that's meant to be called externally: -// HandleCommandLineHelpFlags(). (Well, actually, -// ShowUsageWithFlags() and ShowUsageWithFlagsRestrict() can be called +// 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. // @@ -110,7 +110,7 @@ static void AddString(const string& s, // Create a descriptive string for a flag. // Goes to some trouble to make pretty line breaks. -static string DescribeOneFlag(const CommandLineFlagInfo& flag) { +string DescribeOneFlag(const CommandLineFlagInfo& flag) { string main_part = (string(" -") + flag.name + " (" + flag.description + ')'); const char* c_string = main_part.c_str(); @@ -242,8 +242,8 @@ 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' to -// base/global_strip_options.h), then this flag will not be displayed by +// has been stripped (e.g. by adding '#define STRIP_FLAG_HELP 1' before +// including google/gflags.h), then this flag will not be displayed by // '--help' and its variants. static void ShowUsageWithFlagsMatching(const char *argv0, const vector<string> &substrings) { diff --git a/src/gflags_unittest.cc b/src/gflags_unittest.cc index 8a8db97..03219c6 100644 --- a/src/gflags_unittest.cc +++ b/src/gflags_unittest.cc @@ -35,6 +35,7 @@ #include "config.h" #include <stdio.h> +#include <stdlib.h> // for &exit #include <string.h> #include <unistd.h> // for unlink() #include <sys/stat.h> // for mkdir() @@ -46,8 +47,7 @@ using std::vector; using std::string; -// Returns the number of elements in an array. We don't use the safer -// version in base/basictypes.h as commandlineflags is open-sourced. +// Returns the number of elements in an array. #define GET_ARRAY_SIZE(arr) (sizeof(arr)/sizeof(*(arr))) DECLARE_string(tryfromenv); // in commandlineflags.cc @@ -1109,6 +1109,43 @@ TEST(ParseCommandLineFlagsUsesLastDefinitionTest, EXPECT_EQ(3, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv)); } +TEST(ParseCommandLineFlagsAndDashArgs, TwoDashArgFirst) { + const char* argv[] = { + "my_test", + "--", + "--test_flag=0", + NULL, + }; + + EXPECT_EQ(-1, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv)); + EXPECT_EQ(-1, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv)); +} + +TEST(ParseCommandLineFlagsAndDashArgs, TwoDashArgMiddle) { + const char* argv[] = { + "my_test", + "--test_flag=7", + "--", + "--test_flag=0", + NULL, + }; + + EXPECT_EQ(7, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv)); + EXPECT_EQ(7, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv)); +} + +TEST(ParseCommandLineFlagsAndDashArgs, OneDashArg) { + const char* argv[] = { + "my_test", + "-", + "--test_flag=0", + NULL, + }; + + EXPECT_EQ(0, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv)); + EXPECT_EQ(0, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv)); +} + static int Main(int argc, char **argv) { // We need to call SetArgv before InitGoogle, so our "test" argv will // win out over this executable's real argv. That makes running this diff --git a/src/google/gflags.h.in b/src/google/gflags.h.in index 285a53f..8d3921d 100644 --- a/src/google/gflags.h.in +++ b/src/google/gflags.h.in @@ -50,6 +50,24 @@ // // For more details, see // doc/gflags.html +// +// --- A note about thread-safety: +// +// We describe many functions in this routine as being thread-hostile, +// thread-compatible, or thread-safe. Here are the meanings we use: +// +// thread-safe: it is safe for multiple threads to call this routine +// (or, when referring to a class, methods of this class) +// concurrently. +// thread-hostile: it is not safe for multiple threads to call this +// routine (or methods of this class) concurrently. In gflags, +// most thread-hostile routines are intended to be called early in, +// or even before, main() -- that is, before threads are spawned. +// thread-compatible: it is safe for multiple threads to read from +// this variable (when applied to variables), or to call const +// methods of this class (when applied to classes), as long as no +// other thread is writing to the variable or calling non-const +// methods of this class. #ifndef BASE_COMMANDLINEFLAGS_H__ #define BASE_COMMANDLINEFLAGS_H__ @@ -120,13 +138,22 @@ extern void GetAllFlags(std::vector<CommandLineFlagInfo>* OUTPUT); extern void ShowUsageWithFlags(const char *argv0); // what --help does extern void ShowUsageWithFlagsRestrict(const char *argv0, const char *restrict); +// Create a descriptive string for a flag. +// Goes to some trouble to make pretty line breaks. +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 char* ProgramInvocationShortName(); // basename(argv0) +// ProgramUsage() is thread-safe as long as SetUsageMessage() is only +// called before any threads start. extern const char* ProgramUsage(); // string set by SetUsageMessage() @@ -135,6 +162,8 @@ extern const char* ProgramUsage(); // string set by SetUsageMessage() // or whatever, and set them by calling "FLAGS_foo = bar" (or, more // commonly, via the DEFINE_foo macro). But if you need a bit more // control, we have programmatic ways to get/set the flags as well. +// These programmatic ways to access flags are thread-safe, but direct +// access is only thread-compatible. // Return true iff the flagname was found. // OUTPUT is set to the flag's value, or unchanged if we return false. @@ -196,6 +225,8 @@ extern std::string SetCommandLineOptionWithMode(const char* name, const char* va // 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 { public: @@ -251,6 +282,7 @@ extern const char *StringFromEnv(const char *varname, const char *defval); // usage += argv[0] + " <uselessarg1> <uselessarg2>"; // SetUsageMessage(usage); // Do not include commandline flags in the usage: we do that for you! +// Thread-hostile; meant to be called before any threads are spawned. extern void SetUsageMessage(const std::string& usage); // Looks for flags in argv and parses them. Rearranges argv to put @@ -280,8 +312,10 @@ extern uint32 ParseCommandLineNonHelpFlags(int *argc, char*** argv, // it's too late to change that now. :-( extern void HandleCommandLineHelpFlags(); // in commandlineflags_reporting.cc -// Allow command line reparsing. Disables the error normaly generated -// when an unknown flag is found, since it may be found in a later parse. +// Allow command line reparsing. Disables the error normally +// generated when an unknown flag is found, since it may be found in a +// later parse. Thread-hostile; meant to be called before any threads +// are spawned. extern void AllowCommandLineReparsing(); // Reparse the flags that have not yet been recognized. |