├── src ├── WORKSPACE ├── BUILD ├── windows_port.cc ├── include │ └── gflags │ │ ├── config.h │ │ ├── gflags_gflags.h │ │ ├── gflags_declare.h │ │ ├── gflags_completions.h │ │ └── gflags.h ├── windows_port.h ├── util.h ├── mutex.h ├── gflags_reporting.cc ├── gflags_completions.cc └── gflags.cc ├── README.md ├── archive.zip ├── LICENSE └── update.sh /src/WORKSPACE: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bazel-gflags 2 | gflags for Bazel. 3 | -------------------------------------------------------------------------------- /archive.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imos/bazel-gflags/master/archive.zip -------------------------------------------------------------------------------- /src/BUILD: -------------------------------------------------------------------------------- 1 | licenses(["notice"]) 2 | 3 | cc_library( 4 | name = "gflags", 5 | srcs = glob(["*.cc", "*.h"], exclude = ["windows_*"]), 6 | hdrs = glob(["gflags/*.h"]), 7 | visibility = ["//visibility:public"], 8 | copts = ["-I.", "-Iinclude/gflags"], 9 | includes = ["include"], 10 | linkopts = ["-pthread"], 11 | ) 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Kentaro IMAJO 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e -u 4 | 5 | cd "$(dirname "${0}")" 6 | 7 | : "${UPDATE_REPOSITORY:=1}" 8 | 9 | if (( UPDATE_REPOSITORY )); then 10 | rm -rf repository 11 | fi 12 | 13 | if [ ! -d repository ]; then 14 | git clone 'https://github.com/gflags/gflags' repository 15 | fi 16 | 17 | pushd repository 18 | cmake . 19 | popd 20 | 21 | rm -rf src 22 | mkdir src 23 | cp repository/src/*.h repository/src/*.cc src/ 24 | mkdir -p src/include 25 | cp -R repository/include/gflags src/include/ 26 | 27 | cat << EOM > src/BUILD 28 | licenses(["notice"]) 29 | 30 | cc_library( 31 | name = "gflags", 32 | srcs = glob(["*.cc", "*.h"], exclude = ["windows_*"]), 33 | hdrs = glob(["gflags/*.h"]), 34 | visibility = ["//visibility:public"], 35 | copts = ["-I.", "-Iinclude/gflags"], 36 | includes = ["include"], 37 | linkopts = ["-pthread"], 38 | ) 39 | EOM 40 | 41 | touch src/WORKSPACE 42 | zip -9 archive.zip src/* 43 | 44 | rm -rf test 45 | mkdir test 46 | 47 | cp -R repository/test/* test/ 48 | 49 | cat << EOM > test/WORKSPACE 50 | http_archive( 51 | name = "gflags-archive", 52 | sha256 = "$(openssl dgst -sha256 archive.zip | cut -d' ' -f2)", 53 | url = "http://127.0.0.1:8080/archive.zip", 54 | ) 55 | 56 | bind( 57 | name = "gflags", 58 | actual = "@gflags-archive//:gflags", 59 | ) 60 | EOM 61 | 62 | cat << EOM > test/BUILD 63 | cc_test( 64 | name = "gflags_unittest", 65 | srcs = ["gflags_unittest.cc"], 66 | deps = ["//external:gflags"], 67 | ) 68 | EOM 69 | -------------------------------------------------------------------------------- /src/windows_port.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2009, Google Inc. 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above 11 | * copyright notice, this list of conditions and the following disclaimer 12 | * in the documentation and/or other materials provided with the 13 | * distribution. 14 | * * Neither the name of Google Inc. nor the names of its 15 | * contributors may be used to endorse or promote products derived from 16 | * this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | * --- 31 | * Author: Craig Silverstein 32 | */ 33 | 34 | #ifndef _WIN32 35 | # error You should only be including windows/port.cc in a windows environment! 36 | #endif 37 | 38 | #include // for strlen(), memset(), memcmp() 39 | #include 40 | #include // for va_list, va_start, va_end 41 | #include 42 | 43 | #include "windows_port.h" 44 | 45 | // These call the windows _vsnprintf, but always NUL-terminate. 46 | #if !defined(__MINGW32__) && !defined(__MINGW64__) /* mingw already defines */ 47 | 48 | #ifdef _MSC_VER 49 | # pragma warning(push) 50 | # pragma warning(disable: 4996) // ignore _vsnprintf security warning 51 | #endif 52 | int safe_vsnprintf(char *str, size_t size, const char *format, va_list ap) { 53 | if (size == 0) // not even room for a \0? 54 | return -1; // not what C99 says to do, but what windows does 55 | str[size-1] = '\0'; 56 | return _vsnprintf(str, size-1, format, ap); 57 | } 58 | #ifdef _MSC_VER 59 | # pragma warning(pop) 60 | #endif 61 | 62 | int snprintf(char *str, size_t size, const char *format, ...) { 63 | int r; 64 | va_list ap; 65 | va_start(ap, format); 66 | r = vsnprintf(str, size, format, ap); 67 | va_end(ap); 68 | return r; 69 | } 70 | 71 | #endif /* #if !defined(__MINGW32__) && !defined(__MINGW64__) */ 72 | -------------------------------------------------------------------------------- /src/include/gflags/config.h: -------------------------------------------------------------------------------- 1 | /* Generated from config.h.in during build configuration using CMake. */ 2 | 3 | // Note: This header file is only used internally. It is not part of public interface! 4 | 5 | // --------------------------------------------------------------------------- 6 | // System checks 7 | 8 | // Define if you build this library for a MS Windows OS. 9 | /* #undef OS_WINDOWS */ 10 | 11 | // Define if you have the header file. 12 | #define HAVE_STDINT_H 13 | 14 | // Define if you have the header file. 15 | #define HAVE_SYS_TYPES_H 16 | 17 | // Define if you have the header file. 18 | #define HAVE_INTTYPES_H 19 | 20 | // Define if you have the header file. 21 | #define HAVE_SYS_STAT_H 22 | 23 | // Define if you have the header file. 24 | #define HAVE_UNISTD_H 25 | 26 | // Define if you have the header file. 27 | #define HAVE_FNMATCH_H 28 | 29 | // Define if you have the header file (Windows 2000/XP). 30 | /* #undef HAVE_SHLWAPI_H */ 31 | 32 | // Define if you have the strtoll function. 33 | #define HAVE_STRTOLL 34 | 35 | // Define if you have the strtoq function. 36 | /* #undef HAVE_STRTOQ */ 37 | 38 | // Define if you have the header file. 39 | #define HAVE_PTHREAD 40 | 41 | // Define if your pthread library defines the type pthread_rwlock_t 42 | #define HAVE_RWLOCK 43 | 44 | // gcc requires this to get PRId64, etc. 45 | #if defined(HAVE_INTTYPES_H) && !defined(__STDC_FORMAT_MACROS) 46 | # define __STDC_FORMAT_MACROS 1 47 | #endif 48 | 49 | // --------------------------------------------------------------------------- 50 | // Package information 51 | 52 | // Name of package. 53 | #define PACKAGE gflags 54 | 55 | // Define to the full name of this package. 56 | #define PACKAGE_NAME gflags 57 | 58 | // Define to the full name and version of this package. 59 | #define PACKAGE_STRING gflags 2.2.0 60 | 61 | // Define to the one symbol short name of this package. 62 | #define PACKAGE_TARNAME gflags-2.2.0 63 | 64 | // Define to the version of this package. 65 | #define PACKAGE_VERSION 2.2.0 66 | 67 | // Version number of package. 68 | #define VERSION PACKAGE_VERSION 69 | 70 | // Define to the address where bug reports for this package should be sent. 71 | #define PACKAGE_BUGREPORT https://github.com/schuhschuh/gflags/issues 72 | 73 | // --------------------------------------------------------------------------- 74 | // Path separator 75 | #ifndef PATH_SEPARATOR 76 | # ifdef OS_WINDOWS 77 | # define PATH_SEPARATOR '\\' 78 | # else 79 | # define PATH_SEPARATOR '/' 80 | # endif 81 | #endif 82 | 83 | // --------------------------------------------------------------------------- 84 | // Windows 85 | 86 | // Whether gflags library is a DLL. 87 | #ifndef GFLAGS_IS_A_DLL 88 | # define GFLAGS_IS_A_DLL 0 89 | #endif 90 | 91 | // Always export symbols when compiling a shared library as this file is only 92 | // included by internal modules when building the gflags library itself. 93 | // The gflags_declare.h header file will set it to import these symbols otherwise. 94 | #ifndef GFLAGS_DLL_DECL 95 | # if GFLAGS_IS_A_DLL && defined(_MSC_VER) 96 | # define GFLAGS_DLL_DECL __declspec(dllexport) 97 | # else 98 | # define GFLAGS_DLL_DECL 99 | # endif 100 | #endif 101 | // Flags defined by the gflags library itself must be exported 102 | #ifndef GFLAGS_DLL_DEFINE_FLAG 103 | # define GFLAGS_DLL_DEFINE_FLAG GFLAGS_DLL_DECL 104 | #endif 105 | 106 | #ifdef OS_WINDOWS 107 | // The unittests import the symbols of the shared gflags library 108 | # if GFLAGS_IS_A_DLL && defined(_MSC_VER) 109 | # define GFLAGS_DLL_DECL_FOR_UNITTESTS __declspec(dllimport) 110 | # endif 111 | # include "windows_port.h" 112 | #endif 113 | -------------------------------------------------------------------------------- /src/include/gflags/gflags_gflags.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014, Andreas Schuh 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // ----------------------------------------------------------------------------- 31 | // Imports the gflags library symbols into an alternative/deprecated namespace. 32 | 33 | #ifndef GFLAGS_GFLAGS_H_ 34 | # error The internal header gflags_gflags.h may only be included by gflags.h 35 | #endif 36 | 37 | #ifndef GFLAGS_NS_GFLAGS_H_ 38 | #define GFLAGS_NS_GFLAGS_H_ 39 | 40 | 41 | namespace gflags { 42 | 43 | 44 | using GFLAGS_NAMESPACE::int32; 45 | using GFLAGS_NAMESPACE::uint32; 46 | using GFLAGS_NAMESPACE::int64; 47 | using GFLAGS_NAMESPACE::uint64; 48 | 49 | using GFLAGS_NAMESPACE::RegisterFlagValidator; 50 | using GFLAGS_NAMESPACE::CommandLineFlagInfo; 51 | using GFLAGS_NAMESPACE::GetAllFlags; 52 | using GFLAGS_NAMESPACE::ShowUsageWithFlags; 53 | using GFLAGS_NAMESPACE::ShowUsageWithFlagsRestrict; 54 | using GFLAGS_NAMESPACE::DescribeOneFlag; 55 | using GFLAGS_NAMESPACE::SetArgv; 56 | using GFLAGS_NAMESPACE::GetArgvs; 57 | using GFLAGS_NAMESPACE::GetArgv; 58 | using GFLAGS_NAMESPACE::GetArgv0; 59 | using GFLAGS_NAMESPACE::GetArgvSum; 60 | using GFLAGS_NAMESPACE::ProgramInvocationName; 61 | using GFLAGS_NAMESPACE::ProgramInvocationShortName; 62 | using GFLAGS_NAMESPACE::ProgramUsage; 63 | using GFLAGS_NAMESPACE::VersionString; 64 | using GFLAGS_NAMESPACE::GetCommandLineOption; 65 | using GFLAGS_NAMESPACE::GetCommandLineFlagInfo; 66 | using GFLAGS_NAMESPACE::GetCommandLineFlagInfoOrDie; 67 | using GFLAGS_NAMESPACE::FlagSettingMode; 68 | using GFLAGS_NAMESPACE::SET_FLAGS_VALUE; 69 | using GFLAGS_NAMESPACE::SET_FLAG_IF_DEFAULT; 70 | using GFLAGS_NAMESPACE::SET_FLAGS_DEFAULT; 71 | using GFLAGS_NAMESPACE::SetCommandLineOption; 72 | using GFLAGS_NAMESPACE::SetCommandLineOptionWithMode; 73 | using GFLAGS_NAMESPACE::FlagSaver; 74 | using GFLAGS_NAMESPACE::CommandlineFlagsIntoString; 75 | using GFLAGS_NAMESPACE::ReadFlagsFromString; 76 | using GFLAGS_NAMESPACE::AppendFlagsIntoFile; 77 | using GFLAGS_NAMESPACE::ReadFromFlagsFile; 78 | using GFLAGS_NAMESPACE::BoolFromEnv; 79 | using GFLAGS_NAMESPACE::Int32FromEnv; 80 | using GFLAGS_NAMESPACE::Int64FromEnv; 81 | using GFLAGS_NAMESPACE::Uint64FromEnv; 82 | using GFLAGS_NAMESPACE::DoubleFromEnv; 83 | using GFLAGS_NAMESPACE::StringFromEnv; 84 | using GFLAGS_NAMESPACE::SetUsageMessage; 85 | using GFLAGS_NAMESPACE::SetVersionString; 86 | using GFLAGS_NAMESPACE::ParseCommandLineNonHelpFlags; 87 | using GFLAGS_NAMESPACE::HandleCommandLineHelpFlags; 88 | using GFLAGS_NAMESPACE::AllowCommandLineReparsing; 89 | using GFLAGS_NAMESPACE::ReparseCommandLineNonHelpFlags; 90 | using GFLAGS_NAMESPACE::ShutDownCommandLineFlags; 91 | using GFLAGS_NAMESPACE::FlagRegisterer; 92 | 93 | #ifndef SWIG 94 | using GFLAGS_NAMESPACE::ParseCommandLineFlags; 95 | #endif 96 | 97 | 98 | } // namespace gflags 99 | 100 | 101 | #endif // GFLAGS_NS_GFLAGS_H_ 102 | -------------------------------------------------------------------------------- /src/include/gflags/gflags_declare.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 1999, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // --- 31 | // 32 | // Revamped and reorganized by Craig Silverstein 33 | // 34 | // This is the file that should be included by any file which declares 35 | // command line flag. 36 | 37 | #ifndef GFLAGS_DECLARE_H_ 38 | #define GFLAGS_DECLARE_H_ 39 | 40 | 41 | // --------------------------------------------------------------------------- 42 | // Namespace of gflags library symbols. 43 | #define GFLAGS_NAMESPACE google 44 | 45 | // --------------------------------------------------------------------------- 46 | // Windows DLL import/export. 47 | 48 | // We always want to import the symbols of the gflags library 49 | #ifndef GFLAGS_DLL_DECL 50 | # if 0 && defined(_MSC_VER) 51 | # define GFLAGS_DLL_DECL __declspec(dllimport) 52 | # else 53 | # define GFLAGS_DLL_DECL 54 | # endif 55 | #endif 56 | 57 | // We always want to import variables declared in user code 58 | #ifndef GFLAGS_DLL_DECLARE_FLAG 59 | # ifdef _MSC_VER 60 | # define GFLAGS_DLL_DECLARE_FLAG __declspec(dllimport) 61 | # else 62 | # define GFLAGS_DLL_DECLARE_FLAG 63 | # endif 64 | #endif 65 | 66 | // --------------------------------------------------------------------------- 67 | // Flag types 68 | #include 69 | #if 1 70 | # include // the normal place uint32_t is defined 71 | #elif 1 72 | # include // the normal place u_int32_t is defined 73 | #elif 1 74 | # include // a third place for uint32_t or u_int32_t 75 | #endif 76 | 77 | namespace GFLAGS_NAMESPACE { 78 | 79 | #if 1 // C99 80 | typedef int32_t int32; 81 | typedef uint32_t uint32; 82 | typedef int64_t int64; 83 | typedef uint64_t uint64; 84 | #elif 0 // BSD 85 | typedef int32_t int32; 86 | typedef u_int32_t uint32; 87 | typedef int64_t int64; 88 | typedef u_int64_t uint64; 89 | #elif 0 // Windows 90 | typedef __int32 int32; 91 | typedef unsigned __int32 uint32; 92 | typedef __int64 int64; 93 | typedef unsigned __int64 uint64; 94 | #else 95 | # error Do not know how to define a 32-bit integer quantity on your system 96 | #endif 97 | 98 | } // namespace GFLAGS_NAMESPACE 99 | 100 | 101 | namespace fLS { 102 | 103 | // The meaning of "string" might be different between now and when the 104 | // macros below get invoked (e.g., if someone is experimenting with 105 | // other string implementations that get defined after this file is 106 | // included). Save the current meaning now and use it in the macros. 107 | typedef std::string clstring; 108 | 109 | } // namespace fLS 110 | 111 | 112 | #define DECLARE_VARIABLE(type, shorttype, name) \ 113 | /* We always want to import declared variables, dll or no */ \ 114 | namespace fL##shorttype { extern GFLAGS_DLL_DECLARE_FLAG type FLAGS_##name; } \ 115 | using fL##shorttype::FLAGS_##name 116 | 117 | #define DECLARE_bool(name) \ 118 | DECLARE_VARIABLE(bool, B, name) 119 | 120 | #define DECLARE_int32(name) \ 121 | DECLARE_VARIABLE(::GFLAGS_NAMESPACE::int32, I, name) 122 | 123 | #define DECLARE_int64(name) \ 124 | DECLARE_VARIABLE(::GFLAGS_NAMESPACE::int64, I64, name) 125 | 126 | #define DECLARE_uint64(name) \ 127 | DECLARE_VARIABLE(::GFLAGS_NAMESPACE::uint64, U64, name) 128 | 129 | #define DECLARE_double(name) \ 130 | DECLARE_VARIABLE(double, D, name) 131 | 132 | #define DECLARE_string(name) \ 133 | /* We always want to import declared variables, dll or no */ \ 134 | namespace fLS { \ 135 | using ::fLS::clstring; \ 136 | extern GFLAGS_DLL_DECLARE_FLAG ::fLS::clstring& FLAGS_##name; \ 137 | } \ 138 | using fLS::FLAGS_##name 139 | 140 | 141 | #endif // GFLAGS_DECLARE_H_ 142 | -------------------------------------------------------------------------------- /src/windows_port.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2009, Google Inc. 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above 11 | * copyright notice, this list of conditions and the following disclaimer 12 | * in the documentation and/or other materials provided with the 13 | * distribution. 14 | * * Neither the name of Google Inc. nor the names of its 15 | * contributors may be used to endorse or promote products derived from 16 | * this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | * --- 31 | * Author: Craig Silverstein 32 | * 33 | * These are some portability typedefs and defines to make it a bit 34 | * easier to compile this code under VC++. 35 | * 36 | * Several of these are taken from glib: 37 | * http://developer.gnome.org/doc/API/glib/glib-windows-compatability-functions.html 38 | */ 39 | 40 | #ifndef GFLAGS_WINDOWS_PORT_H_ 41 | #define GFLAGS_WINDOWS_PORT_H_ 42 | 43 | #include "config.h" 44 | 45 | // This must be defined before the windows.h is included. 46 | // It's needed for mutex.h, to give access to the TryLock method. 47 | # if !defined(_WIN32_WINNT) && !(defined( __MINGW32__) || defined(__MINGW64__)) 48 | # define _WIN32_WINNT 0x0400 49 | # endif 50 | // We always want minimal includes 51 | #ifndef WIN32_LEAN_AND_MEAN 52 | # define WIN32_LEAN_AND_MEAN 53 | #endif 54 | #include 55 | #include /* for mkdir */ 56 | #include /* for _putenv, getenv */ 57 | #include /* need this to override stdio's snprintf, also defines _unlink used by unit tests */ 58 | #include /* util.h uses va_copy */ 59 | #include /* for _stricmp and _strdup */ 60 | 61 | /* We can't just use _vsnprintf and _snprintf as drop-in-replacements, 62 | * because they don't always NUL-terminate. :-( We also can't use the 63 | * name vsnprintf, since windows defines that (but not snprintf (!)). 64 | */ 65 | #if !defined(__MINGW32__) && !defined(__MINGW64__) /* mingw already defines */ 66 | extern GFLAGS_DLL_DECL int snprintf(char *str, size_t size, 67 | const char *format, ...); 68 | extern int GFLAGS_DLL_DECL safe_vsnprintf(char *str, size_t size, 69 | const char *format, va_list ap); 70 | #define vsnprintf(str, size, format, ap) safe_vsnprintf(str, size, format, ap) 71 | #define va_copy(dst, src) (dst) = (src) 72 | #endif /* #if !defined(__MINGW32__) && !defined(__MINGW64__) */ 73 | 74 | #ifdef _MSC_VER 75 | # pragma warning(push) 76 | # pragma warning(disable: 4996) // ignore getenv security warning 77 | #endif 78 | inline void setenv(const char* name, const char* value, int) { 79 | // In windows, it's impossible to set a variable to the empty string. 80 | // We handle this by setting it to "0" and the NUL-ing out the \0. 81 | // That is, we putenv("FOO=0") and then find out where in memory the 82 | // putenv wrote "FOO=0", and change it in-place to "FOO=\0". 83 | // c.f. http://svn.apache.org/viewvc/stdcxx/trunk/tests/src/environ.cpp?r1=611451&r2=637508&pathrev=637508 84 | static const char* const kFakeZero = "0"; 85 | if (*value == '\0') 86 | value = kFakeZero; 87 | // Apparently the semantics of putenv() is that the input 88 | // must live forever, so we leak memory here. :-( 89 | const size_t nameval_len = strlen(name) + 1 + strlen(value) + 1; 90 | char* nameval = reinterpret_cast(malloc(nameval_len)); 91 | snprintf(nameval, nameval_len, "%s=%s", name, value); 92 | _putenv(nameval); 93 | if (value == kFakeZero) { 94 | nameval[nameval_len - 2] = '\0'; // works when putenv() makes no copy 95 | if (*getenv(name) != '\0') 96 | *getenv(name) = '\0'; // works when putenv() copies nameval 97 | } 98 | } 99 | #ifdef _MSC_VER 100 | # pragma warning(pop) 101 | #endif 102 | 103 | #define strcasecmp _stricmp 104 | 105 | #if defined(_MSC_VER) && _MSC_VER >= 1400 106 | #define strdup _strdup 107 | #define unlink _unlink 108 | #endif 109 | 110 | #define PRId32 "d" 111 | #define PRIu32 "u" 112 | #define PRId64 "I64d" 113 | #define PRIu64 "I64u" 114 | 115 | #if !defined(__MINGW32__) && !defined(__MINGW64__) 116 | #define strtoq _strtoi64 117 | #define strtouq _strtoui64 118 | #define strtoll _strtoi64 119 | #define strtoull _strtoui64 120 | #define atoll _atoi64 121 | #endif 122 | 123 | #ifndef PATH_MAX 124 | #define PATH_MAX 1024 125 | #endif 126 | 127 | #endif /* GFLAGS_WINDOWS_PORT_H_ */ 128 | -------------------------------------------------------------------------------- /src/include/gflags/gflags_completions.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2008, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // --- 31 | 32 | // 33 | // Implement helpful bash-style command line flag completions 34 | // 35 | // ** Functional API: 36 | // HandleCommandLineCompletions() should be called early during 37 | // program startup, but after command line flag code has been 38 | // initialized, such as the beginning of HandleCommandLineHelpFlags(). 39 | // It checks the value of the flag --tab_completion_word. If this 40 | // flag is empty, nothing happens here. If it contains a string, 41 | // however, then HandleCommandLineCompletions() will hijack the 42 | // process, attempting to identify the intention behind this 43 | // completion. Regardless of the outcome of this deduction, the 44 | // process will be terminated, similar to --helpshort flag 45 | // handling. 46 | // 47 | // ** Overview of Bash completions: 48 | // Bash can be told to programatically determine completions for the 49 | // current 'cursor word'. It does this by (in this case) invoking a 50 | // command with some additional arguments identifying the command 51 | // being executed, the word being completed, and the previous word 52 | // (if any). Bash then expects a sequence of output lines to be 53 | // printed to stdout. If these lines all contain a common prefix 54 | // longer than the cursor word, bash will replace the cursor word 55 | // with that common prefix, and display nothing. If there isn't such 56 | // a common prefix, bash will display the lines in pages using 'more'. 57 | // 58 | // ** Strategy taken for command line completions: 59 | // If we can deduce either the exact flag intended, or a common flag 60 | // prefix, we'll output exactly that. Otherwise, if information 61 | // must be displayed to the user, we'll take the opportunity to add 62 | // some helpful information beyond just the flag name (specifically, 63 | // we'll include the default flag value and as much of the flag's 64 | // description as can fit on a single terminal line width, as specified 65 | // by the flag --tab_completion_columns). Furthermore, we'll try to 66 | // make bash order the output such that the most useful or relevent 67 | // flags are the most likely to be shown at the top. 68 | // 69 | // ** Additional features: 70 | // To assist in finding that one really useful flag, substring matching 71 | // was implemented. Before pressing a to get completion for the 72 | // current word, you can append one or more '?' to the flag to do 73 | // substring matching. Here's the semantics: 74 | // --foo Show me all flags with names prefixed by 'foo' 75 | // --foo? Show me all flags with 'foo' somewhere in the name 76 | // --foo?? Same as prior case, but also search in module 77 | // definition path for 'foo' 78 | // --foo??? Same as prior case, but also search in flag 79 | // descriptions for 'foo' 80 | // Finally, we'll trim the output to a relatively small number of 81 | // flags to keep bash quiet about the verbosity of output. If one 82 | // really wanted to see all possible matches, appending a '+' to the 83 | // search word will force the exhaustive list of matches to be printed. 84 | // 85 | // ** How to have bash accept completions from a binary: 86 | // Bash requires that it be informed about each command that programmatic 87 | // completion should be enabled for. Example addition to a .bashrc 88 | // file would be (your path to gflags_completions.sh file may differ): 89 | 90 | /* 91 | $ complete -o bashdefault -o default -o nospace -C \ 92 | '/home/build/eng/bash/bash_completions.sh --tab_completion_columns $COLUMNS' \ 93 | time env binary_name another_binary [...] 94 | */ 95 | 96 | // This would allow the following to work: 97 | // $ /path/to/binary_name --vmodule 98 | // Or: 99 | // $ ./bin/path/another_binary --gfs_u 100 | // (etc) 101 | // 102 | // Sadly, it appears that bash gives no easy way to force this behavior for 103 | // all commands. That's where the "time" in the above example comes in. 104 | // If you haven't specifically added a command to the list of completion 105 | // supported commands, you can still get completions by prefixing the 106 | // entire command with "env". 107 | // $ env /some/brand/new/binary --vmod 108 | // Assuming that "binary" is a newly compiled binary, this should still 109 | // produce the expected completion output. 110 | 111 | 112 | #ifndef GFLAGS_COMPLETIONS_H_ 113 | #define GFLAGS_COMPLETIONS_H_ 114 | 115 | namespace google { 116 | 117 | extern void HandleCommandLineCompletions(void); 118 | 119 | } 120 | 121 | #endif // GFLAGS_COMPLETIONS_H_ 122 | -------------------------------------------------------------------------------- /src/util.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // --- 30 | // 31 | // Some generically useful utility routines that in google-land would 32 | // be their own projects. We make a shortened version here. 33 | 34 | #ifndef GFLAGS_UTIL_H_ 35 | #define GFLAGS_UTIL_H_ 36 | 37 | #include "config.h" 38 | 39 | #include 40 | #include 41 | #ifdef HAVE_INTTYPES_H 42 | # include 43 | #endif 44 | #include // for va_* 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #ifdef HAVE_SYS_STAT_H 51 | # include // for mkdir 52 | #endif 53 | 54 | 55 | namespace GFLAGS_NAMESPACE { 56 | 57 | 58 | // This is used for unittests for death-testing. It is defined in gflags.cc. 59 | extern GFLAGS_DLL_DECL void (*gflags_exitfunc)(int); 60 | 61 | // Work properly if either strtoll or strtoq is on this system. 62 | #if defined(strtoll) || defined(HAVE_STRTOLL) 63 | # define strto64 strtoll 64 | # define strtou64 strtoull 65 | #elif defined(HAVE_STRTOQ) 66 | # define strto64 strtoq 67 | # define strtou64 strtouq 68 | // Neither strtoll nor strtoq are defined. I hope strtol works! 69 | #else 70 | # define strto64 strtol 71 | # define strtou64 strtoul 72 | #endif 73 | 74 | // If we have inttypes.h, it will have defined PRId32/etc for us. 75 | // If not, take our best guess. 76 | #ifndef PRId32 77 | # define PRId32 "d" 78 | #endif 79 | #ifndef PRId64 80 | # define PRId64 "lld" 81 | #endif 82 | #ifndef PRIu64 83 | # define PRIu64 "llu" 84 | #endif 85 | 86 | typedef signed char int8; 87 | typedef unsigned char uint8; 88 | 89 | // -- utility macros --------------------------------------------------------- 90 | 91 | template struct CompileAssert {}; 92 | #define COMPILE_ASSERT(expr, msg) \ 93 | typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1] 94 | 95 | // Returns the number of elements in an array. 96 | #define arraysize(arr) (sizeof(arr)/sizeof(*(arr))) 97 | 98 | 99 | // -- logging and testing --------------------------------------------------- 100 | 101 | // For now, we ignore the level for logging, and don't show *VLOG's at 102 | // all, except by hand-editing the lines below 103 | #define LOG(level) std::cerr 104 | #define VLOG(level) if (true) {} else std::cerr 105 | #define DVLOG(level) if (true) {} else std::cerr 106 | 107 | // CHECK dies with a fatal error if condition is not true. It is *not* 108 | // controlled by NDEBUG, so the check will be executed regardless of 109 | // compilation mode. Therefore, it is safe to do things like: 110 | // CHECK(fp->Write(x) == 4) 111 | // We allow stream-like objects after this for debugging, but they're ignored. 112 | #define EXPECT_TRUE(condition) \ 113 | if (true) { \ 114 | if (!(condition)) { \ 115 | fprintf(stderr, "Check failed: %s\n", #condition); \ 116 | exit(1); \ 117 | } \ 118 | } else std::cerr << "" 119 | 120 | #define EXPECT_OP(op, val1, val2) \ 121 | if (true) { \ 122 | if (!((val1) op (val2))) { \ 123 | fprintf(stderr, "Check failed: %s %s %s\n", #val1, #op, #val2); \ 124 | exit(1); \ 125 | } \ 126 | } else std::cerr << "" 127 | 128 | #define EXPECT_EQ(val1, val2) EXPECT_OP(==, val1, val2) 129 | #define EXPECT_NE(val1, val2) EXPECT_OP(!=, val1, val2) 130 | #define EXPECT_LE(val1, val2) EXPECT_OP(<=, val1, val2) 131 | #define EXPECT_LT(val1, val2) EXPECT_OP(< , val1, val2) 132 | #define EXPECT_GE(val1, val2) EXPECT_OP(>=, val1, val2) 133 | #define EXPECT_GT(val1, val2) EXPECT_OP(> , val1, val2) 134 | #define EXPECT_FALSE(cond) EXPECT_TRUE(!(cond)) 135 | 136 | // C99 declares isnan and isinf should be macros, so the #ifdef test 137 | // should be reliable everywhere. Of course, it's not, but these 138 | // are testing pertty marginal functionality anyway, so it's ok to 139 | // not-run them even in situations they might, with effort, be made to work. 140 | #ifdef isnan // Some compilers, like sun's for Solaris 10, don't define this 141 | #define EXPECT_NAN(arg) \ 142 | do { \ 143 | if (!isnan(arg)) { \ 144 | fprintf(stderr, "Check failed: isnan(%s)\n", #arg); \ 145 | exit(1); \ 146 | } \ 147 | } while (0) 148 | #else 149 | #define EXPECT_NAN(arg) 150 | #endif 151 | 152 | #ifdef isinf // Some compilers, like sun's for Solaris 10, don't define this 153 | #define EXPECT_INF(arg) \ 154 | do { \ 155 | if (!isinf(arg)) { \ 156 | fprintf(stderr, "Check failed: isinf(%s)\n", #arg); \ 157 | exit(1); \ 158 | } \ 159 | } while (0) 160 | #else 161 | #define EXPECT_INF(arg) 162 | #endif 163 | 164 | #define EXPECT_DOUBLE_EQ(val1, val2) \ 165 | do { \ 166 | if (((val1) < (val2) - 0.001 || (val1) > (val2) + 0.001)) { \ 167 | fprintf(stderr, "Check failed: %s == %s\n", #val1, #val2); \ 168 | exit(1); \ 169 | } \ 170 | } while (0) 171 | 172 | #define EXPECT_STREQ(val1, val2) \ 173 | do { \ 174 | if (strcmp((val1), (val2)) != 0) { \ 175 | fprintf(stderr, "Check failed: streq(%s, %s)\n", #val1, #val2); \ 176 | exit(1); \ 177 | } \ 178 | } while (0) 179 | 180 | // Call this in a .cc file where you will later call RUN_ALL_TESTS in main(). 181 | #define TEST_INIT \ 182 | static std::vector g_testlist; /* the tests to run */ \ 183 | static int RUN_ALL_TESTS() { \ 184 | std::vector::const_iterator it; \ 185 | for (it = g_testlist.begin(); it != g_testlist.end(); ++it) { \ 186 | (*it)(); /* The test will error-exit if there's a problem. */ \ 187 | } \ 188 | fprintf(stderr, "\nPassed %d tests\n\nPASS\n", \ 189 | static_cast(g_testlist.size())); \ 190 | return 0; \ 191 | } 192 | 193 | // Note that this macro uses a FlagSaver to keep tests isolated. 194 | #define TEST(a, b) \ 195 | struct Test_##a##_##b { \ 196 | Test_##a##_##b() { g_testlist.push_back(&Run); } \ 197 | static void Run() { \ 198 | FlagSaver fs; \ 199 | fprintf(stderr, "Running test %s/%s\n", #a, #b); \ 200 | RunTest(); \ 201 | } \ 202 | static void RunTest(); \ 203 | }; \ 204 | static Test_##a##_##b g_test_##a##_##b; \ 205 | void Test_##a##_##b::RunTest() 206 | 207 | // This is a dummy class that eases the google->opensource transition. 208 | namespace testing { 209 | class Test {}; 210 | } 211 | 212 | // Call this in a .cc file where you will later call EXPECT_DEATH 213 | #define EXPECT_DEATH_INIT \ 214 | static bool g_called_exit; \ 215 | static void CalledExit(int) { g_called_exit = true; } 216 | 217 | #define EXPECT_DEATH(fn, msg) \ 218 | do { \ 219 | g_called_exit = false; \ 220 | gflags_exitfunc = &CalledExit; \ 221 | fn; \ 222 | gflags_exitfunc = &exit; /* set back to its default */ \ 223 | if (!g_called_exit) { \ 224 | fprintf(stderr, "Function didn't die (%s): %s\n", msg, #fn); \ 225 | exit(1); \ 226 | } \ 227 | } while (0) 228 | 229 | #define GTEST_HAS_DEATH_TEST 1 230 | 231 | // -- path routines ---------------------------------------------------------- 232 | 233 | // Tries to create the directory path as a temp-dir. If it fails, 234 | // changes path to some directory it *can* create. 235 | #if defined(__MINGW32__) 236 | #include 237 | inline void MakeTmpdir(std::string* path) { 238 | if (!path->empty()) { 239 | path->append("/gflags_unittest_testdir"); 240 | int err = mkdir(path->c_str()); 241 | if (err == 0 || errno == EEXIST) return; 242 | } 243 | // I had trouble creating a directory in /tmp from mingw 244 | *path = "./gflags_unittest"; 245 | mkdir(path->c_str()); 246 | } 247 | #elif defined(_MSC_VER) 248 | #include 249 | inline void MakeTmpdir(std::string* path) { 250 | if (!path->empty()) { 251 | int err = _mkdir(path->c_str()); 252 | if (err == 0 || errno == EEXIST) return; 253 | } 254 | char tmppath_buffer[1024]; 255 | int tmppath_len = GetTempPathA(sizeof(tmppath_buffer), tmppath_buffer); 256 | assert(tmppath_len > 0 && tmppath_len < sizeof(tmppath_buffer)); 257 | assert(tmppath_buffer[tmppath_len - 1] == '\\'); // API guarantees it 258 | *path = std::string(tmppath_buffer) + "gflags_unittest"; 259 | _mkdir(path->c_str()); 260 | } 261 | #else 262 | inline void MakeTmpdir(std::string* path) { 263 | if (!path->empty()) { 264 | int err = mkdir(path->c_str(), 0755); 265 | if (err == 0 || errno == EEXIST) return; 266 | } 267 | mkdir("/tmp/gflags_unittest", 0755); 268 | } 269 | #endif 270 | 271 | // -- string routines -------------------------------------------------------- 272 | 273 | inline void InternalStringPrintf(std::string* output, const char* format, 274 | va_list ap) { 275 | char space[128]; // try a small buffer and hope it fits 276 | 277 | // It's possible for methods that use a va_list to invalidate 278 | // the data in it upon use. The fix is to make a copy 279 | // of the structure before using it and use that copy instead. 280 | va_list backup_ap; 281 | va_copy(backup_ap, ap); 282 | int bytes_written = vsnprintf(space, sizeof(space), format, backup_ap); 283 | va_end(backup_ap); 284 | 285 | if ((bytes_written >= 0) && (static_cast(bytes_written) < sizeof(space))) { 286 | output->append(space, bytes_written); 287 | return; 288 | } 289 | 290 | // Repeatedly increase buffer size until it fits. 291 | int length = sizeof(space); 292 | while (true) { 293 | if (bytes_written < 0) { 294 | // Older snprintf() behavior. :-( Just try doubling the buffer size 295 | length *= 2; 296 | } else { 297 | // We need exactly "bytes_written+1" characters 298 | length = bytes_written+1; 299 | } 300 | char* buf = new char[length]; 301 | 302 | // Restore the va_list before we use it again 303 | va_copy(backup_ap, ap); 304 | bytes_written = vsnprintf(buf, length, format, backup_ap); 305 | va_end(backup_ap); 306 | 307 | if ((bytes_written >= 0) && (bytes_written < length)) { 308 | output->append(buf, bytes_written); 309 | delete[] buf; 310 | return; 311 | } 312 | delete[] buf; 313 | } 314 | } 315 | 316 | // Clears output before writing to it. 317 | inline void SStringPrintf(std::string* output, const char* format, ...) { 318 | va_list ap; 319 | va_start(ap, format); 320 | output->clear(); 321 | InternalStringPrintf(output, format, ap); 322 | va_end(ap); 323 | } 324 | 325 | inline void StringAppendF(std::string* output, const char* format, ...) { 326 | va_list ap; 327 | va_start(ap, format); 328 | InternalStringPrintf(output, format, ap); 329 | va_end(ap); 330 | } 331 | 332 | inline std::string StringPrintf(const char* format, ...) { 333 | va_list ap; 334 | va_start(ap, format); 335 | std::string output; 336 | InternalStringPrintf(&output, format, ap); 337 | va_end(ap); 338 | return output; 339 | } 340 | 341 | inline bool SafeGetEnv(const char *varname, std::string &valstr) 342 | { 343 | #if defined(_MSC_VER) && _MSC_VER >= 1400 344 | char *val; 345 | size_t sz; 346 | if (_dupenv_s(&val, &sz, varname) != 0 || !val) return false; 347 | valstr = val; 348 | free(val); 349 | #else 350 | const char * const val = getenv(varname); 351 | if (!val) return false; 352 | valstr = val; 353 | #endif 354 | return true; 355 | } 356 | 357 | inline int SafeFOpen(FILE **fp, const char* fname, const char *mode) 358 | { 359 | #if defined(_MSC_VER) && _MSC_VER >= 1400 360 | return fopen_s(fp, fname, mode); 361 | #else 362 | assert(fp != NULL); 363 | *fp = fopen(fname, mode); 364 | // errno only guaranteed to be set on failure 365 | return ((*fp == NULL) ? errno : 0); 366 | #endif 367 | } 368 | 369 | 370 | } // namespace GFLAGS_NAMESPACE 371 | 372 | 373 | #endif // GFLAGS_UTIL_H_ 374 | -------------------------------------------------------------------------------- /src/mutex.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2007, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // --- 31 | // 32 | // A simple mutex wrapper, supporting locks and read-write locks. 33 | // You should assume the locks are *not* re-entrant. 34 | // 35 | // This class is meant to be internal-only and should be wrapped by an 36 | // internal namespace. Before you use this module, please give the 37 | // name of your internal namespace for this module. Or, if you want 38 | // to expose it, you'll want to move it to the Google namespace. We 39 | // cannot put this class in global namespace because there can be some 40 | // problems when we have multiple versions of Mutex in each shared object. 41 | // 42 | // NOTE: by default, we have #ifdef'ed out the TryLock() method. 43 | // This is for two reasons: 44 | // 1) TryLock() under Windows is a bit annoying (it requires a 45 | // #define to be defined very early). 46 | // 2) TryLock() is broken for NO_THREADS mode, at least in NDEBUG 47 | // mode. 48 | // If you need TryLock(), and either these two caveats are not a 49 | // problem for you, or you're willing to work around them, then 50 | // feel free to #define GMUTEX_TRYLOCK, or to remove the #ifdefs 51 | // in the code below. 52 | // 53 | // CYGWIN NOTE: Cygwin support for rwlock seems to be buggy: 54 | // http://www.cygwin.com/ml/cygwin/2008-12/msg00017.html 55 | // Because of that, we might as well use windows locks for 56 | // cygwin. They seem to be more reliable than the cygwin pthreads layer. 57 | // 58 | // TRICKY IMPLEMENTATION NOTE: 59 | // This class is designed to be safe to use during 60 | // dynamic-initialization -- that is, by global constructors that are 61 | // run before main() starts. The issue in this case is that 62 | // dynamic-initialization happens in an unpredictable order, and it 63 | // could be that someone else's dynamic initializer could call a 64 | // function that tries to acquire this mutex -- but that all happens 65 | // before this mutex's constructor has run. (This can happen even if 66 | // the mutex and the function that uses the mutex are in the same .cc 67 | // file.) Basically, because Mutex does non-trivial work in its 68 | // constructor, it's not, in the naive implementation, safe to use 69 | // before dynamic initialization has run on it. 70 | // 71 | // The solution used here is to pair the actual mutex primitive with a 72 | // bool that is set to true when the mutex is dynamically initialized. 73 | // (Before that it's false.) Then we modify all mutex routines to 74 | // look at the bool, and not try to lock/unlock until the bool makes 75 | // it to true (which happens after the Mutex constructor has run.) 76 | // 77 | // This works because before main() starts -- particularly, during 78 | // dynamic initialization -- there are no threads, so a) it's ok that 79 | // the mutex operations are a no-op, since we don't need locking then 80 | // anyway; and b) we can be quite confident our bool won't change 81 | // state between a call to Lock() and a call to Unlock() (that would 82 | // require a global constructor in one translation unit to call Lock() 83 | // and another global constructor in another translation unit to call 84 | // Unlock() later, which is pretty perverse). 85 | // 86 | // That said, it's tricky, and can conceivably fail; it's safest to 87 | // avoid trying to acquire a mutex in a global constructor, if you 88 | // can. One way it can fail is that a really smart compiler might 89 | // initialize the bool to true at static-initialization time (too 90 | // early) rather than at dynamic-initialization time. To discourage 91 | // that, we set is_safe_ to true in code (not the constructor 92 | // colon-initializer) and set it to true via a function that always 93 | // evaluates to true, but that the compiler can't know always 94 | // evaluates to true. This should be good enough. 95 | // 96 | // A related issue is code that could try to access the mutex 97 | // after it's been destroyed in the global destructors (because 98 | // the Mutex global destructor runs before some other global 99 | // destructor, that tries to acquire the mutex). The way we 100 | // deal with this is by taking a constructor arg that global 101 | // mutexes should pass in, that causes the destructor to do no 102 | // work. We still depend on the compiler not doing anything 103 | // weird to a Mutex's memory after it is destroyed, but for a 104 | // static global variable, that's pretty safe. 105 | 106 | #ifndef GFLAGS_MUTEX_H_ 107 | #define GFLAGS_MUTEX_H_ 108 | 109 | #include "gflags_declare.h" // to figure out pthreads support 110 | 111 | #if defined(NO_THREADS) 112 | typedef int MutexType; // to keep a lock-count 113 | #elif defined(OS_WINDOWS) 114 | # ifndef WIN32_LEAN_AND_MEAN 115 | # define WIN32_LEAN_AND_MEAN // We only need minimal includes 116 | # endif 117 | # ifndef NOMINMAX 118 | # define NOMINMAX // Don't want windows to override min()/max() 119 | # endif 120 | # ifdef GMUTEX_TRYLOCK 121 | // We need Windows NT or later for TryEnterCriticalSection(). If you 122 | // don't need that functionality, you can remove these _WIN32_WINNT 123 | // lines, and change TryLock() to assert(0) or something. 124 | # ifndef _WIN32_WINNT 125 | # define _WIN32_WINNT 0x0400 126 | # endif 127 | # endif 128 | # include 129 | typedef CRITICAL_SECTION MutexType; 130 | #elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK) 131 | // Needed for pthread_rwlock_*. If it causes problems, you could take it 132 | // out, but then you'd have to unset HAVE_RWLOCK (at least on linux -- it 133 | // *does* cause problems for FreeBSD, or MacOSX, but isn't needed 134 | // for locking there.) 135 | # ifdef __linux__ 136 | # if _XOPEN_SOURCE < 500 // including not being defined at all 137 | # undef _XOPEN_SOURCE 138 | # define _XOPEN_SOURCE 500 // may be needed to get the rwlock calls 139 | # endif 140 | # endif 141 | # include 142 | typedef pthread_rwlock_t MutexType; 143 | #elif defined(HAVE_PTHREAD) 144 | # include 145 | typedef pthread_mutex_t MutexType; 146 | #else 147 | # error Need to implement mutex.h for your architecture, or #define NO_THREADS 148 | #endif 149 | 150 | #include 151 | #include // for abort() 152 | 153 | #define MUTEX_NAMESPACE gflags_mutex_namespace 154 | 155 | namespace MUTEX_NAMESPACE { 156 | 157 | class Mutex { 158 | public: 159 | // This is used for the single-arg constructor 160 | enum LinkerInitialized { LINKER_INITIALIZED }; 161 | 162 | // Create a Mutex that is not held by anybody. This constructor is 163 | // typically used for Mutexes allocated on the heap or the stack. 164 | inline Mutex(); 165 | // This constructor should be used for global, static Mutex objects. 166 | // It inhibits work being done by the destructor, which makes it 167 | // safer for code that tries to acqiure this mutex in their global 168 | // destructor. 169 | inline Mutex(LinkerInitialized); 170 | 171 | // Destructor 172 | inline ~Mutex(); 173 | 174 | inline void Lock(); // Block if needed until free then acquire exclusively 175 | inline void Unlock(); // Release a lock acquired via Lock() 176 | #ifdef GMUTEX_TRYLOCK 177 | inline bool TryLock(); // If free, Lock() and return true, else return false 178 | #endif 179 | // Note that on systems that don't support read-write locks, these may 180 | // be implemented as synonyms to Lock() and Unlock(). So you can use 181 | // these for efficiency, but don't use them anyplace where being able 182 | // to do shared reads is necessary to avoid deadlock. 183 | inline void ReaderLock(); // Block until free or shared then acquire a share 184 | inline void ReaderUnlock(); // Release a read share of this Mutex 185 | inline void WriterLock() { Lock(); } // Acquire an exclusive lock 186 | inline void WriterUnlock() { Unlock(); } // Release a lock from WriterLock() 187 | 188 | private: 189 | MutexType mutex_; 190 | // We want to make sure that the compiler sets is_safe_ to true only 191 | // when we tell it to, and never makes assumptions is_safe_ is 192 | // always true. volatile is the most reliable way to do that. 193 | volatile bool is_safe_; 194 | // This indicates which constructor was called. 195 | bool destroy_; 196 | 197 | inline void SetIsSafe() { is_safe_ = true; } 198 | 199 | // Catch the error of writing Mutex when intending MutexLock. 200 | Mutex(Mutex* /*ignored*/) {} 201 | // Disallow "evil" constructors 202 | Mutex(const Mutex&); 203 | void operator=(const Mutex&); 204 | }; 205 | 206 | // Now the implementation of Mutex for various systems 207 | #if defined(NO_THREADS) 208 | 209 | // When we don't have threads, we can be either reading or writing, 210 | // but not both. We can have lots of readers at once (in no-threads 211 | // mode, that's most likely to happen in recursive function calls), 212 | // but only one writer. We represent this by having mutex_ be -1 when 213 | // writing and a number > 0 when reading (and 0 when no lock is held). 214 | // 215 | // In debug mode, we assert these invariants, while in non-debug mode 216 | // we do nothing, for efficiency. That's why everything is in an 217 | // assert. 218 | 219 | Mutex::Mutex() : mutex_(0) { } 220 | Mutex::Mutex(Mutex::LinkerInitialized) : mutex_(0) { } 221 | Mutex::~Mutex() { assert(mutex_ == 0); } 222 | void Mutex::Lock() { assert(--mutex_ == -1); } 223 | void Mutex::Unlock() { assert(mutex_++ == -1); } 224 | #ifdef GMUTEX_TRYLOCK 225 | bool Mutex::TryLock() { if (mutex_) return false; Lock(); return true; } 226 | #endif 227 | void Mutex::ReaderLock() { assert(++mutex_ > 0); } 228 | void Mutex::ReaderUnlock() { assert(mutex_-- > 0); } 229 | 230 | #elif defined(OS_WINDOWS) 231 | 232 | Mutex::Mutex() : destroy_(true) { 233 | InitializeCriticalSection(&mutex_); 234 | SetIsSafe(); 235 | } 236 | Mutex::Mutex(LinkerInitialized) : destroy_(false) { 237 | InitializeCriticalSection(&mutex_); 238 | SetIsSafe(); 239 | } 240 | Mutex::~Mutex() { if (destroy_) DeleteCriticalSection(&mutex_); } 241 | void Mutex::Lock() { if (is_safe_) EnterCriticalSection(&mutex_); } 242 | void Mutex::Unlock() { if (is_safe_) LeaveCriticalSection(&mutex_); } 243 | #ifdef GMUTEX_TRYLOCK 244 | bool Mutex::TryLock() { return is_safe_ ? 245 | TryEnterCriticalSection(&mutex_) != 0 : true; } 246 | #endif 247 | void Mutex::ReaderLock() { Lock(); } // we don't have read-write locks 248 | void Mutex::ReaderUnlock() { Unlock(); } 249 | 250 | #elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK) 251 | 252 | #define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \ 253 | if (is_safe_ && fncall(&mutex_) != 0) abort(); \ 254 | } while (0) 255 | 256 | Mutex::Mutex() : destroy_(true) { 257 | SetIsSafe(); 258 | if (is_safe_ && pthread_rwlock_init(&mutex_, NULL) != 0) abort(); 259 | } 260 | Mutex::Mutex(Mutex::LinkerInitialized) : destroy_(false) { 261 | SetIsSafe(); 262 | if (is_safe_ && pthread_rwlock_init(&mutex_, NULL) != 0) abort(); 263 | } 264 | Mutex::~Mutex() { if (destroy_) SAFE_PTHREAD(pthread_rwlock_destroy); } 265 | void Mutex::Lock() { SAFE_PTHREAD(pthread_rwlock_wrlock); } 266 | void Mutex::Unlock() { SAFE_PTHREAD(pthread_rwlock_unlock); } 267 | #ifdef GMUTEX_TRYLOCK 268 | bool Mutex::TryLock() { return is_safe_ ? 269 | pthread_rwlock_trywrlock(&mutex_) == 0 : true; } 270 | #endif 271 | void Mutex::ReaderLock() { SAFE_PTHREAD(pthread_rwlock_rdlock); } 272 | void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock); } 273 | #undef SAFE_PTHREAD 274 | 275 | #elif defined(HAVE_PTHREAD) 276 | 277 | #define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \ 278 | if (is_safe_ && fncall(&mutex_) != 0) abort(); \ 279 | } while (0) 280 | 281 | Mutex::Mutex() : destroy_(true) { 282 | SetIsSafe(); 283 | if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) abort(); 284 | } 285 | Mutex::Mutex(Mutex::LinkerInitialized) : destroy_(false) { 286 | SetIsSafe(); 287 | if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) abort(); 288 | } 289 | Mutex::~Mutex() { if (destroy_) SAFE_PTHREAD(pthread_mutex_destroy); } 290 | void Mutex::Lock() { SAFE_PTHREAD(pthread_mutex_lock); } 291 | void Mutex::Unlock() { SAFE_PTHREAD(pthread_mutex_unlock); } 292 | #ifdef GMUTEX_TRYLOCK 293 | bool Mutex::TryLock() { return is_safe_ ? 294 | pthread_mutex_trylock(&mutex_) == 0 : true; } 295 | #endif 296 | void Mutex::ReaderLock() { Lock(); } 297 | void Mutex::ReaderUnlock() { Unlock(); } 298 | #undef SAFE_PTHREAD 299 | 300 | #endif 301 | 302 | // -------------------------------------------------------------------------- 303 | // Some helper classes 304 | 305 | // MutexLock(mu) acquires mu when constructed and releases it when destroyed. 306 | class MutexLock { 307 | public: 308 | explicit MutexLock(Mutex *mu) : mu_(mu) { mu_->Lock(); } 309 | ~MutexLock() { mu_->Unlock(); } 310 | private: 311 | Mutex * const mu_; 312 | // Disallow "evil" constructors 313 | MutexLock(const MutexLock&); 314 | void operator=(const MutexLock&); 315 | }; 316 | 317 | // ReaderMutexLock and WriterMutexLock do the same, for rwlocks 318 | class ReaderMutexLock { 319 | public: 320 | explicit ReaderMutexLock(Mutex *mu) : mu_(mu) { mu_->ReaderLock(); } 321 | ~ReaderMutexLock() { mu_->ReaderUnlock(); } 322 | private: 323 | Mutex * const mu_; 324 | // Disallow "evil" constructors 325 | ReaderMutexLock(const ReaderMutexLock&); 326 | void operator=(const ReaderMutexLock&); 327 | }; 328 | 329 | class WriterMutexLock { 330 | public: 331 | explicit WriterMutexLock(Mutex *mu) : mu_(mu) { mu_->WriterLock(); } 332 | ~WriterMutexLock() { mu_->WriterUnlock(); } 333 | private: 334 | Mutex * const mu_; 335 | // Disallow "evil" constructors 336 | WriterMutexLock(const WriterMutexLock&); 337 | void operator=(const WriterMutexLock&); 338 | }; 339 | 340 | // Catch bug where variable name is omitted, e.g. MutexLock (&mu); 341 | #define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_decl_missing_var_name) 342 | #define ReaderMutexLock(x) COMPILE_ASSERT(0, rmutex_lock_decl_missing_var_name) 343 | #define WriterMutexLock(x) COMPILE_ASSERT(0, wmutex_lock_decl_missing_var_name) 344 | 345 | } // namespace MUTEX_NAMESPACE 346 | 347 | using namespace MUTEX_NAMESPACE; 348 | 349 | #undef MUTEX_NAMESPACE 350 | 351 | #endif /* #define GFLAGS_MUTEX_H__ */ 352 | -------------------------------------------------------------------------------- /src/gflags_reporting.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 1999, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // --- 31 | // 32 | // Revamped and reorganized by Craig Silverstein 33 | // 34 | // This file contains code for handling the 'reporting' flags. These 35 | // are flags that, when present, cause the program to report some 36 | // information and then exit. --help and --version are the canonical 37 | // reporting flags, but we also have flags like --helpxml, etc. 38 | // 39 | // There's only one function that's meant to be called externally: 40 | // HandleCommandLineHelpFlags(). (Well, actually, ShowUsageWithFlags(), 41 | // ShowUsageWithFlagsRestrict(), and DescribeOneFlag() can be called 42 | // externally too, but there's little need for it.) These are all 43 | // declared in the main gflags.h header file. 44 | // 45 | // HandleCommandLineHelpFlags() will check what 'reporting' flags have 46 | // been defined, if any -- the "help" part of the function name is a 47 | // bit misleading -- and do the relevant reporting. It should be 48 | // called after all flag-values have been assigned, that is, after 49 | // parsing the command-line. 50 | 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | 58 | #include "config.h" 59 | #include "gflags.h" 60 | #include "gflags_completions.h" 61 | #include "util.h" 62 | 63 | 64 | // The 'reporting' flags. They all call gflags_exitfunc(). 65 | DEFINE_bool (help, false, "show help on all flags [tip: all flags can have two dashes]"); 66 | DEFINE_bool (helpfull, false, "show help on all flags -- same as -help"); 67 | DEFINE_bool (helpshort, false, "show help on only the main module for this program"); 68 | DEFINE_string(helpon, "", "show help on the modules named by this flag value"); 69 | DEFINE_string(helpmatch, "", "show help on modules whose name contains the specified substr"); 70 | DEFINE_bool (helppackage, false, "show help on all modules in the main package"); 71 | DEFINE_bool (helpxml, false, "produce an xml version of help"); 72 | DEFINE_bool (version, false, "show version and build info and exit"); 73 | 74 | 75 | namespace GFLAGS_NAMESPACE { 76 | 77 | 78 | using std::string; 79 | using std::vector; 80 | 81 | 82 | // -------------------------------------------------------------------- 83 | // DescribeOneFlag() 84 | // DescribeOneFlagInXML() 85 | // Routines that pretty-print info about a flag. These use 86 | // a CommandLineFlagInfo, which is the way the gflags 87 | // API exposes static info about a flag. 88 | // -------------------------------------------------------------------- 89 | 90 | static const int kLineLength = 80; 91 | 92 | static void AddString(const string& s, 93 | string* final_string, int* chars_in_line) { 94 | const int slen = static_cast(s.length()); 95 | if (*chars_in_line + 1 + slen >= kLineLength) { // < 80 chars/line 96 | *final_string += "\n "; 97 | *chars_in_line = 6; 98 | } else { 99 | *final_string += " "; 100 | *chars_in_line += 1; 101 | } 102 | *final_string += s; 103 | *chars_in_line += slen; 104 | } 105 | 106 | static string PrintStringFlagsWithQuotes(const CommandLineFlagInfo& flag, 107 | const string& text, bool current) { 108 | const char* c_string = (current ? flag.current_value.c_str() : 109 | flag.default_value.c_str()); 110 | if (strcmp(flag.type.c_str(), "string") == 0) { // add quotes for strings 111 | return StringPrintf("%s: \"%s\"", text.c_str(), c_string); 112 | } else { 113 | return StringPrintf("%s: %s", text.c_str(), c_string); 114 | } 115 | } 116 | 117 | // Create a descriptive string for a flag. 118 | // Goes to some trouble to make pretty line breaks. 119 | string DescribeOneFlag(const CommandLineFlagInfo& flag) { 120 | string main_part; 121 | SStringPrintf(&main_part, " -%s (%s)", 122 | flag.name.c_str(), 123 | flag.description.c_str()); 124 | const char* c_string = main_part.c_str(); 125 | int chars_left = static_cast(main_part.length()); 126 | string final_string = ""; 127 | int chars_in_line = 0; // how many chars in current line so far? 128 | while (1) { 129 | assert(chars_left == strlen(c_string)); // Unless there's a \0 in there? 130 | const char* newline = strchr(c_string, '\n'); 131 | if (newline == NULL && chars_in_line+chars_left < kLineLength) { 132 | // The whole remainder of the string fits on this line 133 | final_string += c_string; 134 | chars_in_line += chars_left; 135 | break; 136 | } 137 | if (newline != NULL && newline - c_string < kLineLength - chars_in_line) { 138 | int n = static_cast(newline - c_string); 139 | final_string.append(c_string, n); 140 | chars_left -= n + 1; 141 | c_string += n + 1; 142 | } else { 143 | // Find the last whitespace on this 80-char line 144 | int whitespace = kLineLength-chars_in_line-1; // < 80 chars/line 145 | while ( whitespace > 0 && !isspace(c_string[whitespace]) ) { 146 | --whitespace; 147 | } 148 | if (whitespace <= 0) { 149 | // Couldn't find any whitespace to make a line break. Just dump the 150 | // rest out! 151 | final_string += c_string; 152 | chars_in_line = kLineLength; // next part gets its own line for sure! 153 | break; 154 | } 155 | final_string += string(c_string, whitespace); 156 | chars_in_line += whitespace; 157 | while (isspace(c_string[whitespace])) ++whitespace; 158 | c_string += whitespace; 159 | chars_left -= whitespace; 160 | } 161 | if (*c_string == '\0') 162 | break; 163 | StringAppendF(&final_string, "\n "); 164 | chars_in_line = 6; 165 | } 166 | 167 | // Append data type 168 | AddString(string("type: ") + flag.type, &final_string, &chars_in_line); 169 | // The listed default value will be the actual default from the flag 170 | // definition in the originating source file, unless the value has 171 | // subsequently been modified using SetCommandLineOptionWithMode() with mode 172 | // SET_FLAGS_DEFAULT, or by setting FLAGS_foo = bar before ParseCommandLineFlags(). 173 | AddString(PrintStringFlagsWithQuotes(flag, "default", false), &final_string, 174 | &chars_in_line); 175 | if (!flag.is_default) { 176 | AddString(PrintStringFlagsWithQuotes(flag, "currently", true), 177 | &final_string, &chars_in_line); 178 | } 179 | 180 | StringAppendF(&final_string, "\n"); 181 | return final_string; 182 | } 183 | 184 | // Simple routine to xml-escape a string: escape & and < only. 185 | static string XMLText(const string& txt) { 186 | string ans = txt; 187 | for (string::size_type pos = 0; (pos = ans.find("&", pos)) != string::npos; ) 188 | ans.replace(pos++, 1, "&"); 189 | for (string::size_type pos = 0; (pos = ans.find("<", pos)) != string::npos; ) 190 | ans.replace(pos++, 1, "<"); 191 | return ans; 192 | } 193 | 194 | static void AddXMLTag(string* r, const char* tag, const string& txt) { 195 | StringAppendF(r, "<%s>%s", tag, XMLText(txt).c_str(), tag); 196 | } 197 | 198 | 199 | static string DescribeOneFlagInXML(const CommandLineFlagInfo& flag) { 200 | // The file and flagname could have been attributes, but default 201 | // and meaning need to avoid attribute normalization. This way it 202 | // can be parsed by simple programs, in addition to xml parsers. 203 | string r(""); 204 | AddXMLTag(&r, "file", flag.filename); 205 | AddXMLTag(&r, "name", flag.name); 206 | AddXMLTag(&r, "meaning", flag.description); 207 | AddXMLTag(&r, "default", flag.default_value); 208 | AddXMLTag(&r, "current", flag.current_value); 209 | AddXMLTag(&r, "type", flag.type); 210 | r += ""; 211 | return r; 212 | } 213 | 214 | // -------------------------------------------------------------------- 215 | // ShowUsageWithFlags() 216 | // ShowUsageWithFlagsRestrict() 217 | // ShowXMLOfFlags() 218 | // These routines variously expose the registry's list of flag 219 | // values. ShowUsage*() prints the flag-value information 220 | // to stdout in a user-readable format (that's what --help uses). 221 | // The Restrict() version limits what flags are shown. 222 | // ShowXMLOfFlags() prints the flag-value information to stdout 223 | // in a machine-readable format. In all cases, the flags are 224 | // sorted: first by filename they are defined in, then by flagname. 225 | // -------------------------------------------------------------------- 226 | 227 | static const char* Basename(const char* filename) { 228 | const char* sep = strrchr(filename, PATH_SEPARATOR); 229 | return sep ? sep + 1 : filename; 230 | } 231 | 232 | static string Dirname(const string& filename) { 233 | string::size_type sep = filename.rfind(PATH_SEPARATOR); 234 | return filename.substr(0, (sep == string::npos) ? 0 : sep); 235 | } 236 | 237 | // Test whether a filename contains at least one of the substrings. 238 | static bool FileMatchesSubstring(const string& filename, 239 | const vector& substrings) { 240 | for (vector::const_iterator target = substrings.begin(); 241 | target != substrings.end(); 242 | ++target) { 243 | if (strstr(filename.c_str(), target->c_str()) != NULL) 244 | return true; 245 | // If the substring starts with a '/', that means that we want 246 | // the string to be at the beginning of a directory component. 247 | // That should match the first directory component as well, so 248 | // we allow '/foo' to match a filename of 'foo'. 249 | if (!target->empty() && (*target)[0] == PATH_SEPARATOR && 250 | strncmp(filename.c_str(), target->c_str() + 1, 251 | strlen(target->c_str() + 1)) == 0) 252 | return true; 253 | } 254 | return false; 255 | } 256 | 257 | // Show help for every filename which matches any of the target substrings. 258 | // If substrings is empty, shows help for every file. If a flag's help message 259 | // has been stripped (e.g. by adding '#define STRIP_FLAG_HELP 1' 260 | // before including gflags/gflags.h), then this flag will not be displayed 261 | // by '--help' and its variants. 262 | static void ShowUsageWithFlagsMatching(const char *argv0, 263 | const vector &substrings) { 264 | fprintf(stdout, "%s: %s\n", Basename(argv0), ProgramUsage()); 265 | 266 | vector flags; 267 | GetAllFlags(&flags); // flags are sorted by filename, then flagname 268 | 269 | string last_filename; // so we know when we're at a new file 270 | bool first_directory = true; // controls blank lines between dirs 271 | bool found_match = false; // stays false iff no dir matches restrict 272 | for (vector::const_iterator flag = flags.begin(); 273 | flag != flags.end(); 274 | ++flag) { 275 | if (substrings.empty() || 276 | FileMatchesSubstring(flag->filename, substrings)) { 277 | // If the flag has been stripped, pretend that it doesn't exist. 278 | if (flag->description == kStrippedFlagHelp) continue; 279 | found_match = true; // this flag passed the match! 280 | if (flag->filename != last_filename) { // new file 281 | if (Dirname(flag->filename) != Dirname(last_filename)) { // new dir! 282 | if (!first_directory) 283 | fprintf(stdout, "\n\n"); // put blank lines between directories 284 | first_directory = false; 285 | } 286 | fprintf(stdout, "\n Flags from %s:\n", flag->filename.c_str()); 287 | last_filename = flag->filename; 288 | } 289 | // Now print this flag 290 | fprintf(stdout, "%s", DescribeOneFlag(*flag).c_str()); 291 | } 292 | } 293 | if (!found_match && !substrings.empty()) { 294 | fprintf(stdout, "\n No modules matched: use -help\n"); 295 | } 296 | } 297 | 298 | void ShowUsageWithFlagsRestrict(const char *argv0, const char *restrict) { 299 | vector substrings; 300 | if (restrict != NULL && *restrict != '\0') { 301 | substrings.push_back(restrict); 302 | } 303 | ShowUsageWithFlagsMatching(argv0, substrings); 304 | } 305 | 306 | void ShowUsageWithFlags(const char *argv0) { 307 | ShowUsageWithFlagsRestrict(argv0, ""); 308 | } 309 | 310 | // Convert the help, program, and usage to xml. 311 | static void ShowXMLOfFlags(const char *prog_name) { 312 | vector flags; 313 | GetAllFlags(&flags); // flags are sorted: by filename, then flagname 314 | 315 | // XML. There is no corresponding schema yet 316 | fprintf(stdout, "\n"); 317 | // The document 318 | fprintf(stdout, "\n"); 319 | // the program name and usage 320 | fprintf(stdout, "%s\n", 321 | XMLText(Basename(prog_name)).c_str()); 322 | fprintf(stdout, "%s\n", 323 | XMLText(ProgramUsage()).c_str()); 324 | // All the flags 325 | for (vector::const_iterator flag = flags.begin(); 326 | flag != flags.end(); 327 | ++flag) { 328 | if (flag->description != kStrippedFlagHelp) 329 | fprintf(stdout, "%s\n", DescribeOneFlagInXML(*flag).c_str()); 330 | } 331 | // The end of the document 332 | fprintf(stdout, "\n"); 333 | } 334 | 335 | // -------------------------------------------------------------------- 336 | // ShowVersion() 337 | // Called upon --version. Prints build-related info. 338 | // -------------------------------------------------------------------- 339 | 340 | static void ShowVersion() { 341 | const char* version_string = VersionString(); 342 | if (version_string && *version_string) { 343 | fprintf(stdout, "%s version %s\n", 344 | ProgramInvocationShortName(), version_string); 345 | } else { 346 | fprintf(stdout, "%s\n", ProgramInvocationShortName()); 347 | } 348 | # if !defined(NDEBUG) 349 | fprintf(stdout, "Debug build (NDEBUG not #defined)\n"); 350 | # endif 351 | } 352 | 353 | static void AppendPrognameStrings(vector* substrings, 354 | const char* progname) { 355 | string r(""); 356 | r += PATH_SEPARATOR; 357 | r += progname; 358 | substrings->push_back(r + "."); 359 | substrings->push_back(r + "-main."); 360 | substrings->push_back(r + "_main."); 361 | } 362 | 363 | // -------------------------------------------------------------------- 364 | // HandleCommandLineHelpFlags() 365 | // Checks all the 'reporting' commandline flags to see if any 366 | // have been set. If so, handles them appropriately. Note 367 | // that all of them, by definition, cause the program to exit 368 | // if they trigger. 369 | // -------------------------------------------------------------------- 370 | 371 | void HandleCommandLineHelpFlags() { 372 | const char* progname = ProgramInvocationShortName(); 373 | 374 | HandleCommandLineCompletions(); 375 | 376 | vector substrings; 377 | AppendPrognameStrings(&substrings, progname); 378 | 379 | if (FLAGS_helpshort) { 380 | // show only flags related to this binary: 381 | // E.g. for fileutil.cc, want flags containing ... "/fileutil." cc 382 | ShowUsageWithFlagsMatching(progname, substrings); 383 | gflags_exitfunc(1); 384 | 385 | } else if (FLAGS_help || FLAGS_helpfull) { 386 | // show all options 387 | ShowUsageWithFlagsRestrict(progname, ""); // empty restrict 388 | gflags_exitfunc(1); 389 | 390 | } else if (!FLAGS_helpon.empty()) { 391 | string restrict = PATH_SEPARATOR + FLAGS_helpon + "."; 392 | ShowUsageWithFlagsRestrict(progname, restrict.c_str()); 393 | gflags_exitfunc(1); 394 | 395 | } else if (!FLAGS_helpmatch.empty()) { 396 | ShowUsageWithFlagsRestrict(progname, FLAGS_helpmatch.c_str()); 397 | gflags_exitfunc(1); 398 | 399 | } else if (FLAGS_helppackage) { 400 | // Shows help for all files in the same directory as main(). We 401 | // don't want to resort to looking at dirname(progname), because 402 | // the user can pick progname, and it may not relate to the file 403 | // where main() resides. So instead, we search the flags for a 404 | // filename like "/progname.cc", and take the dirname of that. 405 | vector flags; 406 | GetAllFlags(&flags); 407 | string last_package; 408 | for (vector::const_iterator flag = flags.begin(); 409 | flag != flags.end(); 410 | ++flag) { 411 | if (!FileMatchesSubstring(flag->filename, substrings)) 412 | continue; 413 | const string package = Dirname(flag->filename) + PATH_SEPARATOR; 414 | if (package != last_package) { 415 | ShowUsageWithFlagsRestrict(progname, package.c_str()); 416 | VLOG(7) << "Found package: " << package; 417 | if (!last_package.empty()) { // means this isn't our first pkg 418 | LOG(WARNING) << "Multiple packages contain a file=" << progname; 419 | } 420 | last_package = package; 421 | } 422 | } 423 | if (last_package.empty()) { // never found a package to print 424 | LOG(WARNING) << "Unable to find a package for file=" << progname; 425 | } 426 | gflags_exitfunc(1); 427 | 428 | } else if (FLAGS_helpxml) { 429 | ShowXMLOfFlags(progname); 430 | gflags_exitfunc(1); 431 | 432 | } else if (FLAGS_version) { 433 | ShowVersion(); 434 | // Unlike help, we may be asking for version in a script, so return 0 435 | gflags_exitfunc(0); 436 | 437 | } 438 | } 439 | 440 | 441 | } // namespace GFLAGS_NAMESPACE 442 | -------------------------------------------------------------------------------- /src/include/gflags/gflags.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2006, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // --- 31 | // Revamped and reorganized by Craig Silverstein 32 | // 33 | // This is the file that should be included by any file which declares 34 | // or defines a command line flag or wants to parse command line flags 35 | // or print a program usage message (which will include information about 36 | // flags). Executive summary, in the form of an example foo.cc file: 37 | // 38 | // #include "foo.h" // foo.h has a line "DECLARE_int32(start);" 39 | // #include "validators.h" // hypothetical file defining ValidateIsFile() 40 | // 41 | // DEFINE_int32(end, 1000, "The last record to read"); 42 | // 43 | // DEFINE_string(filename, "my_file.txt", "The file to read"); 44 | // // Crash if the specified file does not exist. 45 | // static bool dummy = RegisterFlagValidator(&FLAGS_filename, 46 | // &ValidateIsFile); 47 | // 48 | // DECLARE_bool(verbose); // some other file has a DEFINE_bool(verbose, ...) 49 | // 50 | // void MyFunc() { 51 | // if (FLAGS_verbose) printf("Records %d-%d\n", FLAGS_start, FLAGS_end); 52 | // } 53 | // 54 | // Then, at the command-line: 55 | // ./foo --noverbose --start=5 --end=100 56 | // 57 | // For more details, see 58 | // doc/gflags.html 59 | // 60 | // --- A note about thread-safety: 61 | // 62 | // We describe many functions in this routine as being thread-hostile, 63 | // thread-compatible, or thread-safe. Here are the meanings we use: 64 | // 65 | // thread-safe: it is safe for multiple threads to call this routine 66 | // (or, when referring to a class, methods of this class) 67 | // concurrently. 68 | // thread-hostile: it is not safe for multiple threads to call this 69 | // routine (or methods of this class) concurrently. In gflags, 70 | // most thread-hostile routines are intended to be called early in, 71 | // or even before, main() -- that is, before threads are spawned. 72 | // thread-compatible: it is safe for multiple threads to read from 73 | // this variable (when applied to variables), or to call const 74 | // methods of this class (when applied to classes), as long as no 75 | // other thread is writing to the variable or calling non-const 76 | // methods of this class. 77 | 78 | #ifndef GFLAGS_GFLAGS_H_ 79 | #define GFLAGS_GFLAGS_H_ 80 | 81 | #include 82 | #include 83 | 84 | #include "gflags_declare.h" // IWYU pragma: export 85 | 86 | 87 | // We always want to export variables defined in user code 88 | #ifndef GFLAGS_DLL_DEFINE_FLAG 89 | # ifdef _MSC_VER 90 | # define GFLAGS_DLL_DEFINE_FLAG __declspec(dllexport) 91 | # else 92 | # define GFLAGS_DLL_DEFINE_FLAG 93 | # endif 94 | #endif 95 | 96 | 97 | namespace GFLAGS_NAMESPACE { 98 | 99 | 100 | // -------------------------------------------------------------------- 101 | // To actually define a flag in a file, use DEFINE_bool, 102 | // DEFINE_string, etc. at the bottom of this file. You may also find 103 | // it useful to register a validator with the flag. This ensures that 104 | // when the flag is parsed from the commandline, or is later set via 105 | // SetCommandLineOption, we call the validation function. It is _not_ 106 | // called when you assign the value to the flag directly using the = operator. 107 | // 108 | // The validation function should return true if the flag value is valid, and 109 | // false otherwise. If the function returns false for the new setting of the 110 | // flag, the flag will retain its current value. If it returns false for the 111 | // default value, ParseCommandLineFlags() will die. 112 | // 113 | // This function is safe to call at global construct time (as in the 114 | // example below). 115 | // 116 | // Example use: 117 | // static bool ValidatePort(const char* flagname, int32 value) { 118 | // if (value > 0 && value < 32768) // value is ok 119 | // return true; 120 | // printf("Invalid value for --%s: %d\n", flagname, (int)value); 121 | // return false; 122 | // } 123 | // DEFINE_int32(port, 0, "What port to listen on"); 124 | // static bool dummy = RegisterFlagValidator(&FLAGS_port, &ValidatePort); 125 | 126 | // Returns true if successfully registered, false if not (because the 127 | // first argument doesn't point to a command-line flag, or because a 128 | // validator is already registered for this flag). 129 | extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const bool* flag, bool (*validate_fn)(const char*, bool)); 130 | extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const int32* flag, bool (*validate_fn)(const char*, int32)); 131 | extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const int64* flag, bool (*validate_fn)(const char*, int64)); 132 | extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const uint64* flag, bool (*validate_fn)(const char*, uint64)); 133 | extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const double* flag, bool (*validate_fn)(const char*, double)); 134 | extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const std::string* flag, bool (*validate_fn)(const char*, const std::string&)); 135 | 136 | // Convenience macro for the registration of a flag validator 137 | #define DEFINE_validator(name, validator) \ 138 | static const bool name##_validator_registered = \ 139 | GFLAGS_NAMESPACE::RegisterFlagValidator(&FLAGS_##name, validator) 140 | 141 | 142 | // -------------------------------------------------------------------- 143 | // These methods are the best way to get access to info about the 144 | // list of commandline flags. Note that these routines are pretty slow. 145 | // GetAllFlags: mostly-complete info about the list, sorted by file. 146 | // ShowUsageWithFlags: pretty-prints the list to stdout (what --help does) 147 | // ShowUsageWithFlagsRestrict: limit to filenames with restrict as a substr 148 | // 149 | // In addition to accessing flags, you can also access argv[0] (the program 150 | // name) and argv (the entire commandline), which we sock away a copy of. 151 | // These variables are static, so you should only set them once. 152 | // 153 | // No need to export this data only structure from DLL, avoiding VS warning 4251. 154 | struct CommandLineFlagInfo { 155 | std::string name; // the name of the flag 156 | std::string type; // the type of the flag: int32, etc 157 | std::string description; // the "help text" associated with the flag 158 | std::string current_value; // the current value, as a string 159 | std::string default_value; // the default value, as a string 160 | std::string filename; // 'cleaned' version of filename holding the flag 161 | bool has_validator_fn; // true if RegisterFlagValidator called on this flag 162 | bool is_default; // true if the flag has the default value and 163 | // has not been set explicitly from the cmdline 164 | // or via SetCommandLineOption 165 | const void* flag_ptr; // pointer to the flag's current value (i.e. FLAGS_foo) 166 | }; 167 | 168 | // Using this inside of a validator is a recipe for a deadlock. 169 | // TODO(user) Fix locking when validators are running, to make it safe to 170 | // call validators during ParseAllFlags. 171 | // Also make sure then to uncomment the corresponding unit test in 172 | // gflags_unittest.sh 173 | extern GFLAGS_DLL_DECL void GetAllFlags(std::vector* OUTPUT); 174 | // These two are actually defined in gflags_reporting.cc. 175 | extern GFLAGS_DLL_DECL void ShowUsageWithFlags(const char *argv0); // what --help does 176 | extern GFLAGS_DLL_DECL void ShowUsageWithFlagsRestrict(const char *argv0, const char *restrict); 177 | 178 | // Create a descriptive string for a flag. 179 | // Goes to some trouble to make pretty line breaks. 180 | extern GFLAGS_DLL_DECL std::string DescribeOneFlag(const CommandLineFlagInfo& flag); 181 | 182 | // Thread-hostile; meant to be called before any threads are spawned. 183 | extern GFLAGS_DLL_DECL void SetArgv(int argc, const char** argv); 184 | 185 | // The following functions are thread-safe as long as SetArgv() is 186 | // only called before any threads start. 187 | extern GFLAGS_DLL_DECL const std::vector& GetArgvs(); 188 | extern GFLAGS_DLL_DECL const char* GetArgv(); // all of argv as a string 189 | extern GFLAGS_DLL_DECL const char* GetArgv0(); // only argv0 190 | extern GFLAGS_DLL_DECL uint32 GetArgvSum(); // simple checksum of argv 191 | extern GFLAGS_DLL_DECL const char* ProgramInvocationName(); // argv0, or "UNKNOWN" if not set 192 | extern GFLAGS_DLL_DECL const char* ProgramInvocationShortName(); // basename(argv0) 193 | 194 | // ProgramUsage() is thread-safe as long as SetUsageMessage() is only 195 | // called before any threads start. 196 | extern GFLAGS_DLL_DECL const char* ProgramUsage(); // string set by SetUsageMessage() 197 | 198 | // VersionString() is thread-safe as long as SetVersionString() is only 199 | // called before any threads start. 200 | extern GFLAGS_DLL_DECL const char* VersionString(); // string set by SetVersionString() 201 | 202 | 203 | 204 | // -------------------------------------------------------------------- 205 | // Normally you access commandline flags by just saying "if (FLAGS_foo)" 206 | // or whatever, and set them by calling "FLAGS_foo = bar" (or, more 207 | // commonly, via the DEFINE_foo macro). But if you need a bit more 208 | // control, we have programmatic ways to get/set the flags as well. 209 | // These programmatic ways to access flags are thread-safe, but direct 210 | // access is only thread-compatible. 211 | 212 | // Return true iff the flagname was found. 213 | // OUTPUT is set to the flag's value, or unchanged if we return false. 214 | extern GFLAGS_DLL_DECL bool GetCommandLineOption(const char* name, std::string* OUTPUT); 215 | 216 | // Return true iff the flagname was found. OUTPUT is set to the flag's 217 | // CommandLineFlagInfo or unchanged if we return false. 218 | extern GFLAGS_DLL_DECL bool GetCommandLineFlagInfo(const char* name, CommandLineFlagInfo* OUTPUT); 219 | 220 | // Return the CommandLineFlagInfo of the flagname. exit() if name not found. 221 | // Example usage, to check if a flag's value is currently the default value: 222 | // if (GetCommandLineFlagInfoOrDie("foo").is_default) ... 223 | extern GFLAGS_DLL_DECL CommandLineFlagInfo GetCommandLineFlagInfoOrDie(const char* name); 224 | 225 | enum GFLAGS_DLL_DECL FlagSettingMode { 226 | // update the flag's value (can call this multiple times). 227 | SET_FLAGS_VALUE, 228 | // update the flag's value, but *only if* it has not yet been updated 229 | // with SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef". 230 | SET_FLAG_IF_DEFAULT, 231 | // set the flag's default value to this. If the flag has not yet updated 232 | // yet (via SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef") 233 | // change the flag's current value to the new default value as well. 234 | SET_FLAGS_DEFAULT 235 | }; 236 | 237 | // Set a particular flag ("command line option"). Returns a string 238 | // describing the new value that the option has been set to. The 239 | // return value API is not well-specified, so basically just depend on 240 | // it to be empty if the setting failed for some reason -- the name is 241 | // not a valid flag name, or the value is not a valid value -- and 242 | // non-empty else. 243 | 244 | // SetCommandLineOption uses set_mode == SET_FLAGS_VALUE (the common case) 245 | extern GFLAGS_DLL_DECL std::string SetCommandLineOption (const char* name, const char* value); 246 | extern GFLAGS_DLL_DECL std::string SetCommandLineOptionWithMode(const char* name, const char* value, FlagSettingMode set_mode); 247 | 248 | 249 | // -------------------------------------------------------------------- 250 | // Saves the states (value, default value, whether the user has set 251 | // the flag, registered validators, etc) of all flags, and restores 252 | // them when the FlagSaver is destroyed. This is very useful in 253 | // tests, say, when you want to let your tests change the flags, but 254 | // make sure that they get reverted to the original states when your 255 | // test is complete. 256 | // 257 | // Example usage: 258 | // void TestFoo() { 259 | // FlagSaver s1; 260 | // FLAG_foo = false; 261 | // FLAG_bar = "some value"; 262 | // 263 | // // test happens here. You can return at any time 264 | // // without worrying about restoring the FLAG values. 265 | // } 266 | // 267 | // Note: This class is marked with GFLAGS_ATTRIBUTE_UNUSED because all 268 | // the work is done in the constructor and destructor, so in the standard 269 | // usage example above, the compiler would complain that it's an 270 | // unused variable. 271 | // 272 | // This class is thread-safe. However, its destructor writes to 273 | // exactly the set of flags that have changed value during its 274 | // lifetime, so concurrent _direct_ access to those flags 275 | // (i.e. FLAGS_foo instead of {Get,Set}CommandLineOption()) is unsafe. 276 | 277 | class GFLAGS_DLL_DECL FlagSaver { 278 | public: 279 | FlagSaver(); 280 | ~FlagSaver(); 281 | 282 | private: 283 | class FlagSaverImpl* impl_; // we use pimpl here to keep API steady 284 | 285 | FlagSaver(const FlagSaver&); // no copying! 286 | void operator=(const FlagSaver&); 287 | }; 288 | 289 | // -------------------------------------------------------------------- 290 | // Some deprecated or hopefully-soon-to-be-deprecated functions. 291 | 292 | // This is often used for logging. TODO(csilvers): figure out a better way 293 | extern GFLAGS_DLL_DECL std::string CommandlineFlagsIntoString(); 294 | // Usually where this is used, a FlagSaver should be used instead. 295 | extern GFLAGS_DLL_DECL 296 | bool ReadFlagsFromString(const std::string& flagfilecontents, 297 | const char* prog_name, 298 | bool errors_are_fatal); // uses SET_FLAGS_VALUE 299 | 300 | // These let you manually implement --flagfile functionality. 301 | // DEPRECATED. 302 | extern GFLAGS_DLL_DECL bool AppendFlagsIntoFile(const std::string& filename, const char* prog_name); 303 | extern GFLAGS_DLL_DECL bool ReadFromFlagsFile(const std::string& filename, const char* prog_name, bool errors_are_fatal); // uses SET_FLAGS_VALUE 304 | 305 | 306 | // -------------------------------------------------------------------- 307 | // Useful routines for initializing flags from the environment. 308 | // In each case, if 'varname' does not exist in the environment 309 | // return defval. If 'varname' does exist but is not valid 310 | // (e.g., not a number for an int32 flag), abort with an error. 311 | // Otherwise, return the value. NOTE: for booleans, for true use 312 | // 't' or 'T' or 'true' or '1', for false 'f' or 'F' or 'false' or '0'. 313 | 314 | extern GFLAGS_DLL_DECL bool BoolFromEnv(const char *varname, bool defval); 315 | extern GFLAGS_DLL_DECL int32 Int32FromEnv(const char *varname, int32 defval); 316 | extern GFLAGS_DLL_DECL int64 Int64FromEnv(const char *varname, int64 defval); 317 | extern GFLAGS_DLL_DECL uint64 Uint64FromEnv(const char *varname, uint64 defval); 318 | extern GFLAGS_DLL_DECL double DoubleFromEnv(const char *varname, double defval); 319 | extern GFLAGS_DLL_DECL const char *StringFromEnv(const char *varname, const char *defval); 320 | 321 | 322 | // -------------------------------------------------------------------- 323 | // The next two functions parse gflags from main(): 324 | 325 | // Set the "usage" message for this program. For example: 326 | // string usage("This program does nothing. Sample usage:\n"); 327 | // usage += argv[0] + " "; 328 | // SetUsageMessage(usage); 329 | // Do not include commandline flags in the usage: we do that for you! 330 | // Thread-hostile; meant to be called before any threads are spawned. 331 | extern GFLAGS_DLL_DECL void SetUsageMessage(const std::string& usage); 332 | 333 | // Sets the version string, which is emitted with --version. 334 | // For instance: SetVersionString("1.3"); 335 | // Thread-hostile; meant to be called before any threads are spawned. 336 | extern GFLAGS_DLL_DECL void SetVersionString(const std::string& version); 337 | 338 | 339 | // Looks for flags in argv and parses them. Rearranges argv to put 340 | // flags first, or removes them entirely if remove_flags is true. 341 | // If a flag is defined more than once in the command line or flag 342 | // file, the last definition is used. Returns the index (into argv) 343 | // of the first non-flag argument. 344 | // See top-of-file for more details on this function. 345 | #ifndef SWIG // In swig, use ParseCommandLineFlagsScript() instead. 346 | extern GFLAGS_DLL_DECL uint32 ParseCommandLineFlags(int *argc, char*** argv, bool remove_flags); 347 | #endif 348 | 349 | 350 | // Calls to ParseCommandLineNonHelpFlags and then to 351 | // HandleCommandLineHelpFlags can be used instead of a call to 352 | // ParseCommandLineFlags during initialization, in order to allow for 353 | // changing default values for some FLAGS (via 354 | // e.g. SetCommandLineOptionWithMode calls) between the time of 355 | // command line parsing and the time of dumping help information for 356 | // the flags as a result of command line parsing. If a flag is 357 | // defined more than once in the command line or flag file, the last 358 | // definition is used. Returns the index (into argv) of the first 359 | // non-flag argument. (If remove_flags is true, will always return 1.) 360 | extern GFLAGS_DLL_DECL uint32 ParseCommandLineNonHelpFlags(int *argc, char*** argv, bool remove_flags); 361 | 362 | // This is actually defined in gflags_reporting.cc. 363 | // This function is misnamed (it also handles --version, etc.), but 364 | // it's too late to change that now. :-( 365 | extern GFLAGS_DLL_DECL void HandleCommandLineHelpFlags(); // in gflags_reporting.cc 366 | 367 | // Allow command line reparsing. Disables the error normally 368 | // generated when an unknown flag is found, since it may be found in a 369 | // later parse. Thread-hostile; meant to be called before any threads 370 | // are spawned. 371 | extern GFLAGS_DLL_DECL void AllowCommandLineReparsing(); 372 | 373 | // Reparse the flags that have not yet been recognized. Only flags 374 | // registered since the last parse will be recognized. Any flag value 375 | // must be provided as part of the argument using "=", not as a 376 | // separate command line argument that follows the flag argument. 377 | // Intended for handling flags from dynamically loaded libraries, 378 | // since their flags are not registered until they are loaded. 379 | extern GFLAGS_DLL_DECL void ReparseCommandLineNonHelpFlags(); 380 | 381 | // Clean up memory allocated by flags. This is only needed to reduce 382 | // the quantity of "potentially leaked" reports emitted by memory 383 | // debugging tools such as valgrind. It is not required for normal 384 | // operation, or for the google perftools heap-checker. It must only 385 | // be called when the process is about to exit, and all threads that 386 | // might access flags are quiescent. Referencing flags after this is 387 | // called will have unexpected consequences. This is not safe to run 388 | // when multiple threads might be running: the function is 389 | // thread-hostile. 390 | extern GFLAGS_DLL_DECL void ShutDownCommandLineFlags(); 391 | 392 | 393 | // -------------------------------------------------------------------- 394 | // Now come the command line flag declaration/definition macros that 395 | // will actually be used. They're kind of hairy. A major reason 396 | // for this is initialization: we want people to be able to access 397 | // variables in global constructors and have that not crash, even if 398 | // their global constructor runs before the global constructor here. 399 | // (Obviously, we can't guarantee the flags will have the correct 400 | // default value in that case, but at least accessing them is safe.) 401 | // The only way to do that is have flags point to a static buffer. 402 | // So we make one, using a union to ensure proper alignment, and 403 | // then use placement-new to actually set up the flag with the 404 | // correct default value. In the same vein, we have to worry about 405 | // flag access in global destructors, so FlagRegisterer has to be 406 | // careful never to destroy the flag-values it constructs. 407 | // 408 | // Note that when we define a flag variable FLAGS_, we also 409 | // preemptively define a junk variable, FLAGS_no. This is to 410 | // cause a link-time error if someone tries to define 2 flags with 411 | // names like "logging" and "nologging". We do this because a bool 412 | // flag FLAG can be set from the command line to true with a "-FLAG" 413 | // argument, and to false with a "-noFLAG" argument, and so this can 414 | // potentially avert confusion. 415 | // 416 | // We also put flags into their own namespace. It is purposefully 417 | // named in an opaque way that people should have trouble typing 418 | // directly. The idea is that DEFINE puts the flag in the weird 419 | // namespace, and DECLARE imports the flag from there into the current 420 | // namespace. The net result is to force people to use DECLARE to get 421 | // access to a flag, rather than saying "extern GFLAGS_DLL_DECL bool FLAGS_whatever;" 422 | // or some such instead. We want this so we can put extra 423 | // functionality (like sanity-checking) in DECLARE if we want, and 424 | // make sure it is picked up everywhere. 425 | // 426 | // We also put the type of the variable in the namespace, so that 427 | // people can't DECLARE_int32 something that they DEFINE_bool'd 428 | // elsewhere. 429 | 430 | class GFLAGS_DLL_DECL FlagRegisterer { 431 | public: 432 | FlagRegisterer(const char* name, const char* type, 433 | const char* help, const char* filename, 434 | void* current_storage, void* defvalue_storage); 435 | }; 436 | 437 | // If your application #defines STRIP_FLAG_HELP to a non-zero value 438 | // before #including this file, we remove the help message from the 439 | // binary file. This can reduce the size of the resulting binary 440 | // somewhat, and may also be useful for security reasons. 441 | 442 | extern GFLAGS_DLL_DECL const char kStrippedFlagHelp[]; 443 | 444 | 445 | } // namespace GFLAGS_NAMESPACE 446 | 447 | 448 | #ifndef SWIG // In swig, ignore the main flag declarations 449 | 450 | #if defined(STRIP_FLAG_HELP) && STRIP_FLAG_HELP > 0 451 | // Need this construct to avoid the 'defined but not used' warning. 452 | #define MAYBE_STRIPPED_HELP(txt) \ 453 | (false ? (txt) : GFLAGS_NAMESPACE::kStrippedFlagHelp) 454 | #else 455 | #define MAYBE_STRIPPED_HELP(txt) txt 456 | #endif 457 | 458 | // Each command-line flag has two variables associated with it: one 459 | // with the current value, and one with the default value. However, 460 | // we have a third variable, which is where value is assigned; it's a 461 | // constant. This guarantees that FLAG_##value is initialized at 462 | // static initialization time (e.g. before program-start) rather than 463 | // than global construction time (which is after program-start but 464 | // before main), at least when 'value' is a compile-time constant. We 465 | // use a small trick for the "default value" variable, and call it 466 | // FLAGS_no. This serves the second purpose of assuring a 467 | // compile error if someone tries to define a flag named no 468 | // which is illegal (--foo and --nofoo both affect the "foo" flag). 469 | #define DEFINE_VARIABLE(type, shorttype, name, value, help) \ 470 | namespace fL##shorttype { \ 471 | static const type FLAGS_nono##name = value; \ 472 | /* We always want to export defined variables, dll or no */ \ 473 | GFLAGS_DLL_DEFINE_FLAG type FLAGS_##name = FLAGS_nono##name; \ 474 | type FLAGS_no##name = FLAGS_nono##name; \ 475 | static GFLAGS_NAMESPACE::FlagRegisterer o_##name( \ 476 | #name, #type, MAYBE_STRIPPED_HELP(help), __FILE__, \ 477 | &FLAGS_##name, &FLAGS_no##name); \ 478 | } \ 479 | using fL##shorttype::FLAGS_##name 480 | 481 | // For DEFINE_bool, we want to do the extra check that the passed-in 482 | // value is actually a bool, and not a string or something that can be 483 | // coerced to a bool. These declarations (no definition needed!) will 484 | // help us do that, and never evaluate From, which is important. 485 | // We'll use 'sizeof(IsBool(val))' to distinguish. This code requires 486 | // that the compiler have different sizes for bool & double. Since 487 | // this is not guaranteed by the standard, we check it with a 488 | // COMPILE_ASSERT. 489 | namespace fLB { 490 | struct CompileAssert {}; 491 | typedef CompileAssert expected_sizeof_double_neq_sizeof_bool[ 492 | (sizeof(double) != sizeof(bool)) ? 1 : -1]; 493 | template double GFLAGS_DLL_DECL IsBoolFlag(const From& from); 494 | GFLAGS_DLL_DECL bool IsBoolFlag(bool from); 495 | } // namespace fLB 496 | 497 | // Here are the actual DEFINE_*-macros. The respective DECLARE_*-macros 498 | // are in a separate include, gflags_declare.h, for reducing 499 | // the physical transitive size for DECLARE use. 500 | #define DEFINE_bool(name, val, txt) \ 501 | namespace fLB { \ 502 | typedef ::fLB::CompileAssert FLAG_##name##_value_is_not_a_bool[ \ 503 | (sizeof(::fLB::IsBoolFlag(val)) != sizeof(double))? 1: -1]; \ 504 | } \ 505 | DEFINE_VARIABLE(bool, B, name, val, txt) 506 | 507 | #define DEFINE_int32(name, val, txt) \ 508 | DEFINE_VARIABLE(GFLAGS_NAMESPACE::int32, I, \ 509 | name, val, txt) 510 | 511 | #define DEFINE_int64(name, val, txt) \ 512 | DEFINE_VARIABLE(GFLAGS_NAMESPACE::int64, I64, \ 513 | name, val, txt) 514 | 515 | #define DEFINE_uint64(name,val, txt) \ 516 | DEFINE_VARIABLE(GFLAGS_NAMESPACE::uint64, U64, \ 517 | name, val, txt) 518 | 519 | #define DEFINE_double(name, val, txt) \ 520 | DEFINE_VARIABLE(double, D, name, val, txt) 521 | 522 | // Strings are trickier, because they're not a POD, so we can't 523 | // construct them at static-initialization time (instead they get 524 | // constructed at global-constructor time, which is much later). To 525 | // try to avoid crashes in that case, we use a char buffer to store 526 | // the string, which we can static-initialize, and then placement-new 527 | // into it later. It's not perfect, but the best we can do. 528 | 529 | namespace fLS { 530 | 531 | inline clstring* dont_pass0toDEFINE_string(char *stringspot, 532 | const char *value) { 533 | return new(stringspot) clstring(value); 534 | } 535 | inline clstring* dont_pass0toDEFINE_string(char *stringspot, 536 | const clstring &value) { 537 | return new(stringspot) clstring(value); 538 | } 539 | inline clstring* dont_pass0toDEFINE_string(char *stringspot, 540 | int value); 541 | } // namespace fLS 542 | 543 | // We need to define a var named FLAGS_no##name so people don't define 544 | // --string and --nostring. And we need a temporary place to put val 545 | // so we don't have to evaluate it twice. Two great needs that go 546 | // great together! 547 | // The weird 'using' + 'extern' inside the fLS namespace is to work around 548 | // an unknown compiler bug/issue with the gcc 4.2.1 on SUSE 10. See 549 | // http://code.google.com/p/google-gflags/issues/detail?id=20 550 | #define DEFINE_string(name, val, txt) \ 551 | namespace fLS { \ 552 | using ::fLS::clstring; \ 553 | static union { void* align; char s[sizeof(clstring)]; } s_##name[2]; \ 554 | clstring* const FLAGS_no##name = ::fLS:: \ 555 | dont_pass0toDEFINE_string(s_##name[0].s, \ 556 | val); \ 557 | static GFLAGS_NAMESPACE::FlagRegisterer o_##name( \ 558 | #name, "string", MAYBE_STRIPPED_HELP(txt), __FILE__, \ 559 | s_##name[0].s, new (s_##name[1].s) clstring(*FLAGS_no##name)); \ 560 | extern GFLAGS_DLL_DEFINE_FLAG clstring& FLAGS_##name; \ 561 | using fLS::FLAGS_##name; \ 562 | clstring& FLAGS_##name = *FLAGS_no##name; \ 563 | } \ 564 | using fLS::FLAGS_##name 565 | 566 | #endif // SWIG 567 | 568 | 569 | // Import gflags library symbols into alternative/deprecated namespace(s) 570 | #include "gflags_gflags.h" 571 | 572 | 573 | #endif // GFLAGS_GFLAGS_H_ 574 | -------------------------------------------------------------------------------- /src/gflags_completions.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2008, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // --- 31 | 32 | // Bash-style command line flag completion for C++ binaries 33 | // 34 | // This module implements bash-style completions. It achieves this 35 | // goal in the following broad chunks: 36 | // 37 | // 1) Take a to-be-completed word, and examine it for search hints 38 | // 2) Identify all potentially matching flags 39 | // 2a) If there are no matching flags, do nothing. 40 | // 2b) If all matching flags share a common prefix longer than the 41 | // completion word, output just that matching prefix 42 | // 3) Categorize those flags to produce a rough ordering of relevence. 43 | // 4) Potentially trim the set of flags returned to a smaller number 44 | // that bash is happier with 45 | // 5) Output the matching flags in groups ordered by relevence. 46 | // 5a) Force bash to place most-relevent groups at the top of the list 47 | // 5b) Trim most flag's descriptions to fit on a single terminal line 48 | 49 | 50 | #include "config.h" 51 | 52 | #include 53 | #include 54 | #include // for strlen 55 | 56 | #include 57 | #include 58 | #include 59 | #include 60 | 61 | #include "gflags.h" 62 | #include "util.h" 63 | 64 | using std::set; 65 | using std::string; 66 | using std::vector; 67 | 68 | 69 | DEFINE_string(tab_completion_word, "", 70 | "If non-empty, HandleCommandLineCompletions() will hijack the " 71 | "process and attempt to do bash-style command line flag " 72 | "completion on this value."); 73 | DEFINE_int32(tab_completion_columns, 80, 74 | "Number of columns to use in output for tab completion"); 75 | 76 | 77 | namespace GFLAGS_NAMESPACE { 78 | 79 | 80 | namespace { 81 | // Function prototypes and Type forward declarations. Code may be 82 | // more easily understood if it is roughly ordered according to 83 | // control flow, rather than by C's "declare before use" ordering 84 | struct CompletionOptions; 85 | struct NotableFlags; 86 | 87 | // The entry point if flag completion is to be used. 88 | static void PrintFlagCompletionInfo(void); 89 | 90 | 91 | // 1) Examine search word 92 | static void CanonicalizeCursorWordAndSearchOptions( 93 | const string &cursor_word, 94 | string *canonical_search_token, 95 | CompletionOptions *options); 96 | 97 | static bool RemoveTrailingChar(string *str, char c); 98 | 99 | 100 | // 2) Find all matches 101 | static void FindMatchingFlags( 102 | const vector &all_flags, 103 | const CompletionOptions &options, 104 | const string &match_token, 105 | set *all_matches, 106 | string *longest_common_prefix); 107 | 108 | static bool DoesSingleFlagMatch( 109 | const CommandLineFlagInfo &flag, 110 | const CompletionOptions &options, 111 | const string &match_token); 112 | 113 | 114 | // 3) Categorize matches 115 | static void CategorizeAllMatchingFlags( 116 | const set &all_matches, 117 | const string &search_token, 118 | const string &module, 119 | const string &package_dir, 120 | NotableFlags *notable_flags); 121 | 122 | static void TryFindModuleAndPackageDir( 123 | const vector all_flags, 124 | string *module, 125 | string *package_dir); 126 | 127 | 128 | // 4) Decide which flags to use 129 | static void FinalizeCompletionOutput( 130 | const set &matching_flags, 131 | CompletionOptions *options, 132 | NotableFlags *notable_flags, 133 | vector *completions); 134 | 135 | static void RetrieveUnusedFlags( 136 | const set &matching_flags, 137 | const NotableFlags ¬able_flags, 138 | set *unused_flags); 139 | 140 | 141 | // 5) Output matches 142 | static void OutputSingleGroupWithLimit( 143 | const set &group, 144 | const string &line_indentation, 145 | const string &header, 146 | const string &footer, 147 | bool long_output_format, 148 | int *remaining_line_limit, 149 | size_t *completion_elements_added, 150 | vector *completions); 151 | 152 | // (helpers for #5) 153 | static string GetShortFlagLine( 154 | const string &line_indentation, 155 | const CommandLineFlagInfo &info); 156 | 157 | static string GetLongFlagLine( 158 | const string &line_indentation, 159 | const CommandLineFlagInfo &info); 160 | 161 | 162 | // 163 | // Useful types 164 | 165 | // Try to deduce the intentions behind this completion attempt. Return the 166 | // canonical search term in 'canonical_search_token'. Binary search options 167 | // are returned in the various booleans, which should all have intuitive 168 | // semantics, possibly except: 169 | // - return_all_matching_flags: Generally, we'll trim the number of 170 | // returned candidates to some small number, showing those that are 171 | // most likely to be useful first. If this is set, however, the user 172 | // really does want us to return every single flag as an option. 173 | // - force_no_update: Any time we output lines, all of which share a 174 | // common prefix, bash will 'helpfully' not even bother to show the 175 | // output, instead changing the current word to be that common prefix. 176 | // If it's clear this shouldn't happen, we'll set this boolean 177 | struct CompletionOptions { 178 | bool flag_name_substring_search; 179 | bool flag_location_substring_search; 180 | bool flag_description_substring_search; 181 | bool return_all_matching_flags; 182 | bool force_no_update; 183 | }; 184 | 185 | // Notable flags are flags that are special or preferred for some 186 | // reason. For example, flags that are defined in the binary's module 187 | // are expected to be much more relevent than flags defined in some 188 | // other random location. These sets are specified roughly in precedence 189 | // order. Once a flag is placed in one of these 'higher' sets, it won't 190 | // be placed in any of the 'lower' sets. 191 | struct NotableFlags { 192 | typedef set FlagSet; 193 | FlagSet perfect_match_flag; 194 | FlagSet module_flags; // Found in module file 195 | FlagSet package_flags; // Found in same directory as module file 196 | FlagSet most_common_flags; // One of the XXX most commonly supplied flags 197 | FlagSet subpackage_flags; // Found in subdirectories of package 198 | }; 199 | 200 | 201 | // 202 | // Tab completion implementation - entry point 203 | static void PrintFlagCompletionInfo(void) { 204 | string cursor_word = FLAGS_tab_completion_word; 205 | string canonical_token; 206 | CompletionOptions options = { }; 207 | CanonicalizeCursorWordAndSearchOptions( 208 | cursor_word, 209 | &canonical_token, 210 | &options); 211 | 212 | DVLOG(1) << "Identified canonical_token: '" << canonical_token << "'"; 213 | 214 | vector all_flags; 215 | set matching_flags; 216 | GetAllFlags(&all_flags); 217 | DVLOG(2) << "Found " << all_flags.size() << " flags overall"; 218 | 219 | string longest_common_prefix; 220 | FindMatchingFlags( 221 | all_flags, 222 | options, 223 | canonical_token, 224 | &matching_flags, 225 | &longest_common_prefix); 226 | DVLOG(1) << "Identified " << matching_flags.size() << " matching flags"; 227 | DVLOG(1) << "Identified " << longest_common_prefix 228 | << " as longest common prefix."; 229 | if (longest_common_prefix.size() > canonical_token.size()) { 230 | // There's actually a shared common prefix to all matching flags, 231 | // so may as well output that and quit quickly. 232 | DVLOG(1) << "The common prefix '" << longest_common_prefix 233 | << "' was longer than the token '" << canonical_token 234 | << "'. Returning just this prefix for completion."; 235 | fprintf(stdout, "--%s", longest_common_prefix.c_str()); 236 | return; 237 | } 238 | if (matching_flags.empty()) { 239 | VLOG(1) << "There were no matching flags, returning nothing."; 240 | return; 241 | } 242 | 243 | string module; 244 | string package_dir; 245 | TryFindModuleAndPackageDir(all_flags, &module, &package_dir); 246 | DVLOG(1) << "Identified module: '" << module << "'"; 247 | DVLOG(1) << "Identified package_dir: '" << package_dir << "'"; 248 | 249 | NotableFlags notable_flags; 250 | CategorizeAllMatchingFlags( 251 | matching_flags, 252 | canonical_token, 253 | module, 254 | package_dir, 255 | ¬able_flags); 256 | DVLOG(2) << "Categorized matching flags:"; 257 | DVLOG(2) << " perfect_match: " << notable_flags.perfect_match_flag.size(); 258 | DVLOG(2) << " module: " << notable_flags.module_flags.size(); 259 | DVLOG(2) << " package: " << notable_flags.package_flags.size(); 260 | DVLOG(2) << " most common: " << notable_flags.most_common_flags.size(); 261 | DVLOG(2) << " subpackage: " << notable_flags.subpackage_flags.size(); 262 | 263 | vector completions; 264 | FinalizeCompletionOutput( 265 | matching_flags, 266 | &options, 267 | ¬able_flags, 268 | &completions); 269 | 270 | if (options.force_no_update) 271 | completions.push_back("~"); 272 | 273 | DVLOG(1) << "Finalized with " << completions.size() 274 | << " chosen completions"; 275 | 276 | for (vector::const_iterator it = completions.begin(); 277 | it != completions.end(); 278 | ++it) { 279 | DVLOG(9) << " Completion entry: '" << *it << "'"; 280 | fprintf(stdout, "%s\n", it->c_str()); 281 | } 282 | } 283 | 284 | 285 | // 1) Examine search word (and helper method) 286 | static void CanonicalizeCursorWordAndSearchOptions( 287 | const string &cursor_word, 288 | string *canonical_search_token, 289 | CompletionOptions *options) { 290 | *canonical_search_token = cursor_word; 291 | if (canonical_search_token->empty()) return; 292 | 293 | // Get rid of leading quotes and dashes in the search term 294 | if ((*canonical_search_token)[0] == '"') 295 | *canonical_search_token = canonical_search_token->substr(1); 296 | while ((*canonical_search_token)[0] == '-') 297 | *canonical_search_token = canonical_search_token->substr(1); 298 | 299 | options->flag_name_substring_search = false; 300 | options->flag_location_substring_search = false; 301 | options->flag_description_substring_search = false; 302 | options->return_all_matching_flags = false; 303 | options->force_no_update = false; 304 | 305 | // Look for all search options we can deduce now. Do this by walking 306 | // backwards through the term, looking for up to three '?' and up to 307 | // one '+' as suffixed characters. Consume them if found, and remove 308 | // them from the canonical search token. 309 | int found_question_marks = 0; 310 | int found_plusses = 0; 311 | while (true) { 312 | if (found_question_marks < 3 && 313 | RemoveTrailingChar(canonical_search_token, '?')) { 314 | ++found_question_marks; 315 | continue; 316 | } 317 | if (found_plusses < 1 && 318 | RemoveTrailingChar(canonical_search_token, '+')) { 319 | ++found_plusses; 320 | continue; 321 | } 322 | break; 323 | } 324 | 325 | switch (found_question_marks) { // all fallthroughs 326 | case 3: options->flag_description_substring_search = true; 327 | case 2: options->flag_location_substring_search = true; 328 | case 1: options->flag_name_substring_search = true; 329 | }; 330 | 331 | options->return_all_matching_flags = (found_plusses > 0); 332 | } 333 | 334 | // Returns true if a char was removed 335 | static bool RemoveTrailingChar(string *str, char c) { 336 | if (str->empty()) return false; 337 | if ((*str)[str->size() - 1] == c) { 338 | *str = str->substr(0, str->size() - 1); 339 | return true; 340 | } 341 | return false; 342 | } 343 | 344 | 345 | // 2) Find all matches (and helper methods) 346 | static void FindMatchingFlags( 347 | const vector &all_flags, 348 | const CompletionOptions &options, 349 | const string &match_token, 350 | set *all_matches, 351 | string *longest_common_prefix) { 352 | all_matches->clear(); 353 | bool first_match = true; 354 | for (vector::const_iterator it = all_flags.begin(); 355 | it != all_flags.end(); 356 | ++it) { 357 | if (DoesSingleFlagMatch(*it, options, match_token)) { 358 | all_matches->insert(&*it); 359 | if (first_match) { 360 | first_match = false; 361 | *longest_common_prefix = it->name; 362 | } else { 363 | if (longest_common_prefix->empty() || it->name.empty()) { 364 | longest_common_prefix->clear(); 365 | continue; 366 | } 367 | string::size_type pos = 0; 368 | while (pos < longest_common_prefix->size() && 369 | pos < it->name.size() && 370 | (*longest_common_prefix)[pos] == it->name[pos]) 371 | ++pos; 372 | longest_common_prefix->erase(pos); 373 | } 374 | } 375 | } 376 | } 377 | 378 | // Given the set of all flags, the parsed match options, and the 379 | // canonical search token, produce the set of all candidate matching 380 | // flags for subsequent analysis or filtering. 381 | static bool DoesSingleFlagMatch( 382 | const CommandLineFlagInfo &flag, 383 | const CompletionOptions &options, 384 | const string &match_token) { 385 | // Is there a prefix match? 386 | string::size_type pos = flag.name.find(match_token); 387 | if (pos == 0) return true; 388 | 389 | // Is there a substring match if we want it? 390 | if (options.flag_name_substring_search && 391 | pos != string::npos) 392 | return true; 393 | 394 | // Is there a location match if we want it? 395 | if (options.flag_location_substring_search && 396 | flag.filename.find(match_token) != string::npos) 397 | return true; 398 | 399 | // TODO(user): All searches should probably be case-insensitive 400 | // (especially this one...) 401 | if (options.flag_description_substring_search && 402 | flag.description.find(match_token) != string::npos) 403 | return true; 404 | 405 | return false; 406 | } 407 | 408 | // 3) Categorize matches (and helper method) 409 | 410 | // Given a set of matching flags, categorize them by 411 | // likely relevence to this specific binary 412 | static void CategorizeAllMatchingFlags( 413 | const set &all_matches, 414 | const string &search_token, 415 | const string &module, // empty if we couldn't find any 416 | const string &package_dir, // empty if we couldn't find any 417 | NotableFlags *notable_flags) { 418 | notable_flags->perfect_match_flag.clear(); 419 | notable_flags->module_flags.clear(); 420 | notable_flags->package_flags.clear(); 421 | notable_flags->most_common_flags.clear(); 422 | notable_flags->subpackage_flags.clear(); 423 | 424 | for (set::const_iterator it = 425 | all_matches.begin(); 426 | it != all_matches.end(); 427 | ++it) { 428 | DVLOG(2) << "Examining match '" << (*it)->name << "'"; 429 | DVLOG(7) << " filename: '" << (*it)->filename << "'"; 430 | string::size_type pos = string::npos; 431 | if (!package_dir.empty()) 432 | pos = (*it)->filename.find(package_dir); 433 | string::size_type slash = string::npos; 434 | if (pos != string::npos) // candidate for package or subpackage match 435 | slash = (*it)->filename.find( 436 | PATH_SEPARATOR, 437 | pos + package_dir.size() + 1); 438 | 439 | if ((*it)->name == search_token) { 440 | // Exact match on some flag's name 441 | notable_flags->perfect_match_flag.insert(*it); 442 | DVLOG(3) << "Result: perfect match"; 443 | } else if (!module.empty() && (*it)->filename == module) { 444 | // Exact match on module filename 445 | notable_flags->module_flags.insert(*it); 446 | DVLOG(3) << "Result: module match"; 447 | } else if (!package_dir.empty() && 448 | pos != string::npos && slash == string::npos) { 449 | // In the package, since there was no slash after the package portion 450 | notable_flags->package_flags.insert(*it); 451 | DVLOG(3) << "Result: package match"; 452 | } else if (false) { 453 | // In the list of the XXX most commonly supplied flags overall 454 | // TODO(user): Compile this list. 455 | DVLOG(3) << "Result: most-common match"; 456 | } else if (!package_dir.empty() && 457 | pos != string::npos && slash != string::npos) { 458 | // In a subdirectory of the package 459 | notable_flags->subpackage_flags.insert(*it); 460 | DVLOG(3) << "Result: subpackage match"; 461 | } 462 | 463 | DVLOG(3) << "Result: not special match"; 464 | } 465 | } 466 | 467 | static void PushNameWithSuffix(vector* suffixes, const char* suffix) { 468 | suffixes->push_back( 469 | StringPrintf("/%s%s", ProgramInvocationShortName(), suffix)); 470 | } 471 | 472 | static void TryFindModuleAndPackageDir( 473 | const vector all_flags, 474 | string *module, 475 | string *package_dir) { 476 | module->clear(); 477 | package_dir->clear(); 478 | 479 | vector suffixes; 480 | // TODO(user): There's some inherant ambiguity here - multiple directories 481 | // could share the same trailing folder and file structure (and even worse, 482 | // same file names), causing us to be unsure as to which of the two is the 483 | // actual package for this binary. In this case, we'll arbitrarily choose. 484 | PushNameWithSuffix(&suffixes, "."); 485 | PushNameWithSuffix(&suffixes, "-main."); 486 | PushNameWithSuffix(&suffixes, "_main."); 487 | // These four are new but probably merited? 488 | PushNameWithSuffix(&suffixes, "-test."); 489 | PushNameWithSuffix(&suffixes, "_test."); 490 | PushNameWithSuffix(&suffixes, "-unittest."); 491 | PushNameWithSuffix(&suffixes, "_unittest."); 492 | 493 | for (vector::const_iterator it = all_flags.begin(); 494 | it != all_flags.end(); 495 | ++it) { 496 | for (vector::const_iterator suffix = suffixes.begin(); 497 | suffix != suffixes.end(); 498 | ++suffix) { 499 | // TODO(user): Make sure the match is near the end of the string 500 | if (it->filename.find(*suffix) != string::npos) { 501 | *module = it->filename; 502 | string::size_type sep = it->filename.rfind(PATH_SEPARATOR); 503 | *package_dir = it->filename.substr(0, (sep == string::npos) ? 0 : sep); 504 | return; 505 | } 506 | } 507 | } 508 | } 509 | 510 | // Can't specialize template type on a locally defined type. Silly C++... 511 | struct DisplayInfoGroup { 512 | const char* header; 513 | const char* footer; 514 | set *group; 515 | 516 | int SizeInLines() const { 517 | int size_in_lines = static_cast(group->size()) + 1; 518 | if (strlen(header) > 0) { 519 | size_in_lines++; 520 | } 521 | if (strlen(footer) > 0) { 522 | size_in_lines++; 523 | } 524 | return size_in_lines; 525 | } 526 | }; 527 | 528 | // 4) Finalize and trim output flag set 529 | static void FinalizeCompletionOutput( 530 | const set &matching_flags, 531 | CompletionOptions *options, 532 | NotableFlags *notable_flags, 533 | vector *completions) { 534 | 535 | // We want to output lines in groups. Each group needs to be indented 536 | // the same to keep its lines together. Unless otherwise required, 537 | // only 99 lines should be output to prevent bash from harassing the 538 | // user. 539 | 540 | // First, figure out which output groups we'll actually use. For each 541 | // nonempty group, there will be ~3 lines of header & footer, plus all 542 | // output lines themselves. 543 | int max_desired_lines = // "999999 flags should be enough for anyone. -dave" 544 | (options->return_all_matching_flags ? 999999 : 98); 545 | int lines_so_far = 0; 546 | 547 | vector output_groups; 548 | bool perfect_match_found = false; 549 | if (lines_so_far < max_desired_lines && 550 | !notable_flags->perfect_match_flag.empty()) { 551 | perfect_match_found = true; 552 | DisplayInfoGroup group = 553 | { "", 554 | "==========", 555 | ¬able_flags->perfect_match_flag }; 556 | lines_so_far += group.SizeInLines(); 557 | output_groups.push_back(group); 558 | } 559 | if (lines_so_far < max_desired_lines && 560 | !notable_flags->module_flags.empty()) { 561 | DisplayInfoGroup group = { 562 | "-* Matching module flags *-", 563 | "===========================", 564 | ¬able_flags->module_flags }; 565 | lines_so_far += group.SizeInLines(); 566 | output_groups.push_back(group); 567 | } 568 | if (lines_so_far < max_desired_lines && 569 | !notable_flags->package_flags.empty()) { 570 | DisplayInfoGroup group = { 571 | "-* Matching package flags *-", 572 | "============================", 573 | ¬able_flags->package_flags }; 574 | lines_so_far += group.SizeInLines(); 575 | output_groups.push_back(group); 576 | } 577 | if (lines_so_far < max_desired_lines && 578 | !notable_flags->most_common_flags.empty()) { 579 | DisplayInfoGroup group = { 580 | "-* Commonly used flags *-", 581 | "=========================", 582 | ¬able_flags->most_common_flags }; 583 | lines_so_far += group.SizeInLines(); 584 | output_groups.push_back(group); 585 | } 586 | if (lines_so_far < max_desired_lines && 587 | !notable_flags->subpackage_flags.empty()) { 588 | DisplayInfoGroup group = { 589 | "-* Matching sub-package flags *-", 590 | "================================", 591 | ¬able_flags->subpackage_flags }; 592 | lines_so_far += group.SizeInLines(); 593 | output_groups.push_back(group); 594 | } 595 | 596 | set obscure_flags; // flags not notable 597 | if (lines_so_far < max_desired_lines) { 598 | RetrieveUnusedFlags(matching_flags, *notable_flags, &obscure_flags); 599 | if (!obscure_flags.empty()) { 600 | DisplayInfoGroup group = { 601 | "-* Other flags *-", 602 | "", 603 | &obscure_flags }; 604 | lines_so_far += group.SizeInLines(); 605 | output_groups.push_back(group); 606 | } 607 | } 608 | 609 | // Second, go through each of the chosen output groups and output 610 | // as many of those flags as we can, while remaining below our limit 611 | int remaining_lines = max_desired_lines; 612 | size_t completions_output = 0; 613 | int indent = static_cast(output_groups.size()) - 1; 614 | for (vector::const_iterator it = 615 | output_groups.begin(); 616 | it != output_groups.end(); 617 | ++it, --indent) { 618 | OutputSingleGroupWithLimit( 619 | *it->group, // group 620 | string(indent, ' '), // line indentation 621 | string(it->header), // header 622 | string(it->footer), // footer 623 | perfect_match_found, // long format 624 | &remaining_lines, // line limit - reduces this by number printed 625 | &completions_output, // completions (not lines) added 626 | completions); // produced completions 627 | perfect_match_found = false; 628 | } 629 | 630 | if (completions_output != matching_flags.size()) { 631 | options->force_no_update = false; 632 | completions->push_back("~ (Remaining flags hidden) ~"); 633 | } else { 634 | options->force_no_update = true; 635 | } 636 | } 637 | 638 | static void RetrieveUnusedFlags( 639 | const set &matching_flags, 640 | const NotableFlags ¬able_flags, 641 | set *unused_flags) { 642 | // Remove from 'matching_flags' set all members of the sets of 643 | // flags we've already printed (specifically, those in notable_flags) 644 | for (set::const_iterator it = 645 | matching_flags.begin(); 646 | it != matching_flags.end(); 647 | ++it) { 648 | if (notable_flags.perfect_match_flag.count(*it) || 649 | notable_flags.module_flags.count(*it) || 650 | notable_flags.package_flags.count(*it) || 651 | notable_flags.most_common_flags.count(*it) || 652 | notable_flags.subpackage_flags.count(*it)) 653 | continue; 654 | unused_flags->insert(*it); 655 | } 656 | } 657 | 658 | // 5) Output matches (and helper methods) 659 | 660 | static void OutputSingleGroupWithLimit( 661 | const set &group, 662 | const string &line_indentation, 663 | const string &header, 664 | const string &footer, 665 | bool long_output_format, 666 | int *remaining_line_limit, 667 | size_t *completion_elements_output, 668 | vector *completions) { 669 | if (group.empty()) return; 670 | if (!header.empty()) { 671 | if (*remaining_line_limit < 2) return; 672 | *remaining_line_limit -= 2; 673 | completions->push_back(line_indentation + header); 674 | completions->push_back(line_indentation + string(header.size(), '-')); 675 | } 676 | for (set::const_iterator it = group.begin(); 677 | it != group.end() && *remaining_line_limit > 0; 678 | ++it) { 679 | --*remaining_line_limit; 680 | ++*completion_elements_output; 681 | completions->push_back( 682 | (long_output_format 683 | ? GetLongFlagLine(line_indentation, **it) 684 | : GetShortFlagLine(line_indentation, **it))); 685 | } 686 | if (!footer.empty()) { 687 | if (*remaining_line_limit < 1) return; 688 | --*remaining_line_limit; 689 | completions->push_back(line_indentation + footer); 690 | } 691 | } 692 | 693 | static string GetShortFlagLine( 694 | const string &line_indentation, 695 | const CommandLineFlagInfo &info) { 696 | string prefix; 697 | bool is_string = (info.type == "string"); 698 | SStringPrintf(&prefix, "%s--%s [%s%s%s] ", 699 | line_indentation.c_str(), 700 | info.name.c_str(), 701 | (is_string ? "'" : ""), 702 | info.default_value.c_str(), 703 | (is_string ? "'" : "")); 704 | int remainder = 705 | FLAGS_tab_completion_columns - static_cast(prefix.size()); 706 | string suffix; 707 | if (remainder > 0) 708 | suffix = 709 | (static_cast(info.description.size()) > remainder ? 710 | (info.description.substr(0, remainder - 3) + "...").c_str() : 711 | info.description.c_str()); 712 | return prefix + suffix; 713 | } 714 | 715 | static string GetLongFlagLine( 716 | const string &line_indentation, 717 | const CommandLineFlagInfo &info) { 718 | 719 | string output = DescribeOneFlag(info); 720 | 721 | // Replace '-' with '--', and remove trailing newline before appending 722 | // the module definition location. 723 | string old_flagname = "-" + info.name; 724 | output.replace( 725 | output.find(old_flagname), 726 | old_flagname.size(), 727 | "-" + old_flagname); 728 | // Stick a newline and indentation in front of the type and default 729 | // portions of DescribeOneFlag()s description 730 | static const char kNewlineWithIndent[] = "\n "; 731 | output.replace(output.find(" type:"), 1, string(kNewlineWithIndent)); 732 | output.replace(output.find(" default:"), 1, string(kNewlineWithIndent)); 733 | output = StringPrintf("%s Details for '--%s':\n" 734 | "%s defined: %s", 735 | line_indentation.c_str(), 736 | info.name.c_str(), 737 | output.c_str(), 738 | info.filename.c_str()); 739 | 740 | // Eliminate any doubled newlines that crept in. Specifically, if 741 | // DescribeOneFlag() decided to break the line just before "type" 742 | // or "default", we don't want to introduce an extra blank line 743 | static const string line_of_spaces(FLAGS_tab_completion_columns, ' '); 744 | static const char kDoubledNewlines[] = "\n \n"; 745 | for (string::size_type newlines = output.find(kDoubledNewlines); 746 | newlines != string::npos; 747 | newlines = output.find(kDoubledNewlines)) 748 | // Replace each 'doubled newline' with a single newline 749 | output.replace(newlines, sizeof(kDoubledNewlines) - 1, string("\n")); 750 | 751 | for (string::size_type newline = output.find('\n'); 752 | newline != string::npos; 753 | newline = output.find('\n')) { 754 | int newline_pos = static_cast(newline) % FLAGS_tab_completion_columns; 755 | int missing_spaces = FLAGS_tab_completion_columns - newline_pos; 756 | output.replace(newline, 1, line_of_spaces, 1, missing_spaces); 757 | } 758 | return output; 759 | } 760 | } // anonymous 761 | 762 | void HandleCommandLineCompletions(void) { 763 | if (FLAGS_tab_completion_word.empty()) return; 764 | PrintFlagCompletionInfo(); 765 | gflags_exitfunc(0); 766 | } 767 | 768 | 769 | } // namespace GFLAGS_NAMESPACE 770 | -------------------------------------------------------------------------------- /src/gflags.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 1999, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // --- 31 | // Revamped and reorganized by Craig Silverstein 32 | // 33 | // This file contains the implementation of all our command line flags 34 | // stuff. Here's how everything fits together 35 | // 36 | // * FlagRegistry owns CommandLineFlags owns FlagValue. 37 | // * FlagSaver holds a FlagRegistry (saves it at construct time, 38 | // restores it at destroy time). 39 | // * CommandLineFlagParser lives outside that hierarchy, but works on 40 | // CommandLineFlags (modifying the FlagValues). 41 | // * Free functions like SetCommandLineOption() work via one of the 42 | // above (such as CommandLineFlagParser). 43 | // 44 | // In more detail: 45 | // 46 | // -- The main classes that hold flag data: 47 | // 48 | // FlagValue holds the current value of a flag. It's 49 | // pseudo-templatized: every operation on a FlagValue is typed. It 50 | // also deals with storage-lifetime issues (so flag values don't go 51 | // away in a destructor), which is why we need a whole class to hold a 52 | // variable's value. 53 | // 54 | // CommandLineFlag is all the information about a single command-line 55 | // flag. It has a FlagValue for the flag's current value, but also 56 | // the flag's name, type, etc. 57 | // 58 | // FlagRegistry is a collection of CommandLineFlags. There's the 59 | // global registry, which is where flags defined via DEFINE_foo() 60 | // live. But it's possible to define your own flag, manually, in a 61 | // different registry you create. (In practice, multiple registries 62 | // are used only by FlagSaver). 63 | // 64 | // A given FlagValue is owned by exactly one CommandLineFlag. A given 65 | // CommandLineFlag is owned by exactly one FlagRegistry. FlagRegistry 66 | // has a lock; any operation that writes to a FlagValue or 67 | // CommandLineFlag owned by that registry must acquire the 68 | // FlagRegistry lock before doing so. 69 | // 70 | // --- Some other classes and free functions: 71 | // 72 | // CommandLineFlagInfo is a client-exposed version of CommandLineFlag. 73 | // Once it's instantiated, it has no dependencies or relationships 74 | // with any other part of this file. 75 | // 76 | // FlagRegisterer is the helper class used by the DEFINE_* macros to 77 | // allow work to be done at global initialization time. 78 | // 79 | // CommandLineFlagParser is the class that reads from the commandline 80 | // and instantiates flag values based on that. It needs to poke into 81 | // the innards of the FlagValue->CommandLineFlag->FlagRegistry class 82 | // hierarchy to do that. It's careful to acquire the FlagRegistry 83 | // lock before doing any writing or other non-const actions. 84 | // 85 | // GetCommandLineOption is just a hook into registry routines to 86 | // retrieve a flag based on its name. SetCommandLineOption, on the 87 | // other hand, hooks into CommandLineFlagParser. Other API functions 88 | // are, similarly, mostly hooks into the functionality described above. 89 | 90 | #include "config.h" 91 | #include "gflags.h" 92 | 93 | #include 94 | #include 95 | #include 96 | #if defined(HAVE_FNMATCH_H) 97 | # include 98 | #elif defined(HAVE_SHLWAPI_H) 99 | # include 100 | #endif 101 | #include // For va_list and related operations 102 | #include 103 | #include 104 | 105 | #include 106 | #include 107 | #include 108 | #include // for pair<> 109 | #include 110 | 111 | #include "mutex.h" 112 | #include "util.h" 113 | 114 | // Special flags, type 1: the 'recursive' flags. They set another flag's val. 115 | DEFINE_string(flagfile, "", "load flags from file"); 116 | DEFINE_string(fromenv, "", "set flags from the environment" 117 | " [use 'export FLAGS_flag1=value']"); 118 | DEFINE_string(tryfromenv, "", "set flags from the environment if present"); 119 | 120 | // Special flags, type 2: the 'parsing' flags. They modify how we parse. 121 | DEFINE_string(undefok, "", "comma-separated list of flag names that it is okay to specify " 122 | "on the command line even if the program does not define a flag " 123 | "with that name. IMPORTANT: flags in this list that have " 124 | "arguments MUST use the flag=value format"); 125 | 126 | namespace GFLAGS_NAMESPACE { 127 | 128 | using std::map; 129 | using std::pair; 130 | using std::sort; 131 | using std::string; 132 | using std::vector; 133 | 134 | // This is used by the unittest to test error-exit code 135 | void GFLAGS_DLL_DECL (*gflags_exitfunc)(int) = &exit; // from stdlib.h 136 | 137 | 138 | // The help message indicating that the commandline flag has been 139 | // 'stripped'. It will not show up when doing "-help" and its 140 | // variants. The flag is stripped if STRIP_FLAG_HELP is set to 1 141 | // before including base/gflags.h 142 | 143 | // This is used by this file, and also in gflags_reporting.cc 144 | const char kStrippedFlagHelp[] = "\001\002\003\004 (unknown) \004\003\002\001"; 145 | 146 | namespace { 147 | 148 | // There are also 'reporting' flags, in gflags_reporting.cc. 149 | 150 | static const char kError[] = "ERROR: "; 151 | 152 | // Indicates that undefined options are to be ignored. 153 | // Enables deferred processing of flags in dynamically loaded libraries. 154 | static bool allow_command_line_reparsing = false; 155 | 156 | static bool logging_is_probably_set_up = false; 157 | 158 | // This is a 'prototype' validate-function. 'Real' validate 159 | // functions, take a flag-value as an argument: ValidateFn(bool) or 160 | // ValidateFn(uint64). However, for easier storage, we strip off this 161 | // argument and then restore it when actually calling the function on 162 | // a flag value. 163 | typedef bool (*ValidateFnProto)(); 164 | 165 | // Whether we should die when reporting an error. 166 | enum DieWhenReporting { DIE, DO_NOT_DIE }; 167 | 168 | // Report Error and exit if requested. 169 | static void ReportError(DieWhenReporting should_die, const char* format, ...) { 170 | char error_message[255]; 171 | va_list ap; 172 | va_start(ap, format); 173 | vsnprintf(error_message, sizeof(error_message), format, ap); 174 | va_end(ap); 175 | fprintf(stderr, "%s", error_message); 176 | fflush(stderr); // should be unnecessary, but cygwin's rxvt buffers stderr 177 | if (should_die == DIE) gflags_exitfunc(1); 178 | } 179 | 180 | 181 | // -------------------------------------------------------------------- 182 | // FlagValue 183 | // This represent the value a single flag might have. The major 184 | // functionality is to convert from a string to an object of a 185 | // given type, and back. Thread-compatible. 186 | // -------------------------------------------------------------------- 187 | 188 | class CommandLineFlag; 189 | class FlagValue { 190 | public: 191 | FlagValue(void* valbuf, const char* type, bool transfer_ownership_of_value); 192 | ~FlagValue(); 193 | 194 | bool ParseFrom(const char* spec); 195 | string ToString() const; 196 | 197 | private: 198 | friend class CommandLineFlag; // for many things, including Validate() 199 | friend class GFLAGS_NAMESPACE::FlagSaverImpl; // calls New() 200 | friend class FlagRegistry; // checks value_buffer_ for flags_by_ptr_ map 201 | template friend T GetFromEnv(const char*, const char*, T); 202 | friend bool TryParseLocked(const CommandLineFlag*, FlagValue*, 203 | const char*, string*); // for New(), CopyFrom() 204 | 205 | enum ValueType { 206 | FV_BOOL = 0, 207 | FV_INT32 = 1, 208 | FV_INT64 = 2, 209 | FV_UINT64 = 3, 210 | FV_DOUBLE = 4, 211 | FV_STRING = 5, 212 | FV_MAX_INDEX = 5, 213 | }; 214 | const char* TypeName() const; 215 | bool Equal(const FlagValue& x) const; 216 | FlagValue* New() const; // creates a new one with default value 217 | void CopyFrom(const FlagValue& x); 218 | int ValueSize() const; 219 | 220 | // Calls the given validate-fn on value_buffer_, and returns 221 | // whatever it returns. But first casts validate_fn_proto to a 222 | // function that takes our value as an argument (eg void 223 | // (*validate_fn)(bool) for a bool flag). 224 | bool Validate(const char* flagname, ValidateFnProto validate_fn_proto) const; 225 | 226 | void* value_buffer_; // points to the buffer holding our data 227 | int8 type_; // how to interpret value_ 228 | bool owns_value_; // whether to free value on destruct 229 | 230 | FlagValue(const FlagValue&); // no copying! 231 | void operator=(const FlagValue&); 232 | }; 233 | 234 | 235 | // This could be a templated method of FlagValue, but doing so adds to the 236 | // size of the .o. Since there's no type-safety here anyway, macro is ok. 237 | #define VALUE_AS(type) *reinterpret_cast(value_buffer_) 238 | #define OTHER_VALUE_AS(fv, type) *reinterpret_cast(fv.value_buffer_) 239 | #define SET_VALUE_AS(type, value) VALUE_AS(type) = (value) 240 | 241 | FlagValue::FlagValue(void* valbuf, const char* type, 242 | bool transfer_ownership_of_value) 243 | : value_buffer_(valbuf), 244 | owns_value_(transfer_ownership_of_value) { 245 | for (type_ = 0; type_ <= FV_MAX_INDEX; ++type_) { 246 | if (!strcmp(type, TypeName())) { 247 | break; 248 | } 249 | } 250 | assert(type_ <= FV_MAX_INDEX); // Unknown typename 251 | } 252 | 253 | FlagValue::~FlagValue() { 254 | if (!owns_value_) { 255 | return; 256 | } 257 | switch (type_) { 258 | case FV_BOOL: delete reinterpret_cast(value_buffer_); break; 259 | case FV_INT32: delete reinterpret_cast(value_buffer_); break; 260 | case FV_INT64: delete reinterpret_cast(value_buffer_); break; 261 | case FV_UINT64: delete reinterpret_cast(value_buffer_); break; 262 | case FV_DOUBLE: delete reinterpret_cast(value_buffer_); break; 263 | case FV_STRING: delete reinterpret_cast(value_buffer_); break; 264 | } 265 | } 266 | 267 | bool FlagValue::ParseFrom(const char* value) { 268 | if (type_ == FV_BOOL) { 269 | const char* kTrue[] = { "1", "t", "true", "y", "yes" }; 270 | const char* kFalse[] = { "0", "f", "false", "n", "no" }; 271 | COMPILE_ASSERT(sizeof(kTrue) == sizeof(kFalse), true_false_equal); 272 | for (size_t i = 0; i < sizeof(kTrue)/sizeof(*kTrue); ++i) { 273 | if (strcasecmp(value, kTrue[i]) == 0) { 274 | SET_VALUE_AS(bool, true); 275 | return true; 276 | } else if (strcasecmp(value, kFalse[i]) == 0) { 277 | SET_VALUE_AS(bool, false); 278 | return true; 279 | } 280 | } 281 | return false; // didn't match a legal input 282 | 283 | } else if (type_ == FV_STRING) { 284 | SET_VALUE_AS(string, value); 285 | return true; 286 | } 287 | 288 | // OK, it's likely to be numeric, and we'll be using a strtoXXX method. 289 | if (value[0] == '\0') // empty-string is only allowed for string type. 290 | return false; 291 | char* end; 292 | // Leading 0x puts us in base 16. But leading 0 does not put us in base 8! 293 | // It caused too many bugs when we had that behavior. 294 | int base = 10; // by default 295 | if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X')) 296 | base = 16; 297 | errno = 0; 298 | 299 | switch (type_) { 300 | case FV_INT32: { 301 | const int64 r = strto64(value, &end, base); 302 | if (errno || end != value + strlen(value)) return false; // bad parse 303 | if (static_cast(r) != r) // worked, but number out of range 304 | return false; 305 | SET_VALUE_AS(int32, static_cast(r)); 306 | return true; 307 | } 308 | case FV_INT64: { 309 | const int64 r = strto64(value, &end, base); 310 | if (errno || end != value + strlen(value)) return false; // bad parse 311 | SET_VALUE_AS(int64, r); 312 | return true; 313 | } 314 | case FV_UINT64: { 315 | while (*value == ' ') value++; 316 | if (*value == '-') return false; // negative number 317 | const uint64 r = strtou64(value, &end, base); 318 | if (errno || end != value + strlen(value)) return false; // bad parse 319 | SET_VALUE_AS(uint64, r); 320 | return true; 321 | } 322 | case FV_DOUBLE: { 323 | const double r = strtod(value, &end); 324 | if (errno || end != value + strlen(value)) return false; // bad parse 325 | SET_VALUE_AS(double, r); 326 | return true; 327 | } 328 | default: { 329 | assert(false); // unknown type 330 | return false; 331 | } 332 | } 333 | } 334 | 335 | string FlagValue::ToString() const { 336 | char intbuf[64]; // enough to hold even the biggest number 337 | switch (type_) { 338 | case FV_BOOL: 339 | return VALUE_AS(bool) ? "true" : "false"; 340 | case FV_INT32: 341 | snprintf(intbuf, sizeof(intbuf), "%" PRId32, VALUE_AS(int32)); 342 | return intbuf; 343 | case FV_INT64: 344 | snprintf(intbuf, sizeof(intbuf), "%" PRId64, VALUE_AS(int64)); 345 | return intbuf; 346 | case FV_UINT64: 347 | snprintf(intbuf, sizeof(intbuf), "%" PRIu64, VALUE_AS(uint64)); 348 | return intbuf; 349 | case FV_DOUBLE: 350 | snprintf(intbuf, sizeof(intbuf), "%.17g", VALUE_AS(double)); 351 | return intbuf; 352 | case FV_STRING: 353 | return VALUE_AS(string); 354 | default: 355 | assert(false); 356 | return ""; // unknown type 357 | } 358 | } 359 | 360 | bool FlagValue::Validate(const char* flagname, 361 | ValidateFnProto validate_fn_proto) const { 362 | switch (type_) { 363 | case FV_BOOL: 364 | return reinterpret_cast( 365 | validate_fn_proto)(flagname, VALUE_AS(bool)); 366 | case FV_INT32: 367 | return reinterpret_cast( 368 | validate_fn_proto)(flagname, VALUE_AS(int32)); 369 | case FV_INT64: 370 | return reinterpret_cast( 371 | validate_fn_proto)(flagname, VALUE_AS(int64)); 372 | case FV_UINT64: 373 | return reinterpret_cast( 374 | validate_fn_proto)(flagname, VALUE_AS(uint64)); 375 | case FV_DOUBLE: 376 | return reinterpret_cast( 377 | validate_fn_proto)(flagname, VALUE_AS(double)); 378 | case FV_STRING: 379 | return reinterpret_cast( 380 | validate_fn_proto)(flagname, VALUE_AS(string)); 381 | default: 382 | assert(false); // unknown type 383 | return false; 384 | } 385 | } 386 | 387 | const char* FlagValue::TypeName() const { 388 | static const char types[] = 389 | "bool\0xx" 390 | "int32\0x" 391 | "int64\0x" 392 | "uint64\0" 393 | "double\0" 394 | "string"; 395 | if (type_ > FV_MAX_INDEX) { 396 | assert(false); 397 | return ""; 398 | } 399 | // Directly indexing the strings in the 'types' string, each of them is 7 bytes long. 400 | return &types[type_ * 7]; 401 | } 402 | 403 | bool FlagValue::Equal(const FlagValue& x) const { 404 | if (type_ != x.type_) 405 | return false; 406 | switch (type_) { 407 | case FV_BOOL: return VALUE_AS(bool) == OTHER_VALUE_AS(x, bool); 408 | case FV_INT32: return VALUE_AS(int32) == OTHER_VALUE_AS(x, int32); 409 | case FV_INT64: return VALUE_AS(int64) == OTHER_VALUE_AS(x, int64); 410 | case FV_UINT64: return VALUE_AS(uint64) == OTHER_VALUE_AS(x, uint64); 411 | case FV_DOUBLE: return VALUE_AS(double) == OTHER_VALUE_AS(x, double); 412 | case FV_STRING: return VALUE_AS(string) == OTHER_VALUE_AS(x, string); 413 | default: assert(false); return false; // unknown type 414 | } 415 | } 416 | 417 | FlagValue* FlagValue::New() const { 418 | const char *type = TypeName(); 419 | switch (type_) { 420 | case FV_BOOL: return new FlagValue(new bool(false), type, true); 421 | case FV_INT32: return new FlagValue(new int32(0), type, true); 422 | case FV_INT64: return new FlagValue(new int64(0), type, true); 423 | case FV_UINT64: return new FlagValue(new uint64(0), type, true); 424 | case FV_DOUBLE: return new FlagValue(new double(0.0), type, true); 425 | case FV_STRING: return new FlagValue(new string, type, true); 426 | default: assert(false); return NULL; // unknown type 427 | } 428 | } 429 | 430 | void FlagValue::CopyFrom(const FlagValue& x) { 431 | assert(type_ == x.type_); 432 | switch (type_) { 433 | case FV_BOOL: SET_VALUE_AS(bool, OTHER_VALUE_AS(x, bool)); break; 434 | case FV_INT32: SET_VALUE_AS(int32, OTHER_VALUE_AS(x, int32)); break; 435 | case FV_INT64: SET_VALUE_AS(int64, OTHER_VALUE_AS(x, int64)); break; 436 | case FV_UINT64: SET_VALUE_AS(uint64, OTHER_VALUE_AS(x, uint64)); break; 437 | case FV_DOUBLE: SET_VALUE_AS(double, OTHER_VALUE_AS(x, double)); break; 438 | case FV_STRING: SET_VALUE_AS(string, OTHER_VALUE_AS(x, string)); break; 439 | default: assert(false); // unknown type 440 | } 441 | } 442 | 443 | int FlagValue::ValueSize() const { 444 | if (type_ > FV_MAX_INDEX) { 445 | assert(false); // unknown type 446 | return 0; 447 | } 448 | static const uint8 valuesize[] = { 449 | sizeof(bool), 450 | sizeof(int32), 451 | sizeof(int64), 452 | sizeof(uint64), 453 | sizeof(double), 454 | sizeof(string), 455 | }; 456 | return valuesize[type_]; 457 | } 458 | 459 | // -------------------------------------------------------------------- 460 | // CommandLineFlag 461 | // This represents a single flag, including its name, description, 462 | // default value, and current value. Mostly this serves as a 463 | // struct, though it also knows how to register itself. 464 | // All CommandLineFlags are owned by a (exactly one) 465 | // FlagRegistry. If you wish to modify fields in this class, you 466 | // should acquire the FlagRegistry lock for the registry that owns 467 | // this flag. 468 | // -------------------------------------------------------------------- 469 | 470 | class CommandLineFlag { 471 | public: 472 | // Note: we take over memory-ownership of current_val and default_val. 473 | CommandLineFlag(const char* name, const char* help, const char* filename, 474 | FlagValue* current_val, FlagValue* default_val); 475 | ~CommandLineFlag(); 476 | 477 | const char* name() const { return name_; } 478 | const char* help() const { return help_; } 479 | const char* filename() const { return file_; } 480 | const char* CleanFileName() const; // nixes irrelevant prefix such as homedir 481 | string current_value() const { return current_->ToString(); } 482 | string default_value() const { return defvalue_->ToString(); } 483 | const char* type_name() const { return defvalue_->TypeName(); } 484 | ValidateFnProto validate_function() const { return validate_fn_proto_; } 485 | const void* flag_ptr() const { return current_->value_buffer_; } 486 | 487 | void FillCommandLineFlagInfo(struct CommandLineFlagInfo* result); 488 | 489 | // If validate_fn_proto_ is non-NULL, calls it on value, returns result. 490 | bool Validate(const FlagValue& value) const; 491 | bool ValidateCurrent() const { return Validate(*current_); } 492 | 493 | private: 494 | // for SetFlagLocked() and setting flags_by_ptr_ 495 | friend class FlagRegistry; 496 | friend class GFLAGS_NAMESPACE::FlagSaverImpl; // for cloning the values 497 | // set validate_fn 498 | friend bool AddFlagValidator(const void*, ValidateFnProto); 499 | 500 | // This copies all the non-const members: modified, processed, defvalue, etc. 501 | void CopyFrom(const CommandLineFlag& src); 502 | 503 | void UpdateModifiedBit(); 504 | 505 | const char* const name_; // Flag name 506 | const char* const help_; // Help message 507 | const char* const file_; // Which file did this come from? 508 | bool modified_; // Set after default assignment? 509 | FlagValue* defvalue_; // Default value for flag 510 | FlagValue* current_; // Current value for flag 511 | // This is a casted, 'generic' version of validate_fn, which actually 512 | // takes a flag-value as an arg (void (*validate_fn)(bool), say). 513 | // When we pass this to current_->Validate(), it will cast it back to 514 | // the proper type. This may be NULL to mean we have no validate_fn. 515 | ValidateFnProto validate_fn_proto_; 516 | 517 | CommandLineFlag(const CommandLineFlag&); // no copying! 518 | void operator=(const CommandLineFlag&); 519 | }; 520 | 521 | CommandLineFlag::CommandLineFlag(const char* name, const char* help, 522 | const char* filename, 523 | FlagValue* current_val, FlagValue* default_val) 524 | : name_(name), help_(help), file_(filename), modified_(false), 525 | defvalue_(default_val), current_(current_val), validate_fn_proto_(NULL) { 526 | } 527 | 528 | CommandLineFlag::~CommandLineFlag() { 529 | delete current_; 530 | delete defvalue_; 531 | } 532 | 533 | const char* CommandLineFlag::CleanFileName() const { 534 | // Compute top-level directory & file that this appears in 535 | // search full path backwards. 536 | // Stop going backwards at kRootDir; and skip by the first slash. 537 | static const char kRootDir[] = ""; // can set this to root directory, 538 | 539 | if (sizeof(kRootDir)-1 == 0) // no prefix to strip 540 | return filename(); 541 | 542 | const char* clean_name = filename() + strlen(filename()) - 1; 543 | while ( clean_name > filename() ) { 544 | if (*clean_name == PATH_SEPARATOR) { 545 | if (strncmp(clean_name, kRootDir, sizeof(kRootDir)-1) == 0) { 546 | clean_name += sizeof(kRootDir)-1; // past root-dir 547 | break; 548 | } 549 | } 550 | --clean_name; 551 | } 552 | while ( *clean_name == PATH_SEPARATOR ) ++clean_name; // Skip any slashes 553 | return clean_name; 554 | } 555 | 556 | void CommandLineFlag::FillCommandLineFlagInfo( 557 | CommandLineFlagInfo* result) { 558 | result->name = name(); 559 | result->type = type_name(); 560 | result->description = help(); 561 | result->current_value = current_value(); 562 | result->default_value = default_value(); 563 | result->filename = CleanFileName(); 564 | UpdateModifiedBit(); 565 | result->is_default = !modified_; 566 | result->has_validator_fn = validate_function() != NULL; 567 | result->flag_ptr = flag_ptr(); 568 | } 569 | 570 | void CommandLineFlag::UpdateModifiedBit() { 571 | // Update the "modified" bit in case somebody bypassed the 572 | // Flags API and wrote directly through the FLAGS_name variable. 573 | if (!modified_ && !current_->Equal(*defvalue_)) { 574 | modified_ = true; 575 | } 576 | } 577 | 578 | void CommandLineFlag::CopyFrom(const CommandLineFlag& src) { 579 | // Note we only copy the non-const members; others are fixed at construct time 580 | if (modified_ != src.modified_) modified_ = src.modified_; 581 | if (!current_->Equal(*src.current_)) current_->CopyFrom(*src.current_); 582 | if (!defvalue_->Equal(*src.defvalue_)) defvalue_->CopyFrom(*src.defvalue_); 583 | if (validate_fn_proto_ != src.validate_fn_proto_) 584 | validate_fn_proto_ = src.validate_fn_proto_; 585 | } 586 | 587 | bool CommandLineFlag::Validate(const FlagValue& value) const { 588 | 589 | if (validate_function() == NULL) 590 | return true; 591 | else 592 | return value.Validate(name(), validate_function()); 593 | } 594 | 595 | 596 | // -------------------------------------------------------------------- 597 | // FlagRegistry 598 | // A FlagRegistry singleton object holds all flag objects indexed 599 | // by their names so that if you know a flag's name (as a C 600 | // string), you can access or set it. If the function is named 601 | // FooLocked(), you must own the registry lock before calling 602 | // the function; otherwise, you should *not* hold the lock, and 603 | // the function will acquire it itself if needed. 604 | // -------------------------------------------------------------------- 605 | 606 | struct StringCmp { // Used by the FlagRegistry map class to compare char*'s 607 | bool operator() (const char* s1, const char* s2) const { 608 | return (strcmp(s1, s2) < 0); 609 | } 610 | }; 611 | 612 | 613 | class FlagRegistry { 614 | public: 615 | FlagRegistry() { 616 | } 617 | ~FlagRegistry() { 618 | // Not using STLDeleteElements as that resides in util and this 619 | // class is base. 620 | for (FlagMap::iterator p = flags_.begin(), e = flags_.end(); p != e; ++p) { 621 | CommandLineFlag* flag = p->second; 622 | delete flag; 623 | } 624 | } 625 | 626 | static void DeleteGlobalRegistry() { 627 | delete global_registry_; 628 | global_registry_ = NULL; 629 | } 630 | 631 | // Store a flag in this registry. Takes ownership of the given pointer. 632 | void RegisterFlag(CommandLineFlag* flag); 633 | 634 | void Lock() { lock_.Lock(); } 635 | void Unlock() { lock_.Unlock(); } 636 | 637 | // Returns the flag object for the specified name, or NULL if not found. 638 | CommandLineFlag* FindFlagLocked(const char* name); 639 | 640 | // Returns the flag object whose current-value is stored at flag_ptr. 641 | // That is, for whom current_->value_buffer_ == flag_ptr 642 | CommandLineFlag* FindFlagViaPtrLocked(const void* flag_ptr); 643 | 644 | // A fancier form of FindFlag that works correctly if name is of the 645 | // form flag=value. In that case, we set key to point to flag, and 646 | // modify v to point to the value (if present), and return the flag 647 | // with the given name. If the flag does not exist, returns NULL 648 | // and sets error_message. 649 | CommandLineFlag* SplitArgumentLocked(const char* argument, 650 | string* key, const char** v, 651 | string* error_message); 652 | 653 | // Set the value of a flag. If the flag was successfully set to 654 | // value, set msg to indicate the new flag-value, and return true. 655 | // Otherwise, set msg to indicate the error, leave flag unchanged, 656 | // and return false. msg can be NULL. 657 | bool SetFlagLocked(CommandLineFlag* flag, const char* value, 658 | FlagSettingMode set_mode, string* msg); 659 | 660 | static FlagRegistry* GlobalRegistry(); // returns a singleton registry 661 | 662 | private: 663 | friend class GFLAGS_NAMESPACE::FlagSaverImpl; // reads all the flags in order to copy them 664 | friend class CommandLineFlagParser; // for ValidateAllFlags 665 | friend void GFLAGS_NAMESPACE::GetAllFlags(vector*); 666 | 667 | // The map from name to flag, for FindFlagLocked(). 668 | typedef map FlagMap; 669 | typedef FlagMap::iterator FlagIterator; 670 | typedef FlagMap::const_iterator FlagConstIterator; 671 | FlagMap flags_; 672 | 673 | // The map from current-value pointer to flag, fo FindFlagViaPtrLocked(). 674 | typedef map FlagPtrMap; 675 | FlagPtrMap flags_by_ptr_; 676 | 677 | static FlagRegistry* global_registry_; // a singleton registry 678 | 679 | Mutex lock_; 680 | static Mutex global_registry_lock_; 681 | 682 | static void InitGlobalRegistry(); 683 | 684 | // Disallow 685 | FlagRegistry(const FlagRegistry&); 686 | FlagRegistry& operator=(const FlagRegistry&); 687 | }; 688 | 689 | class FlagRegistryLock { 690 | public: 691 | explicit FlagRegistryLock(FlagRegistry* fr) : fr_(fr) { fr_->Lock(); } 692 | ~FlagRegistryLock() { fr_->Unlock(); } 693 | private: 694 | FlagRegistry *const fr_; 695 | }; 696 | 697 | 698 | void FlagRegistry::RegisterFlag(CommandLineFlag* flag) { 699 | Lock(); 700 | pair ins = 701 | flags_.insert(pair(flag->name(), flag)); 702 | if (ins.second == false) { // means the name was already in the map 703 | if (strcmp(ins.first->second->filename(), flag->filename()) != 0) { 704 | ReportError(DIE, "ERROR: flag '%s' was defined more than once " 705 | "(in files '%s' and '%s').\n", 706 | flag->name(), 707 | ins.first->second->filename(), 708 | flag->filename()); 709 | } else { 710 | ReportError(DIE, "ERROR: something wrong with flag '%s' in file '%s'. " 711 | "One possibility: file '%s' is being linked both statically " 712 | "and dynamically into this executable.\n", 713 | flag->name(), 714 | flag->filename(), flag->filename()); 715 | } 716 | } 717 | // Also add to the flags_by_ptr_ map. 718 | flags_by_ptr_[flag->current_->value_buffer_] = flag; 719 | Unlock(); 720 | } 721 | 722 | CommandLineFlag* FlagRegistry::FindFlagLocked(const char* name) { 723 | FlagConstIterator i = flags_.find(name); 724 | if (i == flags_.end()) { 725 | return NULL; 726 | } else { 727 | return i->second; 728 | } 729 | } 730 | 731 | CommandLineFlag* FlagRegistry::FindFlagViaPtrLocked(const void* flag_ptr) { 732 | FlagPtrMap::const_iterator i = flags_by_ptr_.find(flag_ptr); 733 | if (i == flags_by_ptr_.end()) { 734 | return NULL; 735 | } else { 736 | return i->second; 737 | } 738 | } 739 | 740 | CommandLineFlag* FlagRegistry::SplitArgumentLocked(const char* arg, 741 | string* key, 742 | const char** v, 743 | string* error_message) { 744 | // Find the flag object for this option 745 | const char* flag_name; 746 | const char* value = strchr(arg, '='); 747 | if (value == NULL) { 748 | key->assign(arg); 749 | *v = NULL; 750 | } else { 751 | // Strip out the "=value" portion from arg 752 | key->assign(arg, value-arg); 753 | *v = ++value; // advance past the '=' 754 | } 755 | flag_name = key->c_str(); 756 | 757 | CommandLineFlag* flag = FindFlagLocked(flag_name); 758 | 759 | if (flag == NULL) { 760 | // If we can't find the flag-name, then we should return an error. 761 | // The one exception is if 1) the flag-name is 'nox', 2) there 762 | // exists a flag named 'x', and 3) 'x' is a boolean flag. 763 | // In that case, we want to return flag 'x'. 764 | if (!(flag_name[0] == 'n' && flag_name[1] == 'o')) { 765 | // flag-name is not 'nox', so we're not in the exception case. 766 | *error_message = StringPrintf("%sunknown command line flag '%s'\n", 767 | kError, key->c_str()); 768 | return NULL; 769 | } 770 | flag = FindFlagLocked(flag_name+2); 771 | if (flag == NULL) { 772 | // No flag named 'x' exists, so we're not in the exception case. 773 | *error_message = StringPrintf("%sunknown command line flag '%s'\n", 774 | kError, key->c_str()); 775 | return NULL; 776 | } 777 | if (strcmp(flag->type_name(), "bool") != 0) { 778 | // 'x' exists but is not boolean, so we're not in the exception case. 779 | *error_message = StringPrintf( 780 | "%sboolean value (%s) specified for %s command line flag\n", 781 | kError, key->c_str(), flag->type_name()); 782 | return NULL; 783 | } 784 | // We're in the exception case! 785 | // Make up a fake value to replace the "no" we stripped out 786 | key->assign(flag_name+2); // the name without the "no" 787 | *v = "0"; 788 | } 789 | 790 | // Assign a value if this is a boolean flag 791 | if (*v == NULL && strcmp(flag->type_name(), "bool") == 0) { 792 | *v = "1"; // the --nox case was already handled, so this is the --x case 793 | } 794 | 795 | return flag; 796 | } 797 | 798 | bool TryParseLocked(const CommandLineFlag* flag, FlagValue* flag_value, 799 | const char* value, string* msg) { 800 | // Use tenative_value, not flag_value, until we know value is valid. 801 | FlagValue* tentative_value = flag_value->New(); 802 | if (!tentative_value->ParseFrom(value)) { 803 | if (msg) { 804 | StringAppendF(msg, 805 | "%sillegal value '%s' specified for %s flag '%s'\n", 806 | kError, value, 807 | flag->type_name(), flag->name()); 808 | } 809 | delete tentative_value; 810 | return false; 811 | } else if (!flag->Validate(*tentative_value)) { 812 | if (msg) { 813 | StringAppendF(msg, 814 | "%sfailed validation of new value '%s' for flag '%s'\n", 815 | kError, tentative_value->ToString().c_str(), 816 | flag->name()); 817 | } 818 | delete tentative_value; 819 | return false; 820 | } else { 821 | flag_value->CopyFrom(*tentative_value); 822 | if (msg) { 823 | StringAppendF(msg, "%s set to %s\n", 824 | flag->name(), flag_value->ToString().c_str()); 825 | } 826 | delete tentative_value; 827 | return true; 828 | } 829 | } 830 | 831 | bool FlagRegistry::SetFlagLocked(CommandLineFlag* flag, 832 | const char* value, 833 | FlagSettingMode set_mode, 834 | string* msg) { 835 | flag->UpdateModifiedBit(); 836 | switch (set_mode) { 837 | case SET_FLAGS_VALUE: { 838 | // set or modify the flag's value 839 | if (!TryParseLocked(flag, flag->current_, value, msg)) 840 | return false; 841 | flag->modified_ = true; 842 | break; 843 | } 844 | case SET_FLAG_IF_DEFAULT: { 845 | // set the flag's value, but only if it hasn't been set by someone else 846 | if (!flag->modified_) { 847 | if (!TryParseLocked(flag, flag->current_, value, msg)) 848 | return false; 849 | flag->modified_ = true; 850 | } else { 851 | *msg = StringPrintf("%s set to %s", 852 | flag->name(), flag->current_value().c_str()); 853 | } 854 | break; 855 | } 856 | case SET_FLAGS_DEFAULT: { 857 | // modify the flag's default-value 858 | if (!TryParseLocked(flag, flag->defvalue_, value, msg)) 859 | return false; 860 | if (!flag->modified_) { 861 | // Need to set both defvalue *and* current, in this case 862 | TryParseLocked(flag, flag->current_, value, NULL); 863 | } 864 | break; 865 | } 866 | default: { 867 | // unknown set_mode 868 | assert(false); 869 | return false; 870 | } 871 | } 872 | 873 | return true; 874 | } 875 | 876 | // Get the singleton FlagRegistry object 877 | FlagRegistry* FlagRegistry::global_registry_ = NULL; 878 | Mutex FlagRegistry::global_registry_lock_(Mutex::LINKER_INITIALIZED); 879 | 880 | FlagRegistry* FlagRegistry::GlobalRegistry() { 881 | MutexLock acquire_lock(&global_registry_lock_); 882 | if (!global_registry_) { 883 | global_registry_ = new FlagRegistry; 884 | } 885 | return global_registry_; 886 | } 887 | 888 | // -------------------------------------------------------------------- 889 | // CommandLineFlagParser 890 | // Parsing is done in two stages. In the first, we go through 891 | // argv. For every flag-like arg we can make sense of, we parse 892 | // it and set the appropriate FLAGS_* variable. For every flag- 893 | // like arg we can't make sense of, we store it in a vector, 894 | // along with an explanation of the trouble. In stage 2, we 895 | // handle the 'reporting' flags like --help and --mpm_version. 896 | // (This is via a call to HandleCommandLineHelpFlags(), in 897 | // gflags_reporting.cc.) 898 | // An optional stage 3 prints out the error messages. 899 | // This is a bit of a simplification. For instance, --flagfile 900 | // is handled as soon as it's seen in stage 1, not in stage 2. 901 | // -------------------------------------------------------------------- 902 | 903 | class CommandLineFlagParser { 904 | public: 905 | // The argument is the flag-registry to register the parsed flags in 906 | explicit CommandLineFlagParser(FlagRegistry* reg) : registry_(reg) {} 907 | ~CommandLineFlagParser() {} 908 | 909 | // Stage 1: Every time this is called, it reads all flags in argv. 910 | // However, it ignores all flags that have been successfully set 911 | // before. Typically this is only called once, so this 'reparsing' 912 | // behavior isn't important. It can be useful when trying to 913 | // reparse after loading a dll, though. 914 | uint32 ParseNewCommandLineFlags(int* argc, char*** argv, bool remove_flags); 915 | 916 | // Stage 2: print reporting info and exit, if requested. 917 | // In gflags_reporting.cc:HandleCommandLineHelpFlags(). 918 | 919 | // Stage 3: validate all the commandline flags that have validators 920 | // registered. 921 | void ValidateAllFlags(); 922 | 923 | // Stage 4: report any errors and return true if any were found. 924 | bool ReportErrors(); 925 | 926 | // Set a particular command line option. "newval" is a string 927 | // describing the new value that the option has been set to. If 928 | // option_name does not specify a valid option name, or value is not 929 | // a valid value for option_name, newval is empty. Does recursive 930 | // processing for --flagfile and --fromenv. Returns the new value 931 | // if everything went ok, or empty-string if not. (Actually, the 932 | // return-string could hold many flag/value pairs due to --flagfile.) 933 | // NB: Must have called registry_->Lock() before calling this function. 934 | string ProcessSingleOptionLocked(CommandLineFlag* flag, 935 | const char* value, 936 | FlagSettingMode set_mode); 937 | 938 | // Set a whole batch of command line options as specified by contentdata, 939 | // which is in flagfile format (and probably has been read from a flagfile). 940 | // Returns the new value if everything went ok, or empty-string if 941 | // not. (Actually, the return-string could hold many flag/value 942 | // pairs due to --flagfile.) 943 | // NB: Must have called registry_->Lock() before calling this function. 944 | string ProcessOptionsFromStringLocked(const string& contentdata, 945 | FlagSettingMode set_mode); 946 | 947 | // These are the 'recursive' flags, defined at the top of this file. 948 | // Whenever we see these flags on the commandline, we must take action. 949 | // These are called by ProcessSingleOptionLocked and, similarly, return 950 | // new values if everything went ok, or the empty-string if not. 951 | string ProcessFlagfileLocked(const string& flagval, FlagSettingMode set_mode); 952 | // diff fromenv/tryfromenv 953 | string ProcessFromenvLocked(const string& flagval, FlagSettingMode set_mode, 954 | bool errors_are_fatal); 955 | 956 | private: 957 | FlagRegistry* const registry_; 958 | map error_flags_; // map from name to error message 959 | // This could be a set, but we reuse the map to minimize the .o size 960 | map undefined_names_; // --[flag] name was not registered 961 | }; 962 | 963 | 964 | // Parse a list of (comma-separated) flags. 965 | static void ParseFlagList(const char* value, vector* flags) { 966 | for (const char *p = value; p && *p; value = p) { 967 | p = strchr(value, ','); 968 | size_t len; 969 | if (p) { 970 | len = p - value; 971 | p++; 972 | } else { 973 | len = strlen(value); 974 | } 975 | 976 | if (len == 0) 977 | ReportError(DIE, "ERROR: empty flaglist entry\n"); 978 | if (value[0] == '-') 979 | ReportError(DIE, "ERROR: flag \"%*s\" begins with '-'\n", len, value); 980 | 981 | flags->push_back(string(value, len)); 982 | } 983 | } 984 | 985 | // Snarf an entire file into a C++ string. This is just so that we 986 | // can do all the I/O in one place and not worry about it everywhere. 987 | // Plus, it's convenient to have the whole file contents at hand. 988 | // Adds a newline at the end of the file. 989 | #define PFATAL(s) do { perror(s); gflags_exitfunc(1); } while (0) 990 | 991 | static string ReadFileIntoString(const char* filename) { 992 | const int kBufSize = 8092; 993 | char buffer[kBufSize]; 994 | string s; 995 | FILE* fp; 996 | if ((errno = SafeFOpen(&fp, filename, "r")) != 0) PFATAL(filename); 997 | size_t n; 998 | while ( (n=fread(buffer, 1, kBufSize, fp)) > 0 ) { 999 | if (ferror(fp)) PFATAL(filename); 1000 | s.append(buffer, n); 1001 | } 1002 | fclose(fp); 1003 | return s; 1004 | } 1005 | 1006 | uint32 CommandLineFlagParser::ParseNewCommandLineFlags(int* argc, char*** argv, 1007 | bool remove_flags) { 1008 | const char *program_name = strrchr((*argv)[0], PATH_SEPARATOR); // nix path 1009 | program_name = (program_name == NULL ? (*argv)[0] : program_name+1); 1010 | 1011 | int first_nonopt = *argc; // for non-options moved to the end 1012 | 1013 | registry_->Lock(); 1014 | for (int i = 1; i < first_nonopt; i++) { 1015 | char* arg = (*argv)[i]; 1016 | 1017 | // Like getopt(), we permute non-option flags to be at the end. 1018 | if (arg[0] != '-' || // must be a program argument 1019 | (arg[0] == '-' && arg[1] == '\0')) { // "-" is an argument, not a flag 1020 | memmove((*argv) + i, (*argv) + i+1, (*argc - (i+1)) * sizeof((*argv)[i])); 1021 | (*argv)[*argc-1] = arg; // we go last 1022 | first_nonopt--; // we've been pushed onto the stack 1023 | i--; // to undo the i++ in the loop 1024 | continue; 1025 | } 1026 | 1027 | if (arg[0] == '-') arg++; // allow leading '-' 1028 | if (arg[0] == '-') arg++; // or leading '--' 1029 | 1030 | // -- alone means what it does for GNU: stop options parsing 1031 | if (*arg == '\0') { 1032 | first_nonopt = i+1; 1033 | break; 1034 | } 1035 | 1036 | // Find the flag object for this option 1037 | string key; 1038 | const char* value; 1039 | string error_message; 1040 | CommandLineFlag* flag = registry_->SplitArgumentLocked(arg, &key, &value, 1041 | &error_message); 1042 | if (flag == NULL) { 1043 | undefined_names_[key] = ""; // value isn't actually used 1044 | error_flags_[key] = error_message; 1045 | continue; 1046 | } 1047 | 1048 | if (value == NULL) { 1049 | // Boolean options are always assigned a value by SplitArgumentLocked() 1050 | assert(strcmp(flag->type_name(), "bool") != 0); 1051 | if (i+1 >= first_nonopt) { 1052 | // This flag needs a value, but there is nothing available 1053 | error_flags_[key] = (string(kError) + "flag '" + (*argv)[i] + "'" 1054 | + " is missing its argument"); 1055 | if (flag->help() && flag->help()[0] > '\001') { 1056 | // Be useful in case we have a non-stripped description. 1057 | error_flags_[key] += string("; flag description: ") + flag->help(); 1058 | } 1059 | error_flags_[key] += "\n"; 1060 | break; // we treat this as an unrecoverable error 1061 | } else { 1062 | value = (*argv)[++i]; // read next arg for value 1063 | 1064 | // Heuristic to detect the case where someone treats a string arg 1065 | // like a bool: 1066 | // --my_string_var --foo=bar 1067 | // We look for a flag of string type, whose value begins with a 1068 | // dash, and where the flag-name and value are separated by a 1069 | // space rather than an '='. 1070 | // To avoid false positives, we also require the word "true" 1071 | // or "false" in the help string. Without this, a valid usage 1072 | // "-lat -30.5" would trigger the warning. The common cases we 1073 | // want to solve talk about true and false as values. 1074 | if (value[0] == '-' 1075 | && strcmp(flag->type_name(), "string") == 0 1076 | && (strstr(flag->help(), "true") 1077 | || strstr(flag->help(), "false"))) { 1078 | LOG(WARNING) << "Did you really mean to set flag '" 1079 | << flag->name() << "' to the value '" 1080 | << value << "'?"; 1081 | } 1082 | } 1083 | } 1084 | 1085 | // TODO(csilvers): only set a flag if we hadn't set it before here 1086 | ProcessSingleOptionLocked(flag, value, SET_FLAGS_VALUE); 1087 | } 1088 | registry_->Unlock(); 1089 | 1090 | if (remove_flags) { // Fix up argc and argv by removing command line flags 1091 | (*argv)[first_nonopt-1] = (*argv)[0]; 1092 | (*argv) += (first_nonopt-1); 1093 | (*argc) -= (first_nonopt-1); 1094 | first_nonopt = 1; // because we still don't count argv[0] 1095 | } 1096 | 1097 | logging_is_probably_set_up = true; // because we've parsed --logdir, etc. 1098 | 1099 | return first_nonopt; 1100 | } 1101 | 1102 | string CommandLineFlagParser::ProcessFlagfileLocked(const string& flagval, 1103 | FlagSettingMode set_mode) { 1104 | if (flagval.empty()) 1105 | return ""; 1106 | 1107 | string msg; 1108 | vector filename_list; 1109 | ParseFlagList(flagval.c_str(), &filename_list); // take a list of filenames 1110 | for (size_t i = 0; i < filename_list.size(); ++i) { 1111 | const char* file = filename_list[i].c_str(); 1112 | msg += ProcessOptionsFromStringLocked(ReadFileIntoString(file), set_mode); 1113 | } 1114 | return msg; 1115 | } 1116 | 1117 | string CommandLineFlagParser::ProcessFromenvLocked(const string& flagval, 1118 | FlagSettingMode set_mode, 1119 | bool errors_are_fatal) { 1120 | if (flagval.empty()) 1121 | return ""; 1122 | 1123 | string msg; 1124 | vector flaglist; 1125 | ParseFlagList(flagval.c_str(), &flaglist); 1126 | 1127 | for (size_t i = 0; i < flaglist.size(); ++i) { 1128 | const char* flagname = flaglist[i].c_str(); 1129 | CommandLineFlag* flag = registry_->FindFlagLocked(flagname); 1130 | if (flag == NULL) { 1131 | error_flags_[flagname] = 1132 | StringPrintf("%sunknown command line flag '%s' " 1133 | "(via --fromenv or --tryfromenv)\n", 1134 | kError, flagname); 1135 | undefined_names_[flagname] = ""; 1136 | continue; 1137 | } 1138 | 1139 | const string envname = string("FLAGS_") + string(flagname); 1140 | string envval; 1141 | if (!SafeGetEnv(envname.c_str(), envval)) { 1142 | if (errors_are_fatal) { 1143 | error_flags_[flagname] = (string(kError) + envname + 1144 | " not found in environment\n"); 1145 | } 1146 | continue; 1147 | } 1148 | 1149 | // Avoid infinite recursion. 1150 | if (envval == "fromenv" || envval == "tryfromenv") { 1151 | error_flags_[flagname] = 1152 | StringPrintf("%sinfinite recursion on environment flag '%s'\n", 1153 | kError, envval.c_str()); 1154 | continue; 1155 | } 1156 | 1157 | msg += ProcessSingleOptionLocked(flag, envval.c_str(), set_mode); 1158 | } 1159 | return msg; 1160 | } 1161 | 1162 | string CommandLineFlagParser::ProcessSingleOptionLocked( 1163 | CommandLineFlag* flag, const char* value, FlagSettingMode set_mode) { 1164 | string msg; 1165 | if (value && !registry_->SetFlagLocked(flag, value, set_mode, &msg)) { 1166 | error_flags_[flag->name()] = msg; 1167 | return ""; 1168 | } 1169 | 1170 | // The recursive flags, --flagfile and --fromenv and --tryfromenv, 1171 | // must be dealt with as soon as they're seen. They will emit 1172 | // messages of their own. 1173 | if (strcmp(flag->name(), "flagfile") == 0) { 1174 | msg += ProcessFlagfileLocked(FLAGS_flagfile, set_mode); 1175 | 1176 | } else if (strcmp(flag->name(), "fromenv") == 0) { 1177 | // last arg indicates envval-not-found is fatal (unlike in --tryfromenv) 1178 | msg += ProcessFromenvLocked(FLAGS_fromenv, set_mode, true); 1179 | 1180 | } else if (strcmp(flag->name(), "tryfromenv") == 0) { 1181 | msg += ProcessFromenvLocked(FLAGS_tryfromenv, set_mode, false); 1182 | } 1183 | 1184 | return msg; 1185 | } 1186 | 1187 | void CommandLineFlagParser::ValidateAllFlags() { 1188 | FlagRegistryLock frl(registry_); 1189 | for (FlagRegistry::FlagConstIterator i = registry_->flags_.begin(); 1190 | i != registry_->flags_.end(); ++i) { 1191 | if (!i->second->ValidateCurrent()) { 1192 | // only set a message if one isn't already there. (If there's 1193 | // an error message, our job is done, even if it's not exactly 1194 | // the same error.) 1195 | if (error_flags_[i->second->name()].empty()) 1196 | error_flags_[i->second->name()] = 1197 | string(kError) + "--" + i->second->name() + 1198 | " must be set on the commandline" 1199 | " (default value fails validation)\n"; 1200 | } 1201 | } 1202 | } 1203 | 1204 | bool CommandLineFlagParser::ReportErrors() { 1205 | // error_flags_ indicates errors we saw while parsing. 1206 | // But we ignore undefined-names if ok'ed by --undef_ok 1207 | if (!FLAGS_undefok.empty()) { 1208 | vector flaglist; 1209 | ParseFlagList(FLAGS_undefok.c_str(), &flaglist); 1210 | for (size_t i = 0; i < flaglist.size(); ++i) { 1211 | // We also deal with --no, in case the flagname was boolean 1212 | const string no_version = string("no") + flaglist[i]; 1213 | if (undefined_names_.find(flaglist[i]) != undefined_names_.end()) { 1214 | error_flags_[flaglist[i]] = ""; // clear the error message 1215 | } else if (undefined_names_.find(no_version) != undefined_names_.end()) { 1216 | error_flags_[no_version] = ""; 1217 | } 1218 | } 1219 | } 1220 | // Likewise, if they decided to allow reparsing, all undefined-names 1221 | // are ok; we just silently ignore them now, and hope that a future 1222 | // parse will pick them up somehow. 1223 | if (allow_command_line_reparsing) { 1224 | for (map::const_iterator it = undefined_names_.begin(); 1225 | it != undefined_names_.end(); ++it) 1226 | error_flags_[it->first] = ""; // clear the error message 1227 | } 1228 | 1229 | bool found_error = false; 1230 | string error_message; 1231 | for (map::const_iterator it = error_flags_.begin(); 1232 | it != error_flags_.end(); ++it) { 1233 | if (!it->second.empty()) { 1234 | error_message.append(it->second.data(), it->second.size()); 1235 | found_error = true; 1236 | } 1237 | } 1238 | if (found_error) 1239 | ReportError(DO_NOT_DIE, "%s", error_message.c_str()); 1240 | return found_error; 1241 | } 1242 | 1243 | string CommandLineFlagParser::ProcessOptionsFromStringLocked( 1244 | const string& contentdata, FlagSettingMode set_mode) { 1245 | string retval; 1246 | const char* flagfile_contents = contentdata.c_str(); 1247 | bool flags_are_relevant = true; // set to false when filenames don't match 1248 | bool in_filename_section = false; 1249 | 1250 | const char* line_end = flagfile_contents; 1251 | // We read this file a line at a time. 1252 | for (; line_end; flagfile_contents = line_end + 1) { 1253 | while (*flagfile_contents && isspace(*flagfile_contents)) 1254 | ++flagfile_contents; 1255 | line_end = strchr(flagfile_contents, '\n'); 1256 | size_t len = line_end ? line_end - flagfile_contents 1257 | : strlen(flagfile_contents); 1258 | string line(flagfile_contents, len); 1259 | 1260 | // Each line can be one of four things: 1261 | // 1) A comment line -- we skip it 1262 | // 2) An empty line -- we skip it 1263 | // 3) A list of filenames -- starts a new filenames+flags section 1264 | // 4) A --flag=value line -- apply if previous filenames match 1265 | if (line.empty() || line[0] == '#') { 1266 | // comment or empty line; just ignore 1267 | 1268 | } else if (line[0] == '-') { // flag 1269 | in_filename_section = false; // instead, it was a flag-line 1270 | if (!flags_are_relevant) // skip this flag; applies to someone else 1271 | continue; 1272 | 1273 | const char* name_and_val = line.c_str() + 1; // skip the leading - 1274 | if (*name_and_val == '-') 1275 | name_and_val++; // skip second - too 1276 | string key; 1277 | const char* value; 1278 | string error_message; 1279 | CommandLineFlag* flag = registry_->SplitArgumentLocked(name_and_val, 1280 | &key, &value, 1281 | &error_message); 1282 | // By API, errors parsing flagfile lines are silently ignored. 1283 | if (flag == NULL) { 1284 | // "WARNING: flagname '" + key + "' not found\n" 1285 | } else if (value == NULL) { 1286 | // "WARNING: flagname '" + key + "' missing a value\n" 1287 | } else { 1288 | retval += ProcessSingleOptionLocked(flag, value, set_mode); 1289 | } 1290 | 1291 | } else { // a filename! 1292 | if (!in_filename_section) { // start over: assume filenames don't match 1293 | in_filename_section = true; 1294 | flags_are_relevant = false; 1295 | } 1296 | 1297 | // Split the line up at spaces into glob-patterns 1298 | const char* space = line.c_str(); // just has to be non-NULL 1299 | for (const char* word = line.c_str(); *space; word = space+1) { 1300 | if (flags_are_relevant) // we can stop as soon as we match 1301 | break; 1302 | space = strchr(word, ' '); 1303 | if (space == NULL) 1304 | space = word + strlen(word); 1305 | const string glob(word, space - word); 1306 | // We try matching both against the full argv0 and basename(argv0) 1307 | if (glob == ProgramInvocationName() // small optimization 1308 | || glob == ProgramInvocationShortName() 1309 | #if defined(HAVE_FNMATCH_H) 1310 | || fnmatch(glob.c_str(), ProgramInvocationName(), FNM_PATHNAME) == 0 1311 | || fnmatch(glob.c_str(), ProgramInvocationShortName(), FNM_PATHNAME) == 0 1312 | #elif defined(HAVE_SHLWAPI_H) 1313 | || PathMatchSpec(glob.c_str(), ProgramInvocationName()) 1314 | || PathMatchSpec(glob.c_str(), ProgramInvocationShortName()) 1315 | #endif 1316 | ) { 1317 | flags_are_relevant = true; 1318 | } 1319 | } 1320 | } 1321 | } 1322 | return retval; 1323 | } 1324 | 1325 | // -------------------------------------------------------------------- 1326 | // GetFromEnv() 1327 | // AddFlagValidator() 1328 | // These are helper functions for routines like BoolFromEnv() and 1329 | // RegisterFlagValidator, defined below. They're defined here so 1330 | // they can live in the unnamed namespace (which makes friendship 1331 | // declarations for these classes possible). 1332 | // -------------------------------------------------------------------- 1333 | 1334 | template 1335 | T GetFromEnv(const char *varname, const char* type, T dflt) { 1336 | std::string valstr; 1337 | if (SafeGetEnv(varname, valstr)) { 1338 | FlagValue ifv(new T, type, true); 1339 | if (!ifv.ParseFrom(valstr.c_str())) { 1340 | ReportError(DIE, "ERROR: error parsing env variable '%s' with value '%s'\n", 1341 | varname, valstr.c_str()); 1342 | } 1343 | return OTHER_VALUE_AS(ifv, T); 1344 | } else return dflt; 1345 | } 1346 | 1347 | bool AddFlagValidator(const void* flag_ptr, ValidateFnProto validate_fn_proto) { 1348 | // We want a lock around this routine, in case two threads try to 1349 | // add a validator (hopefully the same one!) at once. We could use 1350 | // our own thread, but we need to loook at the registry anyway, so 1351 | // we just steal that one. 1352 | FlagRegistry* const registry = FlagRegistry::GlobalRegistry(); 1353 | FlagRegistryLock frl(registry); 1354 | // First, find the flag whose current-flag storage is 'flag'. 1355 | // This is the CommandLineFlag whose current_->value_buffer_ == flag 1356 | CommandLineFlag* flag = registry->FindFlagViaPtrLocked(flag_ptr); 1357 | if (!flag) { 1358 | LOG(WARNING) << "Ignoring RegisterValidateFunction() for flag pointer " 1359 | << flag_ptr << ": no flag found at that address"; 1360 | return false; 1361 | } else if (validate_fn_proto == flag->validate_function()) { 1362 | return true; // ok to register the same function over and over again 1363 | } else if (validate_fn_proto != NULL && flag->validate_function() != NULL) { 1364 | LOG(WARNING) << "Ignoring RegisterValidateFunction() for flag '" 1365 | << flag->name() << "': validate-fn already registered"; 1366 | return false; 1367 | } else { 1368 | flag->validate_fn_proto_ = validate_fn_proto; 1369 | return true; 1370 | } 1371 | } 1372 | 1373 | } // end unnamed namespaces 1374 | 1375 | 1376 | // Now define the functions that are exported via the .h file 1377 | 1378 | // -------------------------------------------------------------------- 1379 | // FlagRegisterer 1380 | // This class exists merely to have a global constructor (the 1381 | // kind that runs before main(), that goes an initializes each 1382 | // flag that's been declared. Note that it's very important we 1383 | // don't have a destructor that deletes flag_, because that would 1384 | // cause us to delete current_storage/defvalue_storage as well, 1385 | // which can cause a crash if anything tries to access the flag 1386 | // values in a global destructor. 1387 | // -------------------------------------------------------------------- 1388 | 1389 | FlagRegisterer::FlagRegisterer(const char* name, const char* type, 1390 | const char* help, const char* filename, 1391 | void* current_storage, void* defvalue_storage) { 1392 | if (help == NULL) 1393 | help = ""; 1394 | // FlagValue expects the type-name to not include any namespace 1395 | // components, so we get rid of those, if any. 1396 | if (strchr(type, ':')) 1397 | type = strrchr(type, ':') + 1; 1398 | FlagValue* current = new FlagValue(current_storage, type, false); 1399 | FlagValue* defvalue = new FlagValue(defvalue_storage, type, false); 1400 | // Importantly, flag_ will never be deleted, so storage is always good. 1401 | CommandLineFlag* flag = new CommandLineFlag(name, help, filename, 1402 | current, defvalue); 1403 | FlagRegistry::GlobalRegistry()->RegisterFlag(flag); // default registry 1404 | } 1405 | 1406 | // -------------------------------------------------------------------- 1407 | // GetAllFlags() 1408 | // The main way the FlagRegistry class exposes its data. This 1409 | // returns, as strings, all the info about all the flags in 1410 | // the main registry, sorted first by filename they are defined 1411 | // in, and then by flagname. 1412 | // -------------------------------------------------------------------- 1413 | 1414 | struct FilenameFlagnameCmp { 1415 | bool operator()(const CommandLineFlagInfo& a, 1416 | const CommandLineFlagInfo& b) const { 1417 | int cmp = strcmp(a.filename.c_str(), b.filename.c_str()); 1418 | if (cmp == 0) 1419 | cmp = strcmp(a.name.c_str(), b.name.c_str()); // secondary sort key 1420 | return cmp < 0; 1421 | } 1422 | }; 1423 | 1424 | void GetAllFlags(vector* OUTPUT) { 1425 | FlagRegistry* const registry = FlagRegistry::GlobalRegistry(); 1426 | registry->Lock(); 1427 | for (FlagRegistry::FlagConstIterator i = registry->flags_.begin(); 1428 | i != registry->flags_.end(); ++i) { 1429 | CommandLineFlagInfo fi; 1430 | i->second->FillCommandLineFlagInfo(&fi); 1431 | OUTPUT->push_back(fi); 1432 | } 1433 | registry->Unlock(); 1434 | // Now sort the flags, first by filename they occur in, then alphabetically 1435 | sort(OUTPUT->begin(), OUTPUT->end(), FilenameFlagnameCmp()); 1436 | } 1437 | 1438 | // -------------------------------------------------------------------- 1439 | // SetArgv() 1440 | // GetArgvs() 1441 | // GetArgv() 1442 | // GetArgv0() 1443 | // ProgramInvocationName() 1444 | // ProgramInvocationShortName() 1445 | // SetUsageMessage() 1446 | // ProgramUsage() 1447 | // Functions to set and get argv. Typically the setter is called 1448 | // by ParseCommandLineFlags. Also can get the ProgramUsage string, 1449 | // set by SetUsageMessage. 1450 | // -------------------------------------------------------------------- 1451 | 1452 | // These values are not protected by a Mutex because they are normally 1453 | // set only once during program startup. 1454 | static const char* argv0 = "UNKNOWN"; // just the program name 1455 | static const char* cmdline = ""; // the entire command-line 1456 | static vector argvs; 1457 | static uint32 argv_sum = 0; 1458 | static const char* program_usage = NULL; 1459 | 1460 | void SetArgv(int argc, const char** argv) { 1461 | static bool called_set_argv = false; 1462 | if (called_set_argv) // we already have an argv for you 1463 | return; 1464 | 1465 | called_set_argv = true; 1466 | 1467 | assert(argc > 0); // every program has at least a progname 1468 | argv0 = strdup(argv[0]); // small memory leak, but fn only called once 1469 | assert(argv0); 1470 | 1471 | string cmdline_string; // easier than doing strcats 1472 | for (int i = 0; i < argc; i++) { 1473 | if (i != 0) { 1474 | cmdline_string += " "; 1475 | } 1476 | cmdline_string += argv[i]; 1477 | argvs.push_back(argv[i]); 1478 | } 1479 | cmdline = strdup(cmdline_string.c_str()); // another small memory leak 1480 | assert(cmdline); 1481 | 1482 | // Compute a simple sum of all the chars in argv 1483 | for (const char* c = cmdline; *c; c++) 1484 | argv_sum += *c; 1485 | } 1486 | 1487 | const vector& GetArgvs() { return argvs; } 1488 | const char* GetArgv() { return cmdline; } 1489 | const char* GetArgv0() { return argv0; } 1490 | uint32 GetArgvSum() { return argv_sum; } 1491 | const char* ProgramInvocationName() { // like the GNU libc fn 1492 | return GetArgv0(); 1493 | } 1494 | const char* ProgramInvocationShortName() { // like the GNU libc fn 1495 | const char* slash = strrchr(argv0, '/'); 1496 | #ifdef OS_WINDOWS 1497 | if (!slash) slash = strrchr(argv0, '\\'); 1498 | #endif 1499 | return slash ? slash + 1 : argv0; 1500 | } 1501 | 1502 | void SetUsageMessage(const string& usage) { 1503 | if (program_usage != NULL) 1504 | ReportError(DIE, "ERROR: SetUsageMessage() called twice\n"); 1505 | program_usage = strdup(usage.c_str()); // small memory leak 1506 | } 1507 | 1508 | const char* ProgramUsage() { 1509 | if (program_usage) { 1510 | return program_usage; 1511 | } 1512 | return "Warning: SetUsageMessage() never called"; 1513 | } 1514 | 1515 | // -------------------------------------------------------------------- 1516 | // SetVersionString() 1517 | // VersionString() 1518 | // -------------------------------------------------------------------- 1519 | 1520 | static const char* version_string = NULL; 1521 | 1522 | void SetVersionString(const string& version) { 1523 | if (version_string != NULL) 1524 | ReportError(DIE, "ERROR: SetVersionString() called twice\n"); 1525 | version_string = strdup(version.c_str()); // small memory leak 1526 | } 1527 | 1528 | const char* VersionString() { 1529 | return version_string ? version_string : ""; 1530 | } 1531 | 1532 | 1533 | // -------------------------------------------------------------------- 1534 | // GetCommandLineOption() 1535 | // GetCommandLineFlagInfo() 1536 | // GetCommandLineFlagInfoOrDie() 1537 | // SetCommandLineOption() 1538 | // SetCommandLineOptionWithMode() 1539 | // The programmatic way to set a flag's value, using a string 1540 | // for its name rather than the variable itself (that is, 1541 | // SetCommandLineOption("foo", x) rather than FLAGS_foo = x). 1542 | // There's also a bit more flexibility here due to the various 1543 | // set-modes, but typically these are used when you only have 1544 | // that flag's name as a string, perhaps at runtime. 1545 | // All of these work on the default, global registry. 1546 | // For GetCommandLineOption, return false if no such flag 1547 | // is known, true otherwise. We clear "value" if a suitable 1548 | // flag is found. 1549 | // -------------------------------------------------------------------- 1550 | 1551 | 1552 | bool GetCommandLineOption(const char* name, string* value) { 1553 | if (NULL == name) 1554 | return false; 1555 | assert(value); 1556 | 1557 | FlagRegistry* const registry = FlagRegistry::GlobalRegistry(); 1558 | FlagRegistryLock frl(registry); 1559 | CommandLineFlag* flag = registry->FindFlagLocked(name); 1560 | if (flag == NULL) { 1561 | return false; 1562 | } else { 1563 | *value = flag->current_value(); 1564 | return true; 1565 | } 1566 | } 1567 | 1568 | bool GetCommandLineFlagInfo(const char* name, CommandLineFlagInfo* OUTPUT) { 1569 | if (NULL == name) return false; 1570 | FlagRegistry* const registry = FlagRegistry::GlobalRegistry(); 1571 | FlagRegistryLock frl(registry); 1572 | CommandLineFlag* flag = registry->FindFlagLocked(name); 1573 | if (flag == NULL) { 1574 | return false; 1575 | } else { 1576 | assert(OUTPUT); 1577 | flag->FillCommandLineFlagInfo(OUTPUT); 1578 | return true; 1579 | } 1580 | } 1581 | 1582 | CommandLineFlagInfo GetCommandLineFlagInfoOrDie(const char* name) { 1583 | CommandLineFlagInfo info; 1584 | if (!GetCommandLineFlagInfo(name, &info)) { 1585 | fprintf(stderr, "FATAL ERROR: flag name '%s' doesn't exist\n", name); 1586 | gflags_exitfunc(1); // almost certainly gflags_exitfunc() 1587 | } 1588 | return info; 1589 | } 1590 | 1591 | string SetCommandLineOptionWithMode(const char* name, const char* value, 1592 | FlagSettingMode set_mode) { 1593 | string result; 1594 | FlagRegistry* const registry = FlagRegistry::GlobalRegistry(); 1595 | FlagRegistryLock frl(registry); 1596 | CommandLineFlag* flag = registry->FindFlagLocked(name); 1597 | if (flag) { 1598 | CommandLineFlagParser parser(registry); 1599 | result = parser.ProcessSingleOptionLocked(flag, value, set_mode); 1600 | if (!result.empty()) { // in the error case, we've already logged 1601 | // Could consider logging this change 1602 | } 1603 | } 1604 | // The API of this function is that we return empty string on error 1605 | return result; 1606 | } 1607 | 1608 | string SetCommandLineOption(const char* name, const char* value) { 1609 | return SetCommandLineOptionWithMode(name, value, SET_FLAGS_VALUE); 1610 | } 1611 | 1612 | // -------------------------------------------------------------------- 1613 | // FlagSaver 1614 | // FlagSaverImpl 1615 | // This class stores the states of all flags at construct time, 1616 | // and restores all flags to that state at destruct time. 1617 | // Its major implementation challenge is that it never modifies 1618 | // pointers in the 'main' registry, so global FLAG_* vars always 1619 | // point to the right place. 1620 | // -------------------------------------------------------------------- 1621 | 1622 | class FlagSaverImpl { 1623 | public: 1624 | // Constructs an empty FlagSaverImpl object. 1625 | explicit FlagSaverImpl(FlagRegistry* main_registry) 1626 | : main_registry_(main_registry) { } 1627 | ~FlagSaverImpl() { 1628 | // reclaim memory from each of our CommandLineFlags 1629 | vector::const_iterator it; 1630 | for (it = backup_registry_.begin(); it != backup_registry_.end(); ++it) 1631 | delete *it; 1632 | } 1633 | 1634 | // Saves the flag states from the flag registry into this object. 1635 | // It's an error to call this more than once. 1636 | // Must be called when the registry mutex is not held. 1637 | void SaveFromRegistry() { 1638 | FlagRegistryLock frl(main_registry_); 1639 | assert(backup_registry_.empty()); // call only once! 1640 | for (FlagRegistry::FlagConstIterator it = main_registry_->flags_.begin(); 1641 | it != main_registry_->flags_.end(); 1642 | ++it) { 1643 | const CommandLineFlag* main = it->second; 1644 | // Sets up all the const variables in backup correctly 1645 | CommandLineFlag* backup = new CommandLineFlag( 1646 | main->name(), main->help(), main->filename(), 1647 | main->current_->New(), main->defvalue_->New()); 1648 | // Sets up all the non-const variables in backup correctly 1649 | backup->CopyFrom(*main); 1650 | backup_registry_.push_back(backup); // add it to a convenient list 1651 | } 1652 | } 1653 | 1654 | // Restores the saved flag states into the flag registry. We 1655 | // assume no flags were added or deleted from the registry since 1656 | // the SaveFromRegistry; if they were, that's trouble! Must be 1657 | // called when the registry mutex is not held. 1658 | void RestoreToRegistry() { 1659 | FlagRegistryLock frl(main_registry_); 1660 | vector::const_iterator it; 1661 | for (it = backup_registry_.begin(); it != backup_registry_.end(); ++it) { 1662 | CommandLineFlag* main = main_registry_->FindFlagLocked((*it)->name()); 1663 | if (main != NULL) { // if NULL, flag got deleted from registry(!) 1664 | main->CopyFrom(**it); 1665 | } 1666 | } 1667 | } 1668 | 1669 | private: 1670 | FlagRegistry* const main_registry_; 1671 | vector backup_registry_; 1672 | 1673 | FlagSaverImpl(const FlagSaverImpl&); // no copying! 1674 | void operator=(const FlagSaverImpl&); 1675 | }; 1676 | 1677 | FlagSaver::FlagSaver() 1678 | : impl_(new FlagSaverImpl(FlagRegistry::GlobalRegistry())) { 1679 | impl_->SaveFromRegistry(); 1680 | } 1681 | 1682 | FlagSaver::~FlagSaver() { 1683 | impl_->RestoreToRegistry(); 1684 | delete impl_; 1685 | } 1686 | 1687 | 1688 | // -------------------------------------------------------------------- 1689 | // CommandlineFlagsIntoString() 1690 | // ReadFlagsFromString() 1691 | // AppendFlagsIntoFile() 1692 | // ReadFromFlagsFile() 1693 | // These are mostly-deprecated routines that stick the 1694 | // commandline flags into a file/string and read them back 1695 | // out again. I can see a use for CommandlineFlagsIntoString, 1696 | // for creating a flagfile, but the rest don't seem that useful 1697 | // -- some, I think, are a poor-man's attempt at FlagSaver -- 1698 | // and are included only until we can delete them from callers. 1699 | // Note they don't save --flagfile flags (though they do save 1700 | // the result of having called the flagfile, of course). 1701 | // -------------------------------------------------------------------- 1702 | 1703 | static string TheseCommandlineFlagsIntoString( 1704 | const vector& flags) { 1705 | vector::const_iterator i; 1706 | 1707 | size_t retval_space = 0; 1708 | for (i = flags.begin(); i != flags.end(); ++i) { 1709 | // An (over)estimate of how much space it will take to print this flag 1710 | retval_space += i->name.length() + i->current_value.length() + 5; 1711 | } 1712 | 1713 | string retval; 1714 | retval.reserve(retval_space); 1715 | for (i = flags.begin(); i != flags.end(); ++i) { 1716 | retval += "--"; 1717 | retval += i->name; 1718 | retval += "="; 1719 | retval += i->current_value; 1720 | retval += "\n"; 1721 | } 1722 | return retval; 1723 | } 1724 | 1725 | string CommandlineFlagsIntoString() { 1726 | vector sorted_flags; 1727 | GetAllFlags(&sorted_flags); 1728 | return TheseCommandlineFlagsIntoString(sorted_flags); 1729 | } 1730 | 1731 | bool ReadFlagsFromString(const string& flagfilecontents, 1732 | const char* /*prog_name*/, // TODO(csilvers): nix this 1733 | bool errors_are_fatal) { 1734 | FlagRegistry* const registry = FlagRegistry::GlobalRegistry(); 1735 | FlagSaverImpl saved_states(registry); 1736 | saved_states.SaveFromRegistry(); 1737 | 1738 | CommandLineFlagParser parser(registry); 1739 | registry->Lock(); 1740 | parser.ProcessOptionsFromStringLocked(flagfilecontents, SET_FLAGS_VALUE); 1741 | registry->Unlock(); 1742 | // Should we handle --help and such when reading flags from a string? Sure. 1743 | HandleCommandLineHelpFlags(); 1744 | if (parser.ReportErrors()) { 1745 | // Error. Restore all global flags to their previous values. 1746 | if (errors_are_fatal) 1747 | gflags_exitfunc(1); 1748 | saved_states.RestoreToRegistry(); 1749 | return false; 1750 | } 1751 | return true; 1752 | } 1753 | 1754 | // TODO(csilvers): nix prog_name in favor of ProgramInvocationShortName() 1755 | bool AppendFlagsIntoFile(const string& filename, const char *prog_name) { 1756 | FILE *fp; 1757 | if (SafeFOpen(&fp, filename.c_str(), "a") != 0) { 1758 | return false; 1759 | } 1760 | 1761 | if (prog_name) 1762 | fprintf(fp, "%s\n", prog_name); 1763 | 1764 | vector flags; 1765 | GetAllFlags(&flags); 1766 | // But we don't want --flagfile, which leads to weird recursion issues 1767 | vector::iterator i; 1768 | for (i = flags.begin(); i != flags.end(); ++i) { 1769 | if (strcmp(i->name.c_str(), "flagfile") == 0) { 1770 | flags.erase(i); 1771 | break; 1772 | } 1773 | } 1774 | fprintf(fp, "%s", TheseCommandlineFlagsIntoString(flags).c_str()); 1775 | 1776 | fclose(fp); 1777 | return true; 1778 | } 1779 | 1780 | bool ReadFromFlagsFile(const string& filename, const char* prog_name, 1781 | bool errors_are_fatal) { 1782 | return ReadFlagsFromString(ReadFileIntoString(filename.c_str()), 1783 | prog_name, errors_are_fatal); 1784 | } 1785 | 1786 | 1787 | // -------------------------------------------------------------------- 1788 | // BoolFromEnv() 1789 | // Int32FromEnv() 1790 | // Int64FromEnv() 1791 | // Uint64FromEnv() 1792 | // DoubleFromEnv() 1793 | // StringFromEnv() 1794 | // Reads the value from the environment and returns it. 1795 | // We use an FlagValue to make the parsing easy. 1796 | // Example usage: 1797 | // DEFINE_bool(myflag, BoolFromEnv("MYFLAG_DEFAULT", false), "whatever"); 1798 | // -------------------------------------------------------------------- 1799 | 1800 | bool BoolFromEnv(const char *v, bool dflt) { 1801 | return GetFromEnv(v, "bool", dflt); 1802 | } 1803 | int32 Int32FromEnv(const char *v, int32 dflt) { 1804 | return GetFromEnv(v, "int32", dflt); 1805 | } 1806 | int64 Int64FromEnv(const char *v, int64 dflt) { 1807 | return GetFromEnv(v, "int64", dflt); 1808 | } 1809 | uint64 Uint64FromEnv(const char *v, uint64 dflt) { 1810 | return GetFromEnv(v, "uint64", dflt); 1811 | } 1812 | double DoubleFromEnv(const char *v, double dflt) { 1813 | return GetFromEnv(v, "double", dflt); 1814 | } 1815 | 1816 | #ifdef _MSC_VER 1817 | # pragma warning(push) 1818 | # pragma warning(disable: 4996) // ignore getenv security warning 1819 | #endif 1820 | const char *StringFromEnv(const char *varname, const char *dflt) { 1821 | const char* const val = getenv(varname); 1822 | return val ? val : dflt; 1823 | } 1824 | #ifdef _MSC_VER 1825 | # pragma warning(pop) 1826 | #endif 1827 | 1828 | 1829 | // -------------------------------------------------------------------- 1830 | // RegisterFlagValidator() 1831 | // RegisterFlagValidator() is the function that clients use to 1832 | // 'decorate' a flag with a validation function. Once this is 1833 | // done, every time the flag is set (including when the flag 1834 | // is parsed from argv), the validator-function is called. 1835 | // These functions return true if the validator was added 1836 | // successfully, or false if not: the flag already has a validator, 1837 | // (only one allowed per flag), the 1st arg isn't a flag, etc. 1838 | // This function is not thread-safe. 1839 | // -------------------------------------------------------------------- 1840 | 1841 | bool RegisterFlagValidator(const bool* flag, 1842 | bool (*validate_fn)(const char*, bool)) { 1843 | return AddFlagValidator(flag, reinterpret_cast(validate_fn)); 1844 | } 1845 | bool RegisterFlagValidator(const int32* flag, 1846 | bool (*validate_fn)(const char*, int32)) { 1847 | return AddFlagValidator(flag, reinterpret_cast(validate_fn)); 1848 | } 1849 | bool RegisterFlagValidator(const int64* flag, 1850 | bool (*validate_fn)(const char*, int64)) { 1851 | return AddFlagValidator(flag, reinterpret_cast(validate_fn)); 1852 | } 1853 | bool RegisterFlagValidator(const uint64* flag, 1854 | bool (*validate_fn)(const char*, uint64)) { 1855 | return AddFlagValidator(flag, reinterpret_cast(validate_fn)); 1856 | } 1857 | bool RegisterFlagValidator(const double* flag, 1858 | bool (*validate_fn)(const char*, double)) { 1859 | return AddFlagValidator(flag, reinterpret_cast(validate_fn)); 1860 | } 1861 | bool RegisterFlagValidator(const string* flag, 1862 | bool (*validate_fn)(const char*, const string&)) { 1863 | return AddFlagValidator(flag, reinterpret_cast(validate_fn)); 1864 | } 1865 | 1866 | 1867 | // -------------------------------------------------------------------- 1868 | // ParseCommandLineFlags() 1869 | // ParseCommandLineNonHelpFlags() 1870 | // HandleCommandLineHelpFlags() 1871 | // This is the main function called from main(), to actually 1872 | // parse the commandline. It modifies argc and argv as described 1873 | // at the top of gflags.h. You can also divide this 1874 | // function into two parts, if you want to do work between 1875 | // the parsing of the flags and the printing of any help output. 1876 | // -------------------------------------------------------------------- 1877 | 1878 | static uint32 ParseCommandLineFlagsInternal(int* argc, char*** argv, 1879 | bool remove_flags, bool do_report) { 1880 | SetArgv(*argc, const_cast(*argv)); // save it for later 1881 | 1882 | FlagRegistry* const registry = FlagRegistry::GlobalRegistry(); 1883 | CommandLineFlagParser parser(registry); 1884 | 1885 | // When we parse the commandline flags, we'll handle --flagfile, 1886 | // --tryfromenv, etc. as we see them (since flag-evaluation order 1887 | // may be important). But sometimes apps set FLAGS_tryfromenv/etc. 1888 | // manually before calling ParseCommandLineFlags. We want to evaluate 1889 | // those too, as if they were the first flags on the commandline. 1890 | registry->Lock(); 1891 | parser.ProcessFlagfileLocked(FLAGS_flagfile, SET_FLAGS_VALUE); 1892 | // Last arg here indicates whether flag-not-found is a fatal error or not 1893 | parser.ProcessFromenvLocked(FLAGS_fromenv, SET_FLAGS_VALUE, true); 1894 | parser.ProcessFromenvLocked(FLAGS_tryfromenv, SET_FLAGS_VALUE, false); 1895 | registry->Unlock(); 1896 | 1897 | // Now get the flags specified on the commandline 1898 | const int r = parser.ParseNewCommandLineFlags(argc, argv, remove_flags); 1899 | 1900 | if (do_report) 1901 | HandleCommandLineHelpFlags(); // may cause us to exit on --help, etc. 1902 | 1903 | // See if any of the unset flags fail their validation checks 1904 | parser.ValidateAllFlags(); 1905 | 1906 | if (parser.ReportErrors()) // may cause us to exit on illegal flags 1907 | gflags_exitfunc(1); 1908 | return r; 1909 | } 1910 | 1911 | uint32 ParseCommandLineFlags(int* argc, char*** argv, bool remove_flags) { 1912 | return ParseCommandLineFlagsInternal(argc, argv, remove_flags, true); 1913 | } 1914 | 1915 | uint32 ParseCommandLineNonHelpFlags(int* argc, char*** argv, 1916 | bool remove_flags) { 1917 | return ParseCommandLineFlagsInternal(argc, argv, remove_flags, false); 1918 | } 1919 | 1920 | // -------------------------------------------------------------------- 1921 | // AllowCommandLineReparsing() 1922 | // ReparseCommandLineNonHelpFlags() 1923 | // This is most useful for shared libraries. The idea is if 1924 | // a flag is defined in a shared library that is dlopen'ed 1925 | // sometime after main(), you can ParseCommandLineFlags before 1926 | // the dlopen, then ReparseCommandLineNonHelpFlags() after the 1927 | // dlopen, to get the new flags. But you have to explicitly 1928 | // Allow() it; otherwise, you get the normal default behavior 1929 | // of unrecognized flags calling a fatal error. 1930 | // TODO(csilvers): this isn't used. Just delete it? 1931 | // -------------------------------------------------------------------- 1932 | 1933 | void AllowCommandLineReparsing() { 1934 | allow_command_line_reparsing = true; 1935 | } 1936 | 1937 | void ReparseCommandLineNonHelpFlags() { 1938 | // We make a copy of argc and argv to pass in 1939 | const vector& argvs = GetArgvs(); 1940 | int tmp_argc = static_cast(argvs.size()); 1941 | char** tmp_argv = new char* [tmp_argc + 1]; 1942 | for (int i = 0; i < tmp_argc; ++i) 1943 | tmp_argv[i] = strdup(argvs[i].c_str()); // TODO(csilvers): don't dup 1944 | 1945 | ParseCommandLineNonHelpFlags(&tmp_argc, &tmp_argv, false); 1946 | 1947 | for (int i = 0; i < tmp_argc; ++i) 1948 | free(tmp_argv[i]); 1949 | delete[] tmp_argv; 1950 | } 1951 | 1952 | void ShutDownCommandLineFlags() { 1953 | FlagRegistry::DeleteGlobalRegistry(); 1954 | } 1955 | 1956 | 1957 | } // namespace GFLAGS_NAMESPACE 1958 | --------------------------------------------------------------------------------