Copying ede-bug-report from branches in trunk

This commit is contained in:
Sanel Zukan
2009-07-03 14:23:51 +00:00
parent bfed428c37
commit 66e586f37f
138 changed files with 35380 additions and 0 deletions

View File

@@ -0,0 +1,93 @@
#define _GNU_SOURCE
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "xmlrpc_config.h" /* For HAVE_ASPRINTF, __inline__ */
#include "casprintf.h"
static __inline__ void
simpleVasprintf(char ** const retvalP,
const char * const fmt,
va_list varargs) {
/*----------------------------------------------------------------------------
This is a poor man's implementation of vasprintf(), of GNU fame.
-----------------------------------------------------------------------------*/
size_t const initialSize = 4096;
char * result;
result = malloc(initialSize);
if (result != NULL) {
size_t bytesNeeded;
bytesNeeded = XMLRPC_VSNPRINTF(result, initialSize, fmt, varargs);
if (bytesNeeded > initialSize) {
free(result);
result = malloc(bytesNeeded);
if (result != NULL)
XMLRPC_VSNPRINTF(result, bytesNeeded, fmt, varargs);
} else if (bytesNeeded == initialSize) {
if (result[initialSize-1] != '\0') {
/* This is one of those old systems where vsnprintf()
returns the number of bytes it used, instead of the
number that it needed, and it in fact needed more than
we gave it. Rather than mess with this highly unlikely
case (old system and string > 4095 characters), we just
treat this like an out of memory failure.
*/
free(result);
result = NULL;
}
}
}
*retvalP = result;
}
const char * const strsol = "[Insufficient memory to build string]";
void
cvasprintf(const char ** const retvalP,
const char * const fmt,
va_list varargs) {
char * string;
#if HAVE_ASPRINTF
vasprintf(&string, fmt, varargs);
#else
simpleVasprintf(&string, fmt, varargs);
#endif
if (string == NULL)
*retvalP = strsol;
else
*retvalP = string;
}
void GNU_PRINTF_ATTR(2,3)
casprintf(const char ** const retvalP, const char * const fmt, ...) {
va_list varargs; /* mysterious structure used by variable arg facility */
va_start(varargs, fmt); /* start up the mysterious variable arg facility */
cvasprintf(retvalP, fmt, varargs);
va_end(varargs);
}
void
strfree(const char * const string) {
if (string != strsol)
free((void *)string);
}

View File

@@ -0,0 +1,587 @@
#include "xmlrpc_config.h" /* prereq for mallocvar.h -- defines __inline__ */
#include <sys/types.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <limits.h>
#include "bool.h"
#include "int.h"
#include "mallocvar.h"
#include "casprintf.h"
#include "getoptx.h"
#include "string_parser.h"
#include "cmdline_parser.h"
#define MAXOPTS 100
struct optionDesc {
const char * name;
enum optiontype type;
bool present;
union {
unsigned int u;
int i;
const char * s;
uint64_t llu;
double d;
} value;
};
struct cmdlineParserCtl {
struct optionDesc * optionDescArray;
unsigned int numOptions;
const char ** argumentArray;
unsigned int numArguments;
};
static struct optionx *
createLongOptsArray(struct optionDesc * const optionDescArray,
unsigned int const numOptions) {
struct optionx * longopts;
MALLOCARRAY(longopts, numOptions+1);
if (longopts != NULL) {
unsigned int i;
for (i = 0; i < numOptions; ++i) {
longopts[i].name = optionDescArray[i].name;
/* If the option takes a value, we say it is optional even
though it never is. That's because if we say it is
mandatory, getopt_long_only() pretends it doesn't even
recognize the option if the user doesn't give a value.
We prefer to generate a meaningful error message when
the user omits a required option value.
*/
longopts[i].has_arg =
optionDescArray[i].type == OPTTYPE_FLAG ?
no_argument : optional_argument;
longopts[i].flag = NULL;
longopts[i].val = i;
}
longopts[numOptions].name = 0;
longopts[numOptions].has_arg = 0;
longopts[numOptions].flag = 0;
longopts[numOptions].val = 0;
}
return longopts;
}
static void
parseInt(enum optiontype const type,
const char * const optarg,
unsigned int * const valueUintP,
int * const valueIntP,
const char ** const errorP) {
if (optarg == NULL)
casprintf(errorP, "Option requires a value");
else if (strlen(optarg) == 0)
casprintf(errorP, "Numeric option value is null string");
else {
char * tailptr;
long const longvalue = strtol(optarg, &tailptr, 10);
if (*tailptr != '\0')
casprintf(errorP, "Non-numeric value "
"for numeric option value: '%s'", optarg);
else if (errno == ERANGE || longvalue > INT_MAX)
casprintf(errorP, "Numeric value out of range: %s", optarg);
else {
if (type == OPTTYPE_UINT) {
if (longvalue < 0)
casprintf(errorP, "Unsigned numeric value is "
"negative: %ld", longvalue);
else {
*errorP = NULL;
*valueUintP = (unsigned int) longvalue;
}
} else {
*errorP = NULL;
*valueIntP = (int) longvalue;
}
}
}
}
static void
parseBinUint(const char * const optarg,
uint64_t * const valueP,
const char ** const errorP) {
if (optarg == NULL)
casprintf(errorP, "Option requires a value");
else if (strlen(optarg) == 0)
casprintf(errorP, "Numeric option value is null string");
else {
const char * error;
interpretBinUint(optarg, valueP, &error);
if (error) {
casprintf(errorP, "Invalid numeric option value '%s'. %s",
optarg, error);
strfree(error);
}
}
}
static void
parseFloat(const char * const optarg,
double * const valueP,
const char ** const errorP) {
if (optarg == NULL)
casprintf(errorP, "Option requires a value");
else if (strlen(optarg) == 0)
casprintf(errorP, "Numeric option value is null string");
else {
char * tailptr;
double const doublevalue = strtod(optarg, &tailptr);
if (*tailptr != '\0')
casprintf(errorP, "Non-numeric value "
"for numeric option value: '%s'", optarg);
else if (errno == ERANGE)
casprintf(errorP, "Numeric value out of range: %s", optarg);
else {
*errorP = NULL;
*valueP = doublevalue;
}
}
}
static void
parseOptionValue(const char * const optarg,
struct optionDesc * const optionP,
const char ** const errorP) {
switch (optionP->type) {
case OPTTYPE_FLAG:
*errorP = NULL;
break;
case OPTTYPE_INT:
case OPTTYPE_UINT:
parseInt(optionP->type, optarg, &optionP->value.u, &optionP->value.i,
errorP);
break;
case OPTTYPE_STRING:
if (optarg == NULL)
casprintf(errorP, "Option requires a value");
else {
*errorP = NULL;
optionP->value.s = strdup(optarg);
}
break;
case OPTTYPE_BINUINT:
parseBinUint(optarg, &optionP->value.llu, errorP);
break;
case OPTTYPE_FLOAT:
parseFloat(optarg, &optionP->value.d, errorP);
break;
}
}
static void
processOption(struct optionDesc * const optionP,
const char * const optarg,
const char ** const errorP) {
const char * error;
parseOptionValue(optarg, optionP, &error);
if (error)
casprintf(errorP, "Error in '%s' option: %s", optionP->name, error);
else
optionP->present = true;
}
static void
extractArguments(struct cmdlineParserCtl * const cpP,
unsigned int const argc,
const char ** const argv) {
cpP->numArguments = argc - getopt_argstart();
MALLOCARRAY(cpP->argumentArray, cpP->numArguments);
if (cpP->argumentArray == NULL) {
fprintf(stderr, "Unable to allocate memory for argument array "
"(%u arguments)\n", cpP->numArguments);
abort();
} else {
unsigned int i;
for (i = 0; i < cpP->numArguments; ++i) {
cpP->argumentArray[i] = strdup(argv[getopt_argstart() + i]);
if (cpP->argumentArray[i] == NULL) {
fprintf(stderr, "Unable to allocate memory for Argument %u\n",
i);
abort();
}
}
}
}
void
cmd_processOptions(cmdlineParser const cpP,
int const argc,
const char ** const argv,
const char ** const errorP) {
struct optionx * longopts;
longopts = createLongOptsArray(cpP->optionDescArray, cpP->numOptions);
if (longopts == NULL)
casprintf(errorP, "Unable to get memory for longopts array");
else {
int endOfOptions;
unsigned int i;
*errorP = NULL;
/* Set up initial assumption: No options present */
for (i = 0; i < cpP->numOptions; ++i)
cpP->optionDescArray[i].present = false;
endOfOptions = false; /* initial value */
while (!endOfOptions && !*errorP) {
int const opterr0 = 0;
/* Don't let getopt_long_only() print an error message */
unsigned int longoptsIndex;
const char * unrecognizedOption;
const char * optarg;
getopt_long_onlyx(argc, (char**) argv, "", longopts,
&longoptsIndex, opterr0,
&endOfOptions, &optarg, &unrecognizedOption);
if (unrecognizedOption)
casprintf(errorP, "Unrecognized option: '%s'",
unrecognizedOption);
else {
if (!endOfOptions)
processOption(&cpP->optionDescArray[longoptsIndex], optarg,
errorP);
}
}
if (!*errorP)
extractArguments(cpP, argc, argv);
free(longopts);
}
}
cmdlineParser
cmd_createOptionParser(void) {
struct cmdlineParserCtl * cpP;
MALLOCVAR(cpP);
if (cpP != NULL) {
struct optionDesc * optionDescArray;
cpP->numOptions = 0;
MALLOCARRAY(optionDescArray, MAXOPTS);
if (optionDescArray == NULL) {
free(cpP);
cpP = NULL;
} else
cpP->optionDescArray = optionDescArray;
}
return cpP;
}
void
cmd_destroyOptionParser(cmdlineParser const cpP) {
unsigned int i;
for (i = 0; i < cpP->numOptions; ++i) {
struct optionDesc const option = cpP->optionDescArray[i];
if (option.type == OPTTYPE_STRING && option.present)
strfree(option.value.s);
strfree(option.name);
}
for (i = 0; i < cpP->numArguments; ++i)
strfree(cpP->argumentArray[i]);
free(cpP->optionDescArray);
free(cpP);
}
void
cmd_defineOption(cmdlineParser const cpP,
const char * const name,
enum optiontype const type) {
if (cpP->numOptions < MAXOPTS) {
cpP->optionDescArray[cpP->numOptions].name = strdup(name);
cpP->optionDescArray[cpP->numOptions].type = type;
++cpP->numOptions;
}
}
static struct optionDesc *
findOptionDesc(struct cmdlineParserCtl * const cpP,
const char * const name) {
struct optionDesc * retval;
unsigned int i;
retval = NULL;
for (i = 0; i < cpP->numOptions && !retval; ++i)
if (strcmp(cpP->optionDescArray[i].name, name) == 0)
retval = &cpP->optionDescArray[i];
return retval;
}
int
cmd_optionIsPresent(cmdlineParser const cpP,
const char * const name) {
struct optionDesc * const optionDescP = findOptionDesc(cpP, name);
bool present;
if (!optionDescP) {
fprintf(stderr, "cmdlineParser called incorrectly. "
"optionIsPresent() called for undefined option '%s'\n",
name);
abort();
} else
present = optionDescP->present;
return present;
}
unsigned int
cmd_getOptionValueUint(cmdlineParser const cpP,
const char * const name) {
struct optionDesc * const optionDescP = findOptionDesc(cpP, name);
unsigned int retval;
if (!optionDescP) {
fprintf(stderr, "cmdlineParser called incorrectly. "
"cmd_getOptionValueUint() called for undefined option '%s'\n",
name);
abort();
} else {
if (optionDescP->type != OPTTYPE_UINT) {
fprintf(stderr, "cmdlineParser called incorrectly. "
"cmd_getOptionValueUint() called for non-unsigned integer "
"option '%s'\n", optionDescP->name);
abort();
} else {
if (optionDescP->present)
retval = optionDescP->value.u;
else
retval = 0;
}
}
return retval;
}
int
cmd_getOptionValueInt(cmdlineParser const cpP,
const char * const name) {
struct optionDesc * const optionDescP = findOptionDesc(cpP, name);
int retval;
if (!optionDescP) {
fprintf(stderr, "cmdlineParser called incorrectly. "
"cmd_getOptionValueInt() called for undefined option '%s'\n",
name);
abort();
} else {
if (optionDescP->type != OPTTYPE_INT) {
fprintf(stderr, "cmdlineParser called incorrectly. "
"cmd_getOptionValueInt() called for non-integer "
"option '%s'\n", optionDescP->name);
abort();
} else {
if (optionDescP->present)
retval = optionDescP->value.i;
else
retval = 0;
}
}
return retval;
}
const char *
cmd_getOptionValueString(cmdlineParser const cpP,
const char * const name) {
struct optionDesc * const optionDescP = findOptionDesc(cpP, name);
const char * retval;
if (!optionDescP) {
fprintf(stderr, "cmdlineParser called incorrectly. "
"cmd_getOptionValueString() called for "
"undefined option '%s'\n",
name);
abort();
} else {
if (optionDescP->type != OPTTYPE_STRING) {
fprintf(stderr, "cmdlineParser called incorrectly. "
"getOptionValueString() called for non-string "
"option '%s'\n", optionDescP->name);
abort();
} else {
if (optionDescP->present) {
retval = strdup(optionDescP->value.s);
if (retval == NULL) {
fprintf(stderr,
"out of memory in cmd_getOptionValueString()\n");
abort();
}
} else
retval = NULL;
}
}
return retval;
}
uint64_t
cmd_getOptionValueBinUint(cmdlineParser const cpP,
const char * const name) {
struct optionDesc * const optionDescP = findOptionDesc(cpP, name);
uint64_t retval;
if (!optionDescP) {
fprintf(stderr, "cmdlineParser called incorrectly. "
"cmd_getOptionValueUint() called for undefined option '%s'\n",
name);
abort();
} else {
if (optionDescP->type != OPTTYPE_BINUINT) {
fprintf(stderr, "cmdlineParser called incorrectly. "
"cmd_getOptionValueBinUint() called for "
"non-OPTTYPE_BINUINT "
"option '%s'\n", optionDescP->name);
abort();
} else {
if (optionDescP->present)
retval = optionDescP->value.llu;
else
retval = 0;
}
}
return retval;
}
double
cmd_getOptionValueFloat(cmdlineParser const cpP,
const char * const name) {
struct optionDesc * const optionDescP = findOptionDesc(cpP, name);
double retval;
if (!optionDescP) {
fprintf(stderr, "cmdlineParser called incorrectly. "
"cmd_getOptionValueInt() called for undefined option '%s'\n",
name);
abort();
} else {
if (optionDescP->type != OPTTYPE_FLOAT) {
fprintf(stderr, "cmdlineParser called incorrectly. "
"cmd_getOptionValueInt() called for non-float "
"option '%s'\n", optionDescP->name);
abort();
} else {
if (optionDescP->present)
retval = optionDescP->value.d;
else
retval = 0.0;
}
}
return retval;
}
unsigned int
cmd_argumentCount(cmdlineParser const cpP) {
return cpP->numArguments;
}
const char *
cmd_getArgument(cmdlineParser const cpP,
unsigned int const argNumber) {
const char * retval;
if (argNumber >= cpP->numArguments)
retval = NULL;
else {
retval = strdup(cpP->argumentArray[argNumber]);
if (retval == NULL) {
fprintf(stderr,
"out of memory in cmd_getArgument()\n");
abort();
}
}
return retval;
}

View File

@@ -0,0 +1,157 @@
#include <string>
#include <stdexcept>
#include "girstring.h"
#include "casprintf.h"
#include "cmdline_parser.h"
#include "cmdline_parser.hpp"
using namespace std;
static enum optiontype
optTypeConvert(
CmdlineParser::optType const arg) {
enum optiontype retval;
retval = OPTTYPE_FLAG; // defeat compiler warning
switch (arg) {
case CmdlineParser::FLAG: retval = OPTTYPE_FLAG; break;
case CmdlineParser::INT: retval = OPTTYPE_INT; break;
case CmdlineParser::UINT: retval = OPTTYPE_UINT; break;
case CmdlineParser::STRING: retval = OPTTYPE_STRING; break;
case CmdlineParser::BINUINT: retval = OPTTYPE_BINUINT; break;
case CmdlineParser::FLOAT: retval = OPTTYPE_FLOAT; break;
}
return retval;
}
CmdlineParser::CmdlineParser() {
this->cp = cmd_createOptionParser();
}
CmdlineParser::~CmdlineParser() {
cmd_destroyOptionParser(this->cp);
}
void
CmdlineParser::defineOption(
string const optionName,
optType const optionType) {
cmd_defineOption(this->cp, optionName.c_str(),
optTypeConvert(optionType));
}
void
CmdlineParser::processOptions(
int const argc,
const char ** const argv) {
const char * error;
cmd_processOptions(this->cp, argc, argv, &error);
if (error) {
string const errorS(error);
strfree(error);
throw(runtime_error(errorS));
}
}
bool
CmdlineParser::optionIsPresent(
string const optionName) const {
return (cmd_optionIsPresent(this->cp, optionName.c_str()) ? true : false);
}
int
CmdlineParser::getOptionValueInt(
string const optionName) const {
return cmd_getOptionValueInt(this->cp, optionName.c_str());
}
unsigned int
CmdlineParser::getOptionValueUint(
string const optionName) const {
return cmd_getOptionValueUint(this->cp, optionName.c_str());
}
unsigned long long
CmdlineParser::getOptionValueBinUint(
string const optionName) const {
return cmd_getOptionValueBinUint(this->cp, optionName.c_str());
}
double
CmdlineParser::getOptionValueFloat(
string const optionName) const {
return cmd_getOptionValueFloat(this->cp, optionName.c_str());
}
string
CmdlineParser::getOptionValueString(
string const optionName) const {
const char * const value =
cmd_getOptionValueString(this->cp, optionName.c_str());
string retval;
if (value) {
retval = string(value);
strfree(value);
} else
retval = "";
return retval;
}
unsigned int
CmdlineParser::argumentCount() const {
return cmd_argumentCount(this->cp);
}
string
CmdlineParser::getArgument(
unsigned int const argNumber) const {
const char * const value = cmd_getArgument(this->cp, argNumber);
string const retval(value);
strfree(value);
return retval;
}

View File

@@ -0,0 +1,466 @@
/* This version of `getopt' appears to the caller like standard Unix getopt()
but it behaves differently for the user, since it allows the user
to intersperse the options with the other arguments.
As getopt() works, it permutes the elements of `argv' so that,
when it is done, all the options precede everything else. Thus
all application programs are extended to handle flexible argument order.
Setting the environment variable _POSIX_OPTION_ORDER disables permutation.
Then the behavior is completely standard.
GNU application programs can use a third alternative mode in which
they can distinguish the relative order of options and other arguments.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "getoptx.h"
/* Note that on some systems, the header files above declare variables
for use with their native getopt facilities, and those variables have
the same names as we'd like to use. So we use things like optargx
instead of optarg to avoid the collision.
*/
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
*/
static char *optargx = 0;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to getoptx().
On entry to getoptx(), zero means this is the first call; initialize.
When getoptx() returns EOF, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optindx' communicates from one call to the next
how much of ARGV has been scanned so far.
*/
static int optindx = 0;
/* The next char to be scanned in the option-element
in which the last option character we returned was found.
This allows us to pick up the scan where we left off.
If this is zero, or a null string, it means resume the scan
by advancing to the next ARGV-element. */
static char *nextchar;
/* Callers store zero here to inhibit the error message
for unrecognized options.
*/
static int opterrx;
/* Index in _GETOPT_LONG_OPTIONS of the long-named option actually found.
Only valid when a long-named option was found. */
static int option_index;
struct optionx * _getopt_long_options;
/* Handle permutation of arguments. */
/* Describe the part of ARGV that contains non-options that have
been skipped. `first_nonopt' is the index in ARGV of the first of them;
`last_nonopt' is the index after the last of them. */
static int first_nonopt;
static int last_nonopt;
/* Exchange two adjacent subsequences of ARGV.
One subsequence is elements [first_nonopt,last_nonopt)
which contains all the non-options that have been skipped so far.
The other is elements [last_nonopt,optindx), which contains all
the options processed since those non-options were skipped.
`first_nonopt' and `last_nonopt' are relocated so that they describe
the new indices of the non-options in ARGV after they are moved. */
static void
exchange(char ** const argv) {
unsigned int const nonopts_size =
(last_nonopt - first_nonopt) * sizeof (char *);
char **temp = (char **) malloc (nonopts_size);
if (temp == NULL)
abort();
/* Interchange the two blocks of data in argv. */
memcpy (temp, &argv[first_nonopt], nonopts_size);
memcpy (&argv[first_nonopt], &argv[last_nonopt],
(optindx - last_nonopt) * sizeof (char *));
memcpy (&argv[first_nonopt + optindx - last_nonopt], temp,
nonopts_size);
/* Update records for the slots the non-options now occupy. */
first_nonopt += (optindx - last_nonopt);
last_nonopt = optindx;
free(temp);
}
/* Scan elements of ARGV (whose length is ARGC) for option characters
given in OPTSTRING.
If an element of ARGV starts with '-', and is not exactly "-" or "--",
then it is an option element. The characters of this element
(aside from the initial '-') are option characters. If getoptx()
is called repeatedly, it returns successively each of the option characters
from each of the option elements.
If getoptx() finds another option character, it returns that character,
updating `optindx' and `nextchar' so that the next call to getoptx() can
resume the scan with the following option character or ARGV-element.
If there are no more option characters, getoptx() returns `EOF'.
Then `optindx' is the index in ARGV of the first ARGV-element
that is not an option. (The ARGV-elements have been permuted
so that those that are not options now come last.)
OPTSTRING is a string containing the legitimate option characters.
If an option character is seen that is not listed in OPTSTRING,
return '?' after printing an error message. If you set `opterrx' to
zero, the error message is suppressed but we still return '?'.
If a char in OPTSTRING is followed by a colon, that means it wants an arg,
so the following text in the same ARGV-element, or the text of the following
ARGV-element, is returned in `optargx'. Two colons mean an option that
wants an optional arg; if there is text in the current ARGV-element,
it is returned in `optargx', otherwise `optargx' is set to zero.
If OPTSTRING starts with `-', it requests a different method of handling the
non-option ARGV-elements. See the comments about RETURN_IN_ORDER, above.
Long-named options begin with `+' instead of `-'.
Their names may be abbreviated as long as the abbreviation is unique
or is an exact match for some defined option. If they have an
argument, it follows the option name in the same ARGV-element, separated
from the option name by a `=', or else the in next ARGV-element.
getoptx() returns 0 when it finds a long-named option. */
static int
getoptx(int const argc,
char ** const argv,
const char * const optstring) {
optargx = 0;
/* Initialize the internal data when the first call is made.
Start processing options with ARGV-element 1 (since ARGV-element 0
is the program name); the sequence of previously skipped
non-option ARGV-elements is empty. */
if (optindx == 0)
{
first_nonopt = last_nonopt = optindx = 1;
nextchar = 0;
}
if (nextchar == 0 || *nextchar == 0)
{
/* If we have just processed some options following some non-options,
exchange them so that the options come first. */
if (first_nonopt != last_nonopt && last_nonopt != optindx)
exchange (argv);
else if (last_nonopt != optindx)
first_nonopt = optindx;
/* Now skip any additional non-options
and extend the range of non-options previously skipped. */
while (optindx < argc
&& (argv[optindx][0] != '-'|| argv[optindx][1] == 0)
&& (argv[optindx][0] != '+'|| argv[optindx][1] == 0))
optindx++;
last_nonopt = optindx;
/* Special ARGV-element `--' means premature end of options.
Skip it like a null option,
then exchange with previous non-options as if it were an option,
then skip everything else like a non-option. */
if (optindx != argc && !strcmp (argv[optindx], "--"))
{
optindx++;
if (first_nonopt != last_nonopt && last_nonopt != optindx)
exchange (argv);
else if (first_nonopt == last_nonopt)
first_nonopt = optindx;
last_nonopt = argc;
optindx = argc;
}
/* If we have done all the ARGV-elements, stop the scan
and back over any non-options that we skipped and permuted. */
if (optindx == argc)
{
/* Set the next-arg-index to point at the non-options
that we previously skipped, so the caller will digest them. */
if (first_nonopt != last_nonopt)
optindx = first_nonopt;
return EOF;
}
/* If we have come to a non-option and did not permute it,
either stop the scan or describe it to the caller and pass
it by.
*/
if ((argv[optindx][0] != '-' || argv[optindx][1] == 0)
&& (argv[optindx][0] != '+' || argv[optindx][1] == 0))
{
optargx = argv[optindx++];
return 1;
}
/* We have found another option-ARGV-element.
Start decoding its characters. */
nextchar = argv[optindx] + 1;
}
if ((argv[optindx][0] == '+' || (argv[optindx][0] == '-'))
)
{
struct optionx *p;
char *s = nextchar;
int exact = 0;
int ambig = 0;
struct optionx * pfound;
int indfound;
while (*s && *s != '=') s++;
indfound = 0; /* quite compiler warning */
/* Test all options for either exact match or abbreviated matches. */
for (p = _getopt_long_options, option_index = 0, pfound = NULL;
p->name;
p++, option_index++)
if (!strncmp (p->name, nextchar, s - nextchar))
{
if ((unsigned int)(s - nextchar) == strlen (p->name))
{
/* Exact match found. */
pfound = p;
indfound = option_index;
exact = 1;
break;
}
else if (!pfound)
{
/* First nonexact match found. */
pfound = p;
indfound = option_index;
}
else
/* Second nonexact match found. */
ambig = 1;
}
if (ambig && !exact)
{
fprintf (stderr, "%s: option `%s' is ambiguous\n",
argv[0], argv[optindx]);
nextchar += strlen (nextchar);
return '?';
}
if (pfound)
{
option_index = indfound;
optindx++;
if (*s)
{
if (pfound->has_arg > 0)
optargx = s + 1;
else
{
fprintf (stderr,
"%s: option `%c%s' doesn't allow an argument\n",
argv[0], argv[optindx - 1][0], pfound->name);
nextchar += strlen (nextchar);
return '?';
}
}
else if (pfound->has_arg)
{
if (optindx < argc)
optargx = argv[optindx++];
else if (pfound->has_arg != 2)
{
fprintf (stderr, "%s: option `%s' requires an argument\n",
argv[0], argv[optindx - 1]);
nextchar += strlen (nextchar);
return '?';
}
}
nextchar += strlen (nextchar);
if (pfound->flag)
*(pfound->flag) = pfound->val;
return 0;
}
if (argv[optindx][0] == '+' || strchr (optstring, *nextchar) == 0)
{
if (opterrx != 0)
fprintf (stderr, "%s: unrecognized option `%c%s'\n",
argv[0], argv[optindx][0], nextchar);
nextchar += strlen (nextchar);
return '?';
}
}
/* Look at and handle the next option-character. */
{
char c = *nextchar++;
char *temp = strchr (optstring, c);
/* Increment `optindx' when we start to process its last character. */
if (*nextchar == 0)
optindx++;
if (temp == 0 || c == ':')
{
if (opterrx != 0)
{
if (c < 040 || c >= 0177)
fprintf (stderr, "%s: unrecognized option, "
"character code 0%o\n",
argv[0], c);
else
fprintf (stderr, "%s: unrecognized option `-%c'\n",
argv[0], c);
}
return '?';
}
if (temp[1] == ':')
{
if (temp[2] == ':')
{
/* This is an option that accepts an argument optionally. */
if (*nextchar != 0)
{
optargx = nextchar;
optindx++;
}
else
optargx = 0;
nextchar = 0;
}
else
{
/* This is an option that requires an argument. */
if (*nextchar != 0)
{
optargx = nextchar;
/* If we end this ARGV-element by taking the rest
as an arg, we must advance to the next element
now.
*/
optindx++;
}
else if (optindx == argc)
{
if (opterrx != 0)
fprintf (stderr,
"%s: option `-%c' requires an argument\n",
argv[0], c);
c = '?';
}
else
/* We already incremented `optindx' once;
increment it again when taking next ARGV-elt as
argument.
*/
optargx = argv[optindx++];
nextchar = 0;
}
}
return c;
}
}
void
getopt_long_onlyx(int const argc,
char ** const argv,
const char * const options,
struct optionx * const long_options,
unsigned int * const opt_index,
int const opterrArg,
int * const end_of_options,
const char ** const optarg_arg,
const char ** const unrecognized_option) {
int rc;
opterrx = opterrArg;
_getopt_long_options = long_options;
rc = getoptx(argc, argv, options);
if (rc == 0)
*opt_index = option_index;
if (rc == '?')
*unrecognized_option = argv[optindx];
else
*unrecognized_option = NULL;
if (rc < 0)
*end_of_options = 1;
else
*end_of_options = 0;
*optarg_arg = optargx;
}
unsigned int
getopt_argstart(void) {
/*----------------------------------------------------------------------------
This is a replacement for what traditional getopt does with global
variables.
You call this after getopt_long_onlyx() has returned "end of
options"
-----------------------------------------------------------------------------*/
return optindx;
}
/* Getopt for GNU.
Copyright (C) 1987, 1989 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

View File

@@ -0,0 +1,51 @@
/* Interface to getopt_long_onlyx() */
enum argreq {no_argument, required_argument, optional_argument};
struct optionx {
/* This describes an option. If the field `flag' is nonzero, it
points to a variable that is to be set to the value given in
the field `val' when the option is found, but left unchanged if
the option is not found.
*/
const char * name;
enum argreq has_arg;
int * flag;
int val;
};
/* long_options[] is a list terminated by an element that contains
a NULL 'name' member.
*/
void
getopt_long_onlyx(int const argc,
char ** const argv,
const char * const options,
struct optionx * const long_options,
unsigned int * const opt_index,
int const opterrArg,
int * const end_of_options,
const char ** const optarg_arg,
const char ** const unrecognized_option);
unsigned int
getopt_argstart(void);
/*
Copyright (C) 1989 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */

View File

@@ -0,0 +1,27 @@
#ifndef ASSERTX_HPP_INCLUDED
#define ASSERTX_HPP_INCLUDED
#include <cassert>
/* The compiler often warns you if you give a function formal parameter a
name, but don't use it. But because assert() disappears when doing an
optimized build, the compiler doesn't recognize your reference to the
parameter in the assert() argument. To avoid the bogus warning in
this case, we have ASSERT_ONLY_ARG(), which declares a name for a
formal parameter for purposes of assert() only. In cases where an
assert() would disappear, ASSERT_ONLY_ARG() disappears too.
E.g.
void foo(int const ASSERT_ONLY_ARG(arg1)) {
assert(arg1 > 0);
}
*/
#ifdef NDEBUG
#define ASSERT_ONLY_ARG(x)
#else
#define ASSERT_ONLY_ARG(x) x
#endif
#endif

View File

@@ -0,0 +1,18 @@
/* This takes the place of C99 stdbool.h, which at least some Windows
compilers don't have. (October 2005).
One must not also include <stdbool.h>, because it might cause a name
collision.
*/
#ifndef __cplusplus
/* At least the GNU compiler defines __bool_true_false_are_defined */
#ifndef __bool_true_false_are_defined
#define __bool_true_false_are_defined
typedef enum {
false = 0,
true = 1
} bool;
#endif
#endif

View File

@@ -0,0 +1,19 @@
#ifndef C_UTIL_H_INCLUDED
#define C_UTIL_H_INCLUDED
/* C language stuff. Doesn't involve any libraries that aren't part of
the compiler.
*/
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
/* GNU_PRINTF_ATTR lets the GNU compiler check printf-type
calls to be sure the arguments match the format string, thus preventing
runtime segmentation faults and incorrect messages.
*/
#ifdef __GNUC__
#define GNU_PRINTF_ATTR(a,b) __attribute__ ((format (printf, a, b)))
#else
#define GNU_PRINTF_ATTR(a,b)
#endif
#endif

View File

@@ -0,0 +1,29 @@
#ifndef CASPRINTF_H_INCLUDED
#define CASPRINTF_H_INCLUDED
#include <stdarg.h>
#include "c_util.h"
#ifdef __cplusplus
extern "C" {
#endif
extern const char * const strsol;
void
cvasprintf(const char ** const retvalP,
const char * const fmt,
va_list varargs);
void GNU_PRINTF_ATTR(2,3)
casprintf(const char ** const retvalP, const char * const fmt, ...);
void
strfree(const char * const string);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,86 @@
#ifndef CMDLINE_PARSER_H
#define CMDLINE_PARSER_H
#ifdef __cplusplus
extern "C" {
#endif
#if 0
} /* to fake out automatic code indenters */
#endif
#include "int.h"
/*
NOTE NOTE NOTE: cmd_getOptionValueString() and
cmd_getArgument() return malloc'ed memory (and abort the program if
out of memory). You must free it.
*/
enum optiontype {
OPTTYPE_FLAG,
OPTTYPE_INT,
OPTTYPE_UINT,
OPTTYPE_STRING,
OPTTYPE_BINUINT,
OPTTYPE_FLOAT
};
struct cmdlineParserCtl;
typedef struct cmdlineParserCtl * cmdlineParser;
void
cmd_processOptions(cmdlineParser const cpP,
int const argc,
const char ** const argv,
const char ** const errorP);
cmdlineParser
cmd_createOptionParser(void);
void
cmd_destroyOptionParser(cmdlineParser const cpP);
void
cmd_defineOption(cmdlineParser const cpP,
const char * const name,
enum optiontype const type);
int
cmd_optionIsPresent(cmdlineParser const cpP,
const char * const name);
int
cmd_getOptionValueInt(cmdlineParser const cpP,
const char * const name);
unsigned int
cmd_getOptionValueUint(cmdlineParser const cpP,
const char * const name);
const char *
cmd_getOptionValueString(cmdlineParser const cpP,
const char * const name);
uint64_t
cmd_getOptionValueBinUint(cmdlineParser const cpP,
const char * const name);
double
cmd_getOptionValueFloat(cmdlineParser const cpP,
const char * const name);
unsigned int
cmd_argumentCount(cmdlineParser const cpP);
const char *
cmd_getArgument(cmdlineParser const cpP,
unsigned int const argNumber);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,59 @@
#ifndef CMDLINE_PARSER_HPP_INCLUDED
#define CMDLINE_PARSER_HPP_INCLUDED
#include <string>
struct cmdlineParserCtl;
class CmdlineParser {
public:
CmdlineParser();
~CmdlineParser();
enum optType {FLAG, INT, UINT, STRING, BINUINT, FLOAT};
void
defineOption(std::string const optionName,
optType const optionType);
void
processOptions(int const argc,
const char ** const argv);
bool
optionIsPresent(std::string const optionName) const;
int
getOptionValueInt(std::string const optionName) const;
unsigned int
getOptionValueUint(std::string const optionName) const;
std::string
getOptionValueString(std::string const optionName) const;
unsigned long long
getOptionValueBinUint(std::string const optionName) const;
double
getOptionValueFloat(std::string const optionName) const;
unsigned int
argumentCount() const;
std::string
getArgument(unsigned int const argNumber) const;
private:
struct cmdlineParserCtl * cp;
// Make sure no one can copy this object, because if there are two
// copies, there will be two attempts to destroy *cp.
CmdlineParser(CmdlineParser const&) {};
CmdlineParser&
operator=(CmdlineParser const&) {return *this;}
};
#endif

View File

@@ -0,0 +1,8 @@
#ifndef __GIRMATH_H
#define __GIRMATH_H
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#endif

View File

@@ -0,0 +1,51 @@
#ifndef GIRSTRING_H_INCLUDED
#define GIRSTRING_H_INCLUDED
#include <string.h>
#include "xmlrpc_config.h"
#include "bool.h"
bool
stripcaseeq(const char * const comparand,
const char * const comparator);
static __inline__ bool
streq(const char * const comparator,
const char * const comparand) {
return (strcmp(comparand, comparator) == 0);
}
static __inline__ bool
memeq(const void * const comparator,
const void * const comparand,
size_t const size) {
return (memcmp(comparator, comparand, size) == 0);
}
#define MEMEQ(a,b,c) (memcmp(a, b, c) == 0)
#define MEMSSET(a,b) (memset(a, b, sizeof(*a)))
#define MEMSCPY(a,b) (memcpy(a, b, sizeof(*a)))
#define MEMSZERO(a) (MEMSSET(a, 0))
static __inline__ const char *
sdup(const char * const input) {
return (const char *) strdup(input);
}
/* Copy string pointed by B to array A with size checking. */
#define STRSCPY(A,B) \
(strncpy((A), (B), sizeof(A)), *((A)+sizeof(A)-1) = '\0')
#define STRSCMP(A,B) \
(strncmp((A), (B), sizeof(A)))
/* Concatenate string B onto string in array A with size checking */
#define STRSCAT(A,B) \
(strncat((A), (B), sizeof(A)-strlen(A)), *((A)+sizeof(A)-1) = '\0')
#endif

View File

@@ -0,0 +1,19 @@
#ifndef XMLRPC_INLINE_H_INCLUDED
#define XMLRPC_INLINE_H_INCLUDED
/* Xmlrpc-c uses __inline__ to declare functions that should be
compiled as inline code. Some compilers, e.g. GNU, recognize the
__inline__ keyword.
*/
#ifndef __GNUC__
#ifndef __inline__
#ifdef __sgi
#define __inline__ __inline
#else
#define __inline__
#endif
#endif
#endif
#endif

View File

@@ -0,0 +1,58 @@
/* This takes the place of C99 inttypes.h, which at least some Windows
compilers don't have. (October 2007).
*/
/* PRId64 is the printf-style format specifier for a long long type, as in
long long mynumber = 5;
printf("My number is %" PRId64 ".\n", mynumber);
The LL/ULL macro is for 64 bit integer literals, like this:
long long mask= ULL(1) << 33;
*/
/* 'uint' is quite convenient, but there's no simple way have it everywhere.
Some systems have it in the base system (e.g. GNU C library has it in
<sys/types.h>, and others (e.g. Solaris - 08.12.02) don't. Since we
can't define it unless we know it's not defined already, and we don't
want to burden the reader with a special Xmlrpc-c name such as xuint,
we just use standard "unsigned int" instead.
*/
#ifdef _MSC_VER
# define PRId64 "I64d"
# define PRIu64 "I64u"
#ifndef int16_t
typedef short int16_t;
#endif
#ifndef uint16_t
typedef unsigned short uint16_t;
#endif
#ifndef int32_t
typedef int int32_t;
#endif
#ifndef uint32_t
typedef unsigned int uint32_t;
#endif
#ifndef int64_t
typedef __int64 int64_t;
#endif
#ifndef uint64_t
typedef unsigned __int64 uint64_t;
#endif
#ifndef uint8_t
typedef unsigned char uint8_t;
#endif
/* Older Microsoft compilers don't know the standard ll/ull suffixes */
#define LL(x) x ## i64
#define ULL(x) x ## u64
#else
/* Not Microsoft compiler */
#include <inttypes.h>
#define LL(x) x ## ll
#define ULL(x) x ## ull
#endif

View File

@@ -0,0 +1,193 @@
#ifndef LINKLIST_H_INCLUDED
#define LINKLIST_H_INCLUDED
#include "inline.h"
struct list_head {
/*----------------------------------------------------------------------------
This is a header for an element of a doubly linked list, or an anchor
for such a list.
itemP == NULL means it's an anchor; otherwise it's a header.
Initialize a list header with list_init_header(). You don't have to
do anything to terminate a list header.
Initialize an anchor with list_make_emtpy(). You don't have to do anything
to terminate a list header.
-----------------------------------------------------------------------------*/
struct list_head * nextP;
/* For a header, this is the address of the list header for
the next element in the list. If there is no next element,
it points to the anchor. If the header is not in a list at
all, it is NULL.
For an anchor, it is the address of the list header of the
first element. If the list is empty, it points to the
anchor itself.
*/
struct list_head * prevP;
/* For a header, this is the address of the list header for
the previous element in the list. If there is no previous element,
it points to the anchor. If the header is not in a list at
all, it is NULL.
For an anchor, it is the address of the list header of the
last element. If the list is empty, it points to the
anchor itself.
*/
void * itemP;
/* For a header, this is the address of the list element to which it
belongs. For an anchor, this is NULL.
*/
};
static __inline__ void
list_init_header(struct list_head * const headerP,
void * const itemP) {
headerP->prevP = NULL;
headerP->nextP = NULL;
headerP->itemP = itemP;
}
static __inline__ int
list_is_linked(struct list_head * headerP) {
return headerP->prevP != NULL;
}
static __inline__ int
list_is_empty(struct list_head * const anchorP) {
return anchorP->nextP == anchorP;
}
static __inline__ unsigned int
list_count(struct list_head * const anchorP) {
unsigned int count;
struct list_head * p;
for (p = anchorP->nextP, count = 0;
p != anchorP;
p = p->nextP, ++count);
return count;
}
static __inline__ void
list_make_empty(struct list_head * const anchorP) {
anchorP->prevP = anchorP;
anchorP->nextP = anchorP;
anchorP->itemP = NULL;
}
static __inline__ void
list_insert_after(struct list_head * const beforeHeaderP,
struct list_head * const newHeaderP) {
newHeaderP->prevP = beforeHeaderP;
newHeaderP->nextP = beforeHeaderP->nextP;
beforeHeaderP->nextP = newHeaderP;
newHeaderP->nextP->prevP = newHeaderP;
}
static __inline__ void
list_add_tail(struct list_head * const anchorP,
struct list_head * const headerP) {
list_insert_after(anchorP->prevP, headerP);
}
static __inline__ void
list_add_head(struct list_head * const anchorP,
struct list_head * const headerP) {
list_insert_after(anchorP, headerP);
}
static __inline__ void
list_remove(struct list_head * const headerP) {
headerP->prevP->nextP = headerP->nextP;
headerP->nextP->prevP = headerP->prevP;
headerP->prevP = NULL;
headerP->nextP = NULL;
}
static __inline__ struct list_head *
list_remove_head(struct list_head * const anchorP) {
struct list_head * retval;
if (list_is_empty(anchorP))
retval = NULL;
else {
retval = anchorP->nextP;
list_remove(retval);
}
return retval;
}
static __inline__ struct list_head *
list_remove_tail(struct list_head * const anchorP) {
struct list_head * retval;
if (list_is_empty(anchorP))
retval = NULL;
else {
retval = anchorP->prevP;
list_remove(retval);
}
return retval;
}
static __inline__ void *
list_foreach(struct list_head * const anchorP,
void * functionP(struct list_head *, void *),
void * const context) {
struct list_head * p;
struct list_head * nextP;
void * result;
for (p = anchorP->nextP, nextP = p->nextP, result=NULL;
p != anchorP && result == NULL;
p = nextP, nextP = p->nextP)
result = (*functionP)(p, context);
return result;
}
static __inline__ void
list_append(struct list_head * const newAnchorP,
struct list_head * const baseAnchorP) {
if (!list_is_empty(newAnchorP)) {
baseAnchorP->prevP->nextP = newAnchorP->nextP;
newAnchorP->nextP->prevP = baseAnchorP->prevP;
newAnchorP->prevP->nextP = baseAnchorP;
baseAnchorP->prevP = newAnchorP->prevP;
}
}
#endif

View File

@@ -0,0 +1,111 @@
/* These are some dynamic memory allocation facilities. They are essentially
an extension to C, as they do allocations with a cognizance of C
variables. You can use them to make C read more like a high level
language.
Before including this, you must define an __inline__ macro if your
compiler doesn't recognize it as a keyword.
*/
#ifndef MALLOCVAR_INCLUDED
#define MALLOCVAR_INCLUDED
#include "xmlrpc_config.h"
#include <limits.h>
#include <stdlib.h>
static __inline__ void
mallocProduct(void ** const resultP,
unsigned int const factor1,
unsigned int const factor2) {
/*----------------------------------------------------------------------------
malloc a space whose size in bytes is the product of 'factor1' and
'factor2'. But if that size cannot be represented as an unsigned int,
return NULL without allocating anything. Also return NULL if the malloc
fails.
If either factor is zero, malloc a single byte.
Note that malloc() actually takes a size_t size argument, so the
proper test would be whether the size can be represented by size_t,
not unsigned int. But there is no reliable indication available to
us, like UINT_MAX, of what the limitations of size_t are. We
assume size_t is at least as expressive as unsigned int and that
nobody really needs to allocate more than 4GB of memory.
-----------------------------------------------------------------------------*/
if (factor1 == 0 || factor2 == 0)
*resultP = malloc(1);
else {
if (UINT_MAX / factor2 < factor1)
*resultP = NULL;
else
*resultP = malloc(factor1 * factor2);
}
}
static __inline__ void
reallocProduct(void ** const blockP,
unsigned int const factor1,
unsigned int const factor2) {
void * const oldBlockP = *blockP;
void * newBlockP;
if (UINT_MAX / factor2 < factor1)
newBlockP = NULL;
else
newBlockP = realloc(oldBlockP, factor1 * factor2);
if (newBlockP)
*blockP = newBlockP;
else {
free(oldBlockP);
*blockP = NULL;
}
}
/* IMPLEMENTATION NOTE: There are huge strict aliasing pitfalls here
if you cast pointers, e.g. (void **)
*/
#define MALLOCARRAY(arrayName, nElements) do { \
void * array; \
mallocProduct(&array, nElements, sizeof(arrayName[0])); \
arrayName = array; \
} while (0)
#define REALLOCARRAY(arrayName, nElements) do { \
void * array = arrayName; \
reallocProduct(&array, nElements, sizeof(arrayName[0])); \
arrayName = array; \
} while (0)
#define MALLOCARRAY_NOFAIL(arrayName, nElements) \
do { \
MALLOCARRAY(arrayName, nElements); \
if ((arrayName) == NULL) \
abort(); \
} while(0)
#define REALLOCARRAY_NOFAIL(arrayName, nElements) \
do { \
REALLOCARRAY(arrayName, nElements); \
if ((arrayName) == NULL) \
abort(); \
} while(0)
#define MALLOCVAR(varName) \
varName = malloc(sizeof(*varName))
#define MALLOCVAR_NOFAIL(varName) \
do {if ((varName = malloc(sizeof(*varName))) == NULL) abort();} while(0)
#endif

View File

@@ -0,0 +1,80 @@
/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
** 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 AND CONTRIBUTORS ``AS IS'' AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
** SUCH DAMAGE. */
#ifndef PTHREADX_H_INCLUDED
#define PTHREADX_H_INCLUDED
#ifndef WIN32
# define _REENTRANT
# include <pthread.h>
#elif defined (WIN32)
#include <windows.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef HANDLE pthread_t;
typedef CRITICAL_SECTION pthread_mutex_t;
#define PTHREAD_MUTEX_INITIALIZER NULL
/* usage: pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; */
typedef
struct {
int attrs; /* currently unused. placeholder. */
} pthread_attr_t;
typedef
struct {
int attrs; /* currently unused. placeholder. */
} pthread_mutexattr_t;
/* We make pthread_func identical to a Windows thread start function
so we can use Windows thread functions to implement these pthread
functions directly.
*/
typedef unsigned (WINAPI pthread_func)(void *);
extern int pthread_create(pthread_t * const new_thread_ID,
const pthread_attr_t * const attr,
pthread_func * start_func,
void * const arg);
extern int pthread_cancel(pthread_t target_thread);
extern int pthread_join(pthread_t target_thread, void **status);
extern int pthread_detach(pthread_t target_thread);
extern int pthread_mutex_init(pthread_mutex_t * const mp,
const pthread_mutexattr_t * const attr);
extern int pthread_mutex_lock(pthread_mutex_t * const mp);
extern int pthread_mutex_unlock(pthread_mutex_t * const mp);
extern int pthread_mutex_destroy(pthread_mutex_t * const mp);
#ifdef __cplusplus
}
#endif
#endif /* WIN32 */
#endif

View File

@@ -0,0 +1,67 @@
#ifndef STDARGX_H_INCLUDED
#define STDARGX_H_INCLUDED
#include "xmlrpc_config.h"
#include <stdarg.h>
#include <string.h>
/*----------------------------------------------------------------------------
We need a special version of va_list in order to pass around the
variable argument heap by reference, thus allowing a subroutine to
advance the heap's pointer.
On some systems (e.g. Gcc for PPC or AMD64), va_list is an array.
That invites the scourge of array-to-pointer degeneration if you try
to take its address. Burying it inside a struct as we do with out
va_listx type makes it immune.
Example of what would happen if we used va_list instead of va_listx,
on a system where va_list is an array:
void sub2(va_list * argsP) [
...
}
void sub1(va_list args) {
sub2(&args);
}
This doesn't work. '&args' is the same thing as 'args', so is
va_list, not va_list *. The compiler will even warn you about the
pointer type mismatch.
To use va_listx:
void sub1_va(char * format, va_list args) {
va_listx argsx;
init_va_listx(&argsx, args);
sub2(format, &argsx);
}
-----------------------------------------------------------------------------*/
typedef struct {
/*----------------------------------------------------------------------------
Same thing as va_list, but in a form that works everywhere. See above.
-----------------------------------------------------------------------------*/
va_list v;
} va_listx;
static __inline__ void
init_va_listx(va_listx * const argsxP,
va_list const args) {
#if VA_LIST_IS_ARRAY
/* 'args' is NOT a va_list. It is a pointer to the first element of a
'va_list', which is the same address as a pointer to the va_list
itself.
*/
memcpy(&argsxP->v, args, sizeof(argsxP->v));
#else
argsxP->v = args;
#endif
}
#endif

View File

@@ -0,0 +1,31 @@
#ifndef STRING_PARSER_H_INCLUDED
#define STRING_PARSER_H_INCLUDED
#include "int.h"
void
interpretUll(const char * const string,
uint64_t * const ullP,
const char ** const errorP);
void
interpretLl(const char * const string,
int64_t * const llP,
const char ** const errorP);
void
interpretUint(const char * const string,
unsigned int * const uintP,
const char ** const errorP);
void
interpretInt(const char * const string,
int * const uintP,
const char ** const errorP);
void
interpretBinUint(const char * const string,
uint64_t * const valueP,
const char ** const errorP);
#endif

View File

@@ -0,0 +1,14 @@
#ifndef UNISTDX_H_INCLUDED
#define UNISTDX_H_INCLUDED
/* Xmlrpc-c code #includes "unistdx.h" instead of <unistd.h> because
<unistd.h> does not exist on WIN32.
*/
#ifndef WIN32
# include <unistd.h>
#else
#endif /* WIN32 */
#endif

View File

@@ -0,0 +1,123 @@
/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
** 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 AND CONTRIBUTORS ``AS IS'' AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
** SUCH DAMAGE. */
#include "xmlrpc_config.h"
#ifdef WIN32
#include "pthreadx.h"
#include <process.h>
#undef PACKAGE
#undef VERSION
int
pthread_create(pthread_t * const new_thread_ID,
const pthread_attr_t * const attr,
pthread_func * func,
void * const arg) {
HANDLE hThread;
DWORD dwThreadID;
hThread = (HANDLE) _beginthreadex (
NULL, 0, func, (LPVOID)arg, CREATE_SUSPENDED, &dwThreadID);
SetThreadPriority (hThread, THREAD_PRIORITY_NORMAL);
ResumeThread (hThread);
*new_thread_ID = hThread;
return hThread ? 0 : -1;
}
/* Just kill it. */
int
pthread_cancel(pthread_t const target_thread) {
CloseHandle(target_thread);
return 0;
}
/* Waits for the thread to exit before continuing. */
int
pthread_join(pthread_t const target_thread,
void ** const statusP) {
DWORD dwResult = WaitForSingleObject(target_thread, INFINITE);
*statusP = (void *)dwResult;
return 0;
}
int
pthread_detach(pthread_t const target_thread) {
return 0;
}
int
pthread_mutex_init(pthread_mutex_t * const mp,
const pthread_mutexattr_t * const attr) {
InitializeCriticalSection(mp);
return 0;
}
int
pthread_mutex_lock(pthread_mutex_t * const mp) {
EnterCriticalSection(mp);
return 0;
}
int
pthread_mutex_unlock(pthread_mutex_t * const mp) {
LeaveCriticalSection(mp);
return 0;
}
int
pthread_mutex_destroy(pthread_mutex_t * const mp) {
DeleteCriticalSection(mp);
return 0;
}
#endif

View File

@@ -0,0 +1,226 @@
#include <sys/types.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <limits.h>
#include "int.h"
#include "girstring.h"
#include "casprintf.h"
#include "string_parser.h"
static const char *
strippedSubstring(const char * const string) {
const char * p;
for (p = &string[0]; isspace(*p); ++p);
return p;
}
void
interpretUll(const char * const string,
uint64_t * const ullP,
const char ** const errorP) {
/* strtoull() has the same disappointing weaknesses of strtoul().
See interpretUint().
*/
const char * const strippedString = strippedSubstring(string);
if (strippedString[0] == '\0')
casprintf(errorP, "Null (or all whitespace) string.");
else if (!isdigit(strippedString[0]))
casprintf(errorP, "First non-blank character is '%c', not a digit.",
strippedString[0]);
else {
/* strtoull() does a bizarre thing where if the number is out
of range, it returns a clamped value but tells you about it
by setting errno = ERANGE. If it is not out of range,
strtoull() leaves errno alone.
*/
char * tail;
errno = 0; /* So we can tell if strtoull() overflowed */
*ullP = strtoull(strippedString, &tail, 10);
if (tail[0] != '\0')
casprintf(errorP, "Non-digit stuff in string: %s", tail);
else if (errno == ERANGE)
casprintf(errorP, "Number too large");
else
*errorP = NULL;
}
}
void
interpretLl(const char * const string,
int64_t * const llP,
const char ** const errorP) {
if (string[0] == '\0')
casprintf(errorP, "Null string.");
else {
/* strtoll() does a bizarre thing where if the number is out
of range, it returns a clamped value but tells you about it
by setting errno = ERANGE. If it is not out of range,
strtoll() leaves errno alone.
*/
char * tail;
errno = 0; /* So we can tell if strtoll() overflowed */
*llP = strtoll(string, &tail, 10);
if (tail[0] != '\0')
casprintf(errorP, "Non-digit stuff in string: %s", tail);
else if (errno == ERANGE)
casprintf(errorP, "Number too large");
else
*errorP = NULL;
}
}
void
interpretUint(const char * const string,
unsigned int * const uintP,
const char ** const errorP) {
/* strtoul() does a lousy job of dealing with invalid numbers. A null
string is just zero; a negative number is a large positive one; a
positive (cf unsigned) number is accepted. strtoul is inconsistent
in its treatment of the tail; if there is no valid number at all,
it returns the entire string as the tail, including leading white
space and sign, which are not themselves invalid.
*/
const char * const strippedString = strippedSubstring(string);
if (strippedString[0] == '\0')
casprintf(errorP, "Null (or all whitespace) string.");
else if (!isdigit(strippedString[0]))
casprintf(errorP, "First non-blank character is '%c', not a digit.",
strippedString[0]);
else {
/* strtoul() does a bizarre thing where if the number is out
of range, it returns a clamped value but tells you about it
by setting errno = ERANGE. If it is not out of range,
strtoul() leaves errno alone.
*/
char * tail;
unsigned long ulongValue;
errno = 0; /* So we can tell if strtoul() overflowed */
ulongValue = strtoul(strippedString, &tail, 10);
if (tail[0] != '\0')
casprintf(errorP, "Non-digit stuff in string: %s", tail);
else if (errno == ERANGE)
casprintf(errorP, "Number too large");
else if (ulongValue > UINT_MAX)
casprintf(errorP, "Number too large");
else {
*uintP = ulongValue;
*errorP = NULL;
}
}
}
void
interpretInt(const char * const string,
int * const intP,
const char ** const errorP) {
if (string[0] == '\0')
casprintf(errorP, "Null string.");
else {
/* strtol() does a bizarre thing where if the number is out
of range, it returns a clamped value but tells you about it
by setting errno = ERANGE. If it is not out of range,
strtol() leaves errno alone.
*/
char * tail;
long longValue;
errno = 0; /* So we can tell if strtol() overflowed */
longValue = strtol(string, &tail, 10);
if (tail[0] != '\0')
casprintf(errorP, "Non-digit stuff in string: %s", tail);
else if (errno == ERANGE)
casprintf(errorP, "Number too large");
else if (longValue > INT_MAX)
casprintf(errorP, "Number too large");
else if (longValue < INT_MIN)
casprintf(errorP, "Number too negative");
else {
*intP = longValue;
*errorP = NULL;
}
}
}
void
interpretBinUint(const char * const string,
uint64_t * const valueP,
const char ** const errorP) {
char * tailptr;
long const mantissa_long = strtol(string, &tailptr, 10);
if (errno == ERANGE)
casprintf(errorP,
"Numeric value out of range for computation: '%s'. "
"Try a smaller number with a K, M, G, etc. suffix.",
string);
else {
int64_t const mantissa = mantissa_long;
int64_t argNumber;
*errorP = NULL; /* initial assumption */
if (*tailptr == '\0')
/* There's no suffix. A pure number */
argNumber = mantissa * 1;
else if (stripcaseeq(tailptr, "K"))
argNumber = mantissa * 1024;
else if (stripcaseeq(tailptr, "M"))
argNumber = mantissa * 1024 * 1024;
else if (stripcaseeq(tailptr, "G"))
argNumber = mantissa * 1024 * 1024 * 1024;
else if (stripcaseeq(tailptr, "T"))
argNumber = mantissa * 1024 * 1024 * 1024 * 1024;
else if (stripcaseeq(tailptr, "P"))
argNumber = mantissa * 1024 * 1024 * 1024 * 1024 * 1024;
else {
argNumber = 0; /* quiet compiler warning */
casprintf(errorP, "Garbage suffix '%s' on number", tailptr);
}
if (!*errorP) {
if (argNumber < 0)
casprintf(errorP, "Unsigned numeric value is "
"negative: %" PRId64, argNumber);
else
*valueP = (uint64_t) argNumber;
}
}
}

View File

@@ -0,0 +1,69 @@
#define _GNU_SOURCE
#include <ctype.h>
#include "bool.h"
#include "girstring.h"
bool
stripcaseeq(const char * const comparand,
const char * const comparator) {
/*----------------------------------------------------------------------------
Compare two strings, ignoring leading and trailing blanks and case.
Return true if the strings are identical, false otherwise.
-----------------------------------------------------------------------------*/
const char *p, *q, *px, *qx;
bool equal;
/* Make p and q point to the first non-blank character in each string.
If there are no non-blank characters, make them point to the terminating
NULL.
*/
p = &comparand[0];
while (*p == ' ')
++p;
q = &comparator[0];
while (*q == ' ')
++q;
/* Make px and qx point to the last non-blank character in each string.
If there are no nonblank characters (which implies the string is
null), make them point to the terminating NULL.
*/
if (*p == '\0')
px = p;
else {
px = p + strlen(p) - 1;
while (*px == ' ')
--px;
}
if (*q == '\0')
qx = q;
else {
qx = q + strlen(q) - 1;
while (*qx == ' ')
--qx;
}
equal = true; /* initial assumption */
/* If the stripped strings aren't the same length,
we know they aren't equal
*/
if (px - p != qx - q)
equal = false;
while (p <= px) {
if (toupper(*p) != toupper(*q))
equal = false;
++p; ++q;
}
return equal;
}