Esempio n. 1
0
/*=export_func  optionLoadLine
 *
 * what:  process a string for an option name and value
 *
 * arg:   tOptions*,   pOpts,  program options descriptor
 * arg:   char const*, pzLine, NUL-terminated text
 *
 * doc:
 *
 *  This is a client program callable routine for setting options from, for
 *  example, the contents of a file that they read in.  Only one option may
 *  appear in the text.  It will be treated as a normal (non-preset) option.
 *
 *  When passed a pointer to the option struct and a string, it will find
 *  the option named by the first token on the string and set the option
 *  argument to the remainder of the string.  The caller must NUL terminate
 *  the string.  Any embedded new lines will be included in the option
 *  argument.  If the input looks like one or more quoted strings, then the
 *  input will be "cooked".  The "cooking" is identical to the string
 *  formation used in AutoGen definition files (@pxref{basic expression}),
 *  except that you may not use backquotes.
 *
 * err:   Invalid options are silently ignored.  Invalid option arguments
 *        will cause a warning to print, but the function should return.
=*/
void
optionLoadLine(tOptions * pOpts, char const * pzLine)
{
    tOptState st = OPTSTATE_INITIALIZER(SET);
    char* pz;
    AGDUPSTR(pz, pzLine, "user option line");
    loadOptionLine(pOpts, &st, pz, DIRECTION_PROCESS, OPTION_LOAD_COOKED);
    AGFREE(pz);
}
Esempio n. 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;
}
Esempio n. 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;
}
Esempio n. 4
0
/*  handleStructure
 *
 *  "pzText" 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*
handleStructure(
    tOptions*     pOpts,
    tOptState*    pOS,
    char*         pzText,
    int           direction )
{
    tOptionLoadMode mode = option_load_mode;
    tOptionValue     valu;

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

    while (ISNAMECHAR( *pzText ))  pzText++;
    pcNulPoint = pzText;
    valu.valType = OPARG_TYPE_STRING;

    switch (*pzText) {
    case ' ':
    case '\t':
        pzText = parseAttributes( pOpts, pzText, &mode, &valu );
        if (*pzText == '>')
            break;
        if (*pzText != '/')
            return NULL;
        /* FALLTHROUGH */

    case '/':
        if (pzText[1] != '>')
            return NULL;
        *pzText = NUL;
        pzText += 2;
        loadOptionLine( pOpts, pOS, pzName, direction, mode );
        return pzText;

    case '>':
        break;

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

    /*
     *  If we are here, we have a value.  "pzText" points to a closing angle
     *  bracket.  Separate the name from the value for a moment.
     */
    *pcNulPoint = NUL;
    pzData = ++pzText;

    /*
     *  Find the end of the option text and NUL terminate it
     */
    {
        char   z[64], *pz = z;
        size_t len = strlen(pzName) + 4;
        if (len > sizeof(z))
            pz = AGALOC(len, "scan name");

        sprintf( pz, "</%s>", pzName );
        *pzText = ' ';
        pzText = strstr( pzText, pz );
        if (pz != z) AGFREE(pz);

        if (pzText == NULL)
            return pzText;

        *pzText = NUL;

        pzText += len-1;
    }

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

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

    return pzText;
}
Esempio n. 5
0
/*  handleConfig
 *
 *  "pzText" 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*
handleConfig(
    tOptions*     pOpts,
    tOptState*    pOS,
    char*         pzText,
    int           direction )
{
    char* pzName = pzText++;
    char* pzEnd  = strchr( pzText, '\n' );

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

    while (ISNAMECHAR( (int)*pzText ))  pzText++;
    while (isspace( (int)*pzText )) pzText++;
    if (pzText > pzEnd) {
    name_only:
        *pzEnd++ = NUL;
        loadOptionLine( pOpts, pOS, pzName, direction, 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 ((*pzText == '=') || (*pzText == ':')) {
        while (isspace( (int)*++pzText ))   ;
        if (pzText > pzEnd)
            goto name_only;
    } else if (! isspace((int)pzText[-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;

            case '\n':
                *pcD = NUL;
                pzEnd = pcS;
                goto copy_done;

            case '\\':
                if (*pcS == '\n') {
                    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( pOpts, pOS, pzName, direction, OPTION_LOAD_UNCOOKED );

    return pzEnd;
}
Esempio n. 6
0
/**
 *  "pzText" 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 * pOpts, tOptState * pOS, char * pzText, int dir)
{
    tOptionLoadMode mode = option_load_mode;
    tOptionValue    valu;

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

    while (IS_VALUE_NAME_CHAR(*pzText))  pzText++;
    pcNulPoint = pzText;
    valu.valType = OPARG_TYPE_STRING;

    switch (*pzText) {
    case ' ':
    case '\t':
        pzText = parseAttributes(pOpts, pzText, &mode, &valu);
        if (*pzText == '>')
            break;
        if (*pzText != '/')
            return NULL;
        /* FALLTHROUGH */

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

    case '>':
        break;

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

    /*
     *  If we are here, we have a value.  "pzText" points to a closing angle
     *  bracket.  Separate the name from the value for a moment.
     */
    *pcNulPoint = NUL;
    pzData = ++pzText;

    /*
     *  Find the end of the option text and NUL terminate it
     */
    {
        char   z[64], *pz = z;
        size_t len = strlen(pzName) + 4;
        if (len > sizeof(z))
            pz = AGALOC(len, "scan name");

        sprintf(pz, "</%s>", pzName);
        *pzText = ' ';
        pzText = strstr(pzText, pz);
        if (pz != z) AGFREE(pz);

        if (pzText == NULL)
            return pzText;

        *pzText = NUL;

        pzText += len-1;
    }

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

    /*
     *  If we are getting a "string" value, the process the XML-ish
     *  %XX hex characters.
     */
    if (valu.valType == OPARG_TYPE_STRING) {
        char * pzSrc = pzData;
        char * pzDst = pzData;
        char bf[4];
        bf[2] = NUL;

        for (;;) {
            int ch = ((int)*(pzSrc++)) & 0xFF;
            switch (ch) {
            case NUL: goto string_fixup_done;

            case '%':
                bf[0] = *(pzSrc++);
                bf[1] = *(pzSrc++);
                if ((bf[0] == NUL) || (bf[1] == NUL))
                    goto string_fixup_done;
                ch = strtoul(bf, NULL, 16);
                /* FALLTHROUGH */

            default:
                *(pzDst++) = ch;
            }
        } string_fixup_done:;
        *pzDst = NUL;
    }

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

    return pzText;
}