Пример #1
0
/**
 *  Scan off the xml element name, and the rest of the header, too.
 *  Set the value type to NONE if it ends with "/>".
 *
 * @param[in]  name    the first name character (alphabetic)
 * @param[out] nm_len  the length of the name
 * @param[out] val     set valType field to STRING or NONE.
 *
 * @returns the scan resumption point, or NULL on error
 */
static char const *
scan_xml_name(char const * name, size_t * nm_len, tOptionValue * val)
{
    char const * scan = SPN_VALUE_NAME_CHARS(name + 1);
    *nm_len = (size_t)(scan - name);
    if (*nm_len > 64)
        return NULL;
    val->valType = OPARG_TYPE_STRING;

    if (IS_WHITESPACE_CHAR(*scan)) {
        /*
         * There are attributes following the name.  Parse 'em.
         */
        scan = SPN_WHITESPACE_CHARS(scan);
        scan = parse_attrs(NULL, scan, &option_load_mode, val);
        if (scan == NULL)
            return NULL; /* oops */
    }

    if (! IS_END_XML_TOKEN_CHAR(*scan))
        return NULL; /* oops */

    if (*scan == '/') {
        /*
         * Single element XML entries get inserted as an empty string.
         */
        if (*++scan != '>')
            return NULL;
        val->valType = OPARG_TYPE_NONE;
    }
    return scan+1;
}
Пример #2
0
/**
 *  "txt" points to a '<' character, followed by an alpha.
 *  The end of the entry is either the "/>" following the name, or else a
 *  "</name>" string.
 */
static char *
handle_struct(tOptions * opts, tOptState * ost, char * txt, int dir)
{
    tOptionLoadMode mode = option_load_mode;
    tOptionValue    valu;

    char* pzName = ++txt;
    char* pzData;
    char* pcNulPoint;

    txt = SPN_VALUE_NAME_CHARS(txt);
    pcNulPoint = txt;
    valu.valType = OPARG_TYPE_STRING;

    switch (*txt) {
    case ' ':
    case '\t':
        txt = (void *)parse_attrs(
            opts, SPN_WHITESPACE_CHARS(txt), &mode, &valu);
        if (txt == NULL)
            return txt;
        if (*txt == '>')
            break;
        if (*txt != '/')
            return NULL;
        /* FALLTHROUGH */

    case '/':
        if (txt[1] != '>')
            return NULL;
        *txt = NUL;
        txt += 2;
        loadOptionLine(opts, ost, pzName, dir, mode);
        return txt;

    case '>':
        break;

    default:
        txt = strchr(txt, '>');
        if (txt != NULL)
            txt++;
        return txt;
    }

    /*
     *  If we are here, we have a value.  "txt" points to a closing angle
     *  bracket.  Separate the name from the value for a moment.
     */
    *pcNulPoint = NUL;
    pzData = ++txt;
    txt = trim_xml_text(txt, pzName, mode);
    if (txt == NULL)
        return txt;

    /*
     *  Rejoin the name and value for parsing by "loadOptionLine()".
     *  Erase any attributes parsed by "parse_attrs()".
     */
    memset(pcNulPoint, ' ', (size_t)(pzData - pcNulPoint));

    /*
     *  If we are getting a "string" value that is to be cooked,
     *  then process the XML-ish &xx; XML-ish and %XX hex characters.
     */
    if (  (valu.valType == OPARG_TYPE_STRING)
       && (mode == OPTION_LOAD_COOKED))
        cook_xml_text(pzData);

    /*
     *  "pzName" points to what looks like text for one option/configurable.
     *  It is NUL terminated.  Process it.
     */
    loadOptionLine(opts, ost, pzName, dir, mode);

    return txt;
}
Пример #3
0
/**
 *  "txt" points to the start of some value name.
 *  The end of the entry is the end of the line that is not preceded by
 *  a backslash escape character.  The string value is always processed
 *  in "cooked" mode.
 */
static char *
handle_cfg(tOptions * opts, tOptState * ost, char * txt, int dir)
{
    char* pzName = txt++;
    char* pzEnd  = strchr(txt, NL);

    if (pzEnd == NULL)
        return txt + strlen(txt);

    txt = SPN_VALUE_NAME_CHARS(txt);
    txt = SPN_WHITESPACE_CHARS(txt);
    if (txt > pzEnd) {
    name_only:
        *pzEnd++ = NUL;
        loadOptionLine(opts, ost, pzName, dir, OPTION_LOAD_UNCOOKED);
        return pzEnd;
    }

    /*
     *  Either the first character after the name is a ':' or '=',
     *  or else we must have skipped over white space.  Anything else
     *  is an invalid format and we give up parsing the text.
     */
    if ((*txt == '=') || (*txt == ':')) {
        txt = SPN_WHITESPACE_CHARS(txt+1);
        if (txt > pzEnd)
            goto name_only;
    } else if (! IS_WHITESPACE_CHAR(txt[-1]))
        return NULL;

    /*
     *  IF the value is continued, remove the backslash escape and push "pzEnd"
     *  on to a newline *not* preceded by a backslash.
     */
    if (pzEnd[-1] == '\\') {
        char* pcD = pzEnd-1;
        char* pcS = pzEnd;

        for (;;) {
            char ch = *(pcS++);
            switch (ch) {
            case NUL:
                pcS = NULL;
                /* FALLTHROUGH */

            case NL:
                *pcD = NUL;
                pzEnd = pcS;
                goto copy_done;

            case '\\':
                if (*pcS == NL)
                    ch = *(pcS++);
                /* FALLTHROUGH */
            default:
                *(pcD++) = ch;
            }
        } copy_done:;

    } else {
        /*
         *  The newline was not preceded by a backslash.  NUL it out
         */
        *(pzEnd++) = NUL;
    }

    /*
     *  "pzName" points to what looks like text for one option/configurable.
     *  It is NUL terminated.  Process it.
     */
    loadOptionLine(opts, ost, pzName, dir, OPTION_LOAD_UNCOOKED);

    return pzEnd;
}
Пример #4
0
/**
 *  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 *
scan_name(char const * name, tOptionValue * res)
{
    tOptionValue * new_val;
    char const *   pzScan = name+1; /* we know first char is a name char */
    char const *   pzVal;
    size_t         nm_len = 1;
    size_t         d_len = 0;

    /*
     *  Scan over characters that name a value.  These names may not end
     *  with a colon, but they may contain colons.
     */
    pzScan = SPN_VALUE_NAME_CHARS(name + 1);
    if (pzScan[-1] == ':')
        pzScan--;
    nm_len = (size_t)(pzScan - name);

    pzScan = SPN_HORIZ_WHITE_CHARS(pzScan);

 re_switch:

    switch (*pzScan) {
    case '=':
    case ':':
        pzScan = SPN_HORIZ_WHITE_CHARS(pzScan + 1);
        if ((*pzScan == '=') || (*pzScan == ':'))
            goto default_char;
        goto re_switch;

    case NL:
    case ',':
        pzScan++;
        /* FALLTHROUGH */

    case NUL:
        add_string(&(res->v.nestVal), name, nm_len, NULL, (size_t)0);
        break;

    case '"':
    case '\'':
        pzVal = pzScan;
        pzScan = scan_q_str(pzScan);
        d_len = (size_t)(pzScan - pzVal);
        new_val = add_string(&(res->v.nestVal), name, nm_len, pzVal,
                         d_len);
        if ((new_val != NULL) && (option_load_mode == OPTION_LOAD_COOKED))
            ao_string_cook(new_val->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--;
                d_len = (size_t)(pzScan - pzVal);
                goto string_done;
                /* FALLTHROUGH */

            case NL:
                if (   (pzScan > pzVal + 2)
                    && (pzScan[-2] == '\\')
                    && (pzScan[ 0] != NUL))
                    continue;
                /* FALLTHROUGH */

            case ',':
                d_len = (size_t)(pzScan - pzVal) - 1;
            string_done:
                new_val = add_string(&(res->v.nestVal), name, nm_len,
                                     pzVal, d_len);
                if (new_val != NULL)
                    remove_continuation(new_val->v.strVal);
                goto leave_scan_name;
            }
        }
        break;
    } leave_scan_name:;

    return pzScan;
}
Пример #5
0
static tDefEntry *
find_by_index(tDefEntry * pE, char * pzScan)
{
    int  idx;

    /*
     *  '[]' means the first entry of whatever index number
     */
    if (*pzScan == ']')
        return pE;

    /*
     *  '[$]' means the last entry of whatever index number
     */
    if (*pzScan == '$') {
        pzScan = SPN_WHITESPACE_CHARS(pzScan + 1);
        if (*pzScan != ']')
            return NULL;

        if (pE->pEndTwin != NULL)
            return pE->pEndTwin;

        return pE;
    }

    /*
     *  '[nn]' means the specified index number
     */
    if (IS_DEC_DIGIT_CHAR(*pzScan)) {
        char* pz;
        idx = strtol(pzScan, &pz, 0);

        /*
         *  Skip over any trailing space and make sure we have a closer
         */
        pz = SPN_WHITESPACE_CHARS(pz);
        if (*pz != ']')
            return NULL;
    }

    else {
        /*
         *  '[XX]' means get the index from our definitions
         */
        char* pzDef = pzScan;
        char const* pzVal;

        if (! IS_VAR_FIRST_CHAR(*pzScan))
            return NULL;

        pzScan = SPN_VALUE_NAME_CHARS(pzScan);

        /*
         *  Temporarily remove the character under *pzScan and
         *  find the corresponding defined value.
         */
        {
            char  svch = *pzScan;
            *pzScan = NUL;
            pzVal   = getDefine(pzDef, AG_TRUE);
            *pzScan = svch;
        }

        /*
         *  Skip over any trailing space and make sure we have a closer
         */
        pzScan = SPN_WHITESPACE_CHARS(pzScan);
        if (*pzScan != ']')
            return NULL;

        /*
         *  make sure we found a defined value
         */
        if ((pzVal == NULL) || (*pzVal == NUL))
            return NULL;

        idx = strtol(pzVal, &pzDef, 0);

        /*
         *  Make sure we got a legal number
         */
        if (*pzDef != NUL)
            return NULL;
    }

    /*
     *  Search for the entry with the specified index.
     */
    do  {
        if (pE->index > idx)
            return NULL;
        if (pE->index == idx)
            break;
        pE = pE->pTwin;
    } while (pE != NULL);

    return pE;
}