pax_global_header00006660000000000000000000000064133721164740014522gustar00rootroot0000000000000052 comment=e171aa2d15ed9eb17054558e0b3a6a413bb01067 gflags-2.2.2/000077500000000000000000000000001337211647400127705ustar00rootroot00000000000000gflags-2.2.2/.gitattributes000066400000000000000000000001611337211647400156610ustar00rootroot00000000000000# treat all files in this repository as text files # and normalize them to LF line endings when committed * text gflags-2.2.2/.gitignore000066400000000000000000000006271337211647400147650ustar00rootroot00000000000000/xcode/ /build/ /builds/ /build-*/ /_build/ .DS_Store CMakeCache.txt DartConfiguration.tcl Makefile CMakeFiles/ /Testing/ /include/gflags/config.h /include/gflags/gflags_completions.h /include/gflags/gflags_declare.h /include/gflags/gflags.h /lib/ /test/gflags_unittest_main.cc /test/gflags_unittest-main.cc /packages/ CMakeLists.txt.user /bazel-bin /bazel-genfiles /bazel-gflags /bazel-out /bazel-testlogs gflags-2.2.2/.gitmodules000066400000000000000000000001351337211647400151440ustar00rootroot00000000000000[submodule "doc"] path = doc url = https://github.com/gflags/gflags.git branch = gh-pages gflags-2.2.2/.travis.yml000066400000000000000000000006311337211647400151010ustar00rootroot00000000000000# Ubuntu 14.04 Trusty support, to get newer cmake and compilers. sudo: required dist: trusty language: cpp os: - linux - osx compiler: - clang - gcc env: - CONFIG=Release - CONFIG=Debug script: - mkdir out && cd out && cmake -D CMAKE_BUILD_TYPE=$CONFIG -D GFLAGS_BUILD_SHARED_LIBS=ON -D GFLAGS_BUILD_STATIC_LIBS=ON -D GFLAGS_BUILD_TESTING=ON .. && cmake --build . --config $CONFIG && ctest gflags-2.2.2/AUTHORS.txt000066400000000000000000000000401337211647400146500ustar00rootroot00000000000000google-gflags@googlegroups.com gflags-2.2.2/BUILD000066400000000000000000000010011337211647400135420ustar00rootroot00000000000000# Bazel (http://bazel.io/) BUILD file for gflags. # # See INSTALL.md for instructions for adding gflags to a Bazel workspace. licenses(["notice"]) exports_files(["src/gflags_completions.sh", "COPYING.txt"]) config_setting( name = "x64_windows", values = {"cpu": "x64_windows"}, ) load(":bazel/gflags.bzl", "gflags_sources", "gflags_library") (hdrs, srcs) = gflags_sources(namespace=["gflags", "google"]) gflags_library(hdrs=hdrs, srcs=srcs, threads=0) gflags_library(hdrs=hdrs, srcs=srcs, threads=1) gflags-2.2.2/CMakeLists.txt000066400000000000000000000716161337211647400155430ustar00rootroot00000000000000## CMake configuration file of gflags project ## ## This CMakeLists.txt defines some gflags specific configuration variables ## using the "gflags_define" utility macro. The default values of these variables ## can be overridden either on the CMake command-line using the -D option of ## the cmake command or in a super-project which includes the gflags source ## tree by setting the GFLAGS_ CMake variables before adding the ## gflags source directory via CMake's "add_subdirectory" command. Only when ## the non-cached variable GFLAGS_IS_SUBPROJECT has a value equivalent to FALSE, ## these configuration variables are added to the CMake cache so they can be ## edited in the CMake GUI. By default, GFLAGS_IS_SUBPROJECT is set to TRUE when ## the CMAKE_SOURCE_DIR is not identical to the directory of this CMakeLists.txt ## file, i.e., the top-level directory of the gflags project source tree. ## ## When this project is a subproject (GFLAGS_IS_SUBPROJECT is TRUE), the default ## settings are such that only the static single-threaded library is built without ## installation of the gflags files. The "gflags::gflags" target is in this case an ALIAS ## library target for the "gflags_nothreads_static" library target. Targets which ## depend on the gflags library should link to the "gflags::gflags" library target. ## ## Example CMakeLists.txt of user project which requires separate gflags installation: ## cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR) ## ## project(Foo) ## ## find_package(gflags REQUIRED) ## ## add_executable(foo src/foo.cc) ## target_link_libraries(foo gflags::gflags) ## ## Example CMakeLists.txt of user project which requires separate single-threaded static gflags installation: ## cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR) ## ## project(Foo) ## ## find_package(gflags COMPONENTS nothreads_static) ## ## add_executable(foo src/foo.cc) ## target_link_libraries(foo gflags::gflags) ## ## Example CMakeLists.txt of super-project which contains gflags source tree: ## cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR) ## ## project(Foo) ## ## add_subdirectory(gflags) ## ## add_executable(foo src/foo.cc) ## target_link_libraries(foo gflags::gflags) ## ## Variables to configure the source files: ## - GFLAGS_IS_A_DLL ## - GFLAGS_NAMESPACE ## - GFLAGS_ATTRIBUTE_UNUSED ## - GFLAGS_INTTYPES_FORMAT ## ## Variables to configure the build: ## - GFLAGS_SOVERSION ## - GFLAGS_BUILD_SHARED_LIBS ## - GFLAGS_BUILD_STATIC_LIBS ## - GFLAGS_BUILD_gflags_LIB ## - GFLAGS_BUILD_gflags_nothreads_LIB ## - GFLAGS_BUILD_TESTING ## - GFLAGS_BUILD_PACKAGING ## ## Variables to configure the installation: ## - GFLAGS_INCLUDE_DIR ## - GFLAGS_LIBRARY_INSTALL_DIR or LIB_INSTALL_DIR or LIB_SUFFIX ## - GFLAGS_INSTALL_HEADERS ## - GFLAGS_INSTALL_SHARED_LIBS ## - GFLAGS_INSTALL_STATIC_LIBS cmake_minimum_required (VERSION 3.0.2 FATAL_ERROR) if (POLICY CMP0042) cmake_policy (SET CMP0042 NEW) endif () if (POLICY CMP0048) cmake_policy (SET CMP0048 NEW) endif () # ---------------------------------------------------------------------------- # includes include ("${CMAKE_CURRENT_SOURCE_DIR}/cmake/utils.cmake") # ---------------------------------------------------------------------------- # package information set (PACKAGE_NAME "gflags") set (PACKAGE_VERSION "2.2.2") set (PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set (PACKAGE_TARNAME "${PACKAGE_NAME}-${PACKAGE_VERSION}") set (PACKAGE_BUGREPORT "https://github.com/gflags/gflags/issues") set (PACKAGE_DESCRIPTION "A commandline flags library that allows for distributed flags.") set (PACKAGE_URL "http://gflags.github.io/gflags") project (${PACKAGE_NAME} VERSION ${PACKAGE_VERSION} LANGUAGES CXX) if (CMAKE_VERSION VERSION_LESS 3.4) # C language still needed because the following required CMake modules # (or their dependencies, respectively) are not correctly handling # the case where only CXX is enabled # - CheckTypeSize.cmake (fixed in CMake 3.1, cf. https://cmake.org/Bug/view.php?id=14056) # - FindThreads.cmake (fixed in CMake 3.4, cf. https://cmake.org/Bug/view.php?id=14905) enable_language (C) endif () version_numbers ( ${PACKAGE_VERSION} PACKAGE_VERSION_MAJOR PACKAGE_VERSION_MINOR PACKAGE_VERSION_PATCH ) # shared library ABI version number, can be overridden by package maintainers # using -DGFLAGS_SOVERSION=XXX on the command-line if (GFLAGS_SOVERSION) set (PACKAGE_SOVERSION "${GFLAGS_SOVERSION}") else () # TODO: Change default SOVERSION back to PACKAGE_VERSION_MAJOR with the # next increase of major version number (i.e., 3.0.0 -> SOVERSION 3) # The . SOVERSION should be used for the 2.x releases # versions only which temporarily broke the API by changing the default # namespace from "google" to "gflags". set (PACKAGE_SOVERSION "${PACKAGE_VERSION_MAJOR}.${PACKAGE_VERSION_MINOR}") endif () # when gflags is included as subproject (e.g., as Git submodule/subtree) in the source # tree of a project that uses it, no variables should be added to the CMake cache; # users may set the non-cached variable GFLAGS_IS_SUBPROJECT before add_subdirectory(gflags) if (NOT DEFINED GFLAGS_IS_SUBPROJECT) if ("^${CMAKE_SOURCE_DIR}$" STREQUAL "^${PROJECT_SOURCE_DIR}$") set (GFLAGS_IS_SUBPROJECT FALSE) else () set (GFLAGS_IS_SUBPROJECT TRUE) endif () endif () # prefix for package variables in CMake configuration file string (TOUPPER "${PACKAGE_NAME}" PACKAGE_PREFIX) # convert file path on Windows with back slashes to path with forward slashes # otherwise this causes an issue with the cmake_install.cmake script file (TO_CMAKE_PATH "${CMAKE_INSTALL_PREFIX}" CMAKE_INSTALL_PREFIX) # ---------------------------------------------------------------------------- # options # maintain binary backwards compatibility with gflags library version <= 2.0, # but at the same time enable the use of the preferred new "gflags" namespace gflags_define (STRING NAMESPACE "Name(s) of library namespace (separate multiple options by semicolon)" "google;${PACKAGE_NAME}" "${PACKAGE_NAME}") gflags_property (NAMESPACE ADVANCED TRUE) set (GFLAGS_NAMESPACE_SECONDARY "${NAMESPACE}") list (REMOVE_DUPLICATES GFLAGS_NAMESPACE_SECONDARY) if (NOT GFLAGS_NAMESPACE_SECONDARY) message (FATAL_ERROR "GFLAGS_NAMESPACE must be set to one (or more) valid C++ namespace identifier(s separated by semicolon \";\").") endif () foreach (ns IN LISTS GFLAGS_NAMESPACE_SECONDARY) if (NOT ns MATCHES "^[a-zA-Z][a-zA-Z0-9_]*$") message (FATAL_ERROR "GFLAGS_NAMESPACE contains invalid namespace identifier: ${ns}") endif () endforeach () list (GET GFLAGS_NAMESPACE_SECONDARY 0 GFLAGS_NAMESPACE) list (REMOVE_AT GFLAGS_NAMESPACE_SECONDARY 0) # cached build options when gflags is not a subproject, otherwise non-cached CMake variables # usage: gflags_define(BOOL []) gflags_define (BOOL BUILD_SHARED_LIBS "Request build of shared libraries." OFF OFF) gflags_define (BOOL BUILD_STATIC_LIBS "Request build of static libraries (default if BUILD_SHARED_LIBS is OFF)." OFF ON) gflags_define (BOOL BUILD_gflags_LIB "Request build of the multi-threaded gflags library." ON OFF) gflags_define (BOOL BUILD_gflags_nothreads_LIB "Request build of the single-threaded gflags library." ON ON) gflags_define (BOOL BUILD_PACKAGING "Enable build of distribution packages using CPack." OFF OFF) gflags_define (BOOL BUILD_TESTING "Enable build of the unit tests and their execution using CTest." OFF OFF) gflags_define (BOOL INSTALL_HEADERS "Request installation of headers and other development files." ON OFF) gflags_define (BOOL INSTALL_SHARED_LIBS "Request installation of shared libraries." ON ON) gflags_define (BOOL INSTALL_STATIC_LIBS "Request installation of static libraries." ON OFF) gflags_define (BOOL REGISTER_BUILD_DIR "Request entry of build directory in CMake's package registry." OFF OFF) gflags_define (BOOL REGISTER_INSTALL_PREFIX "Request entry of installed package in CMake's package registry." ON OFF) gflags_property (BUILD_STATIC_LIBS ADVANCED TRUE) gflags_property (INSTALL_HEADERS ADVANCED TRUE) gflags_property (INSTALL_SHARED_LIBS ADVANCED TRUE) gflags_property (INSTALL_STATIC_LIBS ADVANCED TRUE) if (NOT GFLAGS_IS_SUBPROJECT) foreach (varname IN ITEMS CMAKE_INSTALL_PREFIX) gflags_property (${varname} ADVANCED FALSE) endforeach () foreach (varname IN ITEMS CMAKE_CONFIGURATION_TYPES CMAKE_OSX_ARCHITECTURES CMAKE_OSX_DEPLOYMENT_TARGET CMAKE_OSX_SYSROOT) gflags_property (${varname} ADVANCED TRUE) endforeach () if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CXX_FLAGS) gflags_set (CMAKE_BUILD_TYPE Release) endif () if (CMAKE_CONFIGURATION_TYPES) gflags_property (CMAKE_BUILD_TYPE STRINGS "${CMAKE_CONFIGURATION_TYPES}") endif () endif () # NOT GFLAGS_IS_SUBPROJECT if (NOT BUILD_SHARED_LIBS AND NOT BUILD_STATIC_LIBS) set (BUILD_STATIC_LIBS ON) endif () if (NOT BUILD_gflags_LIB AND NOT BUILD_gflags_nothreads_LIB) message (FATAL_ERROR "At least one of [GFLAGS_]BUILD_gflags_LIB and [GFLAGS_]BUILD_gflags_nothreads_LIB must be ON.") endif () gflags_define (STRING INCLUDE_DIR "Name of include directory of installed header files relative to CMAKE_INSTALL_PREFIX/include/" "${PACKAGE_NAME}") gflags_property (INCLUDE_DIR ADVANCED TRUE) file (TO_CMAKE_PATH "${INCLUDE_DIR}" INCLUDE_DIR) if (IS_ABSOLUTE INCLUDE_DIR) message (FATAL_ERROR "[GFLAGS_]INCLUDE_DIR must be a path relative to CMAKE_INSTALL_PREFIX/include/") endif () if (INCLUDE_DIR MATCHES "^\\.\\.[/\\]") message (FATAL_ERROR "[GFLAGS_]INCLUDE_DIR must not start with parent directory reference (../)") endif () set (GFLAGS_INCLUDE_DIR "${INCLUDE_DIR}") # ---------------------------------------------------------------------------- # system checks include (CheckTypeSize) include (CheckIncludeFileCXX) include (CheckCXXSymbolExists) if (WIN32 AND NOT CYGWIN) set (OS_WINDOWS 1) else () set (OS_WINDOWS 0) endif () if (MSVC) set (HAVE_SYS_TYPES_H 1) set (HAVE_STDDEF_H 1) # used by CheckTypeSize module set (HAVE_UNISTD_H 0) set (HAVE_SYS_STAT_H 1) set (HAVE_SHLWAPI_H 1) if (MSVC_VERSION VERSION_LESS 1600) check_include_file_cxx ("stdint.h" HAVE_STDINT_H) bool_to_int (HAVE_STDINT_H) # used in #if directive else () set (HAVE_STDINT_H 1) endif () if (MSVC_VERSION VERSION_LESS 1800) check_include_file_cxx ("inttypes.h" HAVE_INTTYPES_H) bool_to_int (HAVE_INTTYPES_H) # used in #if directive else () set (HAVE_INTTYPES_H 1) endif () else () foreach (fname IN ITEMS unistd stdint inttypes sys/types sys/stat fnmatch) string (TOUPPER "${fname}" FNAME) string (REPLACE "/" "_" FNAME "${FNAME}") if (NOT HAVE_${FNAME}_H) check_include_file_cxx ("${fname}.h" HAVE_${FNAME}_H) endif () endforeach () if (NOT HAVE_FNMATCH_H AND OS_WINDOWS) check_include_file_cxx ("shlwapi.h" HAVE_SHLWAPI_H) endif () # the following are used in #if directives not #ifdef bool_to_int (HAVE_STDINT_H) bool_to_int (HAVE_SYS_TYPES_H) bool_to_int (HAVE_INTTYPES_H) endif () gflags_define (STRING INTTYPES_FORMAT "Format of integer types: \"C99\" (uint32_t), \"BSD\" (u_int32_t), \"VC7\" (__int32)" "") gflags_property (INTTYPES_FORMAT STRINGS "C99;BSD;VC7") gflags_property (INTTYPES_FORMAT ADVANCED TRUE) if (NOT INTTYPES_FORMAT) set (TYPES uint32_t u_int32_t) if (MSVC) list (INSERT TYPES 0 __int32) endif () foreach (type IN LISTS TYPES) check_type_size (${type} ${type} LANGUAGE CXX) if (HAVE_${type}) break () endif () endforeach () if (HAVE_uint32_t) gflags_set (INTTYPES_FORMAT C99) elseif (HAVE_u_int32_t) gflags_set (INTTYPES_FORMAT BSD) elseif (HAVE___int32) gflags_set (INTTYPES_FORMAT VC7) else () gflags_property (INTTYPES_FORMAT ADVANCED FALSE) message (FATAL_ERROR "Do not know how to define a 32-bit integer quantity on your system!" " Neither uint32_t, u_int32_t, nor __int32 seem to be available." " Set [GFLAGS_]INTTYPES_FORMAT to either C99, BSD, or VC7 and try again.") endif () endif () # use of special characters in strings to circumvent bug #0008226 if ("^${INTTYPES_FORMAT}$" STREQUAL "^WIN$") gflags_set (INTTYPES_FORMAT VC7) endif () if (NOT INTTYPES_FORMAT MATCHES "^(C99|BSD|VC7)$") message (FATAL_ERROR "Invalid value for [GFLAGS_]INTTYPES_FORMAT! Choose one of \"C99\", \"BSD\", or \"VC7\"") endif () set (GFLAGS_INTTYPES_FORMAT "${INTTYPES_FORMAT}") set (GFLAGS_INTTYPES_FORMAT_C99 0) set (GFLAGS_INTTYPES_FORMAT_BSD 0) set (GFLAGS_INTTYPES_FORMAT_VC7 0) set ("GFLAGS_INTTYPES_FORMAT_${INTTYPES_FORMAT}" 1) if (MSVC) set (HAVE_strtoll 0) set (HAVE_strtoq 0) else () check_cxx_symbol_exists (strtoll stdlib.h HAVE_STRTOLL) if (NOT HAVE_STRTOLL) check_cxx_symbol_exists (strtoq stdlib.h HAVE_STRTOQ) endif () endif () if (BUILD_gflags_LIB) set (CMAKE_THREAD_PREFER_PTHREAD TRUE) find_package (Threads) if (Threads_FOUND AND CMAKE_USE_PTHREADS_INIT) set (HAVE_PTHREAD 1) check_type_size (pthread_rwlock_t RWLOCK LANGUAGE CXX) else () set (HAVE_PTHREAD 0) endif () if (UNIX AND NOT HAVE_PTHREAD) if (CMAKE_HAVE_PTHREAD_H) set (what "library") else () set (what ".h file") endif () message (FATAL_ERROR "Could not find pthread${what}. Check the log file" "\n\t${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log" "\nor disable the build of the multi-threaded gflags library (BUILD_gflags_LIB=OFF).") endif () else () set (HAVE_PTHREAD 0) endif () # ---------------------------------------------------------------------------- # source files - excluding root subdirectory and/or .in suffix set (PUBLIC_HDRS "gflags.h" "gflags_declare.h" "gflags_completions.h" ) if (GFLAGS_NAMESPACE_SECONDARY) set (INCLUDE_GFLAGS_NS_H "// Import gflags library symbols into alternative/deprecated namespace(s)") foreach (ns IN LISTS GFLAGS_NAMESPACE_SECONDARY) string (TOUPPER "${ns}" NS) set (gflags_ns_h "${PROJECT_BINARY_DIR}/include/${GFLAGS_INCLUDE_DIR}/gflags_${ns}.h") configure_file ("${PROJECT_SOURCE_DIR}/src/gflags_ns.h.in" "${gflags_ns_h}" @ONLY) list (APPEND PUBLIC_HDRS "${gflags_ns_h}") set (INCLUDE_GFLAGS_NS_H "${INCLUDE_GFLAGS_NS_H}\n#include \"gflags_${ns}.h\"") endforeach () else () set (INCLUDE_GFLAGS_NS_H) endif () set (PRIVATE_HDRS "defines.h" "config.h" "util.h" "mutex.h" ) set (GFLAGS_SRCS "gflags.cc" "gflags_reporting.cc" "gflags_completions.cc" ) if (OS_WINDOWS) list (APPEND PRIVATE_HDRS "windows_port.h") list (APPEND GFLAGS_SRCS "windows_port.cc") endif () # ---------------------------------------------------------------------------- # configure source files if (NOT DEFINED GFLAGS_ATTRIBUTE_UNUSED) if (CMAKE_COMPILER_IS_GNUCXX) set (GFLAGS_ATTRIBUTE_UNUSED "__attribute((unused))") else () set (GFLAGS_ATTRIBUTE_UNUSED) endif () endif () # whenever we build a shared library (DLL on Windows), configure the public # headers of the API for use of this shared library rather than the optionally # also build statically linked library; users can override GFLAGS_DLL_DECL # in particular, this done by setting the INTERFACE_COMPILE_DEFINITIONS of # static libraries to include an empty definition for GFLAGS_DLL_DECL if (NOT DEFINED GFLAGS_IS_A_DLL) if (BUILD_SHARED_LIBS) set (GFLAGS_IS_A_DLL 1) else () set (GFLAGS_IS_A_DLL 0) endif () endif () configure_headers (PUBLIC_HDRS ${PUBLIC_HDRS}) configure_sources (PRIVATE_HDRS ${PRIVATE_HDRS}) configure_sources (GFLAGS_SRCS ${GFLAGS_SRCS}) # ---------------------------------------------------------------------------- # output directories if (NOT GFLAGS_IS_SUBPROJECT) set (CMAKE_RUNTIME_OUTPUT_DIRECTORY "bin") set (CMAKE_LIBRARY_OUTPUT_DIRECTORY "lib") set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY "lib") endif () # Set postfixes for generated libraries based on buildtype. set(CMAKE_RELEASE_POSTFIX "") set(CMAKE_DEBUG_POSTFIX "_debug") # ---------------------------------------------------------------------------- # installation directories if (OS_WINDOWS) set (RUNTIME_INSTALL_DIR "bin") set (LIBRARY_INSTALL_DIR "lib") set (INCLUDE_INSTALL_DIR "include") set (CONFIG_INSTALL_DIR "lib/cmake/${PACKAGE_NAME}") set (PKGCONFIG_INSTALL_DIR) else () set (RUNTIME_INSTALL_DIR bin) # The LIB_INSTALL_DIR and LIB_SUFFIX variables are used by the Fedora # package maintainers. Also package maintainers of other distribution # packages need to be able to specify the name of the library directory. if (NOT GFLAGS_LIBRARY_INSTALL_DIR AND LIB_INSTALL_DIR) set (GFLAGS_LIBRARY_INSTALL_DIR "${LIB_INSTALL_DIR}") endif () gflags_define (PATH LIBRARY_INSTALL_DIR "Directory of installed libraries, e.g., \"lib64\"" "lib${LIB_SUFFIX}") gflags_property (LIBRARY_INSTALL_DIR ADVANCED TRUE) set (INCLUDE_INSTALL_DIR include) set (CONFIG_INSTALL_DIR ${LIBRARY_INSTALL_DIR}/cmake/${PACKAGE_NAME}) set (PKGCONFIG_INSTALL_DIR ${LIBRARY_INSTALL_DIR}/pkgconfig) endif () # ---------------------------------------------------------------------------- # add library targets set (TARGETS) # static vs. shared foreach (TYPE IN ITEMS STATIC SHARED) if (BUILD_${TYPE}_LIBS) string (TOLOWER "${TYPE}" type) # whether or not targets are a DLL if (OS_WINDOWS AND "^${TYPE}$" STREQUAL "^SHARED$") set (GFLAGS_IS_A_DLL 1) else () set (GFLAGS_IS_A_DLL 0) endif () # filename suffix for static libraries on Windows if (OS_WINDOWS AND "^${TYPE}$" STREQUAL "^STATIC$") set (type_suffix "_${type}") else () set (type_suffix "") endif () # multi-threaded vs. single-threaded foreach (opts IN ITEMS "" _nothreads) if (BUILD_gflags${opts}_LIB) set (target_name "gflags${opts}_${type}") add_library (${target_name} ${TYPE} ${GFLAGS_SRCS} ${PRIVATE_HDRS} ${PUBLIC_HDRS}) set_target_properties (${target_name} PROPERTIES OUTPUT_NAME "gflags${opts}${type_suffix}" VERSION "${PACKAGE_VERSION}" SOVERSION "${PACKAGE_SOVERSION}" ) set (include_dirs "$") if (INSTALL_HEADERS) list (APPEND include_dirs "$") endif () target_include_directories (${target_name} PUBLIC "${include_dirs}" PRIVATE "${PROJECT_SOURCE_DIR}/src;${PROJECT_BINARY_DIR}/include/${GFLAGS_INCLUDE_DIR}" ) target_compile_definitions (${target_name} PUBLIC GFLAGS_IS_A_DLL=${GFLAGS_IS_A_DLL}) if (opts MATCHES "nothreads") target_compile_definitions (${target_name} PRIVATE NO_THREADS) elseif (CMAKE_USE_PTHREADS_INIT) target_link_libraries (${target_name} ${CMAKE_THREAD_LIBS_INIT}) endif () if (HAVE_SHLWAPI_H) target_link_libraries (${target_name} shlwapi.lib) endif () list (APPEND TARGETS ${target_name}) # add convenience make target for build of both shared and static libraries if (NOT GFLAGS_IS_SUBPROJECT) if (NOT TARGET gflags${opts}) add_custom_target (gflags${opts}) endif () add_dependencies (gflags${opts} ${target_name}) endif () endif () endforeach () endif () endforeach () # add ALIAS target for use in super-project, prefer static over shared, single-threaded over multi-threaded if (GFLAGS_IS_SUBPROJECT) foreach (type IN ITEMS static shared) foreach (opts IN ITEMS "_nothreads" "") if (TARGET gflags${opts}_${type}) # Define "gflags" alias for super-projects treating targets of this library as part of their own project # (also for backwards compatibility with gflags 2.2.1 which only defined this alias) add_library (gflags ALIAS gflags${opts}_${type}) # Define "gflags::gflags" alias for projects that support both find_package(gflags) and add_subdirectory(gflags) add_library (gflags::gflags ALIAS gflags${opts}_${type}) break () endif () endforeach () if (TARGET gflags::gflags) break () endif () endforeach () endif () # ---------------------------------------------------------------------------- # installation rules set (EXPORT_NAME ${PACKAGE_NAME}-targets) file (RELATIVE_PATH INSTALL_PREFIX_REL2CONFIG_DIR "${CMAKE_INSTALL_PREFIX}/${CONFIG_INSTALL_DIR}" "${CMAKE_INSTALL_PREFIX}") configure_file (cmake/config.cmake.in "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}-config-install.cmake" @ONLY) configure_file (cmake/version.cmake.in "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}-config-version.cmake" @ONLY) if (BUILD_SHARED_LIBS AND INSTALL_SHARED_LIBS) foreach (opts IN ITEMS "" _nothreads) if (BUILD_gflags${opts}_LIB) install (TARGETS gflags${opts}_shared EXPORT ${EXPORT_NAME} RUNTIME DESTINATION ${RUNTIME_INSTALL_DIR} LIBRARY DESTINATION ${LIBRARY_INSTALL_DIR} ARCHIVE DESTINATION ${LIBRARY_INSTALL_DIR} ) endif () endforeach () endif () if (BUILD_STATIC_LIBS AND INSTALL_STATIC_LIBS) foreach (opts IN ITEMS "" _nothreads) if (BUILD_gflags${opts}_LIB) install (TARGETS gflags${opts}_static EXPORT ${EXPORT_NAME} RUNTIME DESTINATION ${RUNTIME_INSTALL_DIR} LIBRARY DESTINATION ${LIBRARY_INSTALL_DIR} ARCHIVE DESTINATION ${LIBRARY_INSTALL_DIR} ) endif () endforeach () endif () if (INSTALL_HEADERS) install (FILES ${PUBLIC_HDRS} DESTINATION ${INCLUDE_INSTALL_DIR}/${GFLAGS_INCLUDE_DIR}) install ( FILES "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}-config-install.cmake" RENAME ${PACKAGE_NAME}-config.cmake DESTINATION ${CONFIG_INSTALL_DIR} ) install ( FILES "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}-config-version.cmake" DESTINATION ${CONFIG_INSTALL_DIR} ) install ( EXPORT ${EXPORT_NAME} NAMESPACE ${PACKAGE_NAME}:: DESTINATION ${CONFIG_INSTALL_DIR} ) install ( EXPORT ${EXPORT_NAME} FILE ${PACKAGE_NAME}-nonamespace-targets.cmake DESTINATION ${CONFIG_INSTALL_DIR} ) if (UNIX) install (PROGRAMS src/gflags_completions.sh DESTINATION ${RUNTIME_INSTALL_DIR}) endif () endif () if (PKGCONFIG_INSTALL_DIR) configure_file ("cmake/package.pc.in" "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}.pc" @ONLY) install (FILES "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}.pc" DESTINATION "${PKGCONFIG_INSTALL_DIR}") endif () # ---------------------------------------------------------------------------- # support direct use of build tree set (INSTALL_PREFIX_REL2CONFIG_DIR .) export ( TARGETS ${TARGETS} NAMESPACE ${PACKAGE_NAME}:: FILE "${PROJECT_BINARY_DIR}/${EXPORT_NAME}.cmake" ) export ( TARGETS ${TARGETS} FILE "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}-nonamespace-targets.cmake" ) if (REGISTER_BUILD_DIR) export (PACKAGE ${PACKAGE_NAME}) endif () if (REGISTER_INSTALL_PREFIX) register_gflags_package(${CONFIG_INSTALL_DIR}) endif () configure_file (cmake/config.cmake.in "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}-config.cmake" @ONLY) # ---------------------------------------------------------------------------- # testing - MUST follow the generation of the build tree config file if (BUILD_TESTING) include (CTest) add_subdirectory (test) endif () # ---------------------------------------------------------------------------- # packaging if (BUILD_PACKAGING) if (NOT BUILD_SHARED_LIBS AND NOT INSTALL_HEADERS) message (WARNING "Package will contain static libraries without headers!" "\nRecommended options for generation of runtime package:" "\n BUILD_SHARED_LIBS=ON" "\n BUILD_STATIC_LIBS=OFF" "\n INSTALL_HEADERS=OFF" "\n INSTALL_SHARED_LIBS=ON" "\nRecommended options for generation of development package:" "\n BUILD_SHARED_LIBS=ON" "\n BUILD_STATIC_LIBS=ON" "\n INSTALL_HEADERS=ON" "\n INSTALL_SHARED_LIBS=ON" "\n INSTALL_STATIC_LIBS=ON" ) endif () # default package generators if (APPLE) set (PACKAGE_GENERATOR "PackageMaker") set (PACKAGE_SOURCE_GENERATOR "TGZ;ZIP") elseif (UNIX) set (PACKAGE_GENERATOR "DEB;RPM") set (PACKAGE_SOURCE_GENERATOR "TGZ;ZIP") else () set (PACKAGE_GENERATOR "ZIP") set (PACKAGE_SOURCE_GENERATOR "ZIP") endif () # used package generators set (CPACK_GENERATOR "${PACKAGE_GENERATOR}" CACHE STRING "List of binary package generators (CPack).") set (CPACK_SOURCE_GENERATOR "${PACKAGE_SOURCE_GENERATOR}" CACHE STRING "List of source package generators (CPack).") mark_as_advanced (CPACK_GENERATOR CPACK_SOURCE_GENERATOR) # some package generators (e.g., PackageMaker) do not allow .md extension configure_file ("${CMAKE_CURRENT_LIST_DIR}/README.md" "${CMAKE_CURRENT_BINARY_DIR}/README.txt" COPYONLY) # common package information set (CPACK_PACKAGE_VENDOR "Andreas Schuh") set (CPACK_PACKAGE_CONTACT "google-gflags@googlegroups.com") set (CPACK_PACKAGE_NAME "${PACKAGE_NAME}") set (CPACK_PACKAGE_VERSION "${PACKAGE_VERSION}") set (CPACK_PACKAGE_VERSION_MAJOR "${PACKAGE_VERSION_MAJOR}") set (CPACK_PACKAGE_VERSION_MINOR "${PACKAGE_VERSION_MINOR}") set (CPACK_PACKAGE_VERSION_PATCH "${PACKAGE_VERSION_PATCH}") set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PACKAGE_DESCRIPTION}") set (CPACK_RESOURCE_FILE_WELCOME "${CMAKE_CURRENT_BINARY_DIR}/README.txt") set (CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_LIST_DIR}/COPYING.txt") set (CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_BINARY_DIR}/README.txt") set (CPACK_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") set (CPACK_OUTPUT_FILE_PREFIX packages) set (CPACK_PACKAGE_RELOCATABLE TRUE) set (CPACK_MONOLITHIC_INSTALL TRUE) # RPM package information -- used in cmake/package.cmake.in also for DEB set (CPACK_RPM_PACKAGE_GROUP "Development/Libraries") set (CPACK_RPM_PACKAGE_LICENSE "BSD") set (CPACK_RPM_PACKAGE_URL "${PACKAGE_URL}") set (CPACK_RPM_CHANGELOG_FILE "${CMAKE_CURRENT_LIST_DIR}/ChangeLog.txt") if (INSTALL_HEADERS) set (CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_LIST_DIR}/doc/index.html") else () set (CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_LIST_DIR}/cmake/README_runtime.txt") endif () # system/architecture if (WINDOWS) if (CMAKE_CL_64) set (CPACK_SYSTEM_NAME "win64") else () set (CPACK_SYSTEM_NAME "win32") endif () set (CPACK_PACKAGE_ARCHITECTURE) elseif (APPLE) set (CPACK_PACKAGE_ARCHITECTURE darwin) else () string (TOLOWER "${CMAKE_SYSTEM_NAME}" CPACK_SYSTEM_NAME) if (CMAKE_CXX_FLAGS MATCHES "-m32") set (CPACK_PACKAGE_ARCHITECTURE i386) else () execute_process ( COMMAND dpkg --print-architecture RESULT_VARIABLE RV OUTPUT_VARIABLE CPACK_PACKAGE_ARCHITECTURE ) if (RV EQUAL 0) string (STRIP "${CPACK_PACKAGE_ARCHITECTURE}" CPACK_PACKAGE_ARCHITECTURE) else () execute_process (COMMAND uname -m OUTPUT_VARIABLE CPACK_PACKAGE_ARCHITECTURE) if (CPACK_PACKAGE_ARCHITECTURE MATCHES "x86_64") set (CPACK_PACKAGE_ARCHITECTURE amd64) else () set (CPACK_PACKAGE_ARCHITECTURE i386) endif () endif () endif () endif () # source package settings set (CPACK_SOURCE_TOPLEVEL_TAG "source") set (CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}") set (CPACK_SOURCE_IGNORE_FILES "/\\\\.git/;\\\\.swp$;\\\\.#;/#;\\\\.*~;cscope\\\\.*;/[Bb]uild[.+-_a-zA-Z0-9]*/") # default binary package settings set (CPACK_INCLUDE_TOPLEVEL_DIRECTORY TRUE) set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CPACK_SYSTEM_NAME}") if (CPACK_PACKAGE_ARCHITECTURE) set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-${CPACK_PACKAGE_ARCHITECTURE}") endif () # generator specific configuration file # # allow package maintainers to use their own configuration file # $ cmake -DCPACK_PROJECT_CONFIG_FILE:FILE=/path/to/package/config if (NOT CPACK_PROJECT_CONFIG_FILE) configure_file ( "${CMAKE_CURRENT_LIST_DIR}/cmake/package.cmake.in" "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}-package.cmake" @ONLY ) set (CPACK_PROJECT_CONFIG_FILE "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}-package.cmake") endif () include (CPack) endif () # BUILD_PACKAGING if (NOT GFLAGS_IS_SUBPROJECT AND NOT TARGET uninstall) configure_file ( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" @ONLY ) add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") endif () gflags-2.2.2/COPYING.txt000066400000000000000000000027071337211647400146470ustar00rootroot00000000000000Copyright (c) 2006, Google Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. gflags-2.2.2/ChangeLog.txt000066400000000000000000000313721337211647400153660ustar00rootroot00000000000000* Sun Nov 11 2018 - Andreas Schuh - gflags: version 2.2.2 Fixed 267: Support build with GCC option "-fvisibility=hidden". Fixed 262: Declare FALGS_no##name variables as static to avoid "previous extern" warning. Fixed 261: Declare FlagRegisterer c’tor explicit template instanations as extern in header Fixed 257: Build with _UNICODE support on Windows. Fixed 233/234/235: Move CMake defines that are unused by Bazel to separate header; makes config.h private again Fixed 228: Build with recent MinGW versions that define setenv. Fixed 226: Remove obsolete and unused CleanFileName code Merged 266: Various PVS Studio and GCC warnings. Merged 258: Fix build with some Clang variants that define "restrict" macro. Merged 252: Update documentation on how to use Bazel. Merged 249: Use "_debug" postfix for debug libraries. Merged 247: CMake "project" VERSION; no enable_testing(); "gflags::" import target prefix. Merged 246: Add Bazel-on-Windows support. Merged 239: Use GFLAGS_NAMESPACE instead of "gflags" in test executable. Merged 237: Removed unused functions; fixes compilation with -Werror compiler option. Merged 232: Fix typo in Bazel's BUILD definition Merged 230: Remove using ::fLS::clstring. Merged 221: Add convenience 'uninstall' target * Tue Jul 11 2017 - Andreas Schuh - gflags: version 2.2.1 - Link to online documentation in README - Merged 194: Include utils by file instead of CMAKE_MODULE_PATH search - Merged 195: Remove unused program_name variable - Merged 196: Enable language C for older CMake versions when needed - Merged 202: Changed include directory in bazel build - Merged 207: Mark single argument constructors in mutex.h as explicit - Merged 209: Use inttypes.h on VC++ 2013 and later - Merged 212: Fix statically linked gflags library with MSVC - Meregd 213: Modify installation paths on Windows for vcpkg - Merged 215: Fix static initialization order fiasco caused by global registry lock - Merged 216: Fix use of ARGC in CMake macros - Merged 222: Static code analyzer error regarding strncmp with empty kRootDir - Merged 224: Check HAVE_STDINT_H or HAVE_INTTYPES_H for older MSVC versions * Fri Nov 25 2016 - Andreas Schuh - gflags: version 2.2.0 - Merged 178: Implicitly convert dashes in option names to underscores - Merged 159: CI builds and automatic tests with Travis CI and AppVeyor - Merged 158: Use enum for flag value types - Merged 126: File name postfix for static libraries on Windows - Closed issue 120: Configure and install gflags.pc file for pkg-config users - Fixed issue 127: snprintf already defined when building with MSVC 2015 - Fixed issue 51/138: Memory leaks reported by valgrind - Fixed issue 173: Validate flags only once - Fixed issue 168: Unsigned and signed comparison in gflags_reporting.cc - Fixed issues 176/153: Add -lpthread link argument to Bazel build, refactor BUILD rules - Fixed issue 89: Add GFLAGS_IS_A_DLL to imported CMake target INTERFACE_COMPILE_DEFINITIONS - Fixed issue 104: Set INTERFACE_INCLUDE_DIRECTORIES of exported CMake targets - Fixed issue 174: Missing gflags-targets.cmake file after installation - Fixed issue 186: Error linking to gflags IMPLIB with MSVC using CMake - Closed issue 106: Add example project to test use of gflags library * Tue Mar 24 2014 - Andreas Schuh - gflags: version 2.1.2 - Moved project to GitHub - Added GFLAGS_NAMESPACE definition to gflags_declare.h - Fixed issue 94: Keep "google" as primary namespace and import symbols into "gflags" namespace - Fixed issue 96: Fix binary ABI compatibility with gflags 2.0 using "google" as primary namespace - Fixed issue 97/101: Removed (patched) CMake modules and enabled C language instead - Fixed issue 103: Set CMake policy CMP0042 to silence warning regarding MACOS_RPATH setting * Sun Mar 20 2014 - Andreas Schuh - gflags: version 2.1.1 - Fixed issue 77: GFLAGS_IS_A_DLL expands to empty string in gflags_declare.h - Fixed issue 79: GFLAGS_NAMESPACE not expanded to actual namespace in gflags_declare.h - Fixed issue 80: Allow include path to differ from GFLAGS_NAMESPACE * Thu Mar 20 2014 - Andreas Schuh - gflags: version 2.1.0 - Build system configuration using CMake instead of autotools - CPack packaging support for Debian/Ubuntu, Red Hat, and Mac OS X - Fixed issue 54: Fix "invalid suffix on literal" (C++11) - Fixed issue 57: Use _strdup instead of strdup on Windows - Fixed issue 62: Change all preprocessor include guards to start with GFLAGS_ - Fixed issue 64: Add DEFINE_validator macro - Fixed issue 73: Warnings in Visual Studio 2010 and unable to compile unit test * Wed Jan 25 2012 - Google Inc. - gflags: version 2.0 - Changed the 'official' gflags email in setup.py/etc - Renamed google-gflags.sln to gflags.sln - Changed copyright text to reflect Google's relinquished ownership * Tue Dec 20 2011 - Google Inc. - google-gflags: version 1.7 - Add CommandLineFlagInfo::flag_ptr pointing to current storage (musji) - PORTING: flush after writing to stderr, needed on cygwin - PORTING: Clean up the GFLAGS_DLL_DECL stuff better - Fix a bug in StringPrintf() that affected large strings (csilvers) - Die at configure-time when g++ isn't installed * Fri Jul 29 2011 - Google Inc. - google-gflags: version 1.6 - BUGFIX: Fix a bug where we were leaving out a required $(top_srcdir) - Fix definition of clstring (jyrki) - Split up flag declares into its own file (jyrki) - Add --version support (csilvers) - Update the README for gflags with static libs - Update acx_pthread.m4 for nostdlib - Change ReparseCommandLineFlags to return void (csilvers) - Some doc typofixes and example augmentation (various) * Mon Jan 24 2011 - Google Inc. - google-gflags: version 1.5 - Better reporting of current vs default value (handler) - Add API for cleaning up of memory at program-exit (jmarantz) - Fix macros to work inside namespaces (csilvers) - Use our own string typedef in case string is redefined (csilvers) - Updated to autoconf 2.65 * Wed Oct 13 2010 - Google Inc. - google-gflags: version 1.4 - Add a check to prevent passing 0 to DEFINE_string (jorg) - Reduce compile (.o) size (jyrki) - Some small changes to quiet debug compiles (alexk) - PORTING: better support static linking on windows (csilvers) - DOCUMENTATION: change default values, use validators, etc. - Update the NEWS file to be non-empty - Add pkg-config (.pc) files for libgflags and libgflags_nothreads * Mon Jan 4 2010 - Google Inc. - google-gflags: version 1.3 - PORTABILITY: can now build and run tests under MSVC (csilvers) - Remove the python gflags code, which is now its own package (tansell) - Clarify that "last flag wins" in the docs (csilvers) - Comment danger of using GetAllFlags in validators (wojtekm) - PORTABILITY: Some fixes necessary for c++0x (mboerger) - Makefile fix: $(srcdir) -> $(top_srcdir) in one place (csilvres) - INSTALL: autotools to autoconf v2.64 + automake v1.11 (csilvers) * Thu Sep 10 2009 - Google Inc. - google-gflags: version 1.2 - PORTABILITY: can now build and run tests under mingw (csilvers) - Using a string arg for a bool flag is a compile-time error (rbayardo) - Add --helpxml to gflags.py (salcianu) - Protect against a hypothetical global d'tor mutex problem (csilvers) - BUGFIX: can now define a flag after 'using namespace google' (hamaji) * Tue Apr 14 2009 - Google Inc. - google-gflags: version 1.1 - Add both foo and nofoo for boolean flags, with --undefok (andychu) - Better document how validators work (wojtekm) - Improve binary-detection for bash-completion (mtamsky) - Python: Add a concept of "key flags", used with --help (salcianu) - Python: Robustify flag_values (salcianu) - Python: Add a new DEFINE_bool alias (keir, andrewliu) - Python: Do module introspection based on module name (dsturtevant) - Fix autoconf a bit better, especially on windows and solaris (ajenjo) - BUG FIX: gflags_nothreads was linking against the wrong lib (ajenjo) - BUG FIX: threads-detection failed on FreeBSD; replace it (ajenjo) - PORTABILITY: Quiet an internal compiler error with SUSE 10 (csilvers) - PORTABILITY: Update deb.sh for more recenty debuilds (csilvers) - PORTABILITY: #include more headers to satify new gcc's (csilvers) - INSTALL: Updated to autoconf 2.61 and libtool 1.5.26 (csilvers) * Fri Oct 3 2008 - Google Inc. - google-gflags: version 1.0 - Add a missing newline to an error string (bcmills) - (otherwise exactly the same as gflags 1.0rc2) * Thu Sep 18 2008 - Google Inc. - google-gflags: version 1.0rc2 - Report current flag values in --helpxml (hdn) - Fix compilation troubles with gcc 4.3.3 (simonb) - BUG FIX: I was missing a std:: in DECLARE_string (csilvers) - BUG FIX: Clarify in docs how to specify --bool flags (csilvers) - BUG FIX: Fix --helpshort for source files not in a subdir (csilvers) - BUG FIX: Fix python unittest for 64-bit builds (bcmills) * Tue Aug 19 2008 - Google Inc. - google-gflags: version 1.0rc1 - Move #include files from google/ to gflags/ (csilvers) - Small optimizations to reduce binary (library) size (jyrki) - BUGFIX: forgot a std:: in one of the .h files (csilvers) - Speed up locking by making sure calls are inlined (ajenjo) - 64-BIT COMPATIBILITY: Use %PRId64 instead of %lld (csilvers) - PORTABILITY: fix Makefile to work with Cygwin (ajenjo) - PORTABILITY: fix code to compile under Visual Studio (ajenjo) - PORTABILITY: fix code to compile under Solaris 10 with CC (csilvers) * Mon Jul 21 2008 - Google Inc. - google-gflags: version 0.9 - Add the ability to validate a command-line flag (csilvers) - Add completion support for commandline flags in bash (daven) - Add -W compile flags to Makefile, when using gcc (csilvers) - Allow helpstring to be NULL (cristianoc) - Improved documentation of classes in the .cc file (csilvers) - Fix python bug with AppendFlagValues + shortnames (jjtswan) - Use bool instead of int for boolean flags in gflags.py (bcmills) - Simplify the way we declare flags, now more foolproof (csilvers) - Better error messages when bool flags collide (colohan) - Only evaluate DEFINE_foo macro args once (csilvers) * Wed Mar 26 2008 - Google Inc. - google-gflags: version 0.8 - Export DescribeOneFlag() in the API - Add support for automatic line wrapping at 80 cols for gflags.py - Bugfix: do not treat an isolated "-" the same as an isolated "--" - Update rpm spec to point to Google Code rather than sourceforge (!) - Improve documentation (including documenting thread-safety) - Improve #include hygiene - Improve testing * Thu Oct 18 2007 - Google Inc. - google-gflags: version 0.7 - Deal even more correctly with libpthread not linked in (csilvers) - Add STRIP_LOG, an improved DO_NOT_SHOW_COMMANDLINE_HELP (sioffe) - Be more accurate printing default flag values in --help (dsturtevant) - Reduce .o file size a bit by using shorter namespace names (jeff) - Use relative install path, so 'setup.py --home' works (csilvers) - Notice when a boolean flag has a non-boolean default (bnmouli) - Broaden --helpshort to match foo-main.cc and foo_main.cc (hendrie) - Fix "no modules match" message for --helpshort, etc (hendrie) * Wed Aug 15 2007 - Google Inc. - google-gflags: version 0.6 - Deal correctly with case that libpthread is not linked in (csilvers) - Update Makefile/tests so we pass "make distcheck" (csilvers) - Document and test that last assignment to a flag wins (wan) * Tue Jun 12 2007 - Google Inc. - google-gflags: version 0.5 - Include all m4 macros in the distribution (csilvers) - Python: Fix broken data_files field in setup.py (sidlon) - Python: better string serliaizing and unparsing (abo, csimmons) - Fix checks for NaN and inf to work with Mac OS X (csilvers) * Thu Apr 19 2007 - Google Inc. - google-gflags: version 0.4 - Remove is_default from GetCommandLineFlagInfo (csilvers) - Portability fixes: includes, strtoll, gcc4.3 errors (csilvers) - A few doc typo cleanups (csilvers) * Wed Mar 28 2007 - Google Inc. - google-gflags: version 0.3 - python portability fix: use popen instead of subprocess (csilvers) - Add is_default to CommandLineFlagInfo (pchien) - Make docs a bit prettier (csilvers) - Actually include the python files in the distribution! :-/ (csilvers) * Mon Jan 22 2007 - Google Inc. - google-gflags: version 0.2 - added support for python commandlineflags, as well as c++ - gflags2man, a script to turn flags into a man page (dchristian) * Wed Dec 13 2006 - Google Inc. - google-gflags: version 0.1 gflags-2.2.2/INSTALL.md000066400000000000000000000077351337211647400144340ustar00rootroot00000000000000Installing a binary distribution package ======================================== No official binary distribution packages are provided by the gflags developers. There may, however, be binary packages available for your OS. Please consult also the package repositories of your Linux distribution. For example on Debian/Ubuntu Linux, gflags can be installed using the following command: sudo apt-get install libgflags-dev Compiling the source code with CMake ========================= The build system of gflags is since version 2.1 based on [CMake](http://cmake.org). The common steps to build, test, and install software are therefore: 1. Extract source files. 2. Create build directory and change to it. 3. Run CMake to configure the build tree. 4. Build the software using selected build tool. 5. Test the built software. 6. Install the built files. On Unix-like systems with GNU Make as build tool, these build steps can be summarized by the following sequence of commands executed in a shell, where ```$package``` and ```$version``` are shell variables which represent the name of this package and the obtained version of the software. $ tar xzf gflags-$version-source.tar.gz $ cd gflags-$version $ mkdir build && cd build $ ccmake .. - Press 'c' to configure the build system and 'e' to ignore warnings. - Set CMAKE_INSTALL_PREFIX and other CMake variables and options. - Continue pressing 'c' until the option 'g' is available. - Then press 'g' to generate the configuration files for GNU Make. $ make $ make test (optional) $ make install (optional) In the following, only gflags-specific CMake settings available to configure the build and installation are documented. Note that most of these variables are for advanced users and binary package maintainers only. They usually do not have to be modified. CMake Option | Description --------------------------- | ------------------------------------------------------- CMAKE_INSTALL_PREFIX | Installation directory, e.g., "/usr/local" on Unix and "C:\Program Files\gflags" on Windows. BUILD_SHARED_LIBS | Request build of dynamic link libraries. BUILD_STATIC_LIBS | Request build of static link libraries. Implied if BUILD_SHARED_LIBS is OFF. BUILD_PACKAGING | Enable binary package generation using CPack. BUILD_TESTING | Build tests for execution by CTest. BUILD_NC_TESTS | Request inclusion of negative compilation tests (requires Python). BUILD_CONFIG_TESTS | Request inclusion of package configuration tests (requires Python). BUILD_gflags_LIBS | Request build of multi-threaded gflags libraries (if threading library found). BUILD_gflags_nothreads_LIBS | Request build of single-threaded gflags libraries. GFLAGS_NAMESPACE | Name of the C++ namespace to be used by the gflags library. Note that the public source header files are installed in a subdirectory named after this namespace. To maintain backwards compatibility with the Google Commandline Flags, set this variable to "google". The default is "gflags". GFLAGS_INTTYPES_FORMAT | String identifying format of built-in integer types. GFLAGS_INCLUDE_DIR | Name of headers installation directory relative to CMAKE_INSTALL_PREFIX. LIBRARY_INSTALL_DIR | Name of library installation directory relative to CMAKE_INSTALL_PREFIX. INSTALL_HEADERS | Request installation of public header files. Using gflags with [Bazel](http://bazel.io) ========================= To use gflags in a Bazel project, map it in as an external dependency by editing your WORKSPACE file: git_repository( name = "com_github_gflags_gflags", commit = "", remote = "https://github.com/gflags/gflags.git", ) You can then add `@com_github_gflags_gflags//:gflags` to the `deps` section of a `cc_binary` or `cc_library` rule, and `#include ` to include it in your source code. gflags-2.2.2/README.md000066400000000000000000000325371337211647400142610ustar00rootroot00000000000000[![Build Status](https://travis-ci.org/gflags/gflags.svg?branch=master)](https://travis-ci.org/gflags/gflags) [![Build status](https://ci.appveyor.com/api/projects/status/4ctod566ysraus74/branch/master?svg=true)](https://ci.appveyor.com/project/schuhschuh/gflags/branch/master) The documentation of the gflags library is available online at https://gflags.github.io/gflags/. 11 November 2018 ---------------- I've just released gflags 2.2.2. This maintenance release improves lives of Bazel users (no more "config.h" leaking into global include paths), fixes build with recent MinGW versions, and silences a number of static code analyzer and compiler warnings. The build targets exported by the CMake configuration of this library are now also prefixed by the package name "gflags::" following a more recent (unwritten) CMake convention. The unprefixed target names are still supported to avoid that dependent projects have to be modified due to this change in imported target names. Please report any further issues with this release using the GitHub issue tracker. 11 July 2017 ------------ I've just released gflags 2.2.1. This maintenance release primarily fixes build issues on Windows and false alarms reported by static code analyzers. Please report any further issues with this release using the GitHub issue tracker. 25 November 2016 ---------------- I've finally released gflags 2.2.0. This release adds support for use of the gflags library as external dependency not only in projects using CMake, but also [Bazel](https://bazel.build/), or [pkg-config](https://www.freedesktop.org/wiki/Software/pkg-config/). One new minor feature is added in this release: when a command flag argument contains dashes, these are implicitly converted to underscores. This is to allow those used to separate words of the flag name by dashes to do so, while the flag variable names are required to use underscores. Memory leaks reported by valgrind should be resolved by this release. This release fixes build errors with MS Visual Studio 2015. Please report any further issues with this release using the GitHub issue tracker. 24 March 2015 ------------- I've just released gflags 2.1.2. This release completes the namespace change fixes. In particular, it restores binary ABI compatibility with release version 2.0. The deprecated "google" namespace is by default still kept as primary namespace while symbols are imported into the new "gflags" namespace. This can be overridden using the CMake variable GFLAGS_NAMESPACE. Other fixes of the build configuration are related to the (patched) CMake modules FindThreads.cmake and CheckTypeSize.cmake. These have been removed and instead the C language is enabled again even though gflags is written in C++ only. This release also marks the complete move of the gflags project from Google Code to GitHub. Email addresses of original issue reporters got lost in the process. Given the age of most issue reports, this should be negligable. Please report any further issues using the GitHub issue tracker. 30 March 2014 ------------- I've just released gflags 2.1.1. This release fixes a few bugs in the configuration of gflags\_declare.h and adds a separate GFLAGS\_INCLUDE\_DIR CMake variable to the build configuration. Setting GFLAGS\_NAMESPACE to "google" no longer changes also the include path of the public header files. This allows the use of the library with other Google projects such as glog which still use the deprecated "google" namespace for the gflags library, but include it as "gflags/gflags.h". 20 March 2014 ------------- I've just released gflags 2.1. The major changes are the use of CMake for the build configuration instead of the autotools and packaging support through CPack. The default namespace of all C++ symbols is now "gflags" instead of "google". This can be configured via the GFLAGS\_NAMESPACE variable. This release compiles with all major compilers without warnings and passed the unit tests on Ubuntu 12.04, Windows 7 (Visual Studio 2008 and 2010, Cygwin, MinGW), and Mac OS X (Xcode 5.1). The SVN repository on Google Code is now frozen and replaced by a Git repository such that it can be used as Git submodule by projects. The main hosting of this project remains at Google Code. Thanks to the distributed character of Git, I can push (and pull) changes from both GitHub and Google Code in order to keep the two public repositories in sync. When fixing an issue for a pull request through either of these hosting platforms, please reference the issue number as [described here](https://code.google.com/p/support/wiki/IssueTracker#Integration_with_version_control). For the further development, I am following the [Git branching model](http://nvie.com/posts/a-successful-git-branching-model/) with feature branch names prefixed by "feature/" and bugfix branch names prefixed by "bugfix/", respectively. Binary and source [packages](https://github.com/schuhschuh/gflags/releases) are available on GitHub. 14 January 2014 --------------- The migration of the build system to CMake is almost complete. What remains to be done is rewriting the tests in Python such they can be executed on non-Unix platforms and splitting them up into separate CTest tests. Though merging these changes into the master branch yet remains to be done, it is recommended to already start using the [cmake-migration](https://github.com/schuhschuh/gflags/tree/cmake-migration) branch. 20 April 2013 ------------- More than a year has past since I (Andreas) took over the maintenance for `gflags`. Only few minor changes have been made since then, much to my regret. To get more involved and stimulate participation in the further development of the library, I moved the project source code today to [GitHub](https://github.com/schuhschuh/gflags). I believe that the strengths of [Git](http://git-scm.com/) will allow for better community collaboration as well as ease the integration of changes made by others. I encourage everyone who would like to contribute to send me pull requests. Git's lightweight feature branches will also provide the right tool for more radical changes which should only be merged back into the master branch after these are complete and implement the desired behavior. The SVN repository remains accessible at Google Code and I will keep the master branch of the Git repository hosted at GitHub and the trunk of the Subversion repository synchronized. Initially, I was going to simply switch the Google Code project to Git, but in this case the SVN repository would be frozen and force everyone who would like the latest development changes to use Git as well. Therefore I decided to host the public Git repository at GitHub instead. Please continue to report any issues with gflags on Google Code. The GitHub project will only be used to host the Git repository. One major change of the project structure I have in mind for the next weeks is the migration from autotools to [CMake](http://www.cmake.org/). Check out the (unstable!) [cmake-migration](https://github.com/schuhschuh/gflags/tree/cmake-migration) branch on GitHub for details. 25 January 2012 --------------- I've just released gflags 2.0. The `google-gflags` project has been renamed to `gflags`. I (csilvers) am stepping down as maintainer, to be replaced by Andreas Schuh. Welcome to the team, Andreas! I've seen the energy you have around gflags and the ideas you have for the project going forward, and look forward to having you on the team. I bumped the major version number up to 2 to reflect the new community ownership of the project. All the [changes](ChangeLog.txt) are related to the renaming. There are no functional changes from gflags 1.7. In particular, I've kept the code in the namespace `google`, though in a future version it should be renamed to `gflags`. I've also kept the `/usr/local/include/google/` subdirectory as synonym of `/usr/local/include/gflags/`, though the former name has been obsolete for some time now. 18 January 2011 --------------- The `google-gflags` Google Code page has been renamed to `gflags`, in preparation for the project being renamed to `gflags`. In the coming weeks, I'll be stepping down as maintainer for the gflags project, and as part of that Google is relinquishing ownership of the project; it will now be entirely community run. The name change reflects that shift. 20 December 2011 ---------------- I've just released gflags 1.7. This is a minor release; the major change is that `CommandLineFlagInfo` now exports the address in memory where the flag is located. There has also been a bugfix involving very long --help strings, and some other minor [changes](ChangeLog.txt). 29 July 2011 ------------ I've just released gflags 1.6. The major new feature in this release is support for setting version info, so that --version does something useful. One minor change has required bumping the library number: `ReparseCommandlineFlags` now returns `void` instead of `int` (the int return value was always meaningless). Though I doubt anyone ever used this (meaningless) return value, technically it's a change to the ABI that requires a version bump. A bit sad. There's also a procedural change with this release: I've changed the internal tools used to integrate Google-supplied patches for gflags into the opensource release. These new tools should result in more frequent updates with better change descriptions. They will also result in future `ChangeLog` entries being much more verbose (for better or for worse). See the [ChangeLog](ChangeLog.txt) for a full list of changes for this release. 24 January 2011 --------------- I've just released gflags 1.5. This release has only minor changes from 1.4, including some slightly better reporting in --help, and an new memory-cleanup function that can help when running gflags-using libraries under valgrind. The major change is to fix up the macros (`DEFINE_bool` and the like) to work more reliably inside namespaces. If you have not had a problem with these macros, and don't need any of the other changes described, there is no need to upgrade. See the [ChangeLog](ChangeLog.txt) for a full list of changes for this release. 11 October 2010 --------------- I've just released gflags 1.4. This release has only minor changes from 1.3, including some documentation tweaks and some work to make the library smaller. If 1.3 is working well for you, there's no particular reason to upgrade. 4 January 2010 -------------- I've just released gflags 1.3. gflags now compiles under MSVC, and all tests pass. I **really** never thought non-unix-y Windows folks would want gflags, but at least some of them do. The major news, though, is that I've separated out the python package into its own library, [python-gflags](http://code.google.com/p/python-gflags). If you're interested in the Python version of gflags, that's the place to get it now. 10 September 2009 ----------------- I've just released gflags 1.2. The major change from gflags 1.1 is it now compiles under MinGW (as well as cygwin), and all tests pass. I never thought Windows folks would want unix-style command-line flags, since they're so different from the Windows style, but I guess I was wrong! The other changes are minor, such as support for --htmlxml in the python version of gflags. 15 April 2009 ------------- I've just released gflags 1.1. It has only minor changes fdrom gflags 1.0 (see the [ChangeLog](ChangeLog.txt) for details). The major change is that I moved to a new system for creating .deb and .rpm files. This allows me to create x86\_64 deb and rpm files. In the process of moving to this new system, I noticed an inconsistency: the tar.gz and .rpm files created libraries named libgflags.so, but the deb file created libgoogle-gflags.so. I have fixed the deb file to create libraries like the others. I'm no expert in debian packaging, but I believe this has caused the package name to change as well. Please let me know (at [[mailto:google-gflags@googlegroups.com](mailto:google-gflags@googlegroups.com) google-gflags@googlegroups.com]) if this causes problems for you -- especially if you know of a fix! I would be happy to change the deb packages to add symlinks from the old library name to the new (libgoogle-gflags.so -> libgflags.so), but that is beyond my knowledge of how to make .debs. If you've tried to install a .rpm or .deb and it doesn't work for you, let me know. I'm excited to finally have 64-bit package files, but there may still be some wrinkles in the new system to iron out. 1 October 2008 -------------- gflags 1.0rc2 was out for a few weeks without any issues, so gflags 1.0 is now released. This is much like gflags 0.9. The major change is that the .h files have been moved from `/usr/include/google` to `/usr/include/gflags`. While I have backwards-compatibility forwarding headeds in place, please rewrite existing code to say ``` #include ``` instead of ``` #include ``` I've kept the default namespace to google. You can still change with with the appropriate flag to the configure script (`./configure --help` to see the flags). If you have feedback as to whether the default namespace should change to gflags, which would be a non-backwards-compatible change, send mail to `google-gflags@googlegroups.com`! Version 1.0 also has some neat new features, like support for bash commandline-completion of help flags. See the [ChangeLog](ChangeLog.txt) for more details. If I don't hear any bad news for a few weeks, I'll release 1.0-final. gflags-2.2.2/WORKSPACE000066400000000000000000000003771337211647400142600ustar00rootroot00000000000000# Copyright 2006 Google Inc. All Rights Reserved. # Use of this source code is governed by a BSD-style # license that can be found in the COPYING.txt file. # Bazel (http://bazel.io/) WORKSPACE file for gflags. workspace(name="com_github_gflags_gflags") gflags-2.2.2/appveyor.yml000066400000000000000000000026471337211647400153710ustar00rootroot00000000000000# Configuration for continuous integration service at appveyor.com version: '{build}' os: Visual Studio 2015 environment: matrix: - Toolset: v140 - Toolset: v120 - Toolset: v110 - Toolset: v100 - Toolset: v90 platform: - Win32 - x64 configuration: - Release matrix: exclude: - Toolset: v90 platform: x64 - Toolset: v100 platform: x64 build: verbosity: minimal before_build: - ps: | Write-Output "Configuration: $env:CONFIGURATION" Write-Output "Platform: $env:PLATFORM" $generator = switch ($env:TOOLSET) { "v140" {"Visual Studio 14 2015"} "v120" {"Visual Studio 12 2013"} "v110" {"Visual Studio 11 2012"} "v100" {"Visual Studio 10 2010"} "v90" {"Visual Studio 9 2008"} } if ($env:PLATFORM -eq "x64") { $generator = "$generator Win64" } build_script: - ps: | md _build -Force | Out-Null cd _build & cmake -G "$generator" -D CMAKE_CONFIGURATION_TYPES="Debug;Release" -D GFLAGS_BUILD_TESTING=ON -D GFLAGS_BUILD_SHARED_LIBS=ON -D GFLAGS_BUILD_STATIC_LIBS=ON .. if ($LastExitCode -ne 0) { throw "Exec: $ErrorMessage" } & cmake --build . --config $env:CONFIGURATION if ($LastExitCode -ne 0) { throw "Exec: $ErrorMessage" } test_script: - ps: | & ctest -C $env:CONFIGURATION --output-on-failure if ($LastExitCode -ne 0) { throw "Exec: $ErrorMessage" } gflags-2.2.2/bazel/000077500000000000000000000000001337211647400140655ustar00rootroot00000000000000gflags-2.2.2/bazel/gflags.bzl000066400000000000000000000070261337211647400160460ustar00rootroot00000000000000# ------------------------------------------------------------------------------ # Add native rules to configure source files def gflags_sources(namespace=["google", "gflags"]): native.genrule( name = "gflags_declare_h", srcs = ["src/gflags_declare.h.in"], outs = ["gflags_declare.h"], cmd = ("awk '{ " + "gsub(/@GFLAGS_NAMESPACE@/, \"" + namespace[0] + "\"); " + "gsub(/@(HAVE_STDINT_H|HAVE_SYS_TYPES_H|HAVE_INTTYPES_H|GFLAGS_INTTYPES_FORMAT_C99)@/, \"1\"); " + "gsub(/@([A-Z0-9_]+)@/, \"0\"); " + "print; }' $(<) > $(@)") ) gflags_ns_h_files = [] for ns in namespace[1:]: gflags_ns_h_file = "gflags_{}.h".format(ns) native.genrule( name = gflags_ns_h_file.replace('.', '_'), srcs = ["src/gflags_ns.h.in"], outs = [gflags_ns_h_file], cmd = ("awk '{ " + "gsub(/@ns@/, \"" + ns + "\"); " + "gsub(/@NS@/, \"" + ns.upper() + "\"); " + "print; }' $(<) > $(@)") ) gflags_ns_h_files.append(gflags_ns_h_file) native.genrule( name = "gflags_h", srcs = ["src/gflags.h.in"], outs = ["gflags.h"], cmd = ("awk '{ " + "gsub(/@GFLAGS_ATTRIBUTE_UNUSED@/, \"\"); " + "gsub(/@INCLUDE_GFLAGS_NS_H@/, \"" + '\n'.join(["#include \\\"gflags/{}\\\"".format(hdr) for hdr in gflags_ns_h_files]) + "\"); " + "print; }' $(<) > $(@)") ) native.genrule( name = "gflags_completions_h", srcs = ["src/gflags_completions.h.in"], outs = ["gflags_completions.h"], cmd = "awk '{ gsub(/@GFLAGS_NAMESPACE@/, \"" + namespace[0] + "\"); print; }' $(<) > $(@)" ) hdrs = [":gflags_h", ":gflags_declare_h", ":gflags_completions_h"] hdrs.extend([':' + hdr.replace('.', '_') for hdr in gflags_ns_h_files]) srcs = [ "src/config.h", "src/gflags.cc", "src/gflags_completions.cc", "src/gflags_reporting.cc", "src/mutex.h", "src/util.h", ] + select({ "//:x64_windows": [ "src/windows_port.cc", "src/windows_port.h", ], "//conditions:default": [], }) return [hdrs, srcs] # ------------------------------------------------------------------------------ # Add native rule to build gflags library def gflags_library(hdrs=[], srcs=[], threads=1): name = "gflags" copts = [ "-DGFLAGS_BAZEL_BUILD", "-DGFLAGS_INTTYPES_FORMAT_C99", "-DGFLAGS_IS_A_DLL=0", # macros otherwise defined by CMake configured defines.h file "-DHAVE_STDINT_H", "-DHAVE_SYS_TYPES_H", "-DHAVE_INTTYPES_H", "-DHAVE_SYS_STAT_H", "-DHAVE_STRTOLL", "-DHAVE_STRTOQ", "-DHAVE_RWLOCK", ] + select({ "//:x64_windows": [ "-DOS_WINDOWS", ], "//conditions:default": [ "-DHAVE_UNISTD_H", "-DHAVE_FNMATCH_H", "-DHAVE_PTHREAD", ], }) linkopts = [] if threads: linkopts += select({ "//:x64_windows": [], "//conditions:default": ["-lpthread"], }) else: name += "_nothreads" copts += ["-DNO_THREADS"] native.cc_library( name = name, hdrs = hdrs, srcs = srcs, copts = copts, linkopts = linkopts, visibility = ["//visibility:public"], include_prefix = 'gflags' ) gflags-2.2.2/cmake/000077500000000000000000000000001337211647400140505ustar00rootroot00000000000000gflags-2.2.2/cmake/README_runtime.txt000066400000000000000000000003561337211647400173150ustar00rootroot00000000000000This package contains runtime libraries only which are required by applications that use these libraries for the commandline flags processing. If you want to develop such application, download and install the development package instead. gflags-2.2.2/cmake/cmake_uninstall.cmake.in000066400000000000000000000022231337211647400206270ustar00rootroot00000000000000if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") if (NOT DEFINED CMAKE_INSTALL_PREFIX) set (CMAKE_INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@") endif () message(${CMAKE_INSTALL_PREFIX}) file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) string(REGEX REPLACE "\n" ";" files "${files}") foreach(file ${files}) message(STATUS "Uninstalling $ENV{DESTDIR}${file}") if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") exec_program( "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" OUTPUT_VARIABLE rm_out RETURN_VALUE rm_retval ) if(NOT "${rm_retval}" STREQUAL 0) message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") endif(NOT "${rm_retval}" STREQUAL 0) else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") message(STATUS "File $ENV{DESTDIR}${file} does not exist.") endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") endforeach(file) gflags-2.2.2/cmake/config.cmake.in000066400000000000000000000167201337211647400167320ustar00rootroot00000000000000## gflags CMake configuration file # library version information set (@PACKAGE_PREFIX@_VERSION_STRING "@PACKAGE_VERSION@") set (@PACKAGE_PREFIX@_VERSION_MAJOR @PACKAGE_VERSION_MAJOR@) set (@PACKAGE_PREFIX@_VERSION_MINOR @PACKAGE_VERSION_MINOR@) set (@PACKAGE_PREFIX@_VERSION_PATCH @PACKAGE_VERSION_PATCH@) # import targets if (NOT DEFINED @PACKAGE_PREFIX@_USE_TARGET_NAMESPACE) set (@PACKAGE_PREFIX@_USE_TARGET_NAMESPACE FALSE) endif () if (@PACKAGE_PREFIX@_USE_TARGET_NAMESPACE) include ("${CMAKE_CURRENT_LIST_DIR}/@EXPORT_NAME@.cmake") set (@PACKAGE_PREFIX@_TARGET_NAMESPACE @PACKAGE_NAME@) else () include ("${CMAKE_CURRENT_LIST_DIR}/@PACKAGE_NAME@-nonamespace-targets.cmake") set (@PACKAGE_PREFIX@_TARGET_NAMESPACE) endif () if (@PACKAGE_PREFIX@_TARGET_NAMESPACE) set (@PACKAGE_PREFIX@_TARGET_PREFIX ${@PACKAGE_PREFIX@_TARGET_NAMESPACE}::) else () set (@PACKAGE_PREFIX@_TARGET_PREFIX) endif () # installation prefix get_filename_component (CMAKE_CURRENT_LIST_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) get_filename_component (_INSTALL_PREFIX "${CMAKE_CURRENT_LIST_DIR}/@INSTALL_PREFIX_REL2CONFIG_DIR@" ABSOLUTE) # include directory # # Newer versions of CMake set the INTERFACE_INCLUDE_DIRECTORIES property # of the imported targets. It is hence not necessary to add this path # manually to the include search path for targets which link to gflags. set (@PACKAGE_PREFIX@_INCLUDE_DIR "${_INSTALL_PREFIX}/@INCLUDE_INSTALL_DIR@") if (@PACKAGE_NAME@_FIND_COMPONENTS) foreach (@PACKAGE_NAME@_FIND_COMPONENT IN LISTS @PACKAGE_NAME@_FIND_COMPONENTS) if (@PACKAGE_NAME@_FIND_REQUIRED_${@PACKAGE_NAME@_FIND_COMPONENT} AND NOT TARGET @PACKAGE_NAME@_${@PACKAGE_NAME@_FIND_COMPONENT}) message (FATAL_ERROR "Package @PACKAGE_NAME@ was installed without required component ${@PACKAGE_NAME@_FIND_COMPONENT}!") endif () endforeach () list (GET @PACKAGE_NAME@_FIND_COMPONENTS 0 @PACKAGE_NAME@_FIND_COMPONENT) else () set (@PACKAGE_NAME@_FIND_COMPONENT) endif () # default settings of @PACKAGE_PREFIX@_SHARED and @PACKAGE_PREFIX@_NOTHREADS # # It is recommended to use either one of the following find_package commands # instead of setting the @PACKAGE_PREFIX@_(SHARED|NOTHREADS) variables: # - find_package(@PACKAGE_NAME@ REQUIRED) # - find_package(@PACKAGE_NAME@ COMPONENTS nothreads_static) # - find_package(@PACKAGE_NAME@ COMPONENTS nothreads_shared) # - find_package(@PACKAGE_NAME@ COMPONENTS static) # - find_package(@PACKAGE_NAME@ COMPONENTS shared) if (NOT DEFINED @PACKAGE_PREFIX@_SHARED) if (DEFINED @PACKAGE_NAME@_SHARED) set (@PACKAGE_PREFIX@_SHARED ${@PACKAGE_NAME@_SHARED}) elseif (@PACKAGE_NAME@_FIND_COMPONENT) if (@PACKAGE_NAME@_FIND_COMPONENT MATCHES "shared") set (@PACKAGE_PREFIX@_SHARED TRUE) else () set (@PACKAGE_PREFIX@_SHARED FALSE) endif () elseif (TARGET ${@PACKAGE_PREFIX@_TARGET_PREFIX}@PACKAGE_NAME@_shared OR TARGET ${@PACKAGE_PREFIX@_TARGET_PREFIX}@PACKAGE_NAME@_nothreads_shared) set (@PACKAGE_PREFIX@_SHARED TRUE) else () set (@PACKAGE_PREFIX@_SHARED FALSE) endif () endif () if (NOT DEFINED @PACKAGE_PREFIX@_NOTHREADS) if (DEFINED @PACKAGE_NAME@_NOTHREADS) set (@PACKAGE_PREFIX@_NOTHREADS ${@PACKAGE_NAME@_NOTHREADS}) elseif (@PACKAGE_NAME@_FIND_COMPONENT) if (@PACKAGE_NAME@_FIND_COMPONENT MATCHES "nothreads") set (@PACKAGE_PREFIX@_NOTHREADS TRUE) else () set (@PACKAGE_PREFIX@_NOTHREADS FALSE) endif () elseif (TARGET ${@PACKAGE_PREFIX@_TARGET_PREFIX}PACKAGE_NAME@_static OR TARGET ${@PACKAGE_PREFIX@_TARGET_PREFIX}@PACKAGE_NAME@_shared) set (@PACKAGE_PREFIX@_NOTHREADS FALSE) else () set (@PACKAGE_PREFIX@_NOTHREADS TRUE) endif () endif () # choose imported library target if (NOT @PACKAGE_PREFIX@_TARGET) if (@PACKAGE_NAME@_TARGET) set (@PACKAGE_PREFIX@_TARGET ${@PACKAGE_NAME@_TARGET}) elseif (@PACKAGE_PREFIX@_SHARED) if (@PACKAGE_PREFIX@_NOTHREADS) set (@PACKAGE_PREFIX@_TARGET ${@PACKAGE_PREFIX@_TARGET_PREFIX}@PACKAGE_NAME@_nothreads_shared) else () set (@PACKAGE_PREFIX@_TARGET ${@PACKAGE_PREFIX@_TARGET_PREFIX}@PACKAGE_NAME@_shared) endif () else () if (@PACKAGE_PREFIX@_NOTHREADS) set (@PACKAGE_PREFIX@_TARGET ${@PACKAGE_PREFIX@_TARGET_PREFIX}@PACKAGE_NAME@_nothreads_static) else () set (@PACKAGE_PREFIX@_TARGET ${@PACKAGE_PREFIX@_TARGET_PREFIX}@PACKAGE_NAME@_static) endif () endif () endif () if (NOT TARGET ${@PACKAGE_PREFIX@_TARGET}) message (FATAL_ERROR "Your @PACKAGE_NAME@ installation does not contain a ${@PACKAGE_PREFIX@_TARGET} library target!" " Try a different combination of @PACKAGE_PREFIX@_SHARED and @PACKAGE_PREFIX@_NOTHREADS.") endif () # add more convenient "${@PACKAGE_PREFIX@_TARGET_PREFIX}@PACKAGE_NAME@" import target if (NOT TARGET ${@PACKAGE_PREFIX@_TARGET_PREFIX}@PACKAGE_NAME@) if (@PACKAGE_PREFIX@_SHARED) add_library (${@PACKAGE_PREFIX@_TARGET_PREFIX}@PACKAGE_NAME@ SHARED IMPORTED) else () add_library (${@PACKAGE_PREFIX@_TARGET_PREFIX}@PACKAGE_NAME@ STATIC IMPORTED) endif () # copy INTERFACE_* properties foreach (_@PACKAGE_PREFIX@_PROPERTY_NAME IN ITEMS COMPILE_DEFINITIONS COMPILE_FEATURES COMPILE_OPTIONS INCLUDE_DIRECTORIES LINK_LIBRARIES POSITION_INDEPENDENT_CODE ) get_target_property (_@PACKAGE_PREFIX@_PROPERTY_VALUE ${@PACKAGE_PREFIX@_TARGET} INTERFACE_${_@PACKAGE_PREFIX@_PROPERTY_NAME}) if (_@PACKAGE_PREFIX@_PROPERTY_VALUE) set_target_properties(${@PACKAGE_PREFIX@_TARGET_PREFIX}@PACKAGE_NAME@ PROPERTIES INTERFACE_${_@PACKAGE_PREFIX@_PROPERTY_NAME} "${_@PACKAGE_PREFIX@_PROPERTY_VALUE}" ) endif () endforeach () # copy IMPORTED_*_ properties get_target_property (_@PACKAGE_PREFIX@_CONFIGURATIONS ${@PACKAGE_PREFIX@_TARGET} IMPORTED_CONFIGURATIONS) set_target_properties (${@PACKAGE_PREFIX@_TARGET_PREFIX}@PACKAGE_NAME@ PROPERTIES IMPORTED_CONFIGURATIONS "${_@PACKAGE_PREFIX@_CONFIGURATIONS}") foreach (_@PACKAGE_PREFIX@_PROPERTY_NAME IN ITEMS IMPLIB LOCATION LINK_DEPENDENT_LIBRARIES LINK_INTERFACE_LIBRARIES LINK_INTERFACE_LANGUAGES LINK_INTERFACE_MULTIPLICITY NO_SONAME SONAME ) foreach (_@PACKAGE_PREFIX@_CONFIG IN LISTS _@PACKAGE_PREFIX@_CONFIGURATIONS) get_target_property (_@PACKAGE_PREFIX@_PROPERTY_VALUE ${@PACKAGE_PREFIX@_TARGET} IMPORTED_${_@PACKAGE_PREFIX@_PROPERTY_NAME}_${_@PACKAGE_PREFIX@_CONFIG}) if (_@PACKAGE_PREFIX@_PROPERTY_VALUE) set_target_properties(${@PACKAGE_PREFIX@_TARGET_PREFIX}@PACKAGE_NAME@ PROPERTIES IMPORTED_${_@PACKAGE_PREFIX@_PROPERTY_NAME}_${_@PACKAGE_PREFIX@_CONFIG} "${_@PACKAGE_PREFIX@_PROPERTY_VALUE}" ) endif () endforeach () endforeach () unset (_@PACKAGE_PREFIX@_CONFIGURATIONS) unset (_@PACKAGE_PREFIX@_CONFIG) unset (_@PACKAGE_PREFIX@_PROPERTY_NAME) unset (_@PACKAGE_PREFIX@_PROPERTY_VALUE) endif () # alias for default import target to be compatible with older CMake package configurations set (@PACKAGE_PREFIX@_LIBRARIES "${@PACKAGE_PREFIX@_TARGET}") # set @PACKAGE_NAME@_* variables for backwards compatibility if (NOT "^@PACKAGE_NAME@$" STREQUAL "^@PACKAGE_PREFIX@$") foreach (_@PACKAGE_PREFIX@_VARIABLE IN ITEMS VERSION_STRING VERSION_MAJOR VERSION_MINOR VERSION_PATCH INCLUDE_DIR LIBRARIES TARGET ) set (@PACKAGE_NAME@_${_@PACKAGE_PREFIX@_VARIABLE} "${@PACKAGE_PREFIX@_${_@PACKAGE_PREFIX@_VARIABLE}}") endforeach () unset (_@PACKAGE_PREFIX@_VARIABLE) endif () # unset private variables unset (@PACKAGE_NAME@_FIND_COMPONENT) unset (_INSTALL_PREFIX) gflags-2.2.2/cmake/execute_test.cmake000066400000000000000000000033641337211647400175610ustar00rootroot00000000000000# ---------------------------------------------------------------------------- # sanitize string stored in variable for use in regular expression. macro (sanitize_for_regex STRVAR) string (REGEX REPLACE "([.+*?^$()])" "\\\\\\1" ${STRVAR} "${${STRVAR}}") endmacro () # ---------------------------------------------------------------------------- # script arguments if (NOT COMMAND) message (FATAL_ERROR "Test command not specified!") endif () if (NOT DEFINED EXPECTED_RC) set (EXPECTED_RC 0) endif () if (EXPECTED_OUTPUT) sanitize_for_regex(EXPECTED_OUTPUT) endif () if (UNEXPECTED_OUTPUT) sanitize_for_regex(UNEXPECTED_OUTPUT) endif () # ---------------------------------------------------------------------------- # set a few environment variables (useful for --tryfromenv) set (ENV{FLAGS_undefok} "foo,bar") set (ENV{FLAGS_weirdo} "") set (ENV{FLAGS_version} "true") set (ENV{FLAGS_help} "false") # ---------------------------------------------------------------------------- # execute test command execute_process( COMMAND ${COMMAND} RESULT_VARIABLE RC OUTPUT_VARIABLE OUTPUT ERROR_VARIABLE OUTPUT ) if (OUTPUT) message ("${OUTPUT}") endif () # ---------------------------------------------------------------------------- # check test result if (NOT RC EQUAL EXPECTED_RC) string (REPLACE ";" " " COMMAND "${COMMAND}") message (FATAL_ERROR "Command:\n\t${COMMAND}\nExit status is ${RC}, expected ${EXPECTED_RC}") endif () if (EXPECTED_OUTPUT AND NOT OUTPUT MATCHES "${EXPECTED_OUTPUT}") message (FATAL_ERROR "Test output does not match expected output: ${EXPECTED_OUTPUT}") endif () if (UNEXPECTED_OUTPUT AND OUTPUT MATCHES "${UNEXPECTED_OUTPUT}") message (FATAL_ERROR "Test output matches unexpected output: ${UNEXPECTED_OUTPUT}") endif ()gflags-2.2.2/cmake/package.cmake.in000066400000000000000000000040361337211647400170550ustar00rootroot00000000000000# Per-generator CPack configuration file. See CPACK_PROJECT_CONFIG_FILE documented at # http://www.cmake.org/cmake/help/v2.8.12/cpack.html#variable:CPACK_PROJECT_CONFIG_FILE # # All common CPACK_* variables are set in CMakeLists.txt already. This file only # overrides some of these to provide package generator specific settings. # whether package contains all development files or only runtime files set (DEVEL @INSTALL_HEADERS@) # ------------------------------------------------------------------------------ # Mac OS X package if (CPACK_GENERATOR MATCHES "PackageMaker|DragNDrop") set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}") if (DEVEL) set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-devel") endif () set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-${CPACK_PACKAGE_VERSION}") # ------------------------------------------------------------------------------ # Debian package elseif (CPACK_GENERATOR MATCHES "DEB") set (CPACK_PACKAGE_FILE_NAME "lib${CPACK_PACKAGE_NAME}") if (DEVEL) set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-dev") else () set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}0") endif () set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}_${CPACK_PACKAGE_VERSION}-1_${CPACK_PACKAGE_ARCHITECTURE}") set (CPACK_DEBIAN_PACKAGE_DEPENDS) set (CPACK_DEBIAN_PACKAGE_SECTION "devel") set (CPACK_DEBIAN_PACKAGE_PRIORITY "optional") set (CPACK_DEBIAN_PACKAGE_HOMEPAGE "${CPACK_RPM_PACKAGE_URL}") set (CPACK_DEBIAN_PACKAGE_MAINTAINER "${CPACK_PACKAGE_VENDOR}") set (CPACK_DEBIAN_PACKAGE_ARCHITECTURE "${CPACK_PACKAGE_ARCHITECTURE}") # ------------------------------------------------------------------------------ # RPM package elseif (CPACK_GENERATOR MATCHES "RPM") set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}") if (DEVEL) set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-devel") endif () set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-${CPACK_PACKAGE_VERSION}-1.${CPACK_PACKAGE_ARCHITECTURE}") endif () gflags-2.2.2/cmake/package.pc.in000066400000000000000000000005521337211647400163760ustar00rootroot00000000000000prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=${prefix} bindir=${prefix}/@RUNTIME_INSTALL_DIR@ libdir=${prefix}/@LIBRARY_INSTALL_DIR@ includedir=${prefix}/@INCLUDE_INSTALL_DIR@ Name: @PACKAGE_NAME@ Version: @PACKAGE_VERSION@ Description: @PACKAGE_DESCRIPTION@ URL: @PACKAGE_URL@ Requires: Libs: -L${libdir} -lgflags Libs.private: -lpthread Cflags: -I${includedir} gflags-2.2.2/cmake/utils.cmake000066400000000000000000000172641337211647400162240ustar00rootroot00000000000000## Utility CMake functions. # ---------------------------------------------------------------------------- ## Convert boolean value to 0 or 1 macro (bool_to_int VAR) if (${VAR}) set (${VAR} 1) else () set (${VAR} 0) endif () endmacro () # ---------------------------------------------------------------------------- ## Extract version numbers from version string function (version_numbers version major minor patch) if (version MATCHES "([0-9]+)(\\.[0-9]+)?(\\.[0-9]+)?(rc[1-9][0-9]*|[a-z]+)?") if (CMAKE_MATCH_1) set (_major ${CMAKE_MATCH_1}) else () set (_major 0) endif () if (CMAKE_MATCH_2) set (_minor ${CMAKE_MATCH_2}) string (REGEX REPLACE "^\\." "" _minor "${_minor}") else () set (_minor 0) endif () if (CMAKE_MATCH_3) set (_patch ${CMAKE_MATCH_3}) string (REGEX REPLACE "^\\." "" _patch "${_patch}") else () set (_patch 0) endif () else () set (_major 0) set (_minor 0) set (_patch 0) endif () set ("${major}" "${_major}" PARENT_SCOPE) set ("${minor}" "${_minor}" PARENT_SCOPE) set ("${patch}" "${_patch}" PARENT_SCOPE) endfunction () # ---------------------------------------------------------------------------- ## Determine if cache entry exists macro (gflags_is_cached retvar varname) if (DEFINED ${varname}) get_property (${retvar} CACHE ${varname} PROPERTY TYPE SET) else () set (${retvar} FALSE) endif () endmacro () # ---------------------------------------------------------------------------- ## Add gflags configuration variable # # The default value of the (cached) configuration value can be overridden either # on the CMake command-line or the super-project by setting the GFLAGS_ # variable. When gflags is a subproject of another project (GFLAGS_IS_SUBPROJECT), # the variable is not added to the CMake cache. Otherwise it is cached. macro (gflags_define type varname docstring default) # note that ARGC must be expanded here, as it is not a "real" variable # (see the CMake documentation for the macro command) if ("${ARGC}" GREATER 5) message (FATAL_ERROR "gflags_variable: Too many macro arguments") endif () if (NOT DEFINED GFLAGS_${varname}) if (GFLAGS_IS_SUBPROJECT AND "${ARGC}" EQUAL 5) set (GFLAGS_${varname} "${ARGV4}") else () set (GFLAGS_${varname} "${default}") endif () endif () if (GFLAGS_IS_SUBPROJECT) if (NOT DEFINED ${varname}) set (${varname} "${GFLAGS_${varname}}") endif () else () set (${varname} "${GFLAGS_${varname}}" CACHE ${type} "${docstring}") endif () endmacro () # ---------------------------------------------------------------------------- ## Set property of cached gflags configuration variable macro (gflags_property varname property value) gflags_is_cached (_cached ${varname}) if (_cached) # note that property must be expanded here, as it is not a "real" variable # (see the CMake documentation for the macro command) if ("${property}" STREQUAL "ADVANCED") if (${value}) mark_as_advanced (FORCE ${varname}) else () mark_as_advanced (CLEAR ${varname}) endif () else () set_property (CACHE ${varname} PROPERTY "${property}" "${value}") endif () endif () unset (_cached) endmacro () # ---------------------------------------------------------------------------- ## Modify value of gflags configuration variable macro (gflags_set varname value) gflags_is_cached (_cached ${varname}) if (_cached) set_property (CACHE ${varname} PROPERTY VALUE "${value}") else () set (${varname} "${value}") endif () unset (_cached) endmacro () # ---------------------------------------------------------------------------- ## Configure public header files function (configure_headers out) set (tmp) foreach (src IN LISTS ARGN) if (IS_ABSOLUTE "${src}") list (APPEND tmp "${src}") elseif (EXISTS "${PROJECT_SOURCE_DIR}/src/${src}.in") configure_file ("${PROJECT_SOURCE_DIR}/src/${src}.in" "${PROJECT_BINARY_DIR}/include/${GFLAGS_INCLUDE_DIR}/${src}" @ONLY) list (APPEND tmp "${PROJECT_BINARY_DIR}/include/${GFLAGS_INCLUDE_DIR}/${src}") else () configure_file ("${PROJECT_SOURCE_DIR}/src/${src}" "${PROJECT_BINARY_DIR}/include/${GFLAGS_INCLUDE_DIR}/${src}" COPYONLY) list (APPEND tmp "${PROJECT_BINARY_DIR}/include/${GFLAGS_INCLUDE_DIR}/${src}") endif () endforeach () set (${out} "${tmp}" PARENT_SCOPE) endfunction () # ---------------------------------------------------------------------------- ## Configure source files with .in suffix function (configure_sources out) set (tmp) foreach (src IN LISTS ARGN) if (src MATCHES ".h$" AND EXISTS "${PROJECT_SOURCE_DIR}/src/${src}.in") configure_file ("${PROJECT_SOURCE_DIR}/src/${src}.in" "${PROJECT_BINARY_DIR}/include/${GFLAGS_INCLUDE_DIR}/${src}" @ONLY) list (APPEND tmp "${PROJECT_BINARY_DIR}/include/${GFLAGS_INCLUDE_DIR}/${src}") else () list (APPEND tmp "${PROJECT_SOURCE_DIR}/src/${src}") endif () endforeach () set (${out} "${tmp}" PARENT_SCOPE) endfunction () # ---------------------------------------------------------------------------- ## Add usage test # # Using PASS_REGULAR_EXPRESSION and FAIL_REGULAR_EXPRESSION would # do as well, but CMake/CTest does not allow us to specify an # expected exit status. Moreover, the execute_test.cmake script # sets environment variables needed by the --fromenv/--tryfromenv tests. macro (add_gflags_test name expected_rc expected_output unexpected_output cmd) set (args "--test_tmpdir=${PROJECT_BINARY_DIR}/Testing/Temporary" "--srcdir=${PROJECT_SOURCE_DIR}/test") add_test ( NAME ${name} COMMAND "${CMAKE_COMMAND}" "-DCOMMAND:STRING=$;${args};${ARGN}" "-DEXPECTED_RC:STRING=${expected_rc}" "-DEXPECTED_OUTPUT:STRING=${expected_output}" "-DUNEXPECTED_OUTPUT:STRING=${unexpected_output}" -P "${PROJECT_SOURCE_DIR}/cmake/execute_test.cmake" WORKING_DIRECTORY "${GFLAGS_FLAGFILES_DIR}" ) endmacro () # ------------------------------------------------------------------------------ ## Register installed package with CMake # # This function adds an entry to the CMake registry for packages with the # path of the directory where the package configuration file of the installed # package is located in order to help CMake find the package in a custom # installation prefix. This differs from CMake's export(PACKAGE) command # which registers the build directory instead. function (register_gflags_package CONFIG_DIR) if (NOT IS_ABSOLUTE "${CONFIG_DIR}") set (CONFIG_DIR "${CMAKE_INSTALL_PREFIX}/${CONFIG_DIR}") endif () string (MD5 REGISTRY_ENTRY "${CONFIG_DIR}") if (WIN32) install (CODE "execute_process ( COMMAND reg add \"HKCU\\\\Software\\\\Kitware\\\\CMake\\\\Packages\\\\${PACKAGE_NAME}\" /v \"${REGISTRY_ENTRY}\" /d \"${CONFIG_DIR}\" /t REG_SZ /f RESULT_VARIABLE RT ERROR_VARIABLE ERR OUTPUT_QUIET ) if (RT EQUAL 0) message (STATUS \"Register: Added HKEY_CURRENT_USER\\\\Software\\\\Kitware\\\\CMake\\\\Packages\\\\${PACKAGE_NAME}\\\\${REGISTRY_ENTRY}\") else () string (STRIP \"\${ERR}\" ERR) message (STATUS \"Register: Failed to add registry entry: \${ERR}\") endif ()" ) elseif (IS_DIRECTORY "$ENV{HOME}") file (WRITE "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}-registry-entry" "${CONFIG_DIR}") install ( FILES "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}-registry-entry" DESTINATION "$ENV{HOME}/.cmake/packages/${PACKAGE_NAME}" RENAME "${REGISTRY_ENTRY}" ) endif () endfunction () gflags-2.2.2/cmake/version.cmake.in000066400000000000000000000013241337211647400171440ustar00rootroot00000000000000## gflags CMake configuration version file # ----------------------------------------------------------------------------- # library version set (PACKAGE_VERSION "@PACKAGE_VERSION@") # ----------------------------------------------------------------------------- # check compatibility # Perform compatibility check here using the input CMake variables. # See example in http://www.cmake.org/Wiki/CMake_2.6_Notes. set (PACKAGE_VERSION_COMPATIBLE TRUE) set (PACKAGE_VERSION_UNSUITABLE FALSE) if ("${PACKAGE_FIND_VERSION_MAJOR}" EQUAL "@PACKAGE_VERSION_MAJOR@" AND "${PACKAGE_FIND_VERSION_MINOR}" EQUAL "@PACKAGE_VERSION_MINOR@") set (PACKAGE_VERSION_EXACT TRUE) else () set (PACKAGE_VERSION_EXACT FALSE) endif () gflags-2.2.2/doc/000077500000000000000000000000001337211647400135355ustar00rootroot00000000000000gflags-2.2.2/src/000077500000000000000000000000001337211647400135575ustar00rootroot00000000000000gflags-2.2.2/src/config.h000066400000000000000000000033571337211647400152050ustar00rootroot00000000000000// Note: This header file is only used internally. It is not part of public interface! #ifndef GFLAGS_CONFIG_H_ #define GFLAGS_CONFIG_H_ // --------------------------------------------------------------------------- // System checks // CMake build configuration is written to defines.h file, unused by Bazel build #if !defined(GFLAGS_BAZEL_BUILD) # include "defines.h" #endif // gcc requires this to get PRId64, etc. #if defined(HAVE_INTTYPES_H) && !defined(__STDC_FORMAT_MACROS) # define __STDC_FORMAT_MACROS 1 #endif // --------------------------------------------------------------------------- // Path separator #ifndef PATH_SEPARATOR # ifdef OS_WINDOWS # define PATH_SEPARATOR '\\' # else # define PATH_SEPARATOR '/' # endif #endif // --------------------------------------------------------------------------- // Windows // Always export symbols when compiling a shared library as this file is only // included by internal modules when building the gflags library itself. // The gflags_declare.h header file will set it to import these symbols otherwise. #ifndef GFLAGS_DLL_DECL # if GFLAGS_IS_A_DLL && defined(_MSC_VER) # define GFLAGS_DLL_DECL __declspec(dllexport) # elif defined(__GNUC__) && __GNUC__ >= 4 # define GFLAGS_DLL_DECL __attribute__((visibility("default"))) # else # define GFLAGS_DLL_DECL # endif #endif // Flags defined by the gflags library itself must be exported #ifndef GFLAGS_DLL_DEFINE_FLAG # define GFLAGS_DLL_DEFINE_FLAG GFLAGS_DLL_DECL #endif #ifdef OS_WINDOWS // The unittests import the symbols of the shared gflags library # if GFLAGS_IS_A_DLL && defined(_MSC_VER) # define GFLAGS_DLL_DECL_FOR_UNITTESTS __declspec(dllimport) # endif # include "windows_port.h" #endif #endif // GFLAGS_CONFIG_H_ gflags-2.2.2/src/defines.h.in000066400000000000000000000025551337211647400157610ustar00rootroot00000000000000/* Generated from defines.h.in during build configuration using CMake. */ // Note: This header file is only used internally. It is not part of public interface! // Any cmakedefine is defined using the -D flag instead when Bazel is used. // For Bazel, this file is thus not used to avoid a private file in $(GENDIR). #ifndef GFLAGS_DEFINES_H_ #define GFLAGS_DEFINES_H_ // Define if you build this library for a MS Windows OS. #cmakedefine OS_WINDOWS // Define if you have the header file. #cmakedefine HAVE_STDINT_H // Define if you have the header file. #cmakedefine HAVE_SYS_TYPES_H // Define if you have the header file. #cmakedefine HAVE_INTTYPES_H // Define if you have the header file. #cmakedefine HAVE_SYS_STAT_H // Define if you have the header file. #cmakedefine HAVE_UNISTD_H // Define if you have the header file. #cmakedefine HAVE_FNMATCH_H // Define if you have the header file (Windows 2000/XP). #cmakedefine HAVE_SHLWAPI_H // Define if you have the strtoll function. #cmakedefine HAVE_STRTOLL // Define if you have the strtoq function. #cmakedefine HAVE_STRTOQ // Define if you have the header file. #cmakedefine HAVE_PTHREAD // Define if your pthread library defines the type pthread_rwlock_t #cmakedefine HAVE_RWLOCK #endif // GFLAGS_DEFINES_H_ gflags-2.2.2/src/gflags.cc000066400000000000000000002240241337211647400153350ustar00rootroot00000000000000// Copyright (c) 1999, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // --- // Revamped and reorganized by Craig Silverstein // // This file contains the implementation of all our command line flags // stuff. Here's how everything fits together // // * FlagRegistry owns CommandLineFlags owns FlagValue. // * FlagSaver holds a FlagRegistry (saves it at construct time, // restores it at destroy time). // * CommandLineFlagParser lives outside that hierarchy, but works on // CommandLineFlags (modifying the FlagValues). // * Free functions like SetCommandLineOption() work via one of the // above (such as CommandLineFlagParser). // // In more detail: // // -- The main classes that hold flag data: // // FlagValue holds the current value of a flag. It's // pseudo-templatized: every operation on a FlagValue is typed. It // also deals with storage-lifetime issues (so flag values don't go // away in a destructor), which is why we need a whole class to hold a // variable's value. // // CommandLineFlag is all the information about a single command-line // flag. It has a FlagValue for the flag's current value, but also // the flag's name, type, etc. // // FlagRegistry is a collection of CommandLineFlags. There's the // global registry, which is where flags defined via DEFINE_foo() // live. But it's possible to define your own flag, manually, in a // different registry you create. (In practice, multiple registries // are used only by FlagSaver). // // A given FlagValue is owned by exactly one CommandLineFlag. A given // CommandLineFlag is owned by exactly one FlagRegistry. FlagRegistry // has a lock; any operation that writes to a FlagValue or // CommandLineFlag owned by that registry must acquire the // FlagRegistry lock before doing so. // // --- Some other classes and free functions: // // CommandLineFlagInfo is a client-exposed version of CommandLineFlag. // Once it's instantiated, it has no dependencies or relationships // with any other part of this file. // // FlagRegisterer is the helper class used by the DEFINE_* macros to // allow work to be done at global initialization time. // // CommandLineFlagParser is the class that reads from the commandline // and instantiates flag values based on that. It needs to poke into // the innards of the FlagValue->CommandLineFlag->FlagRegistry class // hierarchy to do that. It's careful to acquire the FlagRegistry // lock before doing any writing or other non-const actions. // // GetCommandLineOption is just a hook into registry routines to // retrieve a flag based on its name. SetCommandLineOption, on the // other hand, hooks into CommandLineFlagParser. Other API functions // are, similarly, mostly hooks into the functionality described above. #include "config.h" #include "gflags/gflags.h" #include #include #include #if defined(HAVE_FNMATCH_H) # include #elif defined(HAVE_SHLWAPI_H) # define NO_SHLWAPI_ISOS # include #endif #include // For va_list and related operations #include #include #include #include #include #include // for pair<> #include #include "mutex.h" #include "util.h" using namespace MUTEX_NAMESPACE; // Special flags, type 1: the 'recursive' flags. They set another flag's val. DEFINE_string(flagfile, "", "load flags from file"); DEFINE_string(fromenv, "", "set flags from the environment" " [use 'export FLAGS_flag1=value']"); DEFINE_string(tryfromenv, "", "set flags from the environment if present"); // Special flags, type 2: the 'parsing' flags. They modify how we parse. DEFINE_string(undefok, "", "comma-separated list of flag names that it is okay to specify " "on the command line even if the program does not define a flag " "with that name. IMPORTANT: flags in this list that have " "arguments MUST use the flag=value format"); namespace GFLAGS_NAMESPACE { using std::map; using std::pair; using std::sort; using std::string; using std::vector; // This is used by the unittest to test error-exit code void GFLAGS_DLL_DECL (*gflags_exitfunc)(int) = &exit; // from stdlib.h // The help message indicating that the commandline flag has been // 'stripped'. It will not show up when doing "-help" and its // variants. The flag is stripped if STRIP_FLAG_HELP is set to 1 // before including base/gflags.h // This is used by this file, and also in gflags_reporting.cc const char kStrippedFlagHelp[] = "\001\002\003\004 (unknown) \004\003\002\001"; namespace { // There are also 'reporting' flags, in gflags_reporting.cc. static const char kError[] = "ERROR: "; // Indicates that undefined options are to be ignored. // Enables deferred processing of flags in dynamically loaded libraries. static bool allow_command_line_reparsing = false; static bool logging_is_probably_set_up = false; // This is a 'prototype' validate-function. 'Real' validate // functions, take a flag-value as an argument: ValidateFn(bool) or // ValidateFn(uint64). However, for easier storage, we strip off this // argument and then restore it when actually calling the function on // a flag value. typedef bool (*ValidateFnProto)(); // Whether we should die when reporting an error. enum DieWhenReporting { DIE, DO_NOT_DIE }; // Report Error and exit if requested. static void ReportError(DieWhenReporting should_die, const char* format, ...) { va_list ap; va_start(ap, format); vfprintf(stderr, format, ap); va_end(ap); fflush(stderr); // should be unnecessary, but cygwin's rxvt buffers stderr if (should_die == DIE) gflags_exitfunc(1); } // -------------------------------------------------------------------- // FlagValue // This represent the value a single flag might have. The major // functionality is to convert from a string to an object of a // given type, and back. Thread-compatible. // -------------------------------------------------------------------- class CommandLineFlag; class FlagValue { public: enum ValueType { FV_BOOL = 0, FV_INT32 = 1, FV_UINT32 = 2, FV_INT64 = 3, FV_UINT64 = 4, FV_DOUBLE = 5, FV_STRING = 6, FV_MAX_INDEX = 6, }; template FlagValue(FlagType* valbuf, bool transfer_ownership_of_value); ~FlagValue(); bool ParseFrom(const char* spec); string ToString() const; ValueType Type() const { return static_cast(type_); } private: friend class CommandLineFlag; // for many things, including Validate() friend class GFLAGS_NAMESPACE::FlagSaverImpl; // calls New() friend class FlagRegistry; // checks value_buffer_ for flags_by_ptr_ map template friend T GetFromEnv(const char*, T); friend bool TryParseLocked(const CommandLineFlag*, FlagValue*, const char*, string*); // for New(), CopyFrom() template struct FlagValueTraits; const char* TypeName() const; bool Equal(const FlagValue& x) const; FlagValue* New() const; // creates a new one with default value void CopyFrom(const FlagValue& x); // Calls the given validate-fn on value_buffer_, and returns // whatever it returns. But first casts validate_fn_proto to a // function that takes our value as an argument (eg void // (*validate_fn)(bool) for a bool flag). bool Validate(const char* flagname, ValidateFnProto validate_fn_proto) const; void* const value_buffer_; // points to the buffer holding our data const int8 type_; // how to interpret value_ const bool owns_value_; // whether to free value on destruct FlagValue(const FlagValue&); // no copying! void operator=(const FlagValue&); }; // Map the given C++ type to a value of the ValueType enum at compile time. #define DEFINE_FLAG_TRAITS(type, value) \ template <> \ struct FlagValue::FlagValueTraits { \ static const ValueType kValueType = value; \ } // Define full template specializations of the FlagValueTraits template // for all supported flag types. DEFINE_FLAG_TRAITS(bool, FV_BOOL); DEFINE_FLAG_TRAITS(int32, FV_INT32); DEFINE_FLAG_TRAITS(uint32, FV_UINT32); DEFINE_FLAG_TRAITS(int64, FV_INT64); DEFINE_FLAG_TRAITS(uint64, FV_UINT64); DEFINE_FLAG_TRAITS(double, FV_DOUBLE); DEFINE_FLAG_TRAITS(std::string, FV_STRING); #undef DEFINE_FLAG_TRAITS // This could be a templated method of FlagValue, but doing so adds to the // size of the .o. Since there's no type-safety here anyway, macro is ok. #define VALUE_AS(type) *reinterpret_cast(value_buffer_) #define OTHER_VALUE_AS(fv, type) *reinterpret_cast(fv.value_buffer_) #define SET_VALUE_AS(type, value) VALUE_AS(type) = (value) template FlagValue::FlagValue(FlagType* valbuf, bool transfer_ownership_of_value) : value_buffer_(valbuf), type_(FlagValueTraits::kValueType), owns_value_(transfer_ownership_of_value) { } FlagValue::~FlagValue() { if (!owns_value_) { return; } switch (type_) { case FV_BOOL: delete reinterpret_cast(value_buffer_); break; case FV_INT32: delete reinterpret_cast(value_buffer_); break; case FV_UINT32: delete reinterpret_cast(value_buffer_); break; case FV_INT64: delete reinterpret_cast(value_buffer_); break; case FV_UINT64: delete reinterpret_cast(value_buffer_); break; case FV_DOUBLE: delete reinterpret_cast(value_buffer_); break; case FV_STRING: delete reinterpret_cast(value_buffer_); break; } } bool FlagValue::ParseFrom(const char* value) { if (type_ == FV_BOOL) { const char* kTrue[] = { "1", "t", "true", "y", "yes" }; const char* kFalse[] = { "0", "f", "false", "n", "no" }; COMPILE_ASSERT(sizeof(kTrue) == sizeof(kFalse), true_false_equal); for (size_t i = 0; i < sizeof(kTrue)/sizeof(*kTrue); ++i) { if (strcasecmp(value, kTrue[i]) == 0) { SET_VALUE_AS(bool, true); return true; } else if (strcasecmp(value, kFalse[i]) == 0) { SET_VALUE_AS(bool, false); return true; } } return false; // didn't match a legal input } else if (type_ == FV_STRING) { SET_VALUE_AS(string, value); return true; } // OK, it's likely to be numeric, and we'll be using a strtoXXX method. if (value[0] == '\0') // empty-string is only allowed for string type. return false; char* end; // Leading 0x puts us in base 16. But leading 0 does not put us in base 8! // It caused too many bugs when we had that behavior. int base = 10; // by default if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X')) base = 16; errno = 0; switch (type_) { case FV_INT32: { const int64 r = strto64(value, &end, base); if (errno || end != value + strlen(value)) return false; // bad parse if (static_cast(r) != r) // worked, but number out of range return false; SET_VALUE_AS(int32, static_cast(r)); return true; } case FV_UINT32: { while (*value == ' ') value++; if (*value == '-') return false; // negative number const uint64 r = strtou64(value, &end, base); if (errno || end != value + strlen(value)) return false; // bad parse if (static_cast(r) != r) // worked, but number out of range return false; SET_VALUE_AS(uint32, static_cast(r)); return true; } case FV_INT64: { const int64 r = strto64(value, &end, base); if (errno || end != value + strlen(value)) return false; // bad parse SET_VALUE_AS(int64, r); return true; } case FV_UINT64: { while (*value == ' ') value++; if (*value == '-') return false; // negative number const uint64 r = strtou64(value, &end, base); if (errno || end != value + strlen(value)) return false; // bad parse SET_VALUE_AS(uint64, r); return true; } case FV_DOUBLE: { const double r = strtod(value, &end); if (errno || end != value + strlen(value)) return false; // bad parse SET_VALUE_AS(double, r); return true; } default: { assert(false); // unknown type return false; } } } string FlagValue::ToString() const { char intbuf[64]; // enough to hold even the biggest number switch (type_) { case FV_BOOL: return VALUE_AS(bool) ? "true" : "false"; case FV_INT32: snprintf(intbuf, sizeof(intbuf), "%" PRId32, VALUE_AS(int32)); return intbuf; case FV_UINT32: snprintf(intbuf, sizeof(intbuf), "%" PRIu32, VALUE_AS(uint32)); return intbuf; case FV_INT64: snprintf(intbuf, sizeof(intbuf), "%" PRId64, VALUE_AS(int64)); return intbuf; case FV_UINT64: snprintf(intbuf, sizeof(intbuf), "%" PRIu64, VALUE_AS(uint64)); return intbuf; case FV_DOUBLE: snprintf(intbuf, sizeof(intbuf), "%.17g", VALUE_AS(double)); return intbuf; case FV_STRING: return VALUE_AS(string); default: assert(false); return ""; // unknown type } } bool FlagValue::Validate(const char* flagname, ValidateFnProto validate_fn_proto) const { switch (type_) { case FV_BOOL: return reinterpret_cast( validate_fn_proto)(flagname, VALUE_AS(bool)); case FV_INT32: return reinterpret_cast( validate_fn_proto)(flagname, VALUE_AS(int32)); case FV_UINT32: return reinterpret_cast( validate_fn_proto)(flagname, VALUE_AS(uint32)); case FV_INT64: return reinterpret_cast( validate_fn_proto)(flagname, VALUE_AS(int64)); case FV_UINT64: return reinterpret_cast( validate_fn_proto)(flagname, VALUE_AS(uint64)); case FV_DOUBLE: return reinterpret_cast( validate_fn_proto)(flagname, VALUE_AS(double)); case FV_STRING: return reinterpret_cast( validate_fn_proto)(flagname, VALUE_AS(string)); default: assert(false); // unknown type return false; } } const char* FlagValue::TypeName() const { static const char types[] = "bool\0xx" "int32\0x" "uint32\0" "int64\0x" "uint64\0" "double\0" "string"; if (type_ > FV_MAX_INDEX) { assert(false); return ""; } // Directly indexing the strings in the 'types' string, each of them is 7 bytes long. return &types[type_ * 7]; } bool FlagValue::Equal(const FlagValue& x) const { if (type_ != x.type_) return false; switch (type_) { case FV_BOOL: return VALUE_AS(bool) == OTHER_VALUE_AS(x, bool); case FV_INT32: return VALUE_AS(int32) == OTHER_VALUE_AS(x, int32); case FV_UINT32: return VALUE_AS(uint32) == OTHER_VALUE_AS(x, uint32); case FV_INT64: return VALUE_AS(int64) == OTHER_VALUE_AS(x, int64); case FV_UINT64: return VALUE_AS(uint64) == OTHER_VALUE_AS(x, uint64); case FV_DOUBLE: return VALUE_AS(double) == OTHER_VALUE_AS(x, double); case FV_STRING: return VALUE_AS(string) == OTHER_VALUE_AS(x, string); default: assert(false); return false; // unknown type } } FlagValue* FlagValue::New() const { switch (type_) { case FV_BOOL: return new FlagValue(new bool(false), true); case FV_INT32: return new FlagValue(new int32(0), true); case FV_UINT32: return new FlagValue(new uint32(0), true); case FV_INT64: return new FlagValue(new int64(0), true); case FV_UINT64: return new FlagValue(new uint64(0), true); case FV_DOUBLE: return new FlagValue(new double(0.0), true); case FV_STRING: return new FlagValue(new string, true); default: assert(false); return NULL; // unknown type } } void FlagValue::CopyFrom(const FlagValue& x) { assert(type_ == x.type_); switch (type_) { case FV_BOOL: SET_VALUE_AS(bool, OTHER_VALUE_AS(x, bool)); break; case FV_INT32: SET_VALUE_AS(int32, OTHER_VALUE_AS(x, int32)); break; case FV_UINT32: SET_VALUE_AS(uint32, OTHER_VALUE_AS(x, uint32)); break; case FV_INT64: SET_VALUE_AS(int64, OTHER_VALUE_AS(x, int64)); break; case FV_UINT64: SET_VALUE_AS(uint64, OTHER_VALUE_AS(x, uint64)); break; case FV_DOUBLE: SET_VALUE_AS(double, OTHER_VALUE_AS(x, double)); break; case FV_STRING: SET_VALUE_AS(string, OTHER_VALUE_AS(x, string)); break; default: assert(false); // unknown type } } // -------------------------------------------------------------------- // CommandLineFlag // This represents a single flag, including its name, description, // default value, and current value. Mostly this serves as a // struct, though it also knows how to register itself. // All CommandLineFlags are owned by a (exactly one) // FlagRegistry. If you wish to modify fields in this class, you // should acquire the FlagRegistry lock for the registry that owns // this flag. // -------------------------------------------------------------------- class CommandLineFlag { public: // Note: we take over memory-ownership of current_val and default_val. CommandLineFlag(const char* name, const char* help, const char* filename, FlagValue* current_val, FlagValue* default_val); ~CommandLineFlag(); const char* name() const { return name_; } const char* help() const { return help_; } const char* filename() const { return file_; } const char* CleanFileName() const; // nixes irrelevant prefix such as homedir string current_value() const { return current_->ToString(); } string default_value() const { return defvalue_->ToString(); } const char* type_name() const { return defvalue_->TypeName(); } ValidateFnProto validate_function() const { return validate_fn_proto_; } const void* flag_ptr() const { return current_->value_buffer_; } FlagValue::ValueType Type() const { return defvalue_->Type(); } void FillCommandLineFlagInfo(struct CommandLineFlagInfo* result); // If validate_fn_proto_ is non-NULL, calls it on value, returns result. bool Validate(const FlagValue& value) const; bool ValidateCurrent() const { return Validate(*current_); } bool Modified() const { return modified_; } private: // for SetFlagLocked() and setting flags_by_ptr_ friend class FlagRegistry; friend class GFLAGS_NAMESPACE::FlagSaverImpl; // for cloning the values // set validate_fn friend bool AddFlagValidator(const void*, ValidateFnProto); // This copies all the non-const members: modified, processed, defvalue, etc. void CopyFrom(const CommandLineFlag& src); void UpdateModifiedBit(); const char* const name_; // Flag name const char* const help_; // Help message const char* const file_; // Which file did this come from? bool modified_; // Set after default assignment? FlagValue* defvalue_; // Default value for flag FlagValue* current_; // Current value for flag // This is a casted, 'generic' version of validate_fn, which actually // takes a flag-value as an arg (void (*validate_fn)(bool), say). // When we pass this to current_->Validate(), it will cast it back to // the proper type. This may be NULL to mean we have no validate_fn. ValidateFnProto validate_fn_proto_; CommandLineFlag(const CommandLineFlag&); // no copying! void operator=(const CommandLineFlag&); }; CommandLineFlag::CommandLineFlag(const char* name, const char* help, const char* filename, FlagValue* current_val, FlagValue* default_val) : name_(name), help_(help), file_(filename), modified_(false), defvalue_(default_val), current_(current_val), validate_fn_proto_(NULL) { } CommandLineFlag::~CommandLineFlag() { delete current_; delete defvalue_; } const char* CommandLineFlag::CleanFileName() const { // This function has been used to strip off a common prefix from // flag source file names. Because flags can be defined in different // shared libraries, there may not be a single common prefix. // Further, this functionality hasn't been active for many years. // Need a better way to produce more user friendly help output or // "anonymize" file paths in help output, respectively. // Follow issue at: https://github.com/gflags/gflags/issues/86 return filename(); } void CommandLineFlag::FillCommandLineFlagInfo( CommandLineFlagInfo* result) { result->name = name(); result->type = type_name(); result->description = help(); result->current_value = current_value(); result->default_value = default_value(); result->filename = CleanFileName(); UpdateModifiedBit(); result->is_default = !modified_; result->has_validator_fn = validate_function() != NULL; result->flag_ptr = flag_ptr(); } void CommandLineFlag::UpdateModifiedBit() { // Update the "modified" bit in case somebody bypassed the // Flags API and wrote directly through the FLAGS_name variable. if (!modified_ && !current_->Equal(*defvalue_)) { modified_ = true; } } void CommandLineFlag::CopyFrom(const CommandLineFlag& src) { // Note we only copy the non-const members; others are fixed at construct time if (modified_ != src.modified_) modified_ = src.modified_; if (!current_->Equal(*src.current_)) current_->CopyFrom(*src.current_); if (!defvalue_->Equal(*src.defvalue_)) defvalue_->CopyFrom(*src.defvalue_); if (validate_fn_proto_ != src.validate_fn_proto_) validate_fn_proto_ = src.validate_fn_proto_; } bool CommandLineFlag::Validate(const FlagValue& value) const { if (validate_function() == NULL) return true; else return value.Validate(name(), validate_function()); } // -------------------------------------------------------------------- // FlagRegistry // A FlagRegistry singleton object holds all flag objects indexed // by their names so that if you know a flag's name (as a C // string), you can access or set it. If the function is named // FooLocked(), you must own the registry lock before calling // the function; otherwise, you should *not* hold the lock, and // the function will acquire it itself if needed. // -------------------------------------------------------------------- struct StringCmp { // Used by the FlagRegistry map class to compare char*'s bool operator() (const char* s1, const char* s2) const { return (strcmp(s1, s2) < 0); } }; class FlagRegistry { public: FlagRegistry() { } ~FlagRegistry() { // Not using STLDeleteElements as that resides in util and this // class is base. for (FlagMap::iterator p = flags_.begin(), e = flags_.end(); p != e; ++p) { CommandLineFlag* flag = p->second; delete flag; } } static void DeleteGlobalRegistry() { delete global_registry_; global_registry_ = NULL; } // Store a flag in this registry. Takes ownership of the given pointer. void RegisterFlag(CommandLineFlag* flag); void Lock() { lock_.Lock(); } void Unlock() { lock_.Unlock(); } // Returns the flag object for the specified name, or NULL if not found. CommandLineFlag* FindFlagLocked(const char* name); // Returns the flag object whose current-value is stored at flag_ptr. // That is, for whom current_->value_buffer_ == flag_ptr CommandLineFlag* FindFlagViaPtrLocked(const void* flag_ptr); // A fancier form of FindFlag that works correctly if name is of the // form flag=value. In that case, we set key to point to flag, and // modify v to point to the value (if present), and return the flag // with the given name. If the flag does not exist, returns NULL // and sets error_message. CommandLineFlag* SplitArgumentLocked(const char* argument, string* key, const char** v, string* error_message); // Set the value of a flag. If the flag was successfully set to // value, set msg to indicate the new flag-value, and return true. // Otherwise, set msg to indicate the error, leave flag unchanged, // and return false. msg can be NULL. bool SetFlagLocked(CommandLineFlag* flag, const char* value, FlagSettingMode set_mode, string* msg); static FlagRegistry* GlobalRegistry(); // returns a singleton registry private: friend class GFLAGS_NAMESPACE::FlagSaverImpl; // reads all the flags in order to copy them friend class CommandLineFlagParser; // for ValidateUnmodifiedFlags friend void GFLAGS_NAMESPACE::GetAllFlags(vector*); // The map from name to flag, for FindFlagLocked(). typedef map FlagMap; typedef FlagMap::iterator FlagIterator; typedef FlagMap::const_iterator FlagConstIterator; FlagMap flags_; // The map from current-value pointer to flag, fo FindFlagViaPtrLocked(). typedef map FlagPtrMap; FlagPtrMap flags_by_ptr_; static FlagRegistry* global_registry_; // a singleton registry Mutex lock_; static void InitGlobalRegistry(); // Disallow FlagRegistry(const FlagRegistry&); FlagRegistry& operator=(const FlagRegistry&); }; class FlagRegistryLock { public: explicit FlagRegistryLock(FlagRegistry* fr) : fr_(fr) { fr_->Lock(); } ~FlagRegistryLock() { fr_->Unlock(); } private: FlagRegistry *const fr_; }; void FlagRegistry::RegisterFlag(CommandLineFlag* flag) { Lock(); pair ins = flags_.insert(pair(flag->name(), flag)); if (ins.second == false) { // means the name was already in the map if (strcmp(ins.first->second->filename(), flag->filename()) != 0) { ReportError(DIE, "ERROR: flag '%s' was defined more than once " "(in files '%s' and '%s').\n", flag->name(), ins.first->second->filename(), flag->filename()); } else { ReportError(DIE, "ERROR: something wrong with flag '%s' in file '%s'. " "One possibility: file '%s' is being linked both statically " "and dynamically into this executable.\n", flag->name(), flag->filename(), flag->filename()); } } // Also add to the flags_by_ptr_ map. flags_by_ptr_[flag->current_->value_buffer_] = flag; Unlock(); } CommandLineFlag* FlagRegistry::FindFlagLocked(const char* name) { FlagConstIterator i = flags_.find(name); if (i == flags_.end()) { // If the name has dashes in it, try again after replacing with // underscores. if (strchr(name, '-') == NULL) return NULL; string name_rep = name; std::replace(name_rep.begin(), name_rep.end(), '-', '_'); return FindFlagLocked(name_rep.c_str()); } else { return i->second; } } CommandLineFlag* FlagRegistry::FindFlagViaPtrLocked(const void* flag_ptr) { FlagPtrMap::const_iterator i = flags_by_ptr_.find(flag_ptr); if (i == flags_by_ptr_.end()) { return NULL; } else { return i->second; } } CommandLineFlag* FlagRegistry::SplitArgumentLocked(const char* arg, string* key, const char** v, string* error_message) { // Find the flag object for this option const char* flag_name; const char* value = strchr(arg, '='); if (value == NULL) { key->assign(arg); *v = NULL; } else { // Strip out the "=value" portion from arg key->assign(arg, value-arg); *v = ++value; // advance past the '=' } flag_name = key->c_str(); CommandLineFlag* flag = FindFlagLocked(flag_name); if (flag == NULL) { // If we can't find the flag-name, then we should return an error. // The one exception is if 1) the flag-name is 'nox', 2) there // exists a flag named 'x', and 3) 'x' is a boolean flag. // In that case, we want to return flag 'x'. if (!(flag_name[0] == 'n' && flag_name[1] == 'o')) { // flag-name is not 'nox', so we're not in the exception case. *error_message = StringPrintf("%sunknown command line flag '%s'\n", kError, key->c_str()); return NULL; } flag = FindFlagLocked(flag_name+2); if (flag == NULL) { // No flag named 'x' exists, so we're not in the exception case. *error_message = StringPrintf("%sunknown command line flag '%s'\n", kError, key->c_str()); return NULL; } if (flag->Type() != FlagValue::FV_BOOL) { // 'x' exists but is not boolean, so we're not in the exception case. *error_message = StringPrintf( "%sboolean value (%s) specified for %s command line flag\n", kError, key->c_str(), flag->type_name()); return NULL; } // We're in the exception case! // Make up a fake value to replace the "no" we stripped out key->assign(flag_name+2); // the name without the "no" *v = "0"; } // Assign a value if this is a boolean flag if (*v == NULL && flag->Type() == FlagValue::FV_BOOL) { *v = "1"; // the --nox case was already handled, so this is the --x case } return flag; } bool TryParseLocked(const CommandLineFlag* flag, FlagValue* flag_value, const char* value, string* msg) { // Use tenative_value, not flag_value, until we know value is valid. FlagValue* tentative_value = flag_value->New(); if (!tentative_value->ParseFrom(value)) { if (msg) { StringAppendF(msg, "%sillegal value '%s' specified for %s flag '%s'\n", kError, value, flag->type_name(), flag->name()); } delete tentative_value; return false; } else if (!flag->Validate(*tentative_value)) { if (msg) { StringAppendF(msg, "%sfailed validation of new value '%s' for flag '%s'\n", kError, tentative_value->ToString().c_str(), flag->name()); } delete tentative_value; return false; } else { flag_value->CopyFrom(*tentative_value); if (msg) { StringAppendF(msg, "%s set to %s\n", flag->name(), flag_value->ToString().c_str()); } delete tentative_value; return true; } } bool FlagRegistry::SetFlagLocked(CommandLineFlag* flag, const char* value, FlagSettingMode set_mode, string* msg) { flag->UpdateModifiedBit(); switch (set_mode) { case SET_FLAGS_VALUE: { // set or modify the flag's value if (!TryParseLocked(flag, flag->current_, value, msg)) return false; flag->modified_ = true; break; } case SET_FLAG_IF_DEFAULT: { // set the flag's value, but only if it hasn't been set by someone else if (!flag->modified_) { if (!TryParseLocked(flag, flag->current_, value, msg)) return false; flag->modified_ = true; } else { *msg = StringPrintf("%s set to %s", flag->name(), flag->current_value().c_str()); } break; } case SET_FLAGS_DEFAULT: { // modify the flag's default-value if (!TryParseLocked(flag, flag->defvalue_, value, msg)) return false; if (!flag->modified_) { // Need to set both defvalue *and* current, in this case TryParseLocked(flag, flag->current_, value, NULL); } break; } default: { // unknown set_mode assert(false); return false; } } return true; } // Get the singleton FlagRegistry object FlagRegistry* FlagRegistry::global_registry_ = NULL; FlagRegistry* FlagRegistry::GlobalRegistry() { static Mutex lock(Mutex::LINKER_INITIALIZED); MutexLock acquire_lock(&lock); if (!global_registry_) { global_registry_ = new FlagRegistry; } return global_registry_; } // -------------------------------------------------------------------- // CommandLineFlagParser // Parsing is done in two stages. In the first, we go through // argv. For every flag-like arg we can make sense of, we parse // it and set the appropriate FLAGS_* variable. For every flag- // like arg we can't make sense of, we store it in a vector, // along with an explanation of the trouble. In stage 2, we // handle the 'reporting' flags like --help and --mpm_version. // (This is via a call to HandleCommandLineHelpFlags(), in // gflags_reporting.cc.) // An optional stage 3 prints out the error messages. // This is a bit of a simplification. For instance, --flagfile // is handled as soon as it's seen in stage 1, not in stage 2. // -------------------------------------------------------------------- class CommandLineFlagParser { public: // The argument is the flag-registry to register the parsed flags in explicit CommandLineFlagParser(FlagRegistry* reg) : registry_(reg) {} ~CommandLineFlagParser() {} // Stage 1: Every time this is called, it reads all flags in argv. // However, it ignores all flags that have been successfully set // before. Typically this is only called once, so this 'reparsing' // behavior isn't important. It can be useful when trying to // reparse after loading a dll, though. uint32 ParseNewCommandLineFlags(int* argc, char*** argv, bool remove_flags); // Stage 2: print reporting info and exit, if requested. // In gflags_reporting.cc:HandleCommandLineHelpFlags(). // Stage 3: validate all the commandline flags that have validators // registered and were not set/modified by ParseNewCommandLineFlags. void ValidateFlags(bool all); void ValidateUnmodifiedFlags(); // Stage 4: report any errors and return true if any were found. bool ReportErrors(); // Set a particular command line option. "newval" is a string // describing the new value that the option has been set to. If // option_name does not specify a valid option name, or value is not // a valid value for option_name, newval is empty. Does recursive // processing for --flagfile and --fromenv. Returns the new value // if everything went ok, or empty-string if not. (Actually, the // return-string could hold many flag/value pairs due to --flagfile.) // NB: Must have called registry_->Lock() before calling this function. string ProcessSingleOptionLocked(CommandLineFlag* flag, const char* value, FlagSettingMode set_mode); // Set a whole batch of command line options as specified by contentdata, // which is in flagfile format (and probably has been read from a flagfile). // Returns the new value if everything went ok, or empty-string if // not. (Actually, the return-string could hold many flag/value // pairs due to --flagfile.) // NB: Must have called registry_->Lock() before calling this function. string ProcessOptionsFromStringLocked(const string& contentdata, FlagSettingMode set_mode); // These are the 'recursive' flags, defined at the top of this file. // Whenever we see these flags on the commandline, we must take action. // These are called by ProcessSingleOptionLocked and, similarly, return // new values if everything went ok, or the empty-string if not. string ProcessFlagfileLocked(const string& flagval, FlagSettingMode set_mode); // diff fromenv/tryfromenv string ProcessFromenvLocked(const string& flagval, FlagSettingMode set_mode, bool errors_are_fatal); private: FlagRegistry* const registry_; map error_flags_; // map from name to error message // This could be a set, but we reuse the map to minimize the .o size map undefined_names_; // --[flag] name was not registered }; // Parse a list of (comma-separated) flags. static void ParseFlagList(const char* value, vector* flags) { for (const char *p = value; p && *p; value = p) { p = strchr(value, ','); size_t len; if (p) { len = p - value; p++; } else { len = strlen(value); } if (len == 0) ReportError(DIE, "ERROR: empty flaglist entry\n"); if (value[0] == '-') ReportError(DIE, "ERROR: flag \"%*s\" begins with '-'\n", len, value); flags->push_back(string(value, len)); } } // Snarf an entire file into a C++ string. This is just so that we // can do all the I/O in one place and not worry about it everywhere. // Plus, it's convenient to have the whole file contents at hand. // Adds a newline at the end of the file. #define PFATAL(s) do { perror(s); gflags_exitfunc(1); } while (0) static string ReadFileIntoString(const char* filename) { const int kBufSize = 8092; char buffer[kBufSize]; string s; FILE* fp; if ((errno = SafeFOpen(&fp, filename, "r")) != 0) PFATAL(filename); size_t n; while ( (n=fread(buffer, 1, kBufSize, fp)) > 0 ) { if (ferror(fp)) PFATAL(filename); s.append(buffer, n); } fclose(fp); return s; } uint32 CommandLineFlagParser::ParseNewCommandLineFlags(int* argc, char*** argv, bool remove_flags) { int first_nonopt = *argc; // for non-options moved to the end registry_->Lock(); for (int i = 1; i < first_nonopt; i++) { char* arg = (*argv)[i]; // Like getopt(), we permute non-option flags to be at the end. if (arg[0] != '-' || arg[1] == '\0') { // must be a program argument: "-" is an argument, not a flag memmove((*argv) + i, (*argv) + i+1, (*argc - (i+1)) * sizeof((*argv)[i])); (*argv)[*argc-1] = arg; // we go last first_nonopt--; // we've been pushed onto the stack i--; // to undo the i++ in the loop continue; } arg++; // skip leading '-' if (arg[0] == '-') arg++; // or leading '--' // -- alone means what it does for GNU: stop options parsing if (*arg == '\0') { first_nonopt = i+1; break; } // Find the flag object for this option string key; const char* value; string error_message; CommandLineFlag* flag = registry_->SplitArgumentLocked(arg, &key, &value, &error_message); if (flag == NULL) { undefined_names_[key] = ""; // value isn't actually used error_flags_[key] = error_message; continue; } if (value == NULL) { // Boolean options are always assigned a value by SplitArgumentLocked() assert(flag->Type() != FlagValue::FV_BOOL); if (i+1 >= first_nonopt) { // This flag needs a value, but there is nothing available error_flags_[key] = (string(kError) + "flag '" + (*argv)[i] + "'" + " is missing its argument"); if (flag->help() && flag->help()[0] > '\001') { // Be useful in case we have a non-stripped description. error_flags_[key] += string("; flag description: ") + flag->help(); } error_flags_[key] += "\n"; break; // we treat this as an unrecoverable error } else { value = (*argv)[++i]; // read next arg for value // Heuristic to detect the case where someone treats a string arg // like a bool: // --my_string_var --foo=bar // We look for a flag of string type, whose value begins with a // dash, and where the flag-name and value are separated by a // space rather than an '='. // To avoid false positives, we also require the word "true" // or "false" in the help string. Without this, a valid usage // "-lat -30.5" would trigger the warning. The common cases we // want to solve talk about true and false as values. if (value[0] == '-' && flag->Type() == FlagValue::FV_STRING && (strstr(flag->help(), "true") || strstr(flag->help(), "false"))) { LOG(WARNING) << "Did you really mean to set flag '" << flag->name() << "' to the value '" << value << "'?"; } } } // TODO(csilvers): only set a flag if we hadn't set it before here ProcessSingleOptionLocked(flag, value, SET_FLAGS_VALUE); } registry_->Unlock(); if (remove_flags) { // Fix up argc and argv by removing command line flags (*argv)[first_nonopt-1] = (*argv)[0]; (*argv) += (first_nonopt-1); (*argc) -= (first_nonopt-1); first_nonopt = 1; // because we still don't count argv[0] } logging_is_probably_set_up = true; // because we've parsed --logdir, etc. return first_nonopt; } string CommandLineFlagParser::ProcessFlagfileLocked(const string& flagval, FlagSettingMode set_mode) { if (flagval.empty()) return ""; string msg; vector filename_list; ParseFlagList(flagval.c_str(), &filename_list); // take a list of filenames for (size_t i = 0; i < filename_list.size(); ++i) { const char* file = filename_list[i].c_str(); msg += ProcessOptionsFromStringLocked(ReadFileIntoString(file), set_mode); } return msg; } string CommandLineFlagParser::ProcessFromenvLocked(const string& flagval, FlagSettingMode set_mode, bool errors_are_fatal) { if (flagval.empty()) return ""; string msg; vector flaglist; ParseFlagList(flagval.c_str(), &flaglist); for (size_t i = 0; i < flaglist.size(); ++i) { const char* flagname = flaglist[i].c_str(); CommandLineFlag* flag = registry_->FindFlagLocked(flagname); if (flag == NULL) { error_flags_[flagname] = StringPrintf("%sunknown command line flag '%s' " "(via --fromenv or --tryfromenv)\n", kError, flagname); undefined_names_[flagname] = ""; continue; } const string envname = string("FLAGS_") + string(flagname); string envval; if (!SafeGetEnv(envname.c_str(), envval)) { if (errors_are_fatal) { error_flags_[flagname] = (string(kError) + envname + " not found in environment\n"); } continue; } // Avoid infinite recursion. if (envval == "fromenv" || envval == "tryfromenv") { error_flags_[flagname] = StringPrintf("%sinfinite recursion on environment flag '%s'\n", kError, envval.c_str()); continue; } msg += ProcessSingleOptionLocked(flag, envval.c_str(), set_mode); } return msg; } string CommandLineFlagParser::ProcessSingleOptionLocked( CommandLineFlag* flag, const char* value, FlagSettingMode set_mode) { string msg; if (value && !registry_->SetFlagLocked(flag, value, set_mode, &msg)) { error_flags_[flag->name()] = msg; return ""; } // The recursive flags, --flagfile and --fromenv and --tryfromenv, // must be dealt with as soon as they're seen. They will emit // messages of their own. if (strcmp(flag->name(), "flagfile") == 0) { msg += ProcessFlagfileLocked(FLAGS_flagfile, set_mode); } else if (strcmp(flag->name(), "fromenv") == 0) { // last arg indicates envval-not-found is fatal (unlike in --tryfromenv) msg += ProcessFromenvLocked(FLAGS_fromenv, set_mode, true); } else if (strcmp(flag->name(), "tryfromenv") == 0) { msg += ProcessFromenvLocked(FLAGS_tryfromenv, set_mode, false); } return msg; } void CommandLineFlagParser::ValidateFlags(bool all) { FlagRegistryLock frl(registry_); for (FlagRegistry::FlagConstIterator i = registry_->flags_.begin(); i != registry_->flags_.end(); ++i) { if ((all || !i->second->Modified()) && !i->second->ValidateCurrent()) { // only set a message if one isn't already there. (If there's // an error message, our job is done, even if it's not exactly // the same error.) if (error_flags_[i->second->name()].empty()) { error_flags_[i->second->name()] = string(kError) + "--" + i->second->name() + " must be set on the commandline"; if (!i->second->Modified()) { error_flags_[i->second->name()] += " (default value fails validation)"; } error_flags_[i->second->name()] += "\n"; } } } } void CommandLineFlagParser::ValidateUnmodifiedFlags() { ValidateFlags(false); } bool CommandLineFlagParser::ReportErrors() { // error_flags_ indicates errors we saw while parsing. // But we ignore undefined-names if ok'ed by --undef_ok if (!FLAGS_undefok.empty()) { vector flaglist; ParseFlagList(FLAGS_undefok.c_str(), &flaglist); for (size_t i = 0; i < flaglist.size(); ++i) { // We also deal with --no, in case the flagname was boolean const string no_version = string("no") + flaglist[i]; if (undefined_names_.find(flaglist[i]) != undefined_names_.end()) { error_flags_[flaglist[i]] = ""; // clear the error message } else if (undefined_names_.find(no_version) != undefined_names_.end()) { error_flags_[no_version] = ""; } } } // Likewise, if they decided to allow reparsing, all undefined-names // are ok; we just silently ignore them now, and hope that a future // parse will pick them up somehow. if (allow_command_line_reparsing) { for (map::const_iterator it = undefined_names_.begin(); it != undefined_names_.end(); ++it) error_flags_[it->first] = ""; // clear the error message } bool found_error = false; string error_message; for (map::const_iterator it = error_flags_.begin(); it != error_flags_.end(); ++it) { if (!it->second.empty()) { error_message.append(it->second.data(), it->second.size()); found_error = true; } } if (found_error) ReportError(DO_NOT_DIE, "%s", error_message.c_str()); return found_error; } string CommandLineFlagParser::ProcessOptionsFromStringLocked( const string& contentdata, FlagSettingMode set_mode) { string retval; const char* flagfile_contents = contentdata.c_str(); bool flags_are_relevant = true; // set to false when filenames don't match bool in_filename_section = false; const char* line_end = flagfile_contents; // We read this file a line at a time. for (; line_end; flagfile_contents = line_end + 1) { while (*flagfile_contents && isspace(*flagfile_contents)) ++flagfile_contents; // Windows uses "\r\n" line_end = strchr(flagfile_contents, '\r'); if (line_end == NULL) line_end = strchr(flagfile_contents, '\n'); size_t len = line_end ? line_end - flagfile_contents : strlen(flagfile_contents); string line(flagfile_contents, len); // Each line can be one of four things: // 1) A comment line -- we skip it // 2) An empty line -- we skip it // 3) A list of filenames -- starts a new filenames+flags section // 4) A --flag=value line -- apply if previous filenames match if (line.empty() || line[0] == '#') { // comment or empty line; just ignore } else if (line[0] == '-') { // flag in_filename_section = false; // instead, it was a flag-line if (!flags_are_relevant) // skip this flag; applies to someone else continue; const char* name_and_val = line.c_str() + 1; // skip the leading - if (*name_and_val == '-') name_and_val++; // skip second - too string key; const char* value; string error_message; CommandLineFlag* flag = registry_->SplitArgumentLocked(name_and_val, &key, &value, &error_message); // By API, errors parsing flagfile lines are silently ignored. if (flag == NULL) { // "WARNING: flagname '" + key + "' not found\n" } else if (value == NULL) { // "WARNING: flagname '" + key + "' missing a value\n" } else { retval += ProcessSingleOptionLocked(flag, value, set_mode); } } else { // a filename! if (!in_filename_section) { // start over: assume filenames don't match in_filename_section = true; flags_are_relevant = false; } // Split the line up at spaces into glob-patterns const char* space = line.c_str(); // just has to be non-NULL for (const char* word = line.c_str(); *space; word = space+1) { if (flags_are_relevant) // we can stop as soon as we match break; space = strchr(word, ' '); if (space == NULL) space = word + strlen(word); const string glob(word, space - word); // We try matching both against the full argv0 and basename(argv0) if (glob == ProgramInvocationName() // small optimization || glob == ProgramInvocationShortName() #if defined(HAVE_FNMATCH_H) || fnmatch(glob.c_str(), ProgramInvocationName(), FNM_PATHNAME) == 0 || fnmatch(glob.c_str(), ProgramInvocationShortName(), FNM_PATHNAME) == 0 #elif defined(HAVE_SHLWAPI_H) || PathMatchSpecA(glob.c_str(), ProgramInvocationName()) || PathMatchSpecA(glob.c_str(), ProgramInvocationShortName()) #endif ) { flags_are_relevant = true; } } } } return retval; } // -------------------------------------------------------------------- // GetFromEnv() // AddFlagValidator() // These are helper functions for routines like BoolFromEnv() and // RegisterFlagValidator, defined below. They're defined here so // they can live in the unnamed namespace (which makes friendship // declarations for these classes possible). // -------------------------------------------------------------------- template T GetFromEnv(const char *varname, T dflt) { std::string valstr; if (SafeGetEnv(varname, valstr)) { FlagValue ifv(new T, true); if (!ifv.ParseFrom(valstr.c_str())) { ReportError(DIE, "ERROR: error parsing env variable '%s' with value '%s'\n", varname, valstr.c_str()); } return OTHER_VALUE_AS(ifv, T); } else return dflt; } bool AddFlagValidator(const void* flag_ptr, ValidateFnProto validate_fn_proto) { // We want a lock around this routine, in case two threads try to // add a validator (hopefully the same one!) at once. We could use // our own thread, but we need to loook at the registry anyway, so // we just steal that one. FlagRegistry* const registry = FlagRegistry::GlobalRegistry(); FlagRegistryLock frl(registry); // First, find the flag whose current-flag storage is 'flag'. // This is the CommandLineFlag whose current_->value_buffer_ == flag CommandLineFlag* flag = registry->FindFlagViaPtrLocked(flag_ptr); if (!flag) { LOG(WARNING) << "Ignoring RegisterValidateFunction() for flag pointer " << flag_ptr << ": no flag found at that address"; return false; } else if (validate_fn_proto == flag->validate_function()) { return true; // ok to register the same function over and over again } else if (validate_fn_proto != NULL && flag->validate_function() != NULL) { LOG(WARNING) << "Ignoring RegisterValidateFunction() for flag '" << flag->name() << "': validate-fn already registered"; return false; } else { flag->validate_fn_proto_ = validate_fn_proto; return true; } } } // end unnamed namespaces // Now define the functions that are exported via the .h file // -------------------------------------------------------------------- // FlagRegisterer // This class exists merely to have a global constructor (the // kind that runs before main(), that goes an initializes each // flag that's been declared. Note that it's very important we // don't have a destructor that deletes flag_, because that would // cause us to delete current_storage/defvalue_storage as well, // which can cause a crash if anything tries to access the flag // values in a global destructor. // -------------------------------------------------------------------- namespace { void RegisterCommandLineFlag(const char* name, const char* help, const char* filename, FlagValue* current, FlagValue* defvalue) { if (help == NULL) help = ""; // Importantly, flag_ will never be deleted, so storage is always good. CommandLineFlag* flag = new CommandLineFlag(name, help, filename, current, defvalue); FlagRegistry::GlobalRegistry()->RegisterFlag(flag); // default registry } } template FlagRegisterer::FlagRegisterer(const char* name, const char* help, const char* filename, FlagType* current_storage, FlagType* defvalue_storage) { FlagValue* const current = new FlagValue(current_storage, false); FlagValue* const defvalue = new FlagValue(defvalue_storage, false); RegisterCommandLineFlag(name, help, filename, current, defvalue); } // Force compiler to generate code for the given template specialization. #define INSTANTIATE_FLAG_REGISTERER_CTOR(type) \ template GFLAGS_DLL_DECL FlagRegisterer::FlagRegisterer( \ const char* name, const char* help, const char* filename, \ type* current_storage, type* defvalue_storage) // Do this for all supported flag types. INSTANTIATE_FLAG_REGISTERER_CTOR(bool); INSTANTIATE_FLAG_REGISTERER_CTOR(int32); INSTANTIATE_FLAG_REGISTERER_CTOR(uint32); INSTANTIATE_FLAG_REGISTERER_CTOR(int64); INSTANTIATE_FLAG_REGISTERER_CTOR(uint64); INSTANTIATE_FLAG_REGISTERER_CTOR(double); INSTANTIATE_FLAG_REGISTERER_CTOR(std::string); #undef INSTANTIATE_FLAG_REGISTERER_CTOR // -------------------------------------------------------------------- // GetAllFlags() // The main way the FlagRegistry class exposes its data. This // returns, as strings, all the info about all the flags in // the main registry, sorted first by filename they are defined // in, and then by flagname. // -------------------------------------------------------------------- struct FilenameFlagnameCmp { bool operator()(const CommandLineFlagInfo& a, const CommandLineFlagInfo& b) const { int cmp = strcmp(a.filename.c_str(), b.filename.c_str()); if (cmp == 0) cmp = strcmp(a.name.c_str(), b.name.c_str()); // secondary sort key return cmp < 0; } }; void GetAllFlags(vector* OUTPUT) { FlagRegistry* const registry = FlagRegistry::GlobalRegistry(); registry->Lock(); for (FlagRegistry::FlagConstIterator i = registry->flags_.begin(); i != registry->flags_.end(); ++i) { CommandLineFlagInfo fi; i->second->FillCommandLineFlagInfo(&fi); OUTPUT->push_back(fi); } registry->Unlock(); // Now sort the flags, first by filename they occur in, then alphabetically sort(OUTPUT->begin(), OUTPUT->end(), FilenameFlagnameCmp()); } // -------------------------------------------------------------------- // SetArgv() // GetArgvs() // GetArgv() // GetArgv0() // ProgramInvocationName() // ProgramInvocationShortName() // SetUsageMessage() // ProgramUsage() // Functions to set and get argv. Typically the setter is called // by ParseCommandLineFlags. Also can get the ProgramUsage string, // set by SetUsageMessage. // -------------------------------------------------------------------- // These values are not protected by a Mutex because they are normally // set only once during program startup. static string argv0("UNKNOWN"); // just the program name static string cmdline; // the entire command-line static string program_usage; static vector argvs; static uint32 argv_sum = 0; void SetArgv(int argc, const char** argv) { static bool called_set_argv = false; if (called_set_argv) return; called_set_argv = true; assert(argc > 0); // every program has at least a name argv0 = argv[0]; cmdline.clear(); for (int i = 0; i < argc; i++) { if (i != 0) cmdline += " "; cmdline += argv[i]; argvs.push_back(argv[i]); } // Compute a simple sum of all the chars in argv argv_sum = 0; for (string::const_iterator c = cmdline.begin(); c != cmdline.end(); ++c) { argv_sum += *c; } } const vector& GetArgvs() { return argvs; } const char* GetArgv() { return cmdline.c_str(); } const char* GetArgv0() { return argv0.c_str(); } uint32 GetArgvSum() { return argv_sum; } const char* ProgramInvocationName() { // like the GNU libc fn return GetArgv0(); } const char* ProgramInvocationShortName() { // like the GNU libc fn size_t pos = argv0.rfind('/'); #ifdef OS_WINDOWS if (pos == string::npos) pos = argv0.rfind('\\'); #endif return (pos == string::npos ? argv0.c_str() : (argv0.c_str() + pos + 1)); } void SetUsageMessage(const string& usage) { program_usage = usage; } const char* ProgramUsage() { if (program_usage.empty()) { return "Warning: SetUsageMessage() never called"; } return program_usage.c_str(); } // -------------------------------------------------------------------- // SetVersionString() // VersionString() // -------------------------------------------------------------------- static string version_string; void SetVersionString(const string& version) { version_string = version; } const char* VersionString() { return version_string.c_str(); } // -------------------------------------------------------------------- // GetCommandLineOption() // GetCommandLineFlagInfo() // GetCommandLineFlagInfoOrDie() // SetCommandLineOption() // SetCommandLineOptionWithMode() // The programmatic way to set a flag's value, using a string // for its name rather than the variable itself (that is, // SetCommandLineOption("foo", x) rather than FLAGS_foo = x). // There's also a bit more flexibility here due to the various // set-modes, but typically these are used when you only have // that flag's name as a string, perhaps at runtime. // All of these work on the default, global registry. // For GetCommandLineOption, return false if no such flag // is known, true otherwise. We clear "value" if a suitable // flag is found. // -------------------------------------------------------------------- bool GetCommandLineOption(const char* name, string* value) { if (NULL == name) return false; assert(value); FlagRegistry* const registry = FlagRegistry::GlobalRegistry(); FlagRegistryLock frl(registry); CommandLineFlag* flag = registry->FindFlagLocked(name); if (flag == NULL) { return false; } else { *value = flag->current_value(); return true; } } bool GetCommandLineFlagInfo(const char* name, CommandLineFlagInfo* OUTPUT) { if (NULL == name) return false; FlagRegistry* const registry = FlagRegistry::GlobalRegistry(); FlagRegistryLock frl(registry); CommandLineFlag* flag = registry->FindFlagLocked(name); if (flag == NULL) { return false; } else { assert(OUTPUT); flag->FillCommandLineFlagInfo(OUTPUT); return true; } } CommandLineFlagInfo GetCommandLineFlagInfoOrDie(const char* name) { CommandLineFlagInfo info; if (!GetCommandLineFlagInfo(name, &info)) { fprintf(stderr, "FATAL ERROR: flag name '%s' doesn't exist\n", name); gflags_exitfunc(1); // almost certainly gflags_exitfunc() } return info; } string SetCommandLineOptionWithMode(const char* name, const char* value, FlagSettingMode set_mode) { string result; FlagRegistry* const registry = FlagRegistry::GlobalRegistry(); FlagRegistryLock frl(registry); CommandLineFlag* flag = registry->FindFlagLocked(name); if (flag) { CommandLineFlagParser parser(registry); result = parser.ProcessSingleOptionLocked(flag, value, set_mode); if (!result.empty()) { // in the error case, we've already logged // Could consider logging this change } } // The API of this function is that we return empty string on error return result; } string SetCommandLineOption(const char* name, const char* value) { return SetCommandLineOptionWithMode(name, value, SET_FLAGS_VALUE); } // -------------------------------------------------------------------- // FlagSaver // FlagSaverImpl // This class stores the states of all flags at construct time, // and restores all flags to that state at destruct time. // Its major implementation challenge is that it never modifies // pointers in the 'main' registry, so global FLAG_* vars always // point to the right place. // -------------------------------------------------------------------- class FlagSaverImpl { public: // Constructs an empty FlagSaverImpl object. explicit FlagSaverImpl(FlagRegistry* main_registry) : main_registry_(main_registry) { } ~FlagSaverImpl() { // reclaim memory from each of our CommandLineFlags vector::const_iterator it; for (it = backup_registry_.begin(); it != backup_registry_.end(); ++it) delete *it; } // Saves the flag states from the flag registry into this object. // It's an error to call this more than once. // Must be called when the registry mutex is not held. void SaveFromRegistry() { FlagRegistryLock frl(main_registry_); assert(backup_registry_.empty()); // call only once! for (FlagRegistry::FlagConstIterator it = main_registry_->flags_.begin(); it != main_registry_->flags_.end(); ++it) { const CommandLineFlag* main = it->second; // Sets up all the const variables in backup correctly CommandLineFlag* backup = new CommandLineFlag( main->name(), main->help(), main->filename(), main->current_->New(), main->defvalue_->New()); // Sets up all the non-const variables in backup correctly backup->CopyFrom(*main); backup_registry_.push_back(backup); // add it to a convenient list } } // Restores the saved flag states into the flag registry. We // assume no flags were added or deleted from the registry since // the SaveFromRegistry; if they were, that's trouble! Must be // called when the registry mutex is not held. void RestoreToRegistry() { FlagRegistryLock frl(main_registry_); vector::const_iterator it; for (it = backup_registry_.begin(); it != backup_registry_.end(); ++it) { CommandLineFlag* main = main_registry_->FindFlagLocked((*it)->name()); if (main != NULL) { // if NULL, flag got deleted from registry(!) main->CopyFrom(**it); } } } private: FlagRegistry* const main_registry_; vector backup_registry_; FlagSaverImpl(const FlagSaverImpl&); // no copying! void operator=(const FlagSaverImpl&); }; FlagSaver::FlagSaver() : impl_(new FlagSaverImpl(FlagRegistry::GlobalRegistry())) { impl_->SaveFromRegistry(); } FlagSaver::~FlagSaver() { impl_->RestoreToRegistry(); delete impl_; } // -------------------------------------------------------------------- // CommandlineFlagsIntoString() // ReadFlagsFromString() // AppendFlagsIntoFile() // ReadFromFlagsFile() // These are mostly-deprecated routines that stick the // commandline flags into a file/string and read them back // out again. I can see a use for CommandlineFlagsIntoString, // for creating a flagfile, but the rest don't seem that useful // -- some, I think, are a poor-man's attempt at FlagSaver -- // and are included only until we can delete them from callers. // Note they don't save --flagfile flags (though they do save // the result of having called the flagfile, of course). // -------------------------------------------------------------------- static string TheseCommandlineFlagsIntoString( const vector& flags) { vector::const_iterator i; size_t retval_space = 0; for (i = flags.begin(); i != flags.end(); ++i) { // An (over)estimate of how much space it will take to print this flag retval_space += i->name.length() + i->current_value.length() + 5; } string retval; retval.reserve(retval_space); for (i = flags.begin(); i != flags.end(); ++i) { retval += "--"; retval += i->name; retval += "="; retval += i->current_value; retval += "\n"; } return retval; } string CommandlineFlagsIntoString() { vector sorted_flags; GetAllFlags(&sorted_flags); return TheseCommandlineFlagsIntoString(sorted_flags); } bool ReadFlagsFromString(const string& flagfilecontents, const char* /*prog_name*/, // TODO(csilvers): nix this bool errors_are_fatal) { FlagRegistry* const registry = FlagRegistry::GlobalRegistry(); FlagSaverImpl saved_states(registry); saved_states.SaveFromRegistry(); CommandLineFlagParser parser(registry); registry->Lock(); parser.ProcessOptionsFromStringLocked(flagfilecontents, SET_FLAGS_VALUE); registry->Unlock(); // Should we handle --help and such when reading flags from a string? Sure. HandleCommandLineHelpFlags(); if (parser.ReportErrors()) { // Error. Restore all global flags to their previous values. if (errors_are_fatal) gflags_exitfunc(1); saved_states.RestoreToRegistry(); return false; } return true; } // TODO(csilvers): nix prog_name in favor of ProgramInvocationShortName() bool AppendFlagsIntoFile(const string& filename, const char *prog_name) { FILE *fp; if (SafeFOpen(&fp, filename.c_str(), "a") != 0) { return false; } if (prog_name) fprintf(fp, "%s\n", prog_name); vector flags; GetAllFlags(&flags); // But we don't want --flagfile, which leads to weird recursion issues vector::iterator i; for (i = flags.begin(); i != flags.end(); ++i) { if (strcmp(i->name.c_str(), "flagfile") == 0) { flags.erase(i); break; } } fprintf(fp, "%s", TheseCommandlineFlagsIntoString(flags).c_str()); fclose(fp); return true; } bool ReadFromFlagsFile(const string& filename, const char* prog_name, bool errors_are_fatal) { return ReadFlagsFromString(ReadFileIntoString(filename.c_str()), prog_name, errors_are_fatal); } // -------------------------------------------------------------------- // BoolFromEnv() // Int32FromEnv() // Uint32FromEnv() // Int64FromEnv() // Uint64FromEnv() // DoubleFromEnv() // StringFromEnv() // Reads the value from the environment and returns it. // We use an FlagValue to make the parsing easy. // Example usage: // DEFINE_bool(myflag, BoolFromEnv("MYFLAG_DEFAULT", false), "whatever"); // -------------------------------------------------------------------- bool BoolFromEnv(const char *v, bool dflt) { return GetFromEnv(v, dflt); } int32 Int32FromEnv(const char *v, int32 dflt) { return GetFromEnv(v, dflt); } uint32 Uint32FromEnv(const char *v, uint32 dflt) { return GetFromEnv(v, dflt); } int64 Int64FromEnv(const char *v, int64 dflt) { return GetFromEnv(v, dflt); } uint64 Uint64FromEnv(const char *v, uint64 dflt) { return GetFromEnv(v, dflt); } double DoubleFromEnv(const char *v, double dflt) { return GetFromEnv(v, dflt); } #ifdef _MSC_VER # pragma warning(push) # pragma warning(disable: 4996) // ignore getenv security warning #endif const char *StringFromEnv(const char *varname, const char *dflt) { const char* const val = getenv(varname); return val ? val : dflt; } #ifdef _MSC_VER # pragma warning(pop) #endif // -------------------------------------------------------------------- // RegisterFlagValidator() // RegisterFlagValidator() is the function that clients use to // 'decorate' a flag with a validation function. Once this is // done, every time the flag is set (including when the flag // is parsed from argv), the validator-function is called. // These functions return true if the validator was added // successfully, or false if not: the flag already has a validator, // (only one allowed per flag), the 1st arg isn't a flag, etc. // This function is not thread-safe. // -------------------------------------------------------------------- bool RegisterFlagValidator(const bool* flag, bool (*validate_fn)(const char*, bool)) { return AddFlagValidator(flag, reinterpret_cast(validate_fn)); } bool RegisterFlagValidator(const int32* flag, bool (*validate_fn)(const char*, int32)) { return AddFlagValidator(flag, reinterpret_cast(validate_fn)); } bool RegisterFlagValidator(const uint32* flag, bool (*validate_fn)(const char*, uint32)) { return AddFlagValidator(flag, reinterpret_cast(validate_fn)); } bool RegisterFlagValidator(const int64* flag, bool (*validate_fn)(const char*, int64)) { return AddFlagValidator(flag, reinterpret_cast(validate_fn)); } bool RegisterFlagValidator(const uint64* flag, bool (*validate_fn)(const char*, uint64)) { return AddFlagValidator(flag, reinterpret_cast(validate_fn)); } bool RegisterFlagValidator(const double* flag, bool (*validate_fn)(const char*, double)) { return AddFlagValidator(flag, reinterpret_cast(validate_fn)); } bool RegisterFlagValidator(const string* flag, bool (*validate_fn)(const char*, const string&)) { return AddFlagValidator(flag, reinterpret_cast(validate_fn)); } // -------------------------------------------------------------------- // ParseCommandLineFlags() // ParseCommandLineNonHelpFlags() // HandleCommandLineHelpFlags() // This is the main function called from main(), to actually // parse the commandline. It modifies argc and argv as described // at the top of gflags.h. You can also divide this // function into two parts, if you want to do work between // the parsing of the flags and the printing of any help output. // -------------------------------------------------------------------- static uint32 ParseCommandLineFlagsInternal(int* argc, char*** argv, bool remove_flags, bool do_report) { SetArgv(*argc, const_cast(*argv)); // save it for later FlagRegistry* const registry = FlagRegistry::GlobalRegistry(); CommandLineFlagParser parser(registry); // When we parse the commandline flags, we'll handle --flagfile, // --tryfromenv, etc. as we see them (since flag-evaluation order // may be important). But sometimes apps set FLAGS_tryfromenv/etc. // manually before calling ParseCommandLineFlags. We want to evaluate // those too, as if they were the first flags on the commandline. registry->Lock(); parser.ProcessFlagfileLocked(FLAGS_flagfile, SET_FLAGS_VALUE); // Last arg here indicates whether flag-not-found is a fatal error or not parser.ProcessFromenvLocked(FLAGS_fromenv, SET_FLAGS_VALUE, true); parser.ProcessFromenvLocked(FLAGS_tryfromenv, SET_FLAGS_VALUE, false); registry->Unlock(); // Now get the flags specified on the commandline const int r = parser.ParseNewCommandLineFlags(argc, argv, remove_flags); if (do_report) HandleCommandLineHelpFlags(); // may cause us to exit on --help, etc. // See if any of the unset flags fail their validation checks parser.ValidateUnmodifiedFlags(); if (parser.ReportErrors()) // may cause us to exit on illegal flags gflags_exitfunc(1); return r; } uint32 ParseCommandLineFlags(int* argc, char*** argv, bool remove_flags) { return ParseCommandLineFlagsInternal(argc, argv, remove_flags, true); } uint32 ParseCommandLineNonHelpFlags(int* argc, char*** argv, bool remove_flags) { return ParseCommandLineFlagsInternal(argc, argv, remove_flags, false); } // -------------------------------------------------------------------- // AllowCommandLineReparsing() // ReparseCommandLineNonHelpFlags() // This is most useful for shared libraries. The idea is if // a flag is defined in a shared library that is dlopen'ed // sometime after main(), you can ParseCommandLineFlags before // the dlopen, then ReparseCommandLineNonHelpFlags() after the // dlopen, to get the new flags. But you have to explicitly // Allow() it; otherwise, you get the normal default behavior // of unrecognized flags calling a fatal error. // TODO(csilvers): this isn't used. Just delete it? // -------------------------------------------------------------------- void AllowCommandLineReparsing() { allow_command_line_reparsing = true; } void ReparseCommandLineNonHelpFlags() { // We make a copy of argc and argv to pass in const vector& argvs = GetArgvs(); int tmp_argc = static_cast(argvs.size()); char** tmp_argv = new char* [tmp_argc + 1]; for (int i = 0; i < tmp_argc; ++i) tmp_argv[i] = strdup(argvs[i].c_str()); // TODO(csilvers): don't dup ParseCommandLineNonHelpFlags(&tmp_argc, &tmp_argv, false); for (int i = 0; i < tmp_argc; ++i) free(tmp_argv[i]); delete[] tmp_argv; } void ShutDownCommandLineFlags() { FlagRegistry::DeleteGlobalRegistry(); } } // namespace GFLAGS_NAMESPACE gflags-2.2.2/src/gflags.h.in000066400000000000000000000735421337211647400156130ustar00rootroot00000000000000// Copyright (c) 2006, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // --- // Revamped and reorganized by Craig Silverstein // // This is the file that should be included by any file which declares // or defines a command line flag or wants to parse command line flags // or print a program usage message (which will include information about // flags). Executive summary, in the form of an example foo.cc file: // // #include "foo.h" // foo.h has a line "DECLARE_int32(start);" // #include "validators.h" // hypothetical file defining ValidateIsFile() // // DEFINE_int32(end, 1000, "The last record to read"); // // DEFINE_string(filename, "my_file.txt", "The file to read"); // // Crash if the specified file does not exist. // static bool dummy = RegisterFlagValidator(&FLAGS_filename, // &ValidateIsFile); // // DECLARE_bool(verbose); // some other file has a DEFINE_bool(verbose, ...) // // void MyFunc() { // if (FLAGS_verbose) printf("Records %d-%d\n", FLAGS_start, FLAGS_end); // } // // Then, at the command-line: // ./foo --noverbose --start=5 --end=100 // // For more details, see // doc/gflags.html // // --- A note about thread-safety: // // We describe many functions in this routine as being thread-hostile, // thread-compatible, or thread-safe. Here are the meanings we use: // // thread-safe: it is safe for multiple threads to call this routine // (or, when referring to a class, methods of this class) // concurrently. // thread-hostile: it is not safe for multiple threads to call this // routine (or methods of this class) concurrently. In gflags, // most thread-hostile routines are intended to be called early in, // or even before, main() -- that is, before threads are spawned. // thread-compatible: it is safe for multiple threads to read from // this variable (when applied to variables), or to call const // methods of this class (when applied to classes), as long as no // other thread is writing to the variable or calling non-const // methods of this class. #ifndef GFLAGS_GFLAGS_H_ #define GFLAGS_GFLAGS_H_ #include #include #include "gflags/gflags_declare.h" // IWYU pragma: export // We always want to export variables defined in user code #ifndef GFLAGS_DLL_DEFINE_FLAG # if GFLAGS_IS_A_DLL && defined(_MSC_VER) # define GFLAGS_DLL_DEFINE_FLAG __declspec(dllexport) # else # define GFLAGS_DLL_DEFINE_FLAG # endif #endif namespace GFLAGS_NAMESPACE { // -------------------------------------------------------------------- // To actually define a flag in a file, use DEFINE_bool, // DEFINE_string, etc. at the bottom of this file. You may also find // it useful to register a validator with the flag. This ensures that // when the flag is parsed from the commandline, or is later set via // SetCommandLineOption, we call the validation function. It is _not_ // called when you assign the value to the flag directly using the = operator. // // The validation function should return true if the flag value is valid, and // false otherwise. If the function returns false for the new setting of the // flag, the flag will retain its current value. If it returns false for the // default value, ParseCommandLineFlags() will die. // // This function is safe to call at global construct time (as in the // example below). // // Example use: // static bool ValidatePort(const char* flagname, int32 value) { // if (value > 0 && value < 32768) // value is ok // return true; // printf("Invalid value for --%s: %d\n", flagname, (int)value); // return false; // } // DEFINE_int32(port, 0, "What port to listen on"); // static bool dummy = RegisterFlagValidator(&FLAGS_port, &ValidatePort); // Returns true if successfully registered, false if not (because the // first argument doesn't point to a command-line flag, or because a // validator is already registered for this flag). extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const bool* flag, bool (*validate_fn)(const char*, bool)); extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const int32* flag, bool (*validate_fn)(const char*, int32)); extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const uint32* flag, bool (*validate_fn)(const char*, uint32)); extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const int64* flag, bool (*validate_fn)(const char*, int64)); extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const uint64* flag, bool (*validate_fn)(const char*, uint64)); extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const double* flag, bool (*validate_fn)(const char*, double)); extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const std::string* flag, bool (*validate_fn)(const char*, const std::string&)); // Convenience macro for the registration of a flag validator #define DEFINE_validator(name, validator) \ static const bool name##_validator_registered = \ GFLAGS_NAMESPACE::RegisterFlagValidator(&FLAGS_##name, validator) // -------------------------------------------------------------------- // These methods are the best way to get access to info about the // list of commandline flags. Note that these routines are pretty slow. // GetAllFlags: mostly-complete info about the list, sorted by file. // ShowUsageWithFlags: pretty-prints the list to stdout (what --help does) // ShowUsageWithFlagsRestrict: limit to filenames with restrict as a substr // // In addition to accessing flags, you can also access argv[0] (the program // name) and argv (the entire commandline), which we sock away a copy of. // These variables are static, so you should only set them once. // // No need to export this data only structure from DLL, avoiding VS warning 4251. struct CommandLineFlagInfo { std::string name; // the name of the flag std::string type; // the type of the flag: int32, etc std::string description; // the "help text" associated with the flag std::string current_value; // the current value, as a string std::string default_value; // the default value, as a string std::string filename; // 'cleaned' version of filename holding the flag bool has_validator_fn; // true if RegisterFlagValidator called on this flag bool is_default; // true if the flag has the default value and // has not been set explicitly from the cmdline // or via SetCommandLineOption const void* flag_ptr; // pointer to the flag's current value (i.e. FLAGS_foo) }; // Using this inside of a validator is a recipe for a deadlock. // TODO(user) Fix locking when validators are running, to make it safe to // call validators during ParseAllFlags. // Also make sure then to uncomment the corresponding unit test in // gflags_unittest.sh extern GFLAGS_DLL_DECL void GetAllFlags(std::vector* OUTPUT); // These two are actually defined in gflags_reporting.cc. extern GFLAGS_DLL_DECL void ShowUsageWithFlags(const char *argv0); // what --help does extern GFLAGS_DLL_DECL void ShowUsageWithFlagsRestrict(const char *argv0, const char *restrict); // Create a descriptive string for a flag. // Goes to some trouble to make pretty line breaks. extern GFLAGS_DLL_DECL std::string DescribeOneFlag(const CommandLineFlagInfo& flag); // Thread-hostile; meant to be called before any threads are spawned. extern GFLAGS_DLL_DECL void SetArgv(int argc, const char** argv); // The following functions are thread-safe as long as SetArgv() is // only called before any threads start. extern GFLAGS_DLL_DECL const std::vector& GetArgvs(); extern GFLAGS_DLL_DECL const char* GetArgv(); // all of argv as a string extern GFLAGS_DLL_DECL const char* GetArgv0(); // only argv0 extern GFLAGS_DLL_DECL uint32 GetArgvSum(); // simple checksum of argv extern GFLAGS_DLL_DECL const char* ProgramInvocationName(); // argv0, or "UNKNOWN" if not set extern GFLAGS_DLL_DECL const char* ProgramInvocationShortName(); // basename(argv0) // ProgramUsage() is thread-safe as long as SetUsageMessage() is only // called before any threads start. extern GFLAGS_DLL_DECL const char* ProgramUsage(); // string set by SetUsageMessage() // VersionString() is thread-safe as long as SetVersionString() is only // called before any threads start. extern GFLAGS_DLL_DECL const char* VersionString(); // string set by SetVersionString() // -------------------------------------------------------------------- // Normally you access commandline flags by just saying "if (FLAGS_foo)" // or whatever, and set them by calling "FLAGS_foo = bar" (or, more // commonly, via the DEFINE_foo macro). But if you need a bit more // control, we have programmatic ways to get/set the flags as well. // These programmatic ways to access flags are thread-safe, but direct // access is only thread-compatible. // Return true iff the flagname was found. // OUTPUT is set to the flag's value, or unchanged if we return false. extern GFLAGS_DLL_DECL bool GetCommandLineOption(const char* name, std::string* OUTPUT); // Return true iff the flagname was found. OUTPUT is set to the flag's // CommandLineFlagInfo or unchanged if we return false. extern GFLAGS_DLL_DECL bool GetCommandLineFlagInfo(const char* name, CommandLineFlagInfo* OUTPUT); // Return the CommandLineFlagInfo of the flagname. exit() if name not found. // Example usage, to check if a flag's value is currently the default value: // if (GetCommandLineFlagInfoOrDie("foo").is_default) ... extern GFLAGS_DLL_DECL CommandLineFlagInfo GetCommandLineFlagInfoOrDie(const char* name); enum GFLAGS_DLL_DECL FlagSettingMode { // update the flag's value (can call this multiple times). SET_FLAGS_VALUE, // update the flag's value, but *only if* it has not yet been updated // with SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef". SET_FLAG_IF_DEFAULT, // set the flag's default value to this. If the flag has not yet updated // yet (via SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef") // change the flag's current value to the new default value as well. SET_FLAGS_DEFAULT }; // Set a particular flag ("command line option"). Returns a string // describing the new value that the option has been set to. The // return value API is not well-specified, so basically just depend on // it to be empty if the setting failed for some reason -- the name is // not a valid flag name, or the value is not a valid value -- and // non-empty else. // SetCommandLineOption uses set_mode == SET_FLAGS_VALUE (the common case) extern GFLAGS_DLL_DECL std::string SetCommandLineOption (const char* name, const char* value); extern GFLAGS_DLL_DECL std::string SetCommandLineOptionWithMode(const char* name, const char* value, FlagSettingMode set_mode); // -------------------------------------------------------------------- // Saves the states (value, default value, whether the user has set // the flag, registered validators, etc) of all flags, and restores // them when the FlagSaver is destroyed. This is very useful in // tests, say, when you want to let your tests change the flags, but // make sure that they get reverted to the original states when your // test is complete. // // Example usage: // void TestFoo() { // FlagSaver s1; // FLAG_foo = false; // FLAG_bar = "some value"; // // // test happens here. You can return at any time // // without worrying about restoring the FLAG values. // } // // Note: This class is marked with GFLAGS_ATTRIBUTE_UNUSED because all // the work is done in the constructor and destructor, so in the standard // usage example above, the compiler would complain that it's an // unused variable. // // This class is thread-safe. However, its destructor writes to // exactly the set of flags that have changed value during its // lifetime, so concurrent _direct_ access to those flags // (i.e. FLAGS_foo instead of {Get,Set}CommandLineOption()) is unsafe. class GFLAGS_DLL_DECL FlagSaver { public: FlagSaver(); ~FlagSaver(); private: class FlagSaverImpl* impl_; // we use pimpl here to keep API steady FlagSaver(const FlagSaver&); // no copying! void operator=(const FlagSaver&); }@GFLAGS_ATTRIBUTE_UNUSED@; // -------------------------------------------------------------------- // Some deprecated or hopefully-soon-to-be-deprecated functions. // This is often used for logging. TODO(csilvers): figure out a better way extern GFLAGS_DLL_DECL std::string CommandlineFlagsIntoString(); // Usually where this is used, a FlagSaver should be used instead. extern GFLAGS_DLL_DECL bool ReadFlagsFromString(const std::string& flagfilecontents, const char* prog_name, bool errors_are_fatal); // uses SET_FLAGS_VALUE // These let you manually implement --flagfile functionality. // DEPRECATED. extern GFLAGS_DLL_DECL bool AppendFlagsIntoFile(const std::string& filename, const char* prog_name); extern GFLAGS_DLL_DECL bool ReadFromFlagsFile(const std::string& filename, const char* prog_name, bool errors_are_fatal); // uses SET_FLAGS_VALUE // -------------------------------------------------------------------- // Useful routines for initializing flags from the environment. // In each case, if 'varname' does not exist in the environment // return defval. If 'varname' does exist but is not valid // (e.g., not a number for an int32 flag), abort with an error. // Otherwise, return the value. NOTE: for booleans, for true use // 't' or 'T' or 'true' or '1', for false 'f' or 'F' or 'false' or '0'. extern GFLAGS_DLL_DECL bool BoolFromEnv(const char *varname, bool defval); extern GFLAGS_DLL_DECL int32 Int32FromEnv(const char *varname, int32 defval); extern GFLAGS_DLL_DECL uint32 Uint32FromEnv(const char *varname, uint32 defval); extern GFLAGS_DLL_DECL int64 Int64FromEnv(const char *varname, int64 defval); extern GFLAGS_DLL_DECL uint64 Uint64FromEnv(const char *varname, uint64 defval); extern GFLAGS_DLL_DECL double DoubleFromEnv(const char *varname, double defval); extern GFLAGS_DLL_DECL const char *StringFromEnv(const char *varname, const char *defval); // -------------------------------------------------------------------- // The next two functions parse gflags from main(): // Set the "usage" message for this program. For example: // string usage("This program does nothing. Sample usage:\n"); // usage += argv[0] + " "; // SetUsageMessage(usage); // Do not include commandline flags in the usage: we do that for you! // Thread-hostile; meant to be called before any threads are spawned. extern GFLAGS_DLL_DECL void SetUsageMessage(const std::string& usage); // Sets the version string, which is emitted with --version. // For instance: SetVersionString("1.3"); // Thread-hostile; meant to be called before any threads are spawned. extern GFLAGS_DLL_DECL void SetVersionString(const std::string& version); // Looks for flags in argv and parses them. Rearranges argv to put // flags first, or removes them entirely if remove_flags is true. // If a flag is defined more than once in the command line or flag // file, the last definition is used. Returns the index (into argv) // of the first non-flag argument. // See top-of-file for more details on this function. #ifndef SWIG // In swig, use ParseCommandLineFlagsScript() instead. extern GFLAGS_DLL_DECL uint32 ParseCommandLineFlags(int *argc, char*** argv, bool remove_flags); #endif // Calls to ParseCommandLineNonHelpFlags and then to // HandleCommandLineHelpFlags can be used instead of a call to // ParseCommandLineFlags during initialization, in order to allow for // changing default values for some FLAGS (via // e.g. SetCommandLineOptionWithMode calls) between the time of // command line parsing and the time of dumping help information for // the flags as a result of command line parsing. If a flag is // defined more than once in the command line or flag file, the last // definition is used. Returns the index (into argv) of the first // non-flag argument. (If remove_flags is true, will always return 1.) extern GFLAGS_DLL_DECL uint32 ParseCommandLineNonHelpFlags(int *argc, char*** argv, bool remove_flags); // This is actually defined in gflags_reporting.cc. // This function is misnamed (it also handles --version, etc.), but // it's too late to change that now. :-( extern GFLAGS_DLL_DECL void HandleCommandLineHelpFlags(); // in gflags_reporting.cc // Allow command line reparsing. Disables the error normally // generated when an unknown flag is found, since it may be found in a // later parse. Thread-hostile; meant to be called before any threads // are spawned. extern GFLAGS_DLL_DECL void AllowCommandLineReparsing(); // Reparse the flags that have not yet been recognized. Only flags // registered since the last parse will be recognized. Any flag value // must be provided as part of the argument using "=", not as a // separate command line argument that follows the flag argument. // Intended for handling flags from dynamically loaded libraries, // since their flags are not registered until they are loaded. extern GFLAGS_DLL_DECL void ReparseCommandLineNonHelpFlags(); // Clean up memory allocated by flags. This is only needed to reduce // the quantity of "potentially leaked" reports emitted by memory // debugging tools such as valgrind. It is not required for normal // operation, or for the google perftools heap-checker. It must only // be called when the process is about to exit, and all threads that // might access flags are quiescent. Referencing flags after this is // called will have unexpected consequences. This is not safe to run // when multiple threads might be running: the function is // thread-hostile. extern GFLAGS_DLL_DECL void ShutDownCommandLineFlags(); // -------------------------------------------------------------------- // Now come the command line flag declaration/definition macros that // will actually be used. They're kind of hairy. A major reason // for this is initialization: we want people to be able to access // variables in global constructors and have that not crash, even if // their global constructor runs before the global constructor here. // (Obviously, we can't guarantee the flags will have the correct // default value in that case, but at least accessing them is safe.) // The only way to do that is have flags point to a static buffer. // So we make one, using a union to ensure proper alignment, and // then use placement-new to actually set up the flag with the // correct default value. In the same vein, we have to worry about // flag access in global destructors, so FlagRegisterer has to be // careful never to destroy the flag-values it constructs. // // Note that when we define a flag variable FLAGS_, we also // preemptively define a junk variable, FLAGS_no. This is to // cause a link-time error if someone tries to define 2 flags with // names like "logging" and "nologging". We do this because a bool // flag FLAG can be set from the command line to true with a "-FLAG" // argument, and to false with a "-noFLAG" argument, and so this can // potentially avert confusion. // // We also put flags into their own namespace. It is purposefully // named in an opaque way that people should have trouble typing // directly. The idea is that DEFINE puts the flag in the weird // namespace, and DECLARE imports the flag from there into the current // namespace. The net result is to force people to use DECLARE to get // access to a flag, rather than saying "extern GFLAGS_DLL_DECL bool FLAGS_whatever;" // or some such instead. We want this so we can put extra // functionality (like sanity-checking) in DECLARE if we want, and // make sure it is picked up everywhere. // // We also put the type of the variable in the namespace, so that // people can't DECLARE_int32 something that they DEFINE_bool'd // elsewhere. class GFLAGS_DLL_DECL FlagRegisterer { public: // We instantiate this template ctor for all supported types, // so it is possible to place implementation of the FlagRegisterer ctor in // .cc file. // Calling this constructor with unsupported type will produce linker error. template FlagRegisterer(const char* name, const char* help, const char* filename, FlagType* current_storage, FlagType* defvalue_storage); }; // Force compiler to not generate code for the given template specialization. #if defined(_MSC_VER) && _MSC_VER < 1800 // Visual Studio 2013 version 12.0 #define GFLAGS_DECLARE_FLAG_REGISTERER_CTOR(type) #else #define GFLAGS_DECLARE_FLAG_REGISTERER_CTOR(type) \ extern template GFLAGS_DLL_DECL FlagRegisterer::FlagRegisterer( \ const char* name, const char* help, const char* filename, \ type* current_storage, type* defvalue_storage) #endif // Do this for all supported flag types. GFLAGS_DECLARE_FLAG_REGISTERER_CTOR(bool); GFLAGS_DECLARE_FLAG_REGISTERER_CTOR(int32); GFLAGS_DECLARE_FLAG_REGISTERER_CTOR(uint32); GFLAGS_DECLARE_FLAG_REGISTERER_CTOR(int64); GFLAGS_DECLARE_FLAG_REGISTERER_CTOR(uint64); GFLAGS_DECLARE_FLAG_REGISTERER_CTOR(double); GFLAGS_DECLARE_FLAG_REGISTERER_CTOR(std::string); #undef GFLAGS_DECLARE_FLAG_REGISTERER_CTOR // If your application #defines STRIP_FLAG_HELP to a non-zero value // before #including this file, we remove the help message from the // binary file. This can reduce the size of the resulting binary // somewhat, and may also be useful for security reasons. extern GFLAGS_DLL_DECL const char kStrippedFlagHelp[]; } // namespace GFLAGS_NAMESPACE #ifndef SWIG // In swig, ignore the main flag declarations #if defined(STRIP_FLAG_HELP) && STRIP_FLAG_HELP > 0 // Need this construct to avoid the 'defined but not used' warning. #define MAYBE_STRIPPED_HELP(txt) \ (false ? (txt) : GFLAGS_NAMESPACE::kStrippedFlagHelp) #else #define MAYBE_STRIPPED_HELP(txt) txt #endif // Each command-line flag has two variables associated with it: one // with the current value, and one with the default value. However, // we have a third variable, which is where value is assigned; it's a // constant. This guarantees that FLAG_##value is initialized at // static initialization time (e.g. before program-start) rather than // than global construction time (which is after program-start but // before main), at least when 'value' is a compile-time constant. We // use a small trick for the "default value" variable, and call it // FLAGS_no. This serves the second purpose of assuring a // compile error if someone tries to define a flag named no // which is illegal (--foo and --nofoo both affect the "foo" flag). #define DEFINE_VARIABLE(type, shorttype, name, value, help) \ namespace fL##shorttype { \ static const type FLAGS_nono##name = value; \ /* We always want to export defined variables, dll or no */ \ GFLAGS_DLL_DEFINE_FLAG type FLAGS_##name = FLAGS_nono##name; \ static type FLAGS_no##name = FLAGS_nono##name; \ static GFLAGS_NAMESPACE::FlagRegisterer o_##name( \ #name, MAYBE_STRIPPED_HELP(help), __FILE__, \ &FLAGS_##name, &FLAGS_no##name); \ } \ using fL##shorttype::FLAGS_##name // For DEFINE_bool, we want to do the extra check that the passed-in // value is actually a bool, and not a string or something that can be // coerced to a bool. These declarations (no definition needed!) will // help us do that, and never evaluate From, which is important. // We'll use 'sizeof(IsBool(val))' to distinguish. This code requires // that the compiler have different sizes for bool & double. Since // this is not guaranteed by the standard, we check it with a // COMPILE_ASSERT. namespace fLB { struct CompileAssert {}; typedef CompileAssert expected_sizeof_double_neq_sizeof_bool[ (sizeof(double) != sizeof(bool)) ? 1 : -1]; template double GFLAGS_DLL_DECL IsBoolFlag(const From& from); GFLAGS_DLL_DECL bool IsBoolFlag(bool from); } // namespace fLB // Here are the actual DEFINE_*-macros. The respective DECLARE_*-macros // are in a separate include, gflags_declare.h, for reducing // the physical transitive size for DECLARE use. #define DEFINE_bool(name, val, txt) \ namespace fLB { \ typedef ::fLB::CompileAssert FLAG_##name##_value_is_not_a_bool[ \ (sizeof(::fLB::IsBoolFlag(val)) != sizeof(double))? 1: -1]; \ } \ DEFINE_VARIABLE(bool, B, name, val, txt) #define DEFINE_int32(name, val, txt) \ DEFINE_VARIABLE(GFLAGS_NAMESPACE::int32, I, \ name, val, txt) #define DEFINE_uint32(name,val, txt) \ DEFINE_VARIABLE(GFLAGS_NAMESPACE::uint32, U, \ name, val, txt) #define DEFINE_int64(name, val, txt) \ DEFINE_VARIABLE(GFLAGS_NAMESPACE::int64, I64, \ name, val, txt) #define DEFINE_uint64(name,val, txt) \ DEFINE_VARIABLE(GFLAGS_NAMESPACE::uint64, U64, \ name, val, txt) #define DEFINE_double(name, val, txt) \ DEFINE_VARIABLE(double, D, name, val, txt) // Strings are trickier, because they're not a POD, so we can't // construct them at static-initialization time (instead they get // constructed at global-constructor time, which is much later). To // try to avoid crashes in that case, we use a char buffer to store // the string, which we can static-initialize, and then placement-new // into it later. It's not perfect, but the best we can do. namespace fLS { inline clstring* dont_pass0toDEFINE_string(char *stringspot, const char *value) { return new(stringspot) clstring(value); } inline clstring* dont_pass0toDEFINE_string(char *stringspot, const clstring &value) { return new(stringspot) clstring(value); } inline clstring* dont_pass0toDEFINE_string(char *stringspot, int value); // Auxiliary class used to explicitly call destructor of string objects // allocated using placement new during static program deinitialization. // The destructor MUST be an inline function such that the explicit // destruction occurs in the same compilation unit as the placement new. class StringFlagDestructor { void *current_storage_; void *defvalue_storage_; public: StringFlagDestructor(void *current, void *defvalue) : current_storage_(current), defvalue_storage_(defvalue) {} ~StringFlagDestructor() { reinterpret_cast(current_storage_ )->~clstring(); reinterpret_cast(defvalue_storage_)->~clstring(); } }; } // namespace fLS // We need to define a var named FLAGS_no##name so people don't define // --string and --nostring. And we need a temporary place to put val // so we don't have to evaluate it twice. Two great needs that go // great together! // The weird 'using' + 'extern' inside the fLS namespace is to work around // an unknown compiler bug/issue with the gcc 4.2.1 on SUSE 10. See // http://code.google.com/p/google-gflags/issues/detail?id=20 #define DEFINE_string(name, val, txt) \ namespace fLS { \ using ::fLS::clstring; \ using ::fLS::StringFlagDestructor; \ static union { void* align; char s[sizeof(clstring)]; } s_##name[2]; \ clstring* const FLAGS_no##name = ::fLS:: \ dont_pass0toDEFINE_string(s_##name[0].s, \ val); \ static GFLAGS_NAMESPACE::FlagRegisterer o_##name( \ #name, MAYBE_STRIPPED_HELP(txt), __FILE__, \ FLAGS_no##name, new (s_##name[1].s) clstring(*FLAGS_no##name)); \ static StringFlagDestructor d_##name(s_##name[0].s, s_##name[1].s); \ extern GFLAGS_DLL_DEFINE_FLAG clstring& FLAGS_##name; \ using fLS::FLAGS_##name; \ clstring& FLAGS_##name = *FLAGS_no##name; \ } \ using fLS::FLAGS_##name #endif // SWIG @INCLUDE_GFLAGS_NS_H@ #endif // GFLAGS_GFLAGS_H_ gflags-2.2.2/src/gflags_completions.cc000066400000000000000000000657301337211647400177600ustar00rootroot00000000000000// Copyright (c) 2008, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // --- // Bash-style command line flag completion for C++ binaries // // This module implements bash-style completions. It achieves this // goal in the following broad chunks: // // 1) Take a to-be-completed word, and examine it for search hints // 2) Identify all potentially matching flags // 2a) If there are no matching flags, do nothing. // 2b) If all matching flags share a common prefix longer than the // completion word, output just that matching prefix // 3) Categorize those flags to produce a rough ordering of relevence. // 4) Potentially trim the set of flags returned to a smaller number // that bash is happier with // 5) Output the matching flags in groups ordered by relevence. // 5a) Force bash to place most-relevent groups at the top of the list // 5b) Trim most flag's descriptions to fit on a single terminal line #include #include #include // for strlen #include #include #include #include #include "config.h" #include "gflags/gflags.h" #include "gflags/gflags_completions.h" #include "util.h" using std::set; using std::string; using std::vector; DEFINE_string(tab_completion_word, "", "If non-empty, HandleCommandLineCompletions() will hijack the " "process and attempt to do bash-style command line flag " "completion on this value."); DEFINE_int32(tab_completion_columns, 80, "Number of columns to use in output for tab completion"); namespace GFLAGS_NAMESPACE { namespace { // Function prototypes and Type forward declarations. Code may be // more easily understood if it is roughly ordered according to // control flow, rather than by C's "declare before use" ordering struct CompletionOptions; struct NotableFlags; // The entry point if flag completion is to be used. static void PrintFlagCompletionInfo(void); // 1) Examine search word static void CanonicalizeCursorWordAndSearchOptions( const string &cursor_word, string *canonical_search_token, CompletionOptions *options); static bool RemoveTrailingChar(string *str, char c); // 2) Find all matches static void FindMatchingFlags( const vector &all_flags, const CompletionOptions &options, const string &match_token, set *all_matches, string *longest_common_prefix); static bool DoesSingleFlagMatch( const CommandLineFlagInfo &flag, const CompletionOptions &options, const string &match_token); // 3) Categorize matches static void CategorizeAllMatchingFlags( const set &all_matches, const string &search_token, const string &module, const string &package_dir, NotableFlags *notable_flags); static void TryFindModuleAndPackageDir( const vector &all_flags, string *module, string *package_dir); // 4) Decide which flags to use static void FinalizeCompletionOutput( const set &matching_flags, CompletionOptions *options, NotableFlags *notable_flags, vector *completions); static void RetrieveUnusedFlags( const set &matching_flags, const NotableFlags ¬able_flags, set *unused_flags); // 5) Output matches static void OutputSingleGroupWithLimit( const set &group, const string &line_indentation, const string &header, const string &footer, bool long_output_format, int *remaining_line_limit, size_t *completion_elements_added, vector *completions); // (helpers for #5) static string GetShortFlagLine( const string &line_indentation, const CommandLineFlagInfo &info); static string GetLongFlagLine( const string &line_indentation, const CommandLineFlagInfo &info); // // Useful types // Try to deduce the intentions behind this completion attempt. Return the // canonical search term in 'canonical_search_token'. Binary search options // are returned in the various booleans, which should all have intuitive // semantics, possibly except: // - return_all_matching_flags: Generally, we'll trim the number of // returned candidates to some small number, showing those that are // most likely to be useful first. If this is set, however, the user // really does want us to return every single flag as an option. // - force_no_update: Any time we output lines, all of which share a // common prefix, bash will 'helpfully' not even bother to show the // output, instead changing the current word to be that common prefix. // If it's clear this shouldn't happen, we'll set this boolean struct CompletionOptions { bool flag_name_substring_search; bool flag_location_substring_search; bool flag_description_substring_search; bool return_all_matching_flags; bool force_no_update; CompletionOptions(): flag_name_substring_search(false), flag_location_substring_search(false), flag_description_substring_search(false), return_all_matching_flags(false), force_no_update(false) { } }; // Notable flags are flags that are special or preferred for some // reason. For example, flags that are defined in the binary's module // are expected to be much more relevent than flags defined in some // other random location. These sets are specified roughly in precedence // order. Once a flag is placed in one of these 'higher' sets, it won't // be placed in any of the 'lower' sets. struct NotableFlags { typedef set FlagSet; FlagSet perfect_match_flag; FlagSet module_flags; // Found in module file FlagSet package_flags; // Found in same directory as module file FlagSet most_common_flags; // One of the XXX most commonly supplied flags FlagSet subpackage_flags; // Found in subdirectories of package }; // // Tab completion implementation - entry point static void PrintFlagCompletionInfo(void) { string cursor_word = FLAGS_tab_completion_word; string canonical_token; CompletionOptions options = CompletionOptions(); CanonicalizeCursorWordAndSearchOptions( cursor_word, &canonical_token, &options); DVLOG(1) << "Identified canonical_token: '" << canonical_token << "'"; vector all_flags; set matching_flags; GetAllFlags(&all_flags); DVLOG(2) << "Found " << all_flags.size() << " flags overall"; string longest_common_prefix; FindMatchingFlags( all_flags, options, canonical_token, &matching_flags, &longest_common_prefix); DVLOG(1) << "Identified " << matching_flags.size() << " matching flags"; DVLOG(1) << "Identified " << longest_common_prefix << " as longest common prefix."; if (longest_common_prefix.size() > canonical_token.size()) { // There's actually a shared common prefix to all matching flags, // so may as well output that and quit quickly. DVLOG(1) << "The common prefix '" << longest_common_prefix << "' was longer than the token '" << canonical_token << "'. Returning just this prefix for completion."; fprintf(stdout, "--%s", longest_common_prefix.c_str()); return; } if (matching_flags.empty()) { VLOG(1) << "There were no matching flags, returning nothing."; return; } string module; string package_dir; TryFindModuleAndPackageDir(all_flags, &module, &package_dir); DVLOG(1) << "Identified module: '" << module << "'"; DVLOG(1) << "Identified package_dir: '" << package_dir << "'"; NotableFlags notable_flags; CategorizeAllMatchingFlags( matching_flags, canonical_token, module, package_dir, ¬able_flags); DVLOG(2) << "Categorized matching flags:"; DVLOG(2) << " perfect_match: " << notable_flags.perfect_match_flag.size(); DVLOG(2) << " module: " << notable_flags.module_flags.size(); DVLOG(2) << " package: " << notable_flags.package_flags.size(); DVLOG(2) << " most common: " << notable_flags.most_common_flags.size(); DVLOG(2) << " subpackage: " << notable_flags.subpackage_flags.size(); vector completions; FinalizeCompletionOutput( matching_flags, &options, ¬able_flags, &completions); if (options.force_no_update) completions.push_back("~"); DVLOG(1) << "Finalized with " << completions.size() << " chosen completions"; for (vector::const_iterator it = completions.begin(); it != completions.end(); ++it) { DVLOG(9) << " Completion entry: '" << *it << "'"; fprintf(stdout, "%s\n", it->c_str()); } } // 1) Examine search word (and helper method) static void CanonicalizeCursorWordAndSearchOptions( const string &cursor_word, string *canonical_search_token, CompletionOptions *options) { *canonical_search_token = cursor_word; if (canonical_search_token->empty()) return; // Get rid of leading quotes and dashes in the search term if ((*canonical_search_token)[0] == '"') *canonical_search_token = canonical_search_token->substr(1); while ((*canonical_search_token)[0] == '-') *canonical_search_token = canonical_search_token->substr(1); options->flag_name_substring_search = false; options->flag_location_substring_search = false; options->flag_description_substring_search = false; options->return_all_matching_flags = false; options->force_no_update = false; // Look for all search options we can deduce now. Do this by walking // backwards through the term, looking for up to three '?' and up to // one '+' as suffixed characters. Consume them if found, and remove // them from the canonical search token. int found_question_marks = 0; int found_plusses = 0; while (true) { if (found_question_marks < 3 && RemoveTrailingChar(canonical_search_token, '?')) { ++found_question_marks; continue; } if (found_plusses < 1 && RemoveTrailingChar(canonical_search_token, '+')) { ++found_plusses; continue; } break; } switch (found_question_marks) { // all fallthroughs case 3: options->flag_description_substring_search = true; case 2: options->flag_location_substring_search = true; case 1: options->flag_name_substring_search = true; }; options->return_all_matching_flags = (found_plusses > 0); } // Returns true if a char was removed static bool RemoveTrailingChar(string *str, char c) { if (str->empty()) return false; if ((*str)[str->size() - 1] == c) { *str = str->substr(0, str->size() - 1); return true; } return false; } // 2) Find all matches (and helper methods) static void FindMatchingFlags( const vector &all_flags, const CompletionOptions &options, const string &match_token, set *all_matches, string *longest_common_prefix) { all_matches->clear(); bool first_match = true; for (vector::const_iterator it = all_flags.begin(); it != all_flags.end(); ++it) { if (DoesSingleFlagMatch(*it, options, match_token)) { all_matches->insert(&*it); if (first_match) { first_match = false; *longest_common_prefix = it->name; } else { if (longest_common_prefix->empty() || it->name.empty()) { longest_common_prefix->clear(); continue; } string::size_type pos = 0; while (pos < longest_common_prefix->size() && pos < it->name.size() && (*longest_common_prefix)[pos] == it->name[pos]) ++pos; longest_common_prefix->erase(pos); } } } } // Given the set of all flags, the parsed match options, and the // canonical search token, produce the set of all candidate matching // flags for subsequent analysis or filtering. static bool DoesSingleFlagMatch( const CommandLineFlagInfo &flag, const CompletionOptions &options, const string &match_token) { // Is there a prefix match? string::size_type pos = flag.name.find(match_token); if (pos == 0) return true; // Is there a substring match if we want it? if (options.flag_name_substring_search && pos != string::npos) return true; // Is there a location match if we want it? if (options.flag_location_substring_search && flag.filename.find(match_token) != string::npos) return true; // TODO(user): All searches should probably be case-insensitive // (especially this one...) if (options.flag_description_substring_search && flag.description.find(match_token) != string::npos) return true; return false; } // 3) Categorize matches (and helper method) // Given a set of matching flags, categorize them by // likely relevence to this specific binary static void CategorizeAllMatchingFlags( const set &all_matches, const string &search_token, const string &module, // empty if we couldn't find any const string &package_dir, // empty if we couldn't find any NotableFlags *notable_flags) { notable_flags->perfect_match_flag.clear(); notable_flags->module_flags.clear(); notable_flags->package_flags.clear(); notable_flags->most_common_flags.clear(); notable_flags->subpackage_flags.clear(); for (set::const_iterator it = all_matches.begin(); it != all_matches.end(); ++it) { DVLOG(2) << "Examining match '" << (*it)->name << "'"; DVLOG(7) << " filename: '" << (*it)->filename << "'"; string::size_type pos = string::npos; if (!package_dir.empty()) pos = (*it)->filename.find(package_dir); string::size_type slash = string::npos; if (pos != string::npos) // candidate for package or subpackage match slash = (*it)->filename.find( PATH_SEPARATOR, pos + package_dir.size() + 1); if ((*it)->name == search_token) { // Exact match on some flag's name notable_flags->perfect_match_flag.insert(*it); DVLOG(3) << "Result: perfect match"; } else if (!module.empty() && (*it)->filename == module) { // Exact match on module filename notable_flags->module_flags.insert(*it); DVLOG(3) << "Result: module match"; } else if (!package_dir.empty() && pos != string::npos && slash == string::npos) { // In the package, since there was no slash after the package portion notable_flags->package_flags.insert(*it); DVLOG(3) << "Result: package match"; } else if (false) { // In the list of the XXX most commonly supplied flags overall // TODO(user): Compile this list. DVLOG(3) << "Result: most-common match"; } else if (!package_dir.empty() && pos != string::npos && slash != string::npos) { // In a subdirectory of the package notable_flags->subpackage_flags.insert(*it); DVLOG(3) << "Result: subpackage match"; } DVLOG(3) << "Result: not special match"; } } static void PushNameWithSuffix(vector* suffixes, const char* suffix) { suffixes->push_back( StringPrintf("/%s%s", ProgramInvocationShortName(), suffix)); } static void TryFindModuleAndPackageDir( const vector &all_flags, string *module, string *package_dir) { module->clear(); package_dir->clear(); vector suffixes; // TODO(user): There's some inherant ambiguity here - multiple directories // could share the same trailing folder and file structure (and even worse, // same file names), causing us to be unsure as to which of the two is the // actual package for this binary. In this case, we'll arbitrarily choose. PushNameWithSuffix(&suffixes, "."); PushNameWithSuffix(&suffixes, "-main."); PushNameWithSuffix(&suffixes, "_main."); // These four are new but probably merited? PushNameWithSuffix(&suffixes, "-test."); PushNameWithSuffix(&suffixes, "_test."); PushNameWithSuffix(&suffixes, "-unittest."); PushNameWithSuffix(&suffixes, "_unittest."); for (vector::const_iterator it = all_flags.begin(); it != all_flags.end(); ++it) { for (vector::const_iterator suffix = suffixes.begin(); suffix != suffixes.end(); ++suffix) { // TODO(user): Make sure the match is near the end of the string if (it->filename.find(*suffix) != string::npos) { *module = it->filename; string::size_type sep = it->filename.rfind(PATH_SEPARATOR); *package_dir = it->filename.substr(0, (sep == string::npos) ? 0 : sep); return; } } } } // Can't specialize template type on a locally defined type. Silly C++... struct DisplayInfoGroup { const char* header; const char* footer; set *group; int SizeInLines() const { int size_in_lines = static_cast(group->size()) + 1; if (strlen(header) > 0) { size_in_lines++; } if (strlen(footer) > 0) { size_in_lines++; } return size_in_lines; } }; // 4) Finalize and trim output flag set static void FinalizeCompletionOutput( const set &matching_flags, CompletionOptions *options, NotableFlags *notable_flags, vector *completions) { // We want to output lines in groups. Each group needs to be indented // the same to keep its lines together. Unless otherwise required, // only 99 lines should be output to prevent bash from harassing the // user. // First, figure out which output groups we'll actually use. For each // nonempty group, there will be ~3 lines of header & footer, plus all // output lines themselves. int max_desired_lines = // "999999 flags should be enough for anyone. -dave" (options->return_all_matching_flags ? 999999 : 98); int lines_so_far = 0; vector output_groups; bool perfect_match_found = false; if (!notable_flags->perfect_match_flag.empty()) { perfect_match_found = true; DisplayInfoGroup group = { "", "==========", ¬able_flags->perfect_match_flag }; lines_so_far += group.SizeInLines(); output_groups.push_back(group); } if (lines_so_far < max_desired_lines && !notable_flags->module_flags.empty()) { DisplayInfoGroup group = { "-* Matching module flags *-", "===========================", ¬able_flags->module_flags }; lines_so_far += group.SizeInLines(); output_groups.push_back(group); } if (lines_so_far < max_desired_lines && !notable_flags->package_flags.empty()) { DisplayInfoGroup group = { "-* Matching package flags *-", "============================", ¬able_flags->package_flags }; lines_so_far += group.SizeInLines(); output_groups.push_back(group); } if (lines_so_far < max_desired_lines && !notable_flags->most_common_flags.empty()) { DisplayInfoGroup group = { "-* Commonly used flags *-", "=========================", ¬able_flags->most_common_flags }; lines_so_far += group.SizeInLines(); output_groups.push_back(group); } if (lines_so_far < max_desired_lines && !notable_flags->subpackage_flags.empty()) { DisplayInfoGroup group = { "-* Matching sub-package flags *-", "================================", ¬able_flags->subpackage_flags }; lines_so_far += group.SizeInLines(); output_groups.push_back(group); } set obscure_flags; // flags not notable if (lines_so_far < max_desired_lines) { RetrieveUnusedFlags(matching_flags, *notable_flags, &obscure_flags); if (!obscure_flags.empty()) { DisplayInfoGroup group = { "-* Other flags *-", "", &obscure_flags }; lines_so_far += group.SizeInLines(); output_groups.push_back(group); } } // Second, go through each of the chosen output groups and output // as many of those flags as we can, while remaining below our limit int remaining_lines = max_desired_lines; size_t completions_output = 0; int indent = static_cast(output_groups.size()) - 1; for (vector::const_iterator it = output_groups.begin(); it != output_groups.end(); ++it, --indent) { OutputSingleGroupWithLimit( *it->group, // group string(indent, ' '), // line indentation string(it->header), // header string(it->footer), // footer perfect_match_found, // long format &remaining_lines, // line limit - reduces this by number printed &completions_output, // completions (not lines) added completions); // produced completions perfect_match_found = false; } if (completions_output != matching_flags.size()) { options->force_no_update = false; completions->push_back("~ (Remaining flags hidden) ~"); } else { options->force_no_update = true; } } static void RetrieveUnusedFlags( const set &matching_flags, const NotableFlags ¬able_flags, set *unused_flags) { // Remove from 'matching_flags' set all members of the sets of // flags we've already printed (specifically, those in notable_flags) for (set::const_iterator it = matching_flags.begin(); it != matching_flags.end(); ++it) { if (notable_flags.perfect_match_flag.count(*it) || notable_flags.module_flags.count(*it) || notable_flags.package_flags.count(*it) || notable_flags.most_common_flags.count(*it) || notable_flags.subpackage_flags.count(*it)) continue; unused_flags->insert(*it); } } // 5) Output matches (and helper methods) static void OutputSingleGroupWithLimit( const set &group, const string &line_indentation, const string &header, const string &footer, bool long_output_format, int *remaining_line_limit, size_t *completion_elements_output, vector *completions) { if (group.empty()) return; if (!header.empty()) { if (*remaining_line_limit < 2) return; *remaining_line_limit -= 2; completions->push_back(line_indentation + header); completions->push_back(line_indentation + string(header.size(), '-')); } for (set::const_iterator it = group.begin(); it != group.end() && *remaining_line_limit > 0; ++it) { --*remaining_line_limit; ++*completion_elements_output; completions->push_back( (long_output_format ? GetLongFlagLine(line_indentation, **it) : GetShortFlagLine(line_indentation, **it))); } if (!footer.empty()) { if (*remaining_line_limit < 1) return; --*remaining_line_limit; completions->push_back(line_indentation + footer); } } static string GetShortFlagLine( const string &line_indentation, const CommandLineFlagInfo &info) { string prefix; bool is_string = (info.type == "string"); SStringPrintf(&prefix, "%s--%s [%s%s%s] ", line_indentation.c_str(), info.name.c_str(), (is_string ? "'" : ""), info.default_value.c_str(), (is_string ? "'" : "")); int remainder = FLAGS_tab_completion_columns - static_cast(prefix.size()); string suffix; if (remainder > 0) suffix = (static_cast(info.description.size()) > remainder ? (info.description.substr(0, remainder - 3) + "...").c_str() : info.description.c_str()); return prefix + suffix; } static string GetLongFlagLine( const string &line_indentation, const CommandLineFlagInfo &info) { string output = DescribeOneFlag(info); // Replace '-' with '--', and remove trailing newline before appending // the module definition location. string old_flagname = "-" + info.name; output.replace( output.find(old_flagname), old_flagname.size(), "-" + old_flagname); // Stick a newline and indentation in front of the type and default // portions of DescribeOneFlag()s description static const char kNewlineWithIndent[] = "\n "; output.replace(output.find(" type:"), 1, string(kNewlineWithIndent)); output.replace(output.find(" default:"), 1, string(kNewlineWithIndent)); output = StringPrintf("%s Details for '--%s':\n" "%s defined: %s", line_indentation.c_str(), info.name.c_str(), output.c_str(), info.filename.c_str()); // Eliminate any doubled newlines that crept in. Specifically, if // DescribeOneFlag() decided to break the line just before "type" // or "default", we don't want to introduce an extra blank line static const string line_of_spaces(FLAGS_tab_completion_columns, ' '); static const char kDoubledNewlines[] = "\n \n"; for (string::size_type newlines = output.find(kDoubledNewlines); newlines != string::npos; newlines = output.find(kDoubledNewlines)) // Replace each 'doubled newline' with a single newline output.replace(newlines, sizeof(kDoubledNewlines) - 1, string("\n")); for (string::size_type newline = output.find('\n'); newline != string::npos; newline = output.find('\n')) { int newline_pos = static_cast(newline) % FLAGS_tab_completion_columns; int missing_spaces = FLAGS_tab_completion_columns - newline_pos; output.replace(newline, 1, line_of_spaces, 1, missing_spaces); } return output; } } // anonymous void HandleCommandLineCompletions(void) { if (FLAGS_tab_completion_word.empty()) return; PrintFlagCompletionInfo(); gflags_exitfunc(0); } } // namespace GFLAGS_NAMESPACE gflags-2.2.2/src/gflags_completions.h.in000066400000000000000000000132151337211647400202160ustar00rootroot00000000000000// Copyright (c) 2008, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // --- // // Implement helpful bash-style command line flag completions // // ** Functional API: // HandleCommandLineCompletions() should be called early during // program startup, but after command line flag code has been // initialized, such as the beginning of HandleCommandLineHelpFlags(). // It checks the value of the flag --tab_completion_word. If this // flag is empty, nothing happens here. If it contains a string, // however, then HandleCommandLineCompletions() will hijack the // process, attempting to identify the intention behind this // completion. Regardless of the outcome of this deduction, the // process will be terminated, similar to --helpshort flag // handling. // // ** Overview of Bash completions: // Bash can be told to programatically determine completions for the // current 'cursor word'. It does this by (in this case) invoking a // command with some additional arguments identifying the command // being executed, the word being completed, and the previous word // (if any). Bash then expects a sequence of output lines to be // printed to stdout. If these lines all contain a common prefix // longer than the cursor word, bash will replace the cursor word // with that common prefix, and display nothing. If there isn't such // a common prefix, bash will display the lines in pages using 'more'. // // ** Strategy taken for command line completions: // If we can deduce either the exact flag intended, or a common flag // prefix, we'll output exactly that. Otherwise, if information // must be displayed to the user, we'll take the opportunity to add // some helpful information beyond just the flag name (specifically, // we'll include the default flag value and as much of the flag's // description as can fit on a single terminal line width, as specified // by the flag --tab_completion_columns). Furthermore, we'll try to // make bash order the output such that the most useful or relevent // flags are the most likely to be shown at the top. // // ** Additional features: // To assist in finding that one really useful flag, substring matching // was implemented. Before pressing a to get completion for the // current word, you can append one or more '?' to the flag to do // substring matching. Here's the semantics: // --foo Show me all flags with names prefixed by 'foo' // --foo? Show me all flags with 'foo' somewhere in the name // --foo?? Same as prior case, but also search in module // definition path for 'foo' // --foo??? Same as prior case, but also search in flag // descriptions for 'foo' // Finally, we'll trim the output to a relatively small number of // flags to keep bash quiet about the verbosity of output. If one // really wanted to see all possible matches, appending a '+' to the // search word will force the exhaustive list of matches to be printed. // // ** How to have bash accept completions from a binary: // Bash requires that it be informed about each command that programmatic // completion should be enabled for. Example addition to a .bashrc // file would be (your path to gflags_completions.sh file may differ): /* $ complete -o bashdefault -o default -o nospace -C \ '/home/build/eng/bash/bash_completions.sh --tab_completion_columns $COLUMNS' \ time env binary_name another_binary [...] */ // This would allow the following to work: // $ /path/to/binary_name --vmodule // Or: // $ ./bin/path/another_binary --gfs_u // (etc) // // Sadly, it appears that bash gives no easy way to force this behavior for // all commands. That's where the "time" in the above example comes in. // If you haven't specifically added a command to the list of completion // supported commands, you can still get completions by prefixing the // entire command with "env". // $ env /some/brand/new/binary --vmod // Assuming that "binary" is a newly compiled binary, this should still // produce the expected completion output. #ifndef GFLAGS_COMPLETIONS_H_ #define GFLAGS_COMPLETIONS_H_ namespace @GFLAGS_NAMESPACE@ { extern void HandleCommandLineCompletions(void); } #endif // GFLAGS_COMPLETIONS_H_ gflags-2.2.2/src/gflags_completions.sh000077500000000000000000000120061337211647400177740ustar00rootroot00000000000000#!/bin/bash # Copyright (c) 2008, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # --- # Author: Dave Nicponski # # This script is invoked by bash in response to a matching compspec. When # this happens, bash calls this script using the command shown in the -C # block of the complete entry, but also appends 3 arguments. They are: # - The command being used for completion # - The word being completed # - The word preceding the completion word. # # Here's an example of how you might use this script: # $ complete -o bashdefault -o default -o nospace -C \ # '/usr/local/bin/gflags_completions.sh --tab_completion_columns $COLUMNS' \ # time env binary_name another_binary [...] # completion_word_index gets the index of the (N-1)th argument for # this command line. completion_word gets the actual argument from # this command line at the (N-1)th position completion_word_index="$(($# - 1))" completion_word="${!completion_word_index}" # TODO(user): Replace this once gflags_completions.cc has # a bool parameter indicating unambiguously to hijack the process for # completion purposes. if [ -z "$completion_word" ]; then # Until an empty value for the completion word stops being misunderstood # by binaries, don't actually execute the binary or the process # won't be hijacked! exit 0 fi # binary_index gets the index of the command being completed (which bash # places in the (N-2)nd position. binary gets the actual command from # this command line at that (N-2)nd position binary_index="$(($# - 2))" binary="${!binary_index}" # For completions to be universal, we may have setup the compspec to # trigger on 'harmless pass-through' commands, like 'time' or 'env'. # If the command being completed is one of those two, we'll need to # identify the actual command being executed. To do this, we need # the actual command line that the was pressed on. Bash helpfully # places this in the $COMP_LINE variable. if [ "$binary" == "time" ] || [ "$binary" == "env" ]; then # we'll assume that the first 'argument' is actually the # binary # TODO(user): This is not perfect - the 'env' command, for instance, # is allowed to have options between the 'env' and 'the command to # be executed'. For example, consider: # $ env FOO="bar" bin/do_something --help # In this case, we'll mistake the FOO="bar" portion as the binary. # Perhaps we should continuing consuming leading words until we # either run out of words, or find a word that is a valid file # marked as executable. I can't think of any reason this wouldn't # work. # Break up the 'original command line' (not this script's command line, # rather the one the was pressed on) and find the second word. parts=( ${COMP_LINE} ) binary=${parts[1]} fi # Build the command line to use for completion. Basically it involves # passing through all the arguments given to this script (except the 3 # that bash added), and appending a '--tab_completion_word "WORD"' to # the arguments. params="" for ((i=1; i<=$(($# - 3)); ++i)); do params="$params \"${!i}\""; done params="$params --tab_completion_word \"$completion_word\"" # TODO(user): Perhaps stash the output in a temporary file somewhere # in /tmp, and only cat it to stdout if the command returned a success # code, to prevent false positives # If we think we have a reasonable command to execute, then execute it # and hope for the best. candidate=$(type -p "$binary") if [ ! -z "$candidate" ]; then eval "$candidate 2>/dev/null $params" elif [ -f "$binary" ] && [ -x "$binary" ]; then eval "$binary 2>/dev/null $params" fi gflags-2.2.2/src/gflags_declare.h.in000066400000000000000000000126221337211647400172620ustar00rootroot00000000000000// Copyright (c) 1999, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // --- // // Revamped and reorganized by Craig Silverstein // // This is the file that should be included by any file which declares // command line flag. #ifndef GFLAGS_DECLARE_H_ #define GFLAGS_DECLARE_H_ // --------------------------------------------------------------------------- // Namespace of gflags library symbols. #define GFLAGS_NAMESPACE @GFLAGS_NAMESPACE@ // --------------------------------------------------------------------------- // Windows DLL import/export. // Whether gflags library is a DLL. // // Set to 1 by default when the shared gflags library was built on Windows. // Must be overwritten when this header file is used with the optionally also // built static library instead; set by CMake's INTERFACE_COMPILE_DEFINITIONS. #ifndef GFLAGS_IS_A_DLL # define GFLAGS_IS_A_DLL @GFLAGS_IS_A_DLL@ #endif // We always want to import the symbols of the gflags library. #ifndef GFLAGS_DLL_DECL # if GFLAGS_IS_A_DLL && defined(_MSC_VER) # define GFLAGS_DLL_DECL __declspec(dllimport) # elif defined(__GNUC__) && __GNUC__ >= 4 # define GFLAGS_DLL_DECL __attribute__((visibility("default"))) # else # define GFLAGS_DLL_DECL # endif #endif // We always want to import variables declared in user code. #ifndef GFLAGS_DLL_DECLARE_FLAG # if GFLAGS_IS_A_DLL && defined(_MSC_VER) # define GFLAGS_DLL_DECLARE_FLAG __declspec(dllimport) # elif defined(__GNUC__) && __GNUC__ >= 4 # define GFLAGS_DLL_DECLARE_FLAG __attribute__((visibility("default"))) # else # define GFLAGS_DLL_DECLARE_FLAG # endif #endif // --------------------------------------------------------------------------- // Flag types #include #if @HAVE_STDINT_H@ # include // the normal place uint32_t is defined #elif @HAVE_SYS_TYPES_H@ # include // the normal place u_int32_t is defined #elif @HAVE_INTTYPES_H@ # include // a third place for uint32_t or u_int32_t #endif namespace GFLAGS_NAMESPACE { #if @GFLAGS_INTTYPES_FORMAT_C99@ // C99 typedef int32_t int32; typedef uint32_t uint32; typedef int64_t int64; typedef uint64_t uint64; #elif @GFLAGS_INTTYPES_FORMAT_BSD@ // BSD typedef int32_t int32; typedef u_int32_t uint32; typedef int64_t int64; typedef u_int64_t uint64; #elif @GFLAGS_INTTYPES_FORMAT_VC7@ // Windows typedef __int32 int32; typedef unsigned __int32 uint32; typedef __int64 int64; typedef unsigned __int64 uint64; #else # error Do not know how to define a 32-bit integer quantity on your system #endif } // namespace GFLAGS_NAMESPACE namespace fLS { // The meaning of "string" might be different between now and when the // macros below get invoked (e.g., if someone is experimenting with // other string implementations that get defined after this file is // included). Save the current meaning now and use it in the macros. typedef std::string clstring; } // namespace fLS #define DECLARE_VARIABLE(type, shorttype, name) \ /* We always want to import declared variables, dll or no */ \ namespace fL##shorttype { extern GFLAGS_DLL_DECLARE_FLAG type FLAGS_##name; } \ using fL##shorttype::FLAGS_##name #define DECLARE_bool(name) \ DECLARE_VARIABLE(bool, B, name) #define DECLARE_int32(name) \ DECLARE_VARIABLE(::GFLAGS_NAMESPACE::int32, I, name) #define DECLARE_uint32(name) \ DECLARE_VARIABLE(::GFLAGS_NAMESPACE::uint32, U, name) #define DECLARE_int64(name) \ DECLARE_VARIABLE(::GFLAGS_NAMESPACE::int64, I64, name) #define DECLARE_uint64(name) \ DECLARE_VARIABLE(::GFLAGS_NAMESPACE::uint64, U64, name) #define DECLARE_double(name) \ DECLARE_VARIABLE(double, D, name) #define DECLARE_string(name) \ /* We always want to import declared variables, dll or no */ \ namespace fLS { \ extern GFLAGS_DLL_DECLARE_FLAG ::fLS::clstring& FLAGS_##name; \ } \ using fLS::FLAGS_##name #endif // GFLAGS_DECLARE_H_ gflags-2.2.2/src/gflags_ns.h.in000066400000000000000000000077331337211647400163120ustar00rootroot00000000000000// Copyright (c) 2014, Andreas Schuh // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ----------------------------------------------------------------------------- // Imports the gflags library symbols into an alternative/deprecated namespace. #ifndef GFLAGS_GFLAGS_H_ # error The internal header gflags_@ns@.h may only be included by gflags.h #endif #ifndef GFLAGS_NS_@NS@_H_ #define GFLAGS_NS_@NS@_H_ namespace @ns@ { using GFLAGS_NAMESPACE::int32; using GFLAGS_NAMESPACE::uint32; using GFLAGS_NAMESPACE::int64; using GFLAGS_NAMESPACE::uint64; using GFLAGS_NAMESPACE::RegisterFlagValidator; using GFLAGS_NAMESPACE::CommandLineFlagInfo; using GFLAGS_NAMESPACE::GetAllFlags; using GFLAGS_NAMESPACE::ShowUsageWithFlags; using GFLAGS_NAMESPACE::ShowUsageWithFlagsRestrict; using GFLAGS_NAMESPACE::DescribeOneFlag; using GFLAGS_NAMESPACE::SetArgv; using GFLAGS_NAMESPACE::GetArgvs; using GFLAGS_NAMESPACE::GetArgv; using GFLAGS_NAMESPACE::GetArgv0; using GFLAGS_NAMESPACE::GetArgvSum; using GFLAGS_NAMESPACE::ProgramInvocationName; using GFLAGS_NAMESPACE::ProgramInvocationShortName; using GFLAGS_NAMESPACE::ProgramUsage; using GFLAGS_NAMESPACE::VersionString; using GFLAGS_NAMESPACE::GetCommandLineOption; using GFLAGS_NAMESPACE::GetCommandLineFlagInfo; using GFLAGS_NAMESPACE::GetCommandLineFlagInfoOrDie; using GFLAGS_NAMESPACE::FlagSettingMode; using GFLAGS_NAMESPACE::SET_FLAGS_VALUE; using GFLAGS_NAMESPACE::SET_FLAG_IF_DEFAULT; using GFLAGS_NAMESPACE::SET_FLAGS_DEFAULT; using GFLAGS_NAMESPACE::SetCommandLineOption; using GFLAGS_NAMESPACE::SetCommandLineOptionWithMode; using GFLAGS_NAMESPACE::FlagSaver; using GFLAGS_NAMESPACE::CommandlineFlagsIntoString; using GFLAGS_NAMESPACE::ReadFlagsFromString; using GFLAGS_NAMESPACE::AppendFlagsIntoFile; using GFLAGS_NAMESPACE::ReadFromFlagsFile; using GFLAGS_NAMESPACE::BoolFromEnv; using GFLAGS_NAMESPACE::Int32FromEnv; using GFLAGS_NAMESPACE::Uint32FromEnv; using GFLAGS_NAMESPACE::Int64FromEnv; using GFLAGS_NAMESPACE::Uint64FromEnv; using GFLAGS_NAMESPACE::DoubleFromEnv; using GFLAGS_NAMESPACE::StringFromEnv; using GFLAGS_NAMESPACE::SetUsageMessage; using GFLAGS_NAMESPACE::SetVersionString; using GFLAGS_NAMESPACE::ParseCommandLineNonHelpFlags; using GFLAGS_NAMESPACE::HandleCommandLineHelpFlags; using GFLAGS_NAMESPACE::AllowCommandLineReparsing; using GFLAGS_NAMESPACE::ReparseCommandLineNonHelpFlags; using GFLAGS_NAMESPACE::ShutDownCommandLineFlags; using GFLAGS_NAMESPACE::FlagRegisterer; #ifndef SWIG using GFLAGS_NAMESPACE::ParseCommandLineFlags; #endif } // namespace @ns@ #endif // GFLAGS_NS_@NS@_H_ gflags-2.2.2/src/gflags_reporting.cc000066400000000000000000000416311337211647400174270ustar00rootroot00000000000000// Copyright (c) 1999, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // --- // // Revamped and reorganized by Craig Silverstein // // This file contains code for handling the 'reporting' flags. These // are flags that, when present, cause the program to report some // information and then exit. --help and --version are the canonical // reporting flags, but we also have flags like --helpxml, etc. // // There's only one function that's meant to be called externally: // HandleCommandLineHelpFlags(). (Well, actually, ShowUsageWithFlags(), // ShowUsageWithFlagsRestrict(), and DescribeOneFlag() can be called // externally too, but there's little need for it.) These are all // declared in the main gflags.h header file. // // HandleCommandLineHelpFlags() will check what 'reporting' flags have // been defined, if any -- the "help" part of the function name is a // bit misleading -- and do the relevant reporting. It should be // called after all flag-values have been assigned, that is, after // parsing the command-line. #include #include #include #include #include #include #include "config.h" #include "gflags/gflags.h" #include "gflags/gflags_completions.h" #include "util.h" // The 'reporting' flags. They all call gflags_exitfunc(). DEFINE_bool (help, false, "show help on all flags [tip: all flags can have two dashes]"); DEFINE_bool (helpfull, false, "show help on all flags -- same as -help"); DEFINE_bool (helpshort, false, "show help on only the main module for this program"); DEFINE_string(helpon, "", "show help on the modules named by this flag value"); DEFINE_string(helpmatch, "", "show help on modules whose name contains the specified substr"); DEFINE_bool (helppackage, false, "show help on all modules in the main package"); DEFINE_bool (helpxml, false, "produce an xml version of help"); DEFINE_bool (version, false, "show version and build info and exit"); namespace GFLAGS_NAMESPACE { using std::string; using std::vector; // -------------------------------------------------------------------- // DescribeOneFlag() // DescribeOneFlagInXML() // Routines that pretty-print info about a flag. These use // a CommandLineFlagInfo, which is the way the gflags // API exposes static info about a flag. // -------------------------------------------------------------------- static const int kLineLength = 80; static void AddString(const string& s, string* final_string, int* chars_in_line) { const int slen = static_cast(s.length()); if (*chars_in_line + 1 + slen >= kLineLength) { // < 80 chars/line *final_string += "\n "; *chars_in_line = 6; } else { *final_string += " "; *chars_in_line += 1; } *final_string += s; *chars_in_line += slen; } static string PrintStringFlagsWithQuotes(const CommandLineFlagInfo& flag, const string& text, bool current) { const char* c_string = (current ? flag.current_value.c_str() : flag.default_value.c_str()); if (strcmp(flag.type.c_str(), "string") == 0) { // add quotes for strings return StringPrintf("%s: \"%s\"", text.c_str(), c_string); } else { return StringPrintf("%s: %s", text.c_str(), c_string); } } // Create a descriptive string for a flag. // Goes to some trouble to make pretty line breaks. string DescribeOneFlag(const CommandLineFlagInfo& flag) { string main_part; SStringPrintf(&main_part, " -%s (%s)", flag.name.c_str(), flag.description.c_str()); const char* c_string = main_part.c_str(); int chars_left = static_cast(main_part.length()); string final_string = ""; int chars_in_line = 0; // how many chars in current line so far? while (1) { assert(static_cast(chars_left) == strlen(c_string)); // Unless there's a \0 in there? const char* newline = strchr(c_string, '\n'); if (newline == NULL && chars_in_line+chars_left < kLineLength) { // The whole remainder of the string fits on this line final_string += c_string; chars_in_line += chars_left; break; } if (newline != NULL && newline - c_string < kLineLength - chars_in_line) { int n = static_cast(newline - c_string); final_string.append(c_string, n); chars_left -= n + 1; c_string += n + 1; } else { // Find the last whitespace on this 80-char line int whitespace = kLineLength-chars_in_line-1; // < 80 chars/line while ( whitespace > 0 && !isspace(c_string[whitespace]) ) { --whitespace; } if (whitespace <= 0) { // Couldn't find any whitespace to make a line break. Just dump the // rest out! final_string += c_string; chars_in_line = kLineLength; // next part gets its own line for sure! break; } final_string += string(c_string, whitespace); chars_in_line += whitespace; while (isspace(c_string[whitespace])) ++whitespace; c_string += whitespace; chars_left -= whitespace; } if (*c_string == '\0') break; StringAppendF(&final_string, "\n "); chars_in_line = 6; } // Append data type AddString(string("type: ") + flag.type, &final_string, &chars_in_line); // The listed default value will be the actual default from the flag // definition in the originating source file, unless the value has // subsequently been modified using SetCommandLineOptionWithMode() with mode // SET_FLAGS_DEFAULT, or by setting FLAGS_foo = bar before ParseCommandLineFlags(). AddString(PrintStringFlagsWithQuotes(flag, "default", false), &final_string, &chars_in_line); if (!flag.is_default) { AddString(PrintStringFlagsWithQuotes(flag, "currently", true), &final_string, &chars_in_line); } StringAppendF(&final_string, "\n"); return final_string; } // Simple routine to xml-escape a string: escape & and < only. static string XMLText(const string& txt) { string ans = txt; for (string::size_type pos = 0; (pos = ans.find("&", pos)) != string::npos; ) ans.replace(pos++, 1, "&"); for (string::size_type pos = 0; (pos = ans.find("<", pos)) != string::npos; ) ans.replace(pos++, 1, "<"); return ans; } static void AddXMLTag(string* r, const char* tag, const string& txt) { StringAppendF(r, "<%s>%s", tag, XMLText(txt).c_str(), tag); } static string DescribeOneFlagInXML(const CommandLineFlagInfo& flag) { // The file and flagname could have been attributes, but default // and meaning need to avoid attribute normalization. This way it // can be parsed by simple programs, in addition to xml parsers. string r(""); AddXMLTag(&r, "file", flag.filename); AddXMLTag(&r, "name", flag.name); AddXMLTag(&r, "meaning", flag.description); AddXMLTag(&r, "default", flag.default_value); AddXMLTag(&r, "current", flag.current_value); AddXMLTag(&r, "type", flag.type); r += ""; return r; } // -------------------------------------------------------------------- // ShowUsageWithFlags() // ShowUsageWithFlagsRestrict() // ShowXMLOfFlags() // These routines variously expose the registry's list of flag // values. ShowUsage*() prints the flag-value information // to stdout in a user-readable format (that's what --help uses). // The Restrict() version limits what flags are shown. // ShowXMLOfFlags() prints the flag-value information to stdout // in a machine-readable format. In all cases, the flags are // sorted: first by filename they are defined in, then by flagname. // -------------------------------------------------------------------- static const char* Basename(const char* filename) { const char* sep = strrchr(filename, PATH_SEPARATOR); return sep ? sep + 1 : filename; } static string Dirname(const string& filename) { string::size_type sep = filename.rfind(PATH_SEPARATOR); return filename.substr(0, (sep == string::npos) ? 0 : sep); } // Test whether a filename contains at least one of the substrings. static bool FileMatchesSubstring(const string& filename, const vector& substrings) { for (vector::const_iterator target = substrings.begin(); target != substrings.end(); ++target) { if (strstr(filename.c_str(), target->c_str()) != NULL) return true; // If the substring starts with a '/', that means that we want // the string to be at the beginning of a directory component. // That should match the first directory component as well, so // we allow '/foo' to match a filename of 'foo'. if (!target->empty() && (*target)[0] == PATH_SEPARATOR && strncmp(filename.c_str(), target->c_str() + 1, strlen(target->c_str() + 1)) == 0) return true; } return false; } // Show help for every filename which matches any of the target substrings. // If substrings is empty, shows help for every file. If a flag's help message // has been stripped (e.g. by adding '#define STRIP_FLAG_HELP 1' // before including gflags/gflags.h), then this flag will not be displayed // by '--help' and its variants. static void ShowUsageWithFlagsMatching(const char *argv0, const vector &substrings) { fprintf(stdout, "%s: %s\n", Basename(argv0), ProgramUsage()); vector flags; GetAllFlags(&flags); // flags are sorted by filename, then flagname string last_filename; // so we know when we're at a new file bool first_directory = true; // controls blank lines between dirs bool found_match = false; // stays false iff no dir matches restrict for (vector::const_iterator flag = flags.begin(); flag != flags.end(); ++flag) { if (substrings.empty() || FileMatchesSubstring(flag->filename, substrings)) { // If the flag has been stripped, pretend that it doesn't exist. if (flag->description == kStrippedFlagHelp) continue; found_match = true; // this flag passed the match! if (flag->filename != last_filename) { // new file if (Dirname(flag->filename) != Dirname(last_filename)) { // new dir! if (!first_directory) fprintf(stdout, "\n\n"); // put blank lines between directories first_directory = false; } fprintf(stdout, "\n Flags from %s:\n", flag->filename.c_str()); last_filename = flag->filename; } // Now print this flag fprintf(stdout, "%s", DescribeOneFlag(*flag).c_str()); } } if (!found_match && !substrings.empty()) { fprintf(stdout, "\n No modules matched: use -help\n"); } } void ShowUsageWithFlagsRestrict(const char *argv0, const char *restrict_) { vector substrings; if (restrict_ != NULL && *restrict_ != '\0') { substrings.push_back(restrict_); } ShowUsageWithFlagsMatching(argv0, substrings); } void ShowUsageWithFlags(const char *argv0) { ShowUsageWithFlagsRestrict(argv0, ""); } // Convert the help, program, and usage to xml. static void ShowXMLOfFlags(const char *prog_name) { vector flags; GetAllFlags(&flags); // flags are sorted: by filename, then flagname // XML. There is no corresponding schema yet fprintf(stdout, "\n"); // The document fprintf(stdout, "\n"); // the program name and usage fprintf(stdout, "%s\n", XMLText(Basename(prog_name)).c_str()); fprintf(stdout, "%s\n", XMLText(ProgramUsage()).c_str()); // All the flags for (vector::const_iterator flag = flags.begin(); flag != flags.end(); ++flag) { if (flag->description != kStrippedFlagHelp) fprintf(stdout, "%s\n", DescribeOneFlagInXML(*flag).c_str()); } // The end of the document fprintf(stdout, "\n"); } // -------------------------------------------------------------------- // ShowVersion() // Called upon --version. Prints build-related info. // -------------------------------------------------------------------- static void ShowVersion() { const char* version_string = VersionString(); if (version_string && *version_string) { fprintf(stdout, "%s version %s\n", ProgramInvocationShortName(), version_string); } else { fprintf(stdout, "%s\n", ProgramInvocationShortName()); } # if !defined(NDEBUG) fprintf(stdout, "Debug build (NDEBUG not #defined)\n"); # endif } static void AppendPrognameStrings(vector* substrings, const char* progname) { string r(""); r += PATH_SEPARATOR; r += progname; substrings->push_back(r + "."); substrings->push_back(r + "-main."); substrings->push_back(r + "_main."); } // -------------------------------------------------------------------- // HandleCommandLineHelpFlags() // Checks all the 'reporting' commandline flags to see if any // have been set. If so, handles them appropriately. Note // that all of them, by definition, cause the program to exit // if they trigger. // -------------------------------------------------------------------- void HandleCommandLineHelpFlags() { const char* progname = ProgramInvocationShortName(); HandleCommandLineCompletions(); vector substrings; AppendPrognameStrings(&substrings, progname); if (FLAGS_helpshort) { // show only flags related to this binary: // E.g. for fileutil.cc, want flags containing ... "/fileutil." cc ShowUsageWithFlagsMatching(progname, substrings); gflags_exitfunc(1); } else if (FLAGS_help || FLAGS_helpfull) { // show all options ShowUsageWithFlagsRestrict(progname, ""); // empty restrict gflags_exitfunc(1); } else if (!FLAGS_helpon.empty()) { string restrict_ = PATH_SEPARATOR + FLAGS_helpon + "."; ShowUsageWithFlagsRestrict(progname, restrict_.c_str()); gflags_exitfunc(1); } else if (!FLAGS_helpmatch.empty()) { ShowUsageWithFlagsRestrict(progname, FLAGS_helpmatch.c_str()); gflags_exitfunc(1); } else if (FLAGS_helppackage) { // Shows help for all files in the same directory as main(). We // don't want to resort to looking at dirname(progname), because // the user can pick progname, and it may not relate to the file // where main() resides. So instead, we search the flags for a // filename like "/progname.cc", and take the dirname of that. vector flags; GetAllFlags(&flags); string last_package; for (vector::const_iterator flag = flags.begin(); flag != flags.end(); ++flag) { if (!FileMatchesSubstring(flag->filename, substrings)) continue; const string package = Dirname(flag->filename) + PATH_SEPARATOR; if (package != last_package) { ShowUsageWithFlagsRestrict(progname, package.c_str()); VLOG(7) << "Found package: " << package; if (!last_package.empty()) { // means this isn't our first pkg LOG(WARNING) << "Multiple packages contain a file=" << progname; } last_package = package; } } if (last_package.empty()) { // never found a package to print LOG(WARNING) << "Unable to find a package for file=" << progname; } gflags_exitfunc(1); } else if (FLAGS_helpxml) { ShowXMLOfFlags(progname); gflags_exitfunc(1); } else if (FLAGS_version) { ShowVersion(); // Unlike help, we may be asking for version in a script, so return 0 gflags_exitfunc(0); } } } // namespace GFLAGS_NAMESPACE gflags-2.2.2/src/mutex.h000066400000000000000000000342061337211647400150770ustar00rootroot00000000000000// Copyright (c) 2007, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // --- // // A simple mutex wrapper, supporting locks and read-write locks. // You should assume the locks are *not* re-entrant. // // This class is meant to be internal-only and should be wrapped by an // internal namespace. Before you use this module, please give the // name of your internal namespace for this module. Or, if you want // to expose it, you'll want to move it to the Google namespace. We // cannot put this class in global namespace because there can be some // problems when we have multiple versions of Mutex in each shared object. // // NOTE: by default, we have #ifdef'ed out the TryLock() method. // This is for two reasons: // 1) TryLock() under Windows is a bit annoying (it requires a // #define to be defined very early). // 2) TryLock() is broken for NO_THREADS mode, at least in NDEBUG // mode. // If you need TryLock(), and either these two caveats are not a // problem for you, or you're willing to work around them, then // feel free to #define GMUTEX_TRYLOCK, or to remove the #ifdefs // in the code below. // // CYGWIN NOTE: Cygwin support for rwlock seems to be buggy: // http://www.cygwin.com/ml/cygwin/2008-12/msg00017.html // Because of that, we might as well use windows locks for // cygwin. They seem to be more reliable than the cygwin pthreads layer. // // TRICKY IMPLEMENTATION NOTE: // This class is designed to be safe to use during // dynamic-initialization -- that is, by global constructors that are // run before main() starts. The issue in this case is that // dynamic-initialization happens in an unpredictable order, and it // could be that someone else's dynamic initializer could call a // function that tries to acquire this mutex -- but that all happens // before this mutex's constructor has run. (This can happen even if // the mutex and the function that uses the mutex are in the same .cc // file.) Basically, because Mutex does non-trivial work in its // constructor, it's not, in the naive implementation, safe to use // before dynamic initialization has run on it. // // The solution used here is to pair the actual mutex primitive with a // bool that is set to true when the mutex is dynamically initialized. // (Before that it's false.) Then we modify all mutex routines to // look at the bool, and not try to lock/unlock until the bool makes // it to true (which happens after the Mutex constructor has run.) // // This works because before main() starts -- particularly, during // dynamic initialization -- there are no threads, so a) it's ok that // the mutex operations are a no-op, since we don't need locking then // anyway; and b) we can be quite confident our bool won't change // state between a call to Lock() and a call to Unlock() (that would // require a global constructor in one translation unit to call Lock() // and another global constructor in another translation unit to call // Unlock() later, which is pretty perverse). // // That said, it's tricky, and can conceivably fail; it's safest to // avoid trying to acquire a mutex in a global constructor, if you // can. One way it can fail is that a really smart compiler might // initialize the bool to true at static-initialization time (too // early) rather than at dynamic-initialization time. To discourage // that, we set is_safe_ to true in code (not the constructor // colon-initializer) and set it to true via a function that always // evaluates to true, but that the compiler can't know always // evaluates to true. This should be good enough. // // A related issue is code that could try to access the mutex // after it's been destroyed in the global destructors (because // the Mutex global destructor runs before some other global // destructor, that tries to acquire the mutex). The way we // deal with this is by taking a constructor arg that global // mutexes should pass in, that causes the destructor to do no // work. We still depend on the compiler not doing anything // weird to a Mutex's memory after it is destroyed, but for a // static global variable, that's pretty safe. #ifndef GFLAGS_MUTEX_H_ #define GFLAGS_MUTEX_H_ #include "gflags/gflags_declare.h" // to figure out pthreads support #if defined(NO_THREADS) typedef int MutexType; // to keep a lock-count #elif defined(OS_WINDOWS) # ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN // We only need minimal includes # endif # ifndef NOMINMAX # define NOMINMAX // Don't want windows to override min()/max() # endif # ifdef GMUTEX_TRYLOCK // We need Windows NT or later for TryEnterCriticalSection(). If you // don't need that functionality, you can remove these _WIN32_WINNT // lines, and change TryLock() to assert(0) or something. # ifndef _WIN32_WINNT # define _WIN32_WINNT 0x0400 # endif # endif # include typedef CRITICAL_SECTION MutexType; #elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK) // Needed for pthread_rwlock_*. If it causes problems, you could take it // out, but then you'd have to unset HAVE_RWLOCK (at least on linux -- it // *does* cause problems for FreeBSD, or MacOSX, but isn't needed // for locking there.) # ifdef __linux__ # if _XOPEN_SOURCE < 500 // including not being defined at all # undef _XOPEN_SOURCE # define _XOPEN_SOURCE 500 // may be needed to get the rwlock calls # endif # endif # include typedef pthread_rwlock_t MutexType; #elif defined(HAVE_PTHREAD) # include typedef pthread_mutex_t MutexType; #else # error Need to implement mutex.h for your architecture, or #define NO_THREADS #endif #include #include // for abort() #define MUTEX_NAMESPACE gflags_mutex_namespace namespace MUTEX_NAMESPACE { class Mutex { public: // This is used for the single-arg constructor enum LinkerInitialized { LINKER_INITIALIZED }; // Create a Mutex that is not held by anybody. This constructor is // typically used for Mutexes allocated on the heap or the stack. inline Mutex(); // This constructor should be used for global, static Mutex objects. // It inhibits work being done by the destructor, which makes it // safer for code that tries to acqiure this mutex in their global // destructor. explicit inline Mutex(LinkerInitialized); // Destructor inline ~Mutex(); inline void Lock(); // Block if needed until free then acquire exclusively inline void Unlock(); // Release a lock acquired via Lock() #ifdef GMUTEX_TRYLOCK inline bool TryLock(); // If free, Lock() and return true, else return false #endif // Note that on systems that don't support read-write locks, these may // be implemented as synonyms to Lock() and Unlock(). So you can use // these for efficiency, but don't use them anyplace where being able // to do shared reads is necessary to avoid deadlock. inline void ReaderLock(); // Block until free or shared then acquire a share inline void ReaderUnlock(); // Release a read share of this Mutex inline void WriterLock() { Lock(); } // Acquire an exclusive lock inline void WriterUnlock() { Unlock(); } // Release a lock from WriterLock() private: MutexType mutex_; // We want to make sure that the compiler sets is_safe_ to true only // when we tell it to, and never makes assumptions is_safe_ is // always true. volatile is the most reliable way to do that. volatile bool is_safe_; // This indicates which constructor was called. bool destroy_; inline void SetIsSafe() { is_safe_ = true; } // Catch the error of writing Mutex when intending MutexLock. explicit Mutex(Mutex* /*ignored*/) {} // Disallow "evil" constructors Mutex(const Mutex&); void operator=(const Mutex&); }; // Now the implementation of Mutex for various systems #if defined(NO_THREADS) // When we don't have threads, we can be either reading or writing, // but not both. We can have lots of readers at once (in no-threads // mode, that's most likely to happen in recursive function calls), // but only one writer. We represent this by having mutex_ be -1 when // writing and a number > 0 when reading (and 0 when no lock is held). // // In debug mode, we assert these invariants, while in non-debug mode // we do nothing, for efficiency. That's why everything is in an // assert. Mutex::Mutex() : mutex_(0) { } Mutex::Mutex(Mutex::LinkerInitialized) : mutex_(0) { } Mutex::~Mutex() { assert(mutex_ == 0); } void Mutex::Lock() { assert(--mutex_ == -1); } void Mutex::Unlock() { assert(mutex_++ == -1); } #ifdef GMUTEX_TRYLOCK bool Mutex::TryLock() { if (mutex_) return false; Lock(); return true; } #endif void Mutex::ReaderLock() { assert(++mutex_ > 0); } void Mutex::ReaderUnlock() { assert(mutex_-- > 0); } #elif defined(OS_WINDOWS) Mutex::Mutex() : destroy_(true) { InitializeCriticalSection(&mutex_); SetIsSafe(); } Mutex::Mutex(LinkerInitialized) : destroy_(false) { InitializeCriticalSection(&mutex_); SetIsSafe(); } Mutex::~Mutex() { if (destroy_) DeleteCriticalSection(&mutex_); } void Mutex::Lock() { if (is_safe_) EnterCriticalSection(&mutex_); } void Mutex::Unlock() { if (is_safe_) LeaveCriticalSection(&mutex_); } #ifdef GMUTEX_TRYLOCK bool Mutex::TryLock() { return is_safe_ ? TryEnterCriticalSection(&mutex_) != 0 : true; } #endif void Mutex::ReaderLock() { Lock(); } // we don't have read-write locks void Mutex::ReaderUnlock() { Unlock(); } #elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK) #define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \ if (is_safe_ && fncall(&mutex_) != 0) abort(); \ } while (0) Mutex::Mutex() : destroy_(true) { SetIsSafe(); if (is_safe_ && pthread_rwlock_init(&mutex_, NULL) != 0) abort(); } Mutex::Mutex(Mutex::LinkerInitialized) : destroy_(false) { SetIsSafe(); if (is_safe_ && pthread_rwlock_init(&mutex_, NULL) != 0) abort(); } Mutex::~Mutex() { if (destroy_) SAFE_PTHREAD(pthread_rwlock_destroy); } void Mutex::Lock() { SAFE_PTHREAD(pthread_rwlock_wrlock); } void Mutex::Unlock() { SAFE_PTHREAD(pthread_rwlock_unlock); } #ifdef GMUTEX_TRYLOCK bool Mutex::TryLock() { return is_safe_ ? pthread_rwlock_trywrlock(&mutex_) == 0 : true; } #endif void Mutex::ReaderLock() { SAFE_PTHREAD(pthread_rwlock_rdlock); } void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock); } #undef SAFE_PTHREAD #elif defined(HAVE_PTHREAD) #define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \ if (is_safe_ && fncall(&mutex_) != 0) abort(); \ } while (0) Mutex::Mutex() : destroy_(true) { SetIsSafe(); if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) abort(); } Mutex::Mutex(Mutex::LinkerInitialized) : destroy_(false) { SetIsSafe(); if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) abort(); } Mutex::~Mutex() { if (destroy_) SAFE_PTHREAD(pthread_mutex_destroy); } void Mutex::Lock() { SAFE_PTHREAD(pthread_mutex_lock); } void Mutex::Unlock() { SAFE_PTHREAD(pthread_mutex_unlock); } #ifdef GMUTEX_TRYLOCK bool Mutex::TryLock() { return is_safe_ ? pthread_mutex_trylock(&mutex_) == 0 : true; } #endif void Mutex::ReaderLock() { Lock(); } void Mutex::ReaderUnlock() { Unlock(); } #undef SAFE_PTHREAD #endif // -------------------------------------------------------------------------- // Some helper classes // MutexLock(mu) acquires mu when constructed and releases it when destroyed. class MutexLock { public: explicit MutexLock(Mutex *mu) : mu_(mu) { mu_->Lock(); } ~MutexLock() { mu_->Unlock(); } private: Mutex * const mu_; // Disallow "evil" constructors MutexLock(const MutexLock&); void operator=(const MutexLock&); }; // ReaderMutexLock and WriterMutexLock do the same, for rwlocks class ReaderMutexLock { public: explicit ReaderMutexLock(Mutex *mu) : mu_(mu) { mu_->ReaderLock(); } ~ReaderMutexLock() { mu_->ReaderUnlock(); } private: Mutex * const mu_; // Disallow "evil" constructors ReaderMutexLock(const ReaderMutexLock&); void operator=(const ReaderMutexLock&); }; class WriterMutexLock { public: explicit WriterMutexLock(Mutex *mu) : mu_(mu) { mu_->WriterLock(); } ~WriterMutexLock() { mu_->WriterUnlock(); } private: Mutex * const mu_; // Disallow "evil" constructors WriterMutexLock(const WriterMutexLock&); void operator=(const WriterMutexLock&); }; // Catch bug where variable name is omitted, e.g. MutexLock (&mu); #define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_decl_missing_var_name) #define ReaderMutexLock(x) COMPILE_ASSERT(0, rmutex_lock_decl_missing_var_name) #define WriterMutexLock(x) COMPILE_ASSERT(0, wmutex_lock_decl_missing_var_name) } // namespace MUTEX_NAMESPACE #endif /* #define GFLAGS_MUTEX_H__ */ gflags-2.2.2/src/util.h000066400000000000000000000334061337211647400147130ustar00rootroot00000000000000// Copyright (c) 2011, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // --- // // Some generically useful utility routines that in google-land would // be their own projects. We make a shortened version here. #ifndef GFLAGS_UTIL_H_ #define GFLAGS_UTIL_H_ #include "config.h" #include #ifdef HAVE_INTTYPES_H # include #endif #include // for va_* #include #include #include #include #include #ifdef HAVE_SYS_STAT_H # include // for mkdir #endif namespace GFLAGS_NAMESPACE { // This is used for unittests for death-testing. It is defined in gflags.cc. extern GFLAGS_DLL_DECL void (*gflags_exitfunc)(int); // Work properly if either strtoll or strtoq is on this system. #if defined(strtoll) || defined(HAVE_STRTOLL) # define strto64 strtoll # define strtou64 strtoull #elif defined(HAVE_STRTOQ) # define strto64 strtoq # define strtou64 strtouq // Neither strtoll nor strtoq are defined. I hope strtol works! #else # define strto64 strtol # define strtou64 strtoul #endif // If we have inttypes.h, it will have defined PRId32/etc for us. // If not, take our best guess. #ifndef PRId32 # define PRId32 "d" #endif #ifndef PRId64 # define PRId64 "lld" #endif #ifndef PRIu64 # define PRIu64 "llu" #endif typedef signed char int8; typedef unsigned char uint8; // -- utility macros --------------------------------------------------------- template struct CompileAssert; template <> struct CompileAssert {}; #define COMPILE_ASSERT(expr, msg) \ enum { assert_##msg = sizeof(CompileAssert) } // Returns the number of elements in an array. #define arraysize(arr) (sizeof(arr)/sizeof(*(arr))) // -- logging and testing --------------------------------------------------- // For now, we ignore the level for logging, and don't show *VLOG's at // all, except by hand-editing the lines below #define LOG(level) std::cerr #define VLOG(level) if (true) {} else std::cerr #define DVLOG(level) if (true) {} else std::cerr // CHECK dies with a fatal error if condition is not true. It is *not* // controlled by NDEBUG, so the check will be executed regardless of // compilation mode. Therefore, it is safe to do things like: // CHECK(fp->Write(x) == 4) // We allow stream-like objects after this for debugging, but they're ignored. #define EXPECT_TRUE(condition) \ if (true) { \ if (!(condition)) { \ fprintf(stderr, "Check failed: %s\n", #condition); \ exit(1); \ } \ } else std::cerr << "" #define EXPECT_OP(op, val1, val2) \ if (true) { \ if (!((val1) op (val2))) { \ fprintf(stderr, "Check failed: %s %s %s\n", #val1, #op, #val2); \ exit(1); \ } \ } else std::cerr << "" #define EXPECT_EQ(val1, val2) EXPECT_OP(==, val1, val2) #define EXPECT_NE(val1, val2) EXPECT_OP(!=, val1, val2) #define EXPECT_LE(val1, val2) EXPECT_OP(<=, val1, val2) #define EXPECT_LT(val1, val2) EXPECT_OP(< , val1, val2) #define EXPECT_GE(val1, val2) EXPECT_OP(>=, val1, val2) #define EXPECT_GT(val1, val2) EXPECT_OP(> , val1, val2) #define EXPECT_FALSE(cond) EXPECT_TRUE(!(cond)) // C99 declares isnan and isinf should be macros, so the #ifdef test // should be reliable everywhere. Of course, it's not, but these // are testing pertty marginal functionality anyway, so it's ok to // not-run them even in situations they might, with effort, be made to work. #ifdef isnan // Some compilers, like sun's for Solaris 10, don't define this #define EXPECT_NAN(arg) \ do { \ if (!isnan(arg)) { \ fprintf(stderr, "Check failed: isnan(%s)\n", #arg); \ exit(1); \ } \ } while (0) #else #define EXPECT_NAN(arg) #endif #ifdef isinf // Some compilers, like sun's for Solaris 10, don't define this #define EXPECT_INF(arg) \ do { \ if (!isinf(arg)) { \ fprintf(stderr, "Check failed: isinf(%s)\n", #arg); \ exit(1); \ } \ } while (0) #else #define EXPECT_INF(arg) #endif #define EXPECT_DOUBLE_EQ(val1, val2) \ do { \ if (((val1) < (val2) - 0.001 || (val1) > (val2) + 0.001)) { \ fprintf(stderr, "Check failed: %s == %s\n", #val1, #val2); \ exit(1); \ } \ } while (0) #define EXPECT_STREQ(val1, val2) \ do { \ if (strcmp((val1), (val2)) != 0) { \ fprintf(stderr, "Check failed: streq(%s, %s)\n", #val1, #val2); \ exit(1); \ } \ } while (0) // Call this in a .cc file where you will later call RUN_ALL_TESTS in main(). #define TEST_INIT \ static std::vector g_testlist; /* the tests to run */ \ static int RUN_ALL_TESTS() { \ std::vector::const_iterator it; \ for (it = g_testlist.begin(); it != g_testlist.end(); ++it) { \ (*it)(); /* The test will error-exit if there's a problem. */ \ } \ fprintf(stderr, "\nPassed %d tests\n\nPASS\n", \ static_cast(g_testlist.size())); \ return 0; \ } // Note that this macro uses a FlagSaver to keep tests isolated. #define TEST(a, b) \ struct Test_##a##_##b { \ Test_##a##_##b() { g_testlist.push_back(&Run); } \ static void Run() { \ FlagSaver fs; \ fprintf(stderr, "Running test %s/%s\n", #a, #b); \ RunTest(); \ } \ static void RunTest(); \ }; \ static Test_##a##_##b g_test_##a##_##b; \ void Test_##a##_##b::RunTest() // This is a dummy class that eases the google->opensource transition. namespace testing { class Test {}; } // Call this in a .cc file where you will later call EXPECT_DEATH #define EXPECT_DEATH_INIT \ static bool g_called_exit; \ static void CalledExit(int) { g_called_exit = true; } #define EXPECT_DEATH(fn, msg) \ do { \ g_called_exit = false; \ gflags_exitfunc = &CalledExit; \ fn; \ gflags_exitfunc = &exit; /* set back to its default */ \ if (!g_called_exit) { \ fprintf(stderr, "Function didn't die (%s): %s\n", msg, #fn); \ exit(1); \ } \ } while (0) #define GTEST_HAS_DEATH_TEST 1 // -- path routines ---------------------------------------------------------- // Tries to create the directory path as a temp-dir. If it fails, // changes path to some directory it *can* create. #if defined(__MINGW32__) #include inline void MakeTmpdir(std::string* path) { if (!path->empty()) { path->append("/gflags_unittest_testdir"); int err = mkdir(path->c_str()); if (err == 0 || errno == EEXIST) return; } // I had trouble creating a directory in /tmp from mingw *path = "./gflags_unittest"; mkdir(path->c_str()); } #elif defined(_MSC_VER) #include inline void MakeTmpdir(std::string* path) { if (!path->empty()) { int err = _mkdir(path->c_str()); if (err == 0 || errno == EEXIST) return; } char tmppath_buffer[1024]; int tmppath_len = GetTempPathA(sizeof(tmppath_buffer), tmppath_buffer); assert(tmppath_len > 0 && tmppath_len < sizeof(tmppath_buffer)); assert(tmppath_buffer[tmppath_len - 1] == '\\'); // API guarantees it *path = std::string(tmppath_buffer) + "gflags_unittest"; _mkdir(path->c_str()); } #else inline void MakeTmpdir(std::string* path) { if (!path->empty()) { int err = mkdir(path->c_str(), 0755); if (err == 0 || errno == EEXIST) return; } mkdir("/tmp/gflags_unittest", 0755); } #endif // -- string routines -------------------------------------------------------- inline void InternalStringPrintf(std::string* output, const char* format, va_list ap) { char space[128]; // try a small buffer and hope it fits // It's possible for methods that use a va_list to invalidate // the data in it upon use. The fix is to make a copy // of the structure before using it and use that copy instead. va_list backup_ap; va_copy(backup_ap, ap); int bytes_written = vsnprintf(space, sizeof(space), format, backup_ap); va_end(backup_ap); if ((bytes_written >= 0) && (static_cast(bytes_written) < sizeof(space))) { output->append(space, bytes_written); return; } // Repeatedly increase buffer size until it fits. int length = sizeof(space); while (true) { if (bytes_written < 0) { // Older snprintf() behavior. :-( Just try doubling the buffer size length *= 2; } else { // We need exactly "bytes_written+1" characters length = bytes_written+1; } char* buf = new char[length]; // Restore the va_list before we use it again va_copy(backup_ap, ap); bytes_written = vsnprintf(buf, length, format, backup_ap); va_end(backup_ap); if ((bytes_written >= 0) && (bytes_written < length)) { output->append(buf, bytes_written); delete[] buf; return; } delete[] buf; } } // Clears output before writing to it. inline void SStringPrintf(std::string* output, const char* format, ...) { va_list ap; va_start(ap, format); output->clear(); InternalStringPrintf(output, format, ap); va_end(ap); } inline void StringAppendF(std::string* output, const char* format, ...) { va_list ap; va_start(ap, format); InternalStringPrintf(output, format, ap); va_end(ap); } inline std::string StringPrintf(const char* format, ...) { va_list ap; va_start(ap, format); std::string output; InternalStringPrintf(&output, format, ap); va_end(ap); return output; } inline bool SafeGetEnv(const char *varname, std::string &valstr) { #if defined(_MSC_VER) && _MSC_VER >= 1400 char *val; size_t sz; if (_dupenv_s(&val, &sz, varname) != 0 || !val) return false; valstr = val; free(val); #else const char * const val = getenv(varname); if (!val) return false; valstr = val; #endif return true; } inline int SafeFOpen(FILE **fp, const char* fname, const char *mode) { #if defined(_MSC_VER) && _MSC_VER >= 1400 return fopen_s(fp, fname, mode); #else assert(fp != NULL); *fp = fopen(fname, mode); // errno only guaranteed to be set on failure return ((*fp == NULL) ? errno : 0); #endif } } // namespace GFLAGS_NAMESPACE #endif // GFLAGS_UTIL_H_ gflags-2.2.2/src/windows_port.cc000066400000000000000000000054531337211647400166330ustar00rootroot00000000000000/* Copyright (c) 2009, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * --- * Author: Craig Silverstein */ #ifndef _WIN32 # error You should only be including windows/port.cc in a windows environment! #endif #include // for strlen(), memset(), memcmp() #include #include // for va_list, va_start, va_end #include #include "windows_port.h" // These call the windows _vsnprintf, but always NUL-terminate. #if !defined(__MINGW32__) && !defined(__MINGW64__) /* mingw already defines */ #if !(defined(_MSC_VER) && _MSC_VER >= 1900) /* msvc 2015 already defines */ #ifdef _MSC_VER # pragma warning(push) # pragma warning(disable: 4996) // ignore _vsnprintf security warning #endif int safe_vsnprintf(char *str, size_t size, const char *format, va_list ap) { if (size == 0) // not even room for a \0? return -1; // not what C99 says to do, but what windows does str[size-1] = '\0'; return _vsnprintf(str, size-1, format, ap); } #ifdef _MSC_VER # pragma warning(pop) #endif int snprintf(char *str, size_t size, const char *format, ...) { int r; va_list ap; va_start(ap, format); r = vsnprintf(str, size, format, ap); va_end(ap); return r; } #endif /* if !(defined(_MSC_VER) && _MSC_VER >= 1900) */ #endif /* #if !defined(__MINGW32__) && !defined(__MINGW64__) */ gflags-2.2.2/src/windows_port.h000066400000000000000000000123341337211647400164710ustar00rootroot00000000000000/* Copyright (c) 2009, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * --- * Author: Craig Silverstein * * These are some portability typedefs and defines to make it a bit * easier to compile this code under VC++. * * Several of these are taken from glib: * http://developer.gnome.org/doc/API/glib/glib-windows-compatability-functions.html */ #ifndef GFLAGS_WINDOWS_PORT_H_ #define GFLAGS_WINDOWS_PORT_H_ #include "config.h" // This must be defined before the windows.h is included. // It's needed for mutex.h, to give access to the TryLock method. # if !defined(_WIN32_WINNT) && !(defined( __MINGW32__) || defined(__MINGW64__)) # define _WIN32_WINNT 0x0400 # endif // We always want minimal includes #ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN #endif #include #include /* for mkdir */ #include /* for _putenv, getenv */ #include /* need this to override stdio's snprintf, also defines _unlink used by unit tests */ #include /* util.h uses va_copy */ #include /* for _stricmp and _strdup */ /* We can't just use _vsnprintf and _snprintf as drop-in-replacements, * because they don't always NUL-terminate. :-( We also can't use the * name vsnprintf, since windows defines that (but not snprintf (!)). */ #if !defined(__MINGW32__) && !defined(__MINGW64__) /* mingw already defines */ #if !(defined(_MSC_VER) && _MSC_VER >= 1900) /* msvc 2015 already defines */ extern GFLAGS_DLL_DECL int snprintf(char *str, size_t size, const char *format, ...); extern int GFLAGS_DLL_DECL safe_vsnprintf(char *str, size_t size, const char *format, va_list ap); #define vsnprintf(str, size, format, ap) safe_vsnprintf(str, size, format, ap) #define va_copy(dst, src) (dst) = (src) #endif #endif /* #if !defined(__MINGW32__) && !defined(__MINGW64__) */ #ifdef _MSC_VER # pragma warning(push) # pragma warning(disable: 4996) // ignore getenv security warning #endif #if !defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 200112L inline void setenv(const char* name, const char* value, int) { // In windows, it's impossible to set a variable to the empty string. // We handle this by setting it to "0" and the NUL-ing out the \0. // That is, we putenv("FOO=0") and then find out where in memory the // putenv wrote "FOO=0", and change it in-place to "FOO=\0". // c.f. http://svn.apache.org/viewvc/stdcxx/trunk/tests/src/environ.cpp?r1=611451&r2=637508&pathrev=637508 static const char* const kFakeZero = "0"; if (*value == '\0') value = kFakeZero; // Apparently the semantics of putenv() is that the input // must live forever, so we leak memory here. :-( const size_t nameval_len = strlen(name) + 1 + strlen(value) + 1; char* nameval = reinterpret_cast(malloc(nameval_len)); snprintf(nameval, nameval_len, "%s=%s", name, value); _putenv(nameval); if (value == kFakeZero) { nameval[nameval_len - 2] = '\0'; // works when putenv() makes no copy if (*getenv(name) != '\0') *getenv(name) = '\0'; // works when putenv() copies nameval } } #endif #ifdef _MSC_VER # pragma warning(pop) #endif #define strcasecmp _stricmp #if defined(_MSC_VER) && _MSC_VER >= 1400 #define strdup _strdup #define unlink _unlink #endif #if defined(_MSC_VER) && _MSC_VER >= 1800 #include #else #define PRId32 "d" #define PRIu32 "u" #define PRId64 "I64d" #define PRIu64 "I64u" #endif #if !defined(__MINGW32__) && !defined(__MINGW64__) #define strtoq _strtoi64 #define strtouq _strtoui64 #define strtoll _strtoi64 #define strtoull _strtoui64 #define atoll _atoi64 #endif #ifndef PATH_MAX #define PATH_MAX 1024 #endif #endif /* GFLAGS_WINDOWS_PORT_H_ */ gflags-2.2.2/test/000077500000000000000000000000001337211647400137475ustar00rootroot00000000000000gflags-2.2.2/test/CMakeLists.txt000066400000000000000000000263141337211647400165150ustar00rootroot00000000000000## gflags tests # ---------------------------------------------------------------------------- # output directories set (CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin") set (CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib") set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib") # set working directory of test commands set (GFLAGS_FLAGFILES_DIR "${CMAKE_CURRENT_SOURCE_DIR}") # ---------------------------------------------------------------------------- # common include directories and link libraries include_directories ("${CMAKE_CURRENT_SOURCE_DIR}") include_directories ("${gflags_SOURCE_DIR}/src") include_directories ("${gflags_BINARY_DIR}/include") include_directories ("${gflags_BINARY_DIR}/include/gflags") if (BUILD_SHARED_LIBS) set (type shared) if (GFLAGS_IS_A_DLL) add_definitions(-DGFLAGS_IS_A_DLL) endif () else () set (type static) endif () if (BUILD_gflags_LIB) link_libraries (gflags_${type}) else () link_libraries (gflags_nothreads_${type}) endif () # ---------------------------------------------------------------------------- # STRIP_FLAG_HELP add_executable (gflags_strip_flags_test gflags_strip_flags_test.cc) # Make sure the --help output doesn't print the stripped text. add_gflags_test (strip_flags_help 1 "" "This text should be stripped out" gflags_strip_flags_test --help) # Make sure the stripped text isn't in the binary at all. add_test ( NAME strip_flags_binary COMMAND "${CMAKE_COMMAND}" "-DBINARY=$" -P "${CMAKE_CURRENT_SOURCE_DIR}/gflags_strip_flags_test.cmake" CONFIGURATIONS Release MinSizeRel ) # ---------------------------------------------------------------------------- # unit tests configure_file (gflags_unittest.cc gflags_unittest-main.cc COPYONLY) configure_file (gflags_unittest.cc gflags_unittest_main.cc COPYONLY) add_executable (gflags_unittest gflags_unittest.cc) add_executable (gflags_unittest-main gflags_unittest-main.cc) add_executable (gflags_unittest_main gflags_unittest_main.cc) if (OS_WINDOWS) set (SLASH "\\\\") else () set (SLASH "/") endif () # First, just make sure the gflags_unittest works as-is add_gflags_test(unittest 0 "" "" gflags_unittest) # --help should show all flags, including flags from gflags_reporting add_gflags_test(help-reporting 1 "${SLASH}gflags_reporting.cc:" "" gflags_unittest --help) # Make sure that --help prints even very long helpstrings. add_gflags_test(long-helpstring 1 "end of a long helpstring" "" gflags_unittest --help) # Make sure --help reflects flag changes made before flag-parsing add_gflags_test(changed_bool1 1 "-changed_bool1 (changed) type: bool default: true" "" gflags_unittest --help) add_gflags_test(changed_bool2 1 "-changed_bool2 (changed) type: bool default: false currently: true" "" gflags_unittest --help) # And on the command-line, too add_gflags_test(changeable_string_var 1 "-changeable_string_var () type: string default: \"1\" currently: \"2\"" "" gflags_unittest --changeable_string_var 2 --help) # --nohelp and --help=false should be as if we didn't say anything add_gflags_test(nohelp 0 "PASS" "" gflags_unittest --nohelp) add_gflags_test(help=false 0 "PASS" "" gflags_unittest --help=false) # --helpfull is the same as help add_gflags_test(helpfull 1 "${SLASH}gflags_reporting.cc:" "" gflags_unittest --helpfull) # --helpshort should show only flags from the gflags_unittest itself add_gflags_test(helpshort 1 "${SLASH}gflags_unittest.cc:" "${SLASH}gflags_reporting.cc:" gflags_unittest --helpshort) # --helpshort should show the tldflag we created in the gflags_unittest dir add_gflags_test(helpshort-tldflag1 1 "tldflag1" "${SLASH}google.cc:" gflags_unittest --helpshort) add_gflags_test(helpshort-tldflag2 1 "tldflag2" "${SLASH}google.cc:" gflags_unittest --helpshort) # --helpshort should work if the main source file is suffixed with [_-]main add_gflags_test(helpshort-main 1 "${SLASH}gflags_unittest-main.cc:" "${SLASH}gflags_reporting.cc:" gflags_unittest-main --helpshort) add_gflags_test(helpshort_main 1 "${SLASH}gflags_unittest_main.cc:" "${SLASH}gflags_reporting.cc:" gflags_unittest_main --helpshort) # --helpon needs an argument add_gflags_test(helpon 1 "'--helpon' is missing its argument; flag description: show help on" "" gflags_unittest --helpon) # --helpon argument indicates what file we'll show args from add_gflags_test(helpon=gflags 1 "${SLASH}gflags.cc:" "${SLASH}gflags_unittest.cc:" gflags_unittest --helpon=gflags) # another way of specifying the argument add_gflags_test(helpon_gflags 1 "${SLASH}gflags.cc:" "${SLASH}gflags_unittest.cc:" gflags_unittest --helpon gflags) # test another argument add_gflags_test(helpon=gflags_unittest 1 "${SLASH}gflags_unittest.cc:" "${SLASH}gflags.cc:" gflags_unittest --helpon=gflags_unittest) # helpmatch is like helpon but takes substrings add_gflags_test(helpmatch_reporting 1 "${SLASH}gflags_reporting.cc:" "${SLASH}gflags_unittest.cc:" gflags_unittest -helpmatch reporting) add_gflags_test(helpmatch=unittest 1 "${SLASH}gflags_unittest.cc:" "${SLASH}gflags.cc:" gflags_unittest -helpmatch=unittest) # if no flags are found with helpmatch or helpon, suggest --help add_gflags_test(helpmatch=nosuchsubstring 1 "No modules matched" "${SLASH}gflags_unittest.cc:" gflags_unittest -helpmatch=nosuchsubstring) add_gflags_test(helpon=nosuchmodule 1 "No modules matched" "${SLASH}gflags_unittest.cc:" gflags_unittest -helpon=nosuchmodule) # helppackage shows all the flags in the same dir as this unittest # --help should show all flags, including flags from google.cc add_gflags_test(helppackage 1 "${SLASH}gflags_reporting.cc:" "" gflags_unittest --helppackage) # xml! add_gflags_test(helpxml 1 "${SLASH}gflags_unittest.cc" "${SLASH}gflags_unittest.cc:" gflags_unittest --helpxml) # just print the version info and exit add_gflags_test(version-1 0 "gflags_unittest" "${SLASH}gflags_unittest.cc:" gflags_unittest --version) add_gflags_test(version-2 0 "version test_version" "${SLASH}gflags_unittest.cc:" gflags_unittest --version) # --undefok is a fun flag... add_gflags_test(undefok-1 1 "unknown command line flag 'foo'" "" gflags_unittest --undefok= --foo --unused_bool) add_gflags_test(undefok-2 0 "PASS" "" gflags_unittest --undefok=foo --foo --unused_bool) # If you say foo is ok to be undefined, we'll accept --nofoo as well add_gflags_test(undefok-3 0 "PASS" "" gflags_unittest --undefok=foo --nofoo --unused_bool) # It's ok if the foo is in the middle add_gflags_test(undefok-4 0 "PASS" "" gflags_unittest --undefok=fee,fi,foo,fum --foo --unused_bool) # But the spelling has to be just right... add_gflags_test(undefok-5 1 "unknown command line flag 'foo'" "" gflags_unittest --undefok=fo --foo --unused_bool) add_gflags_test(undefok-6 1 "unknown command line flag 'foo'" "" gflags_unittest --undefok=foot --foo --unused_bool) # See if we can successfully load our flags from the flagfile add_gflags_test(flagfile.1 0 "gflags_unittest" "${SLASH}gflags_unittest.cc:" gflags_unittest "--flagfile=flagfile.1") add_gflags_test(flagfile.2 0 "PASS" "" gflags_unittest "--flagfile=flagfile.2") add_gflags_test(flagfile.3 0 "PASS" "" gflags_unittest "--flagfile=flagfile.3") # Also try to load flags from the environment add_gflags_test(fromenv=version 0 "gflags_unittest" "${SLASH}gflags_unittest.cc:" gflags_unittest --fromenv=version) add_gflags_test(tryfromenv=version 0 "gflags_unittest" "${SLASH}gflags_unittest.cc:" gflags_unittest --tryfromenv=version) add_gflags_test(fromenv=help 0 "PASS" "" gflags_unittest --fromenv=help) add_gflags_test(tryfromenv=help 0 "PASS" "" gflags_unittest --tryfromenv=help) add_gflags_test(fromenv=helpfull 1 "helpfull not found in environment" "" gflags_unittest --fromenv=helpfull) add_gflags_test(tryfromenv=helpfull 0 "PASS" "" gflags_unittest --tryfromenv=helpfull) add_gflags_test(tryfromenv=undefok 0 "PASS" "" gflags_unittest --tryfromenv=undefok --foo) add_gflags_test(tryfromenv=weirdo 1 "unknown command line flag" "" gflags_unittest --tryfromenv=weirdo) add_gflags_test(tryfromenv-multiple 0 "gflags_unittest" "${SLASH}gflags_unittest.cc:" gflags_unittest --tryfromenv=test_bool,version,unused_bool) add_gflags_test(fromenv=test_bool 1 "not found in environment" "" gflags_unittest --fromenv=test_bool) add_gflags_test(fromenv=test_bool-ok 1 "unknown command line flag" "" gflags_unittest --fromenv=test_bool,ok) # Here, the --version overrides the fromenv add_gflags_test(version-overrides-fromenv 0 "gflags_unittest" "${SLASH}gflags_unittest.cc:" gflags_unittest --fromenv=test_bool,version,ok) # Make sure -- by itself stops argv processing add_gflags_test(dashdash 0 "PASS" "" gflags_unittest -- --help) # And we should die if the flag value doesn't pass the validator add_gflags_test(always_fail 1 "ERROR: failed validation of new value 'true' for flag 'always_fail'" "" gflags_unittest --always_fail) # And if locking in validators fails # TODO(andreas): Worked on Windows 7 Release configuration, but causes # debugger abort() intervention in case of Debug configuration. #add_gflags_test(deadlock_if_cant_lock 0 "PASS" "" gflags_unittest --deadlock_if_cant_lock) # ---------------------------------------------------------------------------- # use gflags_declare.h add_executable (gflags_declare_test gflags_declare_test.cc gflags_declare_flags.cc) add_test(NAME gflags_declare COMMAND gflags_declare_test --message "Hello gflags!") set_tests_properties(gflags_declare PROPERTIES PASS_REGULAR_EXPRESSION "Hello gflags!") # ---------------------------------------------------------------------------- # configure Python script which configures and builds a test project if (BUILD_NC_TESTS OR BUILD_CONFIG_TESTS) find_package (PythonInterp) if (NOT PYTHON_EXECUTABLE) message (FATAL_ERROR "No Python installation found! It is required by the (negative) compilation tests." " Either install Python or set BUILD_NC_TESTS and BUILD_CONFIG_TESTS to FALSE.") endif () set (TMPDIR "${PROJECT_BINARY_DIR}/Testing/Temporary") configure_file (gflags_build.py.in "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/build.py" @ONLY) function (add_gflags_build_test name srcdir expect_fail) set (srcdir "${CMAKE_CURRENT_SOURCE_DIR}/${srcdir}") add_test ( NAME "${name}" COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/build.py" ${name} ${srcdir} ${expect_fail} ) endfunction () endif () # ---------------------------------------------------------------------------- # negative compilation tests option (BUILD_NC_TESTS "Request addition of negative compilation tests." OFF) mark_as_advanced (BUILD_NC_TESTS) if (BUILD_NC_TESTS) add_gflags_build_test (nc_sanity nc 0) add_gflags_build_test (nc_swapped_args nc 1) add_gflags_build_test (nc_int_instead_of_bool nc 1) add_gflags_build_test (nc_bool_in_quotes nc 1) add_gflags_build_test (nc_define_string_with_0 nc 1) endif () # ---------------------------------------------------------------------------- # build configuration test option (BUILD_CONFIG_TESTS "Request addition of package configuration tests." OFF) mark_as_advanced (BUILD_CONFIG_TESTS) if (BUILD_CONFIG_TESTS) add_gflags_build_test (cmake_config config 0) endif () gflags-2.2.2/test/config/000077500000000000000000000000001337211647400152145ustar00rootroot00000000000000gflags-2.2.2/test/config/CMakeLists.txt000066400000000000000000000003431337211647400177540ustar00rootroot00000000000000## gflags package configuration tests cmake_minimum_required (VERSION 2.8.12 FATAL_ERROR) project (gflags_${TEST_NAME}) find_package (gflags REQUIRED) add_executable (foo main.cc) target_link_libraries (foo gflags::gflags) gflags-2.2.2/test/config/main.cc000066400000000000000000000011031337211647400164420ustar00rootroot00000000000000#include #include DEFINE_string(message, "Hello World!", "The message to print"); static bool ValidateMessage(const char* flagname, const std::string &message) { return !message.empty(); } DEFINE_validator(message, ValidateMessage); int main(int argc, char **argv) { gflags::SetUsageMessage("Test CMake configuration of gflags library (gflags-config.cmake)"); gflags::SetVersionString("0.1"); gflags::ParseCommandLineFlags(&argc, &argv, true); std::cout << FLAGS_message << std::endl; gflags::ShutDownCommandLineFlags(); return 0; } gflags-2.2.2/test/flagfile.1000066400000000000000000000000111337211647400155720ustar00rootroot00000000000000--versiongflags-2.2.2/test/flagfile.2000066400000000000000000000000311337211647400155750ustar00rootroot00000000000000--foo=bar --nounused_boolgflags-2.2.2/test/flagfile.3000066400000000000000000000000251337211647400156010ustar00rootroot00000000000000--flagfile=flagfile.2gflags-2.2.2/test/gflags_build.py.in000066400000000000000000000027201337211647400173510ustar00rootroot00000000000000#!/usr/bin/env python import os import sys import subprocess import shutil CMAKE = '@CMAKE_COMMAND@' CMAKE_BUILD_TYPE = '@CMAKE_BUILD_TYPE@' TMPDIR = '@TMPDIR@' SRCDIR = '@SRCDIR@' GFLAGS_DIR = '@gflags_BINARY_DIR@' if __name__ == "__main__": if len(sys.argv) != 4: sys.stderr.write(' '.join(['usage:', sys.argv[0], ' \n'])) sys.exit(1) test_name = sys.argv[1] srcdir = sys.argv[2] expect_fail = (sys.argv[3].lower() in ['true', 'yes', 'on', '1']) bindir = os.path.join(TMPDIR, test_name) if TMPDIR == '': sys.stderr.write('Temporary directory not set!\n') sys.exit(1) # create build directory if os.path.isdir(bindir): shutil.rmtree(bindir) os.makedirs(bindir) # configure the build tree if subprocess.call([CMAKE, '-DCMAKE_BUILD_TYPE:STRING='+CMAKE_BUILD_TYPE, '-Dgflags_DIR:PATH='+GFLAGS_DIR, '-DTEST_NAME:STRING='+test_name, srcdir], cwd=bindir) != 0: sys.stderr.write('Failed to configure the build tree!\n') sys.exit(1) # build the test project exit_code = subprocess.call([CMAKE, '--build', bindir, '--config', CMAKE_BUILD_TYPE], cwd=bindir) if expect_fail == True: if exit_code == 0: sys.stderr.write('Build expected to fail, but it succeeded!\n') sys.exit(1) else: sys.stderr.write('Build failed as expected\n') exit_code = 0 sys.exit(exit_code) gflags-2.2.2/test/gflags_declare_flags.cc000077500000000000000000000003521337211647400203570ustar00rootroot00000000000000#define GFLAGS_DLL_DECLARE_FLAG #include #include DECLARE_string(message); // in gflags_delcare_test.cc void print_message(); void print_message() { std::cout << FLAGS_message << std::endl; } gflags-2.2.2/test/gflags_declare_test.cc000066400000000000000000000005341337211647400202410ustar00rootroot00000000000000#include DEFINE_string(message, "", "The message to print"); void print_message(); // in gflags_declare_flags.cc int main(int argc, char **argv) { GFLAGS_NAMESPACE::SetUsageMessage("Test compilation and use of gflags_declare.h"); GFLAGS_NAMESPACE::ParseCommandLineFlags(&argc, &argv, true); print_message(); return 0; } gflags-2.2.2/test/gflags_strip_flags_test.cc000077500000000000000000000046751337211647400211740ustar00rootroot00000000000000// Copyright (c) 2011, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // --- // Author: csilvers@google.com (Craig Silverstein) // // A simple program that uses STRIP_FLAG_HELP. We'll have a shell // script that runs 'strings' over this program and makes sure // that the help string is not in there. #define STRIP_FLAG_HELP 1 #include #include using GFLAGS_NAMESPACE::SetUsageMessage; using GFLAGS_NAMESPACE::ParseCommandLineFlags; DEFINE_bool(test, true, "This text should be stripped out"); int main(int argc, char** argv) { SetUsageMessage("Usage message"); ParseCommandLineFlags(&argc, &argv, false); // Unfortunately, for us, libtool can replace executables with a shell // script that does some work before calling the 'real' executable // under a different name. We need the 'real' executable name to run // 'strings' on it, so we construct this binary to print the real // name (argv[0]) on stdout when run. puts(argv[0]); return 0; } gflags-2.2.2/test/gflags_strip_flags_test.cmake000066400000000000000000000004161337211647400216510ustar00rootroot00000000000000if (NOT BINARY) message (FATAL_ERROR "BINARY file to check not specified!") endif () file (STRINGS "${BINARY}" strings REGEX "This text should be stripped out") if (strings) message (FATAL_ERROR "Text not stripped from binary like it should be: ${BINARY}") endif () gflags-2.2.2/test/gflags_unittest.cc000077500000000000000000001474341337211647400175000ustar00rootroot00000000000000// Copyright (c) 2005, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // --- // // For now, this unit test does not cover all features of // gflags.cc #include #include "config.h" #include "util.h" #include // for isinf() and isnan() #include #include #include #ifdef HAVE_UNISTD_H # include // for unlink() #endif #include #include TEST_INIT EXPECT_DEATH_INIT // I don't actually use this header file, but #include it under the // old location to make sure that the include-header-forwarding // works. But don't bother on windows; the windows port is so new // it never had the old location-names. #ifndef _MSC_VER #include void (*unused_fn)() = &GFLAGS_NAMESPACE::HandleCommandLineCompletions; #endif using std::string; using std::vector; using GFLAGS_NAMESPACE::int32; using GFLAGS_NAMESPACE::FlagRegisterer; using GFLAGS_NAMESPACE::StringFromEnv; using GFLAGS_NAMESPACE::RegisterFlagValidator; using GFLAGS_NAMESPACE::CommandLineFlagInfo; using GFLAGS_NAMESPACE::GetAllFlags; DEFINE_string(test_tmpdir, "", "Dir we use for temp files"); DEFINE_string(srcdir, StringFromEnv("SRCDIR", "."), "Source-dir root, needed to find gflags_unittest_flagfile"); DECLARE_string(tryfromenv); // in gflags.cc DEFINE_bool(test_bool, false, "tests bool-ness"); DEFINE_int32(test_int32, -1, ""); DEFINE_int64(test_int64, -2, ""); DEFINE_uint32(test_uint32, 1, ""); DEFINE_uint64(test_uint64, 2, ""); DEFINE_double(test_double, -1.0, ""); DEFINE_string(test_string, "initial", ""); // // The below ugliness gets some additional code coverage in the -helpxml // and -helpmatch test cases having to do with string lengths and formatting // DEFINE_bool(test_bool_with_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_long_name, false, "extremely_extremely_extremely_extremely_extremely_extremely_extremely_extremely_long_meaning"); DEFINE_string(test_str1, "initial", ""); DEFINE_string(test_str2, "initial", ""); DEFINE_string(test_str3, "initial", ""); // This is used to test setting tryfromenv manually DEFINE_string(test_tryfromenv, "initial", ""); // Don't try this at home! static int changeable_var = 12; DEFINE_int32(changeable_var, ++changeable_var, ""); static int changeable_bool_var = 8008; DEFINE_bool(changeable_bool_var, ++changeable_bool_var == 8009, ""); static int changeable_string_var = 0; static string ChangeableString() { char r[] = {static_cast('0' + ++changeable_string_var), '\0'}; return r; } DEFINE_string(changeable_string_var, ChangeableString(), ""); // These are never used in this unittest, but can be used by // gflags_unittest.sh when it needs to specify flags // that are legal for gflags_unittest but don't need to // be a particular value. DEFINE_bool(unused_bool, true, "unused bool-ness"); DEFINE_int32(unused_int32, -1001, ""); DEFINE_int64(unused_int64, -2001, ""); DEFINE_uint32(unused_uint32, 1000, ""); DEFINE_uint64(unused_uint64, 2000, ""); DEFINE_double(unused_double, -1000.0, ""); DEFINE_string(unused_string, "unused", ""); // These flags are used by gflags_unittest.sh DEFINE_bool(changed_bool1, false, "changed"); DEFINE_bool(changed_bool2, false, "changed"); DEFINE_bool(long_helpstring, false, "This helpstring goes on forever and ever and ever and ever and " "ever and ever and ever and ever and ever and ever and ever and " "ever and ever and ever and ever and ever and ever and ever and " "ever and ever and ever and ever and ever and ever and ever and " "ever and ever and ever and ever and ever and ever and ever and " "ever and ever and ever and ever and ever and ever and ever and " "ever and ever and ever and ever and ever and ever and ever and " "ever and ever and ever and ever and ever and ever and ever and " "ever and ever and ever and ever and ever and ever and ever and " "ever and ever and ever and ever and ever and ever and ever and " "ever. This is the end of a long helpstring"); static bool AlwaysFail(const char* flag, bool value) { return value == false; } DEFINE_bool(always_fail, false, "will fail to validate when you set it"); DEFINE_validator(always_fail, AlwaysFail); // See the comment by GetAllFlags in gflags.h static bool DeadlockIfCantLockInValidators(const char* flag, bool value) { if (!value) { return true; } vector dummy; GetAllFlags(&dummy); return true; } DEFINE_bool(deadlock_if_cant_lock, false, "will deadlock if set to true and " "if locking of registry in validators fails."); DEFINE_validator(deadlock_if_cant_lock, DeadlockIfCantLockInValidators); #define MAKEFLAG(x) DEFINE_int32(test_flag_num##x, x, "Test flag") // Define 10 flags #define MAKEFLAG10(x) \ MAKEFLAG(x##0); \ MAKEFLAG(x##1); \ MAKEFLAG(x##2); \ MAKEFLAG(x##3); \ MAKEFLAG(x##4); \ MAKEFLAG(x##5); \ MAKEFLAG(x##6); \ MAKEFLAG(x##7); \ MAKEFLAG(x##8); \ MAKEFLAG(x##9) // Define 100 flags #define MAKEFLAG100(x) \ MAKEFLAG10(x##0); \ MAKEFLAG10(x##1); \ MAKEFLAG10(x##2); \ MAKEFLAG10(x##3); \ MAKEFLAG10(x##4); \ MAKEFLAG10(x##5); \ MAKEFLAG10(x##6); \ MAKEFLAG10(x##7); \ MAKEFLAG10(x##8); \ MAKEFLAG10(x##9) // Define a bunch of command-line flags. Each occurrence of the MAKEFLAG100 // macro defines 100 integer flags. This lets us test the effect of having // many flags on startup time. MAKEFLAG100(1); MAKEFLAG100(2); MAKEFLAG100(3); MAKEFLAG100(4); MAKEFLAG100(5); MAKEFLAG100(6); MAKEFLAG100(7); MAKEFLAG100(8); MAKEFLAG100(9); MAKEFLAG100(10); MAKEFLAG100(11); MAKEFLAG100(12); MAKEFLAG100(13); MAKEFLAG100(14); MAKEFLAG100(15); #undef MAKEFLAG100 #undef MAKEFLAG10 #undef MAKEFLAG // This is a pseudo-flag -- we want to register a flag with a filename // at the top level, but there is no way to do this except by faking // the filename. namespace fLI { static const int32 FLAGS_nonotldflag1 = 12; int32 FLAGS_tldflag1 = FLAGS_nonotldflag1; int32 FLAGS_notldflag1 = FLAGS_nonotldflag1; static FlagRegisterer o_tldflag1( "tldflag1", "should show up in --helpshort", "gflags_unittest.cc", &FLAGS_tldflag1, &FLAGS_notldflag1); } using fLI::FLAGS_tldflag1; namespace fLI { static const int32 FLAGS_nonotldflag2 = 23; int32 FLAGS_tldflag2 = FLAGS_nonotldflag2; int32 FLAGS_notldflag2 = FLAGS_nonotldflag2; static FlagRegisterer o_tldflag2( "tldflag2", "should show up in --helpshort", "gflags_unittest.", &FLAGS_tldflag2, &FLAGS_notldflag2); } using fLI::FLAGS_tldflag2; namespace GFLAGS_NAMESPACE { namespace { static string TmpFile(const string& basename) { #ifdef _MSC_VER return FLAGS_test_tmpdir + "\\" + basename; #else return FLAGS_test_tmpdir + "/" + basename; #endif } // Returns the definition of the --flagfile flag to be used in the tests. // Must be called after ParseCommandLineFlags(). static const char* GetFlagFileFlag() { #ifdef _MSC_VER static const string flagfile = FLAGS_srcdir + "\\gflags_unittest_flagfile"; #else static const string flagfile = FLAGS_srcdir + "/gflags_unittest_flagfile"; #endif static const string flagfile_flag = string("--flagfile=") + flagfile; return flagfile_flag.c_str(); } // Defining a variable of type CompileAssertTypesEqual will cause a // compiler error iff T1 and T2 are different types. template struct CompileAssertTypesEqual; template struct CompileAssertTypesEqual { }; template void AssertIsType(Actual& x) { CompileAssertTypesEqual(); } // Verify all the flags are the right type. TEST(FlagTypes, FlagTypes) { AssertIsType(FLAGS_test_bool); AssertIsType(FLAGS_test_int32); AssertIsType(FLAGS_test_int64); AssertIsType(FLAGS_test_uint32); AssertIsType(FLAGS_test_uint64); AssertIsType(FLAGS_test_double); AssertIsType(FLAGS_test_string); } #ifdef GTEST_HAS_DEATH_TEST // Death tests for "help" options. // // The help system automatically calls gflags_exitfunc(1) when you specify any of // the help-related flags ("-helpmatch", "-helpxml") so we can't test // those mainline. // Tests that "-helpmatch" causes the process to die. TEST(ReadFlagsFromStringDeathTest, HelpMatch) { EXPECT_DEATH(ReadFlagsFromString("-helpmatch=base", GetArgv0(), true), ""); } // Tests that "-helpxml" causes the process to die. TEST(ReadFlagsFromStringDeathTest, HelpXml) { EXPECT_DEATH(ReadFlagsFromString("-helpxml", GetArgv0(), true), ""); } #endif // A subroutine needed for testing reading flags from a string. void TestFlagString(const string& flags, const string& expected_string, bool expected_bool, int32 expected_int32, double expected_double) { EXPECT_TRUE(ReadFlagsFromString(flags, GetArgv0(), // errors are fatal true)); EXPECT_EQ(expected_string, FLAGS_test_string); EXPECT_EQ(expected_bool, FLAGS_test_bool); EXPECT_EQ(expected_int32, FLAGS_test_int32); EXPECT_DOUBLE_EQ(expected_double, FLAGS_test_double); } // Tests reading flags from a string. TEST(FlagFileTest, ReadFlagsFromString) { TestFlagString( // Flag string "-test_string=continued\n" "# some comments are in order\n" "# some\n" " # comments\n" "#are\n" " #trickier\n" "# than others\n" "-test_bool=true\n" " -test_int32=1\n" "-test_double=0.0\n", // Expected values "continued", true, 1, 0.0); TestFlagString( // Flag string "# let's make sure it can update values\n" "-test_string=initial\n" "-test_bool=false\n" "-test_int32=123\n" "-test_double=123.0\n", // Expected values "initial", false, 123, 123.0); // Test that flags can use dashes instead of underscores. TestFlagString( // Flag string "-test-string=initial\n" "--test-bool=false\n" "--test-int32=123\n" "--test-double=123.0\n", // Expected values "initial", false, 123, 123.0); } // Tests the filename part of the flagfile TEST(FlagFileTest, FilenamesOurfileLast) { FLAGS_test_string = "initial"; FLAGS_test_bool = false; FLAGS_test_int32 = -1; FLAGS_test_double = -1.0; TestFlagString( // Flag string "-test_string=continued\n" "# some comments are in order\n" "# some\n" " # comments\n" "#are\n" " #trickier\n" "# than others\n" "not_our_filename\n" "-test_bool=true\n" " -test_int32=1\n" "gflags_unittest\n" "-test_double=1000.0\n", // Expected values "continued", false, -1, 1000.0); } TEST(FlagFileTest, FilenamesOurfileFirst) { FLAGS_test_string = "initial"; FLAGS_test_bool = false; FLAGS_test_int32 = -1; FLAGS_test_double = -1.0; TestFlagString( // Flag string "-test_string=continued\n" "# some comments are in order\n" "# some\n" " # comments\n" "#are\n" " #trickier\n" "# than others\n" "gflags_unittest\n" "-test_bool=true\n" " -test_int32=1\n" "not_our_filename\n" "-test_double=1000.0\n", // Expected values "continued", true, 1, -1.0); } #if defined(HAVE_FNMATCH_H) || defined(HAVE_SHLWAPI_H) // otherwise glob isn't supported TEST(FlagFileTest, FilenamesOurfileGlob) { FLAGS_test_string = "initial"; FLAGS_test_bool = false; FLAGS_test_int32 = -1; FLAGS_test_double = -1.0; TestFlagString( // Flag string "-test_string=continued\n" "# some comments are in order\n" "# some\n" " # comments\n" "#are\n" " #trickier\n" "# than others\n" "*flags*\n" "-test_bool=true\n" " -test_int32=1\n" "flags\n" "-test_double=1000.0\n", // Expected values "continued", true, 1, -1.0); } TEST(FlagFileTest, FilenamesOurfileInBigList) { FLAGS_test_string = "initial"; FLAGS_test_bool = false; FLAGS_test_int32 = -1; FLAGS_test_double = -1.0; TestFlagString( // Flag string "-test_string=continued\n" "# some comments are in order\n" "# some\n" " # comments\n" "#are\n" " #trickier\n" "# than others\n" "*first* *flags* *third*\n" "-test_bool=true\n" " -test_int32=1\n" "flags\n" "-test_double=1000.0\n", // Expected values "continued", true, 1, -1.0); } #endif // defined(HAVE_FNMATCH_H) || defined(HAVE_SHLWAPI_H) // Tests that a failed flag-from-string read keeps flags at default values TEST(FlagFileTest, FailReadFlagsFromString) { FLAGS_test_int32 = 119; string flags("# let's make sure it can update values\n" "-test_string=non_initial\n" "-test_bool=false\n" "-test_int32=123\n" "-test_double=illegal\n"); EXPECT_FALSE(ReadFlagsFromString(flags, GetArgv0(), // errors are fatal false)); EXPECT_EQ(119, FLAGS_test_int32); EXPECT_EQ("initial", FLAGS_test_string); } // Tests that flags can be set to ordinary values. TEST(SetFlagValueTest, OrdinaryValues) { EXPECT_EQ("initial", FLAGS_test_str1); SetCommandLineOptionWithMode("test_str1", "second", SET_FLAG_IF_DEFAULT); EXPECT_EQ("second", FLAGS_test_str1); // set; was default SetCommandLineOptionWithMode("test_str1", "third", SET_FLAG_IF_DEFAULT); EXPECT_EQ("second", FLAGS_test_str1); // already set once FLAGS_test_str1 = "initial"; SetCommandLineOptionWithMode("test_str1", "third", SET_FLAG_IF_DEFAULT); EXPECT_EQ("initial", FLAGS_test_str1); // still already set before SetCommandLineOptionWithMode("test_str1", "third", SET_FLAGS_VALUE); EXPECT_EQ("third", FLAGS_test_str1); // changed value SetCommandLineOptionWithMode("test_str1", "fourth", SET_FLAGS_DEFAULT); EXPECT_EQ("third", FLAGS_test_str1); // value not changed (already set before) EXPECT_EQ("initial", FLAGS_test_str2); SetCommandLineOptionWithMode("test_str2", "second", SET_FLAGS_DEFAULT); EXPECT_EQ("second", FLAGS_test_str2); // changed (was default) FLAGS_test_str2 = "extra"; EXPECT_EQ("extra", FLAGS_test_str2); FLAGS_test_str2 = "second"; SetCommandLineOptionWithMode("test_str2", "third", SET_FLAGS_DEFAULT); EXPECT_EQ("third", FLAGS_test_str2); // still changed (was equal to default) SetCommandLineOptionWithMode("test_str2", "fourth", SET_FLAG_IF_DEFAULT); EXPECT_EQ("fourth", FLAGS_test_str2); // changed (was default) EXPECT_EQ("initial", FLAGS_test_str3); SetCommandLineOptionWithMode("test_str3", "second", SET_FLAGS_DEFAULT); EXPECT_EQ("second", FLAGS_test_str3); // changed FLAGS_test_str3 = "third"; SetCommandLineOptionWithMode("test_str3", "fourth", SET_FLAGS_DEFAULT); EXPECT_EQ("third", FLAGS_test_str3); // not changed (was set) SetCommandLineOptionWithMode("test_str3", "fourth", SET_FLAG_IF_DEFAULT); EXPECT_EQ("third", FLAGS_test_str3); // not changed (was set) SetCommandLineOptionWithMode("test_str3", "fourth", SET_FLAGS_VALUE); EXPECT_EQ("fourth", FLAGS_test_str3); // changed value } // Tests that flags can be set to exceptional values. // Note: apparently MINGW doesn't parse inf and nan correctly: // http://www.mail-archive.com/bug-gnulib@gnu.org/msg09573.html // This url says FreeBSD also has a problem, but I didn't see that. TEST(SetFlagValueTest, ExceptionalValues) { #if defined(isinf) && !defined(__MINGW32__) EXPECT_EQ("test_double set to inf\n", SetCommandLineOption("test_double", "inf")); EXPECT_INF(FLAGS_test_double); EXPECT_EQ("test_double set to inf\n", SetCommandLineOption("test_double", "INF")); EXPECT_INF(FLAGS_test_double); #endif // set some bad values EXPECT_EQ("", SetCommandLineOption("test_double", "0.1xxx")); EXPECT_EQ("", SetCommandLineOption("test_double", " ")); EXPECT_EQ("", SetCommandLineOption("test_double", "")); #if defined(isinf) && !defined(__MINGW32__) EXPECT_EQ("test_double set to -inf\n", SetCommandLineOption("test_double", "-inf")); EXPECT_INF(FLAGS_test_double); EXPECT_GT(0, FLAGS_test_double); #endif #if defined(isnan) && !defined(__MINGW32__) EXPECT_EQ("test_double set to nan\n", SetCommandLineOption("test_double", "NaN")); EXPECT_NAN(FLAGS_test_double); #endif } // Tests that integer flags can be specified in many ways TEST(SetFlagValueTest, DifferentRadices) { EXPECT_EQ("test_int32 set to 12\n", SetCommandLineOption("test_int32", "12")); EXPECT_EQ("test_int32 set to 16\n", SetCommandLineOption("test_int32", "0x10")); EXPECT_EQ("test_int32 set to 34\n", SetCommandLineOption("test_int32", "0X22")); // Leading 0 is *not* octal; it's still decimal EXPECT_EQ("test_int32 set to 10\n", SetCommandLineOption("test_int32", "010")); } // Tests what happens when you try to set a flag to an illegal value TEST(SetFlagValueTest, IllegalValues) { FLAGS_test_bool = true; FLAGS_test_int32 = 119; FLAGS_test_int64 = 1191; FLAGS_test_uint32 = 11911; FLAGS_test_uint64 = 119111; EXPECT_EQ("", SetCommandLineOption("test_bool", "12")); EXPECT_EQ("", SetCommandLineOption("test_uint32", "-1970")); EXPECT_EQ("", SetCommandLineOption("test_int32", "7000000000000")); EXPECT_EQ("", SetCommandLineOption("test_uint64", "-1")); EXPECT_EQ("", SetCommandLineOption("test_int64", "not a number!")); // Test the empty string with each type of input EXPECT_EQ("", SetCommandLineOption("test_bool", "")); EXPECT_EQ("", SetCommandLineOption("test_int32", "")); EXPECT_EQ("", SetCommandLineOption("test_int64", "")); EXPECT_EQ("", SetCommandLineOption("test_uint32", "")); EXPECT_EQ("", SetCommandLineOption("test_uint64", "")); EXPECT_EQ("", SetCommandLineOption("test_double", "")); EXPECT_EQ("test_string set to \n", SetCommandLineOption("test_string", "")); EXPECT_TRUE(FLAGS_test_bool); EXPECT_EQ(119, FLAGS_test_int32); EXPECT_EQ(1191, FLAGS_test_int64); EXPECT_EQ(11911, FLAGS_test_uint32); EXPECT_EQ(119111, FLAGS_test_uint64); } // Tests that we only evaluate macro args once TEST(MacroArgs, EvaluateOnce) { EXPECT_EQ(13, FLAGS_changeable_var); // Make sure we don't ++ the value somehow, when evaluating the flag. EXPECT_EQ(13, FLAGS_changeable_var); // Make sure the macro only evaluated this var once. EXPECT_EQ(13, changeable_var); // Make sure the actual value and default value are the same SetCommandLineOptionWithMode("changeable_var", "21", SET_FLAG_IF_DEFAULT); EXPECT_EQ(21, FLAGS_changeable_var); } TEST(MacroArgs, EvaluateOnceBool) { EXPECT_TRUE(FLAGS_changeable_bool_var); EXPECT_TRUE(FLAGS_changeable_bool_var); EXPECT_EQ(8009, changeable_bool_var); SetCommandLineOptionWithMode("changeable_bool_var", "false", SET_FLAG_IF_DEFAULT); EXPECT_FALSE(FLAGS_changeable_bool_var); } TEST(MacroArgs, EvaluateOnceStrings) { EXPECT_EQ("1", FLAGS_changeable_string_var); EXPECT_EQ("1", FLAGS_changeable_string_var); EXPECT_EQ(1, changeable_string_var); SetCommandLineOptionWithMode("changeable_string_var", "different", SET_FLAG_IF_DEFAULT); EXPECT_EQ("different", FLAGS_changeable_string_var); } // Tests that the FooFromEnv does the right thing TEST(FromEnvTest, LegalValues) { setenv("BOOL_VAL1", "true", 1); setenv("BOOL_VAL2", "false", 1); setenv("BOOL_VAL3", "1", 1); setenv("BOOL_VAL4", "F", 1); EXPECT_TRUE(BoolFromEnv("BOOL_VAL1", false)); EXPECT_FALSE(BoolFromEnv("BOOL_VAL2", true)); EXPECT_TRUE(BoolFromEnv("BOOL_VAL3", false)); EXPECT_FALSE(BoolFromEnv("BOOL_VAL4", true)); EXPECT_TRUE(BoolFromEnv("BOOL_VAL_UNKNOWN", true)); EXPECT_FALSE(BoolFromEnv("BOOL_VAL_UNKNOWN", false)); setenv("INT_VAL1", "1", 1); setenv("INT_VAL2", "-1", 1); EXPECT_EQ(1, Int32FromEnv("INT_VAL1", 10)); EXPECT_EQ(-1, Int32FromEnv("INT_VAL2", 10)); EXPECT_EQ(10, Int32FromEnv("INT_VAL_UNKNOWN", 10)); setenv("INT_VAL3", "4294967295", 1); EXPECT_EQ(1, Uint32FromEnv("INT_VAL1", 10)); EXPECT_EQ(4294967295L, Uint32FromEnv("INT_VAL3", 30)); EXPECT_EQ(10, Uint32FromEnv("INT_VAL_UNKNOWN", 10)); setenv("INT_VAL4", "1099511627776", 1); EXPECT_EQ(1, Int64FromEnv("INT_VAL1", 20)); EXPECT_EQ(-1, Int64FromEnv("INT_VAL2", 20)); EXPECT_EQ(1099511627776LL, Int64FromEnv("INT_VAL4", 20)); EXPECT_EQ(20, Int64FromEnv("INT_VAL_UNKNOWN", 20)); EXPECT_EQ(1, Uint64FromEnv("INT_VAL1", 30)); EXPECT_EQ(1099511627776ULL, Uint64FromEnv("INT_VAL4", 30)); EXPECT_EQ(30, Uint64FromEnv("INT_VAL_UNKNOWN", 30)); // I pick values here that can be easily represented exactly in floating-point setenv("DOUBLE_VAL1", "0.0", 1); setenv("DOUBLE_VAL2", "1.0", 1); setenv("DOUBLE_VAL3", "-1.0", 1); EXPECT_EQ(0.0, DoubleFromEnv("DOUBLE_VAL1", 40.0)); EXPECT_EQ(1.0, DoubleFromEnv("DOUBLE_VAL2", 40.0)); EXPECT_EQ(-1.0, DoubleFromEnv("DOUBLE_VAL3", 40.0)); EXPECT_EQ(40.0, DoubleFromEnv("DOUBLE_VAL_UNKNOWN", 40.0)); setenv("STRING_VAL1", "", 1); setenv("STRING_VAL2", "my happy string!", 1); EXPECT_STREQ("", StringFromEnv("STRING_VAL1", "unknown")); EXPECT_STREQ("my happy string!", StringFromEnv("STRING_VAL2", "unknown")); EXPECT_STREQ("unknown", StringFromEnv("STRING_VAL_UNKNOWN", "unknown")); } #ifdef GTEST_HAS_DEATH_TEST // Tests that the FooFromEnv dies on parse-error TEST(FromEnvDeathTest, IllegalValues) { setenv("BOOL_BAD1", "so true!", 1); setenv("BOOL_BAD2", "", 1); EXPECT_DEATH(BoolFromEnv("BOOL_BAD1", false), "error parsing env variable"); EXPECT_DEATH(BoolFromEnv("BOOL_BAD2", true), "error parsing env variable"); setenv("INT_BAD1", "one", 1); setenv("INT_BAD2", "100000000000000000", 1); setenv("INT_BAD3", "0xx10", 1); setenv("INT_BAD4", "", 1); EXPECT_DEATH(Int32FromEnv("INT_BAD1", 10), "error parsing env variable"); EXPECT_DEATH(Int32FromEnv("INT_BAD2", 10), "error parsing env variable"); EXPECT_DEATH(Int32FromEnv("INT_BAD3", 10), "error parsing env variable"); EXPECT_DEATH(Int32FromEnv("INT_BAD4", 10), "error parsing env variable"); EXPECT_DEATH(Uint32FromEnv("INT_BAD1", 10), "error parsing env variable"); EXPECT_DEATH(Uint32FromEnv("INT_BAD2", 10), "error parsing env variable"); EXPECT_DEATH(Uint32FromEnv("INT_BAD3", 10), "error parsing env variable"); EXPECT_DEATH(Uint32FromEnv("INT_BAD4", 10), "error parsing env variable"); setenv("BIGINT_BAD1", "18446744073709551616000", 1); EXPECT_DEATH(Int64FromEnv("INT_BAD1", 20), "error parsing env variable"); EXPECT_DEATH(Int64FromEnv("INT_BAD3", 20), "error parsing env variable"); EXPECT_DEATH(Int64FromEnv("INT_BAD4", 20), "error parsing env variable"); EXPECT_DEATH(Int64FromEnv("BIGINT_BAD1", 200), "error parsing env variable"); setenv("BIGINT_BAD2", "-1", 1); EXPECT_DEATH(Uint64FromEnv("INT_BAD1", 30), "error parsing env variable"); EXPECT_DEATH(Uint64FromEnv("INT_BAD3", 30), "error parsing env variable"); EXPECT_DEATH(Uint64FromEnv("INT_BAD4", 30), "error parsing env variable"); EXPECT_DEATH(Uint64FromEnv("BIGINT_BAD1", 30), "error parsing env variable"); // TODO(csilvers): uncomment this when we disallow negative numbers for uint64 #if 0 EXPECT_DEATH(Uint64FromEnv("BIGINT_BAD2", 30), "error parsing env variable"); #endif setenv("DOUBLE_BAD1", "0.0.0", 1); setenv("DOUBLE_BAD2", "", 1); EXPECT_DEATH(DoubleFromEnv("DOUBLE_BAD1", 40.0), "error parsing env variable"); EXPECT_DEATH(DoubleFromEnv("DOUBLE_BAD2", 40.0), "error parsing env variable"); } #endif // Tests that FlagSaver can save the states of string flags. TEST(FlagSaverTest, CanSaveStringFlagStates) { // 1. Initializes the flags. // State of flag test_str1: // default value - "initial" // current value - "initial" // not set - true SetCommandLineOptionWithMode("test_str2", "second", SET_FLAGS_VALUE); // State of flag test_str2: // default value - "initial" // current value - "second" // not set - false SetCommandLineOptionWithMode("test_str3", "second", SET_FLAGS_DEFAULT); // State of flag test_str3: // default value - "second" // current value - "second" // not set - true // 2. Saves the flag states. { FlagSaver fs; // 3. Modifies the flag states. SetCommandLineOptionWithMode("test_str1", "second", SET_FLAGS_VALUE); EXPECT_EQ("second", FLAGS_test_str1); // State of flag test_str1: // default value - "second" // current value - "second" // not set - true SetCommandLineOptionWithMode("test_str2", "third", SET_FLAGS_DEFAULT); EXPECT_EQ("second", FLAGS_test_str2); // State of flag test_str2: // default value - "third" // current value - "second" // not set - false SetCommandLineOptionWithMode("test_str3", "third", SET_FLAGS_VALUE); EXPECT_EQ("third", FLAGS_test_str3); // State of flag test_str1: // default value - "second" // current value - "third" // not set - false // 4. Restores the flag states. } // 5. Verifies that the states were restored. // Verifies that the value of test_str1 was restored. EXPECT_EQ("initial", FLAGS_test_str1); // Verifies that the "not set" attribute of test_str1 was restored to true. SetCommandLineOptionWithMode("test_str1", "second", SET_FLAG_IF_DEFAULT); EXPECT_EQ("second", FLAGS_test_str1); // Verifies that the value of test_str2 was restored. EXPECT_EQ("second", FLAGS_test_str2); // Verifies that the "not set" attribute of test_str2 was restored to false. SetCommandLineOptionWithMode("test_str2", "fourth", SET_FLAG_IF_DEFAULT); EXPECT_EQ("second", FLAGS_test_str2); // Verifies that the value of test_str3 was restored. EXPECT_EQ("second", FLAGS_test_str3); // Verifies that the "not set" attribute of test_str3 was restored to true. SetCommandLineOptionWithMode("test_str3", "fourth", SET_FLAG_IF_DEFAULT); EXPECT_EQ("fourth", FLAGS_test_str3); } // Tests that FlagSaver can save the values of various-typed flags. TEST(FlagSaverTest, CanSaveVariousTypedFlagValues) { // Initializes the flags. FLAGS_test_bool = false; FLAGS_test_int32 = -1; FLAGS_test_uint32 = 2; FLAGS_test_int64 = -3; FLAGS_test_uint64 = 4; FLAGS_test_double = 5.0; FLAGS_test_string = "good"; // Saves the flag states. { FlagSaver fs; // Modifies the flags. FLAGS_test_bool = true; FLAGS_test_int32 = -5; FLAGS_test_uint32 = 6; FLAGS_test_int64 = -7; FLAGS_test_uint64 = 8; FLAGS_test_double = 8.0; FLAGS_test_string = "bad"; // Restores the flag states. } // Verifies the flag values were restored. EXPECT_FALSE(FLAGS_test_bool); EXPECT_EQ(-1, FLAGS_test_int32); EXPECT_EQ(2, FLAGS_test_uint32); EXPECT_EQ(-3, FLAGS_test_int64); EXPECT_EQ(4, FLAGS_test_uint64); EXPECT_DOUBLE_EQ(5.0, FLAGS_test_double); EXPECT_EQ("good", FLAGS_test_string); } TEST(GetAllFlagsTest, BaseTest) { vector flags; GetAllFlags(&flags); bool found_test_bool = false; vector::const_iterator i; for (i = flags.begin(); i != flags.end(); ++i) { if (i->name == "test_bool") { found_test_bool = true; EXPECT_EQ(i->type, "bool"); EXPECT_EQ(i->default_value, "false"); EXPECT_EQ(i->flag_ptr, &FLAGS_test_bool); break; } } EXPECT_TRUE(found_test_bool); } TEST(ShowUsageWithFlagsTest, BaseTest) { // TODO(csilvers): test this by allowing output other than to stdout. // Not urgent since this functionality is tested via // gflags_unittest.sh, though only through use of --help. } TEST(ShowUsageWithFlagsRestrictTest, BaseTest) { // TODO(csilvers): test this by allowing output other than to stdout. // Not urgent since this functionality is tested via // gflags_unittest.sh, though only through use of --helpmatch. } // Note: all these argv-based tests depend on SetArgv being called // before ParseCommandLineFlags() in main(), below. TEST(GetArgvsTest, BaseTest) { vector argvs = GetArgvs(); EXPECT_EQ(4, argvs.size()); EXPECT_EQ("/test/argv/for/gflags_unittest", argvs[0]); EXPECT_EQ("argv 2", argvs[1]); EXPECT_EQ("3rd argv", argvs[2]); EXPECT_EQ("argv #4", argvs[3]); } TEST(GetArgvTest, BaseTest) { EXPECT_STREQ("/test/argv/for/gflags_unittest " "argv 2 3rd argv argv #4", GetArgv()); } TEST(GetArgv0Test, BaseTest) { EXPECT_STREQ("/test/argv/for/gflags_unittest", GetArgv0()); } TEST(GetArgvSumTest, BaseTest) { // This number is just the sum of the ASCII values of all the chars // in GetArgv(). EXPECT_EQ(4904, GetArgvSum()); } TEST(ProgramInvocationNameTest, BaseTest) { EXPECT_STREQ("/test/argv/for/gflags_unittest", ProgramInvocationName()); } TEST(ProgramInvocationShortNameTest, BaseTest) { EXPECT_STREQ("gflags_unittest", ProgramInvocationShortName()); } TEST(ProgramUsageTest, BaseTest) { // Depends on 1st arg to ParseCommandLineFlags() EXPECT_STREQ("/test/argv/for/gflags_unittest: " " [...]\nDoes something useless.\n", ProgramUsage()); } TEST(GetCommandLineOptionTest, NameExistsAndIsDefault) { string value("will be changed"); bool r = GetCommandLineOption("test_bool", &value); EXPECT_TRUE(r); EXPECT_EQ("false", value); r = GetCommandLineOption("test_int32", &value); EXPECT_TRUE(r); EXPECT_EQ("-1", value); } TEST(GetCommandLineOptionTest, NameExistsAndWasAssigned) { FLAGS_test_int32 = 400; string value("will be changed"); const bool r = GetCommandLineOption("test_int32", &value); EXPECT_TRUE(r); EXPECT_EQ("400", value); } TEST(GetCommandLineOptionTest, NameExistsAndWasSet) { SetCommandLineOption("test_int32", "700"); string value("will be changed"); const bool r = GetCommandLineOption("test_int32", &value); EXPECT_TRUE(r); EXPECT_EQ("700", value); } TEST(GetCommandLineOptionTest, NameExistsAndWasNotSet) { // This doesn't set the flag's value, but rather its default value. // is_default is still true, but the 'default' value returned has changed! SetCommandLineOptionWithMode("test_int32", "800", SET_FLAGS_DEFAULT); string value("will be changed"); const bool r = GetCommandLineOption("test_int32", &value); EXPECT_TRUE(r); EXPECT_EQ("800", value); EXPECT_TRUE(GetCommandLineFlagInfoOrDie("test_int32").is_default); } TEST(GetCommandLineOptionTest, NameExistsAndWasConditionallySet) { SetCommandLineOptionWithMode("test_int32", "900", SET_FLAG_IF_DEFAULT); string value("will be changed"); const bool r = GetCommandLineOption("test_int32", &value); EXPECT_TRUE(r); EXPECT_EQ("900", value); } TEST(GetCommandLineOptionTest, NameDoesNotExist) { string value("will not be changed"); const bool r = GetCommandLineOption("test_int3210", &value); EXPECT_FALSE(r); EXPECT_EQ("will not be changed", value); } TEST(GetCommandLineFlagInfoTest, FlagExists) { CommandLineFlagInfo info; bool r = GetCommandLineFlagInfo("test_int32", &info); EXPECT_TRUE(r); EXPECT_EQ("test_int32", info.name); EXPECT_EQ("int32", info.type); EXPECT_EQ("", info.description); EXPECT_EQ("-1", info.current_value); EXPECT_EQ("-1", info.default_value); EXPECT_TRUE(info.is_default); EXPECT_FALSE(info.has_validator_fn); EXPECT_EQ(&FLAGS_test_int32, info.flag_ptr); FLAGS_test_bool = true; r = GetCommandLineFlagInfo("test_bool", &info); EXPECT_TRUE(r); EXPECT_EQ("test_bool", info.name); EXPECT_EQ("bool", info.type); EXPECT_EQ("tests bool-ness", info.description); EXPECT_EQ("true", info.current_value); EXPECT_EQ("false", info.default_value); EXPECT_FALSE(info.is_default); EXPECT_FALSE(info.has_validator_fn); EXPECT_EQ(&FLAGS_test_bool, info.flag_ptr); FLAGS_test_bool = false; r = GetCommandLineFlagInfo("test_bool", &info); EXPECT_TRUE(r); EXPECT_EQ("test_bool", info.name); EXPECT_EQ("bool", info.type); EXPECT_EQ("tests bool-ness", info.description); EXPECT_EQ("false", info.current_value); EXPECT_EQ("false", info.default_value); EXPECT_FALSE(info.is_default); // value is same, but flag *was* modified EXPECT_FALSE(info.has_validator_fn); EXPECT_EQ(&FLAGS_test_bool, info.flag_ptr); } TEST(GetCommandLineFlagInfoTest, FlagDoesNotExist) { CommandLineFlagInfo info; // Set to some random values that GetCommandLineFlagInfo should not change info.name = "name"; info.type = "type"; info.current_value = "curr"; info.default_value = "def"; info.filename = "/"; info.is_default = false; info.has_validator_fn = true; info.flag_ptr = NULL; bool r = GetCommandLineFlagInfo("test_int3210", &info); EXPECT_FALSE(r); EXPECT_EQ("name", info.name); EXPECT_EQ("type", info.type); EXPECT_EQ("", info.description); EXPECT_EQ("curr", info.current_value); EXPECT_EQ("def", info.default_value); EXPECT_EQ("/", info.filename); EXPECT_FALSE(info.is_default); EXPECT_TRUE(info.has_validator_fn); EXPECT_EQ(NULL, info.flag_ptr); } TEST(GetCommandLineFlagInfoOrDieTest, FlagExistsAndIsDefault) { CommandLineFlagInfo info; info = GetCommandLineFlagInfoOrDie("test_int32"); EXPECT_EQ("test_int32", info.name); EXPECT_EQ("int32", info.type); EXPECT_EQ("", info.description); EXPECT_EQ("-1", info.current_value); EXPECT_EQ("-1", info.default_value); EXPECT_TRUE(info.is_default); EXPECT_EQ(&FLAGS_test_int32, info.flag_ptr); info = GetCommandLineFlagInfoOrDie("test_bool"); EXPECT_EQ("test_bool", info.name); EXPECT_EQ("bool", info.type); EXPECT_EQ("tests bool-ness", info.description); EXPECT_EQ("false", info.current_value); EXPECT_EQ("false", info.default_value); EXPECT_TRUE(info.is_default); EXPECT_FALSE(info.has_validator_fn); EXPECT_EQ(&FLAGS_test_bool, info.flag_ptr); } TEST(GetCommandLineFlagInfoOrDieTest, FlagExistsAndWasAssigned) { FLAGS_test_int32 = 400; CommandLineFlagInfo info; info = GetCommandLineFlagInfoOrDie("test_int32"); EXPECT_EQ("test_int32", info.name); EXPECT_EQ("int32", info.type); EXPECT_EQ("", info.description); EXPECT_EQ("400", info.current_value); EXPECT_EQ("-1", info.default_value); EXPECT_FALSE(info.is_default); EXPECT_EQ(&FLAGS_test_int32, info.flag_ptr); FLAGS_test_bool = true; info = GetCommandLineFlagInfoOrDie("test_bool"); EXPECT_EQ("test_bool", info.name); EXPECT_EQ("bool", info.type); EXPECT_EQ("tests bool-ness", info.description); EXPECT_EQ("true", info.current_value); EXPECT_EQ("false", info.default_value); EXPECT_FALSE(info.is_default); EXPECT_FALSE(info.has_validator_fn); EXPECT_EQ(&FLAGS_test_bool, info.flag_ptr); } #ifdef GTEST_HAS_DEATH_TEST TEST(GetCommandLineFlagInfoOrDieDeathTest, FlagDoesNotExist) { EXPECT_DEATH(GetCommandLineFlagInfoOrDie("test_int3210"), ".*: flag test_int3210 does not exist"); } #endif // These are lightly tested because they're deprecated. Basically, // the tests are meant to cover how existing users use these functions, // but not necessarily how new users could use them. TEST(DeprecatedFunctionsTest, CommandlineFlagsIntoString) { string s = CommandlineFlagsIntoString(); EXPECT_NE(string::npos, s.find("--test_bool=")); } TEST(DeprecatedFunctionsTest, AppendFlagsIntoFile) { FLAGS_test_int32 = 10; // just to make the test more interesting string filename(TmpFile("flagfile")); unlink(filename.c_str()); // just to be safe const bool r = AppendFlagsIntoFile(filename, "not the real argv0"); EXPECT_TRUE(r); FILE* fp; EXPECT_EQ(0, SafeFOpen(&fp, filename.c_str(), "r")); EXPECT_TRUE(fp != NULL); char line[8192]; EXPECT_TRUE(fgets(line, sizeof(line)-1, fp) != NULL); // get the first line // First line should be progname. EXPECT_STREQ("not the real argv0\n", line); bool found_bool = false, found_int32 = false; while (fgets(line, sizeof(line)-1, fp)) { line[sizeof(line)-1] = '\0'; // just to be safe if (strcmp(line, "--test_bool=false\n") == 0) found_bool = true; if (strcmp(line, "--test_int32=10\n") == 0) found_int32 = true; } EXPECT_TRUE(found_int32); EXPECT_TRUE(found_bool); fclose(fp); } TEST(DeprecatedFunctionsTest, ReadFromFlagsFile) { FLAGS_test_int32 = -10; // just to make the test more interesting string filename(TmpFile("flagfile2")); unlink(filename.c_str()); // just to be safe bool r = AppendFlagsIntoFile(filename, GetArgv0()); EXPECT_TRUE(r); FLAGS_test_int32 = -11; r = ReadFromFlagsFile(filename, GetArgv0(), true); EXPECT_TRUE(r); EXPECT_EQ(-10, FLAGS_test_int32); } // unnamed namespace TEST(DeprecatedFunctionsTest, ReadFromFlagsFileFailure) { FLAGS_test_int32 = -20; string filename(TmpFile("flagfile3")); FILE* fp; EXPECT_EQ(0, SafeFOpen(&fp, filename.c_str(), "w")); EXPECT_TRUE(fp != NULL); // Note the error in the bool assignment below... fprintf(fp, "%s\n--test_int32=-21\n--test_bool=not_a_bool!\n", GetArgv0()); fclose(fp); FLAGS_test_int32 = -22; const bool r = ReadFromFlagsFile(filename, GetArgv0(), false); EXPECT_FALSE(r); EXPECT_EQ(-22, FLAGS_test_int32); // the -21 from the flagsfile didn't take } TEST(FlagsSetBeforeInitTest, TryFromEnv) { EXPECT_EQ("pre-set", FLAGS_test_tryfromenv); } // The following test case verifies that ParseCommandLineFlags() and // ParseCommandLineNonHelpFlags() uses the last definition of a flag // in case it's defined more than once. DEFINE_int32(test_flag, -1, "used for testing gflags.cc"); // Parses and returns the --test_flag flag. // If with_help is true, calls ParseCommandLineFlags; otherwise calls // ParseCommandLineNonHelpFlags. int32 ParseTestFlag(bool with_help, int argc, const char** const_argv) { FlagSaver fs; // Restores the flags before returning. // Makes a copy of the input array s.t. it can be reused // (ParseCommandLineFlags() will alter the array). char** const argv_save = new char*[argc + 1]; char** argv = argv_save; memcpy(argv, const_argv, sizeof(*argv)*(argc + 1)); if (with_help) { ParseCommandLineFlags(&argc, &argv, true); } else { ParseCommandLineNonHelpFlags(&argc, &argv, true); } delete[] argv_save; return FLAGS_test_flag; } TEST(ParseCommandLineFlagsUsesLastDefinitionTest, WhenFlagIsDefinedTwiceOnCommandLine) { const char* argv[] = { "my_test", "--test_flag=1", "--test_flag=2", NULL, }; EXPECT_EQ(2, ParseTestFlag(true, arraysize(argv) - 1, argv)); EXPECT_EQ(2, ParseTestFlag(false, arraysize(argv) - 1, argv)); } TEST(ParseCommandLineFlagsUsesLastDefinitionTest, WhenFlagIsDefinedTwiceInFlagFile) { const char* argv[] = { "my_test", GetFlagFileFlag(), NULL, }; EXPECT_EQ(2, ParseTestFlag(true, arraysize(argv) - 1, argv)); EXPECT_EQ(2, ParseTestFlag(false, arraysize(argv) - 1, argv)); } TEST(ParseCommandLineFlagsUsesLastDefinitionTest, WhenFlagIsDefinedInCommandLineAndThenFlagFile) { const char* argv[] = { "my_test", "--test_flag=0", GetFlagFileFlag(), NULL, }; EXPECT_EQ(2, ParseTestFlag(true, arraysize(argv) - 1, argv)); EXPECT_EQ(2, ParseTestFlag(false, arraysize(argv) - 1, argv)); } TEST(ParseCommandLineFlagsUsesLastDefinitionTest, WhenFlagIsDefinedInFlagFileAndThenCommandLine) { const char* argv[] = { "my_test", GetFlagFileFlag(), "--test_flag=3", NULL, }; EXPECT_EQ(3, ParseTestFlag(true, arraysize(argv) - 1, argv)); EXPECT_EQ(3, ParseTestFlag(false, arraysize(argv) - 1, argv)); } TEST(ParseCommandLineFlagsUsesLastDefinitionTest, WhenFlagIsDefinedInCommandLineAndFlagFileAndThenCommandLine) { const char* argv[] = { "my_test", "--test_flag=0", GetFlagFileFlag(), "--test_flag=3", NULL, }; EXPECT_EQ(3, ParseTestFlag(true, arraysize(argv) - 1, argv)); EXPECT_EQ(3, ParseTestFlag(false, arraysize(argv) - 1, argv)); } TEST(ParseCommandLineFlagsAndDashArgs, TwoDashArgFirst) { const char* argv[] = { "my_test", "--", "--test_flag=0", NULL, }; EXPECT_EQ(-1, ParseTestFlag(true, arraysize(argv) - 1, argv)); EXPECT_EQ(-1, ParseTestFlag(false, arraysize(argv) - 1, argv)); } TEST(ParseCommandLineFlagsAndDashArgs, TwoDashArgMiddle) { const char* argv[] = { "my_test", "--test_flag=7", "--", "--test_flag=0", NULL, }; EXPECT_EQ(7, ParseTestFlag(true, arraysize(argv) - 1, argv)); EXPECT_EQ(7, ParseTestFlag(false, arraysize(argv) - 1, argv)); } TEST(ParseCommandLineFlagsAndDashArgs, OneDashArg) { const char* argv[] = { "my_test", "-", "--test_flag=0", NULL, }; EXPECT_EQ(0, ParseTestFlag(true, arraysize(argv) - 1, argv)); EXPECT_EQ(0, ParseTestFlag(false, arraysize(argv) - 1, argv)); } #ifdef GTEST_HAS_DEATH_TEST TEST(ParseCommandLineFlagsUnknownFlagDeathTest, FlagIsCompletelyUnknown) { const char* argv[] = { "my_test", "--this_flag_does_not_exist", NULL, }; EXPECT_DEATH(ParseTestFlag(true, arraysize(argv) - 1, argv), "unknown command line flag.*"); EXPECT_DEATH(ParseTestFlag(false, arraysize(argv) - 1, argv), "unknown command line flag.*"); } TEST(ParseCommandLineFlagsUnknownFlagDeathTest, BoolFlagIsCompletelyUnknown) { const char* argv[] = { "my_test", "--nothis_flag_does_not_exist", NULL, }; EXPECT_DEATH(ParseTestFlag(true, arraysize(argv) - 1, argv), "unknown command line flag.*"); EXPECT_DEATH(ParseTestFlag(false, arraysize(argv) - 1, argv), "unknown command line flag.*"); } TEST(ParseCommandLineFlagsUnknownFlagDeathTest, FlagIsNotABool) { const char* argv[] = { "my_test", "--notest_string", NULL, }; EXPECT_DEATH(ParseTestFlag(true, arraysize(argv) - 1, argv), "boolean value .* specified for .* command line flag"); EXPECT_DEATH(ParseTestFlag(false, arraysize(argv) - 1, argv), "boolean value .* specified for .* command line flag"); } #endif TEST(ParseCommandLineFlagsWrongFields, DescriptionIsInvalid) { // These must not be automatic variables, since command line flags // aren't unregistered and gUnit uses FlagSaver to save and restore // command line flags' values. If these are on the stack, then when // later tests attempt to save and restore their values, the stack // addresses of these variables will be overwritten... Stack smash! static bool current_storage; static bool defvalue_storage; FlagRegisterer fr("flag_name", NULL, "filename", ¤t_storage, &defvalue_storage); CommandLineFlagInfo fi; EXPECT_TRUE(GetCommandLineFlagInfo("flag_name", &fi)); EXPECT_EQ("", fi.description); EXPECT_EQ(¤t_storage, fi.flag_ptr); } static bool ValidateTestFlagIs5(const char* flagname, int32 flagval) { if (flagval == 5) return true; printf("%s isn't 5!\n", flagname); return false; } static bool ValidateTestFlagIs10(const char* flagname, int32 flagval) { return flagval == 10; } TEST(FlagsValidator, ValidFlagViaArgv) { const char* argv[] = { "my_test", "--test_flag=5", NULL, }; EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5)); EXPECT_EQ(5, ParseTestFlag(true, arraysize(argv) - 1, argv)); // Undo the flag validator setting EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL)); } TEST(FlagsValidator, ValidFlagViaSetDefault) { EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5)); // SetCommandLineOptionWithMode returns the empty string on error. EXPECT_NE("", SetCommandLineOptionWithMode("test_flag", "5", SET_FLAG_IF_DEFAULT)); EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL)); } TEST(FlagsValidator, ValidFlagViaSetValue) { EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5)); FLAGS_test_flag = 100; // doesn't trigger the validator // SetCommandLineOptionWithMode returns the empty string on error. EXPECT_NE("", SetCommandLineOptionWithMode("test_flag", "5", SET_FLAGS_VALUE)); EXPECT_NE("", SetCommandLineOptionWithMode("test_flag", "5", SET_FLAGS_DEFAULT)); EXPECT_NE("", SetCommandLineOption("test_flag", "5")); EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL)); } #ifdef GTEST_HAS_DEATH_TEST TEST(FlagsValidatorDeathTest, InvalidFlagViaArgv) { const char* argv[] = { "my_test", "--test_flag=50", NULL, }; EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5)); EXPECT_DEATH(ParseTestFlag(true, arraysize(argv) - 1, argv), "ERROR: failed validation of new value '50' for flag 'test_flag'"); EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL)); } #endif TEST(FlagsValidator, InvalidFlagViaSetDefault) { EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5)); // SetCommandLineOptionWithMode returns the empty string on error. EXPECT_EQ("", SetCommandLineOptionWithMode("test_flag", "50", SET_FLAG_IF_DEFAULT)); EXPECT_EQ(-1, FLAGS_test_flag); // the setting-to-50 should have failed EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL)); } TEST(FlagsValidator, InvalidFlagViaSetValue) { EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5)); FLAGS_test_flag = 100; // doesn't trigger the validator // SetCommandLineOptionWithMode returns the empty string on error. EXPECT_EQ("", SetCommandLineOptionWithMode("test_flag", "50", SET_FLAGS_VALUE)); EXPECT_EQ("", SetCommandLineOptionWithMode("test_flag", "50", SET_FLAGS_DEFAULT)); EXPECT_EQ("", SetCommandLineOption("test_flag", "50")); EXPECT_EQ(100, FLAGS_test_flag); // the setting-to-50 should have failed EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL)); } #ifdef GTEST_HAS_DEATH_TEST TEST(FlagsValidatorDeathTest, InvalidFlagNeverSet) { // If a flag keeps its default value, and that default value is // invalid, we should die at argv-parse time. const char* argv[] = { "my_test", NULL, }; EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5)); EXPECT_DEATH(ParseTestFlag(true, arraysize(argv) - 1, argv), "ERROR: --test_flag must be set on the commandline"); } #endif TEST(FlagsValidator, InvalidFlagPtr) { int32 dummy; EXPECT_FALSE(RegisterFlagValidator(NULL, &ValidateTestFlagIs5)); EXPECT_FALSE(RegisterFlagValidator(&dummy, &ValidateTestFlagIs5)); } TEST(FlagsValidator, RegisterValidatorTwice) { EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5)); EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5)); EXPECT_FALSE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs10)); EXPECT_FALSE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs10)); EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5)); EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL)); EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs10)); EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL)); } TEST(FlagsValidator, CommandLineFlagInfo) { CommandLineFlagInfo info; info = GetCommandLineFlagInfoOrDie("test_flag"); EXPECT_FALSE(info.has_validator_fn); EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5)); info = GetCommandLineFlagInfoOrDie("test_flag"); EXPECT_TRUE(info.has_validator_fn); EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL)); info = GetCommandLineFlagInfoOrDie("test_flag"); EXPECT_FALSE(info.has_validator_fn); } TEST(FlagsValidator, FlagSaver) { { FlagSaver fs; EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5)); EXPECT_EQ("", SetCommandLineOption("test_flag", "50")); // fails validation } EXPECT_NE("", SetCommandLineOption("test_flag", "50")); // validator is gone EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5)); { FlagSaver fs; EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL)); EXPECT_NE("", SetCommandLineOption("test_flag", "50")); // no validator } EXPECT_EQ("", SetCommandLineOption("test_flag", "50")); // validator is back } } // unnamed namespace static int main(int argc, char **argv) { // Run unit tests only if called without arguments, otherwise this program // is used by an "external" usage test const bool run_tests = (argc == 1); // We need to call SetArgv before parsing flags, so our "test" argv will // win out over this executable's real argv. That makes running this // test with a real --help flag kinda annoying, unfortunately. const char* test_argv[] = { "/test/argv/for/gflags_unittest", "argv 2", "3rd argv", "argv #4" }; SetArgv(arraysize(test_argv), test_argv); // The first arg is the usage message, also important for testing. string usage_message = (string(GetArgv0()) + ": [...]\nDoes something useless.\n"); // We test setting tryfromenv manually, and making sure // ParseCommandLineFlags still evaluates it. FLAGS_tryfromenv = "test_tryfromenv"; setenv("FLAGS_test_tryfromenv", "pre-set", 1); // Modify flag values from declared default value in two ways. // The recommended way: SetCommandLineOptionWithMode("changed_bool1", "true", SET_FLAGS_DEFAULT); // The non-recommended way: FLAGS_changed_bool2 = true; SetUsageMessage(usage_message); SetVersionString("test_version"); ParseCommandLineFlags(&argc, &argv, true); MakeTmpdir(&FLAGS_test_tmpdir); int exit_status = 0; if (run_tests) { fprintf(stdout, "Running the unit tests now...\n\n"); fflush(stdout); exit_status = RUN_ALL_TESTS(); } else fprintf(stderr, "\n\nPASS\n"); ShutDownCommandLineFlags(); return exit_status; } } // GFLAGS_NAMESPACE int main(int argc, char** argv) { return GFLAGS_NAMESPACE::main(argc, argv); } gflags-2.2.2/test/gflags_unittest_flagfile000066400000000000000000000000341337211647400207220ustar00rootroot00000000000000--test_flag=1 --test_flag=2 gflags-2.2.2/test/nc/000077500000000000000000000000001337211647400143475ustar00rootroot00000000000000gflags-2.2.2/test/nc/CMakeLists.txt000066400000000000000000000007421337211647400171120ustar00rootroot00000000000000## gflags negative compilation tests cmake_minimum_required (VERSION 2.8.12 FATAL_ERROR) if (NOT TEST_NAME) message (FATAL_ERROR "Missing TEST_NAME CMake flag") endif () string (TOUPPER ${TEST_NAME} TEST_NAME_UPPER) project (gflags_${TEST_NAME}) find_package (gflags REQUIRED) include_directories ("${CMAKE_CURRENT_SOURCE_DIR}/..") add_definitions (-DTEST_${TEST_NAME_UPPER}) add_executable (gflags_${TEST_NAME} gflags_nc.cc) target_link_libraries(gflags_${TEST_NAME} gflags) gflags-2.2.2/test/nc/gflags_nc.cc000066400000000000000000000046421337211647400166070ustar00rootroot00000000000000// Copyright (c) 2009, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // --- // // A negative comiple test for gflags. #include #if defined(TEST_NC_SWAPPED_ARGS) DEFINE_bool(some_bool_flag, "the default value should go here, not the description", false); #elif defined(TEST_NC_INT_INSTEAD_OF_BOOL) DEFINE_bool(some_bool_flag_2, 0, "should have been an int32 flag but mistakenly used bool instead"); #elif defined(TEST_NC_BOOL_IN_QUOTES) DEFINE_bool(some_bool_flag_3, "false", "false in in quotes, which is wrong"); #elif defined(TEST_NC_SANITY) DEFINE_bool(some_bool_flag_4, true, "this is the correct usage of DEFINE_bool"); #elif defined(TEST_NC_DEFINE_STRING_WITH_0) DEFINE_string(some_string_flag, 0, "Trying to construct a string by passing 0 would cause a crash."); #endif int main(int, char **) { return 0; }