aboutsummaryrefslogtreecommitdiff
path: root/sntp/libopts/nested.c
diff options
context:
space:
mode:
Diffstat (limited to 'sntp/libopts/nested.c')
-rw-r--r--sntp/libopts/nested.c538
1 files changed, 314 insertions, 224 deletions
diff --git a/sntp/libopts/nested.c b/sntp/libopts/nested.c
index b39f8d1faddb..f9f7e7ae7b80 100644
--- a/sntp/libopts/nested.c
+++ b/sntp/libopts/nested.c
@@ -1,122 +1,123 @@
-/*
- * $Id: nested.c,v 4.14 2007/02/04 17:44:12 bkorb Exp $
- * Time-stamp: "2007-01-26 11:04:35 bkorb"
+/**
+ * \file nested.c
*
- * 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.
+ * Time-stamp: "2010-08-22 11:17:56 bkorb"
*
- * 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.
+ * Automated Options Nested Values module.
*
- * 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.
+ * 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
*
- * As a special exception, Bruce Korb gives permission for additional
- * uses of the text contained in his release of AutoOpts.
+ * 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.
*
- * 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 GNU Lesser General Public License, version 3 or later
+ * See the files "COPYING.lgplv3" and "COPYING.gplv3"
*
- * This exception does not however invalidate any other reasons why
- * the executable file might be covered by the GNU General Public License.
+ * The Modified Berkeley Software Distribution License
+ * See the file "COPYING.mbsd"
*
- * 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.
+ * These files have the following md5sums:
*
- * 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
*/
+
+typedef struct {
+ int xml_ch;
+ int xml_len;
+ char xml_txt[8];
+} xml_xlate_t;
+
+static xml_xlate_t const xml_xlate[] = {
+ { '&', 4, "amp;" },
+ { '<', 3, "lt;" },
+ { '>', 3, "gt;" },
+ { '"', 5, "quot;" },
+ { '\'',5, "apos;" }
+};
+
/* = = = START-STATIC-FORWARD = = = */
-/* static forward declarations maintained by :mkfwd */
static void
-removeBackslashes( char* pzSrc );
+remove_continuation(char* pzSrc);
static char const*
-scanQuotedString( char const* pzTxt );
+scan_q_str(char const* pzTxt);
static tOptionValue*
-addStringValue( void** pp, char const* pzName, size_t nameLen,
- char const* pzValue, size_t dataLen );
+add_string(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 );
+add_bool(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 );
+add_number(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 );
+add_nested(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 *
+scan_name(char const* pzName, tOptionValue* pRes);
static char const*
-scanXmlEntry( char const* pzName, tOptionValue* pRes );
-
-static void
-unloadNestedArglist( tArgList* pAL );
+scan_xml(char const* pzName, tOptionValue* pRes);
static void
-sortNestedList( tArgList* pAL );
+sort_list(tArgList* pAL);
/* = = = END-STATIC-FORWARD = = = */
-/* removeBackslashes
- *
- * This function assumes that all newline characters were preceeded by
- * backslashes that need removal.
+/**
+ * Backslashes are used for line continuations. We keep the newline
+ * characters, but trim out the backslash:
*/
static void
-removeBackslashes( char* pzSrc )
+remove_continuation(char* pzSrc)
{
- char* pzD = strchr(pzSrc, '\n');
+ char* pzD;
- if (pzD == NULL)
- return;
- *--pzD = '\n';
+ do {
+ while (*pzSrc == '\n') pzSrc++;
+ pzD = strchr(pzSrc, '\n');
+ if (pzD == NULL)
+ return;
+ /*
+ * pzD has skipped at least one non-newline character and now
+ * points to a newline character. It now becomes the source and
+ * pzD goes to the previous character.
+ */
+ pzSrc = pzD--;
+ if (*pzD != '\\')
+ pzD++;
+ } while (pzD == pzSrc);
+
+ /*
+ * Start shifting text.
+ */
for (;;) {
char ch = ((*pzD++) = *(pzSrc++));
switch (ch) {
- case '\n': *--pzD = ch; break;
case NUL: return;
- default:
- ;
+ case '\\':
+ if (*pzSrc == '\n')
+ --pzD; /* rewrite on next iteration */
}
}
}
-
-/* scanQuotedString
- *
+/**
* Find the end of a quoted string, skipping escaped quote characters.
*/
static char const*
-scanQuotedString( char const* pzTxt )
+scan_q_str(char const* pzTxt)
{
char q = *(pzTxt++); /* remember the type of quote */
@@ -149,18 +150,17 @@ scanQuotedString( char const* pzTxt )
}
-/* 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 )
+add_string(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" );
+ pNV = AGALOC(sz, "option name/str value pair");
if (pNV == NULL)
return NULL;
@@ -170,178 +170,173 @@ addStringValue( void** pp, char const* pzName, size_t nameLen,
} else {
pNV->valType = OPARG_TYPE_STRING;
- if (dataLen > 0)
- memcpy( pNV->v.strVal, pzValue, dataLen );
- pNV->v.strVal[dataLen] = NUL;
+ if (dataLen > 0) {
+ char const * pzSrc = pzValue;
+ char * pzDst = pNV->v.strVal;
+ int ct = dataLen;
+ do {
+ int ch = *(pzSrc++) & 0xFF;
+ if (ch == NUL) goto data_copy_done;
+ if (ch == '&')
+ ch = get_special_char(&pzSrc, &ct);
+ *(pzDst++) = ch;
+ } while (--ct > 0);
+ data_copy_done:
+ *pzDst = NUL;
+
+ } else {
+ pNV->v.strVal[0] = NUL;
+ }
+
pNV->pzName = pNV->v.strVal + dataLen + 1;
}
- memcpy( pNV->pzName, pzName, nameLen );
+ memcpy(pNV->pzName, pzName, nameLen);
pNV->pzName[ nameLen ] = NUL;
- addArgListEntry( pp, pNV );
+ 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 )
+add_bool(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" );
+ pNV = AGALOC(sz, "option name/bool value pair");
if (pNV == NULL)
return NULL;
- while (isspace( (int)*pzValue ) && (dataLen > 0)) {
+ while (IS_WHITESPACE_CHAR(*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;
- }
+
+ else if (IS_DEC_DIGIT_CHAR(*pzValue))
+ pNV->v.boolVal = atoi(pzValue);
+
+ else pNV->v.boolVal = ! IS_FALSE_TYPE_CHAR(*pzValue);
pNV->valType = OPARG_TYPE_BOOLEAN;
pNV->pzName = (char*)(pNV + 1);
- memcpy( pNV->pzName, pzName, nameLen );
+ memcpy(pNV->pzName, pzName, nameLen);
pNV->pzName[ nameLen ] = NUL;
- addArgListEntry( pp, pNV );
+ 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 )
+add_number(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" );
+ pNV = AGALOC(sz, "option name/bool value pair");
if (pNV == NULL)
return NULL;
- while (isspace( (int)*pzValue ) && (dataLen > 0)) {
+ while (IS_WHITESPACE_CHAR(*pzValue) && (dataLen > 0)) {
dataLen--; pzValue++;
}
if (dataLen == 0)
- pNV->v.boolVal = 0;
+ pNV->v.longVal = 0;
else
- pNV->v.boolVal = atoi( pzValue );
+ pNV->v.longVal = strtol(pzValue, 0, 0);
pNV->valType = OPARG_TYPE_NUMERIC;
- pNV->pzName = (char*)(pNV + 1);
- memcpy( pNV->pzName, pzName, nameLen );
+ pNV->pzName = (char*)(pNV + 1);
+ memcpy(pNV->pzName, pzName, nameLen);
pNV->pzName[ nameLen ] = NUL;
- addArgListEntry( pp, pNV );
+ 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 )
+add_nested(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" );
+ 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 );
+ memcpy(pNV->pzName, pzName, nameLen);
pNV->pzName[ nameLen ] = NUL;
} else {
- pNV = optionLoadNested( pzValue, pzName, nameLen );
+ pNV = optionLoadNested(pzValue, pzName, nameLen);
}
if (pNV != NULL)
- addArgListEntry( pp, pNV );
+ 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)
+static char const *
+scan_name(char const* pzName, tOptionValue* pRes)
{
tOptionValue* pNV;
- char const * pzScan = pzName+1;
+ char const * pzScan = pzName+1; /* we know first char is a name char */
char const * pzVal;
size_t nameLen = 1;
size_t dataLen = 0;
- while (ISNAMECHAR( (int)*pzScan )) { pzScan++; nameLen++; }
+ /*
+ * Scan over characters that name a value. These names may not end
+ * with a colon, but they may contain colons.
+ */
+ while (IS_VALUE_NAME_CHAR(*pzScan)) { pzScan++; nameLen++; }
+ if (pzScan[-1] == ':') { pzScan--; nameLen--; }
+ while (IS_HORIZ_WHITE_CHAR(*pzScan)) pzScan++;
- while (isspace( (int)*pzScan )) {
- char ch = *(pzScan++);
- if ((ch == '\n') || (ch == ',')) {
- addStringValue(&(pRes->v.nestVal), pzName, nameLen, NULL,(size_t)0);
- return pzScan - 1;
- }
- }
+ re_switch:
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;
- }
+ while (IS_HORIZ_WHITE_CHAR((int)*++pzScan)) ;
+ if ((*pzScan == '=') || (*pzScan == ':'))
+ goto default_char;
+ goto re_switch;
+ case '\n':
case ',':
- comma_char:
pzScan++;
/* FALLTHROUGH */
case NUL:
- nul_byte:
- addStringValue(&(pRes->v.nestVal), pzName, nameLen, NULL, (size_t)0);
+ add_string(&(pRes->v.nestVal), pzName, nameLen, NULL, (size_t)0);
break;
case '"':
case '\'':
- quote_char:
pzVal = pzScan;
- pzScan = scanQuotedString( pzScan );
+ pzScan = scan_q_str(pzScan);
dataLen = pzScan - pzVal;
- pNV = addStringValue( &(pRes->v.nestVal), pzName, nameLen, pzVal,
- dataLen );
+ pNV = add_string(&(pRes->v.nestVal), pzName, nameLen, pzVal,
+ dataLen);
if ((pNV != NULL) && (option_load_mode == OPTION_LOAD_COOKED))
- ao_string_cook( pNV->v.strVal, NULL );
+ ao_string_cook(pNV->v.strVal, NULL);
break;
default:
@@ -370,10 +365,10 @@ scanNameEntry(char const* pzName, tOptionValue* pRes)
case ',':
dataLen = (pzScan - pzVal) - 1;
string_done:
- pNV = addStringValue( &(pRes->v.nestVal), pzName, nameLen,
- pzVal, dataLen );
+ pNV = add_string(&(pRes->v.nestVal), pzName, nameLen,
+ pzVal, dataLen);
if (pNV != NULL)
- removeBackslashes( pNV->v.strVal );
+ remove_continuation(pNV->v.strVal);
goto leave_scan_name;
}
}
@@ -383,15 +378,13 @@ scanNameEntry(char const* pzName, tOptionValue* pRes)
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 )
+scan_xml(char const* pzName, tOptionValue* pRes)
{
size_t nameLen = 1, valLen = 0;
char const* pzScan = ++pzName;
@@ -400,20 +393,20 @@ scanXmlEntry( char const* pzName, tOptionValue* pRes )
tOptionValue* pNewVal;
tOptionLoadMode save_mode = option_load_mode;
- if (! isalpha((int)*pzName)) {
+ if (! IS_VAR_FIRST_CHAR(*pzName)) {
switch (*pzName) {
default:
pzName = NULL;
break;
case '!':
- pzName = strstr( pzName, "-->" );
+ pzName = strstr(pzName, "-->");
if (pzName != NULL)
pzName += 3;
break;
case '?':
- pzName = strchr( pzName, '>' );
+ pzName = strchr(pzName, '>');
if (pzName != NULL)
pzName++;
break;
@@ -421,7 +414,8 @@ scanXmlEntry( char const* pzName, tOptionValue* pRes )
return pzName;
}
- while (isalpha( (int)*++pzScan )) nameLen++;
+ pzScan++;
+ while (IS_VALUE_NAME_CHAR((int)*pzScan)) { pzScan++; nameLen++; }
if (nameLen > 64)
return NULL;
valu.valType = OPARG_TYPE_STRING;
@@ -447,9 +441,9 @@ scanXmlEntry( char const* pzName, tOptionValue* pRes )
option_load_mode = save_mode;
return NULL;
}
- addStringValue(&(pRes->v.nestVal), pzName, nameLen, NULL, (size_t)0);
+ add_string(&(pRes->v.nestVal), pzName, nameLen, NULL, (size_t)0);
option_load_mode = save_mode;
- return pzScan+2;
+ return pzScan+1;
default:
option_load_mode = save_mode;
@@ -477,46 +471,46 @@ scanXmlEntry( char const* pzName, tOptionValue* pRes )
*(pzD++) = '>';
*pzD = NUL;
- pzScan = strstr( pzScan, z );
+ 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++;
+ while (IS_WHITESPACE_CHAR(*pzScan)) pzScan++;
}
switch (valu.valType) {
case OPARG_TYPE_NONE:
- addStringValue( &(pRes->v.nestVal), pzName, nameLen, NULL, (size_t)0);
+ add_string(&(pRes->v.nestVal), pzName, nameLen, NULL, (size_t)0);
break;
case OPARG_TYPE_STRING:
- pNewVal = addStringValue(
+ pNewVal = add_string(
&(pRes->v.nestVal), pzName, nameLen, pzVal, valLen);
if (option_load_mode == OPTION_LOAD_KEEP)
break;
- mungeString( pNewVal->v.strVal, option_load_mode );
+ mungeString(pNewVal->v.strVal, option_load_mode);
break;
case OPARG_TYPE_BOOLEAN:
- addBoolValue( &(pRes->v.nestVal), pzName, nameLen, pzVal, valLen );
+ add_bool(&(pRes->v.nestVal), pzName, nameLen, pzVal, valLen);
break;
case OPARG_TYPE_NUMERIC:
- addNumberValue( &(pRes->v.nestVal), pzName, nameLen, pzVal, valLen );
+ add_number(&(pRes->v.nestVal), pzName, nameLen, pzVal, valLen);
break;
case OPARG_TYPE_HIERARCHY:
{
- char* pz = AGALOC( valLen+1, "hierarchical scan" );
+ char* pz = AGALOC(valLen+1, "hierarchical scan");
if (pz == NULL)
break;
- memcpy( pz, pzVal, valLen );
+ memcpy(pz, pzVal, valLen);
pz[valLen] = NUL;
- addNestedValue( &(pRes->v.nestVal), pzName, nameLen, pz, valLen );
+ add_nested(&(pRes->v.nestVal), pzName, nameLen, pz, valLen);
AGFREE(pz);
break;
}
@@ -532,15 +526,14 @@ scanXmlEntry( char const* pzName, tOptionValue* pRes )
}
-/* 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 void
-unloadNestedArglist( tArgList* pAL )
+LOCAL void
+unload_arg_list(tArgList* pAL)
{
int ct = pAL->useCt;
tCC** ppNV = pAL->apzArgs;
@@ -548,14 +541,13 @@ unloadNestedArglist( tArgList* pAL )
while (ct-- > 0) {
tOptionValue* pNV = (tOptionValue*)(void*)*(ppNV++);
if (pNV->valType == OPARG_TYPE_HIERARCHY)
- unloadNestedArglist( pNV->v.nestVal );
- AGFREE( pNV );
+ unload_arg_list(pNV->v.nestVal);
+ AGFREE(pNV);
}
- AGFREE( (void*)pAL );
+ AGFREE((void*)pAL);
}
-
/*=export_func optionUnloadNested
*
* what: Deallocate the memory for a nested value
@@ -567,7 +559,7 @@ unloadNestedArglist( tArgList* pAL )
* @pxref{libopts-configFileLoad}).
=*/
void
-optionUnloadNested( tOptionValue const * pOV )
+optionUnloadNested(tOptionValue const * pOV)
{
if (pOV == NULL) return;
if (pOV->valType != OPARG_TYPE_HIERARCHY) {
@@ -575,20 +567,18 @@ optionUnloadNested( tOptionValue const * pOV )
return;
}
- unloadNestedArglist( pOV->v.nestVal );
+ unload_arg_list(pOV->v.nestVal);
- AGFREE( (void*)pOV );
+ 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 void
-sortNestedList( tArgList* pAL )
+sort_list(tArgList* pAL)
{
int ix;
int lm = pAL->useCt;
@@ -606,7 +596,7 @@ sortNestedList( tArgList* pAL )
* move the old pointer. Stop before trying to extract the
* "-1" entry.
*/
- while (strcmp( pOldNV->pzName, pNewNV->pzName ) > 0) {
+ while (strcmp(pOldNV->pzName, pNewNV->pzName) > 0) {
pAL->apzArgs[iy+1] = (void*)pOldNV;
pOldNV = (tOptionValue*)(void*)(pAL->apzArgs[--iy]);
if (iy < 0)
@@ -621,7 +611,6 @@ sortNestedList( tArgList* pAL )
}
}
-
/* optionLoadNested
* private:
*
@@ -642,7 +631,6 @@ 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.
@@ -651,60 +639,65 @@ optionLoadNested(char const* pzTxt, char const* pzName, size_t nameLen)
errno = EINVAL;
return NULL;
}
- while (isspace( (int)*pzTxt )) pzTxt++;
+ while (IS_WHITESPACE_CHAR(*pzTxt)) pzTxt++;
if (*pzTxt == NUL) {
errno = ENOENT;
return NULL;
}
- pRes = AGALOC( sizeof(*pRes) + nameLen + 1, "nested args" );
+ 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;
+ memcpy(pRes->pzName, pzName, nameLen);
+ pRes->pzName[nameLen] = NUL;
- pAL = AGALOC( sizeof(*pAL), "nested arg list" );
- if (pAL == NULL) {
- AGFREE( pRes );
- return NULL;
+ {
+ tArgList * 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;
}
- 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 );
+ while (IS_WHITESPACE_CHAR((int)*pzTxt)) pzTxt++;
+ if (IS_VAR_FIRST_CHAR((int)*pzTxt)) {
+ pzTxt = scan_name(pzTxt, pRes);
}
else switch (*pzTxt) {
case NUL: goto scan_done;
- case '<': pzTxt = scanXmlEntry( pzTxt, pRes );
+ case '<': pzTxt = scan_xml(pzTxt, pRes);
+ if (pzTxt == NULL) goto woops;
if (*pzTxt == ',') pzTxt++; break;
- case '#': pzTxt = strchr( pzTxt, '\n' ); 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;
+ {
+ tArgList * al = pRes->v.nestVal;
+ if (al->useCt != 0)
+ sort_list(al);
}
+ return pRes;
+
woops:
- AGFREE( pRes->v.nestVal );
- AGFREE( pRes );
+ AGFREE(pRes->v.nestVal);
+ AGFREE(pRes);
return NULL;
}
-
/*=export_func optionNestedVal
* private:
*
@@ -716,14 +709,111 @@ optionLoadNested(char const* pzTxt, char const* pzName, size_t nameLen)
* Nested value was found on the command line
=*/
void
-optionNestedVal( tOptions* pOpts, tOptDesc* pOD )
+optionNestedVal(tOptions* pOpts, tOptDesc* pOD)
{
- tOptionValue* pOV = optionLoadNested(
- pOD->optArg.argString, pOD->pz_Name, strlen(pOD->pz_Name));
+ if (pOpts < OPTPROC_EMIT_LIMIT)
+ return;
- if (pOV != NULL)
- addArgListEntry( &(pOD->optCookie), (void*)pOV );
+ if (pOD->fOptState & OPTST_RESET) {
+ tArgList* pAL = pOD->optCookie;
+ int ct;
+ tCC ** av;
+
+ if (pAL == NULL)
+ return;
+ ct = pAL->useCt;
+ av = pAL->apzArgs;
+
+ while (--ct >= 0) {
+ void * p = (void *)*(av++);
+ optionUnloadNested((tOptionValue const *)p);
+ }
+
+ AGFREE(pOD->optCookie);
+
+ } else {
+ tOptionValue* pOV = optionLoadNested(
+ pOD->optArg.argString, pOD->pz_Name, strlen(pOD->pz_Name));
+
+ if (pOV != NULL)
+ addArgListEntry(&(pOD->optCookie), (void*)pOV);
+ }
}
+
+/*
+ * get_special_char
+ */
+LOCAL int
+get_special_char(char const ** ppz, int * ct)
+{
+ char const * pz = *ppz;
+
+ if (*ct < 3)
+ return '&';
+
+ if (*pz == '#') {
+ int base = 10;
+ int retch;
+
+ pz++;
+ if (*pz == 'x') {
+ base = 16;
+ pz++;
+ }
+ retch = (int)strtoul(pz, (char **)&pz, base);
+ if (*pz != ';')
+ return '&';
+ base = ++pz - *ppz;
+ if (base > *ct)
+ return '&';
+
+ *ct -= base;
+ *ppz = pz;
+ return retch;
+ }
+
+ {
+ int ctr = sizeof(xml_xlate) / sizeof(xml_xlate[0]);
+ xml_xlate_t const * xlatp = xml_xlate;
+
+ for (;;) {
+ if ( (*ct >= xlatp->xml_len)
+ && (strncmp(pz, xlatp->xml_txt, xlatp->xml_len) == 0)) {
+ *ppz += xlatp->xml_len;
+ *ct -= xlatp->xml_len;
+ return xlatp->xml_ch;
+ }
+
+ if (--ctr <= 0)
+ break;
+ xlatp++;
+ }
+ }
+ return '&';
+}
+
+/*
+ * emit_special_char
+ */
+LOCAL void
+emit_special_char(FILE * fp, int ch)
+{
+ int ctr = sizeof(xml_xlate) / sizeof(xml_xlate[0]);
+ xml_xlate_t const * xlatp = xml_xlate;
+
+ putc('&', fp);
+ for (;;) {
+ if (ch == xlatp->xml_ch) {
+ fputs(xlatp->xml_txt, fp);
+ return;
+ }
+ if (--ctr <= 0)
+ break;
+ xlatp++;
+ }
+ fprintf(fp, "#x%02X;", (ch & 0xFF));
+}
+
/*
* Local Variables:
* mode: C