diff options
Diffstat (limited to 'sntp/libopts/enumeration.c')
-rw-r--r-- | sntp/libopts/enumeration.c | 452 |
1 files changed, 238 insertions, 214 deletions
diff --git a/sntp/libopts/enumeration.c b/sntp/libopts/enumeration.c index 67dd4f47e429..a79a32e5d31c 100644 --- a/sntp/libopts/enumeration.c +++ b/sntp/libopts/enumeration.c @@ -1,96 +1,86 @@ -/* - * $Id: enumeration.c,v 4.17 2007/02/04 17:44:12 bkorb Exp $ - * Time-stamp: "2007-01-13 10:22:35 bkorb" +/** + * \file enumeration.c + * + * Time-stamp: "2011-04-06 10:48:22 bkorb" * * Automated Options Paged Usage module. * * This routine will run run-on options through a pager so the * user may examine, print or edit them at their leisure. - */ - -/* - * Automated Options copyright 1992-2007 Bruce Korb - * - * Automated Options is free software. - * You may redistribute it and/or modify it under the terms of the - * GNU General Public License, as published by the Free Software - * Foundation; either version 2, or (at your option) any later version. * - * Automated Options 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. + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (c) 1992-2011 by Bruce Korb - all rights reserved * - * You should have received a copy of the GNU General Public License - * along with Automated Options. See the file "COPYING". If not, - * write to: The Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. * - * As a special exception, Bruce Korb gives permission for additional - * uses of the text contained in his release of AutoOpts. + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" * - * The exception is that, if you link the AutoOpts library with other - * files to produce an executable, this does not by itself cause the - * resulting executable to be covered by the GNU General Public License. - * Your use of that executable is in no way restricted on account of - * linking the AutoOpts library code into it. + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" * - * This exception does not however invalidate any other reasons why - * the executable file might be covered by the GNU General Public License. + * These files have the following md5sums: * - * This exception applies only to the code released by Bruce Korb under - * the name AutoOpts. If you copy code from other sources under the - * General Public License into a copy of AutoOpts, as the General Public - * License permits, the exception does not apply to the code that you add - * in this way. To avoid misleading anyone as to the status of such - * modified files, you must delete this exception notice from them. - * - * If you write modifications of your own for AutoOpts, it is your choice - * whether to permit this exception to apply to your modifications. - * If you do not wish that, delete this exception notice. + * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 + * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 + * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd */ -tSCC* pz_enum_err_fmt; +static char const * pz_enum_err_fmt; /* = = = START-STATIC-FORWARD = = = */ -/* static forward declarations maintained by :mkfwd */ static void -enumError( - tOptions* pOpts, - tOptDesc* pOD, - tCC* const * paz_names, - int name_ct ); +enum_err(tOptions * pOpts, tOptDesc * pOD, + char const * const * paz_names, int name_ct); static uintptr_t -findName( - tCC* pzName, - tOptions* pOpts, - tOptDesc* pOD, - tCC* const * paz_names, - unsigned int name_ct ); +find_name(char const * pzName, tOptions * pOpts, tOptDesc * pOD, + char const * const * paz_names, unsigned int name_ct); + +static void +set_memb_usage(tOptions * pOpts, tOptDesc * pOD, char const * const * paz_names, + unsigned int name_ct); + +static void +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); /* = = = END-STATIC-FORWARD = = = */ static void -enumError( - tOptions* pOpts, - tOptDesc* pOD, - tCC* const * paz_names, - int name_ct ) +enum_err(tOptions * pOpts, tOptDesc * pOD, + char const * const * paz_names, int name_ct) { size_t max_len = 0; size_t ttl_len = 0; + int ct_down = name_ct; + int hidden = 0; - if (pOpts != NULL) - fprintf( option_usage_fp, pz_enum_err_fmt, pOpts->pzProgName, - pOD->optArg.argString, pOD->pz_Name ); + /* + * A real "pOpts" pointer means someone messed up. Give a real error. + */ + if (pOpts > OPTPROC_EMIT_LIMIT) + fprintf(option_usage_fp, pz_enum_err_fmt, pOpts->pzProgName, + pOD->optArg.argString, pOD->pz_Name); - fprintf( option_usage_fp, zValidKeys, pOD->pz_Name ); + fprintf(option_usage_fp, zValidKeys, pOD->pz_Name); + /* + * If the first name starts with this funny character, then we have + * a first value with an unspellable name. You cannot specify it. + * So, we don't list it either. + */ if (**paz_names == 0x7F) { paz_names++; - name_ct--; + hidden = 1; + ct_down = --name_ct; } /* @@ -98,15 +88,16 @@ enumError( * of all the names. */ { - tCC * const * paz = paz_names; - int ct = name_ct; + char const * const * paz = paz_names; do { - size_t len = strlen( *(paz++) ) + 1; + size_t len = strlen(*(paz++)) + 1; if (len > max_len) max_len = len; ttl_len += len; - } while (--ct > 0); + } while (--ct_down > 0); + + ct_down = name_ct; } /* @@ -114,20 +105,20 @@ enumError( */ if (max_len > 35) { do { - fprintf( option_usage_fp, " %s\n", *(paz_names++) ); - } while (--name_ct > 0); + fprintf(option_usage_fp, " %s\n", *(paz_names++)); + } while (--ct_down > 0); } /* * ELSE IF they all fit on one line, then do so. */ else if (ttl_len < 76) { - fputc( ' ', option_usage_fp ); + fputc(' ', option_usage_fp); do { - fputc( ' ', option_usage_fp ); - fputs( *(paz_names++), option_usage_fp ); - } while (--name_ct > 0); - fputc( '\n', option_usage_fp ); + fputc(' ', option_usage_fp); + fputs(*(paz_names++), option_usage_fp); + } while (--ct_down > 0); + fputc('\n', option_usage_fp); } /* @@ -137,82 +128,86 @@ enumError( int ent_no = 0; char zFmt[16]; /* format for all-but-last entries on a line */ - sprintf( zFmt, "%%-%ds", (int)max_len ); + sprintf(zFmt, "%%-%ds", (int)max_len); max_len = 78 / max_len; /* max_len is now max entries on a line */ - fputs( " ", option_usage_fp ); + fputs(" ", option_usage_fp); /* * Loop through all but the last entry */ - while (--name_ct > 0) { + ct_down = name_ct; + while (--ct_down > 0) { if (++ent_no == max_len) { /* * Last entry on a line. Start next line, too. */ - fprintf( option_usage_fp, "%s\n ", *(paz_names++) ); + fprintf(option_usage_fp, "%s\n ", *(paz_names++)); ent_no = 0; } else - fprintf( option_usage_fp, zFmt, *(paz_names++) ); + fprintf(option_usage_fp, zFmt, *(paz_names++) ); } - fprintf( option_usage_fp, "%s\n", *paz_names ); + fprintf(option_usage_fp, "%s\n", *paz_names); } - /* - * IF we do not have a pOpts pointer, then this output is being requested - * by the usage procedure. Let's not re-invoke it recursively. - */ - if (pOpts != NULL) - (*(pOpts->pUsageProc))( pOpts, EXIT_FAILURE ); - if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_MEMBERSHIP) - fputs( zSetMemberSettings, option_usage_fp ); + if (pOpts > OPTPROC_EMIT_LIMIT) { + fprintf(option_usage_fp, zIntRange, hidden, name_ct - 1 + hidden); + + (*(pOpts->pUsageProc))(pOpts, EXIT_FAILURE); + /* NOTREACHED */ + } + + if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_MEMBERSHIP) { + fprintf(option_usage_fp, zLowerBits, name_ct); + fputs(zSetMemberSettings, option_usage_fp); + } else { + fprintf(option_usage_fp, zIntRange, hidden, name_ct - 1 + hidden); + } } static uintptr_t -findName( - tCC* pzName, - tOptions* pOpts, - tOptDesc* pOD, - tCC* const * paz_names, - unsigned int name_ct ) +find_name(char const * pzName, tOptions * pOpts, tOptDesc * pOD, + char const * const * paz_names, unsigned int name_ct) { - uintptr_t res = name_ct; - size_t len = strlen( (char*)pzName ); - uintptr_t idx; + /* + * Return the matching index as a pointer sized integer. + * The result gets stashed in a char* pointer. + */ + uintptr_t res = name_ct; + size_t len = strlen((char*)pzName); + uintptr_t idx; + + if (IS_DEC_DIGIT_CHAR(*pzName)) { + char * pz = (char *)(void *)pzName; + unsigned long val = strtoul(pz, &pz, 0); + if ((*pz == NUL) && (val < name_ct)) + return (uintptr_t)val; + enum_err(pOpts, pOD, paz_names, (int)name_ct); + return name_ct; + } + /* * Look for an exact match, but remember any partial matches. * Multiple partial matches means we have an ambiguous match. */ for (idx = 0; idx < name_ct; idx++) { - if (strncmp( (char*)paz_names[idx], (char*)pzName, len) == 0) { + if (strncmp((char*)paz_names[idx], (char*)pzName, len) == 0) { if (paz_names[idx][len] == NUL) return idx; /* full match */ - if (res != name_ct) { - pz_enum_err_fmt = zAmbigKey; - option_usage_fp = stderr; - enumError( pOpts, pOD, paz_names, (int)name_ct ); - } - res = idx; /* save partial match */ + res = (res != name_ct) ? ~0 : idx; /* save partial match */ } } - /* - * no partial match -> error - */ - if (res == name_ct) { - pz_enum_err_fmt = zNoKey; - option_usage_fp = stderr; - enumError( pOpts, pOD, paz_names, (int)name_ct ); - } + if (res < name_ct) + return res; /* partial match */ - /* - * Return the matching index as a char* pointer. - * The result gets stashed in a char* pointer, so it will have to fit. - */ - return res; + pz_enum_err_fmt = (res == name_ct) ? zNoKey : zAmbigKey; + option_usage_fp = stderr; + enum_err(pOpts, pOD, paz_names, (int)name_ct); + return name_ct; } @@ -223,20 +218,18 @@ findName( * arg: tOptDesc*, pOD, enumeration option description * arg: unsigned int, enum_val, the enumeration value to map * - * ret_type: char const* + * ret_type: char const * * ret_desc: the enumeration name from const memory * * doc: This converts an enumeration value into the matching string. =*/ -char const* -optionKeywordName( - tOptDesc* pOD, - unsigned int enum_val ) +char const * +optionKeywordName(tOptDesc * pOD, unsigned int enum_val) { tOptDesc od; od.optArg.argEnum = enum_val; - (*(pOD->pOptProc))( (void*)(2UL), &od ); + (*(pOD->pOptProc))(OPTPROC_RETURN_VALNAME, &od ); return od.optArg.argString; } @@ -260,11 +253,8 @@ optionKeywordName( * if there is only one partial match. =*/ uintptr_t -optionEnumerationVal( - tOptions* pOpts, - tOptDesc* pOD, - tCC * const * paz_names, - unsigned int name_ct ) +optionEnumerationVal(tOptions * pOpts, tOptDesc * pOD, + char const * const * paz_names, unsigned int name_ct) { uintptr_t res = 0UL; @@ -273,28 +263,28 @@ optionEnumerationVal( * then it is some sort of special request. */ switch ((uintptr_t)pOpts) { - case 0UL: + case (uintptr_t)OPTPROC_EMIT_USAGE: /* * print the list of enumeration names. */ - enumError( pOpts, pOD, paz_names, (int)name_ct ); + enum_err(pOpts, pOD, paz_names, (int)name_ct); break; - case 1UL: + case (uintptr_t)OPTPROC_EMIT_SHELL: { unsigned int ix = pOD->optArg.argEnum; /* * print the name string. */ if (ix >= name_ct) - printf( "INVALID-%d", ix ); + printf("INVALID-%d", ix); else - fputs( paz_names[ ix ], stdout ); + fputs(paz_names[ ix ], stdout); break; } - case 2UL: + case (uintptr_t)OPTPROC_RETURN_VALNAME: { tSCC zInval[] = "*INVALID*"; unsigned int ix = pOD->optArg.argEnum; @@ -304,12 +294,12 @@ optionEnumerationVal( if (ix >= name_ct) return (uintptr_t)zInval; - res = (uintptr_t)paz_names[ ix ]; + pOD->optArg.argString = paz_names[ix]; break; } default: - res = findName( pOD->optArg.argString, pOpts, pOD, paz_names, name_ct ); + res = find_name(pOD->optArg.argString, pOpts, pOD, paz_names, name_ct); if (pOD->fOptState & OPTST_ALLOC_ARG) { AGFREE(pOD->optArg.argString); @@ -321,6 +311,89 @@ optionEnumerationVal( return res; } +static void +set_memb_usage(tOptions * pOpts, tOptDesc * pOD, char const * const * paz_names, + unsigned int name_ct) +{ + /* + * print the list of enumeration names. + */ + enum_err(OPTPROC_EMIT_USAGE, pOD, paz_names, (int)name_ct ); +} + +static void +set_memb_shell(tOptions * pOpts, tOptDesc * pOD, char const * const * paz_names, + unsigned int name_ct) +{ + /* + * print the name string. + */ + int ix = 0; + uintptr_t bits = (uintptr_t)pOD->optCookie; + size_t len = 0; + + bits &= ((uintptr_t)1 << (uintptr_t)name_ct) - (uintptr_t)1; + + while (bits != 0) { + if (bits & 1) { + if (len++ > 0) fputs(" | ", stdout); + fputs(paz_names[ix], stdout); + } + if (++ix >= name_ct) break; + bits >>= 1; + } +} + +static void +set_memb_names(tOptions * pOpts, tOptDesc * pOD, char const * const * paz_names, + unsigned int name_ct) +{ + static char const none[] = "none"; + static char const plus[3] = " + "; + + char * pz; + uintptr_t bits = (uintptr_t)pOD->optCookie; + int ix = 0; + size_t len = sizeof(none); + + bits &= ((uintptr_t)1 << (uintptr_t)name_ct) - (uintptr_t)1; + + /* + * Replace the enumeration value with the name string. + * First, determine the needed length, then allocate and fill in. + */ + while (bits != 0) { + if (bits & 1) + len += strlen(paz_names[ix]) + sizeof(plus); + if (++ix >= name_ct) break; + bits >>= 1; + } + + pOD->optArg.argString = pz = AGALOC(len, "enum name"); + + /* + * 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, sizeof(none)-1); + pz += sizeof(none)-1; + bits = (uintptr_t)pOD->optCookie; + bits &= ((uintptr_t)1 << (uintptr_t)name_ct) - (uintptr_t)1; + ix = 0; + + while (bits != 0) { + if (bits & 1) { + size_t nln = strlen(paz_names[ix]); + memcpy(pz, plus, sizeof(plus)); + memcpy(pz+sizeof(plus), paz_names[ix], nln); + pz += strlen(paz_names[ix]) + 3; + } + if (++ix >= name_ct) break; + bits >>= 1; + } + *pz = NUL; +} /*=export_func optionSetMembers * what: Convert between bit flag values and strings @@ -339,91 +412,35 @@ optionEnumerationVal( * if there is only one partial match. =*/ void -optionSetMembers( - tOptions* pOpts, - tOptDesc* pOD, - tCC* const * paz_names, - unsigned int name_ct ) +optionSetMembers(tOptions * pOpts, tOptDesc * pOD, + char const* const * paz_names, unsigned int name_ct) { /* * IF the program option descriptor pointer is invalid, * then it is some sort of special request. */ switch ((uintptr_t)pOpts) { - case 0UL: - /* - * print the list of enumeration names. - */ - enumError( pOpts, pOD, paz_names, (int)name_ct ); + case (uintptr_t)OPTPROC_EMIT_USAGE: + set_memb_usage(pOpts, pOD, paz_names, name_ct); return; - case 1UL: - { - /* - * print the name string. - */ - uintptr_t bits = (uintptr_t)pOD->optCookie; - uintptr_t res = 0; - size_t len = 0; - - while (bits != 0) { - if (bits & 1) { - if (len++ > 0) fputs( " | ", stdout ); - fputs( paz_names[ res ], stdout ); - } - if (++res >= name_ct) break; - bits >>= 1; - } + case (uintptr_t)OPTPROC_EMIT_SHELL: + set_memb_shell(pOpts, pOD, paz_names, name_ct); return; - } - case 2UL: - { - char* pz; - uintptr_t bits = (uintptr_t)pOD->optCookie; - uintptr_t res = 0; - size_t len = 0; - - /* - * Replace the enumeration value with the name string. - * First, determine the needed length, then allocate and fill in. - */ - while (bits != 0) { - if (bits & 1) - len += strlen( paz_names[ res ]) + 8; - if (++res >= name_ct) break; - bits >>= 1; - } - - pOD->optArg.argString = pz = AGALOC( len, "enum name" ); - - /* - * 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. - */ - strcpy( pz, "none" ); - pz += 4; - bits = (uintptr_t)pOD->optCookie; - res = 0; - while (bits != 0) { - if (bits & 1) { - strcpy( pz, " + " ); - strcpy( pz+3, paz_names[ res ]); - pz += strlen( paz_names[ res ]) + 3; - } - if (++res >= name_ct) break; - bits >>= 1; - } + case (uintptr_t)OPTPROC_RETURN_VALNAME: + set_memb_names(pOpts, pOD, paz_names, name_ct); return; - } default: break; } + if ((pOD->fOptState & OPTST_RESET) != 0) + return; + { - tCC* pzArg = pOD->optArg.argString; + char const* pzArg = pOD->optArg.argString; uintptr_t res; if ((pzArg == NULL) || (*pzArg == NUL)) { pOD->optCookie = (void*)0; @@ -435,42 +452,49 @@ optionSetMembers( tSCC zSpn[] = " ,|+\t\r\f\n"; int iv, len; - pzArg += strspn( pzArg, zSpn ); + pzArg += strspn(pzArg, zSpn); iv = (*pzArg == '!'); if (iv) - pzArg += strspn( pzArg+1, zSpn ) + 1; + pzArg += strspn(pzArg+1, zSpn) + 1; - len = strcspn( pzArg, zSpn ); + len = strcspn(pzArg, zSpn); if (len == 0) break; - if ((len == 3) && (strncmp(pzArg, zAll, (size_t)3) == 0)) { + if ((len == 3) && (strncmp(pzArg, zAll, 3) == 0)) { if (iv) res = 0; else res = ~0UL; } - else if ((len == 4) && (strncmp(pzArg, zNone, (size_t)4) == 0)) { + else if ((len == 4) && (strncmp(pzArg, zNone, 4) == 0)) { if (! iv) res = 0; } else do { char* pz; - uintptr_t bit = strtoul( pzArg, &pz, 0 ); + uintptr_t bit = strtoul(pzArg, &pz, 0); if (pz != pzArg + len) { char z[ AO_NAME_SIZE ]; - tCC* p; + char const* p; + int shift_ct; + if (*pz != NUL) { if (len >= AO_NAME_LIMIT) break; - strncpy( z, pzArg, (size_t)len ); + memcpy(z, pzArg, (size_t)len); z[len] = NUL; p = z; } else { p = pzArg; } - bit = 1UL << findName(p, pOpts, pOD, paz_names, name_ct); + shift_ct = find_name(p, pOpts, pOD, paz_names, name_ct); + if (shift_ct >= name_ct) { + pOD->optCookie = (void*)0; + return; + } + bit = 1UL << shift_ct; } if (iv) res &= ~bit; @@ -481,7 +505,7 @@ optionSetMembers( break; pzArg += len + 1; } - if (name_ct < (8 * sizeof( uintptr_t ))) { + if (name_ct < (8 * sizeof(uintptr_t))) { res &= (1UL << name_ct) - 1UL; } |