⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 enumeration.c

📁 基于ntp协议的网络时间服务程序
💻 C
字号:
/* *  $Id: enumeration.c,v 4.17 2007/02/04 17:44:12 bkorb Exp $ * Time-stamp:      "2007-01-13 10:22:35 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. * *  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. * * As a special exception, Bruce Korb gives permission for additional * uses of the text contained in his release of AutoOpts. * * 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. * * This exception does not however invalidate any other reasons why * the executable file might be covered by the GNU General Public License. * * 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. */tSCC*  pz_enum_err_fmt;/* = = = START-STATIC-FORWARD = = = *//* static forward declarations maintained by :mkfwd */static voidenumError(    tOptions*     pOpts,    tOptDesc*     pOD,    tCC* const *  paz_names,    int           name_ct );static uintptr_tfindName(    tCC*          pzName,    tOptions*     pOpts,    tOptDesc*     pOD,    tCC* const *  paz_names,    unsigned int  name_ct );/* = = = END-STATIC-FORWARD = = = */static voidenumError(    tOptions*     pOpts,    tOptDesc*     pOD,    tCC* const *  paz_names,    int           name_ct ){    size_t max_len = 0;    size_t ttl_len = 0;    if (pOpts != NULL)        fprintf( option_usage_fp, pz_enum_err_fmt, pOpts->pzProgName,                 pOD->optArg.argString, pOD->pz_Name );    fprintf( option_usage_fp, zValidKeys, pOD->pz_Name );    if (**paz_names == 0x7F) {        paz_names++;        name_ct--;    }    /*     *  Figure out the maximum length of any name, plus the total length     *  of all the names.     */    {        tCC * const * paz = paz_names;        int   ct  = name_ct;        do  {            size_t len = strlen( *(paz++) ) + 1;            if (len > max_len)                max_len = len;            ttl_len += len;        } while (--ct > 0);    }    /*     *  IF any one entry is about 1/2 line or longer, print one per line     */    if (max_len > 35) {        do  {            fprintf( option_usage_fp, "  %s\n", *(paz_names++) );        } while (--name_ct > 0);    }    /*     *  ELSE IF they all fit on one line, then do so.     */    else if (ttl_len < 76) {        fputc( ' ', option_usage_fp );        do  {            fputc( ' ', option_usage_fp );            fputs( *(paz_names++), option_usage_fp );        } while (--name_ct > 0);        fputc( '\n', option_usage_fp );    }    /*     *  Otherwise, columnize the output     */    else {        int   ent_no = 0;        char  zFmt[16];  /* format for all-but-last entries on a line */        sprintf( zFmt, "%%-%ds", (int)max_len );        max_len = 78 / max_len; /* max_len is now max entries on a line */        fputs( "  ", option_usage_fp );        /*         *  Loop through all but the last entry         */        while (--name_ct > 0) {            if (++ent_no == max_len) {                /*                 *  Last entry on a line.  Start next line, too.                 */                fprintf( option_usage_fp, "%s\n  ", *(paz_names++) );                ent_no = 0;            }            else                fprintf( option_usage_fp, zFmt, *(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 );}static uintptr_tfindName(    tCC*          pzName,    tOptions*     pOpts,    tOptDesc*     pOD,    tCC* const *  paz_names,    unsigned int  name_ct ){    uintptr_t     res = name_ct;    size_t        len = strlen( (char*)pzName );    uintptr_t     idx;    /*     *  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 (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 */        }    }    /*     *  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 );    }    /*     *  Return the matching index as a char* pointer.     *  The result gets stashed in a char* pointer, so it will have to fit.     */    return res;}/*=export_func  optionKeywordName * what:  Convert between enumeration values and strings * private: * * arg:   tOptDesc*,     pOD,       enumeration option description * arg:   unsigned int,  enum_val,  the enumeration value to map * * 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 ){    tOptDesc od;    od.optArg.argEnum = enum_val;    (*(pOD->pOptProc))( (void*)(2UL), &od );    return od.optArg.argString;}/*=export_func  optionEnumerationVal * what:  Convert from a string to an enumeration value * private: * * arg:   tOptions*,     pOpts,     the program options descriptor * arg:   tOptDesc*,     pOD,       enumeration option description * arg:   char const * const *,  paz_names, list of enumeration names * arg:   unsigned int,  name_ct,   number of names in list * * ret_type:  uintptr_t * ret_desc:  the enumeration value * * doc:   This converts the optArg.argString string from the option description *        into the index corresponding to an entry in the name list. *        This will match the generated enumeration value. *        Full matches are always accepted.  Partial matches are accepted *        if there is only one partial match.=*/uintptr_toptionEnumerationVal(    tOptions*     pOpts,    tOptDesc*     pOD,    tCC * const * paz_names,    unsigned int  name_ct ){    uintptr_t res = 0UL;    /*     *  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 );        break;    case 1UL:    {        unsigned int ix = pOD->optArg.argEnum;        /*         *  print the name string.         */        if (ix >= name_ct)            printf( "INVALID-%d", ix );        else            fputs( paz_names[ ix ], stdout );        break;    }    case 2UL:    {        tSCC zInval[] = "*INVALID*";        unsigned int ix = pOD->optArg.argEnum;        /*         *  Replace the enumeration value with the name string.         */        if (ix >= name_ct)            return (uintptr_t)zInval;        res = (uintptr_t)paz_names[ ix ];        break;    }    default:        res = findName( pOD->optArg.argString, pOpts, pOD, paz_names, name_ct );        if (pOD->fOptState & OPTST_ALLOC_ARG) {            AGFREE(pOD->optArg.argString);            pOD->fOptState &= ~OPTST_ALLOC_ARG;            pOD->optArg.argString = NULL;        }    }    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:   char const * const *, *                       paz_names, list of enumeration names * arg:   unsigned int,  name_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. *        This will match the generated enumeration value. *        Full matches are always accepted.  Partial matches are accepted *        if there is only one partial match.=*/voidoptionSetMembers(    tOptions*     pOpts,    tOptDesc*     pOD,    tCC* 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 );        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;        }        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;        }        return;    }    default:        break;    }    {        tCC*      pzArg = pOD->optArg.argString;        uintptr_t res;        if ((pzArg == NULL) || (*pzArg == NUL)) {            pOD->optCookie = (void*)0;            return;        }        res = (uintptr_t)pOD->optCookie;        for (;;) {            tSCC zSpn[] = " ,|+\t\r\f\n";            int  iv, len;            pzArg += strspn( pzArg, zSpn );            iv = (*pzArg == '!');            if (iv)                pzArg += strspn( pzArg+1, zSpn ) + 1;            len = strcspn( pzArg, zSpn );            if (len == 0)                break;            if ((len == 3) && (strncmp(pzArg, zAll, (size_t)3) == 0)) {                if (iv)                     res = 0;                else res = ~0UL;            }            else if ((len == 4) && (strncmp(pzArg, zNone, (size_t)4) == 0)) {                if (! iv)                    res = 0;            }            else do {                char* pz;                uintptr_t bit = strtoul( pzArg, &pz, 0 );                if (pz != pzArg + len) {                    char z[ AO_NAME_SIZE ];                    tCC* p;                    if (*pz != NUL) {                        if (len >= AO_NAME_LIMIT)                            break;                        strncpy( z, pzArg, (size_t)len );                        z[len] = NUL;                        p = z;                    } else {                        p = pzArg;                    }                    bit = 1UL << findName(p, pOpts, pOD, paz_names, name_ct);                }                if (iv)                     res &= ~bit;                else res |= bit;            } while (0);            if (pzArg[len] == NUL)                break;            pzArg += len + 1;        }        if (name_ct < (8 * sizeof( uintptr_t ))) {            res &= (1UL << name_ct) - 1UL;        }        pOD->optCookie = (void*)res;    }}/* * Local Variables: * mode: C * c-file-style: "stroustrup" * indent-tabs-mode: nil * End: * end of autoopts/enumeration.c */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -