1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-23 17:34:34 +03:00

r15654: Update our internal copy of popt to that distributed with the RPM 4.2

source code.
(This used to be commit 9559886a92)
This commit is contained in:
James Peach 2006-05-17 00:04:09 +00:00 committed by Gerald (Jerry) Carter
parent f81e4521bf
commit dc64af1d2e
13 changed files with 2248 additions and 683 deletions

View File

@ -18,7 +18,7 @@ LIBS=@LIBS@
CC=@CC@ CC=@CC@
SHLD=@SHLD@ SHLD=@SHLD@
CFLAGS=@CFLAGS@ CFLAGS=@CFLAGS@
CPPFLAGS=@CPPFLAGS@ CPPFLAGS=-DHAVE_CONFIG_H @CPPFLAGS@
EXEEXT=@EXEEXT@ EXEEXT=@EXEEXT@
LDFLAGS=@LDFLAGS@ LDFLAGS=@LDFLAGS@
AR=@AR@ AR=@AR@

View File

@ -819,7 +819,8 @@ AC_HEADER_DIRENT
AC_HEADER_TIME AC_HEADER_TIME
AC_HEADER_SYS_WAIT AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS(aio.h arpa/inet.h sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h rpc/nettype.h) AC_CHECK_HEADERS(aio.h arpa/inet.h sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h rpc/nettype.h)
AC_CHECK_HEADERS(unistd.h utime.h grp.h sys/id.h limits.h memory.h alloca.h) AC_CHECK_HEADERS(unistd.h utime.h grp.h sys/id.h memory.h alloca.h)
AC_CHECK_HEADERS(limits.h float.h)
AC_CHECK_HEADERS(rpc/rpc.h rpcsvc/nis.h rpcsvc/ypclnt.h) AC_CHECK_HEADERS(rpc/rpc.h rpcsvc/nis.h rpcsvc/ypclnt.h)
AC_CHECK_HEADERS(sys/param.h ctype.h sys/wait.h sys/resource.h sys/ioctl.h sys/ipc.h sys/prctl.h) AC_CHECK_HEADERS(sys/param.h ctype.h sys/wait.h sys/resource.h sys/ioctl.h sys/ipc.h sys/prctl.h)
AC_CHECK_HEADERS(sys/mman.h sys/filio.h sys/priv.h sys/shm.h string.h strings.h stdlib.h sys/socket.h) AC_CHECK_HEADERS(sys/mman.h sys/filio.h sys/priv.h sys/shm.h string.h strings.h stdlib.h sys/socket.h)

View File

@ -1,4 +1,7 @@
1.3 -> 1.5 -> 1.6
- add ability to perform callbacks for every, not just first, match.
1.3 -> 1.5
- heavy dose of const's - heavy dose of const's
- poptParseArgvString() now NULL terminates the list - poptParseArgvString() now NULL terminates the list

View File

@ -5,7 +5,7 @@ to getopt(3), it contains a number of enhancements, including:
2) popt can parse arbitrary argv[] style arrays while 2) popt can parse arbitrary argv[] style arrays while
getopt(2) makes this quite difficult getopt(2) makes this quite difficult
3) popt allows users to alias command line arguments 3) popt allows users to alias command line arguments
4) popt provides convience functions for parsting strings 4) popt provides convience functions for parsing strings
into argv[] style arrays into argv[] style arrays
popt is used by rpm, the Red Hat install program, and many other Red Hat popt is used by rpm, the Red Hat install program, and many other Red Hat

View File

@ -1,6 +1,10 @@
/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING /** \ingroup popt
* \file popt/findme.c
*/
/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from file accompanying popt source distributions, available from
ftp://ftp.redhat.com/pub/code/popt */ ftp://ftp.rpm.org/pub/rpm/dist. */
#include "system.h" #include "system.h"
#include "findme.h" #include "findme.h"
@ -9,38 +13,38 @@ const char * findProgramPath(const char * argv0) {
char * path = getenv("PATH"); char * path = getenv("PATH");
char * pathbuf; char * pathbuf;
char * start, * chptr; char * start, * chptr;
char * buf, *local = NULL; char * buf;
/* If there is a / in the argv[0], it has to be an absolute if (argv0 == NULL) return NULL; /* XXX can't happen */
path */ /* If there is a / in the argv[0], it has to be an absolute path */
if (strchr(argv0, '/')) if (strchr(argv0, '/'))
return xstrdup(argv0); return xstrdup(argv0);
if (!path) return NULL; if (path == NULL) return NULL;
local = start = pathbuf = malloc(strlen(path) + 1); start = pathbuf = alloca(strlen(path) + 1);
buf = malloc(strlen(path) + strlen(argv0) + 2); buf = malloc(strlen(path) + strlen(argv0) + sizeof("/"));
if (buf == NULL) return NULL; /* XXX can't happen */
strcpy(pathbuf, path); strcpy(pathbuf, path);
chptr = NULL; chptr = NULL;
/*@-branchstate@*/
do { do {
if ((chptr = strchr(start, ':'))) if ((chptr = strchr(start, ':')))
*chptr = '\0'; *chptr = '\0';
sprintf(buf, "%s/%s", start, argv0); sprintf(buf, "%s/%s", start, argv0);
if (!access(buf, X_OK)) { if (!access(buf, X_OK))
if (local) free(local); return buf;
return buf;
}
if (chptr) if (chptr)
start = chptr + 1; start = chptr + 1;
else else
start = NULL; start = NULL;
} while (start && *start); } while (start && *start);
/*@=branchstate@*/
free(buf); free(buf);
if (local) free(local);
return NULL; return NULL;
} }

View File

@ -1,10 +1,20 @@
/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING /** \ingroup popt
* \file popt/findme.h
*/
/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from file accompanying popt source distributions, available from
ftp://ftp.redhat.com/pub/code/popt */ ftp://ftp.rpm.org/pub/rpm/dist. */
#ifndef H_FINDME #ifndef H_FINDME
#define H_FINDME #define H_FINDME
const char * findProgramPath(const char * argv0); /**
* Return absolute path to executable by searching PATH.
* @param argv0 name of executable
* @return (malloc'd) absolute path to executable (or NULL)
*/
/*@null@*/ const char * findProgramPath(/*@null@*/ const char * argv0)
/*@*/;
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -1,128 +1,543 @@
/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING /** \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 file accompanying popt source distributions, available from
ftp://ftp.redhat.com/pub/code/popt */ ftp://ftp.rpm.org/pub/rpm/dist. */
#ifndef H_POPT #ifndef H_POPT
#define H_POPT #define H_POPT
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h> /* for FILE * */ #include <stdio.h> /* for FILE * */
#define POPT_OPTION_DEPTH 10 #define POPT_OPTION_DEPTH 10
#define POPT_ARG_NONE 0 /** \ingroup popt
#define POPT_ARG_STRING 1 * \name Arg type identifiers
#define POPT_ARG_INT 2 */
#define POPT_ARG_LONG 3 /*@{*/
#define POPT_ARG_INCLUDE_TABLE 4 /* arg points to table */ #define POPT_ARG_NONE 0 /*!< no arg */
#define POPT_ARG_CALLBACK 5 /* table-wide callback... must be #define POPT_ARG_STRING 1 /*!< arg will be saved as string */
#define POPT_ARG_INT 2 /*!< arg will be converted to int */
#define POPT_ARG_LONG 3 /*!< arg will be converted to long */
#define POPT_ARG_INCLUDE_TABLE 4 /*!< arg points to table */
#define POPT_ARG_CALLBACK 5 /*!< table-wide callback... must be
set first in table; arg points set first in table; arg points
to callback, descrip points to to callback, descrip points to
callback data to pass */ callback data to pass */
#define POPT_ARG_INTL_DOMAIN 6 /* set the translation domain #define POPT_ARG_INTL_DOMAIN 6 /*!< set the translation domain
for this table and any for this table and any
included tables; arg points included tables; arg points
to the domain string */ to the domain string */
#define POPT_ARG_VAL 7 /* arg should take value val */ #define POPT_ARG_VAL 7 /*!< arg should take value val */
#define POPT_ARG_FLOAT 8 /*!< arg will be converted to float */
#define POPT_ARG_DOUBLE 9 /*!< arg will be converted to double */
#define POPT_ARG_MASK 0x0000FFFF #define POPT_ARG_MASK 0x0000FFFF
#define POPT_ARGFLAG_ONEDASH 0x80000000 /* allow -longoption */ /*@}*/
#define POPT_ARGFLAG_DOC_HIDDEN 0x40000000 /* don't show in help/usage */
#define POPT_ARGFLAG_STRIP 0x20000000 /* strip this arg from argv (only applies to long args) */ /** \ingroup popt
#define POPT_CBFLAG_PRE 0x80000000 /* call the callback before parse */ * \name Arg modifiers
#define POPT_CBFLAG_POST 0x40000000 /* call the callback after parse */ */
#define POPT_CBFLAG_INC_DATA 0x20000000 /* use data from the include line, /*@{*/
#define POPT_ARGFLAG_ONEDASH 0x80000000 /*!< allow -longoption */
#define POPT_ARGFLAG_DOC_HIDDEN 0x40000000 /*!< don't show in help/usage */
#define POPT_ARGFLAG_STRIP 0x20000000 /*!< strip this arg from argv(only applies to long args) */
#define POPT_ARGFLAG_OPTIONAL 0x10000000 /*!< arg may be missing */
#define POPT_ARGFLAG_OR 0x08000000 /*!< arg will be or'ed */
#define POPT_ARGFLAG_NOR 0x09000000 /*!< arg will be nor'ed */
#define POPT_ARGFLAG_AND 0x04000000 /*!< arg will be and'ed */
#define POPT_ARGFLAG_NAND 0x05000000 /*!< arg will be nand'ed */
#define POPT_ARGFLAG_XOR 0x02000000 /*!< arg will be xor'ed */
#define POPT_ARGFLAG_NOT 0x01000000 /*!< 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 0x00800000 /*!< show default value in --help */
/*@}*/
/** \ingroup popt
* \name Callback modifiers
*/
/*@{*/
#define POPT_CBFLAG_PRE 0x80000000 /*!< call the callback before parse */
#define POPT_CBFLAG_POST 0x40000000 /*!< call the callback after parse */
#define POPT_CBFLAG_INC_DATA 0x20000000 /*!< use data from the include line,
not the subtable */ not the subtable */
#define POPT_CBFLAG_SKIPOPTION 0x10000000 /*!< don't callback with option */
#define POPT_CBFLAG_CONTINUE 0x08000000 /*!< continue callbacks with option */
/*@}*/
#define POPT_ERROR_NOARG -10 /** \ingroup popt
#define POPT_ERROR_BADOPT -11 * \name Error return values
#define POPT_ERROR_OPTSTOODEEP -13 */
#define POPT_ERROR_BADQUOTE -15 /* only from poptParseArgString() */ /*@{*/
#define POPT_ERROR_ERRNO -16 /* only from poptParseArgString() */ #define POPT_ERROR_NOARG -10 /*!< missing argument */
#define POPT_ERROR_BADNUMBER -17 #define POPT_ERROR_BADOPT -11 /*!< unknown option */
#define POPT_ERROR_OVERFLOW -18 #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 */
/*@}*/
/* poptBadOption() flags */ /** \ingroup popt
#define POPT_BADOPTION_NOALIAS (1 << 0) /* don't go into an alias */ * \name poptBadOption() flags
*/
/*@{*/
#define POPT_BADOPTION_NOALIAS (1 << 0) /*!< don't go into an alias */
/*@}*/
/* poptGetContext() flags */ /** \ingroup popt
#define POPT_CONTEXT_NO_EXEC (1 << 0) /* ignore exec expansions */ * \name poptGetContext() flags
#define POPT_CONTEXT_KEEP_FIRST (1 << 1) /* pay attention to argv[0] */ */
#define POPT_CONTEXT_POSIXMEHARDER (1 << 2) /* options can't follow args */ /*@{*/
#define POPT_CONTEXT_NO_EXEC (1 << 0) /*!< ignore exec expansions */
#define POPT_CONTEXT_KEEP_FIRST (1 << 1) /*!< pay attention to argv[0] */
#define POPT_CONTEXT_POSIXMEHARDER (1 << 2) /*!< options can't follow args */
#define POPT_CONTEXT_ARG_OPTS (1 << 4) /*!< return args as options with value 0 */
/*@}*/
/** \ingroup popt
*/
struct poptOption { struct poptOption {
/*@observer@*/ /*@null@*/ const char * longName; /* may be NULL */ /*@observer@*/ /*@null@*/
char shortName; /* may be '\0' */ const char * longName; /*!< may be NULL */
char shortName; /*!< may be '\0' */
int argInfo; int argInfo;
/*@shared@*/ /*@null@*/ void * arg; /* depends on argInfo */ /*@shared@*/ /*@null@*/
int val; /* 0 means don't return, just update flag */ void * arg; /*!< depends on argInfo */
/*@shared@*/ /*@null@*/ const char * descrip; /* description for autohelp -- may be NULL */ int val; /*!< 0 means don't return, just update flag */
/*@shared@*/ /*@null@*/ const char * argDescrip; /* argument description for autohelp */ /*@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 { struct poptAlias {
/*@owned@*/ /*@null@*/ const char * longName; /* may be NULL */ /*@owned@*/ /*@null@*/
char shortName; /* may be '\0' */ const char * longName; /*!< may be NULL */
char shortName; /*!< may be '\0' */
int argc; int argc;
/*@owned@*/ const char ** argv; /* must be free()able */ /*@owned@*/
const char ** argv; /*!< must be free()able */
}; };
extern struct poptOption poptHelpOptions[]; /** \ingroup popt
#define POPT_AUTOHELP { NULL, '\0', POPT_ARG_INCLUDE_TABLE, poptHelpOptions, \ * A popt alias or exec argument for poptAddItem().
0, "Help options", NULL }, */
/*@-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@*/
typedef struct poptContext_s * poptContext; /** \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@*/
#define POPT_AUTOHELP { NULL, '\0', POPT_ARG_INCLUDE_TABLE, poptHelpOptions, \
0, "Help options:", NULL },
#define POPT_TABLEEND { NULL, '\0', 0, 0, 0, NULL, NULL }
/*@}*/
/** \ingroup popt
*/
/*@-exporttype@*/
typedef /*@abstract@*/ struct poptContext_s * poptContext;
/*@=exporttype@*/
/** \ingroup popt
*/
#ifndef __cplusplus #ifndef __cplusplus
/*@-exporttype -typeuse@*/
typedef struct poptOption * poptOption; typedef struct poptOption * poptOption;
/*@=exporttype =typeuse@*/
#endif #endif
enum poptCallbackReason { POPT_CALLBACK_REASON_PRE, /*@-exportconst@*/
POPT_CALLBACK_REASON_POST, enum poptCallbackReason {
POPT_CALLBACK_REASON_OPTION }; POPT_CALLBACK_REASON_PRE = 0,
typedef void (*poptCallbackType)(poptContext con, POPT_CALLBACK_REASON_POST = 1,
enum poptCallbackReason reason, POPT_CALLBACK_REASON_OPTION = 2
const struct poptOption * opt, };
const char * arg, const void * data); /*@=exportconst@*/
/*@only@*/ poptContext poptGetContext(/*@keep@*/ const char * name, #ifdef __cplusplus
int argc, /*@keep@*/ const char ** argv, extern "C" {
/*@keep@*/ const struct poptOption * options, int flags); #endif
void poptResetContext(poptContext con); /*@-type@*/
/* returns 'val' element, -1 on last item, POPT_ERROR_* on error */ /** \ingroup popt
int poptGetNextOpt(poptContext con); * Table callback prototype.
/* returns NULL if no argument is available */ * @param con context
/*@observer@*/ /*@null@*/ const char * poptGetOptArg(poptContext con); * @param reason reason for callback
/* returns NULL if no more options are available */ * @param opt option that triggered callback
/*@observer@*/ /*@null@*/ const char * poptGetArg(poptContext con); * @param arg @todo Document.
/*@observer@*/ /*@null@*/ const char * poptPeekArg(poptContext con); * @param data @todo Document.
/*@observer@*/ /*@null@*/ const char ** poptGetArgs(poptContext con); */
/* returns the option which caused the most recent error */ typedef void (*poptCallbackType) (poptContext con,
/*@observer@*/ const char * poptBadOption(poptContext con, int flags); enum poptCallbackReason reason,
void poptFreeContext( /*@only@*/ poptContext con); /*@null@*/ const struct poptOption * opt,
int poptStuffArgs(poptContext con, /*@keep@*/ const char ** argv); /*@null@*/ const char * arg,
int poptAddAlias(poptContext con, struct poptAlias alias, int flags); /*@null@*/ const void * data)
int poptReadConfigFile(poptContext con, const char * fn); /*@*/;
/* like above, but reads /etc/popt and $HOME/.popt along with environment
vars */ /** \ingroup popt
int poptReadDefaultConfig(poptContext con, int useEnv); * Initialize popt context.
/* argv should be freed -- this allows ', ", and \ quoting, but ' is treated * @param name context name (usually argv[0] program name)
the same as " and both may include \ quotes */ * @param argc no. of arguments
int poptDupArgv(int argc, const char **argv, * @param argv argument array
/*@out@*/ int * argcPtr, /*@out@*/ const char *** argvPtr); * @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,
int flags)
/*@*/;
/** \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@*/ const 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@*/ 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@*/ 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, int flags)
/*@*/;
/** \ingroup popt
* Destroy context.
* @param con context
* @return NULL always
*/
/*@null@*/ poptContext poptFreeContext( /*@only@*/ /*@null@*/ poptContext con)
/*@modifies con @*/;
/** \ingroup popt
* Add arguments to context.
* @param con context
* @param argv argument array, NULL terminated
* @return 0 on success, POPT_ERROR_OPTSTOODEEP on failure
*/
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
* 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 fileSystem, internalState @*/
/*@modifies con->execs, con->numExecs,
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
*/
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, int poptParseArgvString(const char * s,
/*@out@*/ int * argcPtr, /*@out@*/ const char *** argvPtr); /*@out@*/ int * argcPtr, /*@out@*/ const char *** argvPtr)
/*@observer@*/ const char *poptStrerror(const int error); /*@modifies *argcPtr, *argvPtr @*/;
void poptSetExecPath(poptContext con, const char * path, int allowAbsolute);
void poptPrintHelp(poptContext con, FILE * f, int flags);
void poptPrintUsage(poptContext con, FILE * f, int flags);
void poptSetOtherOptionHelp(poptContext con, const char * text);
/*@observer@*/ const char * poptGetInvocationName(poptContext con);
/* shuffles argv pointers to remove stripped args, returns new argc */
int poptStrippedArgv(poptContext con, int argc, char **argv);
/** \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 *const 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?
*/
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@*/
/**
* 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, int argInfo, long aLong)
/*@modifies *arg @*/
/*@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, int argInfo, long aLong)
/*@modifies *arg @*/
/*@requires maxSet(arg) >= 0 /\ maxRead(arg) == 0 @*/;
/*@=incondefs@*/
/*@=type@*/
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -1,101 +1,147 @@
/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING /** \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 file accompanying popt source distributions, available from
ftp://ftp.redhat.com/pub/code/popt */ ftp://ftp.rpm.org/pub/rpm/dist. */
#include "system.h" #include "system.h"
#include "poptint.h" #include "poptint.h"
static void configLine(poptContext con, char * line) { /*@-compmempass@*/ /* FIX: item->option.longName kept, not dependent. */
static void configLine(poptContext con, char * line)
/*@modifies con @*/
{
/*@-type@*/
int nameLength = strlen(con->appName); int nameLength = strlen(con->appName);
char * opt; /*@=type@*/
struct poptAlias alias; const char * entryType;
char * entryType; const char * opt;
char * longName = NULL; poptItem item = alloca(sizeof(*item));
char shortName = '\0'; int i, j;
/*@-boundswrite@*/
memset(item, 0, sizeof(*item));
/*@-type@*/
if (strncmp(line, con->appName, nameLength)) return; if (strncmp(line, con->appName, nameLength)) return;
/*@=type@*/
line += nameLength; line += nameLength;
if (!*line || !isspace(*line)) return; if (*line == '\0' || !isspace(*line)) return;
while (*line && isspace(*line)) line++;
while (*line != '\0' && isspace(*line)) line++;
entryType = line; entryType = line;
while (*line == '\0' || !isspace(*line)) line++;
while (!*line || !isspace(*line)) line++;
*line++ = '\0'; *line++ = '\0';
while (*line && isspace(*line)) line++;
if (!*line) return; while (*line != '\0' && isspace(*line)) line++;
if (*line == '\0') return;
opt = line; opt = line;
while (*line == '\0' || !isspace(*line)) line++;
while (!*line || !isspace(*line)) line++;
*line++ = '\0'; *line++ = '\0';
while (*line && isspace(*line)) line++;
if (!*line) return;
while (*line != '\0' && isspace(*line)) line++;
if (*line == '\0') return;
/*@-temptrans@*/ /* FIX: line alias is saved */
if (opt[0] == '-' && opt[1] == '-') if (opt[0] == '-' && opt[1] == '-')
longName = opt + 2; item->option.longName = opt + 2;
else if (opt[0] == '-' && !opt[2]) else if (opt[0] == '-' && opt[2] == '\0')
shortName = opt[1]; item->option.shortName = opt[1];
/*@=temptrans@*/
if (!strcmp(entryType, "alias")) { if (poptParseArgvString(line, &item->argc, &item->argv)) return;
if (poptParseArgvString(line, &alias.argc, &alias.argv)) return;
alias.longName = longName, alias.shortName = shortName;
poptAddAlias(con, alias, 0);
} else if (!strcmp(entryType, "exec")) {
con->execs = realloc(con->execs,
sizeof(*con->execs) * (con->numExecs + 1));
if (longName)
con->execs[con->numExecs].longName = xstrdup(longName);
else
con->execs[con->numExecs].longName = NULL;
con->execs[con->numExecs].shortName = shortName; /*@-modobserver@*/
con->execs[con->numExecs].script = xstrdup(line); item->option.argInfo = POPT_ARGFLAG_DOC_HIDDEN;
for (i = 0, j = 0; i < item->argc; i++, j++) {
con->numExecs++; 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@*/
/*@=boundswrite@*/
int poptReadConfigFile(poptContext con, const char * fn) { /*@-nullstate@*/ /* FIX: item->argv[] may be NULL */
char * file=NULL, * chptr, * end; if (!strcmp(entryType, "alias"))
char * buf=NULL, * dst; (void) poptAddItem(con, item, 0);
else if (!strcmp(entryType, "exec"))
(void) poptAddItem(con, item, 1);
/*@=nullstate@*/
}
/*@=compmempass@*/
int poptReadConfigFile(poptContext con, const char * fn)
{
const char * file, * chptr, * end;
char * buf;
/*@dependent@*/ char * dst;
int fd, rc; int fd, rc;
int fileLength; off_t fileLength;
fd = open(fn, O_RDONLY); fd = open(fn, O_RDONLY);
if (fd < 0) { if (fd < 0)
if (errno == ENOENT) return (errno == ENOENT ? 0 : POPT_ERROR_ERRNO);
return 0;
else
return POPT_ERROR_ERRNO;
}
fileLength = lseek(fd, 0, SEEK_END); fileLength = lseek(fd, 0, SEEK_END);
(void) lseek(fd, 0, 0); if (fileLength == -1 || lseek(fd, 0, 0) == -1) {
file = malloc(fileLength + 1);
if (read(fd, file, fileLength) != fileLength) {
rc = errno; rc = errno;
close(fd); (void) close(fd);
/*@-mods@*/
errno = rc; errno = rc;
if (file) free(file); /*@=mods@*/
return POPT_ERROR_ERRNO; return POPT_ERROR_ERRNO;
} }
close(fd);
dst = buf = malloc(fileLength + 1); file = alloca(fileLength + 1);
if (read(fd, (char *)file, fileLength) != fileLength) {
rc = errno;
(void) close(fd);
/*@-mods@*/
errno = rc;
/*@=mods@*/
return POPT_ERROR_ERRNO;
}
if (close(fd) == -1)
return POPT_ERROR_ERRNO;
/*@-boundswrite@*/
dst = buf = alloca(fileLength + 1);
chptr = file; chptr = file;
end = (file + fileLength); end = (file + fileLength);
/*@-infloops@*/ /* LCL: can't detect chptr++ */
while (chptr < end) { while (chptr < end) {
switch (*chptr) { switch (*chptr) {
case '\n': case '\n':
*dst = '\0'; *dst = '\0';
dst = buf; dst = buf;
while (*dst && isspace(*dst)) dst++; while (*dst && isspace(*dst)) dst++;
if (*dst && *dst != '#') { if (*dst && *dst != '#')
configLine(con, dst); configLine(con, dst);
}
chptr++; chptr++;
break; /*@switchbreak@*/ break;
case '\\': case '\\':
*dst++ = *chptr++; *dst++ = *chptr++;
if (chptr < end) { if (chptr < end) {
@ -105,38 +151,40 @@ int poptReadConfigFile(poptContext con, const char * fn) {
else else
*dst++ = *chptr++; *dst++ = *chptr++;
} }
break; /*@switchbreak@*/ break;
default: default:
*dst++ = *chptr++; *dst++ = *chptr++;
break; /*@switchbreak@*/ break;
} }
} }
/*@=infloops@*/
free(file); /*@=boundswrite@*/
free(buf);
return 0; return 0;
} }
int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv) { int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv)
{
char * fn, * home; char * fn, * home;
int rc; int rc;
/*@-type@*/
if (!con->appName) return 0; if (!con->appName) return 0;
/*@=type@*/
rc = poptReadConfigFile(con, "/etc/popt"); rc = poptReadConfigFile(con, "/etc/popt");
if (rc) return rc; if (rc) return rc;
#if defined(HAVE_GETUID) && defined(HAVE_GETEUID)
if (getuid() != geteuid()) return 0; if (getuid() != geteuid()) return 0;
#endif
if ((home = getenv("HOME"))) { if ((home = getenv("HOME"))) {
fn = malloc(strlen(home) + 20); fn = alloca(strlen(home) + 20);
strcpy(fn, home); strcpy(fn, home);
strcat(fn, "/.popt"); strcat(fn, "/.popt");
rc = poptReadConfigFile(con, fn); rc = poptReadConfigFile(con, fn);
free(fn);
if (rc) return rc; if (rc) return rc;
} }
return 0; return 0;
} }

View File

@ -1,48 +1,96 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING /*@-type@*/
/** \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 file accompanying popt source distributions, available from
ftp://ftp.redhat.com/pub/code/popt */ ftp://ftp.rpm.org/pub/rpm/dist. */
#include "system.h" #include "system.h"
#include "poptint.h" #include "poptint.h"
/**
* Display arguments.
* @param con context
* @param foo (unused)
* @param key option(s)
* @param arg (unused)
* @param data (unused)
*/
static void displayArgs(poptContext con, static void displayArgs(poptContext con,
/*@unused@*/ enum poptCallbackReason foo, /*@unused@*/ enum poptCallbackReason foo,
struct poptOption * key, struct poptOption * key,
/*@unused@*/ const char * arg, /*@unused@*/ void * data) { /*@unused@*/ const char * arg, /*@unused@*/ void * data)
if (key->shortName== '?') /*@globals fileSystem@*/
/*@modifies fileSystem@*/
{
if (key->shortName == '?')
poptPrintHelp(con, stdout, 0); poptPrintHelp(con, stdout, 0);
else else
poptPrintUsage(con, stdout, 0); poptPrintUsage(con, stdout, 0);
exit(0); 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[] = { struct poptOption poptHelpOptions[] = {
{ NULL, '\0', POPT_ARG_CALLBACK, (void *)&displayArgs, '\0', NULL, NULL }, { NULL, '\0', POPT_ARG_CALLBACK, (void *)&displayArgs, '\0', NULL, NULL },
{ "help", '?', 0, NULL, '?', N_("Show this help message"), NULL }, { "help", '?', 0, NULL, '?', N_("Show this help message"), NULL },
{ "usage", '\0', 0, NULL, 'u', N_("Display brief usage message"), NULL }, { "usage", '\0', 0, NULL, 'u', N_("Display brief usage message"), NULL },
{ NULL, '\0', 0, NULL, 0, NULL, NULL } #ifdef NOTYET
{ "defaults", '\0', POPT_ARG_NONE, &show_option_defaults, 0,
N_("Display option defaults in message"), NULL },
#endif
POPT_TABLEEND
} ; } ;
/*@=castfcnptr@*/
/**
/*@observer@*/ /*@null@*/ static const char * * @param table option(s)
getTableTranslationDomain(const struct poptOption *table) */
/*@observer@*/ /*@null@*/ static const char *const
getTableTranslationDomain(/*@null@*/ const struct poptOption *table)
/*@*/
{ {
const struct poptOption *opt; const struct poptOption *opt;
for(opt = table; if (table != NULL)
opt->longName || opt->shortName || opt->arg; for (opt = table; opt->longName || opt->shortName || opt->arg; opt++) {
opt++) { if (opt->argInfo == POPT_ARG_INTL_DOMAIN)
if(opt->argInfo == POPT_ARG_INTL_DOMAIN) return opt->arg;
return opt->arg; }
} return NULL;
return NULL;
} }
/*@observer@*/ /*@null@*/ static const char * /**
getArgDescrip(const struct poptOption * opt, const char *translation_domain) * @param opt option(s)
* @param translation_domain translation domain
*/
/*@observer@*/ /*@null@*/ static const char *const
getArgDescrip(const struct poptOption * opt,
/*@-paramuse@*/ /* FIX: i18n macros disabled with lclint */
/*@null@*/ const char * translation_domain)
/*@=paramuse@*/
/*@*/
{ {
if (!(opt->argInfo & POPT_ARG_MASK)) return NULL; if (!(opt->argInfo & POPT_ARG_MASK)) return NULL;
@ -50,45 +98,242 @@ getArgDescrip(const struct poptOption * opt, const char *translation_domain)
if (opt->argDescrip) return POPT_(opt->argDescrip); if (opt->argDescrip) return POPT_(opt->argDescrip);
if (opt->argDescrip) return D_(translation_domain, opt->argDescrip); if (opt->argDescrip) return D_(translation_domain, opt->argDescrip);
return POPT_("ARG");
switch (opt->argInfo & POPT_ARG_MASK) {
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_LONG: return POPT_("LONG");
case POPT_ARG_STRING: return POPT_("STRING");
case POPT_ARG_FLOAT: return POPT_("FLOAT");
case POPT_ARG_DOUBLE: return POPT_("DOUBLE");
default: return POPT_("ARG");
}
} }
static void singleOptionHelp(FILE * f, int maxLeftCol, /**
const struct poptOption * opt, * Display default value for an option.
const char *translation_domain) { * @param lineLength
* @param opt option(s)
* @param translation_domain translation domain
* @return
*/
static /*@only@*/ /*@null@*/ char *
singleOptionDefaultValue(int 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 */
/*@-boundswrite@*/
*le = '\0';
*le++ = '(';
strcpy(le, defstr); le += strlen(le);
*le++ = ':';
*le++ = ' ';
if (opt->arg) /* XXX programmer error */
switch (opt->argInfo & POPT_ARG_MASK) {
case POPT_ARG_VAL:
case POPT_ARG_INT:
{ long aLong = *((int *)opt->arg);
le += sprintf(le, "%ld", aLong);
} break;
case POPT_ARG_LONG:
{ long aLong = *((long *)opt->arg);
le += sprintf(le, "%ld", aLong);
} break;
case POPT_ARG_FLOAT:
{ double aDouble = *((float *)opt->arg);
le += sprintf(le, "%g", aDouble);
} break;
case POPT_ARG_DOUBLE:
{ double aDouble = *((double *)opt->arg);
le += sprintf(le, "%g", aDouble);
} break;
case POPT_ARG_STRING:
{ const char * s = *(const char **)opt->arg;
if (s == NULL) {
strcpy(le, "null"); le += strlen(le);
} else {
size_t slen = 4*lineLength - (le - l) - sizeof("\"...\")");
*le++ = '"';
strncpy(le, s, slen); le[slen] = '\0'; le += strlen(le);
if (slen < strlen(s)) {
strcpy(le, "..."); le += strlen(le);
}
*le++ = '"';
}
} break;
case POPT_ARG_NONE:
default:
l = _free(l);
return NULL;
/*@notreached@*/ break;
}
*le++ = ')';
*le = '\0';
/*@=boundswrite@*/
return l;
}
/**
* Display help text for an option.
* @param fp output file handle
* @param maxLeftCol
* @param opt option(s)
* @param translation_domain translation domain
*/
static void singleOptionHelp(FILE * fp, int maxLeftCol,
const struct poptOption * opt,
/*@null@*/ const char * translation_domain)
/*@globals fileSystem @*/
/*@modifies *fp, fileSystem @*/
{
int indentLength = maxLeftCol + 5; int indentLength = maxLeftCol + 5;
int lineLength = 79 - indentLength; int lineLength = 79 - indentLength;
const char * help = D_(translation_domain, opt->descrip); const char * help = D_(translation_domain, opt->descrip);
int helpLength;
const char * ch;
char format[10];
char * left;
const char * argDescrip = getArgDescrip(opt, translation_domain); const char * argDescrip = getArgDescrip(opt, translation_domain);
int helpLength;
char * defs = NULL;
char * left;
int nb = maxLeftCol + 1;
left = malloc(maxLeftCol + 1); /* Make sure there's more than enough room in target buffer. */
*left = '\0'; if (opt->longName) nb += strlen(opt->longName);
if (argDescrip) nb += strlen(argDescrip);
/*@-boundswrite@*/
left = malloc(nb);
if (left == NULL) return; /* XXX can't happen */
left[0] = '\0';
left[maxLeftCol] = '\0';
if (opt->longName && opt->shortName) if (opt->longName && opt->shortName)
sprintf(left, "-%c, --%s", opt->shortName, opt->longName); sprintf(left, "-%c, %s%s", opt->shortName,
else if (opt->shortName) ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"),
opt->longName);
else if (opt->shortName != '\0')
sprintf(left, "-%c", opt->shortName); sprintf(left, "-%c", opt->shortName);
else if (opt->longName) else if (opt->longName)
sprintf(left, "--%s", opt->longName); sprintf(left, "%s%s",
if (!*left) return ; ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"),
opt->longName);
if (!*left) goto out;
if (argDescrip) { if (argDescrip) {
strcat(left, "="); char * le = left + strlen(left);
strcat(left, argDescrip);
if (opt->argInfo & POPT_ARGFLAG_OPTIONAL)
*le++ = '[';
/* Choose type of output */
/*@-branchstate@*/
if (opt->argInfo & POPT_ARGFLAG_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;
*te = '\0';
if (help) {
strcpy(te, help); te += strlen(te);
}
*te++ = ' ';
strcpy(te, defs);
defs = _free(defs);
}
defs = t;
}
}
/*@=branchstate@*/
if (opt->argDescrip == NULL) {
switch (opt->argInfo & POPT_ARG_MASK) {
case POPT_ARG_NONE:
break;
case POPT_ARG_VAL:
#ifdef NOTNOW /* XXX pug ugly nerdy output */
{ long aLong = opt->val;
int ops = (opt->argInfo & POPT_ARGFLAG_LOGICALOPS);
int negate = (opt->argInfo & POPT_ARGFLAG_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++ = '=';
if (negate) *le++ = '~';
/*@-formatconst@*/
le += sprintf(le, (ops ? "0x%lx" : "%ld"), aLong);
/*@=formatconst@*/
*le++ = ']';
}
#endif
break;
case POPT_ARG_INT:
case POPT_ARG_LONG:
case POPT_ARG_FLOAT:
case POPT_ARG_DOUBLE:
case POPT_ARG_STRING:
*le++ = '=';
strcpy(le, argDescrip); le += strlen(le);
break;
default:
break;
}
} else {
*le++ = '=';
strcpy(le, argDescrip); le += strlen(le);
}
if (opt->argInfo & POPT_ARGFLAG_OPTIONAL)
*le++ = ']';
*le = '\0';
} }
/*@=boundswrite@*/
if (help) if (help)
fprintf(f," %-*s ", maxLeftCol, left); fprintf(fp," %-*s ", maxLeftCol, left);
else { else {
fprintf(f," %s\n", left); fprintf(fp," %s\n", left);
goto out; goto out;
} }
left = _free(left);
if (defs) {
help = defs; defs = NULL;
}
helpLength = strlen(help); helpLength = strlen(help);
/*@-boundsread@*/
while (helpLength > lineLength) { while (helpLength > lineLength) {
const char * ch;
char format[16];
ch = help + lineLength - 1; ch = help + lineLength - 1;
while (ch > help && !isspace(*ch)) ch--; while (ch > help && !isspace(*ch)) ch--;
if (ch == help) break; /* give up */ if (ch == help) break; /* give up */
@ -96,39 +341,57 @@ static void singleOptionHelp(FILE * f, int maxLeftCol,
ch++; ch++;
sprintf(format, "%%.%ds\n%%%ds", (int) (ch - help), indentLength); sprintf(format, "%%.%ds\n%%%ds", (int) (ch - help), indentLength);
fprintf(f, format, help, " "); /*@-formatconst@*/
fprintf(fp, format, help, " ");
/*@=formatconst@*/
help = ch; help = ch;
while (isspace(*help) && *help) help++; while (isspace(*help) && *help) help++;
helpLength = strlen(help); helpLength = strlen(help);
} }
/*@=boundsread@*/
if (helpLength) fprintf(f, "%s\n", help); if (helpLength) fprintf(fp, "%s\n", help);
out: out:
free(left); /*@-dependenttrans@*/
defs = _free(defs);
/*@=dependenttrans@*/
left = _free(left);
} }
/**
* @param opt option(s)
* @param translation_domain translation domain
*/
static int maxArgWidth(const struct poptOption * opt, static int maxArgWidth(const struct poptOption * opt,
const char * translation_domain) { /*@null@*/ const char * translation_domain)
/*@*/
{
int max = 0; int max = 0;
int this; int len = 0;
const char * s; const char * s;
if (opt != NULL)
while (opt->longName || opt->shortName || opt->arg) { while (opt->longName || opt->shortName || opt->arg) {
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) { if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
this = maxArgWidth(opt->arg, translation_domain); if (opt->arg) /* XXX program error */
if (this > max) max = this; len = maxArgWidth(opt->arg, translation_domain);
if (len > max) max = len;
} else if (!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) { } else if (!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) {
this = opt->shortName ? 2 : 0; len = sizeof(" ")-1;
if (opt->shortName != '\0') len += sizeof("-X")-1;
if (opt->shortName != '\0' && opt->longName) len += sizeof(", ")-1;
if (opt->longName) { if (opt->longName) {
if (this) this += 2; len += ((opt->argInfo & POPT_ARGFLAG_ONEDASH)
this += strlen(opt->longName) + 2; ? sizeof("-")-1 : sizeof("--")-1);
len += strlen(opt->longName);
} }
s = getArgDescrip(opt, translation_domain); s = getArgDescrip(opt, translation_domain);
if (s) if (s)
this += strlen(s) + 1; len += sizeof("=")-1 + strlen(s);
if (this > max) max = this; if (opt->argInfo & POPT_ARGFLAG_OPTIONAL) len += sizeof("[]")-1;
if (len > max) max = len;
} }
opt++; opt++;
@ -137,165 +400,339 @@ static int maxArgWidth(const struct poptOption * opt,
return max; return max;
} }
static void singleTableHelp(FILE * f, const struct poptOption * table, /**
int left, * Display popt alias and exec help.
const char *translation_domain) { * @param fp output file handle
const struct poptOption * opt; * @param items alias/exec array
const char *sub_transdom; * @param nitems no. of alias/exec entries
* @param left
* @param translation_domain translation domain
*/
static void itemHelp(FILE * fp,
/*@null@*/ poptItem items, int nitems, int left,
/*@null@*/ const char * translation_domain)
/*@globals fileSystem @*/
/*@modifies *fp, fileSystem @*/
{
poptItem item;
int i;
opt = table; if (items != NULL)
while (opt->longName || opt->shortName || opt->arg) { for (i = 0, item = items; i < nitems; i++, item++) {
if ((opt->longName || opt->shortName) && const struct poptOption * opt;
opt = &item->option;
if ((opt->longName || opt->shortName) &&
!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN))
singleOptionHelp(f, left, opt, translation_domain); singleOptionHelp(fp, left, opt, translation_domain);
opt++;
}
opt = table;
while (opt->longName || opt->shortName || opt->arg) {
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
sub_transdom = getTableTranslationDomain(opt->arg);
if(!sub_transdom)
sub_transdom = translation_domain;
if (opt->descrip)
fprintf(f, "\n%s\n", D_(sub_transdom, opt->descrip));
singleTableHelp(f, opt->arg, left, sub_transdom);
}
opt++;
} }
} }
static int showHelpIntro(poptContext con, FILE * f) { /**
* Display help text for a table of options.
* @param con context
* @param fp output file handle
* @param table option(s)
* @param left
* @param translation_domain translation domain
*/
static void singleTableHelp(poptContext con, FILE * fp,
/*@null@*/ const struct poptOption * table, int left,
/*@null@*/ const char * translation_domain)
/*@globals fileSystem @*/
/*@modifies *fp, fileSystem @*/
{
const struct poptOption * opt;
const char *sub_transdom;
if (table == poptAliasOptions) {
itemHelp(fp, con->aliases, con->numAliases, left, NULL);
itemHelp(fp, con->execs, con->numExecs, left, NULL);
return;
}
if (table != NULL)
for (opt = table; (opt->longName || opt->shortName || opt->arg); opt++) {
if ((opt->longName || opt->shortName) &&
!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN))
singleOptionHelp(fp, left, opt, translation_domain);
}
if (table != NULL)
for (opt = table; (opt->longName || opt->shortName || opt->arg); opt++) {
if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_INCLUDE_TABLE)
continue;
sub_transdom = getTableTranslationDomain(opt->arg);
if (sub_transdom == NULL)
sub_transdom = translation_domain;
if (opt->descrip)
fprintf(fp, "\n%s\n", D_(sub_transdom, opt->descrip));
singleTableHelp(con, fp, opt->arg, left, sub_transdom);
}
}
/**
* @param con context
* @param fp output file handle
*/
static int showHelpIntro(poptContext con, FILE * fp)
/*@globals fileSystem @*/
/*@modifies *fp, fileSystem @*/
{
int len = 6; int len = 6;
const char * fn; const char * fn;
fprintf(f, POPT_("Usage:")); fprintf(fp, POPT_("Usage:"));
if (!(con->flags & POPT_CONTEXT_KEEP_FIRST)) { if (!(con->flags & POPT_CONTEXT_KEEP_FIRST)) {
/*@-boundsread@*/
/*@-nullderef@*/ /* LCL: wazzup? */
fn = con->optionStack->argv[0]; fn = con->optionStack->argv[0];
if (strchr(fn, '/')) fn = strchr(fn, '/') + 1; /*@=nullderef@*/
fprintf(f, " %s", fn); /*@=boundsread@*/
if (fn == NULL) return len;
if (strchr(fn, '/')) fn = strrchr(fn, '/') + 1;
fprintf(fp, " %s", fn);
len += strlen(fn) + 1; len += strlen(fn) + 1;
} }
return len; return len;
} }
void poptPrintHelp(poptContext con, FILE * f, /*@unused@*/ int flags) { void poptPrintHelp(poptContext con, FILE * fp, /*@unused@*/ int flags)
{
int leftColWidth; int leftColWidth;
showHelpIntro(con, f); (void) showHelpIntro(con, fp);
if (con->otherHelp) if (con->otherHelp)
fprintf(f, " %s\n", con->otherHelp); fprintf(fp, " %s\n", con->otherHelp);
else else
fprintf(f, " %s\n", POPT_("[OPTION...]")); fprintf(fp, " %s\n", POPT_("[OPTION...]"));
leftColWidth = maxArgWidth(con->options, NULL); leftColWidth = maxArgWidth(con->options, NULL);
singleTableHelp(f, con->options, leftColWidth, NULL); singleTableHelp(con, fp, con->options, leftColWidth, NULL);
} }
static int singleOptionUsage(FILE * f, int cursor, /**
const struct poptOption * opt, * @param fp output file handle
const char *translation_domain) { * @param cursor
int len = 3; * @param opt option(s)
* @param translation_domain translation domain
*/
static int singleOptionUsage(FILE * fp, int cursor,
const struct poptOption * opt,
/*@null@*/ const char *translation_domain)
/*@globals fileSystem @*/
/*@modifies *fp, fileSystem @*/
{
int len = 4;
char shortStr[2] = { '\0', '\0' }; char shortStr[2] = { '\0', '\0' };
const char * item = shortStr; const char * item = shortStr;
const char * argDescrip = getArgDescrip(opt, translation_domain); const char * argDescrip = getArgDescrip(opt, translation_domain);
if (opt->shortName) { if (opt->shortName != '\0' && opt->longName != NULL) {
if (!(opt->argInfo & POPT_ARG_MASK)) len += 2;
return cursor; /* we did these already */ if (!(opt->argInfo & POPT_ARGFLAG_ONEDASH)) len++;
len += strlen(opt->longName);
} else if (opt->shortName != '\0') {
len++; len++;
*shortStr = opt->shortName; shortStr[0] = opt->shortName;
shortStr[1] = '\0'; shortStr[1] = '\0';
} else if (opt->longName) { } else if (opt->longName) {
len += 1 + strlen(opt->longName); len += strlen(opt->longName);
if (!(opt->argInfo & POPT_ARGFLAG_ONEDASH)) len++;
item = opt->longName; item = opt->longName;
} }
if (len == 3) return cursor; if (len == 4) return cursor;
if (argDescrip) if (argDescrip)
len += strlen(argDescrip) + 1; len += strlen(argDescrip) + 1;
if ((cursor + len) > 79) { if ((cursor + len) > 79) {
fprintf(f, "\n "); fprintf(fp, "\n ");
cursor = 7; cursor = 7;
} }
fprintf(f, " [-%s%s%s%s]", opt->shortName ? "" : "-", item, if (opt->longName && opt->shortName) {
argDescrip ? (opt->shortName ? " " : "=") : "", fprintf(fp, " [-%c|-%s%s%s%s]",
argDescrip ? argDescrip : ""); opt->shortName, ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "" : "-"),
opt->longName,
(argDescrip ? " " : ""),
(argDescrip ? argDescrip : ""));
} else {
fprintf(fp, " [-%s%s%s%s]",
((opt->shortName || (opt->argInfo & POPT_ARGFLAG_ONEDASH)) ? "" : "-"),
item,
(argDescrip ? (opt->shortName != '\0' ? " " : "=") : ""),
(argDescrip ? argDescrip : ""));
}
return cursor + len + 1; return cursor + len + 1;
} }
static int singleTableUsage(FILE * f, int cursor, const struct poptOption * table, /**
const char *translation_domain) { * Display popt alias and exec usage.
const struct poptOption * opt; * @param fp output file handle
* @param cursor
opt = table; * @param item alias/exec array
while (opt->longName || opt->shortName || opt->arg) { * @param nitems no. of ara/exec entries
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INTL_DOMAIN) * @param translation_domain translation domain
translation_domain = (const char *)opt->arg; */
else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) static int itemUsage(FILE * fp, int cursor, poptItem item, int nitems,
cursor = singleTableUsage(f, cursor, opt->arg, /*@null@*/ const char * translation_domain)
translation_domain); /*@globals fileSystem @*/
else if ((opt->longName || opt->shortName) && /*@modifies *fp, fileSystem @*/
!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) {
cursor = singleOptionUsage(f, cursor, opt, translation_domain); int i;
opt++; /*@-branchstate@*/ /* FIX: W2DO? */
if (item != NULL)
for (i = 0; i < nitems; i++, item++) {
const struct poptOption * opt;
opt = &item->option;
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INTL_DOMAIN) {
translation_domain = (const char *)opt->arg;
} else if ((opt->longName || opt->shortName) &&
!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) {
cursor = singleOptionUsage(fp, cursor, opt, translation_domain);
}
} }
/*@=branchstate@*/
return cursor; return cursor;
} }
static int showShortOptions(const struct poptOption * opt, FILE * f, /**
char * str) { * Keep track of option tables already processed.
char s[300]; /* this is larger then the ascii set, so */
it should do just fine */ typedef struct poptDone_s {
int nopts;
int maxopts;
const void ** opts;
} * poptDone;
s[0] = '\0'; /**
if (str == NULL) { * Display usage text for a table of options.
memset(s, 0, sizeof(s)); * @param con context
str = s; * @param fp output file handle
* @param cursor
* @param opt option(s)
* @param translation_domain translation domain
* @param done tables already processed
* @return
*/
static int singleTableUsage(poptContext con, FILE * fp, int cursor,
/*@null@*/ const struct poptOption * opt,
/*@null@*/ const char * translation_domain,
/*@null@*/ poptDone done)
/*@globals fileSystem @*/
/*@modifies *fp, done, fileSystem @*/
{
/*@-branchstate@*/ /* FIX: W2DO? */
if (opt != NULL)
for (; (opt->longName || opt->shortName || opt->arg) ; opt++) {
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INTL_DOMAIN) {
translation_domain = (const char *)opt->arg;
} else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
if (done) {
int i = 0;
for (i = 0; i < done->nopts; i++) {
/*@-boundsread@*/
const void * that = done->opts[i];
/*@=boundsread@*/
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;
/*@-boundswrite@*/
if (done->nopts < done->maxopts)
done->opts[done->nopts++] = (const void *) opt->arg;
/*@=boundswrite@*/
}
cursor = singleTableUsage(con, fp, cursor, opt->arg,
translation_domain, done);
} else if ((opt->longName || opt->shortName) &&
!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) {
cursor = singleOptionUsage(fp, cursor, opt, translation_domain);
}
} }
/*@=branchstate@*/
while (opt->longName || opt->shortName || opt->arg) { return cursor;
if (opt->shortName && !(opt->argInfo & POPT_ARG_MASK))
str[strlen(str)] = opt->shortName;
else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE)
showShortOptions(opt->arg, f, str);
opt++;
}
if (s != str || !*s)
return 0;
fprintf(f, " [-%s]", s);
return strlen(s) + 4;
} }
void poptPrintUsage(poptContext con, FILE * f, /*@unused@*/ int flags) { /**
* 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 int 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 alloca on top level call. */
char * s = (str != NULL ? str : memset(alloca(300), 0, 300));
int len = 0;
/*@-boundswrite@*/
if (opt != NULL)
for (; (opt->longName || opt->shortName || opt->arg); opt++) {
if (opt->shortName && !(opt->argInfo & POPT_ARG_MASK))
s[strlen(s)] = opt->shortName;
else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE)
if (opt->arg) /* XXX program error */
len = showShortOptions(opt->arg, fp, s);
}
/*@=boundswrite@*/
/* 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;
}
return len;
}
void poptPrintUsage(poptContext con, FILE * fp, /*@unused@*/ int flags)
{
poptDone done = memset(alloca(sizeof(*done)), 0, sizeof(*done));
int cursor; int cursor;
cursor = showHelpIntro(con, f); done->nopts = 0;
cursor += showShortOptions(con->options, f, NULL); done->maxopts = 64;
singleTableUsage(f, cursor, con->options, NULL); cursor = done->maxopts * sizeof(*done->opts);
/*@-boundswrite@*/
done->opts = memset(alloca(cursor), 0, cursor);
done->opts[done->nopts++] = (const void *) con->options;
/*@=boundswrite@*/
cursor = showHelpIntro(con, fp);
cursor += showShortOptions(con->options, fp, NULL);
cursor = singleTableUsage(con, fp, cursor, con->options, NULL, done);
cursor = itemUsage(fp, cursor, con->aliases, con->numAliases, NULL);
cursor = itemUsage(fp, cursor, con->execs, con->numExecs, NULL);
if (con->otherHelp) { if (con->otherHelp) {
cursor += strlen(con->otherHelp) + 1; cursor += strlen(con->otherHelp) + 1;
if (cursor > 79) fprintf(f, "\n "); if (cursor > 79) fprintf(fp, "\n ");
fprintf(f, " %s", con->otherHelp); fprintf(fp, " %s", con->otherHelp);
} }
fprintf(f, "\n"); fprintf(fp, "\n");
} }
void poptSetOtherOptionHelp(poptContext con, const char * text) { void poptSetOtherOptionHelp(poptContext con, const char * text)
if (con->otherHelp) xfree(con->otherHelp); {
con->otherHelp = _free(con->otherHelp);
con->otherHelp = xstrdup(text); con->otherHelp = xstrdup(text);
} }
/*@=type@*/

View File

@ -1,71 +1,116 @@
/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING /** \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 file accompanying popt source distributions, available from
ftp://ftp.redhat.com/pub/code/popt */ ftp://ftp.rpm.org/pub/rpm/dist. */
#ifndef H_POPTINT #ifndef H_POPTINT
#define H_POPTINT #define H_POPTINT
/**
* 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. */ /* Bit mask macros. */
/*@-exporttype -redef @*/
typedef unsigned int __pbm_bits; typedef unsigned int __pbm_bits;
/*@=exporttype =redef @*/
#define __PBM_NBITS (8 * sizeof (__pbm_bits)) #define __PBM_NBITS (8 * sizeof (__pbm_bits))
#define __PBM_IX(d) ((d) / __PBM_NBITS) #define __PBM_IX(d) ((d) / __PBM_NBITS)
#define __PBM_MASK(d) ((__pbm_bits) 1 << ((d) % __PBM_NBITS)) #define __PBM_MASK(d) ((__pbm_bits) 1 << (((unsigned)(d)) % __PBM_NBITS))
/*@-exporttype -redef @*/
typedef struct { typedef struct {
__pbm_bits bits[1]; __pbm_bits bits[1];
} pbm_set; } pbm_set;
/*@=exporttype =redef @*/
#define __PBM_BITS(set) ((set)->bits) #define __PBM_BITS(set) ((set)->bits)
#define PBM_ALLOC(d) calloc(__PBM_IX (d) + 1, sizeof(__pbm_bits)) #define PBM_ALLOC(d) calloc(__PBM_IX (d) + 1, sizeof(__pbm_bits))
#define PBM_FREE(s) free(s); #define PBM_FREE(s) _free(s);
#define PBM_SET(d, s) (__PBM_BITS (s)[__PBM_IX (d)] |= __PBM_MASK (d)) #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_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) #define PBM_ISSET(d, s) ((__PBM_BITS (s)[__PBM_IX (d)] & __PBM_MASK (d)) != 0)
struct optionStackEntry { struct optionStackEntry {
int argc; int argc;
/*@only@*/ const char ** argv; /*@only@*/ /*@null@*/
/*@only@*/ pbm_set * argb; const char ** argv;
/*@only@*/ /*@null@*/
pbm_set * argb;
int next; int next;
/*@only@*/ const char * nextArg; /*@only@*/ /*@null@*/
/*@keep@*/ const char * nextCharArg; const char * nextArg;
/*@dependent@*/ struct poptAlias * currAlias; /*@observer@*/ /*@null@*/
const char * nextCharArg;
/*@dependent@*/ /*@null@*/
poptItem currAlias;
int stuffed; int stuffed;
}; };
struct execEntry {
const char * longName;
char shortName;
const char * script;
};
struct poptContext_s { struct poptContext_s {
struct optionStackEntry optionStack[POPT_OPTION_DEPTH]; struct optionStackEntry optionStack[POPT_OPTION_DEPTH];
/*@dependent@*/ struct optionStackEntry * os; /*@dependent@*/
/*@owned@*/ const char ** leftovers; struct optionStackEntry * os;
/*@owned@*/ /*@null@*/
const char ** leftovers;
int numLeftovers; int numLeftovers;
int nextLeftover; int nextLeftover;
/*@keep@*/ const struct poptOption * options; /*@keep@*/
const struct poptOption * options;
int restLeftover; int restLeftover;
/*@only@*/ const char * appName; /*@only@*/ /*@null@*/
/*@only@*/ struct poptAlias * aliases; const char * appName;
/*@only@*/ /*@null@*/
poptItem aliases;
int numAliases; int numAliases;
int flags; int flags;
struct execEntry * execs; /*@owned@*/ /*@null@*/
poptItem execs;
int numExecs; int numExecs;
/*@only@*/ const char ** finalArgv; /*@only@*/ /*@null@*/
const char ** finalArgv;
int finalArgvCount; int finalArgvCount;
int finalArgvAlloced; int finalArgvAlloced;
/*@dependent@*/ struct execEntry * doExec; /*@dependent@*/ /*@null@*/
/*@only@*/ const char * execPath; poptItem doExec;
/*@only@*/
const char * execPath;
int execAbsolute; int execAbsolute;
/*@only@*/ const char * otherHelp; /*@only@*/
const char * otherHelp;
/*@null@*/
pbm_set * arg_strip; pbm_set * arg_strip;
}; };
#define xfree(_a) free((void *)_a) #ifdef HAVE_LIBINTL_H
#include <libintl.h>
#endif
#define POPT_(foo) (foo) #if defined(HAVE_GETTEXT) && !defined(__LCLINT__)
#define D_(dom, str) (str) #define _(foo) gettext(foo)
#define N_(foo) (foo) #else
#define _(foo) foo
#endif
#if defined(HAVE_DCGETTEXT) && !defined(__LCLINT__)
#define D_(dom, str) dgettext(dom, str)
#define POPT_(foo) D_("popt", foo)
#else
#define D_(dom, str) str
#define POPT_(foo) foo
#endif
#define N_(foo) foo
#endif #endif

View File

@ -1,11 +1,16 @@
/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING /** \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 file accompanying popt source distributions, available from
ftp://ftp.redhat.com/pub/code/popt */ ftp://ftp.rpm.org/pub/rpm/dist. */
#include "system.h" #include "system.h"
#define POPT_ARGV_ARRAY_GROW_DELTA 5 #define POPT_ARGV_ARRAY_GROW_DELTA 5
/*@-boundswrite@*/
int poptDupArgv(int argc, const char **argv, int poptDupArgv(int argc, const char **argv,
int * argcPtr, const char *** argvPtr) int * argcPtr, const char *** argvPtr)
{ {
@ -14,6 +19,8 @@ int poptDupArgv(int argc, const char **argv,
char * dst; char * dst;
int i; int i;
if (argc <= 0 || argv == NULL) /* XXX can't happen */
return POPT_ERROR_NOARG;
for (i = 0; i < argc; i++) { for (i = 0; i < argc; i++) {
if (argv[i] == NULL) if (argv[i] == NULL)
return POPT_ERROR_NOARG; return POPT_ERROR_NOARG;
@ -21,20 +28,32 @@ int poptDupArgv(int argc, const char **argv,
} }
dst = malloc(nb); dst = malloc(nb);
if (dst == NULL) /* XXX can't happen */
return POPT_ERROR_MALLOC;
argv2 = (void *) dst; argv2 = (void *) dst;
dst += (argc + 1) * sizeof(*argv); dst += (argc + 1) * sizeof(*argv);
/*@-branchstate@*/
for (i = 0; i < argc; i++) { for (i = 0; i < argc; i++) {
argv2[i] = dst; argv2[i] = dst;
dst += strlen(strcpy(dst, argv[i])) + 1; dst += strlen(strcpy(dst, argv[i])) + 1;
} }
/*@=branchstate@*/
argv2[argc] = NULL; argv2[argc] = NULL;
*argvPtr = argv2; if (argvPtr) {
*argcPtr = argc; *argvPtr = argv2;
} else {
free(argv2);
argv2 = NULL;
}
if (argcPtr)
*argcPtr = argc;
return 0; return 0;
} }
/*@=boundswrite@*/
/*@-bounds@*/
int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr) int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
{ {
const char * src; const char * src;
@ -43,31 +62,32 @@ int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
const char ** argv = malloc(sizeof(*argv) * argvAlloced); const char ** argv = malloc(sizeof(*argv) * argvAlloced);
int argc = 0; int argc = 0;
int buflen = strlen(s) + 1; int buflen = strlen(s) + 1;
char *buf0 = calloc(buflen, 1); char * buf = memset(alloca(buflen), 0, buflen);
char *buf = buf0; int rc = POPT_ERROR_MALLOC;
if (argv == NULL) return rc;
argv[argc] = buf; argv[argc] = buf;
for (src = s; *src; src++) { for (src = s; *src != '\0'; src++) {
if (quote == *src) { if (quote == *src) {
quote = '\0'; quote = '\0';
} else if (quote) { } else if (quote != '\0') {
if (*src == '\\') { if (*src == '\\') {
src++; src++;
if (!*src) { if (!*src) {
free(argv); rc = POPT_ERROR_BADQUOTE;
free(buf0); goto exit;
return POPT_ERROR_BADQUOTE;
} }
if (*src != quote) *buf++ = '\\'; if (*src != quote) *buf++ = '\\';
} }
*buf++ = *src; *buf++ = *src;
} else if (isspace(*src)) { } else if (isspace(*src)) {
if (*argv[argc]) { if (*argv[argc] != '\0') {
buf++, argc++; buf++, argc++;
if (argc == argvAlloced) { if (argc == argvAlloced) {
argvAlloced += POPT_ARGV_ARRAY_GROW_DELTA; argvAlloced += POPT_ARGV_ARRAY_GROW_DELTA;
argv = realloc(argv, sizeof(*argv) * argvAlloced); argv = realloc(argv, sizeof(*argv) * argvAlloced);
if (argv == NULL) goto exit;
} }
argv[argc] = buf; argv[argc] = buf;
} }
@ -75,18 +95,17 @@ int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
case '"': case '"':
case '\'': case '\'':
quote = *src; quote = *src;
break; /*@switchbreak@*/ break;
case '\\': case '\\':
src++; src++;
if (!*src) { if (!*src) {
free(argv); rc = POPT_ERROR_BADQUOTE;
free(buf0); goto exit;
return POPT_ERROR_BADQUOTE;
} }
/*@fallthrough@*/ /*@fallthrough@*/
default: default:
*buf++ = *src; *buf++ = *src;
break; /*@switchbreak@*/ break;
} }
} }
@ -94,9 +113,115 @@ int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
argc++, buf++; argc++, buf++;
} }
(void) poptDupArgv(argc, argv, argcPtr, argvPtr); rc = poptDupArgv(argc, argv, argcPtr, argvPtr);
free(argv); exit:
free(buf0); if (argv) free(argv);
return rc;
}
/*@=bounds@*/
/* 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@*/ int flags)
{
char line[999];
char * argstr;
char * p;
char * q;
char * x;
int t;
int argvlen = 0;
size_t maxlinelen = sizeof(line);
size_t linelen;
int maxargvlen = 480;
int linenum = 0;
*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) {
linenum++;
p = line;
/* loop until first non-space char or EOL */
while( *p != '\0' && isspace(*p) )
p++;
linelen = strlen(p);
if (linelen >= maxlinelen-1)
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' && (!isspace(*q)) && *q != '=')
q++;
if (isspace(*q)) {
/* a space after the name, find next non space */
*q++='\0';
while( *q != '\0' && isspace((int)*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 = 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' && isspace(*q))
q++;
if (*q == '\0')
continue; /* XXX silently ignore missing value */
/* now, loop and strip all ending whitespace */
x = p + linelen;
while (isspace(*--x))
*x = 0; /* null out last char if space (including fgets() NL) */
/* rest of line accept */
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; return 0;
} }

View File

@ -1,6 +1,18 @@
#ifdef HAVE_CONFIG_H
#include "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> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <limits.h> #include <limits.h>
@ -23,6 +35,14 @@
#include <libc.h> #include <libc.h>
#endif #endif
#if defined(__LCLINT__)
/*@-declundef -incondefs -redecl@*/ /* LCL: missing annotation */
/*@only@*/ void * alloca (size_t __size)
/*@ensures MaxSet(result) == (__size - 1) @*/
/*@*/;
/*@=declundef =incondefs =redecl@*/
#endif
/* AIX requires this to be the first thing in the file. */ /* AIX requires this to be the first thing in the file. */
#ifndef __GNUC__ #ifndef __GNUC__
# if HAVE_ALLOCA_H # if HAVE_ALLOCA_H
@ -40,7 +60,10 @@ char *alloca ();
#define alloca __builtin_alloca #define alloca __builtin_alloca
#endif #endif
/*@only@*/ char * xstrdup (const char *str); /*@-redecl -redef@*/
/*@mayexit@*/ /*@only@*/ char * xstrdup (const char *str)
/*@*/;
/*@=redecl =redef@*/
#if HAVE_MCHECK_H && defined(__GNUC__) #if HAVE_MCHECK_H && defined(__GNUC__)
#define vmefail() (fprintf(stderr, "virtual memory exhausted.\n"), exit(EXIT_FAILURE), NULL) #define vmefail() (fprintf(stderr, "virtual memory exhausted.\n"), exit(EXIT_FAILURE), NULL)