src/lib/options.c 1.27
1.27 2009/09/23 18:42:28 angie
Fixed compiler warnings from gcc 4.3.3, mostly about system calls whose return values weren't checked and non-literal format strings with no args.
Index: src/lib/options.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/lib/options.c,v
retrieving revision 1.26
retrieving revision 1.27
diff -b -B -U 1000000 -r1.26 -r1.27
--- src/lib/options.c 13 Aug 2009 21:48:17 -0000 1.26
+++ src/lib/options.c 23 Sep 2009 18:42:28 -0000 1.27
@@ -1,413 +1,414 @@
/* Options.c - stuff to handle command line options.
* This is smaller and more flexible than the cgiSpoof
* routines we used to use - though cgiSpoof is still the
* method of choice for actual CGI routines that want to
* be tested from the command line.
*
* This file is copyright 2002 Jim Kent, but license is hereby
* granted for all use - public, private or commercial. */
#include "common.h"
#include "hash.h"
#include "verbose.h"
#include "options.h"
static char const rcsid[] = "$Id$";
#ifdef MACHTYPE_alpha
#define strtoll strtol
#endif
/* mask for type in optionSpec.flags */
#define OPTION_TYPE_MASK (OPTION_BOOLEAN|OPTION_STRING|OPTION_INT|OPTION_FLOAT|OPTION_LONG_LONG|OPTION_DOUBLE)
static struct optionSpec commonOptions[] = {
{"verbose", OPTION_INT},
{NULL, 0},
};
static struct optionSpec *matchingOption(char *name, struct optionSpec *optionSpecs)
/* Go through spec table and return spec that matches name, or NULL
* if none. */
{
while (optionSpecs->name != NULL)
{
if (sameString(optionSpecs->name, name))
return optionSpecs;
optionSpecs += 1;
}
return NULL;
}
static void validateOption(char *name, char *val, struct optionSpec *optionSpecs)
/* validate an option against a list of values */
{
char *valEnd;
struct optionSpec *optionSpec = matchingOption(name, optionSpecs);
if (optionSpec == NULL)
optionSpec = matchingOption(name, commonOptions);
if (optionSpec == NULL)
errAbort("-%s is not a valid option", name);
+long long discardMe = 0;
switch (optionSpec->flags & OPTION_TYPE_MASK) {
case OPTION_BOOLEAN:
if (val != NULL)
errAbort("boolean option -%s must not have value", name);
break;
case OPTION_STRING:
if (val == NULL)
errAbort("string option -%s must have a value", name);
break;
case OPTION_INT:
if (val == NULL)
errAbort("int option -%s must have a value", name);
- strtol(val, &valEnd, 10);
+ discardMe = strtol(val, &valEnd, 10);
if ((*val == '\0') || (*valEnd != '\0'))
errAbort("value of -%s is not a valid integer: \"%s\"",
name, val);
break;
case OPTION_LONG_LONG:
if (val == NULL)
errAbort("int option -%s must have a value", name);
- strtoll(val, &valEnd, 10);
+ discardMe = strtoll(val, &valEnd, 10);
if ((*val == '\0') || (*valEnd != '\0'))
errAbort("value of -%s is not a valid long long: \"%s\"",
name, val);
break;
case OPTION_FLOAT:
if (val == NULL)
errAbort("float option -%s must have a value", name);
- strtod(val, &valEnd);
+ discardMe = (long long)strtod(val, &valEnd);
if ((*val == '\0') || (*valEnd != '\0'))
errAbort("value of -%s is not a valid float: \"%s\"",
name, val);
break;
case OPTION_DOUBLE:
if (val == NULL)
errAbort("double option -%s must have a value", name);
- strtod(val, &valEnd);
+ discardMe = (long long)strtod(val, &valEnd);
if ((*val == '\0') || (*valEnd != '\0'))
errAbort("value of -%s is not a valid double: \"%s\"",
name, val);
break;
default:
errAbort("bug: invalid type in optionSpec for %s", optionSpec->name);
}
}
static void parseMultiOption(struct hash *hash, char *name, char* val, struct optionSpec *spec)
/* process multiple instances of an option, requres that the optionSpec of the option */
{
struct slName *valList;
switch (spec->flags & OPTION_TYPE_MASK)
{
case OPTION_STRING:
valList = hashFindVal(hash, name);
if (valList == NULL) /* first multi option */
{
valList = newSlName(val);
hashAdd(hash, name, valList);
}
else
{
struct slName *el = newSlName(val);
slAddTail(valList, el); /* added next multi option */
}
break;
default:
errAbort("UNIMPLEMENTED: multiple instances of a non-string option is not currently implemented");
}
}
static boolean parseAnOption(struct hash *hash, char *arg, struct optionSpec *optionSpecs)
/* Parse a single option argument and add to the hash, validating if
* optionSpecs is not NULL. Return TRUE if it's arg is an option argument
* FALSE if it's not.
*/
{
char *name, *val;
char *eqPtr = strchr(arg, '=');
if (!((eqPtr != NULL) || (arg[0] == '-')))
return FALSE; /* not an option */
/* A dash by itself is not an option. It can mean
* negative strand for some of the DNA oriented utilities. */
if (arg[0] == '-' && (arg[1] == 0 || isspace(arg[1])))
return FALSE;
/* It's nice to be able to use url's in the command line, but they
* may have = in them... */
if (startsWith("http://", arg)
|| startsWith("https://", arg)
|| startsWith("ftp://", arg))
return FALSE;
name = arg;
if (name[0] == '-')
name++;
if (eqPtr != NULL)
{
*eqPtr = '\0';
val = eqPtr+1;
}
else
val = NULL;
if (optionSpecs != NULL)
validateOption(name, val, optionSpecs);
if (val == NULL)
val = "on";
if (optionSpecs == NULL)
hashAdd(hash, name, val);
else
{
struct optionSpec *spec = matchingOption(name, optionSpecs);
if (spec != NULL && (spec->flags & OPTION_MULTI)) /* process multiple instances of option */
parseMultiOption(hash, name, val, spec);
else
hashAdd(hash, name, val);
}
if (eqPtr != NULL)
*eqPtr = '=';
return TRUE;
}
static struct hash *parseOptions(int *pArgc, char *argv[], boolean justFirst,
struct optionSpec *optionSpecs)
/* Parse and optionally validate options */
{
int i, origArgc, newArgc = 1;
char **rdPt = argv+1, **wrPt = argv+1;
struct hash *hash = newHash(6);
origArgc = *pArgc;
/* parse arguments */
for (i=1; i<origArgc; ++i)
{
if (sameString(*rdPt, "--"))
{
rdPt++;
i++;
break;
}
if (!parseAnOption(hash, *rdPt, optionSpecs))
{
/* not an option */
if (justFirst)
break;
*wrPt++ = *rdPt;
newArgc++;
}
rdPt++;
}
/* copy any remaining positional args */
for (; i<origArgc; ++i)
{
*wrPt++ = *rdPt++;
newArgc++;
}
*pArgc = newArgc;
*wrPt = NULL;
return hash;
}
struct hash *optionParseIntoHash(int *pArgc, char *argv[], boolean justFirst)
/* Read options in command line (only up to first real argument) into
* options hash. Options come in three forms:
* -option words starting with dash
* option=val words with = in the middle
* -option=val combining the two.
* The resulting hash will be keyed by the option name with the val
* string for value. For '-option' types the value is 'on'. */
{
return parseOptions(pArgc, argv, justFirst, NULL);
}
static struct hash *options = NULL;
static struct optionSpec *optionSpecification = NULL;
static void setOptions(struct hash *hash)
/* Set global options hash to hash, and also do processing
* of log file and other common options. */
{
options = hash;
if (optionExists("verbose"))
verboseSetLevel(optionInt("verbose", 0));
}
void optionHashSome(int *pArgc, char *argv[], boolean justFirst)
/* Set up option hash from command line, optionally only adding
* up to first non-optional word. */
{
if (options == NULL)
{
struct hash *hash = parseOptions(pArgc, argv, justFirst, NULL);
setOptions(hash);
}
}
void optionHash(int *pArgc, char *argv[])
/* Read options in command line into options hash.
* Options come in three forms:
* -option words starting with dash
* option=val words with = in the middle
* -option=val combining the two.
* The resulting hash will be keyed by the option name with the val
* string for value. For '-option' types the value is 'on'. */
{
optionHashSome(pArgc, argv, FALSE);
}
void optionFree()
/* free the option hash */
{
freeHash(&options);
}
void optionInit(int *pArgc, char *argv[], struct optionSpec *optionSpecs)
/* Read options in command line into options hash.
* Options come in three forms:
* -option words starting with dash
* option=val words with = in the middle
* -option=val combining the two.
* The resulting hash will be keyed by the option name with the val
* string for value. For '-option' types the value is 'on'.
* The words in argv are parsed in assending order. If a word of
* "--" is encountered, argument parsing stops.
* If optionSpecs is not NULL, it is an array of optionSpec that are
* used to validate the options. An option must exist in the array
* and the value must be convertable to the type specified in flags.
* Boolean options must no value, all other options must have one.
* Array is terminated by a optionSpec with a NULL name.
* If array NULL, no validation is done.
*/
{
if (options == NULL)
{
struct hash *hash = parseOptions(pArgc, argv, FALSE, optionSpecs);
setOptions(hash);
optionSpecification = optionSpecs;
}
}
static char *optGet(char *name)
/* Lookup option name. Complain if options hash not set. */
{
if (options == NULL)
errAbort("optGet called before optionHash");
return hashFindVal(options, name);
}
char *optionVal(char *name, char *defaultVal)
/* Return named option if in options hash, otherwise default. */
{
char *ret;
/* if a optionSpec was used, make sure this option is not a multi option */
if(optionSpecification != NULL) {
struct optionSpec *spec = matchingOption(name, optionSpecification);
if(spec != NULL && (spec->flags & OPTION_MULTI))
errAbort("ERROR: optionVal cannot be used to get the value of an OPTION_MULTI");
}
ret = optGet(name);
if (ret == NULL)
ret = defaultVal;
return ret;
}
int optionInt(char *name, int defaultVal)
/* Return integer value of named option, or default value
* if not set. */
{
char *s = optGet(name);
char *valEnd;
int val;
if (s == NULL)
return defaultVal;
if (sameString(s,"on"))
return defaultVal;
val = strtol(s, &valEnd, 10);
if ((*s == '\0') || (*valEnd != '\0'))
errAbort("value of -%s is not a valid integer: \"%s\"", name, s);
return val;
}
long long optionLongLong(char *name, long long defaultVal)
/* Return long long value of named option, or default value
* if not set. */
{
char *s = optGet(name);
char *valEnd;
long long val;
if (s == NULL)
return defaultVal;
if (sameString(s,"on"))
return defaultVal;
val = strtoll(s, &valEnd, 10);
if ((*s == '\0') || (*valEnd != '\0'))
errAbort("value of -%s is not a valid long long: \"%s\"", name, s);
return val;
}
float optionFloat(char *name, float defaultVal)
/* Return floating point value or default value if not set. */
{
char *s = optGet(name);
char *valEnd;
float val;
if (s == NULL)
return defaultVal;
val = strtod(s, &valEnd);
if ((*s == '\0') || (*valEnd != '\0'))
errAbort("value of -%s is not a valid float: \"%s\"", name, s);
return val;
}
struct slName *optionMultiVal(char *name, struct slName *defaultVal)
/* Return named option if in options hash, otherwise default. */
{
struct slName *ret;
if(optionSpecification == NULL)
errAbort("ERROR: optionMultiVal can only be used after optionInit is called "
"with a non-NULL optionSpecs");
ret = hashFindVal(options, name);
if (ret == NULL)
ret = defaultVal;
return ret;
}
double optionDouble(char *name, double defaultVal)
/* Return double value or default value if not set */
{
char *s = optGet(name);
char *valEnd;
double val;
if (s == NULL)
return defaultVal;
val = strtod(s, &valEnd);
if ((*s == '\0') || (*valEnd != '\0'))
errAbort("value of -%s is not a valid double: \"%s\"", name, s);
return val;
}
boolean optionExists(char *name)
/* Return TRUE if option has been set. */
{
return optGet(name) != NULL;
}
void optionMustExist(char *name)
/* Abort if option has not been set. */
{
if (optGet(name) == NULL)
errAbort("Missing required command line flag %s", name);
}