summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCraig Silverstein <csilvers+gflags@google.com>2008-03-27 20:11:07 +0000
committerCraig Silverstein <csilvers+gflags@google.com>2008-03-27 20:11:07 +0000
commit83911c12f3a570c86c6d2c957ddd49be3bcb07ac (patch)
treec4a25768c4a24108e226d54011a1e31806e4705d /src
parent585a44a0c0a99af1256941f3718eade36b6941e7 (diff)
downloadgflags-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.cc31
-rw-r--r--src/gflags_reporting.cc10
-rw-r--r--src/gflags_unittest.cc41
-rw-r--r--src/google/gflags.h.in38
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.