Commit ab3d7650 authored by Craig Silverstein's avatar Craig Silverstein

* PORTING: Add windows (MSVC) support (csilvers)

	* Comment danger of using GetAllFlags in validators (wojtekm)
	* Add python support for gnu_getopt (hobe)
	* DEFINE_list now accepts a list as a default (dsturtevant)
	* TMPDIR -> TEST_TMPDIR in Makefile, fixing objcopy behavior (csilvers)
	* Fix the 'cp' command to use $(top_srcdir) in the Makefile (csilvers)



git-svn-id: https://gflags.googlecode.com/svn/trunk@34 6586e3c6-dcc4-952a-343f-ff74eb82781d
parent 688ea02a
......@@ -38,6 +38,8 @@ dist_doc_DATA = AUTHORS COPYING ChangeLog INSTALL NEWS README \
## The libraries (.so's) you want to install
lib_LTLIBRARIES =
## The location of the windows project file for each binary we make
WINDOWS_PROJECTS = google-gflags.sln
## unittests you want to run when people type 'make check'.
## TESTS is for binary unittests, check_SCRIPTS for script-based unittests.
......@@ -53,11 +55,12 @@ CLEANFILES =
## vvvv RULES TO MAKE THE LIBRARIES, BINARIES, AND UNITTESTS
GFLAGS_SOURCES = $(gflagsinclude_HEADERS) src/config.h src/mutex.h \
GFLAGS_SOURCES = $(gflagsinclude_HEADERS) src/mutex.h \
src/gflags.cc src/gflags_reporting.cc \
src/gflags_completions.cc
lib_LTLIBRARIES += libgflags.la
WINDOWS_PROJECTS += vsprojects/libgflags/libgflags.vcproj
libgflags_la_SOURCES = $(GFLAGS_SOURCES)
libgflags_la_CXXFLAGS = $(PTHREAD_CFLAGS) -DNDEBUG
libgflags_la_LDFLAGS = $(PTHREAD_CFLAGS)
......@@ -68,7 +71,9 @@ libgflags_nothreads_la_SOURCES = $(GFLAGS_SOURCES)
libgflags_nothreads_la_CXXFLAGS = -DNDEBUG -DNO_THREADS
TESTS += gflags_unittest
gflags_unittest_SOURCES = $(gflagsinclude_HEADERS) src/config.h \
WINDOWS_PROJECTS += vsprojects/gflags_unittest/gflags_unittest.vcproj
gflags_unittest_SOURCES = $(gflagsinclude_HEADERS) \
src/config_for_unittests.h \
src/gflags_unittest.cc
gflags_unittest_CXXFLAGS = $(PTHREAD_CFLAGS)
gflags_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
......@@ -83,21 +88,21 @@ gflags_nothreads_unittest_LDADD = libgflags_nothreads.la
# holds main() has a name ending with -main or _main. To keep the
# Makefile small :-), we test the no-threads version of these.
TESTS += gflags_unittest2
gflags_unittest2_SOURCES = $(gflagsinclude_HEADERS) src/config.h \
gflags_unittest2_SOURCES = $(gflagsinclude_HEADERS) \
src/gflags_unittest-main.cc
gflags_unittest2_LDADD = libgflags_nothreads.la
src/gflags_unittest-main.cc: src/gflags_unittest.cc
rm -f src/gflags_unittest-main.cc
cp -p src/gflags_unittest.cc src/gflags_unittest-main.cc
cp -p $(top_srcdir)/src/gflags_unittest.cc src/gflags_unittest-main.cc
CLEANFILES += src/gflags_unittest-main.cc
TESTS += gflags_unittest3
gflags_unittest3_SOURCES = $(gflagsinclude_HEADERS) src/config.h \
gflags_unittest3_SOURCES = $(gflagsinclude_HEADERS) \
src/gflags_unittest_main.cc
gflags_unittest3_LDADD = libgflags_nothreads.la
src/gflags_unittest_main.cc: src/gflags_unittest.cc
rm -f src/gflags_unittest_main.cc
cp -p src/gflags_unittest.cc src/gflags_unittest_main.cc
cp -p $(top_srcdir)/src/gflags_unittest.cc src/gflags_unittest_main.cc
CLEANFILES += src/gflags_unittest_main.cc
# Some buggy sh's ignore "" instead of treating it as a positional
......@@ -110,27 +115,27 @@ gflags_unittest_sh: gflags_unittest$(EXEEXT) \
gflags_unittest2$(EXEEXT) \
gflags_unittest3$(EXEEXT)
bash --version >/dev/null 2>&1 && export SH=bash || export SH=sh; \
$$SH "$(top_srcdir)/src/gflags_unittest.sh" "$(PWD)/gflags_unittest" \
"$(top_srcdir)" "@TMPDIR@"
$$SH "$(top_srcdir)/src/gflags_unittest.sh" \
"$(PWD)/gflags_unittest" "$(top_srcdir)" "@TEST_TMPDIR@"
# These are negative-compilation tests. We want to make sure these
# erroneous use of the flags macros correctly fail to compile.
# Again, we just bother testing with the no-threads version of the library.
check_SCRIPTS += gflags_nc_test1
gflags_nc_test1: $(gflagsinclude_HEADERS) src/config.h src/gflags_nc.cc
gflags_nc_test1: $(gflagsinclude_HEADERS) src/gflags_nc.cc
! $(CXX) -DTEST_SWAPPED_ARGS $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gflags_nc_test1.o $(srcdir)/src/gflags_nc.cc && echo "Compile failed, like it was supposed to"
check_SCRIPTS += gflags_nc_test2
gflags_nc_test2: $(gflagsinclude_HEADERS) src/config.h src/gflags_nc.cc
gflags_nc_test2: $(gflagsinclude_HEADERS) src/gflags_nc.cc
! $(CXX) -DTEST_INT_INSTEAD_OF_BOOL $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gflags_nc_test2.o $(srcdir)/src/gflags_nc.cc && echo "Compile failed, like it was supposed to"
check_SCRIPTS += gflags_nc_test3
gflags_nc_test3: $(gflagsinclude_HEADERS) src/config.h src/gflags_nc.cc
gflags_nc_test3: $(gflagsinclude_HEADERS) src/gflags_nc.cc
! $(CXX) -DTEST_BOOL_IN_QUOTES $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gflags_nc_test3.o $(srcdir)/src/gflags_nc.cc && echo "Compile failed, like it was supposed to"
# This one, on the other hand, should succeed.
check_SCRIPTS += gflags_nc_test4
gflags_nc_test4: $(gflagsinclude_HEADERS) src/config.h src/gflags_nc.cc
gflags_nc_test4: $(gflagsinclude_HEADERS) src/gflags_nc.cc
$(CXX) -DSANITY $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gflags_nc_test4.o $(srcdir)/src/gflags_nc.cc && echo "Compile failed, like it was supposed to"
# This file isn't covered under any rule that would cause it to be distributed.
......@@ -141,6 +146,7 @@ PYTHON = python/setup.py \
python/gflags.py \
python/gflags2man.py \
python/gflags_unittest.py \
python/gflags_helpxml_test.py \
python/test_module_foo.py \
python/test_module_bar.py
......@@ -162,4 +168,7 @@ libtool: $(LIBTOOL_DEPS)
$(SHELL) ./config.status --recheck
EXTRA_DIST = packages/rpm.sh packages/rpm/rpm.spec packages/deb.sh packages/deb \
libtool $(SCRIPTS) $(PYTHON) \
src/windows/config.h src/windows/port.h src/windows/port.cc \
src/windows/gflags/gflags.h src/windows/gflags/gflags_completions.h \
$(WINDOWS_PROJECTS) \
src/solaris/libstdc++.la
......@@ -215,6 +215,7 @@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PTHREAD_CC = @PTHREAD_CC@
......@@ -225,7 +226,7 @@ SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
TMPDIR = @TMPDIR@
TEST_TMPDIR = @TEST_TMPDIR@
VERSION = @VERSION@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
......@@ -309,6 +310,9 @@ dist_doc_DATA = AUTHORS COPYING ChangeLog INSTALL NEWS README \
doc/designstyle.css doc/gflags.html
lib_LTLIBRARIES = libgflags.la libgflags_nothreads.la
WINDOWS_PROJECTS = google-gflags.sln \
vsprojects/libgflags/libgflags.vcproj \
vsprojects/gflags_unittest/gflags_unittest.vcproj
# Also make sure this works when we don't link in pthreads
......@@ -334,7 +338,7 @@ check_SCRIPTS = gflags_unittest_sh gflags_nc_test1 gflags_nc_test2 \
noinst_SCRIPTS = src/gflags_unittest.sh
# Used for auto-generated source files
CLEANFILES = src/gflags_unittest-main.cc src/gflags_unittest_main.cc
GFLAGS_SOURCES = $(gflagsinclude_HEADERS) src/config.h src/mutex.h \
GFLAGS_SOURCES = $(gflagsinclude_HEADERS) src/mutex.h \
src/gflags.cc src/gflags_reporting.cc \
src/gflags_completions.cc
......@@ -344,7 +348,8 @@ libgflags_la_LDFLAGS = $(PTHREAD_CFLAGS)
libgflags_la_LIBADD = $(PTHREAD_LIBS)
libgflags_nothreads_la_SOURCES = $(GFLAGS_SOURCES)
libgflags_nothreads_la_CXXFLAGS = -DNDEBUG -DNO_THREADS
gflags_unittest_SOURCES = $(gflagsinclude_HEADERS) src/config.h \
gflags_unittest_SOURCES = $(gflagsinclude_HEADERS) \
src/config_for_unittests.h \
src/gflags_unittest.cc
gflags_unittest_CXXFLAGS = $(PTHREAD_CFLAGS)
......@@ -352,11 +357,11 @@ gflags_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
gflags_unittest_LDADD = libgflags.la
gflags_nothreads_unittest_SOURCES = $(gflags_unittest_SOURCES)
gflags_nothreads_unittest_LDADD = libgflags_nothreads.la
gflags_unittest2_SOURCES = $(gflagsinclude_HEADERS) src/config.h \
gflags_unittest2_SOURCES = $(gflagsinclude_HEADERS) \
src/gflags_unittest-main.cc
gflags_unittest2_LDADD = libgflags_nothreads.la
gflags_unittest3_SOURCES = $(gflagsinclude_HEADERS) src/config.h \
gflags_unittest3_SOURCES = $(gflagsinclude_HEADERS) \
src/gflags_unittest_main.cc
gflags_unittest3_LDADD = libgflags_nothreads.la
......@@ -369,11 +374,15 @@ PYTHON = python/setup.py \
python/gflags.py \
python/gflags2man.py \
python/gflags_unittest.py \
python/gflags_helpxml_test.py \
python/test_module_foo.py \
python/test_module_bar.py
EXTRA_DIST = packages/rpm.sh packages/rpm/rpm.spec packages/deb.sh packages/deb \
libtool $(SCRIPTS) $(PYTHON) \
src/windows/config.h src/windows/port.h src/windows/port.cc \
src/windows/gflags/gflags.h src/windows/gflags/gflags_completions.h \
$(WINDOWS_PROJECTS) \
src/solaris/libstdc++.la
all: all-am
......@@ -825,7 +834,7 @@ check-TESTS: $(TESTS)
distdir: $(DISTFILES)
$(am__remove_distdir)
mkdir $(distdir)
$(mkdir_p) $(distdir)/doc $(distdir)/m4 $(distdir)/packages $(distdir)/packages/rpm $(distdir)/python $(distdir)/src $(distdir)/src/gflags $(distdir)/src/google $(distdir)/src/solaris
$(mkdir_p) $(distdir)/doc $(distdir)/m4 $(distdir)/packages $(distdir)/packages/rpm $(distdir)/python $(distdir)/src $(distdir)/src/gflags $(distdir)/src/google $(distdir)/src/solaris $(distdir)/src/windows $(distdir)/src/windows/gflags $(distdir)/vsprojects/gflags_unittest $(distdir)/vsprojects/libgflags
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
list='$(DISTFILES)'; for file in $$list; do \
......@@ -1064,23 +1073,23 @@ uninstall-am: uninstall-binSCRIPTS uninstall-dist_docDATA \
src/gflags_unittest-main.cc: src/gflags_unittest.cc
rm -f src/gflags_unittest-main.cc
cp -p src/gflags_unittest.cc src/gflags_unittest-main.cc
cp -p $(top_srcdir)/src/gflags_unittest.cc src/gflags_unittest-main.cc
src/gflags_unittest_main.cc: src/gflags_unittest.cc
rm -f src/gflags_unittest_main.cc
cp -p src/gflags_unittest.cc src/gflags_unittest_main.cc
cp -p $(top_srcdir)/src/gflags_unittest.cc src/gflags_unittest_main.cc
gflags_unittest_sh: gflags_unittest$(EXEEXT) \
gflags_unittest2$(EXEEXT) \
gflags_unittest3$(EXEEXT)
bash --version >/dev/null 2>&1 && export SH=bash || export SH=sh; \
$$SH "$(top_srcdir)/src/gflags_unittest.sh" "$(PWD)/gflags_unittest" \
"$(top_srcdir)" "@TMPDIR@"
gflags_nc_test1: $(gflagsinclude_HEADERS) src/config.h src/gflags_nc.cc
$$SH "$(top_srcdir)/src/gflags_unittest.sh" \
"$(PWD)/gflags_unittest" "$(top_srcdir)" "@TEST_TMPDIR@"
gflags_nc_test1: $(gflagsinclude_HEADERS) src/gflags_nc.cc
! $(CXX) -DTEST_SWAPPED_ARGS $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gflags_nc_test1.o $(srcdir)/src/gflags_nc.cc && echo "Compile failed, like it was supposed to"
gflags_nc_test2: $(gflagsinclude_HEADERS) src/config.h src/gflags_nc.cc
gflags_nc_test2: $(gflagsinclude_HEADERS) src/gflags_nc.cc
! $(CXX) -DTEST_INT_INSTEAD_OF_BOOL $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gflags_nc_test2.o $(srcdir)/src/gflags_nc.cc && echo "Compile failed, like it was supposed to"
gflags_nc_test3: $(gflagsinclude_HEADERS) src/config.h src/gflags_nc.cc
gflags_nc_test3: $(gflagsinclude_HEADERS) src/gflags_nc.cc
! $(CXX) -DTEST_BOOL_IN_QUOTES $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gflags_nc_test3.o $(srcdir)/src/gflags_nc.cc && echo "Compile failed, like it was supposed to"
gflags_nc_test4: $(gflagsinclude_HEADERS) src/config.h src/gflags_nc.cc
gflags_nc_test4: $(gflagsinclude_HEADERS) src/gflags_nc.cc
$(CXX) -DSANITY $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gflags_nc_test4.o $(srcdir)/src/gflags_nc.cc && echo "Compile failed, like it was supposed to"
rpm: dist-gzip packages/rpm.sh packages/rpm/rpm.spec
......
......@@ -9,6 +9,9 @@ See INSTALL for (generic) installation instructions for C++: basically
To install the python module, run
cd python; python ./setup.py install
You can also compile this under Windows, if you want. The solution
file (for VC 7.1 and later) is in this directory.
When you install the python library, you also get a helper
application, gflags2man.py, installed into /usr/local/bin. You can
run gflags2man.py to create an instant man page, with all the
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -28,14 +28,14 @@ case $host_os in
# "make install".
AC_DISABLE_FAST_INSTALL
# /tmp is a mount-point in mingw, and hard to use. use cwd instead
TMPDIR=gflags_testdir
TEST_TMPDIR=gflags_testdir
;;
*)
AC_ENABLE_FAST_INSTALL
TMPDIR=/tmp/gflags
TEST_TMPDIR=/tmp/gflags
;;
esac
AC_SUBST(TMPDIR)
AC_SUBST(TEST_TMPDIR)
# Uncomment this if you'll be exporting libraries (.so's)
AC_PROG_LIBTOOL
......@@ -97,6 +97,16 @@ AC_SUBST(ac_cv_have___int16)
## Check out ../autoconf/ for other macros you can call to do useful stuff
# For windows, this has a non-trivial value (__declspec(export)), but any
# system that uses configure wants this to be the empty string.
AC_DEFINE(GFLAGS_DLL_DECL,,
[Always the empty-string on non-windows systems.
On windows, should be "__declspec(dllexport)".
This way, when we compile the dll, we export our functions/classes.
It's safe to define this here because config.h is only used
internally, to compile the DLL, and every DLL source file
#includes "config.h" before anything else.])
# Write generated configuration file, and also .h files
AC_CONFIG_FILES([Makefile src/gflags/gflags.h src/gflags/gflags_completions.h])
AC_OUTPUT
Microsoft Visual Studio Solution File, Format Version 8.00
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgflags", "vsprojects\libgflags\libgflags.vcproj", "{FB27FBDB-E6C0-4D00-A7F8-1EEEF1B48ABC}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gflags_unittest", "vsprojects\gflags_unittest\gflags_unittest.vcproj", "{4B263748-5F0F-468C-8C5C-ED2682BB6BE3}"
ProjectSection(ProjectDependencies) = postProject
{FB27FBDB-E6C0-4D00-A7F8-1EEEF1B48ABC} = {FB27FBDB-E6C0-4D00-A7F8-1EEEF1B48ABC}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfiguration) = preSolution
Debug = Debug
Release = Release
EndGlobalSection
GlobalSection(ProjectDependencies) = postSolution
EndGlobalSection
GlobalSection(ProjectConfiguration) = postSolution
{FB27FBDB-E6C0-4D00-A7F8-1EEEF1B48ABC}.Debug.ActiveCfg = Debug|Win32
{FB27FBDB-E6C0-4D00-A7F8-1EEEF1B48ABC}.Debug.Build.0 = Debug|Win32
{FB27FBDB-E6C0-4D00-A7F8-1EEEF1B48ABC}.Release.ActiveCfg = Release|Win32
{FB27FBDB-E6C0-4D00-A7F8-1EEEF1B48ABC}.Release.Build.0 = Release|Win32
{4B263748-5F0F-468C-8C5C-ED2682BB6BE3}.Debug.ActiveCfg = Debug|Win32
{4B263748-5F0F-468C-8C5C-ED2682BB6BE3}.Debug.Build.0 = Debug|Win32
{4B263748-5F0F-468C-8C5C-ED2682BB6BE3}.Release.ActiveCfg = Release|Win32
{4B263748-5F0F-468C-8C5C-ED2682BB6BE3}.Release.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection
GlobalSection(ExtensibilityAddIns) = postSolution
EndGlobalSection
EndGlobal
......@@ -661,6 +661,16 @@ class FlagValues:
# key for that module.
self.__dict__['__key_flags_by_module'] = {}
# Set if we should use new style gnu_getopt rather than getopt when parsing
# the args. Only possible with Python 2.3+
self.UseGnuGetOpt(False)
def UseGnuGetOpt(self, use_gnu_getopt=True):
self.__dict__['__use_gnu_getopt'] = use_gnu_getopt
def IsGnuGetOpt(self):
return self.__dict__['__use_gnu_getopt']
def FlagDict(self):
return self.__dict__['__flags']
......@@ -974,6 +984,9 @@ class FlagValues:
args = argv[1:]
while True:
try:
if self.__dict__['__use_gnu_getopt']:
optlist, unparsed_args = getopt.gnu_getopt(args, shortopts, longopts)
else:
optlist, unparsed_args = getopt.getopt(args, shortopts, longopts)
break
except getopt.GetoptError, e:
......@@ -1029,6 +1042,10 @@ class FlagValues:
raise UnrecognizedFlagError(opt)
if unparsed_args:
if self.__dict__['__use_gnu_getopt']:
# if using gnu_getopt just return the program name + remainder of argv.
return argv[:1] + unparsed_args
else:
# unparsed_args becomes the first non-flag detected by getopt to
# the end of argv. Because argv may have been modified above,
# return original_argv for this region.
......@@ -2099,7 +2116,9 @@ class BaseListParser(ArgumentParser):
self.syntactic_help = "a %s separated list" % self._name
def Parse(self, argument):
if argument == '':
if isinstance(argument, list):
return argument
elif argument == '':
return []
else:
return [s.strip() for s in argument.split(self._token)]
......
......@@ -97,6 +97,10 @@ def MultiLineEqual(expected_help, help):
class FlagsUnitTest(unittest.TestCase):
"Flags Unit Test"
def setUp(self):
# make sure we are using the old, stupid way of parsing flags.
FLAGS.UseGnuGetOpt(False)
def assertListEqual(self, list1, list2):
"""Asserts that, when sorted, list1 and list2 are identical."""
sorted_list1 = list1[:]
......@@ -127,12 +131,13 @@ class FlagsUnitTest(unittest.TestCase):
flags.DEFINE_integer("x", 3, "how eXtreme to be")
flags.DEFINE_integer("l", 0x7fffffff00000000L, "how long to be")
flags.DEFINE_list('letters', 'a,b,c', "a list of letters")
flags.DEFINE_list('numbers', [1, 2, 3], "a list of numbers")
flags.DEFINE_enum("kwery", None, ['who', 'what', 'why', 'where', 'when'],
"?")
# Specify number of flags defined above. The short_name defined
# for 'repeat' counts as an extra flag.
number_defined_flags = 10 + 1
number_defined_flags = 11 + 1
self.assertEqual(len(FLAGS.RegisteredFlags()),
number_defined_flags + number_test_framework_flags)
......@@ -143,8 +148,10 @@ class FlagsUnitTest(unittest.TestCase):
assert FLAGS.x == 3, "integer default values not set:" + FLAGS.x
assert FLAGS.l == 0x7fffffff00000000L, ("integer default values not set:"
+ FLAGS.l)
assert FLAGS.letters == ['a', 'b', 'c'], "list default values not set:" \
+ FLAGS.letters
assert FLAGS.letters == ['a', 'b', 'c'], ("list default values not set:"
+ FLAGS.letters)
assert FLAGS.numbers == [1, 2, 3], ("list default values not set:"
+ FLAGS.numbers)
assert FLAGS.kwery is None, ("enum default None value not set:"
+ FLAGS.kwery)
......@@ -158,6 +165,7 @@ class FlagsUnitTest(unittest.TestCase):
assert flag_values['x'] == 3
assert flag_values['l'] == 0x7fffffff00000000L
assert flag_values['letters'] == ['a', 'b', 'c']
assert flag_values['numbers'] == [1, 2, 3]
assert flag_values['kwery'] is None
# Verify string form of defaults
......@@ -170,6 +178,7 @@ class FlagsUnitTest(unittest.TestCase):
assert FLAGS['x'].default_as_str == "'3'"
assert FLAGS['l'].default_as_str == "'9223372032559808512'"
assert FLAGS['letters'].default_as_str == "'a,b,c'"
assert FLAGS['numbers'].default_as_str == "'1,2,3'"
# Verify that the iterator for flags yields all the keys
keys = list(FLAGS)
......@@ -211,6 +220,7 @@ class FlagsUnitTest(unittest.TestCase):
assert 'x' in FLAGS.RegisteredFlags()
assert 'l' in FLAGS.RegisteredFlags()
assert 'letters' in FLAGS.RegisteredFlags()
assert 'numbers' in FLAGS.RegisteredFlags()
# has_key
assert FLAGS.has_key('name')
......@@ -479,6 +489,7 @@ class FlagsUnitTest(unittest.TestCase):
return ' '.join(nonbool_flags + truebool_flags + falsebool_flags)
argv = ('./program', '--repeat=3', '--name=giants', '--nodebug')
FLAGS(argv)
self.assertEqual(FLAGS.get('repeat', None), 3)
self.assertEqual(FLAGS.get('name', None), 'giants')
......@@ -489,6 +500,7 @@ class FlagsUnitTest(unittest.TestCase):
"--letters ['a', 'b', 'c'] "
"--m ['str1', 'str2'] --m_str ['str1', 'str2'] "
"--name giants "
"--numbers [1, 2, 3] "
"--repeat 3 "
"--s ['sing1'] --s_str ['sing1'] "
"--testget4 None --testlist [] "
......@@ -514,6 +526,7 @@ class FlagsUnitTest(unittest.TestCase):
"--m ['str1', 'str2', 'upd1'] "
"--m_str ['str1', 'str2', 'upd1'] "
"--name giants "
"--numbers [1, 2, 3] "
"--repeat 3 "
"--s ['upd2'] --s_str ['upd2'] "
"--testget4 None --testlist [] "
......@@ -871,6 +884,18 @@ class FlagsUnitTest(unittest.TestCase):
self.assertEqual(argv, fake_argv[:1] + fake_argv[2:])
self._UndeclareSomeFlags()
def test_parse_flags_after_args_if_using_gnu_getopt(self):
"""
Test that flags given after arguments are parsed if using gnu_getopt.
"""
self.__DeclareSomeFlags()
FLAGS.UseGnuGetOpt()
fake_argv = ['fooScript', '--UnitTestBoolFlag',
'command', '--UnitTestB']
argv = FLAGS(fake_argv)
self.assertEqual(argv, ['fooScript', 'command'])
self._UndeclareSomeFlags()
def test_SetDefault(self):
"""
Test changing flag defaults.
......@@ -1004,6 +1029,7 @@ class FlagsUnitTest(unittest.TestCase):
# TODO(csilvers): we should still parse --onedash_name=Harry as a
# flag, but currently we don't (we stop flag processing as soon as
# we see the first non-flag).
# - This requires gnu_getopt from Python 2.3+ see FLAGS.UseGnuGetOpt()
def test_unrecognized_flags(self):
# Unknown flag --nosuchflag
......@@ -1193,6 +1219,9 @@ class FlagsUnitTest(unittest.TestCase):
(default: 'Bob')
--[no]noexec: boolean flag with no as prefix
(default: 'true')
--numbers: a list of numbers
(default: '1,2,3')
(a comma separated list)
--[no]q: quiet mode
(default: 'true')
--[no]quack: superstring of 'q'
......
/* src/config.h.in. Generated from configure.ac by autoheader. */
/* Always the empty-string on non-windows systems. On windows, should be
"__declspec(dllexport)". This way, when we compile the dll, we export our
functions/classes. It's safe to define this here because config.h is only
used internally, to compile the DLL, and every DLL source file #includes
"config.h" before anything else. */
#undef GFLAGS_DLL_DECL
/* Namespace for Google classes */
#undef GOOGLE_NAMESPACE
......@@ -72,6 +79,9 @@
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
......
// 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.
// ---
// All Rights Reserved.
//
// Author: Craig Silverstein
//
// This file is needed for windows -- unittests are not part of the
// gflags dll, but still want to include config.h just like the
// dll does, so they can use internal tools and APIs for testing.
//
// The problem is that config.h declares GFLAGS_DLL_DECL to be
// for exporting symbols, but the unittest needs to *import* symbols
// (since it's not the dll).
//
// The solution is to have this file, which is just like config.h but
// sets GFLAGS_DLL_DECL to do a dllimport instead of a dllexport.
//
// The reason we need this extra GFLAGS_DLL_DECL_FOR_UNITTESTS
// variable is in case people want to set GFLAGS_DLL_DECL explicitly
// to something other than __declspec(dllexport). In that case, they
// may want to use something other than __declspec(dllimport) for the
// unittest case. For that, we allow folks to define both
// GFLAGS_DLL_DECL and GFLAGS_DLL_DECL_FOR_UNITTESTS explicitly.
//
// NOTE: This file is equivalent to config.h on non-windows systems,
// which never defined GFLAGS_DLL_DECL_FOR_UNITTESTS and always
// define GFLAGS_DLL_DECL to the empty string.
#include "config.h"
#undef GFLAGS_DLL_DECL
#ifdef GFLAGS_DLL_DECL_FOR_UNITTESTS
# define GFLAGS_DLL_DECL GFLAGS_DLL_DECL_FOR_UNITTESTS
#else
# define GFLAGS_DLL_DECL // if DLL_DECL_FOR_UNITTESTS isn't defined, use ""
#endif
......@@ -112,7 +112,7 @@
#include <vector>
#include <utility> // for pair<>
#include <algorithm>
#include "gflags/gflags.h"
#include <gflags/gflags.h>
#include "mutex.h"
#ifndef PATH_SEPARATOR
......@@ -178,7 +178,7 @@ _START_GOOGLE_NAMESPACE_
const char kStrippedFlagHelp[] = "\001\002\003\004 (unknown) \004\003\002\001";
// This is used by the unittest to test error-exit code
void (*commandlineflags_exitfunc)(int) = &exit; // from stdlib.h
void GFLAGS_DLL_DECL (*commandlineflags_exitfunc)(int) = &exit; // from stdlib.h
namespace {
......
......@@ -176,6 +176,11 @@ struct CommandLineFlagInfo {
bool is_default; // true if the flag has default value
};
// Using this inside of a validator is a recipe for a deadlock.
// TODO(wojtekm) Fix locking when validators are running, to make it safe to
// call validators during ParseAllFlags.
// Also make sure then to uncomment the corresponding unit test in
// commandlineflags_unittest.sh
extern void GetAllFlags(std::vector<CommandLineFlagInfo>* OUTPUT);
// These two are actually defined in commandlineflags_reporting.cc.
extern void ShowUsageWithFlags(const char *argv0); // what --help does
......@@ -479,25 +484,25 @@ template<typename From> double IsBoolFlag(const From& from);
bool IsBoolFlag(bool from);
} // namespace fLB
#define DECLARE_bool(name) DECLARE_VARIABLE(bool,B, name)
#define DEFINE_bool(name,val,txt) \
#define DECLARE_bool(name) DECLARE_VARIABLE(bool, B, name)
#define DEFINE_bool(name, val, txt) \
namespace fLB { \
typedef CompileAssert FLAG_##name##_value_is_not_a_bool[ \
(sizeof(::fLB::IsBoolFlag(val)) != sizeof(double)) ? 1 : -1]; \
} \
DEFINE_VARIABLE(bool,B, name, val, txt)
DEFINE_VARIABLE(bool, B, name, val, txt)
#define DECLARE_int32(name) DECLARE_VARIABLE(@ac_google_namespace@::int32,I, name)
#define DEFINE_int32(name,val,txt) DEFINE_VARIABLE(@ac_google_namespace@::int32,I, name, val, txt)
#define DECLARE_int32(name) DECLARE_VARIABLE(@ac_google_namespace@::int32, I, name)
#define DEFINE_int32(name,val,txt) DEFINE_VARIABLE(@ac_google_namespace@::int32, I, name, val, txt)
#define DECLARE_int64(name) DECLARE_VARIABLE(@ac_google_namespace@::int64,I64, name)
#define DEFINE_int64(name,val,txt) DEFINE_VARIABLE(@ac_google_namespace@::int64,I64, name, val, txt)
#define DECLARE_int64(name) DECLARE_VARIABLE(@ac_google_namespace@::int64, I64, name)
#define DEFINE_int64(name,val,txt) DEFINE_VARIABLE(@ac_google_namespace@::int64, I64, name, val, txt)
#define DECLARE_uint64(name) DECLARE_VARIABLE(@ac_google_namespace@::uint64,U64, name)
#define DEFINE_uint64(name,val,txt) DEFINE_VARIABLE(@ac_google_namespace@::uint64,U64, name, val, txt)
#define DECLARE_uint64(name) DECLARE_VARIABLE(@ac_google_namespace@::uint64, U64, name)
#define DEFINE_uint64(name,val,txt) DEFINE_VARIABLE(@ac_google_namespace@::uint64, U64, name, val, txt)
#define DECLARE_double(name) DECLARE_VARIABLE(double,D, name)
#define DEFINE_double(name,val,txt) DEFINE_VARIABLE(double,D, name, val, txt)
#define DECLARE_double(name) DECLARE_VARIABLE(double, D, name)
#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
......
......@@ -58,7 +58,7 @@
#include <utility>
#include <vector>
#include "gflags/gflags.h"
#include <gflags/gflags.h>
using std::set;
using std::string;
......
......@@ -55,8 +55,8 @@
#include <assert.h>
#include <string>
#include <vector>
#include "gflags/gflags.h"
#include "gflags/gflags_completions.h"
#include <gflags/gflags.h>
#include <gflags/gflags_completions.h>
#ifndef PATH_SEPARATOR
#define PATH_SEPARATOR '/'
......
......@@ -33,26 +33,38 @@
// For now, this unit test does not cover all features of
// gflags.cc
#include "config.h"
#include "config_for_unittests.h"
#include <stdio.h>
#include <stdlib.h> // for &exit
#include <assert.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h> // for unlink()
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h> // for mkdir()
#endif
#include <math.h> // for isinf() and isnan()
#include <vector>
#include <string>
#include "gflags/gflags.h"
#include <gflags/gflags.h>
// I don't actually use this header file, but #include it under the
// old location to make sure that the include-header-forwarding
// works.
#include "google/gflags_completions.h"
// works. But don't bother on windows; the windows port is so new
// it never had the old location-names.
#ifndef _WIN32
#include <google/gflags_completions.h>
void (*unused_fn)() = &GOOGLE_NAMESPACE::HandleCommandLineCompletions;
#endif
using std::vector;
using std::string;
using GOOGLE_NAMESPACE::int32;
using GOOGLE_NAMESPACE::FlagRegisterer;
using GOOGLE_NAMESPACE::StringFromEnv;
using GOOGLE_NAMESPACE::RegisterFlagValidator;
using GOOGLE_NAMESPACE::CommandLineFlagInfo;
using GOOGLE_NAMESPACE::GetAllFlags;
// Returns the number of elements in an array.
#define GET_ARRAY_SIZE(arr) (sizeof(arr)/sizeof(*(arr)))
......@@ -82,7 +94,7 @@ void setenv(const char* name, const char* value, int) {
DECLARE_string(tryfromenv); // in gflags.cc
DEFINE_string(test_tmpdir, "/tmp/gflags_unittest", "Dir we use for temp files");
DEFINE_string(srcdir, GOOGLE_NAMESPACE::StringFromEnv("SRCDIR", "."),
DEFINE_string(srcdir, StringFromEnv("SRCDIR", "."),
"Source-dir root, needed to find gflags_unittest_flagfile");
......@@ -139,9 +151,25 @@ DEFINE_bool(changed_bool2, false, "changed");
static bool AlwaysFail(const char* flag, bool value) { return value == false; }
DEFINE_bool(always_fail, false, "will fail to validate when you set it");
static const bool dummy = GOOGLE_NAMESPACE::RegisterFlagValidator(&FLAGS_always_fail, AlwaysFail);
static const bool dummy = RegisterFlagValidator(&FLAGS_always_fail, AlwaysFail);
// See the comment by GetAllFlags in commandlineflags.h
static bool DeadlockIfCantLockInValidators(const char* flag, bool value) {
if (!value) {
return true;
}
vector<CommandLineFlagInfo> 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.");
static const bool dummy1 = RegisterFlagValidator(&FLAGS_deadlock_if_cant_lock,
DeadlockIfCantLockInValidators);
// This is a psuedo-flag -- we want to register a flag with a filename
// 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 {
......@@ -239,11 +267,11 @@ _START_GOOGLE_NAMESPACE_
static bool g_called_exit;
static void CalledExit(int) { g_called_exit = true; }
extern GFLAGS_DLL_DECL void (*commandlineflags_exitfunc)(int); // in gflags.cc
#define EXPECT_DEATH(fn, msg) \
do { \
g_called_exit = false; \
extern void (*commandlineflags_exitfunc)(int); /* in gflags.cc */ \
commandlineflags_exitfunc = &CalledExit; \
fn; \
commandlineflags_exitfunc = &exit; /* set back to its default */ \
......@@ -1518,10 +1546,17 @@ static int Main(int argc, char **argv) {
SetUsageMessage(usage_message.c_str());
ParseCommandLineFlags(&argc, &argv, true);
#ifdef __MINGW32__
#if defined(__MINGW32__)
// I had trouble creating a directory in /tmp from mingw
FLAGS_test_tmpdir = "./gflags_unittest_testdir";
mkdir(FLAGS_test_tmpdir.c_str()); // mingw has a weird one-arg mkdir
#elif defined(_WIN32)
char tmppath_buffer[1024];
int tmppath_len = GetTempPathA(sizeof(tmppath_buffer), tmppath_buffer);
assert(tmppath_len > 0 && tmppath_len < sizeof(tmppath_buffer));
assert(tmppath_buffer[tmppath_len - 1] == '\\'); // API guarantees it
FLAGS_test_tmpdir = string(tmppath_buffer) + "gflags_unittest_testdir";
_mkdir(FLAGS_test_tmpdir.c_str());
#else
mkdir(FLAGS_test_tmpdir.c_str(), 0755);
#endif
......
......@@ -215,8 +215,11 @@ Expect $LINENO 0 "gflags_unittest" "gflags_unittest.cc" \
# Make sure -- by itself stops argv processing
Expect $LINENO 0 "PASS" "" -- --help
# And we should die if the flag value doesn't pas the validator
# And we should die if the flag value doesn't pass the validator
Expect $LINENO 1 "ERROR: failed validation of new value 'true' for flag 'always_fail'" "" --always_fail
# TODO(wojtekm) And if locking in validators fails.
# Expect $LINENO 0 "PASS" "" --deadlock_if_cant_lock
echo "PASS"
exit 0
/* src/config.h.in. Generated from configure.ac by autoheader. */
/* Sometimes we accidentally #include this config.h instead of the one
in .. -- this is particularly true for msys/mingw, which uses the
unix config.h but also runs code in the windows directory.
*/
#ifdef __MINGW32__
#include "../config.h"
#define GOOGLE_GFLAGS_WINDOWS_CONFIG_H_
#endif
#ifndef GOOGLE_GFLAGS_WINDOWS_CONFIG_H_
#define GOOGLE_GFLAGS_WINDOWS_CONFIG_H_
/* Always the empty-string on non-windows systems. On windows, should be
"__declspec(dllexport)". This way, when we compile the dll, we export our
functions/classes. It's safe to define this here because config.h is only
used internally, to compile the DLL, and every DLL source file #includes
"config.h" before anything else. */
#ifndef GFLAGS_DLL_DECL
# define GFLAGS_IS_A_DLL 1 /* not set if you're statically linking */
# define GFLAGS_DLL_DECL __declspec(dllexport)
# define GFLAGS_DLL_DECL_FOR_UNITTESTS __declspec(dllimport)
#endif
/* Namespace for Google classes */
#define GOOGLE_NAMESPACE ::google
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define to 1 if you have the <fnmatch.h> header file. */
#undef HAVE_FNMATCH_H
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* define if the compiler implements namespaces */
#define HAVE_NAMESPACES 1
/* Define if you have POSIX threads libraries and header files. */
#undef HAVE_PTHREAD
/* Define to 1 if you have the `putenv' function. */
#define HAVE_PUTENV 1
/* Define to 1 if you have the `setenv' function. */
#undef HAVE_SETENV
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the `strtoll' function. */
#define HAVE_STRTOLL 1
/* Define to 1 if you have the `strtoq' function. */
#define HAVE_STRTOQ 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* define if your compiler has __attribute__ */
#undef HAVE___ATTRIBUTE__
/* Name of package */
#undef PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define to necessary symbol if this constant uses a non-standard name on
your system. */
#undef PTHREAD_CREATE_JOINABLE
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* the namespace where STL code like vector<> is defined */
#define STL_NAMESPACE std
/* Version number of package */
#undef VERSION
/* Stops putting the code inside the Google namespace */
#define _END_GOOGLE_NAMESPACE_ }
/* Puts following code inside the Google namespace */
#define _START_GOOGLE_NAMESPACE_ namespace google {
// ---------------------------------------------------------------------
// Extra stuff not found in config.h.in
// This must be defined before the windows.h is included. It's needed
// for mutex.h, to give access to the TryLock method.
#ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x0400
#endif
// TODO(csilvers): include windows/port.h in every relevant source file instead?
#include "windows/port.h"
#endif /* GOOGLE_GFLAGS_WINDOWS_CONFIG_H_ */
// 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.
// ---
// Author: Ray Sidney
// 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);"
//
// DEFINE_int32(end, 1000, "The last record to read");
// 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 GOOGLE_GFLAGS_H_
#define GOOGLE_GFLAGS_H_
#include <string>
#include <vector>
// We care a lot about number of bits things take up. Unfortunately,
// systems define their bit-specific ints in a lot of different ways.
// We use our own way, and have a typedef to get there.
// Note: these commands below may look like "#if 1" or "#if 0", but
// that's because they were constructed that way at ./configure time.
// Look at gflags.h.in to see how they're calculated (based on your config).
#if 0
#include <stdint.h> // the normal place uint16_t is defined
#endif
#if 1
#include <sys/types.h> // the normal place u_int16_t is defined
#endif
#if 0
#include <inttypes.h> // a third place for uint16_t or u_int16_t
#endif
// Annoying stuff for windows -- makes sure clients can import these functions
#ifndef GFLAGS_DLL_DECL
# ifdef _WIN32
# define GFLAGS_DLL_DECL __declspec(dllimport)
# else
# define GFLAGS_DLL_DECL
# endif
#endif
namespace google {
#if 0 // the C99 format
typedef int32_t int32;
typedef uint32_t uint32;
typedef int64_t int64;
typedef uint64_t uint64;
#elif 0 // the BSD format
typedef int32_t int32;
typedef u_int32_t uint32;
typedef int64_t int64;
typedef u_int64_t uint64;
#elif 1 // the windows (vc7) format
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
// --------------------------------------------------------------------
// 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.
//
// 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, InitGoogle 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).
GFLAGS_DLL_DECL bool RegisterFlagValidator(const bool* flag,
bool (*validate_fn)(const char*, bool));
GFLAGS_DLL_DECL bool RegisterFlagValidator(const int32* flag,
bool (*validate_fn)(const char*, int32));
GFLAGS_DLL_DECL bool RegisterFlagValidator(const int64* flag,
bool (*validate_fn)(const char*, int64));
GFLAGS_DLL_DECL bool RegisterFlagValidator(const uint64* flag,
bool (*validate_fn)(const char*, uint64));
GFLAGS_DLL_DECL bool RegisterFlagValidator(const double* flag,
bool (*validate_fn)(const char*, double));
GFLAGS_DLL_DECL bool RegisterFlagValidator(const std::string* flag,
bool (*validate_fn)(const char*, const std::string&));
// --------------------------------------------------------------------
// 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.
struct GFLAGS_DLL_DECL CommandLineFlagInfo {
std::string name; // the name of the flag
std::string type; // the type of the flag: int32, etc
std::string description; // the "help text" associated with the flag
std::string current_value; // the current value, as a string
std::string default_value; // the default value, as a string
std::string filename; // 'cleaned' version of filename holding the flag
bool has_validator_fn; // true if RegisterFlagValidator called on flag
bool is_default; // true if the flag has default value
};
// Using this inside of a validator is a recipe for a deadlock.
// TODO(wojtekm) Fix locking when validators are running, to make it safe to
// call validators during ParseAllFlags.
// Also make sure then to uncomment the corresponding unit test in
// commandlineflags_unittest.sh
extern GFLAGS_DLL_DECL void GetAllFlags(std::vector<CommandLineFlagInfo>* OUTPUT);
// These two are actually defined in commandlineflags_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<std::string>& GetArgvs(); // all of argv as a vector
extern GFLAGS_DLL_DECL const char* GetArgv(); // all of argv as a string
extern GFLAGS_DLL_DECL const char* GetArgv0(); // only argv0
extern GFLAGS_DLL_DECL uint32 GetArgvSum(); // simple checksum of argv
extern GFLAGS_DLL_DECL const char* ProgramInvocationName(); // argv0, or "UNKNOWN" if not set
extern GFLAGS_DLL_DECL const 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()
// --------------------------------------------------------------------
// 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 __attribute__((unused)) because all the
// work is done in the constructor and destructor, so in the standard
// usage example above, the compiler would complain that it's an
// unused variable.
//
// This class is thread-safe.
class 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&);
} ;
// --------------------------------------------------------------------
// 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 SaveCommandFlags(); // actually defined in google.cc !
extern GFLAGS_DLL_DECL bool ReadFromFlagsFile(const std::string& filename, const char* prog_name,
bool errors_are_fatal); // uses SET_FLAGS_VALUE
// --------------------------------------------------------------------
// 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 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 commandlineflags from main():
// Set the "usage" message for this program. For example:
// string usage("This program does nothing. Sample usage:\n");
// usage += argv[0] + " <uselessarg1> <uselessarg2>";
// SetUsageMessage(usage);
// Do not include commandline flags in the usage: we do that for you!
// Thread-hostile; meant to be called before any threads are spawned.
extern GFLAGS_DLL_DECL void SetUsageMessage(const std::string& usage);
// 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.
// 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.
extern GFLAGS_DLL_DECL uint32 ParseCommandLineNonHelpFlags(int *argc, char*** argv,
bool remove_flags);
// This is actually defined in commandlineflags_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 commandlineflags_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 uint32 ReparseCommandLineNonHelpFlags();
// --------------------------------------------------------------------
// 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_<name>, we also
// preemptively define a junk variable, FLAGS_no<name>. 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 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:
FlagRegisterer(const char* name, const char* type,
const char* help, const char* filename,
void* current_storage, void* defvalue_storage);
};
extern bool FlagsTypeWarn(const char *name);
// If your application #defines STRIP_FLAG_HELP to a non-zero value
// before #including this file, we remove the help message from the
// binary file. This can reduce the size of the resulting binary
// somewhat, and may also be useful for security reasons.
extern const char kStrippedFlagHelp[];
}
#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) : 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<name>. This serves the second purpose of assuring a
// compile error if someone tries to define a flag named no<name>
// which is illegal (--foo and --nofoo both affect the "foo" flag).
#define DEFINE_VARIABLE(type, shorttype, name, value, help) \
namespace fL##shorttype { \
static const type FLAGS_nono##name = value; \
/* We always want to export defined variables, dll or no */ \
__declspec(dllexport) type FLAGS_##name = FLAGS_nono##name; \
type FLAGS_no##name = FLAGS_nono##name; \
static ::google::FlagRegisterer o_##name( \
#name, #type, MAYBE_STRIPPED_HELP(help), __FILE__, \
&FLAGS_##name, &FLAGS_no##name); \
} \
using fL##shorttype::FLAGS_##name
#define DECLARE_VARIABLE(type, shorttype, name) \
namespace fL##shorttype { \
/* We always want to import declared variables, dll or no */ \
extern __declspec(dllimport) type FLAGS_##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-time assert (msg[-1] will give a compile-time error).
namespace fLB {
struct CompileAssert {};
typedef CompileAssert expected_sizeof_double_neq_sizeof_bool[
(sizeof(double) != sizeof(bool)) ? 1 : -1];
template<typename From> GFLAGS_DLL_DECL double IsBoolFlag(const From& from);
GFLAGS_DLL_DECL bool IsBoolFlag(bool from);
} // namespace fLB
#define DECLARE_bool(name) DECLARE_VARIABLE(bool, B, name)
#define DEFINE_bool(name, val, txt) \
namespace fLB { \
typedef CompileAssert FLAG_##name##_value_is_not_a_bool[ \
(sizeof(::fLB::IsBoolFlag(val)) != sizeof(double)) ? 1 : -1]; \
} \
DEFINE_VARIABLE(bool, B, name, val, txt)
#define DECLARE_int32(name) DECLARE_VARIABLE(::google::int32, I, name)
#define DEFINE_int32(name,val,txt) DEFINE_VARIABLE(::google::int32, I, name, val, txt)
#define DECLARE_int64(name) DECLARE_VARIABLE(::google::int64, I64, name)
#define DEFINE_int64(name,val,txt) DEFINE_VARIABLE(::google::int64, I64, name, val, txt)
#define DECLARE_uint64(name) DECLARE_VARIABLE(::google::uint64, U64, name)
#define DEFINE_uint64(name,val,txt) DEFINE_VARIABLE(::google::uint64, U64, name, val, txt)
#define DECLARE_double(name) DECLARE_VARIABLE(double, D, name)
#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.
#define DECLARE_string(name) namespace fLS { extern __declspec(dllimport) std::string& FLAGS_##name; } \
using fLS::FLAGS_##name
// 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 { \
static union { void* align; char s[sizeof(std::string)]; } s_##name[2]; \
const std::string* const FLAGS_no##name = new (s_##name[0].s) std::string(val); \
static ::google::FlagRegisterer o_##name( \
#name, "string", MAYBE_STRIPPED_HELP(txt), __FILE__, \
s_##name[0].s, new (s_##name[1].s) std::string(*FLAGS_no##name)); \
extern __declspec(dllexport) std::string& FLAGS_##name; \
using fLS::FLAGS_##name; \
std::string& FLAGS_##name = *(reinterpret_cast<std::string*>(s_##name[0].s)); \
} \
using fLS::FLAGS_##name
#endif // SWIG
#endif // GOOGLE_GFLAGS_H_
// 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
//
// 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 <TAB> 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<TAB> Show me all flags with names prefixed by 'foo'
// --foo?<TAB> Show me all flags with 'foo' somewhere in the name
// --foo??<TAB> Same as prior case, but also search in module
// definition path for 'foo'
// --foo???<TAB> 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 \
'/usr/local/bin/gflags_completions.sh --tab_completion_columns $COLUMNS' \
time env binary_name another_binary [...]
*/
// This would allow the following to work:
// $ /path/to/binary_name --vmodule<TAB>
// Or:
// $ ./bin/path/another_binary --gfs_u<TAB>
// (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<TAB>
// Assuming that "binary" is a newly compiled binary, this should still
// produce the expected completion output.
#ifndef GOOGLE_GFLAGS_COMPLETIONS_H_
#define GOOGLE_GFLAGS_COMPLETIONS_H_
// Annoying stuff for windows -- makes sure clients can import these functions
#ifndef GFLAGS_DLL_DECL
# ifdef _WIN32
# define GFLAGS_DLL_DECL __declspec(dllimport)
# else
# define GFLAGS_DLL_DECL
# endif
#endif
namespace google {
GFLAGS_DLL_DECL void HandleCommandLineCompletions(void);
}
#endif // GOOGLE_GFLAGS_COMPLETIONS_H_
/* 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 <config.h>
#include <string.h> // for strlen(), memset(), memcmp()
#include <assert.h>
#include <stdarg.h> // for va_list, va_start, va_end
#include <windows.h>
#include "port.h"
#ifndef HAVE_SNPRINTF
int snprintf(char *str, size_t size, const char *format, ...) {
if (size == 0) // not even room for a \0?
return -1; // not what C99 says to do, but what windows does
va_list ap;
va_start(ap, format);
const int r = _vsnprintf(str, size-1, format, ap);
va_end(ap);
str[size-1] = '\0';
return r;
}
#endif
/* 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 GOOGLE_GFLAGS_WINDOWS_PORT_H_
#define GOOGLE_GFLAGS_WINDOWS_PORT_H_
// You should never include this file directly, but always include it
// from either config.h (MSVC) or mingw.h (MinGW/msys).
#if !defined(GOOGLE_GFLAGS_WINDOWS_CONFIG_H_)
# error "port.h should only be included from config.h"
#endif
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN /* We always want minimal includes */
#endif
#include <windows.h>
#include <direct.h> /* for mkdir */
#include <stdio.h> /* need this to override stdio's snprintf */
#define putenv _putenv
// ----------------------------------- STRING ROUTINES
// We can't just use _snprintf as a drop-in-replacement, because it
// doesn't always NUL-terminate. :-(
extern GFLAGS_DLL_DECL int snprintf(char *str, size_t size,
const char *format, ...);
#define strcasecmp _stricmp
#define PRId32 "d"
#define PRIu32 "u"
#define PRId64 "I64d"
#define PRIu64 "I64u"
#ifndef __MINGW32__
#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 /* _WIN32 */
#endif /* GOOGLE_GFLAGS_WINDOWS_PORT_H_ */
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="gflags_unittest"
ProjectGUID="{4B263748-5F0F-468C-8C5C-ED2682BB6BE3}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="5"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/gflags_unittest.exe"
LinkIncremental="2"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/gflags_unittest.pdb"
SubSystem="1"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="4"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/gflags_unittest.exe"
LinkIncremental="1"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
<File
RelativePath="..\..\src\gflags_unittest.cc">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
RuntimeLibrary="3"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
RuntimeLibrary="2"/>
</FileConfiguration>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{AFC737F1-C7A5-4376-A066-2A32D752A2FF}">
<File
RelativePath="..\..\src\windows\gflags\gflags.h">
</File>
<File
RelativePath="..\..\src\windows\gflags\gflags_completions.h">
</File>
<File
RelativePath="..\..\src\windows\config.h">
</File>
<File
RelativePath="..\..\src\config_for_unittests.h">
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="libgflags"
ProjectGUID="{FB27FBDB-E6C0-4D00-A7F8-1EEEF1B48ABC}"
RootNamespace="libgflags"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBGFLAGS_EXPORTS"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/libgflags-debug.dll"
LinkIncremental="2"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/libgflags-debug.pdb"
SubSystem="2"
ImportLibrary="$(OutDir)/libgflags-debug.lib"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBGFLAGS_EXPORTS"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/libgflags.dll"
LinkIncremental="1"
GenerateDebugInformation="TRUE"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
ImportLibrary="$(OutDir)/libgflags.lib"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
<File
RelativePath="..\..\src\gflags.cc">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
RuntimeLibrary="3"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
RuntimeLibrary="2"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\gflags_reporting.cc">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
RuntimeLibrary="3"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
RuntimeLibrary="2"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\gflags_completions.cc">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
RuntimeLibrary="3"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
RuntimeLibrary="2"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\windows\port.cc">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
RuntimeLibrary="3"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
RuntimeLibrary="2"/>
</FileConfiguration>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
<File
RelativePath="..\..\src\mutex.h">
</File>
<File
RelativePath="..\..\src\windows\gflags\gflags.h">
</File>
<File
RelativePath="..\..\src\windows\gflags\gflags_completions.h">
</File>
<File
RelativePath="..\..\src\windows\config.h">
</File>
<File
RelativePath="..\..\src\windows\port.h">
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment