Compare commits
3
Commits
brep-debug
...
popt
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
22b58f489a | ||
|
|
768753fb7d | ||
|
|
3a1063e437 |
@@ -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
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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
|
||||
@@ -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")
|
||||
|
||||
@@ -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 "
|
||||
|
||||
@@ -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
|
||||
)
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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
@@ -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
|
||||
@@ -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.
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
@@ -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
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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) */
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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"
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
Executable
+179
@@ -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."
|
||||
Reference in New Issue
Block a user