updated libopts to 5.18

This commit is contained in:
Nikos Mavrogiannopoulos
2013-11-05 21:04:56 +01:00
parent 6cfa963a1b
commit e7e29b8396
34 changed files with 1152 additions and 926 deletions

View File

@@ -33,8 +33,6 @@
* 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd
*/
static char const * pz_enum_err_fmt;
/* = = = START-STATIC-FORWARD = = = */
static void
enum_err(tOptions * pOpts, tOptDesc * pOD,
@@ -49,8 +47,15 @@ set_memb_shell(tOptions * pOpts, tOptDesc * pOD, char const * const * paz_names,
unsigned int name_ct);
static void
set_memb_names(tOptions * pOpts, tOptDesc * pOD, char const * const * paz_names,
unsigned int name_ct);
set_memb_names(tOptions * opts, tOptDesc * od, char const * const * nm_list,
unsigned int nm_ct);
static uintptr_t
check_membership_start(tOptDesc * od, char const ** argp, bool * invert);
static uintptr_t
find_member_bit(tOptions * opts, tOptDesc * od, char const * pz, int len,
char const * const * nm_list, unsigned int nm_ct);
/* = = = END-STATIC-FORWARD = = = */
static void
@@ -360,16 +365,14 @@ set_memb_shell(tOptions * pOpts, tOptDesc * pOD, char const * const * paz_names,
}
static void
set_memb_names(tOptions * pOpts, tOptDesc * pOD, char const * const * paz_names,
unsigned int name_ct)
set_memb_names(tOptions * opts, tOptDesc * od, char const * const * nm_list,
unsigned int nm_ct)
{
char * pz;
uintptr_t bits = (uintptr_t)pOD->optCookie;
uintptr_t mask = (1UL << (uintptr_t)nm_ct) - 1UL;
uintptr_t bits = (uintptr_t)od->optCookie & mask;
unsigned int ix = 0;
size_t len = NONE_STR_LEN + 1;
(void)pOpts;
bits &= ((uintptr_t)1 << (uintptr_t)name_ct) - (uintptr_t)1;
size_t len = 1;
/*
* Replace the enumeration value with the name string.
@@ -377,46 +380,161 @@ set_memb_names(tOptions * pOpts, tOptDesc * pOD, char const * const * paz_names,
*/
while (bits != 0) {
if (bits & 1)
len += strlen(paz_names[ix]) + PLUS_STR_LEN + 1;
if (++ix >= name_ct) break;
len += strlen(nm_list[ix]) + PLUS_STR_LEN + 1;
if (++ix >= nm_ct) break;
bits >>= 1;
}
pOD->optArg.argString = pz = AGALOC(len, "enum");
od->optArg.argString = pz = AGALOC(len, "enum");
bits = (uintptr_t)od->optCookie & mask;
if (bits == 0) {
*pz = NUL;
return;
}
/*
* Start by clearing all the bits. We want to turn off any defaults
* because we will be restoring to current state, not adding to
* the default set of bits.
*/
memcpy(pz, NONE_STR, NONE_STR_LEN);
pz += NONE_STR_LEN;
bits = (uintptr_t)pOD->optCookie;
bits &= ((uintptr_t)1 << (uintptr_t)name_ct) - (uintptr_t)1;
ix = 0;
for (ix = 0; ; ix++) {
size_t nln;
int doit = bits & 1;
while (bits != 0) {
if (bits & 1) {
size_t nln = strlen(paz_names[ix]);
memcpy(pz, PLUS_STR, PLUS_STR_LEN);
memcpy(pz+PLUS_STR_LEN, paz_names[ix], nln);
pz += nln + PLUS_STR_LEN;
}
if (++ix >= name_ct) break;
bits >>= 1;
if (doit == 0)
continue;
nln = strlen(nm_list[ix]);
memcpy(pz, nm_list[ix], nln);
pz += nln;
if (bits == 0)
break;
memcpy(pz, PLUS_STR, PLUS_STR_LEN);
pz += PLUS_STR_LEN;
}
*pz = NUL;
(void)opts;
}
/**
* Check membership start conditions. An equal character (@samp{=}) says to
* clear the result and not carry over any residual value. A carat
* (@samp{^}), which may follow the equal character, says to invert the
* result. The scanning pointer is advanced past these characters and any
* leading white space. Invalid sequences are indicated by setting the
* scanning pointer to NULL.
*
* @param od the set membership option description
* @param argp a pointer to the string scanning pointer
* @param invert a pointer to the boolean inversion indicator
*
* @returns either zero or the original value for the optCookie.
*/
static uintptr_t
check_membership_start(tOptDesc * od, char const ** argp, bool * invert)
{
uintptr_t res = (uintptr_t)od->optCookie;
char const * arg = SPN_WHITESPACE_CHARS(od->optArg.argString);
if ((arg == NULL) || (*arg == NUL))
goto member_start_fail;
*invert = false;
switch (*arg) {
case '=':
res = 0UL;
arg = SPN_WHITESPACE_CHARS(arg + 1);
switch (*arg) {
case '=': case ',':
goto member_start_fail;
case '^':
goto inversion;
default:
break;
}
break;
case '^':
inversion:
*invert = true;
arg = SPN_WHITESPACE_CHARS(arg + 1);
if (*arg != ',')
break;
/* FALLTHROUGH */
case ',':
goto member_start_fail;
default:
break;
}
*argp = arg;
return res;
member_start_fail:
*argp = NULL;
return 0UL;
}
/**
* convert a name to a bit. Look up a name string to get a bit number
* and shift the value "1" left that number of bits.
*
* @param opts program options descriptor
* @param od the set membership option description
* @param pz address of the start of the bit name
* @param nm_list the list of names for this option
* @param nm_ct the number of entries in this list
*
* @returns 0UL on error, other an unsigned long with the correct bit set.
*/
static uintptr_t
find_member_bit(tOptions * opts, tOptDesc * od, char const * pz, int len,
char const * const * nm_list, unsigned int nm_ct)
{
char nm_buf[ AO_NAME_SIZE ];
memcpy(nm_buf, pz, len);
nm_buf[len] = NUL;
{
unsigned int shift_ct = (unsigned int)
find_name(nm_buf, opts, od, nm_list, nm_ct);
if (shift_ct >= nm_ct)
return 0UL;
return 1UL << shift_ct;
}
}
/*=export_func optionMemberList
* what: Get the list of members of a bit mask set
*
* arg: tOptDesc *, od, the set membership option description
*
* ret_type: char*
* ret_desc: the names of the set bits
*
* doc: This converts the OPT_VALUE_name mask value to a allocated string.
* It is the caller's responsibility to free the string.
=*/
char *
optionMemberList(tOptDesc * od)
{
uintptr_t sv = od->optArg.argIntptr;
char * res;
(*(od->pOptProc))(OPTPROC_RETURN_VALNAME, od);
res = (void *)od->optArg.argString;
od->optArg.argIntptr = sv;
return res;
}
/*=export_func optionSetMembers
* what: Convert between bit flag values and strings
* private:
*
* arg: tOptions*, pOpts, the program options descriptor
* arg: tOptDesc*, pOD, enumeration option description
* arg: tOptions*, opts, the program options descriptor
* arg: tOptDesc*, od, the set membership option description
* arg: char const * const *,
* paz_names, list of enumeration names
* arg: unsigned int, name_ct, number of names in list
* nm_list, list of enumeration names
* arg: unsigned int, nm_ct, number of names in list
*
* doc: This converts the optArg.argString string from the option description
* into the index corresponding to an entry in the name list.
@@ -425,105 +543,103 @@ set_memb_names(tOptions * pOpts, tOptDesc * pOD, char const * const * paz_names,
* if there is only one partial match.
=*/
void
optionSetMembers(tOptions * pOpts, tOptDesc * pOD,
char const* const * paz_names, unsigned int name_ct)
optionSetMembers(tOptions * opts, tOptDesc * od,
char const * const * nm_list, unsigned int nm_ct)
{
/*
* IF the program option descriptor pointer is invalid,
* then it is some sort of special request.
*/
switch ((uintptr_t)pOpts) {
switch ((uintptr_t)opts) {
case (uintptr_t)OPTPROC_EMIT_USAGE:
enum_err(OPTPROC_EMIT_USAGE, pOD, paz_names, name_ct);
enum_err(OPTPROC_EMIT_USAGE, od, nm_list, nm_ct);
return;
case (uintptr_t)OPTPROC_EMIT_SHELL:
set_memb_shell(pOpts, pOD, paz_names, name_ct);
set_memb_shell(opts, od, nm_list, nm_ct);
return;
case (uintptr_t)OPTPROC_RETURN_VALNAME:
set_memb_names(pOpts, pOD, paz_names, name_ct);
set_memb_names(opts, od, nm_list, nm_ct);
return;
default:
break;
}
if ((pOD->fOptState & OPTST_RESET) != 0)
if ((od->fOptState & OPTST_RESET) != 0)
return;
{
char const * pzArg = pOD->optArg.argString;
uintptr_t res;
if ((pzArg == NULL) || (*pzArg == NUL)) {
pOD->optCookie = (void*)0;
return;
}
char const * arg;
bool invert;
uintptr_t res = check_membership_start(od, &arg, &invert);
if (arg == NULL)
goto fail_return;
res = (uintptr_t)pOD->optCookie;
for (;;) {
int iv, len;
while (*arg != NUL) {
bool inv_val = false;
int len;
pzArg = SPN_SET_SEPARATOR_CHARS(pzArg);
iv = (*pzArg == '!');
if (iv)
pzArg = SPN_WHITESPACE_CHARS(pzArg+1);
switch (*arg) {
case ',':
arg = SPN_WHITESPACE_CHARS(arg+1);
if ((*arg == ',') || (*arg == '|'))
goto fail_return;
continue;
len = (int)(BRK_SET_SEPARATOR_CHARS(pzArg) - pzArg);
case '-':
case '!':
inv_val = true;
/* FALLTHROUGH */
case '+':
case '|':
arg = SPN_WHITESPACE_CHARS(arg+1);
}
len = (int)(BRK_SET_SEPARATOR_CHARS(arg) - arg);
if (len == 0)
break;
if ((len == 3) && (strncmp(pzArg, zAll, 3) == 0)) {
if (iv)
if ((len == 3) && (strncmp(arg, zAll, 3) == 0)) {
if (inv_val)
res = 0;
else res = ~0UL;
}
else if ((len == 4) && (strncmp(pzArg, zNone, 4) == 0)) {
if (! iv)
else if ((len == 4) && (strncmp(arg, zNone, 4) == 0)) {
if (! inv_val)
res = 0;
}
else do {
char* pz;
uintptr_t bit = strtoul(pzArg, &pz, 0);
char * pz;
uintptr_t bit = strtoul(arg, &pz, 0);
if (pz != pzArg + len) {
char z[ AO_NAME_SIZE ];
char const* p;
unsigned int shift_ct;
if (*pz != NUL) {
if (len >= AO_NAME_LIMIT)
break;
memcpy(z, pzArg, (size_t)len);
z[len] = NUL;
p = z;
} else {
p = pzArg;
}
shift_ct = (unsigned int)
find_name(p, pOpts, pOD, paz_names, name_ct);
if (shift_ct >= name_ct) {
pOD->optCookie = (void*)0;
return;
}
bit = 1UL << shift_ct;
if (pz != arg + len) {
bit = find_member_bit(opts, od, pz, len, nm_list, nm_ct);
if (bit == 0UL)
goto fail_return;
}
if (iv)
if (inv_val)
res &= ~bit;
else res |= bit;
} while (false);
if (pzArg[len] == NUL)
break;
pzArg += len + 1;
}
if (name_ct < (8 * sizeof(uintptr_t))) {
res &= (1UL << name_ct) - 1UL;
arg = SPN_WHITESPACE_CHARS(arg + len);
}
pOD->optCookie = (void*)res;
if (invert)
res ^= ~0UL;
if (nm_ct < (8 * sizeof(uintptr_t)))
res &= (1UL << nm_ct) - 1UL;
od->optCookie = (void *)res;
}
return;
fail_return:
od->optCookie = (void *)0;
}
/** @}