Пример #1
0
/*
 *  shortOptionFind
 *
 *  Find the short option descriptor for the current option
 */
LOCAL tSuccess
shortOptionFind(tOptions* pOpts, uint_t optValue, tOptState* pOptState)
{
    tOptDesc*  pRes = pOpts->pOptDesc;
    int        ct   = pOpts->optCt;

    /*
     *  Search the option list
     */
    do  {
        if (optValue != pRes->optValue)
            continue;

        if (SKIP_OPT(pRes)) {
            if (  (pRes->fOptState == (OPTST_OMITTED | OPTST_NO_INIT))
               && (pRes->pz_Name != NULL)) {
                fprintf(stderr, zDisabledErr, pOpts->pzProgPath, pRes->pz_Name);
                if (pRes->pzText != NULL)
                    fprintf(stderr, " -- %s", pRes->pzText);
                fputc('\n', stderr);
                (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE);
                /* NOTREACHED */
            }
            goto short_opt_error;
        }

        pOptState->pOD     = pRes;
        pOptState->optType = TOPT_SHORT;
        return SUCCESS;

    } while (pRes++, --ct > 0);

    /*
     *  IF    the character value is a digit
     *    AND there is a special number option ("-n")
     *  THEN the result is the "option" itself and the
     *       option is the specially marked "number" option.
     */
    if (  IS_DEC_DIGIT_CHAR(optValue)
       && (pOpts->specOptIdx.number_option != NO_EQUIVALENT) ) {
        pOptState->pOD = \
        pRes           = pOpts->pOptDesc + pOpts->specOptIdx.number_option;
        (pOpts->pzCurOpt)--;
        pOptState->optType = TOPT_SHORT;
        return SUCCESS;
    }

short_opt_error:

    /*
     *  IF we are to stop on errors (the default, actually)
     *  THEN call the usage procedure.
     */
    if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
        fprintf(stderr, zIllOptChr, pOpts->pzProgPath, optValue);
        (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE);
    }

    return FAILURE;
}
Пример #2
0
/**
 *  Alters the current line number and/or file name.  You may wish to
 *  use this directive if you extract definition source from other files.
 *  @command{getdefs} uses this mechanism so AutoGen will report the correct
 *  file and approximate line number of any errors found in extracted
 *  definitions.
 */
char *
doDir_line(directive_enum_t id, char const * dir, char * scan_next)
{
    (void)id;
    /*
     *  The sequence must be:  #line <number> "file-name-string"
     *
     *  Start by scanning up to and extracting the line number.
     */
    dir = SPN_WHITESPACE_CHARS(dir);
    if (! IS_DEC_DIGIT_CHAR(*dir))
        return scan_next;

    cctx->scx_line = (int)strtol(dir, (char **)&dir, 0);

    /*
     *  Now extract the quoted file name string.
     *  We dup the string so it won't disappear on us.
     */
    dir = SPN_WHITESPACE_CHARS(dir);
    if (*(dir++) != '"')
        return scan_next;
    {
        char * pz = strchr(dir, '"');
        if (pz == NULL)
            return scan_next;
        *pz = NUL;
    }

    AGDUPSTR(cctx->scx_fname, dir, "#line");

    return scan_next;
}
Пример #3
0
/*=directive line
 *
 *  text:
 *
 *  Alters the current line number and/or file name.  You may wish to
 *  use this directive if you extract definition source from other files.
 *  @command{getdefs} uses this mechanism so AutoGen will report the correct
 *  file and approximate line number of any errors found in extracted
 *  definitions.
=*/
static char*
doDir_line(char* pzArg, char* pzScan)
{
    /*
     *  The sequence must be:  #line <number> "file-name-string"
     *
     *  Start by scanning up to and extracting the line number.
     */
    while (IS_WHITESPACE_CHAR(*pzArg)) pzArg++;
    if (! IS_DEC_DIGIT_CHAR(*pzArg))
        return pzScan;

    pCurCtx->lineNo = strtol(pzArg, &pzArg, 0);

    /*
     *  Now extract the quoted file name string.
     *  We dup the string so it won't disappear on us.
     */
    while (IS_WHITESPACE_CHAR(*pzArg)) pzArg++;
    if (*(pzArg++) != '"')
        return pzScan;
    {
        char* pz = strchr(pzArg, '"');
        if (pz == NULL)
            return pzScan;
        *pz = NUL;
    }

    AGDUPSTR(pCurCtx->pzCtxFname, pzArg, "#line file name");

    return pzScan;
}
Пример #4
0
/**
 *  Associate a name with a boolean value
 *
 * @param[in,out] pp        argument list to add to
 * @param[in]     name      the name of the "suboption"
 * @param[in]     nm_len    the length of the name
 * @param[in]     val       the boolean value for the suboption
 * @param[in]     d_len     the length of the value
 *
 * @returns the new value structure
 */
static tOptionValue *
add_bool(void ** pp, char const * name, size_t nm_len,
         char const * val, size_t d_len)
{
    size_t sz = nm_len + sizeof(tOptionValue) + 1;
    tOptionValue * new_val = AGALOC(sz, "bool val");

    /*
     * Scan over whitespace is constrained by "d_len"
     */
    while (IS_WHITESPACE_CHAR(*val) && (d_len > 0)) {
        d_len--; val++;
    }

    if (d_len == 0)
        new_val->v.boolVal = 0;

    else if (IS_DEC_DIGIT_CHAR(*val))
        new_val->v.boolVal = (unsigned)atoi(val);

    else new_val->v.boolVal = ! IS_FALSE_TYPE_CHAR(*val);

    new_val->valType = OPARG_TYPE_BOOLEAN;
    new_val->pzName = (char *)(new_val + 1);
    memcpy(new_val->pzName, name, nm_len);
    new_val->pzName[ nm_len ] = NUL;
    addArgListEntry(pp, new_val);
    return new_val;
}
Пример #5
0
/*  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 (IS_WHITESPACE_CHAR(*pzValue) && (dataLen > 0)) {
        dataLen--; pzValue++;
    }
    if (dataLen == 0)
        pNV->v.boolVal = 0;

    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 );
    pNV->pzName[ nameLen ] = NUL;
    addArgListEntry( pp, pNV );
    return pNV;
}
Пример #6
0
/**
 * Figure out where to insert an entry in a list of twins.
 */
LOCAL tDefEntry*
findPlace(char* name, char const * pzIndex)
{
    tDefEntry* pE = getEntry();

    pE->pzDefName = name;

    if (pzIndex == NULL)
        pE->index = NO_INDEX;

    else if (IS_DEC_DIGIT_CHAR(*pzIndex) || (*pzIndex == '-'))
        pE->index = strtol(pzIndex, NULL, 0);

    else {
        pzIndex = getDefine(pzIndex, AG_TRUE);
        if (pzIndex != NULL)
            pE->index = strtol(pzIndex, NULL, 0);
        else pE->index = NO_INDEX;
    }

    strtransform(pE->pzDefName, pE->pzDefName);
    pE->valType     = VALTYP_UNKNOWN;
    pE->pzSrcFile   = (char*)pCurCtx->pzCtxFname;
    pE->srcLineNum  = pCurCtx->lineNo;
    return (pCurrentEntry = insertDef(pE));
}
Пример #7
0
/*=gfunc version_compare
 *
 * what:   compare two version numbers
 * general_use:
 *
 * exparg: op, comparison operator
 * exparg: v1, first version
 * exparg: v2, compared-to version
 *
 * doc:  Converts v1 and v2 strings into 64 bit values and returns the
 *       result of running 'op' on those values.  It assumes that the version
 *       is a 1 to 4 part dot-separated series of numbers.  Suffixes like,
 *       "5pre4" or "5-pre4" will be interpreted as two numbers.  The first
 *       number ("5" in this case) will be decremented and the number after
 *       the "pre" will be added to 0xC000.  (Unless your platform is unable
 *       to support 64 bit integer arithmetic.  Then it will be added to 0xC0.)
 *       Consequently, these yield true:
 *       @example
 *       (version-compare > "5.8.5"       "5.8.5-pre4")
 *       (version-compare > "5.8.5-pre10" "5.8.5-pre4")
 *       @end example
=*/
static ver_type_t
str2int_ver(char* pz)
{
    char* pzStr = pz;
    ver_type_t  val = 0;
    int ix = 4;

    while (--ix >= 0) {
        unsigned int v;
        val <<= VER_UNIT_SHIFT;
        while (IS_WHITESPACE_CHAR(*pz))  pz++;

    next_number:
        if (! IS_DEC_DIGIT_CHAR(*pz)) break;
        v = (unsigned int)strtoul(pz, &pz, 0) & ((1 << VER_UNIT_SHIFT) - 1);
        if (pz == NULL)
            break;
        val += v;
        if (*pz == '-') pz++;

        switch (*pz) {
        case 'p':
            if ((pz[1] == 'r') && (pz[2] == 'e')) {
                pz += 3;
                val = (val << 2) - 1;
                val <<= (VER_UNIT_SHIFT - 2);
                if (--ix < 0) goto leave_str2int_ver;
                goto next_number;
            }
            /* FALLTHROUGH */

        default:
            goto leave_str2int_ver;

        case '.':
            if (! IS_DEC_DIGIT_CHAR(*(++pz)))
                goto leave_str2int_ver;
            break;
        }
    } leave_str2int_ver: ;

    while (--ix >= 0)  val <<= VER_UNIT_SHIFT;
    if (OPT_VALUE_TRACE >= TRACE_EXPRESSIONS)
        fprintf(pfTrace, "0x%016llX <<== '%s'\n", (long long)val, pzStr);
    return val;
}
Пример #8
0
/**
 * Convert a name or number into a binary number.
 * "~0" and "-1" will be converted to the largest value in the enumeration.
 *
 * @param name       the keyword name (number) to convert
 * @param pOpts      the program's option descriptor
 * @param pOD        the option descriptor for this option
 * @param paz_names  the list of keywords for this option
 * @param name_ct    the count of keywords
 */
static uintptr_t
find_name(char const * name, tOptions * pOpts, tOptDesc * pOD,
          char const * const *  paz_names, unsigned int name_ct)
{
    /*
     *  Return the matching index as a pointer sized integer.
     *  The result gets stashed in a char * pointer.
     */
    uintptr_t   res = name_ct;
    size_t      len = strlen((char *)name);
    uintptr_t   idx;

    if (IS_DEC_DIGIT_CHAR(*name)) {
        char * pz = VOIDP(name);
        unsigned long val = strtoul(pz, &pz, 0);
        if ((*pz == NUL) && (val < name_ct))
            return (uintptr_t)val;
        pz_enum_err_fmt = znum_too_large;
        option_usage_fp = stderr;
        enum_err(pOpts, pOD, paz_names, (int)name_ct);
        return name_ct;
    }

    if (IS_INVERSION_CHAR(*name) && (name[2] == NUL)) {
        if (  ((name[0] == '~') && (name[1] == '0'))
           || ((name[0] == '-') && (name[1] == '1')))
        return (uintptr_t)(name_ct - 1);
        goto oops;
    }

    /*
     *  Look for an exact match, but remember any partial matches.
     *  Multiple partial matches means we have an ambiguous match.
     */
    for (idx = 0; idx < name_ct; idx++) {
        if (strncmp((char *)paz_names[idx], (char *)name, len) == 0) {
            if (paz_names[idx][len] == NUL)
                return idx;  /* full match */

            if (res == name_ct)
                res = idx; /* save partial match */
            else
                res = (uintptr_t)~0;  /* may yet find full match */
        }
    }

    if (res < name_ct)
        return res; /* partial match */

 oops:

    pz_enum_err_fmt = (res == name_ct) ? zNoKey : zambiguous_key;
    option_usage_fp = stderr;
    enum_err(pOpts, pOD, paz_names, (int)name_ct);
    return name_ct;
}
Пример #9
0
static uintptr_t
findName(
    tCC*          pzName,
    tOptions*     pOpts,
    tOptDesc*     pOD,
    tCC* const *  paz_names,
    unsigned int  name_ct )
{
    /*
     *  Return the matching index as a pointer sized integer.
     *  The result gets stashed in a char* pointer.
     */
    uintptr_t     res = name_ct;
    size_t        len = strlen( (char*)pzName );
    uintptr_t     idx;

    if (IS_DEC_DIGIT_CHAR(*pzName)) {
        char * pz = (char *)(void *)pzName;
        unsigned long val = strtoul(pz, &pz, 0);
        if ((*pz == NUL) && (val < name_ct))
            return (uintptr_t)val;
        enumError(pOpts, pOD, paz_names, (int)name_ct);
        return name_ct;
    }

    /*
     *  Look for an exact match, but remember any partial matches.
     *  Multiple partial matches means we have an ambiguous match.
     */
    for (idx = 0; idx < name_ct; idx++) {
        if (strncmp( (char*)paz_names[idx], (char*)pzName, len) == 0) {
            if (paz_names[idx][len] == NUL)
                return idx;  /* full match */

            res = (res != name_ct) ? ~0 : idx; /* save partial match */
        }
    }

    if (res < name_ct)
        return res; /* partial match */

    pz_enum_err_fmt = (res == name_ct) ? zNoKey : zAmbigKey;
    option_usage_fp = stderr;
    enumError(pOpts, pOD, paz_names, (int)name_ct);
    return name_ct;
}
Пример #10
0
/*
 *  eval_true - should a string be interpreted as TRUE?
 *
 *  It is always true unless:
 *
 *  1.  it is the empty string
 *  2.  it starts with a digit and the number evaluates to zero
 *  3.  it starts with either "#f" or "#F"
 *  4.  For its length or its first five characters (whichever is less)
 *      it matches the string "false"
 */
static ag_bool
eval_true(void)
{
    ag_bool needFree;
    ag_bool res = AG_TRUE;
    char const * pz = evalExpression(&needFree);

    if (IS_DEC_DIGIT_CHAR(*pz))
        res = (atoi(pz) == 0) ? AG_FALSE : AG_TRUE;

    else switch (*pz) {
    case NUL:
        res = AG_FALSE;
        break;

    case '#':
        if ((pz[1] == 'f') || (pz[1] == 'F'))
            res = AG_FALSE;
        break;

    case 'f':
    case 'F':
    {
        int len = strlen(pz);
        if (len > 5)
            len = 5;
        if (strneqvcmp(EVAL_TRUE_FALSE_STR, pz, len) == 0)
            res = AG_FALSE;
        break;
    }
    }

    if (needFree)
        AGFREE(pz);

    return res;
}
Пример #11
0
/**
 * parse XML encodings
 */
static int
parse_xml_encoding(char ** ppz)
{
#   define XMLTABLE             \
        _xmlNm_(amp,   '&')     \
        _xmlNm_(lt,    '<')     \
        _xmlNm_(gt,    '>')     \
        _xmlNm_(ff,    '\f')    \
        _xmlNm_(ht,    '\t')    \
        _xmlNm_(cr,    '\r')    \
        _xmlNm_(vt,    '\v')    \
        _xmlNm_(bel,   '\a')    \
        _xmlNm_(nl,    NL)      \
        _xmlNm_(space, ' ')     \
        _xmlNm_(quot,  '"')     \
        _xmlNm_(apos,  '\'')

    static struct {
        char const * const  nm_str;
        unsigned short      nm_len;
        short               nm_val;
    } const xml_names[] = {
#   define _xmlNm_(_n, _v) { #_n ";", sizeof(#_n), _v },
        XMLTABLE
#   undef  _xmlNm_
#   undef XMLTABLE
    };

    static int const nm_ct = sizeof(xml_names) / sizeof(xml_names[0]);
    int    base = 10;

    char * pz = *ppz;

    if (*pz == '#') {
        pz++;
        goto parse_number;
    }

    if (IS_DEC_DIGIT_CHAR(*pz)) {
        unsigned long v;

    parse_number:
        switch (*pz) {
        case 'x': case 'X':
            /*
             * Some forms specify hex with:  &#xNN;
             */
            base = 16;
            pz++;
            break;

        case '0':
            /*
             *  &#0022; is hex and &#22; is decimal.  Cool.
             *  Ya gotta love it.
             */
            if (pz[1] == '0')
                base = 16;
            break;
        }

        v = strtoul(pz, &pz, base);
        if ((*pz != ';') || (v > 0x7F))
            return NUL;
        *ppz = pz + 1;
        return (int)v;
    }

    {
        int ix = 0;
        do  {
            if (strncmp(pz, xml_names[ix].nm_str, xml_names[ix].nm_len)
                == 0) {
                *ppz = pz + xml_names[ix].nm_len;
                return xml_names[ix].nm_val;
            }
        } while (++ix < nm_ct);
    }

    return NUL;
}
Пример #12
0
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *
 *  It may be a number, a name, a keyword or garbage.
 *  Figure out which.
 */
static char*
assembleName(char * pzScan, te_dp_event * pRetVal)
{
    /*
     *  Check for a number.
     *  Scan it in and advance "pzScan".
     */
    if (  IS_DEC_DIGIT_CHAR(*pzScan)
       || (  (*pzScan == '-')
          && IS_DEC_DIGIT_CHAR(pzScan[1])
       )  )  {
        pz_token = pzScan;
        (void)strtol(pzScan, &pzScan, 0);
        *pRetVal = DP_EV_NUMBER;
        return pzScan;
    }

    if (! IS_UNQUOTABLE_CHAR(*pzScan))
        AG_ABEND(aprf("%s Error: Invalid input char '%c' in %s on line %d\n",
                      pzProg, *pzScan, pCurCtx->pzCtxFname, pCurCtx->lineNo));

    {
        unsigned char* pz = (unsigned char*)pzScan;

        while (IS_VALUE_NAME_CHAR(*pz))          pz++;

        if (IS_UNQUOTABLE_CHAR(*pz)) {
            *pRetVal = DP_EV_OTHER_NAME;
            while (IS_UNQUOTABLE_CHAR(*++pz))    ;
        } else
            *pRetVal = DP_EV_VAR_NAME;

        /*
         *  Return a NAME token, maybe.
         *  If the name is actually a keyword,
         *  we will return that token code instead.
         */
        pz_token = pzScan;
        pzScan   = (char*)pz;
    }

    /*
     *  Now scan the keyword table.
     */
    if (*pRetVal == DP_EV_VAR_NAME) {
        char sv_ch = *pzScan;  /* preserve the following character */
        int  kw_ix = 0;
        *pzScan = NUL;         /* NUL terminate the name           */

        do  {
            if (streqvcmp(apzKeywords[ kw_ix ], (char*)pz_token) == 0) {
                /*
                 *  Return the keyword token code instead of DP_EV_NAME
                 */
                *pRetVal = aKeywordTkn[ kw_ix ];
                break;
            }
        } while (++kw_ix < KEYWORD_CT);

        *pzScan = sv_ch;         /* restore the following character  */
    }

    return pzScan;
}
Пример #13
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;
}
Пример #14
0
/**
 *  Run the FSM.  Will return CGI_ST_DONE or CGI_ST_INVALID
 */
te_cgi_state
cgi_run_fsm(
    char const * pzSrc,
    int inlen,
    char * pzOut,
    int outlen )
{
    te_cgi_state cgi_state = CGI_ST_INIT;
    te_cgi_event trans_evt;
    te_cgi_state nxtSt;
    te_cgi_trans trans;
    char const * saved_pzSrc = pzSrc;
    int saved_inlen = inlen;
    char * saved_pzOut = pzOut;
    int saved_outlen = outlen;
    (void)saved_pzSrc;
    (void)saved_inlen;
    (void)saved_pzOut;
    (void)saved_outlen;

    while (cgi_state < CGI_ST_INVALID) {

        /* START == FIND TRANSITION == DO NOT CHANGE THIS COMMENT */

        char  curCh;
        if (--inlen < 0) {
            trans_evt = CGI_EV_END;
            curCh = NUL;

        } else {
            if (outlen < 4) {
                static char const exhaustion[] = "output space exhausted\n";
                if (saved_outlen > (int)sizeof(exhaustion))
                    memcpy(saved_pzOut, exhaustion, sizeof(exhaustion));

                return CGI_ST_INVALID;
            }
            curCh = *(pzSrc++);
            if (IS_ALPHABETIC_CHAR( curCh ))
                trans_evt = CGI_EV_ALPHA;
            else if (IS_DEC_DIGIT_CHAR( curCh ))
                trans_evt = CGI_EV_NAME_CHAR;
            else switch (curCh) {
            case '_': trans_evt = CGI_EV_NAME_CHAR; break;
            case '=': trans_evt = CGI_EV_EQUAL;     break;
            case '+': trans_evt = CGI_EV_SPACE;     curCh = ' '; break;
            case '%': trans_evt = CGI_EV_ESCAPE;    break;
            case '&': trans_evt = CGI_EV_SEPARATOR; break;
            default:  trans_evt = CGI_EV_OTHER;     break;
            }
        }

        /* END   == FIND TRANSITION == DO NOT CHANGE THIS COMMENT */

#ifndef __COVERITY__
        if (trans_evt >= CGI_EV_INVALID) {
            nxtSt = CGI_ST_INVALID;
            trans = CGI_TR_INVALID;
        } else
#endif /* __COVERITY__ */
        {
            const t_cgi_transition * ttbl =
            cgi_trans_table[ cgi_state ] + trans_evt;
            nxtSt = ttbl->next_state;
            trans = ttbl->transition;
        }


        switch (trans) {
        case CGI_TR_INVALID:
            /* START == INVALID == DO NOT CHANGE THIS COMMENT */
            exit( cgi_invalid_transition( cgi_state, trans_evt ));
            /* END   == INVALID == DO NOT CHANGE THIS COMMENT */
            break;


        case CGI_TR_NAME_EQUAL:
            /* START == NAME_EQUAL == DO NOT CHANGE THIS COMMENT */
            strcpy( pzOut, "='" );
            outlen -= 2;
            pzOut  += 2;
            /* END   == NAME_EQUAL == DO NOT CHANGE THIS COMMENT */
            break;


        case CGI_TR_SEPARATE:
            /* START == SEPARATE == DO NOT CHANGE THIS COMMENT */
            strcpy( pzOut, "';\n" );
            outlen -= 2;
            pzOut  += 3;
            /* END   == SEPARATE == DO NOT CHANGE THIS COMMENT */
            break;


        case CGI_TR_STASH:
            /* START == STASH == DO NOT CHANGE THIS COMMENT */
            *(pzOut++) = curCh;
            outlen--;
            /* END   == STASH == DO NOT CHANGE THIS COMMENT */
            break;


        case CGI_TR_VALUE_ESCAPE:
            /* START == VALUE_ESCAPE == DO NOT CHANGE THIS COMMENT */
            {
            char z[4];
            if (inlen < 2)
                exit( cgi_invalid_transition( cgi_state, trans_evt ));

            z[0] = *(pzSrc++);
            z[1] = *(pzSrc++);
            z[2] = NUL;
            inlen -= 2;

            /*
             *  We must backslash quote certain characters that are %-quoted
             *  in the input string:
             */
            switch (*(pzOut++) = (char)strtol( z, NULL, 16 )) {
            case '\'':
            case '\\':
            case '#':
                pzOut[0]  = pzOut[-1];
                pzOut[-1] = '\\';
                pzOut++;
            }
            }
            /* END   == VALUE_ESCAPE == DO NOT CHANGE THIS COMMENT */
            break;


        default:
            /* START == BROKEN MACHINE == DO NOT CHANGE THIS COMMENT */
            exit( cgi_invalid_transition( cgi_state, trans_evt ));
            /* END   == BROKEN MACHINE == DO NOT CHANGE THIS COMMENT */
        }

        cgi_state = nxtSt;
    }
    return cgi_state;
}