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

📄 nested.c

📁 基于ntp协议的网络时间服务程序
💻 C
📖 第 1 页 / 共 2 页
字号:
                /* FALLTHROUGH */            case ',':                dataLen = (pzScan - pzVal) - 1;            string_done:                pNV = addStringValue( &(pRes->v.nestVal), pzName, nameLen,                                      pzVal, dataLen );                if (pNV != NULL)                    removeBackslashes( pNV->v.strVal );                goto leave_scan_name;            }        }        break;    } leave_scan_name:;    return pzScan;}/*  scanXmlEntry * *  We've found a '<' character.  We ignore this if it is a comment or a *  directive.  If it is something else, then whatever it is we are looking *  at is bogus.  Returning NULL stops processing. */static char const*scanXmlEntry( char const* pzName, tOptionValue* pRes ){    size_t nameLen = 1, valLen = 0;    char const*   pzScan = ++pzName;    char const*   pzVal;    tOptionValue  valu;    tOptionValue* pNewVal;    tOptionLoadMode save_mode = option_load_mode;    if (! isalpha((int)*pzName)) {        switch (*pzName) {        default:            pzName = NULL;            break;        case '!':            pzName = strstr( pzName, "-->" );            if (pzName != NULL)                pzName += 3;            break;        case '?':            pzName = strchr( pzName, '>' );            if (pzName != NULL)                pzName++;            break;        }        return pzName;    }    while (isalpha( (int)*++pzScan ))  nameLen++;    if (nameLen > 64)        return NULL;    valu.valType = OPARG_TYPE_STRING;    switch (*pzScan) {    case ' ':    case '\t':        pzScan = parseAttributes(            NULL, (char*)pzScan, &option_load_mode, &valu );        if (*pzScan == '>') {            pzScan++;            break;        }        if (*pzScan != '/') {            option_load_mode = save_mode;            return NULL;        }        /* FALLTHROUGH */    case '/':        if (*++pzScan != '>') {            option_load_mode = save_mode;            return NULL;        }        addStringValue(&(pRes->v.nestVal), pzName, nameLen, NULL, (size_t)0);        option_load_mode = save_mode;        return pzScan+2;    default:        option_load_mode = save_mode;        return NULL;    case '>':        pzScan++;        break;    }    pzVal = pzScan;    {        char z[68];        char* pzD = z;        int  ct = nameLen;        char const* pzS = pzName;        *(pzD++) = '<';        *(pzD++) = '/';        do  {            *(pzD++) = *(pzS++);        } while (--ct > 0);        *(pzD++) = '>';        *pzD = NUL;        pzScan = strstr( pzScan, z );        if (pzScan == NULL) {            option_load_mode = save_mode;            return NULL;        }        valLen = (pzScan - pzVal);        pzScan += nameLen + 3;        while (isspace(  (int)*pzScan ))  pzScan++;    }    switch (valu.valType) {    case OPARG_TYPE_NONE:        addStringValue( &(pRes->v.nestVal), pzName, nameLen, NULL, (size_t)0);        break;    case OPARG_TYPE_STRING:        pNewVal = addStringValue(            &(pRes->v.nestVal), pzName, nameLen, pzVal, valLen);        if (option_load_mode == OPTION_LOAD_KEEP)            break;        mungeString( pNewVal->v.strVal, option_load_mode );        break;    case OPARG_TYPE_BOOLEAN:        addBoolValue( &(pRes->v.nestVal), pzName, nameLen, pzVal, valLen );        break;    case OPARG_TYPE_NUMERIC:        addNumberValue( &(pRes->v.nestVal), pzName, nameLen, pzVal, valLen );        break;    case OPARG_TYPE_HIERARCHY:    {        char* pz = AGALOC( valLen+1, "hierarchical scan" );        if (pz == NULL)            break;        memcpy( pz, pzVal, valLen );        pz[valLen] = NUL;        addNestedValue( &(pRes->v.nestVal), pzName, nameLen, pz, valLen );        AGFREE(pz);        break;    }    case OPARG_TYPE_ENUMERATION:    case OPARG_TYPE_MEMBERSHIP:    default:        break;    }    option_load_mode = save_mode;    return pzScan;}/*  unloadNestedArglist * *  Deallocate a list of option arguments.  This must have been gotten from *  a hierarchical option argument, not a stacked list of strings.  It is *  an internal call, so it is not validated.  The caller is responsible for *  knowing what they are doing. */static voidunloadNestedArglist( tArgList* pAL ){    int ct = pAL->useCt;    tCC** ppNV = pAL->apzArgs;    while (ct-- > 0) {        tOptionValue* pNV = (tOptionValue*)(void*)*(ppNV++);        if (pNV->valType == OPARG_TYPE_HIERARCHY)            unloadNestedArglist( pNV->v.nestVal );        AGFREE( pNV );    }    AGFREE( (void*)pAL );}/*=export_func  optionUnloadNested * * what:  Deallocate the memory for a nested value * arg:   + tOptionValue const * + pOptVal + the hierarchical value + * * doc: *  A nested value needs to be deallocated.  The pointer passed in should *  have been gotten from a call to @code{configFileLoad()} (See *  @pxref{libopts-configFileLoad}).=*/voidoptionUnloadNested( tOptionValue const * pOV ){    if (pOV == NULL) return;    if (pOV->valType != OPARG_TYPE_HIERARCHY) {        errno = EINVAL;        return;    }    unloadNestedArglist( pOV->v.nestVal );    AGFREE( (void*)pOV );}/*  sortNestedList * *  This is a _stable_ sort.  The entries are sorted alphabetically, *  but within entries of the same name the ordering is unchanged. *  Typically, we also hope the input is sorted. */static voidsortNestedList( tArgList* pAL ){    int ix;    int lm = pAL->useCt;    /*     *  This loop iterates "useCt" - 1 times.     */    for (ix = 0; ++ix < lm;) {        int iy = ix-1;        tOptionValue* pNewNV = (tOptionValue*)(void*)(pAL->apzArgs[ix]);        tOptionValue* pOldNV = (tOptionValue*)(void*)(pAL->apzArgs[iy]);        /*         *  For as long as the new entry precedes the "old" entry,         *  move the old pointer.  Stop before trying to extract the         *  "-1" entry.         */        while (strcmp( pOldNV->pzName, pNewNV->pzName ) > 0) {            pAL->apzArgs[iy+1] = (void*)pOldNV;            pOldNV = (tOptionValue*)(void*)(pAL->apzArgs[--iy]);            if (iy < 0)                break;        }        /*         *  Always store the pointer.  Sometimes it is redundant,         *  but the redundancy is cheaper than a test and branch sequence.         */        pAL->apzArgs[iy+1] = (void*)pNewNV;    }}/* optionLoadNested * private: * * what:  parse a hierarchical option argument * arg:   + char const*     + pzTxt   + the text to scan + * arg:   + char const*     + pzName  + the name for the text + * arg:   + size_t          + nameLen + the length of "name"  + * * ret_type:  tOptionValue* * ret_desc:  An allocated, compound value structure * * doc: *  A block of text represents a series of values.  It may be an *  entire configuration file, or it may be an argument to an *  option that takes a hierarchical value. */LOCAL tOptionValue*optionLoadNested(char const* pzTxt, char const* pzName, size_t nameLen){    tOptionValue* pRes;    tArgList*     pAL;    /*     *  Make sure we have some data and we have space to put what we find.     */    if (pzTxt == NULL) {        errno = EINVAL;        return NULL;    }    while (isspace( (int)*pzTxt ))  pzTxt++;    if (*pzTxt == NUL) {        errno = ENOENT;        return NULL;    }    pRes = AGALOC( sizeof(*pRes) + nameLen + 1, "nested args" );    if (pRes == NULL) {        errno = ENOMEM;        return NULL;    }    pRes->valType   = OPARG_TYPE_HIERARCHY;    pRes->pzName    = (char*)(pRes + 1);    memcpy( pRes->pzName, pzName, nameLen );    pRes->pzName[ nameLen ] = NUL;    pAL = AGALOC( sizeof(*pAL), "nested arg list" );    if (pAL == NULL) {        AGFREE( pRes );        return NULL;    }    pRes->v.nestVal = pAL;    pAL->useCt   = 0;    pAL->allocCt = MIN_ARG_ALLOC_CT;    /*     *  Scan until we hit a NUL.     */    do  {        while (isspace( (int)*pzTxt ))  pzTxt++;        if (isalpha( (int)*pzTxt )) {            pzTxt = scanNameEntry( pzTxt, pRes );        }        else switch (*pzTxt) {        case NUL: goto scan_done;        case '<': pzTxt = scanXmlEntry( pzTxt, pRes );                  if (*pzTxt == ',') pzTxt++;     break;        case '#': pzTxt = strchr( pzTxt, '\n' );  break;        default:  goto woops;        }    } while (pzTxt != NULL); scan_done:;    pAL = pRes->v.nestVal;    if (pAL->useCt != 0) {        sortNestedList( pAL );        return pRes;    } woops:    AGFREE( pRes->v.nestVal );    AGFREE( pRes );    return NULL;}/*=export_func  optionNestedVal * private: * * what:  parse a hierarchical option argument * arg:   + tOptions* + pOpts    + program options descriptor + * arg:   + tOptDesc* + pOptDesc + the descriptor for this arg + * * doc: *  Nested value was found on the command line=*/voidoptionNestedVal( tOptions* pOpts, tOptDesc* pOD ){    tOptionValue* pOV = optionLoadNested(        pOD->optArg.argString, pOD->pz_Name, strlen(pOD->pz_Name));    if (pOV != NULL)        addArgListEntry( &(pOD->optCookie), (void*)pOV );}/* * Local Variables: * mode: C * c-file-style: "stroustrup" * indent-tabs-mode: nil * End: * end of autoopts/nested.c */

⌨️ 快捷键说明

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