Compare commits

...
3 Commits
Author SHA1 Message Date
Clifford Yapp 22b58f489a Looks like we won't need this branch after all.
(svn branch delete)

svn:revision:57418
svn:branch:popt
svn:account:starseeker
2013-09-04 14:14:53 +00:00
Clifford Yapp 768753fb7d Integrate popt option handling library version 1.16 from http://rpm5.org/files/popt/
svn:revision:57410
svn:branch:popt
svn:account:starseeker
2013-09-04 01:09:26 +00:00
Clifford Yapp 3a1063e437 Branch for experimenting with the popt option handling library.
svn:revision:57409
svn:branch:popt
svn:account:starseeker
2013-09-04 00:39:38 +00:00
29 changed files with 9506 additions and 2 deletions
+11
View File
@@ -629,6 +629,17 @@ BRLCAD_ENABLE_TK is OFF.
Aliases: ENABLE_TKTABLE
--- BRLCAD_LIBPOPT ---
Option for enabling and disabling compilation of the libpopt triangle
simplification library provided with BRL-CAD's source code. Default
is AUTO, responsive to the toplevel BRLCAD_BUNDLED_LIBS option and
testing first for a system version if BRLCAD_BUNDLED_LIBS is also
AUTO.
Aliases: ENABLE_POPT
--- BRLCAD_OPENNURBS ---
Option for enabling and disabling compilation of the openNURBS library
Vendored
+4
View File
@@ -154,6 +154,10 @@ do
shift;;
--disable-tktable) options="$options -DBRLCAD_TKTABLE=SYSTEM";
shift;;
--enable-popt) options="$options -DBRLCAD_LIBPOPT=BUNDLED";
shift;;
--disable-popt) options="$options -DBRLCAD_LIBPOPT=SYSTEM";
shift;;
--enable-opennurbs) options="$options -DBRLCAD_OPENNURBS=BUNDLED";
shift;;
--disable-opennurbs) options="$options -DBRLCAD_OPENNURBS=SYSTEM";
+60
View File
@@ -0,0 +1,60 @@
# F I N D P O P T . C M A K E
# BRL-CAD
#
# Copyright (c) 2013 United States Government as represented by
# the U.S. Army Research Laboratory.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. 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.
#
# 3. The name of the author may not be used to endorse or promote
# products derived from this software without specific prior written
# permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
#
###
# - Find View Dependent Simplification library
#
# The following variables are set:
#
# POPT_INCLUDE_DIRS - where to find popt.h, etc.
# POPT_LIBRARIES - List of libraries when using popt.
# POPT_FOUND - True if popt found.
find_path(POPT_INCLUDE_DIR popt.h)
find_library(POPT_LIBRARY NAMES popt poptlib)
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(POPT DEFAULT_MSG POPT_LIBRARY POPT_INCLUDE_DIR)
IF (POPT_FOUND)
set(POPT_INCLUDE_DIRS ${POPT_INCLUDE_DIR})
set(POPT_LIBRARIES ${POPT_LIBRARY})
endif()
# Local Variables:
# tab-width: 8
# mode: cmake
# indent-tabs-mode: t
# End:
# ex: shiftwidth=2 tabstop=8
+5 -2
View File
@@ -6,7 +6,10 @@ set(BU_INCLUDE_DIRS
)
# locally used but not needed by users of the library
set(BU_LOCAL_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR})
set(BU_LOCAL_INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}
${LIBPOPT_INCLUDE_DIR}
)
BRLCAD_LIB_INCLUDE_DIRS(bu BU_INCLUDE_DIRS BU_LOCAL_INCLUDE_DIRS)
@@ -95,7 +98,7 @@ set(LIBBU_SOURCES
xdr.c
)
BRLCAD_ADDLIB(libbu "${LIBBU_SOURCES}" "${CMAKE_THREAD_LIBS_INIT};${TCL_LIBRARY};${WINSOCK_LIB};${PSAPI_LIB};${M_LIBRARY}")
BRLCAD_ADDLIB(libbu "${LIBBU_SOURCES}" "${CMAKE_THREAD_LIBS_INIT};${LIBPOPT_LIBRARY};${TCL_LIBRARY};${WINSOCK_LIB};${PSAPI_LIB};${M_LIBRARY}")
set_target_properties(libbu PROPERTIES VERSION 20.0.1 SOVERSION 20)
get_directory_property(BRLCAD_TCL_BUILD DIRECTORY ${BRLCAD_SOURCE_DIR}/src/other DEFINITION BRLCAD_TCL_BUILD)
if("${BRLCAD_TCL_BUILD}" STREQUAL "ON")
+15
View File
@@ -768,6 +768,21 @@ DISTCLEAN(${CMAKE_BINARY_DIR}/lib/Tktable2.10)
#DISTCLEAN(${CMAKE_CURRENT_BINARY_DIR}/tktreectrl/tktreectrl_cfg.h)
#DISTCLEAN(${CMAKE_BINARY_DIR}/lib/TkTreeCtrl2.4)
# POPTlib - An option parsing library
set(libpopt_ALIASES ENABLE_POPT)
set(libpopt_DESCRIPTION "
Option for enabling and disabling compilation of the libpopt triangle
simplification library provided with BRL-CAD's source code. Default
is AUTO, responsive to the toplevel BRLCAD_BUNDLED_LIBS option and
testing first for a system version if BRLCAD_BUNDLED_LIBS is also
AUTO.
")
THIRD_PARTY(libpopt libpopt "" libpopt_ALIASES libpopt_DESCRIPTION NOSYS)
set(LIBPOPT_INCLUDE_DIR "${BRLCAD_SOURCE_DIR}/src/other/libpopt" CACHE STRING "Directory containing libpopt headers." FORCE)
# OpenNURBS Library
set(opennurbs_ALIASES ENABLE_OPENNURBS)
set(opennurbs_DESCRIPTION "
+18
View File
@@ -0,0 +1,18 @@
SET(libpopt_ignore_files
CHANGES
COPYING
Doxyfile.in
Makefile.am
README
configure.ac
lookup3.c
popt.3
popt.h
popt.spec.in
poptint.h
system.h
tdict.c
test1.c
test2.c
testit.sh
)
+204
View File
@@ -0,0 +1,204 @@
1.15 -> 1.16:
- add lv.po, update translations (Translation Project).
- include xcode project files in distributed popt tar ball.
- make distcheck is now squeaky clean.
- permit VPATH builds.
- add shallow tests using ISP/RAS api-sanity-autotest.pl.
- prefix bit set routines with popt to avoid symbol coolisions w rpm.
- add tdict.c to exercise popt bit sets against /usr/dict/words.
- add poptBitsArgs() method to generate args bit set.
- add methods for bit set union and intersection.
- permit comma separated attribute lists, handle negated attributes.
- better test for POPT_ARG_BITSET.
- add POPT_ARG_BITSET handling.
- add POPT_ARG_SHORT handling.
- handle all callback traversals within a C switch (for extendability ease).
- add popt.pc.
- devzero2000: add AC_CONFIG_AUX_DIR, AC_CONFIG_MACRO_DIR to configure. Create build-aux
- devzero2000: del acinclude.m4 : AC_CHECK_VA_COPY is not used
1.14 -> 1.15:
- release popt-1.15.
- rse: fix building under --disable-nls
- rse: fix building under non GLIBC platforms where glob_pattern_p fallback has to be used
- rse: fix building under platforms where FNM_EXTMATCH is not available
- jbj: poptReadFile: permit NULL if return values are not desired.
- jbj: poptReadFile: add routine.
- jbj: trim out escaped newline(s) from file content, other fixes.
- jbj: permit popt alias/exec to include content from a file.
- jbj: permit glob(3) patterns in appName field of popt alias/exec config.
- jbj: add test cases for bit operations and toggles.
- jbj: avoid displaying --[no]nofoo with POPT_ARGFLAG_TOGGLE.
- jbj: add poptArgInfo() to get argInfo, implementing POPT_ARGFLAG_TOGGLE.
- jbj: add longOptionStrcmp() to match w POPT_ARGFLAG_TOGGLE.
- jbj: change singleDash arg to a bit enum, use LF_ISSET(ONEDASH) instead.
- jbj: rework the glob wrappers into something more useful. portability todo++.
- jbj: stub in glob(3) wrappers for popt. more useful poptGlob() API next.
- jbj: add poptInit/poptFini/poptReadConfigFiles/poptSaneFile routines.
- jbj: rewrite poptReadConfigFile(), styling for (i.e. my) readbility.
- jbj: reserve a bit for --[no]opt prefix toggling.
- jbj: fix: check/print argv[0] in --help for NULL.
- jbj: permit type/group bitmasks to be changed (if needed somewhen).
- jbj: snip out 8 unused bits for argument groups.
- jbj: fix: eliminate dead code (CID#5).
- jbj: fix: rearrange code to better hint to coverity scan (CID#9).
- jbj: fix: rewrite (and simplify) strdup_locale_from_utf8() (CID#7, CID#8, CID#11, CID#12).
- jbj: test/use HAVE_SRANDOM to avoid portability issues.
- jbj: fix: remove AC_CHECK_VA_COPY check, va_copy is no longer used.
- jbj: add eo.po and id.po (Translation Project).
- jbj: updated da.po (Translation Project).
- jbj: extend coverage to several additional setup routines.
- jbj: add tests for --usage/--help coverage.
- jbj: add lconv/gcov targets to Makefile.am.
- jbj: refactor automagic (*opt->arg) option arg store to poptSaveArg().
- ldv: update INPUT tag in Doxyfile.in, fix doxygen warnings in popthelp.c.
- start popt-1.15 development.
1.13 -> 1.14:
- release popt-1.14.
- jbj: remove findme.c, add poptint.c, to po/POTFILES.in.
- jbj: use stpcpy 2 more places (Wayne Davison<wayned@samba.org>).
- jbj: add @LTLIBICONV@ when needed (Stanislav Brabec<sbrabec@suse.cz>).
- jbj: fix: remove the "echo --" Fedorable hack-a-round.
- rsc: updated de.po (not from the Translation Project).
- jbj: study the mess with splint. Sigh, splint is so easily confused ...
- jbj: rewrite findProgramPath & move to popt.c. Nuke the findme.{c,h} toys.
- jbj: use stpcpy several more places (Wayne Davison<wayned@samba.org>).
- jbj: enable equal after short option (Wayne Davison<wayned@samba.org>).
- jbj: permit "#define POPT_fprintf fprintf" to lose the malloc'ing fprintf.
- jbj: use vasprintf(3) when available (Wayne Davison<wayned@samba.org>).
- jbj: study the mess with splint, remove annotations where possible.
- jbj: add -D_GNU_SOURCE for gcc to use __builtin_stpcpy when available.
- jbj: add static inline stpcpy for the deprived.
- jbj: use stpcpy to eliminate sprintf calls everywhere but popthelp.c
- jbj: remove (now unneeded afaik) va_copy() from POPT_fprintf().
- jbj: inline strdup_fprintf() => POPT_fprintf keeping (unneeded?) va_copy.
- rse: fix memcpy(3) based va_copy(3) fallbacks
- jbj: fix: short option with "foo=bar" argument was mishandled.
(Wayne Davison<wayned@samba.org>).
- jbj: rename _ABS to avoid collisions, define DBL_EPSILON if not present
(Wayne Davison<wayned@samba.org>).
- jbj: test for <glob.h>, disable reading directory poptrc files if not.
- jbj: add __attribute__(__unused__) (Wayne Davison<wayned@samba.org>).
- jbj: permit equal after short option (Wayne Davison<wayned@samba.org>).
- jbj: make sure that short options are printed only once with --usage.
- jbj: don't display hidden short options with --usage.
- jbj: updated sv.po (Translation Project).
- jbj: updated {fi,nl}.po (Translation Project).
- jbj: updated th.po (Translation Project).
- rsc: avoid multilib file conflicts in generated doxygen.
- jbj: updated vi.po and zh_CN.po (Translation Project).
- jbj: fix: keep the poptHelpOptions array exactly the same size.
- jbj: updated pl.po (Translation Project).
- jbj: add new fi, th, zh_TW translations (Translation Project).
- jbj: add "make updatepo" to simplify PO file maintenance.
- jbj: display POPT_ARG_ARGV options in --help just like other options.
- jbj: add test for POPT_ARG_ARGV handling.
- jbj: fix: permit "--foo bar" and "--foo=bar" equivalent forms for aliases.
- jbj: fix: tests 20 -> 23 require an explicit '--' arg separator now.
- jbj: popt.3: add POPT_ARG_ARGV description.
- jbj: use NUL terminator to align help with (possible) multibyte chars.
- jbj: add utf8_skip_data table[] to keep track of utf8 character widths.
- jbj: refactor the POPT_WCHAR_HACK into stringDisplayWidth().
- jbj: add POPT_dgettext() prototype.
- jbj: add POPT_dgettext() for popt internal UTF-8 codeset (Takao Fujiwara).
- jbj: add POPT_next_char(), backout POPT_fprintf() usage (for the moment).
- jbj: finish POPT_ARG_ARGV implementation.
- jbj: free aliases/execs with common code.
- jbj: rewrite the callback logic using a switch for simplicity.
- jbj: hide bit field structure behind F_ISSET/LF_ISSET/CBF_ISSET macros.
- jbj: expose poptSaveLongLong and poptSaveString in the loader map.
- jbj: add POPT_ARG_ARGV, starting with the poptSaveString() method.
- jbj: add help for POPT_ARG_LONGLONG.
- jbj: hmmm, POSIXly correct --echo-args needs fixing, disable for now.
- jbj: poptint.h: typedef's for string and string arrays.
- jbj: add POPT_ARG_LONGLONG, and poptSaveLongLong().
- jbj: poptint.h: add poptSubstituteHelpI18N() to bury the ABI hack.
- jbj: start using poptArg and poptArgType() where useful.
- jbj: poptint.h: add a poptArgType define for bitfield type abstraction.
- jbj: poptint.h: add a poptArg union for opt->arg access without casts.
- jbj: include "-- Terminate options" end-of-options msg in poptHelpOptions.
- jbj: opt->argDescrip[0] determines "--foo=bar" or "--foo bar".
- jbj: --long always padded for alignment with/without "-X, ".
- jbj: Display shortName iff printable non-space.
- jbj: POPT_AUTOALIAS: if no popt aliases/execs, don't display the sub-head.
- jbj: add --libdir=/%{_lib} to popt.spec.
- jbj: add .cvsignore to m4 subdirectory.
- jbj: remove duplicate nb locale from ALL_LINGUAS.
- jbj: autogen.sh: on linux, add --libdir=/lib (no /lib64 autodetect yet).
1.12 -> 1.13:
- release popt-1.13.
- jbj: add a %track section (as in rpm-5.0) to popt.spec.
- jbj: chg poptGetOptArg() to "char *", document application needs to free.
- jbj: re-add it.po (from Sandro Bonazzola <sandro.bonazzola@gmail.com>).
- jbj: rescuscitate the splint annotations.
- jbj: change sizeof to use the type implicitly, rather than explicitly.
- jbj: remove incorrect casts, changing to size_t where needed.
- jbj: remove unused STD_VFPRINTF macro.
- jbj: reindent (and otherwise diddle) recent patch for popt coding style.
- jbj: remove splint bounds/branch annotations, little gain, much pain.
- jbj: revert alloca usage again again.
- jbj: handle Solaris signed character isspace(3) issues consistently.
- bero: read /etc/popt.d/* files.
- jbj: don't read /etc/popt twice (#290531).
- jbj: isspace(3) has i18n encoding signednesss issues on Solaris (#172393).
- jbj: refactor column cursor to a structure, carry maxcols as well.
- jbj: use TIOCGWINSZ to determine --help column wrapping.
- jbj: help formatting for POPT_ARG_MAINCALL.
- jbj: remove N_(...) markings from popt.h, markers in popthelp.c instead.
- jbj: add zh_CN.po (Translation Project).
- jbj: use PACKAGE_BUGREPORT.
- jbj: hotwire POPT_AUTOHELP/POPT_AUTOALIAS lookup in popt i18n domain.
1.11 -> 1.12
- jbj: plug a memory leak.
- jbj: fix index thinko.
- jbj: add vi.po (Translation Project).
- jbj: add nl.po (Translation Project).
1.5 -> 1.6
- add ability to perform callbacks for every, not just first, match.
1.3 -> 1.5
- heavy dose of const's
- poptParseArgvString() now NULL terminates the list
1.2.3 -> 1.3
- added support for single -
- misc bug fixes
- portability improvements
1.2.2 -> 1.2.3
- fixed memset() in help message generation (Dale Hawkins)
- added extern "C" stuff to popt.h for C++ compilers (Dale Hawkins)
- const'ified poptParseArgvString (Jeff Garzik)
1.2.1 -> 1.2.2
- fixed bug in chaind alias happens which seems to have only
affected --triggers in rpm
- added POPT_ARG_VAL
- popt.3 installed by default
1.2 -> 1.2.1
- added POPT_ARG_INTL_DOMAIN (Elliot Lee)
- updated Makefile's to be more GNUish (Elliot Lee)
1.1 -> 1.2
- added popt.3 man page (Robert Lynch)
- don't use mmap anymore (its lack of portability isn't worth the
trouble)
- added test script
- added support for exec
- removed support for *_POPT_ALIASES env variable -- it was a bad
idea
- reorganized into multiple source files
- added automatic help generation, POPT_AUTOHELP
- added table callbacks
- added table inclusion
- updated man page for new features
- added test scripts
1.0 -> 1.1
- moved to autoconf (Fred Fish)
- added STRERROR replacement (Norbert Warmuth)
- added const keywords (Bruce Perens)
+109
View File
@@ -0,0 +1,109 @@
# Minimum required version of CMake
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
IF(COMMAND CMAKE_POLICY)
CMAKE_POLICY(SET CMP0003 NEW)
ENDIF(COMMAND CMAKE_POLICY)
# Set CMake project name
PROJECT(POPT)
set(PACKAGE popt)
set(VERSION 1.16)
set(PACKAGE_VERSION ${VERSION})
set(POPT_SYSCONFDIR /etc/conf)
#---------------------------------------------------------------------
# Configure install locations. Don't set these if they have already
# been set by some other means (like a higher level CMakeLists.txt file
# including this one.)
# The location in which to install executables.
if(NOT BIN_DIR)
set(BIN_DIR bin)
endif(NOT BIN_DIR)
# The location in which to install header files.
if(NOT INCLUDE_DIR)
set(INCLUDE_DIR include)
endif(NOT INCLUDE_DIR)
# The location in which to install libraries.
if(NOT LIB_DIR)
if(NOT WIN32)
set(LIB_DIR lib)
else(NOT WIN32)
set(LIB_DIR bin)
endif(NOT WIN32)
endif(NOT LIB_DIR)
# The location in which to install Manual pages
if(NOT MAN_DIR)
set(MAN_DIR man)
endif(NOT MAN_DIR)
include(CheckIncludeFiles)
CHECK_INCLUDE_FILES(float.h HAVE_FLOAT_H)
CHECK_INCLUDE_FILES(fnmatch.h HAVE_FNMATCH_H)
CHECK_INCLUDE_FILES(glob.h HAVE_GLOB_H)
CHECK_INCLUDE_FILES(langinfo.h HAVE_LANGINFO_H)
CHECK_INCLUDE_FILES(libintl.h HAVE_LIBINTL_H)
CHECK_INCLUDE_FILES(mcheck.h HAVE_MCHECK_H)
CHECK_INCLUDE_FILES(unistd.h HAVE_UNISTD_H)
include(CheckFunctionExists)
CHECK_FUNCTION_EXISTS(setreuid HAVE_SETREUID)
CHECK_FUNCTION_EXISTS(getuid HAVE_GETUID)
CHECK_FUNCTION_EXISTS(geteuid HAVE_GETEUID)
CHECK_FUNCTION_EXISTS(iconv HAVE_ICONV)
CHECK_FUNCTION_EXISTS(mtrace HAVE_MTRACE)
CHECK_FUNCTION_EXISTS(__set_getenv HAVE___SET_GETENV)
CHECK_FUNCTION_EXISTS(setregid HAVE_SETREGID)
CHECK_FUNCTION_EXISTS(stpcpy HAVE_STPCPY)
CHECK_FUNCTION_EXISTS(strerror HAVE_STRERROR)
CHECK_FUNCTION_EXISTS(vasprintf HAVE_VASPRINTF)
CHECK_FUNCTION_EXISTS(srandom HAVE_SRANDOM)
configure_file(config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
add_definitions(-DHAVE_CONFIG_H)
include_directories(
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}
)
set(POPT_SRCS popt.c poptparse.c poptconfig.c popthelp.c poptint.c)
set(UNUSED_SRCS lookup3.c)
set(TEST_SRCS test1.c test2.c tdict.c)
set(POPT_HDRS popt.h)
set(POPT_NOINST_HDRS poptint.h system.h)
add_library(libpopt SHARED ${POPT_SRCS})
install(TARGETS libpopt
RUNTIME DESTINATION ${BIN_DIR}
LIBRARY DESTINATION ${LIB_DIR}
ARCHIVE DESTINATION ${LIB_DIR})
if(MSVC)
set_property(TARGET libpopt APPEND PROPERTY COMPILE_DEFINITIONS "POPT_DLL_EXPORTS")
endif(MSVC)
if(BUILD_STATIC_LIBS)
add_library(libpopt-static STATIC ${POPT_SRCS})
if(CMAKE_CL_64)
set_target_properties(libpopt-static PROPERTIES STATIC_LIBRARY_FLAGS "/machine:x64")
endif(CMAKE_CL_64)
endif(BUILD_STATIC_LIBS)
# Local Variables:
# tab-width: 8
# mode: cmake
# indent-tabs-mode: t
# End:
# ex: shiftwidth=2 tabstop=8
+22
View File
@@ -0,0 +1,22 @@
Copyright (c) 1998 Red Hat Software
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of the X Consortium shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from the X Consortium.
File diff suppressed because it is too large Load Diff
+118
View File
@@ -0,0 +1,118 @@
# Makefile for popt library.
AUTOMAKE_OPTIONS = 1.4 foreign
LINT = splint
MCCABE = pmccabe
EXTRA_DIST = config.rpath lookup3.c autogen.sh CHANGES $(man_MANS) \
m4/Makefile.in \
footer_no_timestamp.html libpopt.vers \
testit.sh test-poptrc \
popt.xcodeproj/project.pbxproj \
popt.ps
SUBDIRS = po . auto
AM_CPPFLAGS = -I. -I$(top_srcdir)
noinst_HEADERS = poptint.h system.h
noinst_PROGRAMS = test1 test2 tdict # test3
test1_SOURCES = test1.c
test1_LDFLAGS =
test1_LDADD = $(usrlib_LTLIBRARIES)
test2_SOURCES = test2.c
test2_LDFLAGS =
test2_LDADD = $(usrlib_LTLIBRARIES)
#test3_SOURCES = test3.c
#test3_LDFLAGS =
#test3_LDADD = $(usrlib_LTLIBRARIES)
tdict_SOURCES = tdict.c
tdict_LDFLAGS =
tdict_LDADD = $(usrlib_LTLIBRARIES)
noinst_SCRIPTS = testit.sh
TESTS_ENVIRONMENT = \
test1="$(top_builddir)/test1"
TESTS = $(top_srcdir)/testit.sh
include_HEADERS = popt.h
usrlibdir = $(libdir)
usrlib_LTLIBRARIES = libpopt.la
libpopt_la_SOURCES = popt.c poptparse.c poptconfig.c popthelp.c poptint.c
libpopt_la_LDFLAGS = -no-undefined @LTLIBINTL@ @LTLIBICONV@
pkgconfigdir = $(prefix)/lib/pkgconfig
pkgconfig_DATA = popt.pc
if HAVE_LD_VERSION_SCRIPT
libpopt_la_LDFLAGS += -Wl,--version-script=$(top_srcdir)/libpopt.vers
endif
man_MANS = popt.3
BUILT_SOURCES = popt.pc # popt.lcd
distclean-local:
rm -rf .ccache
.PHONY: updatepo
updatepo:
rsync -Lrtvz translationproject.org::tp/latest/popt/ po
popt.lcd: Makefile.am ${libpopt_la_SOURCES} ${include_HEADERS} ${noinst_HEADERS}
lclint -dump $@ ${libpopt_la_SOURCES}
.PHONY: sources
sources:
@echo $(libpopt_la_SOURCES:%=popt/%)
.PHONY: lint
lint:
$(LINT) ${DEFS} ${INCLUDES} test1.c ${libpopt_la_SOURCES}
.PHONY: mccabe
mccabe:
$(MCCABE) $(libpopt_la_SOURCES) | sort -n -r | head -n 10
.PHONY: doxygen
doxygen: Doxyfile
rm -rf doxygen
mkdir -p doxygen
doxygen
.PHONY: lcov-reset # run lcov from scratch, always
lcov-reset:
make lcov-run
make lcov-report
.PHONY: lcov # run lcov from scratch if the dir is not there
lcov:
make lcov-reset
.PHONY: lcov-run # reset run coverage tests
lcov-run:
@-rm -rf lcov
find . -name "*.gcda" -exec rm {} \;
make check
.PHONY: lcov-report # generate report based on current coverage data
lcov-report:
mkdir lcov
lcov --directory . --capture --output-file lcov/lcov.info
lcov -l lcov/lcov.info | grep -v "`cd $(top_srcdir) && pwd`" | cut -d: -f1 > lcov/remove
lcov -r lcov/lcov.info `cat lcov/remove` > lcov/lcov.cleaned.info
rm lcov/remove
mv lcov/lcov.cleaned.info lcov/lcov.info
genhtml -t "$(PACKAGE_STRING)" -o lcov lcov/lcov.info
#.PHONY: lcov-upload
#lcov-upload: lcov
# rsync -rvz -e ssh --delete lcov/* ???
ACLOCAL_AMFLAGS = -I m4
+16
View File
@@ -0,0 +1,16 @@
This is the popt(3) command line option parsing library. While it is similiar
to getopt(3), it contains a number of enhancements, including:
1) popt is fully reentrant
2) popt can parse arbitrary argv[] style arrays while
getopt(3) makes this quite difficult
3) popt allows users to alias command line arguments
4) popt provides convience functions for parsing strings
into argv[] style arrays
Complete documentation on popt(3) is available in popt.ps (included in this
tarball), which is excerpted with permission from the book "Linux
Application Development" by Michael K. Johnson and Erik Troan (available
from Addison Wesley in May, 1998).
Comments on popt should be addressed to popt-devel@rpm5.org.
+106
View File
@@ -0,0 +1,106 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if you have the <dlfcn.h> header file. */
#cmakedefine HAVE_DLFCN_H 1
/* Define to 1 if you have the <float.h> header file. */
#cmakedefine HAVE_FLOAT_H 1
/* Define to 1 if you have the <fnmatch.h> header file. */
#cmakedefine HAVE_FNMATCH_H 1
/* Define to 1 if you have the `geteuid' function. */
#cmakedefine HAVE_GETEUID 1
/* Define if the GNU gettext() function is already present or preinstalled. */
#cmakedefine HAVE_GETTEXT 1
/* Define to 1 if you have the `getuid' function. */
#cmakedefine HAVE_GETUID 1
/* Define to 1 if you have the <glob.h> header file. */
#cmakedefine HAVE_GLOB_H 1
/* Define if you have the iconv() function and it works. */
#cmakedefine HAVE_ICONV 1
/* Define to 1 if you have the <inttypes.h> header file. */
#cmakedefine HAVE_INTTYPES_H 1
/* Define to 1 if you have the <langinfo.h> header file. */
#cmakedefine HAVE_LANGINFO_H 1
/* Define to 1 if you have the <libintl.h> header file. */
#cmakedefine HAVE_LIBINTL_H 1
/* Define to 1 if you have the <mcheck.h> header file. */
#cmakedefine HAVE_MCHECK_H 1
/* Define to 1 if you have the <memory.h> header file. */
#cmakedefine HAVE_MEMORY_H 1
/* Define to 1 if you have the `mtrace' function. */
#cmakedefine HAVE_MTRACE 1
/* Define to 1 if you have the `setregid' function. */
#cmakedefine HAVE_SETREGID 1
/* Define to 1 if you have the `srandom' function. */
#cmakedefine HAVE_SRANDOM 1
/* Define to 1 if you have the <stdint.h> header file. */
#cmakedefine HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#cmakedefine HAVE_STDLIB_H 1
/* Define to 1 if you have the `stpcpy' function. */
#cmakedefine HAVE_STPCPY 1
/* Define to 1 if you have the `strerror' function. */
#cmakedefine HAVE_STRERROR 1
/* Define to 1 if you have the <strings.h> header file. */
#cmakedefine HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#cmakedefine HAVE_STRING_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#cmakedefine HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#cmakedefine HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#cmakedefine HAVE_UNISTD_H 1
/* Define to 1 if you have the `vasprintf' function. */
#cmakedefine HAVE_VASPRINTF 1
/* Define to 1 if you have the `__secure_getenv' function. */
#cmakedefine HAVE___SECURE_GETENV 1
/* Name of package */
#cmakedefine PACKAGE "@PACKAGE@"
/* Version number of package */
#cmakedefine VERSION @VERSION@
/* Define to the version of this package. */
#cmakedefine PACKAGE_VERSION @PACKAGE_VERSION@
/* Define the system configuration directory for Popt. */
#cmakedefine POPT_SYSCONFDIR "@POPT_SYSCONFDIR@"
/* Define to 1 if the C compiler supports function prototypes. */
#cmakedefine PROTOTYPES 1
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Number of bits in a file offset, on hosts where this is settable. */
#cmakedefine _FILE_OFFSET_BITS
/* Define like PROTOTYPES; this can be used by system headers. */
#cmakedefine __PROTOTYPES
+135
View File
@@ -0,0 +1,135 @@
AC_PREREQ(2.57)
AC_INIT(popt, 1.16, popt-devel@rpm5.org)
AC_CONFIG_SRCDIR([popt.h])
AC_CONFIG_HEADERS([config.h])
AC_CANONICAL_TARGET
dnl Must come before AM_INIT_AUTOMAKE.
dnl AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([foreign -Wall])
AM_MAINTAINER_MODE
# Library code modified: REVISION++
# Interfaces changed/added/removed: CURRENT++ REVISION=0
# Interfaces added: AGE++
# Interfaces removed: AGE=0
AC_SUBST(LT_CURRENT, 0)
AC_SUBST(LT_REVISION, 0)
AC_SUBST(LT_AGE, 8)
ALL_LINGUAS="cs da de eo es fi fr ga gl hu id is it ja ko lv nb nl pl pt ro ru sk sl sv th tr uk vi wa zh_TW zh_CN"
AC_PROG_CC_STDC
AC_PROG_CC
AC_PROG_INSTALL
AC_PROG_LIBTOOL
dnl if CC is gcc, we can rebuild the dependencies (since the depend rule
dnl requires gcc). If it's not, don't rebuild dependencies -- use what was
dnl shipped with RPM.
if test X"$GCC" = "Xyes"; then
CFLAGS="$CFLAGS -Wall -W"
TARGET="depend allprogs"
else
TARGET="everything"
dnl let the Makefile know that we're done with `depend', since we don't
dnl have gcc we're not going to rebuild our dependencies at all.
echo >.depend-done
fi
AC_SUBST(TARGET)
CFLAGS="$CFLAGS -D_GNU_SOURCE -D_REENTRANT"
AC_GCC_TRADITIONAL
AC_SYS_LARGEFILE
AC_ISC_POSIX
AM_C_PROTOTYPES
AC_CHECK_HEADERS(float.h fnmatch.h glob.h langinfo.h libintl.h mcheck.h unistd.h)
# For some systems we know that we have ld_version scripts.
# Use it then as default.
have_ld_version_script=no
case "${host}" in
*-*-linux*)
have_ld_version_script=yes
;;
*-*-gnu*)
have_ld_version_script=yes
;;
esac
AC_ARG_ENABLE([ld-version-script],
AC_HELP_STRING([--enable-ld-version-script],
[enable/disable use of linker version script.
(default is system dependent)]),
[have_ld_version_script=$enableval],
[ : ] )
AM_CONDITIONAL(HAVE_LD_VERSION_SCRIPT, test "$have_ld_version_script" = "yes")
AC_ARG_ENABLE(build-gcov,
AS_HELP_STRING([--enable-build-gcov], [build POPT instrumented for gcov]), [dnl
if test ".$enableval" = .yes; then
if test ".`$CC --version 2>&1 | grep 'GCC'`" != .; then
dnl # GNU GCC (usually "gcc")
CFLAGS="$CFLAGS -fprofile-arcs -ftest-coverage"
fi
fi
])
AC_CHECK_FUNC(setreuid, [], [
AC_CHECK_LIB(ucb, setreuid, [if echo $LIBS | grep -- -lucb >/dev/null ;then :; else LIBS="$LIBS -lc -lucb" USEUCB=y;fi])
])
AC_CHECK_FUNCS(getuid geteuid iconv mtrace __secure_getenv setregid stpcpy strerror vasprintf srandom)
AM_GNU_GETTEXT([external])
AM_ICONV_LINK
popt_sysconfdir="${sysconfdir}"
eval "popt_sysconfdir=\"${popt_sysconfdir}\"" # expand contained ${prefix}
AC_DEFINE_UNQUOTED([POPT_SYSCONFDIR], ["$popt_sysconfdir"], [Full path to default POPT configuration directory])
# Define a (hope) portable Libs pkgconfig directive that
# - Don't harm if the default library search path include ${libdir}
# (https://bugzilla.novell.com/show_bug.cgi?id=529921)
# - Don't require a not upstream patch to pkgconfig
# (https://bugs.freedesktop.org/show_bug.cgi?id=16095)
popt_pkgconfig_libs='-L${libdir} -lpopt'
case "${host}" in
*-*-linux*)
case "${libdir}" in
/usr/lib|/usr/lib64|/lib|/lib64)
popt_pkgconfig_libs='-lpopt'
;;
*)
popt_pkgconfig_libs='-L${libdir} -lpopt'
;;
esac
;;
*-*-gnu*)
case "${libdir}" in
/usr/lib|/usr/lib64|/lib|/lib64)
popt_pkgconfig_libs='-lpopt'
;;
*)
popt_pkgconfig_libs='-L${libdir} -lpopt'
;;
esac
;;
esac
AC_SUBST([POPT_PKGCONFIG_LIBS],"$popt_pkgconfig_libs")
POPT_SOURCE_PATH="`pwd`"
AC_DEFINE_UNQUOTED(POPT_SOURCE_PATH, "$POPT_SOURCE_PATH",
[Full path to popt top_srcdir.])
AC_SUBST(POPT_SOURCE_PATH)
AC_CONFIG_SUBDIRS()
AC_CONFIG_FILES([ po/Makefile.in m4/Makefile
Doxyfile Makefile popt.pc popt.spec test-poptrc
auto/Makefile auto/desc auto/types
])
AC_OUTPUT
+969
View File
@@ -0,0 +1,969 @@
/* -------------------------------------------------------------------- */
/*
* lookup3.c, by Bob Jenkins, May 2006, Public Domain.
*
* These are functions for producing 32-bit hashes for hash table lookup.
* jlu32w(), jlu32l(), jlu32lpair(), jlu32b(), _JLU3_MIX(), and _JLU3_FINAL()
* are externally useful functions. Routines to test the hash are included
* if SELF_TEST is defined. You can use this free for any purpose. It's in
* the public domain. It has no warranty.
*
* You probably want to use jlu32l(). jlu32l() and jlu32b()
* hash byte arrays. jlu32l() is is faster than jlu32b() on
* little-endian machines. Intel and AMD are little-endian machines.
* On second thought, you probably want jlu32lpair(), which is identical to
* jlu32l() except it returns two 32-bit hashes for the price of one.
* You could implement jlu32bpair() if you wanted but I haven't bothered here.
*
* If you want to find a hash of, say, exactly 7 integers, do
* a = i1; b = i2; c = i3;
* _JLU3_MIX(a,b,c);
* a += i4; b += i5; c += i6;
* _JLU3_MIX(a,b,c);
* a += i7;
* _JLU3_FINAL(a,b,c);
* then use c as the hash value. If you have a variable size array of
* 4-byte integers to hash, use jlu32w(). If you have a byte array (like
* a character string), use jlu32l(). If you have several byte arrays, or
* a mix of things, see the comments above jlu32l().
*
* Why is this so big? I read 12 bytes at a time into 3 4-byte integers,
* then mix those integers. This is fast (you can do a lot more thorough
* mixing with 12*3 instructions on 3 integers than you can with 3 instructions
* on 1 byte), but shoehorning those bytes into integers efficiently is messy.
*/
/* -------------------------------------------------------------------- */
#include <stdint.h>
#if defined(_JLU3_SELFTEST)
# define _JLU3_jlu32w 1
# define _JLU3_jlu32l 1
# define _JLU3_jlu32lpair 1
# define _JLU3_jlu32b 1
#endif
/*@-redef@*/
/*@unchecked@*/
static const union _dbswap {
const uint32_t ui;
const unsigned char uc[4];
} endian = { .ui = 0x11223344 };
# define HASH_LITTLE_ENDIAN (endian.uc[0] == (unsigned char) 0x44)
# define HASH_BIG_ENDIAN (endian.uc[0] == (unsigned char) 0x11)
/*@=redef@*/
#ifndef ROTL32
# define ROTL32(x, s) (((x) << (s)) | ((x) >> (32 - (s))))
#endif
/* NOTE: The _size parameter should be in bytes. */
#define _JLU3_INIT(_h, _size) (0xdeadbeef + ((uint32_t)(_size)) + (_h))
/* -------------------------------------------------------------------- */
/*
* _JLU3_MIX -- mix 3 32-bit values reversibly.
*
* This is reversible, so any information in (a,b,c) before _JLU3_MIX() is
* still in (a,b,c) after _JLU3_MIX().
*
* If four pairs of (a,b,c) inputs are run through _JLU3_MIX(), or through
* _JLU3_MIX() in reverse, there are at least 32 bits of the output that
* are sometimes the same for one pair and different for another pair.
* This was tested for:
* * pairs that differed by one bit, by two bits, in any combination
* of top bits of (a,b,c), or in any combination of bottom bits of
* (a,b,c).
* * "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
* the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
* is commonly produced by subtraction) look like a single 1-bit
* difference.
* * the base values were pseudorandom, all zero but one bit set, or
* all zero plus a counter that starts at zero.
*
* Some k values for my "a-=c; a^=ROTL32(c,k); c+=b;" arrangement that
* satisfy this are
* 4 6 8 16 19 4
* 9 15 3 18 27 15
* 14 9 3 7 17 3
* Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing
* for "differ" defined as + with a one-bit base and a two-bit delta. I
* used http://burtleburtle.net/bob/hash/avalanche.html to choose
* the operations, constants, and arrangements of the variables.
*
* This does not achieve avalanche. There are input bits of (a,b,c)
* that fail to affect some output bits of (a,b,c), especially of a. The
* most thoroughly mixed value is c, but it doesn't really even achieve
* avalanche in c.
*
* This allows some parallelism. Read-after-writes are good at doubling
* the number of bits affected, so the goal of mixing pulls in the opposite
* direction as the goal of parallelism. I did what I could. Rotates
* seem to cost as much as shifts on every machine I could lay my hands
* on, and rotates are much kinder to the top and bottom bits, so I used
* rotates.
*/
/* -------------------------------------------------------------------- */
#define _JLU3_MIX(a,b,c) \
{ \
a -= c; a ^= ROTL32(c, 4); c += b; \
b -= a; b ^= ROTL32(a, 6); a += c; \
c -= b; c ^= ROTL32(b, 8); b += a; \
a -= c; a ^= ROTL32(c,16); c += b; \
b -= a; b ^= ROTL32(a,19); a += c; \
c -= b; c ^= ROTL32(b, 4); b += a; \
}
/* -------------------------------------------------------------------- */
/**
* _JLU3_FINAL -- final mixing of 3 32-bit values (a,b,c) into c
*
* Pairs of (a,b,c) values differing in only a few bits will usually
* produce values of c that look totally different. This was tested for
* * pairs that differed by one bit, by two bits, in any combination
* of top bits of (a,b,c), or in any combination of bottom bits of
* (a,b,c).
* * "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
* the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
* is commonly produced by subtraction) look like a single 1-bit
* difference.
* * the base values were pseudorandom, all zero but one bit set, or
* all zero plus a counter that starts at zero.
*
* These constants passed:
* 14 11 25 16 4 14 24
* 12 14 25 16 4 14 24
* and these came close:
* 4 8 15 26 3 22 24
* 10 8 15 26 3 22 24
* 11 8 15 26 3 22 24
*/
/* -------------------------------------------------------------------- */
#define _JLU3_FINAL(a,b,c) \
{ \
c ^= b; c -= ROTL32(b,14); \
a ^= c; a -= ROTL32(c,11); \
b ^= a; b -= ROTL32(a,25); \
c ^= b; c -= ROTL32(b,16); \
a ^= c; a -= ROTL32(c,4); \
b ^= a; b -= ROTL32(a,14); \
c ^= b; c -= ROTL32(b,24); \
}
#if defined(_JLU3_jlu32w)
uint32_t jlu32w(uint32_t h, /*@null@*/ const uint32_t *k, size_t size)
/*@*/;
/* -------------------------------------------------------------------- */
/**
* This works on all machines. To be useful, it requires
* -- that the key be an array of uint32_t's, and
* -- that the size be the number of uint32_t's in the key
*
* The function jlu32w() is identical to jlu32l() on little-endian
* machines, and identical to jlu32b() on big-endian machines,
* except that the size has to be measured in uint32_ts rather than in
* bytes. jlu32l() is more complicated than jlu32w() only because
* jlu32l() has to dance around fitting the key bytes into registers.
*
* @param h the previous hash, or an arbitrary value
* @param *k the key, an array of uint32_t values
* @param size the size of the key, in uint32_ts
* @return the lookup3 hash
*/
/* -------------------------------------------------------------------- */
uint32_t jlu32w(uint32_t h, const uint32_t *k, size_t size)
{
uint32_t a = _JLU3_INIT(h, (size * sizeof(*k)));
uint32_t b = a;
uint32_t c = a;
if (k == NULL)
goto exit;
/*----------------------------------------------- handle most of the key */
while (size > 3) {
a += k[0];
b += k[1];
c += k[2];
_JLU3_MIX(a,b,c);
size -= 3;
k += 3;
}
/*----------------------------------------- handle the last 3 uint32_t's */
switch (size) {
case 3 : c+=k[2];
case 2 : b+=k[1];
case 1 : a+=k[0];
_JLU3_FINAL(a,b,c);
/*@fallthrough@*/
case 0:
break;
}
/*---------------------------------------------------- report the result */
exit:
return c;
}
#endif /* defined(_JLU3_jlu32w) */
#if defined(_JLU3_jlu32l)
uint32_t jlu32l(uint32_t h, const void *key, size_t size)
/*@*/;
/* -------------------------------------------------------------------- */
/*
* jlu32l() -- hash a variable-length key into a 32-bit value
* h : can be any 4-byte value
* k : the key (the unaligned variable-length array of bytes)
* size : the size of the key, counting by bytes
* Returns a 32-bit value. Every bit of the key affects every bit of
* the return value. Two keys differing by one or two bits will have
* totally different hash values.
*
* The best hash table sizes are powers of 2. There is no need to do
* mod a prime (mod is sooo slow!). If you need less than 32 bits,
* use a bitmask. For example, if you need only 10 bits, do
* h = (h & hashmask(10));
* In which case, the hash table should have hashsize(10) elements.
*
* If you are hashing n strings (uint8_t **)k, do it like this:
* for (i=0, h=0; i<n; ++i) h = jlu32l(h, k[i], len[i]);
*
* By Bob Jenkins, 2006. bob_jenkins@burtleburtle.net. You may use this
* code any way you wish, private, educational, or commercial. It's free.
*
* Use for hash table lookup, or anything where one collision in 2^^32 is
* acceptable. Do NOT use for cryptographic purposes.
*
* @param h the previous hash, or an arbitrary value
* @param *k the key, an array of uint8_t values
* @param size the size of the key
* @return the lookup3 hash
*/
/* -------------------------------------------------------------------- */
uint32_t jlu32l(uint32_t h, const void *key, size_t size)
{
union { const void *ptr; size_t i; } u;
uint32_t a = _JLU3_INIT(h, size);
uint32_t b = a;
uint32_t c = a;
if (key == NULL)
goto exit;
u.ptr = key;
if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {
const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */
#ifdef VALGRIND
const uint8_t *k8;
#endif
/*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
while (size > 12) {
a += k[0];
b += k[1];
c += k[2];
_JLU3_MIX(a,b,c);
size -= 12;
k += 3;
}
/*------------------------- handle the last (probably partial) block */
/*
* "k[2]&0xffffff" actually reads beyond the end of the string, but
* then masks off the part it's not allowed to read. Because the
* string is aligned, the masked-off tail is in the same word as the
* rest of the string. Every machine with memory protection I've seen
* does it on word boundaries, so is OK with this. But VALGRIND will
* still catch it and complain. The masking trick does make the hash
* noticably faster for short strings (like English words).
*/
#ifndef VALGRIND
switch (size) {
case 12: c += k[2]; b+=k[1]; a+=k[0]; break;
case 11: c += k[2]&0xffffff; b+=k[1]; a+=k[0]; break;
case 10: c += k[2]&0xffff; b+=k[1]; a+=k[0]; break;
case 9: c += k[2]&0xff; b+=k[1]; a+=k[0]; break;
case 8: b += k[1]; a+=k[0]; break;
case 7: b += k[1]&0xffffff; a+=k[0]; break;
case 6: b += k[1]&0xffff; a+=k[0]; break;
case 5: b += k[1]&0xff; a+=k[0]; break;
case 4: a += k[0]; break;
case 3: a += k[0]&0xffffff; break;
case 2: a += k[0]&0xffff; break;
case 1: a += k[0]&0xff; break;
case 0: goto exit;
}
#else /* make valgrind happy */
k8 = (const uint8_t *)k;
switch (size) {
case 12: c += k[2]; b+=k[1]; a+=k[0] break;
case 11: c += ((uint32_t)k8[10])<<16; /*@fallthrough@*/
case 10: c += ((uint32_t)k8[9])<<8; /*@fallthrough@*/
case 9: c += k8[8]; /*@fallthrough@*/
case 8: b += k[1]; a+=k[0]; break;
case 7: b += ((uint32_t)k8[6])<<16; /*@fallthrough@*/
case 6: b += ((uint32_t)k8[5])<<8; /*@fallthrough@*/
case 5: b += k8[4]; /*@fallthrough@*/
case 4: a += k[0]; break;
case 3: a += ((uint32_t)k8[2])<<16; /*@fallthrough@*/
case 2: a += ((uint32_t)k8[1])<<8; /*@fallthrough@*/
case 1: a += k8[0]; break;
case 0: goto exit;
}
#endif /* !valgrind */
} else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) {
const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */
const uint8_t *k8;
/*----------- all but last block: aligned reads and different mixing */
while (size > 12) {
a += k[0] + (((uint32_t)k[1])<<16);
b += k[2] + (((uint32_t)k[3])<<16);
c += k[4] + (((uint32_t)k[5])<<16);
_JLU3_MIX(a,b,c);
size -= 12;
k += 6;
}
/*------------------------- handle the last (probably partial) block */
k8 = (const uint8_t *)k;
switch (size) {
case 12:
c += k[4]+(((uint32_t)k[5])<<16);
b += k[2]+(((uint32_t)k[3])<<16);
a += k[0]+(((uint32_t)k[1])<<16);
break;
case 11:
c += ((uint32_t)k8[10])<<16;
/*@fallthrough@*/
case 10:
c += (uint32_t)k[4];
b += k[2]+(((uint32_t)k[3])<<16);
a += k[0]+(((uint32_t)k[1])<<16);
break;
case 9:
c += (uint32_t)k8[8];
/*@fallthrough@*/
case 8:
b += k[2]+(((uint32_t)k[3])<<16);
a += k[0]+(((uint32_t)k[1])<<16);
break;
case 7:
b += ((uint32_t)k8[6])<<16;
/*@fallthrough@*/
case 6:
b += (uint32_t)k[2];
a += k[0]+(((uint32_t)k[1])<<16);
break;
case 5:
b += (uint32_t)k8[4];
/*@fallthrough@*/
case 4:
a += k[0]+(((uint32_t)k[1])<<16);
break;
case 3:
a += ((uint32_t)k8[2])<<16;
/*@fallthrough@*/
case 2:
a += (uint32_t)k[0];
break;
case 1:
a += (uint32_t)k8[0];
break;
case 0:
goto exit;
}
} else { /* need to read the key one byte at a time */
const uint8_t *k = (const uint8_t *)key;
/*----------- all but the last block: affect some 32 bits of (a,b,c) */
while (size > 12) {
a += (uint32_t)k[0];
a += ((uint32_t)k[1])<<8;
a += ((uint32_t)k[2])<<16;
a += ((uint32_t)k[3])<<24;
b += (uint32_t)k[4];
b += ((uint32_t)k[5])<<8;
b += ((uint32_t)k[6])<<16;
b += ((uint32_t)k[7])<<24;
c += (uint32_t)k[8];
c += ((uint32_t)k[9])<<8;
c += ((uint32_t)k[10])<<16;
c += ((uint32_t)k[11])<<24;
_JLU3_MIX(a,b,c);
size -= 12;
k += 12;
}
/*---------------------------- last block: affect all 32 bits of (c) */
switch (size) {
case 12: c += ((uint32_t)k[11])<<24; /*@fallthrough@*/
case 11: c += ((uint32_t)k[10])<<16; /*@fallthrough@*/
case 10: c += ((uint32_t)k[9])<<8; /*@fallthrough@*/
case 9: c += (uint32_t)k[8]; /*@fallthrough@*/
case 8: b += ((uint32_t)k[7])<<24; /*@fallthrough@*/
case 7: b += ((uint32_t)k[6])<<16; /*@fallthrough@*/
case 6: b += ((uint32_t)k[5])<<8; /*@fallthrough@*/
case 5: b += (uint32_t)k[4]; /*@fallthrough@*/
case 4: a += ((uint32_t)k[3])<<24; /*@fallthrough@*/
case 3: a += ((uint32_t)k[2])<<16; /*@fallthrough@*/
case 2: a += ((uint32_t)k[1])<<8; /*@fallthrough@*/
case 1: a += (uint32_t)k[0];
break;
case 0:
goto exit;
}
}
_JLU3_FINAL(a,b,c);
exit:
return c;
}
#endif /* defined(_JLU3_jlu32l) */
#if defined(_JLU3_jlu32lpair)
/**
* jlu32lpair: return 2 32-bit hash values.
*
* This is identical to jlu32l(), except it returns two 32-bit hash
* values instead of just one. This is good enough for hash table
* lookup with 2^^64 buckets, or if you want a second hash if you're not
* happy with the first, or if you want a probably-unique 64-bit ID for
* the key. *pc is better mixed than *pb, so use *pc first. If you want
* a 64-bit value do something like "*pc + (((uint64_t)*pb)<<32)".
*
* @param h the previous hash, or an arbitrary value
* @param *key the key, an array of uint8_t values
* @param size the size of the key in bytes
* @retval *pc, IN: primary initval, OUT: primary hash
* *retval *pb IN: secondary initval, OUT: secondary hash
*/
void jlu32lpair(const void *key, size_t size, uint32_t *pc, uint32_t *pb)
{
union { const void *ptr; size_t i; } u;
uint32_t a = _JLU3_INIT(*pc, size);
uint32_t b = a;
uint32_t c = a;
if (key == NULL)
goto exit;
c += *pb; /* Add the secondary hash. */
u.ptr = key;
if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {
const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */
#ifdef VALGRIND
const uint8_t *k8;
#endif
/*-- all but last block: aligned reads and affect 32 bits of (a,b,c) */
while (size > (size_t)12) {
a += k[0];
b += k[1];
c += k[2];
_JLU3_MIX(a,b,c);
size -= 12;
k += 3;
}
/*------------------------- handle the last (probably partial) block */
/*
* "k[2]&0xffffff" actually reads beyond the end of the string, but
* then masks off the part it's not allowed to read. Because the
* string is aligned, the masked-off tail is in the same word as the
* rest of the string. Every machine with memory protection I've seen
* does it on word boundaries, so is OK with this. But VALGRIND will
* still catch it and complain. The masking trick does make the hash
* noticably faster for short strings (like English words).
*/
#ifndef VALGRIND
switch (size) {
case 12: c += k[2]; b+=k[1]; a+=k[0]; break;
case 11: c += k[2]&0xffffff; b+=k[1]; a+=k[0]; break;
case 10: c += k[2]&0xffff; b+=k[1]; a+=k[0]; break;
case 9: c += k[2]&0xff; b+=k[1]; a+=k[0]; break;
case 8: b += k[1]; a+=k[0]; break;
case 7: b += k[1]&0xffffff; a+=k[0]; break;
case 6: b += k[1]&0xffff; a+=k[0]; break;
case 5: b += k[1]&0xff; a+=k[0]; break;
case 4: a += k[0]; break;
case 3: a += k[0]&0xffffff; break;
case 2: a += k[0]&0xffff; break;
case 1: a += k[0]&0xff; break;
case 0: goto exit;
}
#else /* make valgrind happy */
k8 = (const uint8_t *)k;
switch (size) {
case 12: c += k[2]; b+=k[1]; a+=k[0]; break;
case 11: c += ((uint32_t)k8[10])<<16; /*@fallthrough@*/
case 10: c += ((uint32_t)k8[9])<<8; /*@fallthrough@*/
case 9: c += k8[8]; /*@fallthrough@*/
case 8: b += k[1]; a+=k[0]; break;
case 7: b += ((uint32_t)k8[6])<<16; /*@fallthrough@*/
case 6: b += ((uint32_t)k8[5])<<8; /*@fallthrough@*/
case 5: b += k8[4]; /*@fallthrough@*/
case 4: a += k[0]; break;
case 3: a += ((uint32_t)k8[2])<<16; /*@fallthrough@*/
case 2: a += ((uint32_t)k8[1])<<8; /*@fallthrough@*/
case 1: a += k8[0]; break;
case 0: goto exit;
}
#endif /* !valgrind */
} else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) {
const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */
const uint8_t *k8;
/*----------- all but last block: aligned reads and different mixing */
while (size > (size_t)12) {
a += k[0] + (((uint32_t)k[1])<<16);
b += k[2] + (((uint32_t)k[3])<<16);
c += k[4] + (((uint32_t)k[5])<<16);
_JLU3_MIX(a,b,c);
size -= 12;
k += 6;
}
/*------------------------- handle the last (probably partial) block */
k8 = (const uint8_t *)k;
switch (size) {
case 12:
c += k[4]+(((uint32_t)k[5])<<16);
b += k[2]+(((uint32_t)k[3])<<16);
a += k[0]+(((uint32_t)k[1])<<16);
break;
case 11:
c += ((uint32_t)k8[10])<<16;
/*@fallthrough@*/
case 10:
c += k[4];
b += k[2]+(((uint32_t)k[3])<<16);
a += k[0]+(((uint32_t)k[1])<<16);
break;
case 9:
c += k8[8];
/*@fallthrough@*/
case 8:
b += k[2]+(((uint32_t)k[3])<<16);
a += k[0]+(((uint32_t)k[1])<<16);
break;
case 7:
b += ((uint32_t)k8[6])<<16;
/*@fallthrough@*/
case 6:
b += k[2];
a += k[0]+(((uint32_t)k[1])<<16);
break;
case 5:
b += k8[4];
/*@fallthrough@*/
case 4:
a += k[0]+(((uint32_t)k[1])<<16);
break;
case 3:
a += ((uint32_t)k8[2])<<16;
/*@fallthrough@*/
case 2:
a += k[0];
break;
case 1:
a += k8[0];
break;
case 0:
goto exit;
}
} else { /* need to read the key one byte at a time */
const uint8_t *k = (const uint8_t *)key;
/*----------- all but the last block: affect some 32 bits of (a,b,c) */
while (size > (size_t)12) {
a += k[0];
a += ((uint32_t)k[1])<<8;
a += ((uint32_t)k[2])<<16;
a += ((uint32_t)k[3])<<24;
b += k[4];
b += ((uint32_t)k[5])<<8;
b += ((uint32_t)k[6])<<16;
b += ((uint32_t)k[7])<<24;
c += k[8];
c += ((uint32_t)k[9])<<8;
c += ((uint32_t)k[10])<<16;
c += ((uint32_t)k[11])<<24;
_JLU3_MIX(a,b,c);
size -= 12;
k += 12;
}
/*---------------------------- last block: affect all 32 bits of (c) */
switch (size) {
case 12: c += ((uint32_t)k[11])<<24; /*@fallthrough@*/
case 11: c += ((uint32_t)k[10])<<16; /*@fallthrough@*/
case 10: c += ((uint32_t)k[9])<<8; /*@fallthrough@*/
case 9: c += k[8]; /*@fallthrough@*/
case 8: b += ((uint32_t)k[7])<<24; /*@fallthrough@*/
case 7: b += ((uint32_t)k[6])<<16; /*@fallthrough@*/
case 6: b += ((uint32_t)k[5])<<8; /*@fallthrough@*/
case 5: b += k[4]; /*@fallthrough@*/
case 4: a += ((uint32_t)k[3])<<24; /*@fallthrough@*/
case 3: a += ((uint32_t)k[2])<<16; /*@fallthrough@*/
case 2: a += ((uint32_t)k[1])<<8; /*@fallthrough@*/
case 1: a += k[0];
break;
case 0:
goto exit;
}
}
_JLU3_FINAL(a,b,c);
exit:
*pc = c;
*pb = b;
return;
}
#endif /* defined(_JLU3_jlu32lpair) */
#if defined(_JLU3_jlu32b)
uint32_t jlu32b(uint32_t h, /*@null@*/ const void *key, size_t size)
/*@*/;
/*
* jlu32b():
* This is the same as jlu32w() on big-endian machines. It is different
* from jlu32l() on all machines. jlu32b() takes advantage of
* big-endian byte ordering.
*
* @param h the previous hash, or an arbitrary value
* @param *k the key, an array of uint8_t values
* @param size the size of the key
* @return the lookup3 hash
*/
uint32_t jlu32b(uint32_t h, const void *key, size_t size)
{
union { const void *ptr; size_t i; } u;
uint32_t a = _JLU3_INIT(h, size);
uint32_t b = a;
uint32_t c = a;
if (key == NULL)
return h;
u.ptr = key;
if (HASH_BIG_ENDIAN && ((u.i & 0x3) == 0)) {
const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */
#ifdef VALGRIND
const uint8_t *k8;
#endif
/*-- all but last block: aligned reads and affect 32 bits of (a,b,c) */
while (size > 12) {
a += k[0];
b += k[1];
c += k[2];
_JLU3_MIX(a,b,c);
size -= 12;
k += 3;
}
/*------------------------- handle the last (probably partial) block */
/*
* "k[2]<<8" actually reads beyond the end of the string, but
* then shifts out the part it's not allowed to read. Because the
* string is aligned, the illegal read is in the same word as the
* rest of the string. Every machine with memory protection I've seen
* does it on word boundaries, so is OK with this. But VALGRIND will
* still catch it and complain. The masking trick does make the hash
* noticably faster for short strings (like English words).
*/
#ifndef VALGRIND
switch (size) {
case 12: c += k[2]; b+=k[1]; a+=k[0]; break;
case 11: c += k[2]&0xffffff00; b+=k[1]; a+=k[0]; break;
case 10: c += k[2]&0xffff0000; b+=k[1]; a+=k[0]; break;
case 9: c += k[2]&0xff000000; b+=k[1]; a+=k[0]; break;
case 8: b += k[1]; a+=k[0]; break;
case 7: b += k[1]&0xffffff00; a+=k[0]; break;
case 6: b += k[1]&0xffff0000; a+=k[0]; break;
case 5: b += k[1]&0xff000000; a+=k[0]; break;
case 4: a += k[0]; break;
case 3: a += k[0]&0xffffff00; break;
case 2: a += k[0]&0xffff0000; break;
case 1: a += k[0]&0xff000000; break;
case 0: goto exit;
}
#else /* make valgrind happy */
k8 = (const uint8_t *)k;
switch (size) { /* all the case statements fall through */
case 12: c += k[2]; b+=k[1]; a+=k[0]; break;
case 11: c += ((uint32_t)k8[10])<<8; /*@fallthrough@*/
case 10: c += ((uint32_t)k8[9])<<16; /*@fallthrough@*/
case 9: c += ((uint32_t)k8[8])<<24; /*@fallthrough@*/
case 8: b += k[1]; a+=k[0]; break;
case 7: b += ((uint32_t)k8[6])<<8; /*@fallthrough@*/
case 6: b += ((uint32_t)k8[5])<<16; /*@fallthrough@*/
case 5: b += ((uint32_t)k8[4])<<24; /*@fallthrough@*/
case 4: a += k[0]; break;
case 3: a += ((uint32_t)k8[2])<<8; /*@fallthrough@*/
case 2: a += ((uint32_t)k8[1])<<16; /*@fallthrough@*/
case 1: a += ((uint32_t)k8[0])<<24; break;
case 0: goto exit;
}
#endif /* !VALGRIND */
} else { /* need to read the key one byte at a time */
const uint8_t *k = (const uint8_t *)key;
/*----------- all but the last block: affect some 32 bits of (a,b,c) */
while (size > 12) {
a += ((uint32_t)k[0])<<24;
a += ((uint32_t)k[1])<<16;
a += ((uint32_t)k[2])<<8;
a += ((uint32_t)k[3]);
b += ((uint32_t)k[4])<<24;
b += ((uint32_t)k[5])<<16;
b += ((uint32_t)k[6])<<8;
b += ((uint32_t)k[7]);
c += ((uint32_t)k[8])<<24;
c += ((uint32_t)k[9])<<16;
c += ((uint32_t)k[10])<<8;
c += ((uint32_t)k[11]);
_JLU3_MIX(a,b,c);
size -= 12;
k += 12;
}
/*---------------------------- last block: affect all 32 bits of (c) */
switch (size) { /* all the case statements fall through */
case 12: c += k[11]; /*@fallthrough@*/
case 11: c += ((uint32_t)k[10])<<8; /*@fallthrough@*/
case 10: c += ((uint32_t)k[9])<<16; /*@fallthrough@*/
case 9: c += ((uint32_t)k[8])<<24; /*@fallthrough@*/
case 8: b += k[7]; /*@fallthrough@*/
case 7: b += ((uint32_t)k[6])<<8; /*@fallthrough@*/
case 6: b += ((uint32_t)k[5])<<16; /*@fallthrough@*/
case 5: b += ((uint32_t)k[4])<<24; /*@fallthrough@*/
case 4: a += k[3]; /*@fallthrough@*/
case 3: a += ((uint32_t)k[2])<<8; /*@fallthrough@*/
case 2: a += ((uint32_t)k[1])<<16; /*@fallthrough@*/
case 1: a += ((uint32_t)k[0])<<24; /*@fallthrough@*/
break;
case 0:
goto exit;
}
}
_JLU3_FINAL(a,b,c);
exit:
return c;
}
#endif /* defined(_JLU3_jlu32b) */
#if defined(_JLU3_SELFTEST)
/* used for timings */
static void driver1(void)
/*@*/
{
uint8_t buf[256];
uint32_t i;
uint32_t h=0;
time_t a,z;
time(&a);
for (i=0; i<256; ++i) buf[i] = 'x';
for (i=0; i<1; ++i) {
h = jlu32l(h, &buf[0], sizeof(buf[0]));
}
time(&z);
if (z-a > 0) printf("time %d %.8x\n", (int)(z-a), h);
}
/* check that every input bit changes every output bit half the time */
#define HASHSTATE 1
#define HASHLEN 1
#define MAXPAIR 60
#define MAXLEN 70
static void driver2(void)
/*@*/
{
uint8_t qa[MAXLEN+1], qb[MAXLEN+2], *a = &qa[0], *b = &qb[1];
uint32_t c[HASHSTATE], d[HASHSTATE], i=0, j=0, k, l, m=0, z;
uint32_t e[HASHSTATE],f[HASHSTATE],g[HASHSTATE],h[HASHSTATE];
uint32_t x[HASHSTATE],y[HASHSTATE];
uint32_t hlen;
printf("No more than %d trials should ever be needed \n",MAXPAIR/2);
for (hlen=0; hlen < MAXLEN; ++hlen) {
z=0;
for (i=0; i<hlen; ++i) { /*-------------- for each input byte, */
for (j=0; j<8; ++j) { /*--------------- for each input bit, */
for (m=1; m<8; ++m) { /*--- for serveral possible initvals, */
for (l=0; l<HASHSTATE; ++l)
e[l]=f[l]=g[l]=h[l]=x[l]=y[l]=~((uint32_t)0);
/* check that every output bit is affected by that input bit */
for (k=0; k<MAXPAIR; k+=2) {
uint32_t finished=1;
/* keys have one bit different */
for (l=0; l<hlen+1; ++l) {a[l] = b[l] = (uint8_t)0;}
/* have a and b be two keys differing in only one bit */
a[i] ^= (k<<j);
a[i] ^= (k>>(8-j));
c[0] = jlu32l(m, a, hlen);
b[i] ^= ((k+1)<<j);
b[i] ^= ((k+1)>>(8-j));
d[0] = jlu32l(m, b, hlen);
/* check every bit is 1, 0, set, and not set at least once */
for (l=0; l<HASHSTATE; ++l) {
e[l] &= (c[l]^d[l]);
f[l] &= ~(c[l]^d[l]);
g[l] &= c[l];
h[l] &= ~c[l];
x[l] &= d[l];
y[l] &= ~d[l];
if (e[l]|f[l]|g[l]|h[l]|x[l]|y[l]) finished=0;
}
if (finished) break;
}
if (k>z) z=k;
if (k == MAXPAIR) {
printf("Some bit didn't change: ");
printf("%.8x %.8x %.8x %.8x %.8x %.8x ",
e[0],f[0],g[0],h[0],x[0],y[0]);
printf("i %d j %d m %d len %d\n", i, j, m, hlen);
}
if (z == MAXPAIR) goto done;
}
}
}
done:
if (z < MAXPAIR) {
printf("Mix success %2d bytes %2d initvals ",i,m);
printf("required %d trials\n", z/2);
}
}
printf("\n");
}
/* Check for reading beyond the end of the buffer and alignment problems */
static void driver3(void)
/*@*/
{
uint8_t buf[MAXLEN+20], *b;
uint32_t len;
uint8_t q[] = "This is the time for all good men to come to the aid of their country...";
uint32_t h;
uint8_t qq[] = "xThis is the time for all good men to come to the aid of their country...";
uint32_t i;
uint8_t qqq[] = "xxThis is the time for all good men to come to the aid of their country...";
uint32_t j;
uint8_t qqqq[] = "xxxThis is the time for all good men to come to the aid of their country...";
uint32_t ref,x,y;
uint8_t *p;
uint32_t m = 13;
printf("Endianness. These lines should all be the same (for values filled in):\n");
printf("%.8x %.8x %.8x\n",
jlu32w(m, (const uint32_t *)q, (sizeof(q)-1)/4),
jlu32w(m, (const uint32_t *)q, (sizeof(q)-5)/4),
jlu32w(m, (const uint32_t *)q, (sizeof(q)-9)/4));
p = q;
printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n",
jlu32l(m, p, sizeof(q)-1), jlu32l(m, p, sizeof(q)-2),
jlu32l(m, p, sizeof(q)-3), jlu32l(m, p, sizeof(q)-4),
jlu32l(m, p, sizeof(q)-5), jlu32l(m, p, sizeof(q)-6),
jlu32l(m, p, sizeof(q)-7), jlu32l(m, p, sizeof(q)-8),
jlu32l(m, p, sizeof(q)-9), jlu32l(m, p, sizeof(q)-10),
jlu32l(m, p, sizeof(q)-11), jlu32l(m, p, sizeof(q)-12));
p = &qq[1];
printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n",
jlu32l(m, p, sizeof(q)-1), jlu32l(m, p, sizeof(q)-2),
jlu32l(m, p, sizeof(q)-3), jlu32l(m, p, sizeof(q)-4),
jlu32l(m, p, sizeof(q)-5), jlu32l(m, p, sizeof(q)-6),
jlu32l(m, p, sizeof(q)-7), jlu32l(m, p, sizeof(q)-8),
jlu32l(m, p, sizeof(q)-9), jlu32l(m, p, sizeof(q)-10),
jlu32l(m, p, sizeof(q)-11), jlu32l(m, p, sizeof(q)-12));
p = &qqq[2];
printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n",
jlu32l(m, p, sizeof(q)-1), jlu32l(m, p, sizeof(q)-2),
jlu32l(m, p, sizeof(q)-3), jlu32l(m, p, sizeof(q)-4),
jlu32l(m, p, sizeof(q)-5), jlu32l(m, p, sizeof(q)-6),
jlu32l(m, p, sizeof(q)-7), jlu32l(m, p, sizeof(q)-8),
jlu32l(m, p, sizeof(q)-9), jlu32l(m, p, sizeof(q)-10),
jlu32l(m, p, sizeof(q)-11), jlu32l(m, p, sizeof(q)-12));
p = &qqqq[3];
printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n",
jlu32l(m, p, sizeof(q)-1), jlu32l(m, p, sizeof(q)-2),
jlu32l(m, p, sizeof(q)-3), jlu32l(m, p, sizeof(q)-4),
jlu32l(m, p, sizeof(q)-5), jlu32l(m, p, sizeof(q)-6),
jlu32l(m, p, sizeof(q)-7), jlu32l(m, p, sizeof(q)-8),
jlu32l(m, p, sizeof(q)-9), jlu32l(m, p, sizeof(q)-10),
jlu32l(m, p, sizeof(q)-11), jlu32l(m, p, sizeof(q)-12));
printf("\n");
for (h=0, b=buf+1; h<8; ++h, ++b) {
for (i=0; i<MAXLEN; ++i) {
len = i;
for (j=0; j<i; ++j)
*(b+j)=0;
/* these should all be equal */
m = 1;
ref = jlu32l(m, b, len);
*(b+i)=(uint8_t)~0;
*(b-1)=(uint8_t)~0;
x = jlu32l(m, b, len);
y = jlu32l(m, b, len);
if ((ref != x) || (ref != y))
printf("alignment error: %.8x %.8x %.8x %d %d\n",ref,x,y, h, i);
}
}
}
/* check for problems with nulls */
static void driver4(void)
/*@*/
{
uint8_t buf[1];
uint32_t h;
uint32_t i;
uint32_t state[HASHSTATE];
buf[0] = ~0;
for (i=0; i<HASHSTATE; ++i)
state[i] = 1;
printf("These should all be different\n");
h = 0;
for (i=0; i<8; ++i) {
h = jlu32l(h, buf, 0);
printf("%2ld 0-byte strings, hash is %.8x\n", (long)i, h);
}
}
int main(int argc, char ** argv)
{
driver1(); /* test that the key is hashed: used for timings */
driver2(); /* test that whole key is hashed thoroughly */
driver3(); /* test that nothing but the key is hashed */
driver4(); /* test hashing multiple buffers (all buffers are null) */
return 1;
}
#endif /* _JLU3_SELFTEST */
+772
View File
@@ -0,0 +1,772 @@
.TH POPT 3 "June 30, 1998" "" "Linux Programmer's Manual"
.SH NAME
popt \- Parse command line options
.SH SYNOPSIS
.nf
.B #include <popt.h>
.sp
.BI "poptContext poptGetContext(const char * " name ", int " argc ,
.BI " const char ** "argv ,
.BI " const struct poptOption * " options ,
.BI " int " flags );
.sp
.BI "void poptFreeContext(poptContext " con );
.sp
.BI "void poptResetContext(poptContext " con );
.sp
.BI "int poptGetNextOpt(poptContext " con );
.sp
.BI "const char * poptGetOptArg(poptContext " con );
.sp
.BI "const char * poptGetArg(poptContext " con );
.sp
.BI "const char * poptPeekArg(poptContext " con );
.sp
.BI "const char ** poptGetArgs(poptContext " con );
.sp
.BI "const char *const poptStrerror(const int " error );
.sp
.BI "const char * poptBadOption(poptContext " con ", int " flags );
.sp
.BI "int poptReadDefaultConfig(poptContext " con ", int " flags );
.sp
.BI "int poptReadConfigFile(poptContext " con ", char * " fn );
.sp
.BI "int poptAddAlias(poptContext " con ", struct poptAlias " alias ,
.BI " int " flags );
.sp
.BI "int poptParseArgvString(char * " s ", int * " argcPtr ,
.BI " const char *** " argvPtr );
.sp
.BI "int poptDupArgv(int " argc ", const char ** " argv ", int * " argcPtr ",
.BI " const char *** " argvPtr ");"
.sp
.BI "int poptStuffArgs(poptContext " con ", const char ** " argv );
.sp
.fi
.SH DESCRIPTION
The popt library exists essentially for parsing command-line
options. It is found superior in many ways when compared to
parsing the argv array by hand or using the getopt functions
.B getopt()
and
.B getopt_long()
[see
.BR getopt "(3)]."
Some specific advantages of popt are: it does not utilize global
.RI "variables, thus enabling multiple passes in parsing " argv
.RI "; it can parse an arbitrary array of " argv "-style elements, "
allowing parsing of command-line-strings from any source;
it provides a standard method of option aliasing (to be
discussed at length below.); it can exec external option filters; and,
finally, it can automatically generate help and usage messages for
the application.
.sp
Like
.BR getopt_long() ,
the popt library supports short and long style options. Recall
that a
.B short option
consists of a - character followed by a single alphanumeric character.
A
.BR "long option" ,
common in GNU utilities, consists of two - characters followed by a
string made up of letters, numbers and hyphens. Long options are
optionally allowed to begin with a single -, primarily to allow command-line
compatibility between popt applications and X toolkit applications.
Either type of option may be followed by an argument. A space separates a
short option from its arguments; either a space or an = separates a long
option from an argument.
.sp
The popt library is highly portable and should work on any POSIX
platform. The latest version is distributed with rpm and is always available
from: ftp://ftp.rpm.org/pub/rpm/dist.
.sp
It may be redistributed under the X consortium license, see the file COPYING
in the popt source distribution for details.
.SH "BASIC POPT USAGE"
.SS "1. THE OPTION TABLE"
Applications provide popt with information on their command-line
options by means of an "option table," i.e., an array of
.B struct poptOption
structures:
.sp
#include <popt.h>
.sp
.nf
struct poptOption {
const char * longName; /* may be NULL */
char shortName; /* may be '\\0' */
int argInfo;
void * arg; /* depends on argInfo */
int val; /* 0 means don't return, just update flag */
char * descrip; /* description for autohelp -- may be NULL */
char * argDescrip; /* argument description for autohelp */
};
.fi
.sp
Each member of the table defines a single option that may be
passed to the program. Long and short options are considered
a single option that may occur in two different forms. The
first two members,
.IR longName " and " shortName ", define the names of the option;"
the first is a long name, while the latter is a single character.
.sp
The
.IR argInfo " member tells popt what type of argument is expected"
after the option. If no argument is expected,
.B POPT_ARG_NONE
should be used.
The rest of the valid values are shown in the following table:
.sp
.TS
lfB lfB lfB
lfB lfR lfR.
Value Description arg Type
POPT_ARG_NONE No argument expected int
POPT_ARG_STRING No type checking to be performed char *
POPT_ARG_ARGV No type checking to be performed char **
POPT_ARG_SHORT An short argument is expected short
POPT_ARG_INT An integer argument is expected int
POPT_ARG_LONG A long integer is expected long
POPT_ARG_LONGLONG A long long integer is expected long long
POPT_ARG_VAL Integer value taken from \f(CWval\fR int
POPT_ARG_FLOAT An float argument is expected float
POPT_ARG_DOUBLE A double argument is expected double
.TE
.sp
For numeric values, if the \fIargInfo\fR value is bitwise or'd with one of
\fBPOPT_ARGFLAG_OR\fR, \fBPOPT_ARGFLAG_AND\fR, or \fBPOPT_ARGFLAG_XOR\fR,
the value is saved by performing an OR, AND, or XOR.
If the \fIargInfo\fR value is bitwise or'd with \fBPOPT_ARGFLAG_NOT\fR,
the value will be negated before saving. For the common operations of
setting and/or clearing bits, \fBPOPT_BIT_SET\fR and \fBPOPT_BIT_CLR\fR
have the appropriate flags set to perform bit operations.
.sp
If the \fIargInfo\fR value is bitwise or'd with \fBPOPT_ARGFLAG_ONEDASH\fR,
the long argument may be given with a single - instead of two. For example,
if \fB--longopt\fR is an option with \fBPOPT_ARGFLAG_ONEDASH\fR, is
specified, \fB-longopt\fR is accepted as well.
.sp
.RI "The next element, " arg ", allows popt to automatically update "
.RI "program variables when the option is used. If " arg " is "
.BR NULL ", it is ignored and popt takes no special action. "
Otherwise it should point to a variable of the type indicated in the
.RB "right-most column of the table above. A " POPT_ARG_ARGV " arg will
(re-)allocate an array of char * string pointers, append the string argument, and add a
.BR NULL " sentinel at the end of the array as needed."
.RB "The target char ** address of a " POPT_ARG_ARGV " arg should be initialized to " NULL "."
.sp
.RI "If the option takes no argument (" argInfo " is "
.BR POPT_ARG_NONE "), the variable pointed to by "
.IR arg " is set to 1 when the option is used. (Incidentally, it "
will perhaps not escape the attention of hunt-and-peck typists that
.RB "the value of " POPT_ARG_NONE " is 0.) If the option does take "
an argument, the variable that
.IR arg " points to is updated to reflect the value of the argument."
.RB "Any string is acceptable for " POPT_ARG_STRING " and " POPT_ARG_ARGV " arguments, but "
.BR POPT_ARG_INT ", " POPT_ARG_SHORT ", " POPT_ARG_LONG ", " POPT_ARG_LONGLONG ", " POPT_ARG_FLOAT ", and "
.BR POPT_ARG_DOUBLE " are converted to the appropriate type, and an "
error returned if the conversion fails.
.sp
\fBPOPT_ARG_VAL\fR causes \fIarg\fP to be set to the (integer) value of
\fIval\fP when the argument is found. This is most often useful for
mutually-exclusive arguments in cases where it is not an error for
multiple arguments to occur and where you want the last argument
specified to win; for example, "rm -i -f". \fBPOPT_ARG_VAL\fP causes
the parsing function not to return a value, since the value of \fIval\fP
has already been used.
.sp
If the \fIargInfo\fR value is bitwise or'd with \fBPOPT_ARGFLAG_OPTIONAL\fR,
the argument to the long option may be omitted. If the long option
is used without an argument, a default value of zero or NULL will be saved
(if the arg pointer is present), otherwise behavior will be identical to
a long option with argument.
.sp
.RI "The next option, " val ", is the value popt's parsing function
should return when the option is encountered. If it is 0, the parsing
function does not return a value, instead parsing the next
command-line argument.
.sp
.RI "The last two options, " descrip " and " argDescrip " are only required
if automatic help messages are desired (automatic usage messages can
.RI "be generated without them). " descrip " is a text description of the
.RI "argument and " argdescrip " is a short summary of the type of arguments
.RI "the option expects, or NULL if the option doesn't require any
arguments.
.sp
.RB "If popt should automatically provide " --usage " and " --help " (" -? ")
.RB "options, one line in the table should be the macro " POPT_AUTOHELP ".
.RB "This macro includes another option table (via " POPT_ARG_INCLUDE_TABLE
; see below) in the main one which provides the table entries for these
.RB "arguments. When " --usage " or " --help " are passed to programs which
use popt's automatical help, popt displays the appropriate message on
stderr as soon as it finds the option, and exits the program with a
return code of 0. If you want to use popt's automatic help generation in
a different way, you need to explicitly add the option entries to your programs
.RB "option table instead of using " POPT_AUTOHELP ".
.sp
If the \fIargInfo\fR value is bitwise or'd with \fBPOPT_ARGFLAG_DOC_HIDDEN\fR,
the argument will not be shown in help output.
.sp
If the \fIargInfo\fR value is bitwise or'd with \fBPOPT_ARGFLAG_SHOW_DEFAULT\fR,
the inital value of the arg will be shown in help output.
.sp
The final structure in the table should have all the pointer values set
.RB "to " NULL " and all the arithmetic values set to 0, marking the "
.RB "end of the table. The macro " POPT_TABLEEND " is provided to do that.
.sp
There are two types of option table entries which do not specify command
line options. When either of these types of entries are used, the
\fIlongName\fR element must be \fBNULL\fR and the \fBshortName\fR element
must be \fB'\\0'\fR.
.sp
The first of these special entry types allows the application to nest
another option table in the current one; such nesting may extend quite
deeply (the actual depth is limited by the program's stack). Including
other option tables allows a library to provide a standard set of
command-line options to every program which uses it (this is often done
in graphical programming toolkits, for example). To do this, set
the \fIargInfo\fR field to \fBPOPT_ARG_INCLUDE_TABLE\fR and the
\fRarg\fR field to point to the table which is being included. If
automatic help generation is being used, the \fIdescrip\fR field should
contain a overall description of the option table being included.
.sp
The other special option table entry type tells popt to call a function (a
callback) when any option in that table is found. This is especially usefull
when included option tables are being used, as the program which provides
the top-level option table doesn't need to be aware of the other options
which are provided by the included table. When a callback is set for
a table, the parsing function never returns information on an option in
the table. Instead, options information must be retained via the callback
or by having popt set a variable through the option's \fIarg\fR field.
Option callbacks should match the following prototype:
.sp
.nf
.BI "void poptCallbackType(poptContext con,
.BI " const struct poptOption * opt,
.BI " const char * arg, void * data);
.fi
.sp
The first parameter is the context which is being parsed (see the next
section for information on contexts), \fIopt\fR points to the option
which triggered this callback, and \fIarg\fR is the option's argument.
If the option does not take an argument, \fIarg\fR is \fBNULL\fR. The
final parameter, \fIdata\fR is taken from the \fIdescrip\fR field
of the option table entry which defined the callback. As \fIdescrip\fR
is a pointer, this allows callback functions to be passed an arbitrary
set of data (though a typecast will have to be used).
.sp
The option table entry which defines a callback has an \fIargInfo\fR of
\fBPOPT_ARG_CALLBACK\fR, an \fIarg\fR which points to the callback
function, and a \fIdescrip\fR field which specifies an arbitrary pointer
to be passed to the callback.
.SS "2. CREATING A CONTEXT"
popt can interleave the parsing of multiple command-line sets. It allows
this by keeping all the state information for a particular set of
command-line arguments in a
.BR poptContext " data structure, an opaque type that should not be "
modified outside the popt library.
.sp
.RB "New popt contexts are created by " poptGetContext() ":"
.sp
.nf
.BI "poptContext poptGetContext(const char * " name ", int "argc ",
.BI " const char ** "argv ",
.BI " const struct poptOption * "options ",
.BI " int "flags ");"
.fi
.sp
The first parameter,
.IR name ", is used only for alias handling (discussed later). It "
should be the name of the application whose options are being parsed,
.RB "or should be " NULL " if no option aliasing is desired. The next "
two arguments specify the command-line arguments to parse. These are
.RB "generally passed to " poptGetContext() " exactly as they were "
.RB "passed to the program's " main() " function. The "
.IR options " parameter points to the table of command-line options, "
which was described in the previous section. The final parameter,
.IR flags ,
can take one of three values:
.br
.TS
lfB lfB
lfB lfR.
Value Description
POPT_CONTEXT_NO_EXEC Ignore exec expansions
POPT_CONTEXT_KEEP_FIRST Do not ignore argv[0]
POPT_CONTEXT_POSIXMEHARDER Options cannot follow arguments
.TE
.sp
.RB "A " poptContext " keeps track of which options have already been "
parsed and which remain, among other things. If a program wishes to
restart option processing of a set of arguments, it can reset the
.BR poptContext " by passing the context as the sole argument to "
.BR poptResetContext() .
.sp
When argument processing is complete, the process should free the
.BR poptContext " as it contains dynamically allocated components. The "
.BR poptFreeContext() " function takes a "
.BR poptContext " as its sole argument and frees the resources the "
context is using.
.sp
.RB "Here are the prototypes of both " poptResetContext() " and "
.BR poptFreeContext() :
.sp
.nf
.B #include <popt.h>
.BI "void poptFreeContext(poptContext " con ");"
.BI "void poptResetContext(poptContext " con ");"
.fi
.sp
.SS "3. PARSING THE COMMAND LINE"
.RB "After an application has created a " poptContext ", it may begin "
.RB "parsing arguments. " poptGetNextOpt() " performs the actual "
argument parsing.
.sp
.nf
.B #include <popt.h>
.BI "int poptGetNextOpt(poptContext " con ");"
.fi
.sp
Taking the context as its sole argument, this function parses the next
command-line argument found. After finding the next argument in the
option table, the function fills in the object pointed to by the option
.RI "table entry's " arg
.RB "pointer if it is not " NULL ". If the val entry for the option is "
non-0, the function then returns that value. Otherwise,
.BR poptGetNextOpt() " continues on to the next argument."
.sp
.BR poptGetNextOpt() " returns -1 when the final argument has been "
parsed, and other negative values when errors occur. This makes it a
good idea to
.RI "keep the " val " elements in the options table greater than 0."
.sp
.RI "If all of the command-line options are handled through " arg
pointers, command-line parsing is reduced to the following line of code:
.sp
.nf
rc = poptGetNextOpt(poptcon);
.fi
.sp
Many applications require more complex command-line parsing than this,
however, and use the following structure:
.sp
.nf
while ((rc = poptGetNextOpt(poptcon)) > 0) {
switch (rc) {
/* specific arguments are handled here */
}
}
.fi
.sp
When returned options are handled, the application needs to know the
value of any arguments that were specified after the option. There are two
ways to discover them. One is to ask popt to fill in a variable with the
.RI "value of the option through the option table's " arg " elements. The "
.RB "other is to use " poptGetOptArg() ":"
.sp
.nf
.B #include <popt.h>
.BI "char * poptGetOptArg(poptContext " con ");"
.fi
.sp
This function returns the argument given for the final option returned by
.BR poptGetNextOpt() ", or it returns " NULL " if no argument was specified."
The calling function is responsible for deallocating this string.
.sp
.SS "4. LEFTOVER ARGUMENTS"
Many applications take an arbitrary number of command-line arguments,
such as a list of file names. When popt encounters an argument that does
not begin with a -, it assumes it is such an argument and adds it to a list
of leftover arguments. Three functions allow applications to access such
arguments:
.nf
.HP
.BI "const char * poptGetArg(poptContext " con ");"
.fi
This function returns the next leftover argument and marks it as
processed.
.PP
.nf
.HP
.BI "const char * poptPeekArg(poptContext " con ");"
.fi
The next leftover argument is returned but not marked as processed.
This allows an application to look ahead into the argument list,
without modifying the list.
.PP
.nf
.HP
.BI "const char ** poptGetArgs(poptContext " con ");"
.fi
All the leftover arguments are returned in a manner identical to
.IR argv ". The final element in the returned array points to "
.BR NULL ", indicating the end of the arguments.
.sp
.SS "5. AUTOMATIC HELP MESSAGES"
The \fBpopt\fR library can automatically generate help messages which
describe the options a program accepts. There are two types of help
messages which can be generated. Usage messages are a short messages
which lists valid options, but does not describe them. Help messages
describe each option on one (or more) lines, resulting in a longer, but
more useful, message. Whenever automatic help messages are used, the
\fBdescrip\fR and \fBargDescrip\fR fields \fBstruct poptOption\fR members
should be filled in for each option.
.sp
The \fBPOPT_AUTOHELP\fR macro makes it easy to add \fB--usage\fR and
\fB--help\fR messages to your program, and is described in part 1
of this man page. If more control is needed over your help messages,
the following two functions are available:
.sp
.nf
.B #include <popt.h>
.BI "void poptPrintHelp(poptContext " con ", FILE * " f ", int " flags ");
.BI "void poptPrintUsage(poptContext " con ", FILE * " f ", int " flags ");
.fi
.sp
\fBpoptPrintHelp()\fR displays the standard help message to the stdio file
descriptor f, while \fBpoptPrintUsage()\fR displays the shorter usage
message. Both functions currently ignore the \fBflags\fR argument; it is
there to allow future changes.
.sp
.SH "ERROR HANDLING"
All of the popt functions that can return errors return integers.
When an error occurs, a negative error code is returned. The
following table summarizes the error codes that occur:
.sp
.nf
.B " Error Description"
.BR "POPT_ERROR_NOARG " "Argument missing for an option."
.BR "POPT_ERROR_BADOPT " "Option's argument couldn't be parsed."
.BR "POPT_ERROR_OPTSTOODEEP " "Option aliasing nested too deeply."
.BR "POPT_ERROR_BADQUOTE " "Quotations do not match."
.BR "POPT_ERROR_BADNUMBER " "Option couldn't be converted to number."
.BR "POPT_ERROR_OVERFLOW " "A given number was too big or small."
.fi
.sp
Here is a more detailed discussion of each error:
.sp
.TP
.B POPT_ERROR_NOARG
An option that requires an argument was specified on the command
line, but no argument was given. This can be returned only by
.BR poptGetNextOpt() .
.sp
.TP
.B POPT_ERROR_BADOPT
.RI "An option was specified in " argv " but is not in the option
.RB "table. This error can be returned only from " poptGetNextOpt() .
.sp
.TP
.B POPT_ERROR_OPTSTOODEEP
A set of option aliases is nested too deeply. Currently, popt
follows options only 10 levels to prevent infinite recursion. Only
.BR poptGetNextOpt() " can return this error."
.sp
.TP
.B POPT_ERROR_BADQUOTE
A parsed string has a quotation mismatch (such as a single quotation
.RB "mark). " poptParseArgvString() ", " poptReadConfigFile() ", or "
.BR poptReadDefaultConfig() " can return this error."
.sp
.TP
.B POPT_ERROR_BADNUMBER
A conversion from a string to a number (int or long) failed due
to the string containing nonnumeric characters. This occurs when
.BR poptGetNextOpt() " is processing an argument of type "
.BR POPT_ARG_INT ", " POPT_ARG_SHORT ", " POPT_ARG_LONG ", " POPT_ARG_LONGLONG ", "
.RB POPT_ARG_FLOAT ", or " POPT_ARG_DOUBLE "."
.sp
.TP
.B POPT_ERROR_OVERFLOW
A string-to-number conversion failed because the number was too
.RB "large or too small. Like " POPT_ERROR_BADNUMBER ", this error
.RB "can occur only when " poptGetNextOpt() " is processing an "
.RB "argument of type " POPT_ARG_INT ", " POPT_ARG_SHORT ", " POPT_ARG_LONG ", " POPT_ARG_LONGLONG ", "
.RB POPT_ARG_FLOAT ", or " POPT_ARG_DOUBLE "."
.sp
.TP
.B POPT_ERROR_ERRNO
.RI "A system call returned with an error, and " errno " still
contains the error from the system call. Both
.BR poptReadConfigFile() " and " poptReadDefaultConfig() " can "
return this error.
.sp
.PP
Two functions are available to make it easy for applications to provide
good error messages.
.HP
.nf
.BI "const char *const poptStrerror(const int " error ");"
.fi
This function takes a popt error code and returns a string describing
.RB "the error, just as with the standard " strerror() " function."
.PP
.HP
.nf
.BI "const char * poptBadOption(poptContext " con ", int " flags ");"
.fi
.RB "If an error occurred during " poptGetNextOpt() ", this function "
.RI "returns the option that caused the error. If the " flags " argument"
.RB "is set to " POPT_BADOPTION_NOALIAS ", the outermost option is "
.RI "returned. Otherwise, " flags " should be 0, and the option that is "
returned may have been specified through an alias.
.PP
These two functions make popt error handling trivial for most
applications. When an error is detected from most of the functions,
an error message is printed along with the error string from
.BR poptStrerror() ". When an error occurs during argument parsing, "
code similiar to the following displays a useful error message:
.sp
.nf
fprintf(stderr, "%s: %s\\n",
poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
poptStrerror(rc));
.fi
.sp
.SH "OPTION ALIASING"
.RB "One of the primary benefits of using popt over " getopt() " is the "
ability to use option aliasing. This lets the user specify options that
popt expands into other options when they are specified. If the standard
.RB "grep program made use of popt, users could add a " --text " option "
.RB "that expanded to " "-i -n -E -2" " to let them more easily find "
information in text files.
.sp
.SS "1. SPECIFYING ALIASES"
.RI "Aliases are normally specified in two places: " /etc/popt
.RB "and the " .popt " file in the user's home directory (found through "
.RB "the " HOME " environment variable). Both files have the same format, "
an arbitrary number of lines formatted like this:
.sp
.IB appname " alias " newoption "" " expansion"
.sp
.RI "The " appname " is the name of the application, which must be the "
.RI "same as the " name " parameter passed to "
.BR poptGetContext() ". This allows each file to specify aliases for "
.RB "multiple programs. The " alias " keyword specifies that an alias is "
being defined; currently popt configuration files support only aliases, but
other abilities may be added in the future. The next option is the option
that should be aliased, and it may be either a short or a long option. The
rest of the line specifies the expansion for the alias. It is parsed
similarly to a shell command, which allows \\, ", and ' to be used for
quoting. If a backslash is the final character on a line, the next line
in the file is assumed to be a logical continuation of the line containing
the backslash, just as in shell.
.sp
.RB "The following entry would add a " --text " option to the grep command, "
as suggested at the beginning of this section.
.sp
.B "grep alias --text -i -n -E -2"
.SS "2. ENABLING ALIASES"
.RB "An application must enable alias expansion for a " poptContext
.RB "before calling " poptGetNextArg() " for the first time. There are "
three functions that define aliases for a context:
.HP
.nf
.BI "int poptReadDefaultConfig(poptContext " con ", int " flags ");"
.fi
.RI "This function reads aliases from " /etc/popt " and the "
.BR .popt " file in the user's home directory. Currently, "
.IR flags " should be "
.BR NULL ", as it is provided only for future expansion."
.PP
.HP
.nf
.BI "int poptReadConfigFile(poptContext " con ", char * " fn ");"
.fi
.RI "The file specified by " fn " is opened and parsed as a popt "
configuration file. This allows programs to use program-specific
configuration files.
.PP
.HP
.nf
.BI "int poptAddAlias(poptContext " con ", struct poptAlias " alias ",
.BI " int " flags ");"
.fi
Occasionally, processes want to specify aliases without having to
read them from a configuration file. This function adds a new alias
.RI "to a context. The " flags " argument should be 0, as it is "
currently reserved for future expansion. The new alias is specified
.RB "as a " "struct poptAlias" ", which is defined as:"
.sp
.nf
struct poptAlias {
const char * longName; /* may be NULL */
char shortName; /* may be '\\0' */
int argc;
const char ** argv; /* must be free()able */
};
.fi
.sp
.RI "The first two elements, " longName " and " shortName ", specify "
.RI "the option that is aliased. The final two, " argc " and " argv ","
define the expansion to use when the aliases option is encountered.
.PP
.SH "PARSING ARGUMENT STRINGS"
Although popt is usually used for parsing arguments already divided into
.RI "an " argv "-style array, some programs need to parse strings that "
are formatted identically to command lines. To facilitate this, popt
provides a function that parses a string into an array of strings,
using rules similiar to normal shell parsing.
.sp
.nf
.B "#include <popt.h>"
.BI "int poptParseArgvString(char * " s ", int * " argcPtr ",
.BI " char *** " argvPtr ");"
.BI "int poptDupArgv(int " argc ", const char ** " argv ", int * " argcPtr ",
.BI " const char *** " argvPtr ");"
.fi
.sp
.RI "The string s is parsed into an " argv "-style array. The integer "
.RI "pointed to by the " argcPtr " parameter contains the number of elements "
.RI "parsed, and the final " argvPtr " parameter contains the address of the"
newly created array.
.RB "The routine " poptDupArgv() " can be used to make a copy of an existing "
argument array.
.sp
.RI "The " argvPtr
.RB "created by " poptParseArgvString() " or " poptDupArgv() " is suitable to pass directly "
.RB "to " poptGetContext() .
Both routines return a single dynamically allocated contiguous
.RB "block of storage and should be " free() "ed when the application is"
finished with the storage.
.SH "HANDLING EXTRA ARGUMENTS"
Some applications implement the equivalent of option aliasing but need
.RB "to do so through special logic. The " poptStuffArgs() " function "
allows an application to insert new arguments into the current
.BR poptContext .
.sp
.nf
.B "#include <popt.h>"
.BI "int poptStuffArgs(poptContext "con ", const char ** " argv ");"
.fi
.sp
.RI "The passed " argv
.RB "must have a " NULL " pointer as its final element. When "
.BR poptGetNextOpt() " is next called, the "
"stuffed" arguments are the first to be parsed. popt returns to the
normal arguments once all the stuffed arguments have been exhausted.
.SH "EXAMPLE"
The following example is a simplified version of the program "robin"
which appears in Chapter 15 of the text cited below. Robin has
been stripped of everything but its argument-parsing logic, slightly
reworked, and renamed "parse." It may prove useful in illustrating
at least some of the features of the extremely rich popt library.
.sp
.nf
#include <popt.h>
#include <stdio.h>
void usage(poptContext optCon, int exitcode, char *error, char *addl) {
poptPrintUsage(optCon, stderr, 0);
if (error) fprintf(stderr, "%s: %s\n", error, addl);
exit(exitcode);
}
int main(int argc, char *argv[]) {
char c; /* used for argument parsing */
int i = 0; /* used for tracking options */
char *portname;
int speed = 0; /* used in argument parsing to set speed */
int raw = 0; /* raw mode? */
int j;
char buf[BUFSIZ+1];
poptContext optCon; /* context for parsing command-line options */
struct poptOption optionsTable[] = {
{ "bps", 'b', POPT_ARG_INT, &speed, 0,
"signaling rate in bits-per-second", "BPS" },
{ "crnl", 'c', 0, 0, 'c',
"expand cr characters to cr/lf sequences", NULL },
{ "hwflow", 'h', 0, 0, 'h',
"use hardware (RTS/CTS) flow control", NULL },
{ "noflow", 'n', 0, 0, 'n',
"use no flow control", NULL },
{ "raw", 'r', 0, &raw, 0,
"don't perform any character conversions", NULL },
{ "swflow", 's', 0, 0, 's',
"use software (XON/XOF) flow control", NULL } ,
POPT_AUTOHELP
{ NULL, 0, 0, NULL, 0 }
};
optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
poptSetOtherOptionHelp(optCon, "[OPTIONS]* <port>");
if (argc < 2) {
poptPrintUsage(optCon, stderr, 0);
exit(1);
}
/* Now do options processing, get portname */
while ((c = poptGetNextOpt(optCon)) >= 0) {
switch (c) {
case 'c':
buf[i++] = 'c';
break;
case 'h':
buf[i++] = 'h';
break;
case 's':
buf[i++] = 's';
break;
case 'n':
buf[i++] = 'n';
break;
}
}
portname = poptGetArg(optCon);
if((portname == NULL) || !(poptPeekArg(optCon) == NULL))
usage(optCon, 1, "Specify a single port", ".e.g., /dev/cua0");
if (c < -1) {
/* an error occurred during option processing */
fprintf(stderr, "%s: %s\\n",
poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
poptStrerror(c));
return 1;
}
/* Print out options, portname chosen */
printf("Options chosen: ");
for(j = 0; j < i ; j++)
printf("-%c ", buf[j]);
if(raw) printf("-r ");
if(speed) printf("-b %d ", speed);
printf("\\nPortname chosen: %s\\n", portname);
poptFreeContext(optCon);
exit(0);
}
.fi
.sp
RPM, a popular Linux package management program, makes heavy use
of popt's features. Many of its command-line arguments are implemented
through popt aliases, which makes RPM an excellent example of how to
take advantage of the popt library. For more information on RPM, see
http://www.rpm.org. The popt source code distribution includes test
program(s) which use all of the features of the popt libraries in
various ways. If a feature isn't working for you, the popt test code
is the first place to look.
.SH BUGS
None presently known.
.SH AUTHOR
Erik W. Troan <ewt@redhat.com>
.PP
This man page is derived in part from
.IR "Linux Application Development"
by Michael K. Johnson and Erik W. Troan, Copyright (c) 1998 by Addison
Wesley Longman, Inc., and included in the popt documentation with the
permission of the Publisher and the appreciation of the Authors.
.PP
Thanks to Robert Lynch for his extensive work on this man page.
.SH "SEE ALSO"
.BR getopt (3)
.sp
.IR "Linux Application Development" ", by Michael K. Johnson and "
Erik W. Troan (Addison-Wesley, 1998; ISBN 0-201-30821-5), Chapter 24.
.sp
.BR popt.ps " is a Postscript version of the above cited book "
chapter. It can be found in the source archive for popt available at:
ftp://ftp.rpm.org/pub/rpm.
File diff suppressed because it is too large Load Diff
+744
View File
@@ -0,0 +1,744 @@
/** \file popt/popt.h
* \ingroup popt
*/
/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
ftp://ftp.rpm.org/pub/rpm/dist. */
#ifndef H_POPT
#define H_POPT
#include <stdio.h> /* for FILE * */
#define POPT_OPTION_DEPTH 10
/** \ingroup popt
* \name Arg type identifiers
*/
/*@{*/
#define POPT_ARG_NONE 0U /*!< no arg */
#define POPT_ARG_STRING 1U /*!< arg will be saved as string */
#define POPT_ARG_INT 2U /*!< arg ==> int */
#define POPT_ARG_LONG 3U /*!< arg ==> long */
#define POPT_ARG_INCLUDE_TABLE 4U /*!< arg points to table */
#define POPT_ARG_CALLBACK 5U /*!< table-wide callback... must be
set first in table; arg points
to callback, descrip points to
callback data to pass */
#define POPT_ARG_INTL_DOMAIN 6U /*!< set the translation domain
for this table and any
included tables; arg points
to the domain string */
#define POPT_ARG_VAL 7U /*!< arg should take value val */
#define POPT_ARG_FLOAT 8U /*!< arg ==> float */
#define POPT_ARG_DOUBLE 9U /*!< arg ==> double */
#define POPT_ARG_LONGLONG 10U /*!< arg ==> long long */
#define POPT_ARG_MAINCALL 16U+11U /*!< EXPERIMENTAL: return (*arg) (argc, argv) */
#define POPT_ARG_ARGV 12U /*!< dupe'd arg appended to realloc'd argv array. */
#define POPT_ARG_SHORT 13U /*!< arg ==> short */
#define POPT_ARG_BITSET 16U+14U /*!< arg ==> bit set */
#define POPT_ARG_MASK 0x000000FFU
#define POPT_GROUP_MASK 0x0000FF00U
/*@}*/
/** \ingroup popt
* \name Arg modifiers
*/
/*@{*/
#define POPT_ARGFLAG_ONEDASH 0x80000000U /*!< allow -longoption */
#define POPT_ARGFLAG_DOC_HIDDEN 0x40000000U /*!< don't show in help/usage */
#define POPT_ARGFLAG_STRIP 0x20000000U /*!< strip this arg from argv(only applies to long args) */
#define POPT_ARGFLAG_OPTIONAL 0x10000000U /*!< arg may be missing */
#define POPT_ARGFLAG_OR 0x08000000U /*!< arg will be or'ed */
#define POPT_ARGFLAG_NOR 0x09000000U /*!< arg will be nor'ed */
#define POPT_ARGFLAG_AND 0x04000000U /*!< arg will be and'ed */
#define POPT_ARGFLAG_NAND 0x05000000U /*!< arg will be nand'ed */
#define POPT_ARGFLAG_XOR 0x02000000U /*!< arg will be xor'ed */
#define POPT_ARGFLAG_NOT 0x01000000U /*!< arg will be negated */
#define POPT_ARGFLAG_LOGICALOPS \
(POPT_ARGFLAG_OR|POPT_ARGFLAG_AND|POPT_ARGFLAG_XOR)
#define POPT_BIT_SET (POPT_ARG_VAL|POPT_ARGFLAG_OR)
/*!< set arg bit(s) */
#define POPT_BIT_CLR (POPT_ARG_VAL|POPT_ARGFLAG_NAND)
/*!< clear arg bit(s) */
#define POPT_ARGFLAG_SHOW_DEFAULT 0x00800000U /*!< show default value in --help */
#define POPT_ARGFLAG_RANDOM 0x00400000U /*!< random value in [1,arg] */
#define POPT_ARGFLAG_TOGGLE 0x00200000U /*!< permit --[no]opt prefix toggle */
/*@}*/
/** \ingroup popt
* \name Callback modifiers
*/
/*@{*/
#define POPT_CBFLAG_PRE 0x80000000U /*!< call the callback before parse */
#define POPT_CBFLAG_POST 0x40000000U /*!< call the callback after parse */
#define POPT_CBFLAG_INC_DATA 0x20000000U /*!< use data from the include line,
not the subtable */
#define POPT_CBFLAG_SKIPOPTION 0x10000000U /*!< don't callback with option */
#define POPT_CBFLAG_CONTINUE 0x08000000U /*!< continue callbacks with option */
/*@}*/
/** \ingroup popt
* \name Error return values
*/
/*@{*/
#define POPT_ERROR_NOARG -10 /*!< missing argument */
#define POPT_ERROR_BADOPT -11 /*!< unknown option */
#define POPT_ERROR_OPTSTOODEEP -13 /*!< aliases nested too deeply */
#define POPT_ERROR_BADQUOTE -15 /*!< error in paramter quoting */
#define POPT_ERROR_ERRNO -16 /*!< errno set, use strerror(errno) */
#define POPT_ERROR_BADNUMBER -17 /*!< invalid numeric value */
#define POPT_ERROR_OVERFLOW -18 /*!< number too large or too small */
#define POPT_ERROR_BADOPERATION -19 /*!< mutually exclusive logical operations requested */
#define POPT_ERROR_NULLARG -20 /*!< opt->arg should not be NULL */
#define POPT_ERROR_MALLOC -21 /*!< memory allocation failed */
#define POPT_ERROR_BADCONFIG -22 /*!< config file failed sanity test */
/*@}*/
/** \ingroup popt
* \name poptBadOption() flags
*/
/*@{*/
#define POPT_BADOPTION_NOALIAS (1U << 0) /*!< don't go into an alias */
/*@}*/
/** \ingroup popt
* \name poptGetContext() flags
*/
/*@{*/
#define POPT_CONTEXT_NO_EXEC (1U << 0) /*!< ignore exec expansions */
#define POPT_CONTEXT_KEEP_FIRST (1U << 1) /*!< pay attention to argv[0] */
#define POPT_CONTEXT_POSIXMEHARDER (1U << 2) /*!< options can't follow args */
#define POPT_CONTEXT_ARG_OPTS (1U << 4) /*!< return args as options with value 0 */
/*@}*/
/** \ingroup popt
*/
struct poptOption {
/*@observer@*/ /*@null@*/
const char * longName; /*!< may be NULL */
char shortName; /*!< may be NUL */
unsigned int argInfo;
/*@shared@*/ /*@null@*/
void * arg; /*!< depends on argInfo */
int val; /*!< 0 means don't return, just update flag */
/*@observer@*/ /*@null@*/
const char * descrip; /*!< description for autohelp -- may be NULL */
/*@observer@*/ /*@null@*/
const char * argDescrip; /*!< argument description for autohelp */
};
/** \ingroup popt
* A popt alias argument for poptAddAlias().
*/
struct poptAlias {
/*@owned@*/ /*@null@*/
const char * longName; /*!< may be NULL */
char shortName; /*!< may be NUL */
int argc;
/*@owned@*/
const char ** argv; /*!< must be free()able */
};
/** \ingroup popt
* A popt alias or exec argument for poptAddItem().
*/
/*@-exporttype@*/
typedef struct poptItem_s {
struct poptOption option; /*!< alias/exec name(s) and description. */
int argc; /*!< (alias) no. of args. */
/*@owned@*/
const char ** argv; /*!< (alias) args, must be free()able. */
} * poptItem;
/*@=exporttype@*/
/** \ingroup popt
* \name Auto-generated help/usage
*/
/*@{*/
/**
* Empty table marker to enable displaying popt alias/exec options.
*/
/*@-exportvar@*/
/*@unchecked@*/ /*@observer@*/
extern struct poptOption poptAliasOptions[];
/*@=exportvar@*/
#define POPT_AUTOALIAS { NULL, '\0', POPT_ARG_INCLUDE_TABLE, poptAliasOptions, \
0, "Options implemented via popt alias/exec:", NULL },
/**
* Auto help table options.
*/
/*@-exportvar@*/
/*@unchecked@*/ /*@observer@*/
extern struct poptOption poptHelpOptions[];
/*@=exportvar@*/
/*@-exportvar@*/
/*@unchecked@*/ /*@observer@*/
extern struct poptOption * poptHelpOptionsI18N;
/*@=exportvar@*/
#define POPT_AUTOHELP { NULL, '\0', POPT_ARG_INCLUDE_TABLE, poptHelpOptions, \
0, "Help options:", NULL },
#define POPT_TABLEEND { NULL, '\0', 0, NULL, 0, NULL, NULL }
/*@}*/
/** \ingroup popt
*/
/*@-exporttype@*/
typedef /*@abstract@*/ struct poptContext_s * poptContext;
/*@=exporttype@*/
/** \ingroup popt
*/
#ifndef __cplusplus
/*@-exporttype -typeuse@*/
typedef struct poptOption * poptOption;
/*@=exporttype =typeuse@*/
#endif
/** \ingroup popt
*/
/*@-exportconst@*/
enum poptCallbackReason {
POPT_CALLBACK_REASON_PRE = 0,
POPT_CALLBACK_REASON_POST = 1,
POPT_CALLBACK_REASON_OPTION = 2
};
/*@=exportconst@*/
#ifdef __cplusplus
extern "C" {
#endif
/*@-type@*/
/** \ingroup popt
* Table callback prototype.
* @param con context
* @param reason reason for callback
* @param opt option that triggered callback
* @param arg @todo Document.
* @param data @todo Document.
*/
typedef void (*poptCallbackType) (poptContext con,
enum poptCallbackReason reason,
/*@null@*/ const struct poptOption * opt,
/*@null@*/ const char * arg,
/*@null@*/ const void * data)
/*@globals internalState @*/
/*@modifies internalState @*/;
/** \ingroup popt
* Destroy context.
* @param con context
* @return NULL always
*/
/*@null@*/
poptContext poptFreeContext( /*@only@*/ /*@null@*/ poptContext con)
/*@modifies con @*/;
/** \ingroup popt
* Initialize popt context.
* @param name context name (usually argv[0] program name)
* @param argc no. of arguments
* @param argv argument array
* @param options address of popt option table
* @param flags or'd POPT_CONTEXT_* bits
* @return initialized popt context
*/
/*@only@*/ /*@null@*/
poptContext poptGetContext(
/*@dependent@*/ /*@keep@*/ const char * name,
int argc, /*@dependent@*/ /*@keep@*/ const char ** argv,
/*@dependent@*/ /*@keep@*/ const struct poptOption * options,
unsigned int flags)
/*@globals internalState @*/
/*@modifies internalState @*/;
/** \ingroup popt
* Destroy context (alternative implementation).
* @param con context
* @return NULL always
*/
/*@null@*/
poptContext poptFini( /*@only@*/ /*@null@*/ poptContext con)
/*@modifies con @*/;
/** \ingroup popt
* Initialize popt context (alternative implementation).
* This routine does poptGetContext() and then poptReadConfigFiles().
* @param argc no. of arguments
* @param argv argument array
* @param options address of popt option table
* @param configPaths colon separated file path(s) to read.
* @return initialized popt context (NULL on error).
*/
/*@only@*/ /*@null@*/ /*@unused@*/
poptContext poptInit(int argc, /*@dependent@*/ /*@keep@*/ const char ** argv,
/*@dependent@*/ /*@keep@*/ const struct poptOption * options,
/*@null@*/ const char * configPaths)
/*@globals fileSystem, internalState @*/
/*@modifies fileSystem, internalState @*/;
/** \ingroup popt
* Reinitialize popt context.
* @param con context
*/
/*@unused@*/
void poptResetContext(/*@null@*/poptContext con)
/*@modifies con @*/;
/** \ingroup popt
* Return value of next option found.
* @param con context
* @return next option val, -1 on last item, POPT_ERROR_* on error
*/
int poptGetNextOpt(/*@null@*/poptContext con)
/*@globals fileSystem, internalState @*/
/*@modifies con, fileSystem, internalState @*/;
/** \ingroup popt
* Return next option argument (if any).
* @param con context
* @return option argument, NULL if no argument is available
*/
/*@observer@*/ /*@null@*/ /*@unused@*/
char * poptGetOptArg(/*@null@*/poptContext con)
/*@modifies con @*/;
/** \ingroup popt
* Return next argument.
* @param con context
* @return next argument, NULL if no argument is available
*/
/*@observer@*/ /*@null@*/ /*@unused@*/
const char * poptGetArg(/*@null@*/poptContext con)
/*@modifies con @*/;
/** \ingroup popt
* Peek at current argument.
* @param con context
* @return current argument, NULL if no argument is available
*/
/*@observer@*/ /*@null@*/ /*@unused@*/
const char * poptPeekArg(/*@null@*/poptContext con)
/*@*/;
/** \ingroup popt
* Return remaining arguments.
* @param con context
* @return argument array, NULL terminated
*/
/*@observer@*/ /*@null@*/
const char ** poptGetArgs(/*@null@*/poptContext con)
/*@modifies con @*/;
/** \ingroup popt
* Return the option which caused the most recent error.
* @param con context
* @param flags
* @return offending option
*/
/*@observer@*/
const char * poptBadOption(/*@null@*/poptContext con, unsigned int flags)
/*@*/;
/** \ingroup popt
* Add arguments to context.
* @param con context
* @param argv argument array, NULL terminated
* @return 0 on success, POPT_ERROR_OPTSTOODEEP on failure
*/
/*@unused@*/
int poptStuffArgs(poptContext con, /*@keep@*/ const char ** argv)
/*@modifies con @*/;
/** \ingroup popt
* Add alias to context.
* @todo Pass alias by reference, not value.
* @deprecated Use poptAddItem instead.
* @param con context
* @param alias alias to add
* @param flags (unused)
* @return 0 on success
*/
/*@unused@*/
int poptAddAlias(poptContext con, struct poptAlias alias, int flags)
/*@modifies con @*/;
/** \ingroup popt
* Add alias/exec item to context.
* @param con context
* @param newItem alias/exec item to add
* @param flags 0 for alias, 1 for exec
* @return 0 on success
*/
int poptAddItem(poptContext con, poptItem newItem, int flags)
/*@modifies con @*/;
/** \ingroup popt
* Perform sanity checks on a file path.
* @param fn file name
* @return 0 on OK, 1 on NOTOK.
*/
int poptSaneFile(const char * fn)
/*@globals errno, internalState @*/
/*@modifies errno, internalState @*/;
/**
* Read a file into a buffer.
* @param fn file name
* @retval *bp buffer (malloc'd) (or NULL)
* @retval *nbp no. of bytes in buffer (including final NUL) (or NULL)
* @param flags 1 to trim escaped newlines
* return 0 on success
*/
int poptReadFile(const char * fn, /*@null@*/ /*@out@*/ char ** bp,
/*@null@*/ /*@out@*/ size_t * nbp, int flags)
/*@globals errno, fileSystem, internalState @*/
/*@modifies *bp, *nbp, errno, fileSystem, internalState @*/;
#define POPT_READFILE_TRIMNEWLINES 1
/** \ingroup popt
* Read configuration file.
* @param con context
* @param fn file name to read
* @return 0 on success, POPT_ERROR_ERRNO on failure
*/
int poptReadConfigFile(poptContext con, const char * fn)
/*@globals errno, fileSystem, internalState @*/
/*@modifies con->execs, con->numExecs,
errno, fileSystem, internalState @*/;
/** \ingroup popt
* Read configuration file(s).
* Colon separated files to read, looping over poptReadConfigFile().
* Note that an '@' character preceeding a path in the list will
* also perform additional sanity checks on the file before reading.
* @param con context
* @param paths colon separated file name(s) to read
* @return 0 on success, POPT_ERROR_BADCONFIG on failure
*/
int poptReadConfigFiles(poptContext con, /*@null@*/ const char * paths)
/*@globals errno, fileSystem, internalState @*/
/*@modifies con->execs, con->numExecs,
errno, fileSystem, internalState @*/;
/** \ingroup popt
* Read default configuration from /etc/popt and $HOME/.popt.
* @param con context
* @param useEnv (unused)
* @return 0 on success, POPT_ERROR_ERRNO on failure
*/
/*@unused@*/
int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv)
/*@globals fileSystem, internalState @*/
/*@modifies con->execs, con->numExecs,
fileSystem, internalState @*/;
/** \ingroup popt
* Duplicate an argument array.
* @note: The argument array is malloc'd as a single area, so only argv must
* be free'd.
*
* @param argc no. of arguments
* @param argv argument array
* @retval argcPtr address of returned no. of arguments
* @retval argvPtr address of returned argument array
* @return 0 on success, POPT_ERROR_NOARG on failure
*/
int poptDupArgv(int argc, /*@null@*/ const char **argv,
/*@null@*/ /*@out@*/ int * argcPtr,
/*@null@*/ /*@out@*/ const char *** argvPtr)
/*@modifies *argcPtr, *argvPtr @*/;
/** \ingroup popt
* Parse a string into an argument array.
* The parse allows ', ", and \ quoting, but ' is treated the same as " and
* both may include \ quotes.
* @note: The argument array is malloc'd as a single area, so only argv must
* be free'd.
*
* @param s string to parse
* @retval argcPtr address of returned no. of arguments
* @retval argvPtr address of returned argument array
*/
int poptParseArgvString(const char * s,
/*@out@*/ int * argcPtr, /*@out@*/ const char *** argvPtr)
/*@modifies *argcPtr, *argvPtr @*/;
/** \ingroup popt
* Parses an input configuration file and returns an string that is a
* command line. For use with popt. You must free the return value when done.
*
* Given the file:
\verbatim
# this line is ignored
# this one too
aaa
bbb
ccc
bla=bla
this_is = fdsafdas
bad_line=
reall bad line
reall bad line = again
5555= 55555
test = with lots of spaces
\endverbatim
*
* The result is:
\verbatim
--aaa --bbb --ccc --bla="bla" --this_is="fdsafdas" --5555="55555" --test="with lots of spaces"
\endverbatim
*
* Passing this to poptParseArgvString() yields an argv of:
\verbatim
'--aaa'
'--bbb'
'--ccc'
'--bla=bla'
'--this_is=fdsafdas'
'--5555=55555'
'--test=with lots of spaces'
\endverbatim
*
* @bug NULL is returned if file line is too long.
* @bug Silently ignores invalid lines.
*
* @param fp file handle to read
* @param *argstrp return string of options (malloc'd)
* @param flags unused
* @return 0 on success
* @see poptParseArgvString
*/
/*@-fcnuse@*/
int poptConfigFileToString(FILE *fp, /*@out@*/ char ** argstrp, int flags)
/*@globals fileSystem @*/
/*@modifies *fp, *argstrp, fileSystem @*/;
/*@=fcnuse@*/
/** \ingroup popt
* Return formatted error string for popt failure.
* @param error popt error
* @return error string
*/
/*@observer@*/
const char * poptStrerror(const int error)
/*@*/;
/** \ingroup popt
* Limit search for executables.
* @param con context
* @param path single path to search for executables
* @param allowAbsolute absolute paths only?
*/
/*@unused@*/
void poptSetExecPath(poptContext con, const char * path, int allowAbsolute)
/*@modifies con @*/;
/** \ingroup popt
* Print detailed description of options.
* @param con context
* @param fp ouput file handle
* @param flags (unused)
*/
void poptPrintHelp(poptContext con, FILE * fp, /*@unused@*/ int flags)
/*@globals fileSystem @*/
/*@modifies fp, fileSystem @*/;
/** \ingroup popt
* Print terse description of options.
* @param con context
* @param fp ouput file handle
* @param flags (unused)
*/
void poptPrintUsage(poptContext con, FILE * fp, /*@unused@*/ int flags)
/*@globals fileSystem @*/
/*@modifies fp, fileSystem @*/;
/** \ingroup popt
* Provide text to replace default "[OPTION...]" in help/usage output.
* @param con context
* @param text replacement text
*/
/*@-fcnuse@*/
void poptSetOtherOptionHelp(poptContext con, const char * text)
/*@modifies con @*/;
/*@=fcnuse@*/
/** \ingroup popt
* Return argv[0] from context.
* @param con context
* @return argv[0]
*/
/*@-fcnuse@*/
/*@observer@*/
const char * poptGetInvocationName(poptContext con)
/*@*/;
/*@=fcnuse@*/
/** \ingroup popt
* Shuffle argv pointers to remove stripped args, returns new argc.
* @param con context
* @param argc no. of args
* @param argv arg vector
* @return new argc
*/
/*@-fcnuse@*/
int poptStrippedArgv(poptContext con, int argc, char ** argv)
/*@modifies *argv @*/;
/*@=fcnuse@*/
/**
* Add a string to an argv array.
* @retval *argvp argv array
* @param argInfo (unused)
* @param val string arg to add (using strdup)
* @return 0 on success, POPT_ERROR_NULLARG/POPT_ERROR_BADOPERATION
*/
/*@unused@*/
int poptSaveString(/*@null@*/ const char *** argvp, unsigned int argInfo,
/*@null@*/const char * val)
/*@modifies *argvp @*/;
/**
* Save a long long, performing logical operation with value.
* @warning Alignment check may be too strict on certain platorms.
* @param arg integer pointer, aligned on int boundary.
* @param argInfo logical operation (see POPT_ARGFLAG_*)
* @param aLongLong value to use
* @return 0 on success, POPT_ERROR_NULLARG/POPT_ERROR_BADOPERATION
*/
/*@-incondefs@*/
/*@unused@*/
int poptSaveLongLong(/*@null@*/ long long * arg, unsigned int argInfo,
long long aLongLong)
/*@globals internalState @*/
/*@modifies *arg, internalState @*/
/*@requires maxSet(arg) >= 0 /\ maxRead(arg) == 0 @*/;
/*@=incondefs@*/
/**
* Save a long, performing logical operation with value.
* @warning Alignment check may be too strict on certain platorms.
* @param arg integer pointer, aligned on int boundary.
* @param argInfo logical operation (see POPT_ARGFLAG_*)
* @param aLong value to use
* @return 0 on success, POPT_ERROR_NULLARG/POPT_ERROR_BADOPERATION
*/
/*@-incondefs@*/
/*@unused@*/
int poptSaveLong(/*@null@*/ long * arg, unsigned int argInfo, long aLong)
/*@globals internalState @*/
/*@modifies *arg, internalState @*/
/*@requires maxSet(arg) >= 0 /\ maxRead(arg) == 0 @*/;
/*@=incondefs@*/
/**
* Save a short integer, performing logical operation with value.
* @warning Alignment check may be too strict on certain platorms.
* @param arg short pointer, aligned on short boundary.
* @param argInfo logical operation (see POPT_ARGFLAG_*)
* @param aLong value to use
* @return 0 on success, POPT_ERROR_NULLARG/POPT_ERROR_BADOPERATION
*/
/*@-incondefs@*/
/*@unused@*/
int poptSaveShort(/*@null@*/ short * arg, unsigned int argInfo, long aLong)
/*@globals internalState @*/
/*@modifies *arg, internalState @*/
/*@requires maxSet(arg) >= 0 /\ maxRead(arg) == 0 @*/;
/*@=incondefs@*/
/**
* Save an integer, performing logical operation with value.
* @warning Alignment check may be too strict on certain platorms.
* @param arg integer pointer, aligned on int boundary.
* @param argInfo logical operation (see POPT_ARGFLAG_*)
* @param aLong value to use
* @return 0 on success, POPT_ERROR_NULLARG/POPT_ERROR_BADOPERATION
*/
/*@-incondefs@*/
/*@unused@*/
int poptSaveInt(/*@null@*/ int * arg, unsigned int argInfo, long aLong)
/*@globals internalState @*/
/*@modifies *arg, internalState @*/
/*@requires maxSet(arg) >= 0 /\ maxRead(arg) == 0 @*/;
/*@=incondefs@*/
/* The bit set typedef. */
/*@-exporttype@*/
typedef struct poptBits_s {
unsigned int bits[1];
} * poptBits;
/*@=exporttype@*/
#define _POPT_BITS_N 1024U /* estimated population */
#define _POPT_BITS_M ((3U * _POPT_BITS_N) / 2U)
#define _POPT_BITS_K 16U /* no. of linear hash combinations */
/*@-exportlocal -exportvar -globuse @*/
/*@unchecked@*/
extern unsigned int _poptBitsN;
/*@unchecked@*/
extern unsigned int _poptBitsM;
/*@unchecked@*/
extern unsigned int _poptBitsK;
/*@=exportlocal =exportvar =globuse @*/
/*@-exportlocal@*/
int poptBitsAdd(/*@null@*/poptBits bits, /*@null@*/const char * s)
/*@modifies bits @*/;
/*@=exportlocal@*/
int poptBitsChk(/*@null@*/poptBits bits, /*@null@*/const char * s)
/*@*/;
int poptBitsClr(/*@null@*/poptBits bits)
/*@modifies bits @*/;
/*@-exportlocal@*/
int poptBitsDel(/*@null@*/poptBits bits, /*@null@*/const char * s)
/*@modifies bits @*/;
/*@-fcnuse@*/
int poptBitsIntersect(/*@null@*/ poptBits * ap, /*@null@*/ const poptBits b)
/*@modifies *ap @*/;
int poptBitsUnion(/*@null@*/ poptBits * ap, /*@null@*/ const poptBits b)
/*@modifies *ap @*/;
int poptBitsArgs(/*@null@*/ poptContext con, /*@null@*/ poptBits * ap)
/*@modifies con, *ap @*/;
/*@=fcnuse@*/
/*@=exportlocal@*/
/**
* Save a string into a bit set (experimental).
* @retval *bits bit set (lazily malloc'd if NULL)
* @param argInfo logical operation (see POPT_ARGFLAG_*)
* @param s string to add to bit set
* @return 0 on success, POPT_ERROR_NULLARG/POPT_ERROR_BADOPERATION
*/
/*@-incondefs@*/
/*@unused@*/
int poptSaveBits(/*@null@*/ poptBits * bitsp, unsigned int argInfo,
/*@null@*/ const char * s)
/*@globals _poptBitsN, _poptBitsM, _poptBitsK, internalState @*/
/*@modifies *bitsp, _poptBitsN, _poptBitsM, _poptBitsK, internalState @*/;
/*@=incondefs@*/
/*@=type@*/
#ifdef __cplusplus
}
#endif
#endif
+82
View File
@@ -0,0 +1,82 @@
%{expand:%%global _pkgconfigdir %{_libdir}/pkgconfig}
%define _libdir /%{_lib}
Summary: A C library for parsing command line parameters.
Name: popt
Version: @VERSION@
Release: 1
License: X Consortium
Group: System Environment/Libraries
Source: http://rpm5.org/files/popt/%{name}-%{version}.tar.gz
BuildRequires: gettext
BuildRoot: %{_tmppath}/%{name}-root
%description
Popt is a C library for parsing command line parameters. Popt was
heavily influenced by the getopt() and getopt_long() functions, but it
improves on them by allowing more powerful argument expansion. Popt
can parse arbitrary argv[] style arrays and automatically set
variables based on command line arguments. Popt allows command line
arguments to be aliased via configuration files and includes utility
functions for parsing arbitrary strings into argv[] arrays using
shell-like rules.
%prep
%setup -q
%build
%configure
make
%install
rm -rf $RPM_BUILD_ROOT
make DESTDIR=$RPM_BUILD_ROOT install
%find_lang popt
%check
make check || :
%track
prog popt = {
version = %{version}
url = http://rpm5.org/%{name}
regex = %{name}-(\d+\.\d+\.\d+)\.tar\.gz
}
%clean
rm -rf $RPM_BUILD_ROOT
%files -f popt.lang
%defattr(-,root,root)
%{_libdir}/libpopt.*
%{_includedir}/popt.h
%{_mandir}/man3/popt.3*
%{_pkgconfigdir}/popt.pc
%changelog
* Wed Feb 17 2010 Jeff Johnson <jbj@rpm5.org>
- release popt-1.16 through rpm5.org.
* Fri Apr 10 2009 Jeff Johnson <jbj@rpm5.org>
- release popt-1.15 through rpm5.org.
* Tue Dec 11 2007 Jeff Johnson <jbj@rpm5.org>
- release popt-1.13 through rpm5.org.
* Tue Jul 10 2007 Jeff Johnson <jbj@rpm5.org>
- release popt-1.12 through rpm5.org.
* Sat Jun 9 2007 Jeff Johnson <jbj@rpm5.org>
- release popt-1.11 through rpm5.org.
* Thu Dec 10 1998 Michael Johnson <johnsonm@redhat.com>
- released 1.2.2; see CHANGES
* Tue Nov 17 1998 Michael K. Johnson <johnsonm@redhat.com>
- added man page to default install
* Thu Oct 22 1998 Erik Troan <ewt@redhat.com>
- see CHANGES file for 1.2
* Thu Apr 09 1998 Erik Troan <ewt@redhat.com>
- added ./configure step to spec file
+582
View File
@@ -0,0 +1,582 @@
/** \ingroup popt
* \file popt/poptconfig.c
*/
/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
ftp://ftp.rpm.org/pub/rpm/dist. */
#include "system.h"
#include "poptint.h"
#include <sys/stat.h>
#if defined(HAVE_FNMATCH_H)
#include <fnmatch.h>
#if defined(__LCLINT__)
/*@-declundef -exportheader -incondefs -protoparammatch -redecl -type @*/
extern int fnmatch (const char *__pattern, const char *__name, int __flags)
/*@*/;
/*@=declundef =exportheader =incondefs =protoparammatch =redecl =type @*/
#endif /* __LCLINT__ */
#endif
#if defined(HAVE_GLOB_H)
#include <glob.h>
#if defined(__LCLINT__)
/*@-declundef -exportheader -incondefs -protoparammatch -redecl -type @*/
extern int glob (const char *__pattern, int __flags,
/*@null@*/ int (*__errfunc) (const char *, int),
/*@out@*/ glob_t *__pglob)
/*@globals errno, fileSystem @*/
/*@modifies *__pglob, errno, fileSystem @*/;
/* XXX only annotation is a white lie */
extern void globfree (/*@only@*/ glob_t *__pglob)
/*@modifies *__pglob @*/;
/* XXX _GNU_SOURCE ifdef and/or retrofit is needed for portability. */
extern int glob_pattern_p (const char *__pattern, int __quote)
/*@*/;
/*@=declundef =exportheader =incondefs =protoparammatch =redecl =type @*/
#endif /* __LCLINT__ */
#if !defined(__GLIBC__)
/* Return nonzero if PATTERN contains any metacharacters.
Metacharacters can be quoted with backslashes if QUOTE is nonzero. */
static int
glob_pattern_p (const char * pattern, int quote)
/*@*/
{
const char * p;
int open = 0;
for (p = pattern; *p != '\0'; ++p)
switch (*p) {
case '?':
case '*':
return 1;
/*@notreached@*/ /*@switchbreak@*/ break;
case '\\':
if (quote && p[1] != '\0')
++p;
/*@switchbreak@*/ break;
case '[':
open = 1;
/*@switchbreak@*/ break;
case ']':
if (open)
return 1;
/*@switchbreak@*/ break;
}
return 0;
}
#endif /* !defined(__GLIBC__) */
/*@unchecked@*/
static int poptGlobFlags = 0;
static int poptGlob_error(/*@unused@*/ UNUSED(const char * epath),
/*@unused@*/ UNUSED(int eerrno))
/*@*/
{
return 1;
}
#endif /* HAVE_GLOB_H */
/**
* Return path(s) from a glob pattern.
* @param con context
* @param pattern glob pattern
* @retval *acp no. of paths
* @retval *avp array of paths
* @return 0 on success
*/
static int poptGlob(/*@unused@*/ UNUSED(poptContext con), const char * pattern,
/*@out@*/ int * acp, /*@out@*/ const char *** avp)
/*@modifies *acp, *avp @*/
{
const char * pat = pattern;
int rc = 0; /* assume success */
/* XXX skip the attention marker. */
if (pat[0] == '@' && pat[1] != '(')
pat++;
#if defined(HAVE_GLOB_H)
if (glob_pattern_p(pat, 0)) {
glob_t _g, *pglob = &_g;
if (!glob(pat, poptGlobFlags, poptGlob_error, pglob)) {
if (acp) {
*acp = (int) pglob->gl_pathc;
pglob->gl_pathc = 0;
}
if (avp) {
/*@-onlytrans@*/
*avp = (const char **) pglob->gl_pathv;
/*@=onlytrans@*/
pglob->gl_pathv = NULL;
}
/*@-nullstate@*/
globfree(pglob);
/*@=nullstate@*/
} else
rc = POPT_ERROR_ERRNO;
} else
#endif /* HAVE_GLOB_H */
{
if (acp)
*acp = 1;
if (avp && (*avp = calloc((size_t)(1 + 1), sizeof (**avp))) != NULL)
(*avp)[0] = xstrdup(pat);
}
return rc;
}
/*@access poptContext @*/
int poptSaneFile(const char * fn)
{
struct stat sb;
uid_t uid = getuid();
if (stat(fn, &sb) == -1)
return 1;
if ((uid_t)sb.st_uid != uid)
return 0;
if (!S_ISREG(sb.st_mode))
return 0;
/*@-bitwisesigned@*/
if (sb.st_mode & (S_IWGRP|S_IWOTH))
return 0;
/*@=bitwisesigned@*/
return 1;
}
int poptReadFile(const char * fn, char ** bp, size_t * nbp, int flags)
{
int fdno;
char * b = NULL;
off_t nb = 0;
char * s, * t, * se;
int rc = POPT_ERROR_ERRNO; /* assume failure */
fdno = open(fn, O_RDONLY);
if (fdno < 0)
goto exit;
if ((nb = lseek(fdno, 0, SEEK_END)) == (off_t)-1
|| lseek(fdno, 0, SEEK_SET) == (off_t)-1
|| (b = calloc(sizeof(*b), (size_t)nb + 1)) == NULL
|| read(fdno, (char *)b, (size_t)nb) != (ssize_t)nb)
{
int oerrno = errno;
(void) close(fdno);
errno = oerrno;
goto exit;
}
if (close(fdno) == -1)
goto exit;
if (b == NULL) {
rc = POPT_ERROR_MALLOC;
goto exit;
}
rc = 0;
/* Trim out escaped newlines. */
/*@-bitwisesigned@*/
if (flags & POPT_READFILE_TRIMNEWLINES)
/*@=bitwisesigned@*/
{
for (t = b, s = b, se = b + nb; *s && s < se; s++) {
switch (*s) {
case '\\':
if (s[1] == '\n') {
s++;
continue;
}
/*@fallthrough@*/
default:
*t++ = *s;
/*@switchbreak@*/ break;
}
}
*t++ = '\0';
nb = (off_t)(t - b);
}
exit:
if (rc != 0) {
/*@-usedef@*/
if (b)
free(b);
/*@=usedef@*/
b = NULL;
nb = 0;
}
if (bp)
*bp = b;
/*@-usereleased@*/
else if (b)
free(b);
/*@=usereleased@*/
if (nbp)
*nbp = (size_t)nb;
/*@-compdef -nullstate @*/ /* XXX cannot annotate char ** correctly */
return rc;
/*@=compdef =nullstate @*/
}
/**
* Check for application match.
* @param con context
* @param s config application name
* return 0 if config application matches
*/
static int configAppMatch(poptContext con, const char * s)
/*@*/
{
int rc = 1;
if (con->appName == NULL) /* XXX can't happen. */
return rc;
#if defined(HAVE_GLOB_H) && defined(HAVE_FNMATCH_H)
if (glob_pattern_p(s, 1)) {
/*@-bitwisesigned@*/
static int flags = FNM_PATHNAME | FNM_PERIOD;
#ifdef FNM_EXTMATCH
flags |= FNM_EXTMATCH;
#endif
/*@=bitwisesigned@*/
rc = fnmatch(s, con->appName, flags);
} else
#endif
rc = strcmp(s, con->appName);
return rc;
}
/*@-compmempass@*/ /* FIX: item->option.longName kept, not dependent. */
static int poptConfigLine(poptContext con, char * line)
/*@globals fileSystem, internalState @*/
/*@modifies con, fileSystem, internalState @*/
{
char *b = NULL;
size_t nb = 0;
char * se = line;
const char * appName;
const char * entryType;
const char * opt;
struct poptItem_s item_buf;
poptItem item = &item_buf;
int i, j;
int rc = POPT_ERROR_BADCONFIG;
if (con->appName == NULL)
goto exit;
memset(item, 0, sizeof(*item));
appName = se;
while (*se != '\0' && !_isspaceptr(se)) se++;
if (*se == '\0')
goto exit;
else
*se++ = '\0';
if (configAppMatch(con, appName)) goto exit;
while (*se != '\0' && _isspaceptr(se)) se++;
entryType = se;
while (*se != '\0' && !_isspaceptr(se)) se++;
if (*se != '\0') *se++ = '\0';
while (*se != '\0' && _isspaceptr(se)) se++;
if (*se == '\0') goto exit;
opt = se;
while (*se != '\0' && !_isspaceptr(se)) se++;
if (opt[0] == '-' && *se == '\0') goto exit;
if (*se != '\0') *se++ = '\0';
while (*se != '\0' && _isspaceptr(se)) se++;
if (opt[0] == '-' && *se == '\0') goto exit;
/*@-temptrans@*/ /* FIX: line alias is saved */
if (opt[0] == '-' && opt[1] == '-')
item->option.longName = opt + 2;
else if (opt[0] == '-' && opt[2] == '\0')
item->option.shortName = opt[1];
else {
const char * fn = opt;
/* XXX handle globs and directories in fn? */
if ((rc = poptReadFile(fn, &b, &nb, POPT_READFILE_TRIMNEWLINES)) != 0)
goto exit;
if (b == NULL || nb == 0)
goto exit;
/* Append remaining text to the interpolated file option text. */
if (*se != '\0') {
size_t nse = strlen(se) + 1;
if ((b = realloc(b, (nb + nse))) == NULL) /* XXX can't happen */
goto exit;
(void) stpcpy( stpcpy(&b[nb-1], " "), se);
nb += nse;
}
se = b;
/* Use the basename of the path as the long option name. */
{ const char * longName = strrchr(fn, '/');
if (longName != NULL)
longName++;
else
longName = fn;
if (longName == NULL) /* XXX can't happen. */
goto exit;
/* Single character basenames are treated as short options. */
if (longName[1] != '\0')
item->option.longName = longName;
else
item->option.shortName = longName[0];
}
}
/*@=temptrans@*/
if (poptParseArgvString(se, &item->argc, &item->argv)) goto exit;
/*@-modobserver@*/
item->option.argInfo = POPT_ARGFLAG_DOC_HIDDEN;
for (i = 0, j = 0; i < item->argc; i++, j++) {
const char * f;
if (!strncmp(item->argv[i], "--POPTdesc=", sizeof("--POPTdesc=")-1)) {
f = item->argv[i] + sizeof("--POPTdesc=");
if (f[0] == '$' && f[1] == '"') f++;
item->option.descrip = f;
item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN;
j--;
} else
if (!strncmp(item->argv[i], "--POPTargs=", sizeof("--POPTargs=")-1)) {
f = item->argv[i] + sizeof("--POPTargs=");
if (f[0] == '$' && f[1] == '"') f++;
item->option.argDescrip = f;
item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN;
item->option.argInfo |= POPT_ARG_STRING;
j--;
} else
if (j != i)
item->argv[j] = item->argv[i];
}
if (j != i) {
item->argv[j] = NULL;
item->argc = j;
}
/*@=modobserver@*/
/*@-nullstate@*/ /* FIX: item->argv[] may be NULL */
if (!strcmp(entryType, "alias"))
rc = poptAddItem(con, item, 0);
else if (!strcmp(entryType, "exec"))
rc = poptAddItem(con, item, 1);
/*@=nullstate@*/
exit:
rc = 0; /* XXX for now, always return success */
if (b)
free(b);
return rc;
}
/*@=compmempass@*/
int poptReadConfigFile(poptContext con, const char * fn)
{
char * b = NULL, *be;
size_t nb = 0;
const char *se;
char *t, *te;
int rc;
int xx;
if ((rc = poptReadFile(fn, &b, &nb, POPT_READFILE_TRIMNEWLINES)) != 0)
return (errno == ENOENT ? 0 : rc);
if (b == NULL || nb == 0)
return POPT_ERROR_BADCONFIG;
if ((t = malloc(nb + 1)) == NULL)
goto exit;
te = t;
be = (b + nb);
for (se = b; se < be; se++) {
switch (*se) {
case '\n':
*te = '\0';
te = t;
while (*te && _isspaceptr(te)) te++;
if (*te && *te != '#')
xx = poptConfigLine(con, te);
/*@switchbreak@*/ break;
/*@-usedef@*/ /* XXX *se may be uninitialized */
case '\\':
*te = *se++;
/* \ at the end of a line does not insert a \n */
if (se < be && *se != '\n') {
te++;
*te++ = *se;
}
/*@switchbreak@*/ break;
default:
*te++ = *se;
/*@switchbreak@*/ break;
/*@=usedef@*/
}
}
free(t);
rc = 0;
exit:
if (b)
free(b);
return rc;
}
int poptReadConfigFiles(poptContext con, const char * paths)
{
char * buf = (paths ? xstrdup(paths) : NULL);
const char * p;
char * pe;
int rc = 0; /* assume success */
for (p = buf; p != NULL && *p != '\0'; p = pe) {
const char ** av = NULL;
int ac = 0;
int i;
int xx;
/* locate start of next path element */
pe = strchr(p, ':');
if (pe != NULL && *pe == ':')
*pe++ = '\0';
else
pe = (char *) (p + strlen(p));
xx = poptGlob(con, p, &ac, &av);
/* work-off each resulting file from the path element */
for (i = 0; i < ac; i++) {
const char * fn = av[i];
if (av[i] == NULL) /* XXX can't happen */
/*@innercontinue@*/ continue;
/* XXX should '@' attention be pushed into poptReadConfigFile? */
if (p[0] == '@' && p[1] != '(') {
if (fn[0] == '@' && fn[1] != '(')
fn++;
xx = poptSaneFile(fn);
if (!xx && rc == 0)
rc = POPT_ERROR_BADCONFIG;
/*@innercontinue@*/ continue;
}
xx = poptReadConfigFile(con, fn);
if (xx && rc == 0)
rc = xx;
free((void *)av[i]);
av[i] = NULL;
}
free(av);
av = NULL;
}
/*@-usedef@*/
if (buf)
free(buf);
/*@=usedef@*/
return rc;
}
int poptReadDefaultConfig(poptContext con, /*@unused@*/ UNUSED(int useEnv))
{
static const char _popt_sysconfdir[] = POPT_SYSCONFDIR "/popt";
static const char _popt_etc[] = "/etc/popt";
char * home;
struct stat sb;
int rc = 0; /* assume success */
if (con->appName == NULL) goto exit;
if (strcmp(_popt_sysconfdir, _popt_etc)) {
rc = poptReadConfigFile(con, _popt_sysconfdir);
if (rc) goto exit;
}
rc = poptReadConfigFile(con, _popt_etc);
if (rc) goto exit;
#if defined(HAVE_GLOB_H)
if (!stat("/etc/popt.d", &sb) && S_ISDIR(sb.st_mode)) {
const char ** av = NULL;
int ac = 0;
int i;
if ((rc = poptGlob(con, "/etc/popt.d/*", &ac, &av)) == 0) {
for (i = 0; rc == 0 && i < ac; i++) {
const char * fn = av[i];
if (fn == NULL || strstr(fn, ".rpmnew") || strstr(fn, ".rpmsave"))
continue;
if (!stat(fn, &sb)) {
if (!S_ISREG(sb.st_mode) && !S_ISLNK(sb.st_mode))
continue;
}
rc = poptReadConfigFile(con, fn);
free((void *)av[i]);
av[i] = NULL;
}
free(av);
av = NULL;
}
}
if (rc) goto exit;
#endif
if ((home = getenv("HOME"))) {
char * fn = malloc(strlen(home) + 20);
if (fn != NULL) {
(void) stpcpy(stpcpy(fn, home), "/.popt");
rc = poptReadConfigFile(con, fn);
free(fn);
} else
rc = POPT_ERROR_ERRNO;
if (rc) goto exit;
}
exit:
return rc;
}
poptContext
poptFini(poptContext con)
{
return poptFreeContext(con);
}
poptContext
poptInit(int argc, const char ** argv,
const struct poptOption * options, const char * configPaths)
{
poptContext con = NULL;
const char * argv0;
if (argv == NULL || argv[0] == NULL || options == NULL)
return con;
if ((argv0 = strrchr(argv[0], '/')) != NULL) argv0++;
else argv0 = argv[0];
con = poptGetContext(argv0, argc, (const char **)argv, options, 0);
if (con != NULL&& poptReadConfigFiles(con, configPaths))
con = poptFini(con);
return con;
}
+925
View File
@@ -0,0 +1,925 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/** \ingroup popt
* \file popt/popthelp.c
*/
/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
ftp://ftp.rpm.org/pub/rpm/dist. */
#include "system.h"
#define POPT_USE_TIOCGWINSZ
#ifdef POPT_USE_TIOCGWINSZ
#include <sys/ioctl.h>
#endif
#define POPT_WCHAR_HACK
#ifdef POPT_WCHAR_HACK
#include <wchar.h> /* for mbsrtowcs */
/*@access mbstate_t @*/
#endif
#include "poptint.h"
/*@access poptContext@*/
/**
* Display arguments.
* @param con context
* @param foo (unused)
* @param key option(s)
* @param arg (unused)
* @param data (unused)
*/
/*@exits@*/
static void displayArgs(poptContext con,
/*@unused@*/ UNUSED(enum poptCallbackReason foo),
struct poptOption * key,
/*@unused@*/ UNUSED(const char * arg),
/*@unused@*/ UNUSED(void * data))
/*@globals fileSystem@*/
/*@modifies fileSystem@*/
{
if (key->shortName == '?')
poptPrintHelp(con, stdout, 0);
else
poptPrintUsage(con, stdout, 0);
#if !defined(__LCLINT__) /* XXX keep both splint & valgrind happy */
con = poptFreeContext(con);
#endif
exit(0);
}
#ifdef NOTYET
/*@unchecked@*/
static int show_option_defaults = 0;
#endif
/**
* Empty table marker to enable displaying popt alias/exec options.
*/
/*@observer@*/ /*@unchecked@*/
struct poptOption poptAliasOptions[] = {
POPT_TABLEEND
};
/**
* Auto help table options.
*/
/*@-castfcnptr@*/
/*@observer@*/ /*@unchecked@*/
struct poptOption poptHelpOptions[] = {
{ NULL, '\0', POPT_ARG_CALLBACK, (void *)displayArgs, 0, NULL, NULL },
{ "help", '?', 0, NULL, (int)'?', N_("Show this help message"), NULL },
{ "usage", '\0', 0, NULL, (int)'u', N_("Display brief usage message"), NULL },
POPT_TABLEEND
} ;
/*@observer@*/ /*@unchecked@*/
static struct poptOption poptHelpOptions2[] = {
/*@-readonlytrans@*/
{ NULL, '\0', POPT_ARG_INTL_DOMAIN, PACKAGE, 0, NULL, NULL},
/*@=readonlytrans@*/
{ NULL, '\0', POPT_ARG_CALLBACK, (void *)displayArgs, 0, NULL, NULL },
{ "help", '?', 0, NULL, (int)'?', N_("Show this help message"), NULL },
{ "usage", '\0', 0, NULL, (int)'u', N_("Display brief usage message"), NULL },
#ifdef NOTYET
{ "defaults", '\0', POPT_ARG_NONE, &show_option_defaults, 0,
N_("Display option defaults in message"), NULL },
#endif
{ "", '\0', 0, NULL, 0, N_("Terminate options"), NULL },
POPT_TABLEEND
} ;
/*@observer@*/ /*@unchecked@*/
struct poptOption * poptHelpOptionsI18N = poptHelpOptions2;
/*@=castfcnptr@*/
#define _POPTHELP_MAXLINE ((size_t)79)
typedef struct columns_s {
size_t cur;
size_t max;
} * columns_t;
/**
* Return no. of columns in output window.
* @param fp FILE
* @return no. of columns
*/
static size_t maxColumnWidth(FILE *fp)
/*@*/
{
size_t maxcols = _POPTHELP_MAXLINE;
#if defined(TIOCGWINSZ)
struct winsize ws;
int fdno = fileno(fp ? fp : stdout);
memset(&ws, 0, sizeof(ws));
if (fdno >= 0 && !ioctl(fdno, (unsigned long)TIOCGWINSZ, &ws)) {
size_t ws_col = (size_t)ws.ws_col;
if (ws_col > maxcols && ws_col < (size_t)256)
maxcols = ws_col - 1;
}
#endif
return maxcols;
}
/**
* Determine number of display characters in a string.
* @param s string
* @return no. of display characters.
*/
static inline size_t stringDisplayWidth(const char *s)
/*@*/
{
size_t n = strlen(s);
#ifdef POPT_WCHAR_HACK
mbstate_t t;
memset ((void *)&t, 0, sizeof (t)); /* In initial state. */
/* Determine number of display characters. */
n = mbsrtowcs (NULL, &s, n, &t);
#else
n = 0;
for (; *s; s = POPT_next_char(s))
n++;
#endif
return n;
}
/**
* @param opt option(s)
*/
/*@observer@*/ /*@null@*/ static const char *
getTableTranslationDomain(/*@null@*/ const struct poptOption *opt)
/*@*/
{
if (opt != NULL)
for (; opt->longName || opt->shortName || opt->arg; opt++) {
if (opt->argInfo == POPT_ARG_INTL_DOMAIN)
return opt->arg;
}
return NULL;
}
/**
* @param opt option(s)
* @param translation_domain translation domain
*/
/*@observer@*/ /*@null@*/ static const char *
getArgDescrip(const struct poptOption * opt,
/*@-paramuse@*/ /* FIX: i18n macros disabled with lclint */
/*@null@*/ const char * translation_domain)
/*@=paramuse@*/
/*@*/
{
if (!poptArgType(opt)) return NULL;
if (poptArgType(opt) == POPT_ARG_MAINCALL)
return opt->argDescrip;
if (poptArgType(opt) == POPT_ARG_ARGV)
return opt->argDescrip;
if (opt->argDescrip) {
/* Some strings need popt library, not application, i18n domain. */
if (opt == (poptHelpOptions + 1)
|| opt == (poptHelpOptions + 2)
|| !strcmp(opt->argDescrip, N_("Help options:"))
|| !strcmp(opt->argDescrip, N_("Options implemented via popt alias/exec:")))
return POPT_(opt->argDescrip);
/* Use the application i18n domain. */
return D_(translation_domain, opt->argDescrip);
}
switch (poptArgType(opt)) {
case POPT_ARG_NONE: return POPT_("NONE");
#ifdef DYING
case POPT_ARG_VAL: return POPT_("VAL");
#else
case POPT_ARG_VAL: return NULL;
#endif
case POPT_ARG_INT: return POPT_("INT");
case POPT_ARG_SHORT: return POPT_("SHORT");
case POPT_ARG_LONG: return POPT_("LONG");
case POPT_ARG_LONGLONG: return POPT_("LONGLONG");
case POPT_ARG_STRING: return POPT_("STRING");
case POPT_ARG_FLOAT: return POPT_("FLOAT");
case POPT_ARG_DOUBLE: return POPT_("DOUBLE");
case POPT_ARG_MAINCALL: return NULL;
case POPT_ARG_ARGV: return NULL;
default: return POPT_("ARG");
}
}
/**
* Display default value for an option.
* @param lineLength display positions remaining
* @param opt option(s)
* @param translation_domain translation domain
* @return
*/
static /*@only@*/ /*@null@*/ char *
singleOptionDefaultValue(size_t lineLength,
const struct poptOption * opt,
/*@-paramuse@*/ /* FIX: i18n macros disabled with lclint */
/*@null@*/ const char * translation_domain)
/*@=paramuse@*/
/*@*/
{
const char * defstr = D_(translation_domain, "default");
char * le = malloc(4*lineLength + 1);
char * l = le;
if (le == NULL) return NULL; /* XXX can't happen */
*le = '\0';
*le++ = '(';
le = stpcpy(le, defstr);
*le++ = ':';
*le++ = ' ';
if (opt->arg) { /* XXX programmer error */
poptArg arg = { .ptr = opt->arg };
switch (poptArgType(opt)) {
case POPT_ARG_VAL:
case POPT_ARG_INT:
le += sprintf(le, "%d", arg.intp[0]);
break;
case POPT_ARG_SHORT:
le += sprintf(le, "%hd", arg.shortp[0]);
break;
case POPT_ARG_LONG:
le += sprintf(le, "%ld", arg.longp[0]);
break;
case POPT_ARG_LONGLONG:
le += sprintf(le, "%lld", arg.longlongp[0]);
break;
case POPT_ARG_FLOAT:
{ double aDouble = (double) arg.floatp[0];
le += sprintf(le, "%g", aDouble);
} break;
case POPT_ARG_DOUBLE:
le += sprintf(le, "%g", arg.doublep[0]);
break;
case POPT_ARG_MAINCALL:
le += sprintf(le, "%p", opt->arg);
break;
case POPT_ARG_ARGV:
le += sprintf(le, "%p", opt->arg);
break;
case POPT_ARG_STRING:
{ const char * s = arg.argv[0];
if (s == NULL)
le = stpcpy(le, "null");
else {
size_t limit = 4*lineLength - (le - l) - sizeof("\"\")");
size_t slen;
*le++ = '"';
strncpy(le, s, limit); le[limit] = '\0'; le += (slen = strlen(le));
if (slen == limit && s[limit])
le[-1] = le[-2] = le[-3] = '.';
*le++ = '"';
}
} break;
case POPT_ARG_NONE:
default:
l = _free(l);
return NULL;
/*@notreached@*/ break;
}
}
*le++ = ')';
*le = '\0';
return l;
}
/**
* Display help text for an option.
* @param fp output file handle
* @param columns output display width control
* @param opt option(s)
* @param translation_domain translation domain
*/
static void singleOptionHelp(FILE * fp, columns_t columns,
const struct poptOption * opt,
/*@null@*/ const char * translation_domain)
/*@globals fileSystem @*/
/*@modifies fp, fileSystem @*/
{
size_t maxLeftCol = columns->cur;
size_t indentLength = maxLeftCol + 5;
size_t lineLength = columns->max - indentLength;
const char * help = D_(translation_domain, opt->descrip);
const char * argDescrip = getArgDescrip(opt, translation_domain);
/* Display shortName iff printable non-space. */
int prtshort = (int)(isprint((int)opt->shortName) && opt->shortName != ' ');
size_t helpLength;
char * defs = NULL;
char * left;
size_t nb = maxLeftCol + 1;
int displaypad = 0;
int xx;
/* Make sure there's more than enough room in target buffer. */
if (opt->longName) nb += strlen(opt->longName);
if (F_ISSET(opt, TOGGLE)) nb += sizeof("[no]") - 1;
if (argDescrip) nb += strlen(argDescrip);
left = malloc(nb);
if (left == NULL) return; /* XXX can't happen */
left[0] = '\0';
left[maxLeftCol] = '\0';
#define prtlong (opt->longName != NULL) /* XXX splint needs a clue */
if (!(prtshort || prtlong))
goto out;
if (prtshort && prtlong) {
char *dash = F_ISSET(opt, ONEDASH) ? "-" : "--";
left[0] = '-';
left[1] = opt->shortName;
(void) stpcpy(stpcpy(stpcpy(left+2, ", "), dash), opt->longName);
} else if (prtshort) {
left[0] = '-';
left[1] = opt->shortName;
left[2] = '\0';
} else if (prtlong) {
/* XXX --long always padded for alignment with/without "-X, ". */
char *dash = poptArgType(opt) == POPT_ARG_MAINCALL ? ""
: (F_ISSET(opt, ONEDASH) ? "-" : "--");
const char *longName = opt->longName;
const char *toggle;
if (F_ISSET(opt, TOGGLE)) {
toggle = "[no]";
if (longName[0] == 'n' && longName[1] == 'o') {
longName += sizeof("no") - 1;
if (longName[0] == '-')
longName++;
}
} else
toggle = "";
(void) stpcpy(stpcpy(stpcpy(stpcpy(left, " "), dash), toggle), longName);
}
#undef prtlong
if (argDescrip) {
char * le = left + strlen(left);
if (F_ISSET(opt, OPTIONAL))
*le++ = '[';
/* Choose type of output */
if (F_ISSET(opt, SHOW_DEFAULT)) {
defs = singleOptionDefaultValue(lineLength, opt, translation_domain);
if (defs) {
char * t = malloc((help ? strlen(help) : 0) +
strlen(defs) + sizeof(" "));
if (t) {
char * te = t;
if (help)
te = stpcpy(te, help);
*te++ = ' ';
strcpy(te, defs);
defs = _free(defs);
defs = t;
}
}
}
if (opt->argDescrip == NULL) {
switch (poptArgType(opt)) {
case POPT_ARG_NONE:
break;
case POPT_ARG_VAL:
#ifdef NOTNOW /* XXX pug ugly nerdy output */
{ long aLong = opt->val;
int ops = F_ISSET(opt, LOGICALOPS);
int negate = F_ISSET(opt, NOT);
/* Don't bother displaying typical values */
if (!ops && (aLong == 0L || aLong == 1L || aLong == -1L))
break;
*le++ = '[';
switch (ops) {
case POPT_ARGFLAG_OR:
*le++ = '|';
/*@innerbreak@*/ break;
case POPT_ARGFLAG_AND:
*le++ = '&';
/*@innerbreak@*/ break;
case POPT_ARGFLAG_XOR:
*le++ = '^';
/*@innerbreak@*/ break;
default:
/*@innerbreak@*/ break;
}
*le++ = (opt->longName != NULL ? '=' : ' ');
if (negate) *le++ = '~';
/*@-formatconst@*/
le += sprintf(le, (ops ? "0x%lx" : "%ld"), aLong);
/*@=formatconst@*/
*le++ = ']';
}
#endif
break;
case POPT_ARG_INT:
case POPT_ARG_SHORT:
case POPT_ARG_LONG:
case POPT_ARG_LONGLONG:
case POPT_ARG_FLOAT:
case POPT_ARG_DOUBLE:
case POPT_ARG_STRING:
*le++ = (opt->longName != NULL ? '=' : ' ');
le = stpcpy(le, argDescrip);
break;
default:
break;
}
} else {
char *leo;
/* XXX argDescrip[0] determines "--foo=bar" or "--foo bar". */
if (!strchr(" =(", argDescrip[0]))
*le++ = ((poptArgType(opt) == POPT_ARG_MAINCALL) ? ' ' :
(poptArgType(opt) == POPT_ARG_ARGV) ? ' ' : '=');
le = stpcpy(leo = le, argDescrip);
/* Adjust for (possible) wide characters. */
displaypad = (int)((le - leo) - stringDisplayWidth(argDescrip));
}
if (F_ISSET(opt, OPTIONAL))
*le++ = ']';
*le = '\0';
}
if (help)
xx = POPT_fprintf(fp," %-*s ", (int)(maxLeftCol+displaypad), left);
else {
xx = POPT_fprintf(fp," %s\n", left);
goto out;
}
left = _free(left);
if (defs)
help = defs;
helpLength = strlen(help);
while (helpLength > lineLength) {
const char * ch;
char format[16];
ch = help + lineLength - 1;
while (ch > help && !_isspaceptr(ch))
ch = POPT_prev_char(ch);
if (ch == help) break; /* give up */
while (ch > (help + 1) && _isspaceptr(ch))
ch = POPT_prev_char (ch);
ch = POPT_next_char(ch);
/*
* XXX strdup is necessary to add NUL terminator so that an unknown
* no. of (possible) multi-byte characters can be displayed.
*/
{ char * fmthelp = xstrdup(help);
if (fmthelp) {
fmthelp[ch - help] = '\0';
sprintf(format, "%%s\n%%%ds", (int) indentLength);
/*@-formatconst@*/
xx = POPT_fprintf(fp, format, fmthelp, " ");
/*@=formatconst@*/
free(fmthelp);
}
}
help = ch;
while (_isspaceptr(help) && *help)
help = POPT_next_char(help);
helpLength = strlen(help);
}
if (helpLength) fprintf(fp, "%s\n", help);
help = NULL;
out:
/*@-dependenttrans@*/
defs = _free(defs);
/*@=dependenttrans@*/
left = _free(left);
}
/**
* Find display width for longest argument string.
* @param opt option(s)
* @param translation_domain translation domain
* @return display width
*/
static size_t maxArgWidth(const struct poptOption * opt,
/*@null@*/ const char * translation_domain)
/*@*/
{
size_t max = 0;
size_t len = 0;
const char * argDescrip;
if (opt != NULL)
while (opt->longName || opt->shortName || opt->arg) {
if (poptArgType(opt) == POPT_ARG_INCLUDE_TABLE) {
if (opt->arg) /* XXX program error */
len = maxArgWidth(opt->arg, translation_domain);
if (len > max) max = len;
} else if (!F_ISSET(opt, DOC_HIDDEN)) {
len = sizeof(" ")-1;
/* XXX --long always padded for alignment with/without "-X, ". */
len += sizeof("-X, ")-1;
if (opt->longName) {
len += (F_ISSET(opt, ONEDASH) ? sizeof("-") : sizeof("--")) - 1;
len += strlen(opt->longName);
}
argDescrip = getArgDescrip(opt, translation_domain);
if (argDescrip) {
/* XXX argDescrip[0] determines "--foo=bar" or "--foo bar". */
if (!strchr(" =(", argDescrip[0])) len += sizeof("=")-1;
/* Adjust for (possible) wide characters. */
len += stringDisplayWidth(argDescrip);
}
if (F_ISSET(opt, OPTIONAL)) len += sizeof("[]")-1;
if (len > max) max = len;
}
opt++;
}
return max;
}
/**
* Display popt alias and exec help.
* @param fp output file handle
* @param items alias/exec array
* @param nitems no. of alias/exec entries
* @param columns output display width control
* @param translation_domain translation domain
*/
static void itemHelp(FILE * fp,
/*@null@*/ poptItem items, int nitems,
columns_t columns,
/*@null@*/ const char * translation_domain)
/*@globals fileSystem @*/
/*@modifies fp, fileSystem @*/
{
poptItem item;
int i;
if (items != NULL)
for (i = 0, item = items; i < nitems; i++, item++) {
const struct poptOption * opt;
opt = &item->option;
if ((opt->longName || opt->shortName) && !F_ISSET(opt, DOC_HIDDEN))
singleOptionHelp(fp, columns, opt, translation_domain);
}
}
/**
* Display help text for a table of options.
* @param con context
* @param fp output file handle
* @param table option(s)
* @param columns output display width control
* @param translation_domain translation domain
*/
static void singleTableHelp(poptContext con, FILE * fp,
/*@null@*/ const struct poptOption * table,
columns_t columns,
/*@null@*/ const char * translation_domain)
/*@globals fileSystem @*/
/*@modifies fp, columns->cur, fileSystem @*/
{
const struct poptOption * opt;
const char *sub_transdom;
int xx;
if (table == poptAliasOptions) {
itemHelp(fp, con->aliases, con->numAliases, columns, NULL);
itemHelp(fp, con->execs, con->numExecs, columns, NULL);
return;
}
if (table != NULL)
for (opt = table; opt->longName || opt->shortName || opt->arg; opt++) {
if ((opt->longName || opt->shortName) && !F_ISSET(opt, DOC_HIDDEN))
singleOptionHelp(fp, columns, opt, translation_domain);
}
if (table != NULL)
for (opt = table; opt->longName || opt->shortName || opt->arg; opt++) {
if (poptArgType(opt) != POPT_ARG_INCLUDE_TABLE)
continue;
sub_transdom = getTableTranslationDomain(opt->arg);
if (sub_transdom == NULL)
sub_transdom = translation_domain;
/* If no popt aliases/execs, skip poptAliasOption processing. */
if (opt->arg == poptAliasOptions && !(con->numAliases || con->numExecs))
continue;
if (opt->descrip)
xx = POPT_fprintf(fp, "\n%s\n", D_(sub_transdom, opt->descrip));
singleTableHelp(con, fp, opt->arg, columns, sub_transdom);
}
}
/**
* @param con context
* @param fp output file handle
*/
static size_t showHelpIntro(poptContext con, FILE * fp)
/*@globals fileSystem @*/
/*@modifies fp, fileSystem @*/
{
size_t len = (size_t)6;
int xx;
xx = POPT_fprintf(fp, POPT_("Usage:"));
if (!(con->flags & POPT_CONTEXT_KEEP_FIRST)) {
struct optionStackEntry * os = con->optionStack;
const char * fn = (os->argv ? os->argv[0] : NULL);
if (fn == NULL) return len;
if (strchr(fn, '/')) fn = strrchr(fn, '/') + 1;
/* XXX POPT_fprintf not needed for argv[0] display. */
fprintf(fp, " %s", fn);
len += strlen(fn) + 1;
}
return len;
}
void poptPrintHelp(poptContext con, FILE * fp, /*@unused@*/ UNUSED(int flags))
{
columns_t columns = calloc((size_t)1, sizeof(*columns));
int xx;
(void) showHelpIntro(con, fp);
if (con->otherHelp)
xx = POPT_fprintf(fp, " %s\n", con->otherHelp);
else
xx = POPT_fprintf(fp, " %s\n", POPT_("[OPTION...]"));
if (columns) {
columns->cur = maxArgWidth(con->options, NULL);
columns->max = maxColumnWidth(fp);
singleTableHelp(con, fp, con->options, columns, NULL);
free(columns);
}
}
/**
* Display usage text for an option.
* @param fp output file handle
* @param columns output display width control
* @param opt option(s)
* @param translation_domain translation domain
*/
static size_t singleOptionUsage(FILE * fp, columns_t columns,
const struct poptOption * opt,
/*@null@*/ const char *translation_domain)
/*@globals fileSystem @*/
/*@modifies fp, columns->cur, fileSystem @*/
{
size_t len = sizeof(" []")-1;
const char * argDescrip = getArgDescrip(opt, translation_domain);
/* Display shortName iff printable non-space. */
int prtshort = (int)(isprint((int)opt->shortName) && opt->shortName != ' ');
#define prtlong (opt->longName != NULL) /* XXX splint needs a clue */
if (!(prtshort || prtlong))
return columns->cur;
len = sizeof(" []")-1;
if (prtshort)
len += sizeof("-c")-1;
if (prtlong) {
if (prtshort) len += sizeof("|")-1;
len += (F_ISSET(opt, ONEDASH) ? sizeof("-") : sizeof("--")) - 1;
len += strlen(opt->longName);
}
if (argDescrip) {
/* XXX argDescrip[0] determines "--foo=bar" or "--foo bar". */
if (!strchr(" =(", argDescrip[0])) len += sizeof("=")-1;
/* Adjust for (possible) wide characters. */
len += stringDisplayWidth(argDescrip);
}
if ((columns->cur + len) > columns->max) {
fprintf(fp, "\n ");
columns->cur = (size_t)7;
}
fprintf(fp, " [");
if (prtshort)
fprintf(fp, "-%c", opt->shortName);
if (prtlong)
fprintf(fp, "%s%s%s",
(prtshort ? "|" : ""),
(F_ISSET(opt, ONEDASH) ? "-" : "--"),
opt->longName);
#undef prtlong
if (argDescrip) {
/* XXX argDescrip[0] determines "--foo=bar" or "--foo bar". */
if (!strchr(" =(", argDescrip[0])) fprintf(fp, "=");
fprintf(fp, "%s", argDescrip);
}
fprintf(fp, "]");
return columns->cur + len + 1;
}
/**
* Display popt alias and exec usage.
* @param fp output file handle
* @param columns output display width control
* @param item alias/exec array
* @param nitems no. of ara/exec entries
* @param translation_domain translation domain
*/
static size_t itemUsage(FILE * fp, columns_t columns,
/*@null@*/ poptItem item, int nitems,
/*@null@*/ const char * translation_domain)
/*@globals fileSystem @*/
/*@modifies fp, columns->cur, fileSystem @*/
{
int i;
if (item != NULL)
for (i = 0; i < nitems; i++, item++) {
const struct poptOption * opt;
opt = &item->option;
if (poptArgType(opt) == POPT_ARG_INTL_DOMAIN) {
translation_domain = (const char *)opt->arg;
} else
if ((opt->longName || opt->shortName) && !F_ISSET(opt, DOC_HIDDEN)) {
columns->cur = singleOptionUsage(fp, columns, opt, translation_domain);
}
}
return columns->cur;
}
/**
* Keep track of option tables already processed.
*/
typedef struct poptDone_s {
int nopts;
int maxopts;
/*@null@*/
const void ** opts;
} * poptDone;
/**
* Display usage text for a table of options.
* @param con context
* @param fp output file handle
* @param columns output display width control
* @param opt option(s)
* @param translation_domain translation domain
* @param done tables already processed
* @return
*/
static size_t singleTableUsage(poptContext con, FILE * fp, columns_t columns,
/*@null@*/ const struct poptOption * opt,
/*@null@*/ const char * translation_domain,
/*@null@*/ poptDone done)
/*@globals fileSystem @*/
/*@modifies fp, columns->cur, done, fileSystem @*/
{
if (opt != NULL)
for (; (opt->longName || opt->shortName || opt->arg) ; opt++) {
if (poptArgType(opt) == POPT_ARG_INTL_DOMAIN) {
translation_domain = (const char *)opt->arg;
} else
if (poptArgType(opt) == POPT_ARG_INCLUDE_TABLE) {
if (done) {
int i = 0;
if (done->opts != NULL)
for (i = 0; i < done->nopts; i++) {
const void * that = done->opts[i];
if (that == NULL || that != opt->arg)
/*@innercontinue@*/ continue;
/*@innerbreak@*/ break;
}
/* Skip if this table has already been processed. */
if (opt->arg == NULL || i < done->nopts)
continue;
if (done->opts != NULL && done->nopts < done->maxopts)
done->opts[done->nopts++] = (const void *) opt->arg;
}
columns->cur = singleTableUsage(con, fp, columns, opt->arg,
translation_domain, done);
} else
if ((opt->longName || opt->shortName) && !F_ISSET(opt, DOC_HIDDEN)) {
columns->cur = singleOptionUsage(fp, columns, opt, translation_domain);
}
}
return columns->cur;
}
/**
* Return concatenated short options for display.
* @todo Sub-tables should be recursed.
* @param opt option(s)
* @param fp output file handle
* @retval str concatenation of short options
* @return length of display string
*/
static size_t showShortOptions(const struct poptOption * opt, FILE * fp,
/*@null@*/ char * str)
/*@globals fileSystem @*/
/*@modifies str, *fp, fileSystem @*/
/*@requires maxRead(str) >= 0 @*/
{
/* bufsize larger then the ascii set, lazy allocation on top level call. */
size_t nb = (size_t)300;
char * s = (str != NULL ? str : calloc((size_t)1, nb));
size_t len = (size_t)0;
if (s == NULL)
return 0;
if (opt != NULL)
for (; (opt->longName || opt->shortName || opt->arg); opt++) {
if (!F_ISSET(opt, DOC_HIDDEN) && opt->shortName && !poptArgType(opt))
{
/* Display shortName iff unique printable non-space. */
if (!strchr(s, opt->shortName) && isprint((int)opt->shortName)
&& opt->shortName != ' ')
s[strlen(s)] = opt->shortName;
} else if (poptArgType(opt) == POPT_ARG_INCLUDE_TABLE)
if (opt->arg) /* XXX program error */
len = showShortOptions(opt->arg, fp, s);
}
/* On return to top level, print the short options, return print length. */
if (s != str && *s != '\0') {
fprintf(fp, " [-%s]", s);
len = strlen(s) + sizeof(" [-]")-1;
}
/*@-temptrans@*/ /* LCL: local s, not str arg, is being freed. */
if (s != str)
free(s);
/*@=temptrans@*/
return len;
}
void poptPrintUsage(poptContext con, FILE * fp, /*@unused@*/ UNUSED(int flags))
{
columns_t columns = calloc((size_t)1, sizeof(*columns));
struct poptDone_s done_buf;
poptDone done = &done_buf;
memset(done, 0, sizeof(*done));
done->nopts = 0;
done->maxopts = 64;
if (columns) {
columns->cur = done->maxopts * sizeof(*done->opts);
columns->max = maxColumnWidth(fp);
done->opts = calloc((size_t)1, columns->cur);
/*@-keeptrans@*/
if (done->opts != NULL)
done->opts[done->nopts++] = (const void *) con->options;
/*@=keeptrans@*/
columns->cur = showHelpIntro(con, fp);
columns->cur += showShortOptions(con->options, fp, NULL);
columns->cur = singleTableUsage(con, fp, columns, con->options, NULL, done);
columns->cur = itemUsage(fp, columns, con->aliases, con->numAliases, NULL);
columns->cur = itemUsage(fp, columns, con->execs, con->numExecs, NULL);
if (con->otherHelp) {
columns->cur += strlen(con->otherHelp) + 1;
if (columns->cur > columns->max) fprintf(fp, "\n ");
fprintf(fp, " %s", con->otherHelp);
}
fprintf(fp, "\n");
if (done->opts != NULL)
free(done->opts);
free(columns);
}
}
void poptSetOtherOptionHelp(poptContext con, const char * text)
{
con->otherHelp = _free(con->otherHelp);
con->otherHelp = xstrdup(text);
}
+199
View File
@@ -0,0 +1,199 @@
#include "system.h"
#include <stdarg.h>
#include "poptint.h"
/* Any pair of 32 bit hashes can be used. lookup3.c generates pairs, will do. */
#define _JLU3_jlu32lpair 1
#define jlu32lpair poptJlu32lpair
#include "lookup3.c"
/*@-varuse +charint +ignoresigns @*/
/*@unchecked@*/ /*@observer@*/
static const unsigned char utf8_skip_data[256] = {
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1
};
/*@=varuse =charint =ignoresigns @*/
const char *
POPT_prev_char (const char *str)
{
const char *p = str;
while (1) {
p--;
if (((unsigned)*p & 0xc0) != (unsigned)0x80)
return p;
}
}
const char *
POPT_next_char (const char *str)
{
const char *p = str;
while (*p != '\0') {
p++;
if (((unsigned)*p & 0xc0) != (unsigned)0x80)
break;
}
return p;
}
#if !defined(POPT_fprintf) /* XXX lose all the goop ... */
#if defined(HAVE_DCGETTEXT) && !defined(__LCLINT__)
/*
* Rebind a "UTF-8" codeset for popt's internal use.
*/
char *
POPT_dgettext(const char * dom, const char * str)
{
char * codeset = NULL;
char * retval = NULL;
if (!dom)
dom = textdomain(NULL);
codeset = bind_textdomain_codeset(dom, NULL);
bind_textdomain_codeset(dom, "UTF-8");
retval = dgettext(dom, str);
bind_textdomain_codeset(dom, codeset);
return retval;
}
#endif
#ifdef HAVE_ICONV
/**
* Return malloc'd string converted from UTF-8 to current locale.
* @param istr input string (UTF-8 encoding assumed)
* @return localized string
*/
static /*@only@*/ /*@null@*/ char *
strdup_locale_from_utf8 (/*@null@*/ char * istr)
/*@*/
{
char * codeset = NULL;
char * ostr = NULL;
iconv_t cd;
if (istr == NULL)
return NULL;
#ifdef HAVE_LANGINFO_H
codeset = nl_langinfo ((nl_item)CODESET);
#endif
if (codeset != NULL && strcmp(codeset, "UTF-8") != 0
&& (cd = iconv_open(codeset, "UTF-8")) != (iconv_t)-1)
{
char * shift_pin = NULL;
size_t db = strlen(istr);
/*@owned@*/
char * dstr = malloc((db + 1) * sizeof(*dstr));
char * pin = istr;
char * pout = dstr;
size_t ib = db;
size_t ob = db;
size_t err;
if (dstr == NULL)
return NULL;
err = iconv(cd, NULL, NULL, NULL, NULL);
while (1) {
*pout = '\0';
err = iconv(cd, &pin, &ib, &pout, &ob);
if (err != (size_t)-1) {
if (shift_pin == NULL) {
shift_pin = pin;
pin = NULL;
ib = 0;
continue;
}
} else
switch (errno) {
case E2BIG:
{ size_t used = (size_t)(pout - dstr);
db *= 2;
dstr = realloc(dstr, (db + 1) * sizeof(*dstr));
if (dstr != NULL) {
pout = dstr + used;
ob = db - used;
continue;
}
} /*@switchbreak@*/ break;
case EINVAL:
case EILSEQ:
default:
/*@switchbreak@*/ break;
}
break;
}
(void) iconv_close(cd);
*pout = '\0';
ostr = xstrdup(dstr);
free(dstr);
} else
ostr = xstrdup(istr);
return ostr;
}
#endif
int
POPT_fprintf (FILE * stream, const char * format, ...)
{
char * b = NULL, * ob = NULL;
int rc;
va_list ap;
#if defined(HAVE_VASPRINTF) && !defined(__LCLINT__)
va_start(ap, format);
if ((rc = vasprintf(&b, format, ap)) < 0)
b = NULL;
va_end(ap);
#else
size_t nb = (size_t)1;
/* HACK: add +1 to the realloc no. of bytes "just in case". */
/* XXX Likely unneeded, the issues wrto vsnprintf(3) return b0rkage have
* to do with whether the final '\0' is counted (or not). The code
* below already adds +1 for the (possibly already counted) trailing NUL.
*/
while ((b = realloc(b, nb+1)) != NULL) {
va_start(ap, format);
rc = vsnprintf(b, nb, format, ap);
va_end(ap);
if (rc > -1) { /* glibc 2.1 */
if ((size_t)rc < nb)
break;
nb = (size_t)(rc + 1); /* precise buffer length known */
} else /* glibc 2.0 */
nb += (nb < (size_t)100 ? (size_t)100 : nb);
ob = b;
}
#endif
rc = 0;
if (b != NULL) {
#ifdef HAVE_ICONV
ob = strdup_locale_from_utf8(b);
if (ob != NULL) {
rc = fprintf(stream, "%s", ob);
free(ob);
} else
#endif
rc = fprintf(stream, "%s", b);
free (b);
}
return rc;
}
#endif /* !defined(POPT_fprintf) */
+222
View File
@@ -0,0 +1,222 @@
/** \ingroup popt
* \file popt/poptint.h
*/
/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
ftp://ftp.rpm.org/pub/rpm/dist. */
#ifndef H_POPTINT
#define H_POPTINT
#include <stdint.h>
/**
* Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
* @param p memory to free
* @retval NULL always
*/
/*@unused@*/ static inline /*@null@*/ void *
_free(/*@only@*/ /*@null@*/ const void * p)
/*@modifies p @*/
{
if (p != NULL) free((void *)p);
return NULL;
}
/* Bit mask macros. */
/*@-exporttype -redef @*/
typedef unsigned int __pbm_bits;
/*@=exporttype =redef @*/
#define __PBM_NBITS (8 * sizeof (__pbm_bits))
#define __PBM_IX(d) ((d) / __PBM_NBITS)
#define __PBM_MASK(d) ((__pbm_bits) 1 << (((unsigned)(d)) % __PBM_NBITS))
/*@-exporttype -redef @*/
typedef struct {
__pbm_bits bits[1];
} pbm_set;
/*@=exporttype =redef @*/
#define __PBM_BITS(set) ((set)->bits)
#define PBM_ALLOC(d) calloc(__PBM_IX (d) + 1, sizeof(__pbm_bits))
#define PBM_FREE(s) _free(s);
#define PBM_SET(d, s) (__PBM_BITS (s)[__PBM_IX (d)] |= __PBM_MASK (d))
#define PBM_CLR(d, s) (__PBM_BITS (s)[__PBM_IX (d)] &= ~__PBM_MASK (d))
#define PBM_ISSET(d, s) ((__PBM_BITS (s)[__PBM_IX (d)] & __PBM_MASK (d)) != 0)
extern void poptJlu32lpair(/*@null@*/ const void *key, size_t size,
uint32_t *pc, uint32_t *pb)
/*@modifies *pc, *pb@*/;
/** \ingroup popt
* Typedef's for string and array of strings.
*/
/*@-exporttype@*/
typedef const char * poptString;
typedef poptString * poptArgv;
/*@=exporttype@*/
/** \ingroup popt
* A union to simplify opt->arg access without casting.
*/
/*@-exporttype -fielduse@*/
typedef union poptArg_u {
/*@shared@*/
void * ptr;
int * intp;
short * shortp;
long * longp;
long long * longlongp;
float * floatp;
double * doublep;
const char ** argv;
poptCallbackType cb;
/*@shared@*/
poptOption opt;
} poptArg;
/*@=exporttype =fielduse@*/
/*@-exportvar@*/
/*@unchecked@*/
extern unsigned int _poptArgMask;
/*@unchecked@*/
extern unsigned int _poptGroupMask;
/*@=exportvar@*/
#define poptArgType(_opt) ((_opt)->argInfo & _poptArgMask)
#define poptGroup(_opt) ((_opt)->argInfo & _poptGroupMask)
#define F_ISSET(_opt, _FLAG) ((_opt)->argInfo & POPT_ARGFLAG_##_FLAG)
#define LF_ISSET(_FLAG) (argInfo & POPT_ARGFLAG_##_FLAG)
#define CBF_ISSET(_opt, _FLAG) ((_opt)->argInfo & POPT_CBFLAG_##_FLAG)
/* XXX sick hack to preserve pretense of a popt-1.x ABI. */
#define poptSubstituteHelpI18N(opt) \
{ /*@-observertrans@*/ \
if ((opt) == poptHelpOptions) (opt) = poptHelpOptionsI18N; \
/*@=observertrans@*/ }
struct optionStackEntry {
int argc;
/*@only@*/ /*@null@*/
poptArgv argv;
/*@only@*/ /*@null@*/
pbm_set * argb;
int next;
/*@only@*/ /*@null@*/
char * nextArg;
/*@observer@*/ /*@null@*/
const char * nextCharArg;
/*@dependent@*/ /*@null@*/
poptItem currAlias;
int stuffed;
};
struct poptContext_s {
struct optionStackEntry optionStack[POPT_OPTION_DEPTH];
/*@dependent@*/
struct optionStackEntry * os;
/*@owned@*/ /*@null@*/
poptArgv leftovers;
int numLeftovers;
int nextLeftover;
/*@keep@*/
const struct poptOption * options;
int restLeftover;
/*@only@*/ /*@null@*/
const char * appName;
/*@only@*/ /*@null@*/
poptItem aliases;
int numAliases;
unsigned int flags;
/*@owned@*/ /*@null@*/
poptItem execs;
int numExecs;
/*@only@*/ /*@null@*/
poptArgv finalArgv;
int finalArgvCount;
int finalArgvAlloced;
/*@null@*/
int (*maincall) (int argc, const char **argv);
/*@dependent@*/ /*@null@*/
poptItem doExec;
/*@only@*/ /*@null@*/
const char * execPath;
int execAbsolute;
/*@only@*/ /*@relnull@*/
const char * otherHelp;
/*@null@*/
pbm_set * arg_strip;
};
#if defined(POPT_fprintf)
#define POPT_dgettext dgettext
#else
#ifdef HAVE_ICONV
#include <iconv.h>
#if defined(__LCLINT__)
/*@-declundef -incondefs @*/
extern /*@only@*/ iconv_t iconv_open(const char *__tocode, const char *__fromcode)
/*@*/;
extern size_t iconv(iconv_t __cd, /*@null@*/ char ** __inbuf,
/*@null@*/ /*@out@*/ size_t * __inbytesleft,
/*@null@*/ /*@out@*/ char ** __outbuf,
/*@null@*/ /*@out@*/ size_t * __outbytesleft)
/*@modifies __cd,
*__inbuf, *__inbytesleft, *__outbuf, *__outbytesleft @*/;
extern int iconv_close(/*@only@*/ iconv_t __cd)
/*@modifies __cd @*/;
/*@=declundef =incondefs @*/
#endif
#endif
#ifdef HAVE_LANGINFO_H
#include <langinfo.h>
#if defined(__LCLINT__)
/*@-declundef -incondefs @*/
extern char *nl_langinfo (nl_item __item)
/*@*/;
/*@=declundef =incondefs @*/
#endif
#endif
#if defined(HAVE_DCGETTEXT) && !defined(__LCLINT__)
char *POPT_dgettext(const char * dom, const char * str)
/*@*/;
#endif
int POPT_fprintf (FILE* stream, const char *format, ...)
/*@globals fileSystem @*/
/*@modifies stream, fileSystem @*/;
#endif /* !defined(POPT_fprintf) */
const char *POPT_prev_char (/*@returned@*/ const char *str)
/*@*/;
const char *POPT_next_char (/*@returned@*/ const char *str)
/*@*/;
#endif
#if defined(ENABLE_NLS) && defined(HAVE_LIBINTL_H)
#include <libintl.h>
#endif
#if defined(ENABLE_NLS) && defined(HAVE_GETTEXT) && !defined(__LCLINT__)
#define _(foo) gettext(foo)
#else
#define _(foo) foo
#endif
#if defined(ENABLE_NLS) && defined(HAVE_DCGETTEXT) && !defined(__LCLINT__)
#define D_(dom, str) POPT_dgettext(dom, str)
#define POPT_(foo) D_("popt", foo)
#else
#define D_(dom, str) str
#define POPT_(foo) foo
#endif
#define N_(foo) foo
+230
View File
@@ -0,0 +1,230 @@
/** \ingroup popt
* \file popt/poptparse.c
*/
/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
ftp://ftp.rpm.org/pub/rpm/dist. */
#include "system.h"
#define POPT_ARGV_ARRAY_GROW_DELTA 5
int poptDupArgv(int argc, const char **argv,
int * argcPtr, const char *** argvPtr)
{
size_t nb = (argc + 1) * sizeof(*argv);
const char ** argv2;
char * dst;
int i;
if (argc <= 0 || argv == NULL) /* XXX can't happen */
return POPT_ERROR_NOARG;
for (i = 0; i < argc; i++) {
if (argv[i] == NULL)
return POPT_ERROR_NOARG;
nb += strlen(argv[i]) + 1;
}
dst = malloc(nb);
if (dst == NULL) /* XXX can't happen */
return POPT_ERROR_MALLOC;
argv2 = (void *) dst;
dst += (argc + 1) * sizeof(*argv);
*dst = '\0';
for (i = 0; i < argc; i++) {
argv2[i] = dst;
dst = stpcpy(dst, argv[i]);
dst++; /* trailing NUL */
}
argv2[argc] = NULL;
if (argvPtr) {
*argvPtr = argv2;
} else {
free(argv2);
argv2 = NULL;
}
if (argcPtr)
*argcPtr = argc;
return 0;
}
int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
{
const char * src;
char quote = '\0';
int argvAlloced = POPT_ARGV_ARRAY_GROW_DELTA;
const char ** argv = malloc(sizeof(*argv) * argvAlloced);
int argc = 0;
size_t buflen = strlen(s) + 1;
char * buf, * bufOrig = NULL;
int rc = POPT_ERROR_MALLOC;
if (argv == NULL) return rc;
buf = bufOrig = calloc((size_t)1, buflen);
if (buf == NULL) {
free(argv);
return rc;
}
argv[argc] = buf;
for (src = s; *src != '\0'; src++) {
if (quote == *src) {
quote = '\0';
} else if (quote != '\0') {
if (*src == '\\') {
src++;
if (!*src) {
rc = POPT_ERROR_BADQUOTE;
goto exit;
}
if (*src != quote) *buf++ = '\\';
}
*buf++ = *src;
} else if (_isspaceptr(src)) {
if (*argv[argc] != '\0') {
buf++, argc++;
if (argc == argvAlloced) {
argvAlloced += POPT_ARGV_ARRAY_GROW_DELTA;
argv = realloc(argv, sizeof(*argv) * argvAlloced);
if (argv == NULL) goto exit;
}
argv[argc] = buf;
}
} else switch (*src) {
case '"':
case '\'':
quote = *src;
/*@switchbreak@*/ break;
case '\\':
src++;
if (!*src) {
rc = POPT_ERROR_BADQUOTE;
goto exit;
}
/*@fallthrough@*/
default:
*buf++ = *src;
/*@switchbreak@*/ break;
}
}
if (strlen(argv[argc])) {
argc++, buf++;
}
rc = poptDupArgv(argc, argv, argcPtr, argvPtr);
exit:
if (bufOrig) free(bufOrig);
if (argv) free(argv);
return rc;
}
/* still in the dev stage.
* return values, perhaps 1== file erro
* 2== line to long
* 3== umm.... more?
*/
int poptConfigFileToString(FILE *fp, char ** argstrp,
/*@unused@*/ UNUSED(int flags))
{
char line[999];
char * argstr;
char * p;
char * q;
char * x;
size_t t;
size_t argvlen = 0;
size_t maxlinelen = sizeof(line);
size_t linelen;
size_t maxargvlen = (size_t)480;
*argstrp = NULL;
/* | this_is = our_line
* p q x
*/
if (fp == NULL)
return POPT_ERROR_NULLARG;
argstr = calloc(maxargvlen, sizeof(*argstr));
if (argstr == NULL) return POPT_ERROR_MALLOC;
while (fgets(line, (int)maxlinelen, fp) != NULL) {
p = line;
/* loop until first non-space char or EOL */
while( *p != '\0' && _isspaceptr(p) )
p++;
linelen = strlen(p);
if (linelen >= maxlinelen-1) {
free(argstr);
return POPT_ERROR_OVERFLOW; /* XXX line too long */
}
if (*p == '\0' || *p == '\n') continue; /* line is empty */
if (*p == '#') continue; /* comment line */
q = p;
while (*q != '\0' && (!_isspaceptr(q)) && *q != '=')
q++;
if (_isspaceptr(q)) {
/* a space after the name, find next non space */
*q++='\0';
while( *q != '\0' && _isspaceptr(q) ) q++;
}
if (*q == '\0') {
/* single command line option (ie, no name=val, just name) */
q[-1] = '\0'; /* kill off newline from fgets() call */
argvlen += (t = (size_t)(q - p)) + (sizeof(" --")-1);
if (argvlen >= maxargvlen) {
maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2;
argstr = realloc(argstr, maxargvlen);
if (argstr == NULL) return POPT_ERROR_MALLOC;
}
strcat(argstr, " --");
strcat(argstr, p);
continue;
}
if (*q != '=')
continue; /* XXX for now, silently ignore bogus line */
/* *q is an equal sign. */
*q++ = '\0';
/* find next non-space letter of value */
while (*q != '\0' && _isspaceptr(q))
q++;
if (*q == '\0')
continue; /* XXX silently ignore missing value */
/* now, loop and strip all ending whitespace */
x = p + linelen;
while (_isspaceptr(--x))
*x = '\0'; /* null out last char if space (including fgets() NL) */
/* rest of line accept */
t = (size_t)(x - p);
argvlen += t + (sizeof("' --='")-1);
if (argvlen >= maxargvlen) {
maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2;
argstr = realloc(argstr, maxargvlen);
if (argstr == NULL) return POPT_ERROR_MALLOC;
}
strcat(argstr, " --");
strcat(argstr, p);
strcat(argstr, "=\"");
strcat(argstr, q);
strcat(argstr, "\"");
}
*argstrp = argstr;
return 0;
}
+103
View File
@@ -0,0 +1,103 @@
/**
* \file popt/system.h
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#if defined (__GLIBC__) && defined(__LCLINT__)
/*@-declundef@*/
/*@unchecked@*/
extern __const __int32_t *__ctype_tolower;
/*@unchecked@*/
extern __const __int32_t *__ctype_toupper;
/*@=declundef@*/
#endif
#include <ctype.h>
/* XXX isspace(3) has i18n encoding signednesss issues on Solaris. */
#define _isspaceptr(_chp) isspace((int)(*(unsigned char *)(_chp)))
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#ifdef HAVE_MCHECK_H
#include <mcheck.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(HAVE_UNISTD_H) && !defined(__LCLINT__)
#include <unistd.h>
#endif
#ifdef __NeXT
/* access macros are not declared in non posix mode in unistd.h -
don't try to use posix on NeXTstep 3.3 ! */
#include <libc.h>
#endif
/*@-incondefs@*/
/*@mayexit@*/ /*@only@*/ /*@out@*/ /*@unused@*/
void * xmalloc (size_t size)
/*@globals errno @*/
/*@ensures maxSet(result) == (size - 1) @*/
/*@modifies errno @*/;
/*@mayexit@*/ /*@only@*/ /*@unused@*/
void * xcalloc (size_t nmemb, size_t size)
/*@ensures maxSet(result) == (nmemb - 1) @*/
/*@*/;
/*@mayexit@*/ /*@only@*/ /*@unused@*/
void * xrealloc (/*@null@*/ /*@only@*/ void * ptr, size_t size)
/*@ensures maxSet(result) == (size - 1) @*/
/*@modifies *ptr @*/;
/*@mayexit@*/ /*@only@*/ /*@unused@*/
char * xstrdup (const char *str)
/*@*/;
/*@=incondefs@*/
#if !defined(HAVE_STPCPY)
/* Copy SRC to DEST, returning the address of the terminating '\0' in DEST. */
static inline char * stpcpy (char *dest, const char * src) {
register char *d = dest;
register const char *s = src;
do
*d++ = *s;
while (*s++ != '\0');
return d - 1;
}
#endif
/* Memory allocation via macro defs to get meaningful locations from mtrace() */
#if defined(HAVE_MCHECK_H) && defined(__GNUC__)
#define vmefail() (fprintf(stderr, "virtual memory exhausted.\n"), exit(EXIT_FAILURE), NULL)
#define xmalloc(_size) (malloc(_size) ? : vmefail())
#define xcalloc(_nmemb, _size) (calloc((_nmemb), (_size)) ? : vmefail())
#define xrealloc(_ptr, _size) (realloc((_ptr), (_size)) ? : vmefail())
#define xstrdup(_str) (strcpy((malloc(strlen(_str)+1) ? : vmefail()), (_str)))
#else
#define xmalloc(_size) malloc(_size)
#define xcalloc(_nmemb, _size) calloc((_nmemb), (_size))
#define xrealloc(_ptr, _size) realloc((_ptr), (_size))
#define xstrdup(_str) strdup(_str)
#endif /* defined(HAVE_MCHECK_H) && defined(__GNUC__) */
#if defined(HAVE___SECURE_GETENV) && !defined(__LCLINT__)
#define getenv(_s) __secure_getenv(_s)
#endif
#if !defined(__GNUC__) && !defined(__attribute__)
#define __attribute__(x)
#endif
#define UNUSED(x) x __attribute__((__unused__))
#include "popt.h"
+132
View File
@@ -0,0 +1,132 @@
#include "system.h"
#include <stdio.h>
#include "popt.h"
static int _debug = 0;
static int _verbose = 1;
static const char * dictfn = "/usr/share/dict/words";
static poptBits dictbits = NULL;
static struct {
unsigned total;
unsigned hits;
unsigned misses;
} e;
static int loadDict(const char * fn, poptBits * ap)
{
char b[BUFSIZ];
size_t nb = sizeof(b);
FILE * fp = fopen(fn, "r");
char * t, *te;
int nlines = -1;
if (fp == NULL || ferror(fp)) goto exit;
nlines = 0;
while ((t = fgets(b, nb, fp)) != NULL) {
while (*t && isspace(*t)) t++;
if (*t == '#') continue;
te = t + strlen(t);
while (te-- > t && isspace(*te)) *te = '\0';
if (*t == '\0') continue;
if (ap) {
if (_debug)
fprintf(stderr, "==> poptSaveBits(%p, \"%s\")\n", *ap, t);
(void) poptSaveBits(ap, 0, t);
}
nlines++;
}
exit:
if (fp) (void) fclose(fp);
return nlines;
}
static struct poptOption options[] = {
{ "debug", 'd', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, &_debug, 1,
"Set debugging.", NULL },
{ "verbose", 'v', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, &_verbose, 1,
"Set verbosity.", NULL },
POPT_AUTOALIAS
POPT_AUTOHELP
POPT_TABLEEND
};
int main(int argc, const char ** argv)
{
poptContext optCon = NULL;
const char ** av = NULL;
poptBits avbits = NULL;
int ec = 2; /* assume failure */
int rc;
#if defined(HAVE_MCHECK_H) && defined(HAVE_MTRACE)
mtrace(); /* Trace malloc only if MALLOC_TRACE=mtrace-output-file. */
#endif
/* XXX Scale the Bloom filters in popt. */
if ((rc = loadDict(dictfn, NULL)) <= 0)
goto exit;
_poptBitsK = 2;
_poptBitsM = 0;
_poptBitsN = _poptBitsK * rc;
optCon = poptGetContext("tdict", argc, argv, options, 0);
/* Read all the options (if any). */
while ((rc = poptGetNextOpt(optCon)) > 0) {
char * optArg = poptGetOptArg(optCon);
if (optArg) free(optArg);
switch (rc) {
default: goto exit; break;
}
}
if (rc < -1) {
fprintf(stderr, "tdict: %s: %s\n",
poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
poptStrerror(rc));
goto exit;
}
if ((rc = loadDict(dictfn, &dictbits)) <= 0)
goto exit;
av = poptGetArgs(optCon);
if ((rc = poptBitsArgs(optCon, &avbits)) != 0)
goto exit;
if (avbits) {
poptBits Ibits = NULL;
(void) poptBitsUnion(&Ibits, dictbits);
rc = poptBitsIntersect(&Ibits, avbits);
fprintf(stdout, "===== %s words are in %s\n", (rc ? "Some" : "No"), dictfn);
if (Ibits) free(Ibits);
}
if (av && avbits)
while (*av) {
rc = poptBitsChk(dictbits, *av);
if (rc < 0) goto exit;
e.total++;
if (rc > 0) {
if (_verbose)
fprintf(stdout, "%s:\tYES\n", *av);
e.hits++;
} else {
if (_verbose)
fprintf(stdout, "%s:\tNO\n", *av);
e.misses++;
}
av++;
}
ec = 0;
exit:
fprintf(stdout, "===== poptBits N:%u M:%u K:%u (%uKb) total(%u) = hits(%u) + misses(%u)\n",
_poptBitsN, _poptBitsM, _poptBitsK, (((_poptBitsM/8)+1)+1023)/1024, e.total, e.hits, e.misses);
if (avbits) free(avbits);
optCon = poptFreeContext(optCon);
#if defined(HAVE_MCHECK_H) && defined(HAVE_MTRACE)
muntrace(); /* Trace malloc only if MALLOC_TRACE=mtrace-output-file. */
#endif
return ec;
}
+362
View File
@@ -0,0 +1,362 @@
/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
ftp://ftp.rpm.org/pub/rpm/dist. */
#include "system.h"
/*@unchecked@*/
static int pass2 = 0;
static void option_callback(/*@unused@*/ UNUSED(poptContext con),
/*@unused@*/ UNUSED(enum poptCallbackReason reason),
const struct poptOption * opt,
char * arg, void * data)
/*@globals fileSystem @*/
/*@modifies fileSystem @*/
{
if (pass2)
fprintf(stdout, "callback: %c %s %s ", opt->val, (char *) data, arg);
}
/*@unchecked@*/
static int arg1 = 0;
/*@unchecked@*/ /*@observer@*/
static char * arg2 = "(none)";
/*@unchecked@*/
static int arg3 = 0;
/*@unchecked@*/
static int inc = 0;
/*@unchecked@*/
static int shortopt = 0;
/*@unchecked@*/
static int aVal = 141421;
/*@unchecked@*/
static int bVal = 141421;
/*@unchecked@*/
static unsigned int aFlag = 0x8aceU;
/*@unchecked@*/
static unsigned int bFlag = 0x8aceU;
/*@unchecked@*/
static short aShort = (short)4523;
/*@unchecked@*/
static short bShort = (short)4523;
/*@unchecked@*/
static int aInt = 271828;
/*@unchecked@*/
static int bInt = 271828;
/*@unchecked@*/
static long aLong = 738905609L;
/*@unchecked@*/
static long bLong = 738905609L;
/*@unchecked@*/
static long long aLongLong = 738905609LL;
/*@unchecked@*/
static long long bLongLong = 738905609LL;
/*@unchecked@*/
static float aFloat = 3.1415926535;
/*@unchecked@*/
static float bFloat = 3.1415926535;
/*@unchecked@*/
static double aDouble = 9.86960440108935861883;
/*@unchecked@*/
static double bDouble = 9.86960440108935861883;
/*@unchecked@*/ /*@only@*/ /*@null@*/
static const char ** aArgv = NULL;
/*@unchecked@*/ /*@only@*/ /*@null@*/
static void * aBits = NULL;
/*@unchecked@*/ /*@observer@*/
static const char *attributes[] = {
"foo", "bar", "baz", "bing", "bang", "boom"
};
/*@unchecked@*/
static size_t nattributes = (sizeof(attributes) / sizeof(attributes[0]));
/*@unchecked@*/ /*@null@*/
static char * oStr = (char *) -1;
/*@unchecked@*/
static int singleDash = 0;
/*@unchecked@*/ /*@observer@*/
static char * lStr =
"This tests default strings and exceeds the ... limit. "
"123456789+123456789+123456789+123456789+123456789+ "
"123456789+123456789+123456789+123456789+123456789+ "
"123456789+123456789+123456789+123456789+123456789+ "
"123456789+123456789+123456789+123456789+123456789+ ";
/*@unchecked@*/ /*@null@*/
static char * nStr = NULL;
/*@unchecked@*/
static struct poptOption moreCallbackArgs[] = {
{ NULL, '\0', POPT_ARG_CALLBACK|POPT_CBFLAG_INC_DATA,
(void *)option_callback, 0,
NULL, NULL },
{ "cb2", 'c', POPT_ARG_STRING, NULL, (int)'c',
"Test argument callbacks", NULL },
POPT_TABLEEND
};
/*@unchecked@*/
static struct poptOption callbackArgs[] = {
{ NULL, '\0', POPT_ARG_CALLBACK, (void *)option_callback, 0,
"sampledata", NULL },
{ "cb", 'c', POPT_ARG_STRING, NULL, (int)'c',
"Test argument callbacks", NULL },
{ "longopt", '\0', 0, NULL, (int)'l',
"Unused option for help testing", NULL },
POPT_TABLEEND
};
/*@unchecked@*/
static struct poptOption moreArgs[] = {
{ "inc", 'I', 0, &inc, 0, "An included argument", NULL },
POPT_TABLEEND
};
/*@unchecked@*/
static struct poptOption options[] = {
{ NULL, '\0', POPT_ARG_INCLUDE_TABLE, &moreCallbackArgs, 0,
"arg for cb2", NULL },
{ "arg1", '\0', 0, &arg1, 0, "First argument with a really long"
" description. After all, we have to test argument help"
" wrapping somehow, right?", NULL },
{ "arg2", '2', POPT_ARG_STRING | POPT_ARGFLAG_SHOW_DEFAULT, &arg2, 0,
"Another argument", "ARG" },
{ "arg3", '3', POPT_ARG_INT, &arg3, 0,
"A third argument", "ANARG" },
{ "onedash", '\0', POPT_ARGFLAG_ONEDASH, &shortopt, 0,
"POPT_ARGFLAG_ONEDASH: Option takes a single -", NULL },
{ "hidden", '\0', POPT_ARG_STRING | POPT_ARGFLAG_DOC_HIDDEN, NULL, 0,
"POPT_ARGFLAG_HIDDEN: A hidden option (--help shouldn't display)",
NULL },
{ "optional", '\0', POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, &oStr, 0,
"POPT_ARGFLAG_OPTIONAL: Takes an optional string argument", NULL },
{ "val", '\0', POPT_ARG_VAL | POPT_ARGFLAG_SHOW_DEFAULT, &aVal, 125992,
"POPT_ARG_VAL: 125992 141421", 0},
{ "int", 'i', POPT_ARG_INT | POPT_ARGFLAG_SHOW_DEFAULT, &aInt, 0,
"POPT_ARG_INT: 271828", NULL },
{ "short", 's', POPT_ARG_SHORT | POPT_ARGFLAG_SHOW_DEFAULT, &aShort, 0,
"POPT_ARG_SHORT: 4523", NULL },
{ "long", 'l', POPT_ARG_LONG | POPT_ARGFLAG_SHOW_DEFAULT, &aLong, 0,
"POPT_ARG_LONG: 738905609", NULL },
{ "longlong", 'L', POPT_ARG_LONGLONG | POPT_ARGFLAG_SHOW_DEFAULT, &aLongLong, 0,
"POPT_ARG_LONGLONG: 738905609", NULL },
{ "float", 'f', POPT_ARG_FLOAT | POPT_ARGFLAG_SHOW_DEFAULT, &aFloat, 0,
"POPT_ARG_FLOAT: 3.14159", NULL },
{ "double", 'd', POPT_ARG_DOUBLE | POPT_ARGFLAG_SHOW_DEFAULT, &aDouble, 0,
"POPT_ARG_DOUBLE: 9.8696", NULL },
{ "randint", '\0', POPT_ARG_INT|POPT_ARGFLAG_RANDOM, &aInt, 0,
"POPT_ARGFLAG_RANDOM: experimental", NULL },
{ "randshort", '\0', POPT_ARG_SHORT|POPT_ARGFLAG_RANDOM, &aShort, 0,
"POPT_ARGFLAG_RANDOM: experimental", NULL },
{ "randlong", '\0', POPT_ARG_LONG|POPT_ARGFLAG_RANDOM, &aLong, 0,
"POPT_ARGFLAG_RANDOM: experimental", NULL },
{ "randlonglong", '\0', POPT_ARG_LONGLONG|POPT_ARGFLAG_RANDOM, &aLongLong, 0,
"POPT_ARGFLAG_RANDOM: experimental", NULL },
{ "argv", '\0', POPT_ARG_ARGV, &aArgv, 0,
"POPT_ARG_ARGV: append string to argv array (can be used multiple times)","STRING"},
{ "bits", '\0', POPT_ARG_BITSET|POPT_ARGFLAG_DOC_HIDDEN, &aBits, 0,
"POPT_ARG_BITSET: add string to bit set (can be used multiple times)","STRING"},
{ "bitset", '\0', POPT_BIT_SET | POPT_ARGFLAG_TOGGLE | POPT_ARGFLAG_SHOW_DEFAULT, &aFlag, 0x7777,
"POPT_BIT_SET: |= 0x7777", 0},
{ "bitclr", '\0', POPT_BIT_CLR | POPT_ARGFLAG_TOGGLE | POPT_ARGFLAG_SHOW_DEFAULT, &aFlag, 0xf842,
"POPT_BIT_CLR: &= ~0xf842", 0},
{ "bitxor", '\0', POPT_ARG_VAL | POPT_ARGFLAG_XOR | POPT_ARGFLAG_SHOW_DEFAULT, &aFlag, (0x8ace^0xfeed),
"POPT_ARGFLAG_XOR: ^= (0x8ace^0xfeed)", 0},
{ "nstr", '\0', POPT_ARG_STRING | POPT_ARGFLAG_SHOW_DEFAULT, &nStr, 0,
"POPT_ARG_STRING: (null)", NULL},
{ "lstr", '\0', POPT_ARG_STRING | POPT_ARGFLAG_SHOW_DEFAULT, &lStr, 0,
"POPT_ARG_STRING: \"123456789...\"", NULL},
{ NULL, '-', POPT_ARG_NONE | POPT_ARGFLAG_DOC_HIDDEN, &singleDash, 0,
NULL, NULL },
{ NULL, '\0', POPT_ARG_INCLUDE_TABLE, &moreArgs, 0,
NULL, NULL },
{ NULL, '\0', POPT_ARG_INCLUDE_TABLE, &callbackArgs, 0,
"Callback arguments", NULL },
POPT_AUTOALIAS
POPT_AUTOHELP
POPT_TABLEEND
};
static void resetVars(void)
/*@globals arg1, arg2, arg3, inc, shortopt,
aVal, aFlag, aShort, aInt, aLong, aLongLong, aFloat, aDouble,
aArgv, aBits, oStr, singleDash, pass2 @*/
/*@modifies arg1, arg2, arg3, inc, shortopt,
aVal, aFlag, aShort, aInt, aLong, aLongLong, aFloat, aDouble,
aArgv, aBits, oStr, singleDash, pass2 @*/
{
arg1 = 0;
arg2 = "(none)";
arg3 = 0;
inc = 0;
shortopt = 0;
aVal = bVal;
aFlag = bFlag;
aShort = bShort;
aInt = bInt;
aLong = bLong;
aLongLong = bLongLong;
aFloat = bFloat;
aDouble = bDouble;
if (aArgv) {
int i;
for (i = 0; aArgv[i] != NULL; i++) {
/*@-unqualifiedtrans@*/
free((void *)aArgv[i]);
/*@=unqualifiedtrans@*/
aArgv[i] = NULL;
}
free(aArgv);
aArgv = NULL;
}
if (aBits)
(void) poptBitsClr(aBits);
oStr = (char *) -1;
singleDash = 0;
pass2 = 0;
}
int main(int argc, const char ** argv)
/*@globals pass2, fileSystem, internalState @*/
/*@modifies pass2, fileSystem, internalState @*/
{
int rc;
int ec = 0;
poptContext optCon;
const char ** rest;
int help = 0;
int usage = 0;
#if defined(HAVE_MCHECK_H) && defined(HAVE_MTRACE)
/*@-moduncon -noeffectuncon@*/
mtrace(); /* Trace malloc only if MALLOC_TRACE=mtrace-output-file. */
/*@=moduncon =noeffectuncon@*/
#endif
/*@-modobserver@*/
resetVars();
/*@=modobserver@*/
/*@-temptrans@*/
optCon = poptGetContext("test1", argc, argv, options, 0);
/*@=temptrans@*/
(void) poptReadConfigFile(optCon, "./test-poptrc");
(void) poptReadDefaultConfig(optCon, 1);
poptSetExecPath(optCon, ".", 1);
#if 1
while ((rc = poptGetNextOpt(optCon)) > 0) /* Read all the options ... */
{};
poptResetContext(optCon); /* ... and then start over. */
/*@-modobserver@*/
resetVars();
/*@=modobserver@*/
#endif
pass2 = 1;
if ((rc = poptGetNextOpt(optCon)) < -1) {
fprintf(stderr, "test1: bad argument %s: %s\n",
poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
poptStrerror(rc));
ec = 2;
goto exit;
}
if (help) {
poptPrintHelp(optCon, stdout, 0);
goto exit;
}
if (usage) {
poptPrintUsage(optCon, stdout, 0);
goto exit;
}
fprintf(stdout, "arg1: %d arg2: %s", arg1, arg2);
if (arg3)
fprintf(stdout, " arg3: %d", arg3);
if (inc)
fprintf(stdout, " inc: %d", inc);
if (shortopt)
fprintf(stdout, " short: %d", shortopt);
if (aVal != bVal)
fprintf(stdout, " aVal: %d", aVal);
if (aFlag != bFlag)
fprintf(stdout, " aFlag: 0x%x", aFlag);
if (aShort != bShort)
fprintf(stdout, " aShort: %hd", aShort);
if (aInt != bInt)
fprintf(stdout, " aInt: %d", aInt);
if (aLong != bLong)
fprintf(stdout, " aLong: %ld", aLong);
if (aLongLong != bLongLong)
fprintf(stdout, " aLongLong: %lld", aLongLong);
/*@-realcompare@*/
if (aFloat != bFloat)
fprintf(stdout, " aFloat: %g", (double)aFloat);
if (aDouble != bDouble)
fprintf(stdout, " aDouble: %g", aDouble);
/*@=realcompare@*/
if (aArgv != NULL) {
const char **av = aArgv;
const char * arg;
fprintf(stdout, " aArgv:");
while ((arg = *av++) != NULL)
fprintf(stdout, " %s", arg);
}
if (aBits) {
const char * separator = " ";
size_t i;
fprintf(stdout, " aBits:");
for (i = 0; i < nattributes; i++) {
if (!poptBitsChk(aBits, attributes[i]))
continue;
fprintf(stdout, "%s%s", separator, attributes[i]);
separator = ",";
}
}
/*@-nullpass@*/
if (oStr != (char *)-1)
fprintf(stdout, " oStr: %s", (oStr ? oStr : "(none)"));
/*@=nullpass@*/
if (singleDash)
fprintf(stdout, " -");
if (poptPeekArg(optCon) != NULL) {
rest = poptGetArgs(optCon);
if (rest) {
fprintf(stdout, " rest:");
while (*rest) {
fprintf(stdout, " %s", *rest);
rest++;
}
}
}
fprintf(stdout, "\n");
exit:
optCon = poptFreeContext(optCon);
#if defined(HAVE_MCHECK_H) && defined(HAVE_MTRACE)
/*@-moduncon -noeffectuncon@*/
muntrace(); /* Trace malloc only if MALLOC_TRACE=mtrace-output-file. */
/*@=moduncon =noeffectuncon@*/
#endif
return ec;
}
+149
View File
@@ -0,0 +1,149 @@
/*
Popt Library Test Program Number Too
--> "a real world test of popt bugs" <--
Copyright (C) 1999 US Interactive, Inc.
This program can be used under the GPL or LGPL at your
whim as long as this Copyright remains attached.
*/
#include "system.h"
char *PathnameOfKeyFile = NULL;
char *PathnameOfOfferFile = NULL;
char *txHost = NULL;
int txSslPort = 443;
int txStoreId = 0;
char *contentProtocol = NULL;
char *contentHost = NULL;
int contentPort = 80;
char *contentPath = NULL;
char *dbPassword = NULL;
char *dbUserName = NULL;
char *rcfile = "createuser-defaults";
char *username=NULL;
char *password = NULL;
char *firstname = NULL;
char *lastname = NULL;
char *addr1 = NULL;
char *addr2 = NULL;
char *city = NULL;
char *state = NULL;
char *postal = NULL;
char *country = NULL;
char *email = NULL;
char *dayphone = NULL;
char *fax = NULL;
int
main(int argc, const char ** argv) {
poptContext optCon; /* context for parsing command-line options */
struct poptOption userOptionsTable[] = {
{ "first", 'f', POPT_ARG_STRING, &firstname, 0,
"user's first name", "first" },
{ "last", 'l', POPT_ARG_STRING, &lastname, 0,
"user's last name", "last" },
{ "username", 'u', POPT_ARG_STRING, &username, 0,
"system user name", "user" },
{ "password", 'p', POPT_ARG_STRING, &password, 0,
"system password name", "password" },
{ "addr1", '1', POPT_ARG_STRING, &addr1, 0,
"line 1 of address", "addr1" },
{ "addr2", '2', POPT_ARG_STRING, &addr2, 0,
"line 2 of address", "addr2" },
{ "city", 'c', POPT_ARG_STRING, &city, 0,
"city", "city" },
{ "state", 's', POPT_ARG_STRING, &state, 0,
"state or province", "state" },
{ "postal", 'P', POPT_ARG_STRING, &postal, 0,
"postal or zip code", "postal" },
{ "zip", 'z', POPT_ARG_STRING, &postal, 0,
"postal or zip code", "postal" },
{ "country", 'C', POPT_ARG_STRING, &country, 0,
"two letter ISO country code", "country" },
{ "email", 'e', POPT_ARG_STRING, &email, 0,
"user's email address", "email" },
{ "dayphone", 'd', POPT_ARG_STRING, &dayphone, 0,
"day time phone number", "dayphone" },
{ "fax", 'F', POPT_ARG_STRING, &fax, 0,
"fax number", "fax" },
{ NULL, 0, 0, NULL, 0, NULL, NULL }
};
struct poptOption transactOptionsTable[] = {
{ "keyfile", '\0', POPT_ARG_STRING, &PathnameOfKeyFile, 0,
"transact offer key file (flat_O.kf)", "key-file" },
{ "offerfile", '\0', POPT_ARG_STRING, &PathnameOfOfferFile, 0,
"offer template file (osl.ofr)", "offer-file" },
{ "storeid", '\0', POPT_ARG_INT, &txStoreId, 0,
"store id", "store-id" },
{ "rcfile", '\0', POPT_ARG_STRING, &rcfile, 0,
"default command line options (in popt format)", "rcfile" },
{ "txhost", '\0', POPT_ARG_STRING, &txHost, 0,
"transact host", "transact-host" },
{ "txsslport", '\0', POPT_ARG_INT, &txSslPort, 0,
"transact server ssl port ", "transact ssl port" },
{ "cnhost", '\0', POPT_ARG_STRING, &contentHost, 0,
"content host", "content-host" },
{ "cnpath", '\0', POPT_ARG_STRING, &contentPath, 0,
"content url path", "content-path" },
{ NULL, 0, 0, NULL, 0, NULL, NULL }
};
struct poptOption databaseOptionsTable[] = {
{ "dbpassword", '\0', POPT_ARG_STRING, &dbPassword, 0,
"Database password", "DB password" },
{ "dbusername", '\0', POPT_ARG_STRING, &dbUserName, 0,
"Database user name", "DB UserName" },
{ NULL, 0, 0, NULL, 0, NULL, NULL }
};
struct poptOption optionsTable[] = {
{ NULL, '\0', POPT_ARG_INCLUDE_TABLE, NULL, 0,
"Transact Options (not all will apply)", NULL },
{ NULL, '\0', POPT_ARG_INCLUDE_TABLE, NULL, 0,
"Transact Database Names", NULL },
{ NULL, '\0', POPT_ARG_INCLUDE_TABLE, NULL, 0,
"User Fields", NULL },
POPT_AUTOHELP
{ NULL, 0, 0, NULL, 0, NULL, NULL }
};
optionsTable[0].arg = transactOptionsTable;
optionsTable[1].arg = databaseOptionsTable;
optionsTable[2].arg = userOptionsTable;
#if defined(HAVE_MCHECK_H) && defined(HAVE_MTRACE)
mtrace(); /* Trace malloc only if MALLOC_TRACE=mtrace-output-file. */
#endif
optCon = poptGetContext("createuser", argc, argv, optionsTable, 0);
poptReadConfigFile(optCon, rcfile );
/* although there are no options to be parsed, check for --help */
poptGetNextOpt(optCon);
optCon = poptFreeContext(optCon);
printf( "dbusername %s\tdbpassword %s\n"
"txhost %s\ttxsslport %d\ttxstoreid %d\tpathofkeyfile %s\n"
"username %s\tpassword %s\tfirstname %s\tlastname %s\n"
"addr1 %s\taddr2 %s\tcity %s\tstate %s\tpostal %s\n"
"country %s\temail %s\tdayphone %s\tfax %s\n",
dbUserName, dbPassword,
txHost, txSslPort, txStoreId, PathnameOfKeyFile,
username, password, firstname, lastname,
addr1,addr2, city, state, postal,
country, email, dayphone, fax);
return 0;
}
+179
View File
@@ -0,0 +1,179 @@
#!/bin/sh
run() {
prog=$1; shift
name=$1; shift
answer=$1; shift
echo Running test $name.
result=`HOME=$builddir $builddir/$prog $*`
if [ "$answer" != "$result" ]; then
echo "Test \"$prog $*\" failed with: \"$result\" != \"$answer\" "
exit 2
fi
}
run_diff() {
prog=$1; shift
name=$1; shift
in_file=$1; shift
answer_file=$1; shift
out=$builddir/tmp.out
diff_file=$builddir/tmp.diff
echo Running test $name.
$builddir/$prog $in_file > $out
ret=$?
diff $out $answer_file > $diff_file
diff_ret=$?
if [ "$diff_ret" != "0" ]; then
echo "Test \"$name\" failed output is in $out, diff is:"
cat $diff_file
exit 2
fi
rm $out $diff_file
}
builddir=`pwd`
srcdir=$builddir
cd ${srcdir}
test1=${builddir}/test1
echo "Running tests in `pwd`"
#make -q testcases
run test1 "test1 - 1" "arg1: 1 arg2: (none)" --arg1
run test1 "test1 - 2" "arg1: 0 arg2: foo" --arg2 foo
run test1 "test1 - 3" "arg1: 1 arg2: something" --arg1 --arg2 something
run test1 "test1 - 4" "arg1: 0 arg2: another" --simple another
run test1 "test1 - 5" "arg1: 1 arg2: alias" --two
run test1 "test1 - 6" "arg1: 1 arg2: (none) rest: --arg2" --arg1 -- --arg2
run test1 "test1 - 7" "arg1: 0 arg2: abcd rest: --arg1" --simple abcd -- --arg1
run test1 "test1 - 8" "arg1: 1 arg2: (none) rest: --arg2" --arg1 --takerest --arg2
run test1 "test1 - 9" "arg1: 0 arg2: foo" -2 foo
run test1 "test1 - 10" "arg1: 0 arg2: (none) arg3: 50" -3 50
run test1 "test1 - 11" "arg1: 0 arg2: bar" -T bar
run test1 "test1 - 12" "arg1: 1 arg2: (none)" -O
run test1 "test1 - 13" "arg1: 1 arg2: foo" -OT foo
run test1 "test1 - 14" "arg1: 0 arg2: (none) inc: 1" --inc
run test1 "test1 - 15" "arg1: 0 arg2: foo inc: 1" -I --arg2 foo
POSIX_ME_HARDER=1 ; export POSIX_ME_HARDER
run test1 "test1 - 16" "arg1: 1 arg2: (none) rest: foo --arg2 something" --arg1 foo --arg2 something
unset POSIX_ME_HARDER
POSIXLY_CORRECT=1 ; export POSIXLY_CORRECT
run test1 "test1 - 17" "arg1: 1 arg2: (none) rest: foo --arg2 something" --arg1 foo --arg2 something
unset POSIXLY_CORRECT
run test1 "test1 - 18" "callback: c sampledata bar arg1: 1 arg2: (none)" --arg1 --cb bar
run test1 "test1 - 19" "" --echo-args
run test1 "test1 - 20" "--arg1" --echo-args --arg1
run test1 "test1 - 21" "--arg2 something" -T something -e
run test1 "test1 - 22" "--arg2 something more args" -T something -a more args
run test1 "test1 - 23" "--echo-args -a" --echo-args -e -a
run test1 "test1 - 24" "arg1: 0 arg2: (none) short: 1" -onedash
run test1 "test1 - 25" "arg1: 0 arg2: (none) short: 1" --onedash
run test1 "test1 - 26" "callback: c arg for cb2 foo arg1: 0 arg2: (none)" --cb2 foo
run test1 "test1 - 27" "arg1: 0 arg2: (none) rest: -" -
run test1 "test1 - 28" "arg1: 0 arg2: foo rest: -" - -2 foo
run test1 "test1 - 29" "arg1: 0 arg2: bbbb" --arg2=aaaa -2 bbbb
run test1 "test1 - 30" "arg1: 0 arg2: 'foo bingo' rest: boggle" --grab bingo boggle
run test1 "test1 - 31" "arg1: 0 arg2: 'foo bar' rest: boggle" --grabbar boggle
run test1 "test1 - 32" "arg1: 0 arg2: (none) aInt: 123456789" -i 123456789
run test1 "test1 - 33" "arg1: 0 arg2: (none) aInt: 123456789" --int 123456789
run test1 "test1 - 34" "arg1: 0 arg2: (none) aShort: 12345" -s 12345
run test1 "test1 - 35" "arg1: 0 arg2: (none) aShort: 12345" --short 12345
run test1 "test1 - 36" "arg1: 0 arg2: (none) aLong: 1123456789" -l 1123456789
run test1 "test1 - 37" "arg1: 0 arg2: (none) aLong: 1123456789" --long 1123456789
run test1 "test1 - 38" "arg1: 0 arg2: (none) aLongLong: 1111123456789" -L 1111123456789
run test1 "test1 - 39" "arg1: 0 arg2: (none) aLongLong: 1111123456789" --longlong 1111123456789
run test1 "test1 - 40" "arg1: 0 arg2: (none) aFloat: 10.1" -f 10.1
run test1 "test1 - 41" "arg1: 0 arg2: (none) aFloat: 10.1" --float 10.1
run test1 "test1 - 42" "arg1: 0 arg2: (none) aDouble: 10.1" -d 10.1
run test1 "test1 - 43" "arg1: 0 arg2: (none) aDouble: 10.1" --double 10.1
run test1 "test1 - 44" "arg1: 0 arg2: (none) oStr: (none)" --optional
run test1 "test1 - 45" "arg1: 0 arg2: (none) oStr: yadda" --optional=yadda
run test1 "test1 - 46" "arg1: 0 arg2: (none) oStr: yadda" --optional yadda
run test1 "test1 - 47" "arg1: 0 arg2: (none) oStr: ping rest: pong" --optional=ping pong
run test1 "test1 - 48" "arg1: 0 arg2: (none) oStr: ping rest: pong" --optional ping pong
run test1 "test1 - 49" "arg1: 0 arg2: (none) aArgv: A B rest: C" --argv A --argv B C
run test1 "test1 - 50" "arg1: 0 arg2: foo=bar" -2foo=bar
run test1 "test1 - 51" "arg1: 0 arg2: foo=bar" -2=foo=bar
run test1 "test1 - 52" "arg1: 0 arg2: (none) aFlag: 0xfeed" --bitxor
run test1 "test1 - 53" "arg1: 0 arg2: (none) aFlag: 0xffff" --bitset
run test1 "test1 - 54" "arg1: 0 arg2: (none) aFlag: 0x28c" --bitclr
run test1 "test1 - 55" "arg1: 0 arg2: (none) aFlag: 0x8888" --nobitset
run test1 "test1 - 56" "arg1: 0 arg2: (none) aFlag: 0xface" --nobitclr
run test1 "test1 - 57" "arg1: 0 arg2: (none) aBits: foo,baz" --bits foo,bar,baz,!bar
run test1 "test1 - 58" "\
Usage: lt-test1 [-I?] [-c|--cb2=STRING] [--arg1] [-2|--arg2=ARG]
[-3|--arg3=ANARG] [-onedash] [--optional=STRING] [--val]
[-i|--int=INT] [-s|--short=SHORT] [-l|--long=LONG]
[-L|--longlong=LONGLONG] [-f|--float=FLOAT] [-d|--double=DOUBLE]
[--randint=INT] [--randshort=SHORT] [--randlong=LONG]
[--randlonglong=LONGLONG] [--argv=STRING] [--bitset] [--bitclr]
[--bitxor] [--nstr=STRING] [--lstr=STRING] [-I|--inc]
[-c|--cb=STRING] [--longopt] [-?|--help] [--usage] [--simple=ARG]" --usage
run test1 "test1 - 59" "\
Usage: lt-test1 [OPTION...]
--arg1 First argument with a really long
description. After all, we have to test
argument help wrapping somehow, right?
-2, --arg2=ARG Another argument (default: \"(none)\")
-3, --arg3=ANARG A third argument
-onedash POPT_ARGFLAG_ONEDASH: Option takes a single -
--optional[=STRING] POPT_ARGFLAG_OPTIONAL: Takes an optional
string argument
--val POPT_ARG_VAL: 125992 141421
-i, --int=INT POPT_ARG_INT: 271828 (default: 271828)
-s, --short=SHORT POPT_ARG_SHORT: 4523 (default: 4523)
-l, --long=LONG POPT_ARG_LONG: 738905609 (default: 738905609)
-L, --longlong=LONGLONG POPT_ARG_LONGLONG: 738905609 (default:
738905609)
-f, --float=FLOAT POPT_ARG_FLOAT: 3.14159 (default: 3.14159)
-d, --double=DOUBLE POPT_ARG_DOUBLE: 9.8696 (default: 9.8696)
--randint=INT POPT_ARGFLAG_RANDOM: experimental
--randshort=SHORT POPT_ARGFLAG_RANDOM: experimental
--randlong=LONG POPT_ARGFLAG_RANDOM: experimental
--randlonglong=LONGLONG POPT_ARGFLAG_RANDOM: experimental
--argv STRING POPT_ARG_ARGV: append string to argv array
(can be used multiple times)
--[no]bitset POPT_BIT_SET: |= 0x7777
--[no]bitclr POPT_BIT_CLR: &= ~0xf842
--bitxor POPT_ARGFLAG_XOR: ^= (0x8ace^0xfeed)
--nstr=STRING POPT_ARG_STRING: (null) (default: null)
--lstr=STRING POPT_ARG_STRING: \"123456789...\" (default:
\"This tests default strings and exceeds the
... limit.
123456789+123456789+123456789+123456789+123456789+ 123456789+123456789+123456789+123456789+123456789+ 1234567...\")
arg for cb2
-c, --cb2=STRING Test argument callbacks
-I, --inc An included argument
Callback arguments
-c, --cb=STRING Test argument callbacks
--longopt Unused option for help testing
Options implemented via popt alias/exec:
--simple=ARG simple description
Help options:
-?, --help Show this help message
--usage Display brief usage message" --help
#run_diff test3 "test3 - 51" test3-data/01.input test3-data/01.answer
#run_diff test3 "test3 - 52" test3-data/02.input test3-data/02.answer
#run_diff test3 "test3 - 53" test3-data/03.input test3-data/03.answer
echo ""
echo "Passed."