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

📄 nested.c

📁 基于ntp协议的网络时间服务程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  $Id: nested.c,v 4.14 2007/02/04 17:44:12 bkorb Exp $ *  Time-stamp:      "2007-01-26 11:04:35 bkorb" * *   Automated Options Nested Values module. *//* *  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. *//* = = = START-STATIC-FORWARD = = = *//* static forward declarations maintained by :mkfwd */static voidremoveBackslashes( char* pzSrc );static char const*scanQuotedString( char const* pzTxt );static tOptionValue*addStringValue( void** pp, char const* pzName, size_t nameLen,                char const* pzValue, size_t dataLen );static tOptionValue*addBoolValue( void** pp, char const* pzName, size_t nameLen,                char const* pzValue, size_t dataLen );static tOptionValue*addNumberValue( void** pp, char const* pzName, size_t nameLen,                char const* pzValue, size_t dataLen );static tOptionValue*addNestedValue( void** pp, char const* pzName, size_t nameLen,                char* pzValue, size_t dataLen );static char const*scanNameEntry(char const* pzName, tOptionValue* pRes);static char const*scanXmlEntry( char const* pzName, tOptionValue* pRes );static voidunloadNestedArglist( tArgList* pAL );static voidsortNestedList( tArgList* pAL );/* = = = END-STATIC-FORWARD = = = *//*  removeBackslashes * *  This function assumes that all newline characters were preceeded by *  backslashes that need removal. */static voidremoveBackslashes( char* pzSrc ){    char* pzD = strchr(pzSrc, '\n');    if (pzD == NULL)        return;    *--pzD = '\n';    for (;;) {        char ch = ((*pzD++) = *(pzSrc++));        switch (ch) {        case '\n': *--pzD = ch; break;        case NUL:  return;        default:            ;        }    }}/*  scanQuotedString * *  Find the end of a quoted string, skipping escaped quote characters. */static char const*scanQuotedString( char const* pzTxt ){    char q = *(pzTxt++); /* remember the type of quote */    for (;;) {        char ch = *(pzTxt++);        if (ch == NUL)            return pzTxt-1;        if (ch == q)            return pzTxt;        if (ch == '\\') {            ch = *(pzTxt++);            /*             *  IF the next character is NUL, drop the backslash, too.             */            if (ch == NUL)                return pzTxt - 2;            /*             *  IF the quote character or the escape character were escaped,             *  then skip both, as long as the string does not end.             */            if ((ch == q) || (ch == '\\')) {                if (*(pzTxt++) == NUL)                    return pzTxt-1;            }        }    }}/*  addStringValue * *  Associate a name with either a string or no value. */static tOptionValue*addStringValue( void** pp, char const* pzName, size_t nameLen,                char const* pzValue, size_t dataLen ){    tOptionValue* pNV;    size_t sz = nameLen + dataLen + sizeof(*pNV);    pNV = AGALOC( sz, "option name/str value pair" );    if (pNV == NULL)        return NULL;    if (pzValue == NULL) {        pNV->valType = OPARG_TYPE_NONE;        pNV->pzName = pNV->v.strVal;    } else {        pNV->valType = OPARG_TYPE_STRING;        if (dataLen > 0)            memcpy( pNV->v.strVal, pzValue, dataLen );        pNV->v.strVal[dataLen] = NUL;        pNV->pzName = pNV->v.strVal + dataLen + 1;    }    memcpy( pNV->pzName, pzName, nameLen );    pNV->pzName[ nameLen ] = NUL;    addArgListEntry( pp, pNV );    return pNV;}/*  addBoolValue * *  Associate a name with either a string or no value. */static tOptionValue*addBoolValue( void** pp, char const* pzName, size_t nameLen,                char const* pzValue, size_t dataLen ){    tOptionValue* pNV;    size_t sz = nameLen + sizeof(*pNV) + 1;    pNV = AGALOC( sz, "option name/bool value pair" );    if (pNV == NULL)        return NULL;    while (isspace( (int)*pzValue ) && (dataLen > 0)) {        dataLen--; pzValue++;    }    if (dataLen == 0)        pNV->v.boolVal = 0;    else if (isdigit( (int)*pzValue ))        pNV->v.boolVal = atoi( pzValue );    else switch (*pzValue) {    case 'f':    case 'F':    case 'n':    case 'N':        pNV->v.boolVal = 0; break;    default:        pNV->v.boolVal = 1;    }    pNV->valType = OPARG_TYPE_BOOLEAN;    pNV->pzName = (char*)(pNV + 1);    memcpy( pNV->pzName, pzName, nameLen );    pNV->pzName[ nameLen ] = NUL;    addArgListEntry( pp, pNV );    return pNV;}/*  addNumberValue * *  Associate a name with either a string or no value. */static tOptionValue*addNumberValue( void** pp, char const* pzName, size_t nameLen,                char const* pzValue, size_t dataLen ){    tOptionValue* pNV;    size_t sz = nameLen + sizeof(*pNV) + 1;    pNV = AGALOC( sz, "option name/bool value pair" );    if (pNV == NULL)        return NULL;    while (isspace( (int)*pzValue ) && (dataLen > 0)) {        dataLen--; pzValue++;    }    if (dataLen == 0)        pNV->v.boolVal = 0;    else        pNV->v.boolVal = atoi( pzValue );    pNV->valType = OPARG_TYPE_NUMERIC;    pNV->pzName = (char*)(pNV + 1);    memcpy( pNV->pzName, pzName, nameLen );    pNV->pzName[ nameLen ] = NUL;    addArgListEntry( pp, pNV );    return pNV;}/*  addNestedValue * *  Associate a name with either a string or no value. */static tOptionValue*addNestedValue( void** pp, char const* pzName, size_t nameLen,                char* pzValue, size_t dataLen ){    tOptionValue* pNV;    if (dataLen == 0) {        size_t sz = nameLen + sizeof(*pNV) + 1;        pNV = AGALOC( sz, "empty nested value pair" );        if (pNV == NULL)            return NULL;        pNV->v.nestVal = NULL;        pNV->valType = OPARG_TYPE_HIERARCHY;        pNV->pzName = (char*)(pNV + 1);        memcpy( pNV->pzName, pzName, nameLen );        pNV->pzName[ nameLen ] = NUL;    } else {        pNV = optionLoadNested( pzValue, pzName, nameLen );    }    if (pNV != NULL)        addArgListEntry( pp, pNV );    return pNV;}/*  scanNameEntry * *  We have an entry that starts with a name.  Find the end of it, cook it *  (if called for) and create the name/value association. */static char const*scanNameEntry(char const* pzName, tOptionValue* pRes){    tOptionValue* pNV;    char const * pzScan = pzName+1;    char const * pzVal;    size_t       nameLen = 1;    size_t       dataLen = 0;    while (ISNAMECHAR( (int)*pzScan ))  { pzScan++; nameLen++; }    while (isspace( (int)*pzScan )) {        char ch = *(pzScan++);        if ((ch == '\n') || (ch == ',')) {            addStringValue(&(pRes->v.nestVal), pzName, nameLen, NULL,(size_t)0);            return pzScan - 1;        }    }    switch (*pzScan) {    case '=':    case ':':        while (isspace( (int)*++pzScan ))  ;        switch (*pzScan) {        case ',':  goto comma_char;        case '"':        case '\'': goto quote_char;        case NUL:  goto nul_byte;        default:   goto default_char;        }    case ',':    comma_char:        pzScan++;        /* FALLTHROUGH */    case NUL:    nul_byte:        addStringValue(&(pRes->v.nestVal), pzName, nameLen, NULL, (size_t)0);        break;    case '"':    case '\'':    quote_char:        pzVal = pzScan;        pzScan = scanQuotedString( pzScan );        dataLen = pzScan - pzVal;        pNV = addStringValue( &(pRes->v.nestVal), pzName, nameLen, pzVal,                              dataLen );        if ((pNV != NULL) && (option_load_mode == OPTION_LOAD_COOKED))            ao_string_cook( pNV->v.strVal, NULL );        break;    default:    default_char:        /*         *  We have found some strange text value.  It ends with a newline         *  or a comma.         */        pzVal = pzScan;        for (;;) {            char ch = *(pzScan++);            switch (ch) {            case NUL:                pzScan--;                dataLen = pzScan - pzVal;                goto string_done;                /* FALLTHROUGH */            case '\n':                if (   (pzScan > pzVal + 2)                    && (pzScan[-2] == '\\')                    && (pzScan[ 0] != NUL))                    continue;

⌨️ 快捷键说明

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