Example #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;
}
Example #2
0
/**
 *  Emit GNU-standard long option handling code.
 *
 * @param[in] opts  the program options
 */
static void
emit_long(tOptions * opts)
{
    tOptDesc * od = opts->pOptDesc;
    int        ct  = opts->optCt;

    fputs(zOptionCase, stdout);

    /*
     *  do each option, ...
     */
    do  {
        /*
         *  Documentation & compiled-out options
         */
        if (SKIP_OPT(od))
            continue;

        emit_match_expr(od->pz_Name, od, opts);
        emit_action(opts, od);

        /*
         *  Now, do the same thing for the disablement version of the option.
         */
        if (od->pz_DisableName != NULL) {
            emit_match_expr(od->pz_DisableName, od, opts);
            emit_inaction(opts, od);
        }
    } while (od++, --ct > 0);

    printf(UNK_OPT_FMT, OPTION_STR, opts->pzPROGNAME);
}
Example #3
0
static void
emit_wrapup(tOptions * opts)
{
    tOptDesc *   od     = opts->pOptDesc;
    int          opt_ct = opts->presetOptCt;
    char const * fmt;

    printf(FINISH_LOOP, opts->pzPROGNAME);
    for (;opt_ct > 0; od++, --opt_ct) {
        /*
         *  Options that are either usage documentation or are compiled out
         *  are not to be processed.
         */
        if (SKIP_OPT(od) || (od->pz_NAME == NULL))
            continue;

        /*
         *  do not presence check if there is no minimum/must-set
         */
        if ((od->optMinCt == 0) && ((od->fOptState & OPTST_MUST_SET) == 0))
            continue;

        if (od->optMaxCt > 1)
             fmt = CHK_MIN_COUNT;
        else fmt = CHK_ONE_REQUIRED;

        {
            int min = (od->optMinCt == 0) ? 1 : od->optMinCt;
            printf(fmt, opts->pzPROGNAME, od->pz_NAME, min);
        }
    }
    fputs(END_MARK, stdout);
}
Example #4
0
/*
 *  Emit GNU-standard long option handling code
 */
static void
emitLong( tOptions* pOpts )
{
    tOptDesc* pOD = pOpts->pOptDesc;
    int       ct  = pOpts->optCt;

    fputs( zOptionCase, stdout );

    /*
     *  do each option, ...
     */
    do  {
        /*
         *  Documentation & compiled-out options
         */
        if (SKIP_OPT(pOD))
            continue;

        emitMatchExpr( pOD->pz_Name, pOD, pOpts );
        printOptionAction( pOpts, pOD );

        /*
         *  Now, do the same thing for the disablement version of the option.
         */
        if (pOD->pz_DisableName != NULL) {
            emitMatchExpr( pOD->pz_DisableName, pOD, pOpts );
            printOptionInaction( pOpts, pOD );
        }
    } while (pOD++, --ct > 0);

    printf( zOptionUnknown, "option", pOpts->pzPROGNAME );
}
Example #5
0
/**
 *  Set the option to the indicated option number.
 *
 * @param opts      option data
 * @param arg       option argument (if glued to name)
 * @param idx       option index
 * @param disable   mark disabled option
 * @param st        state about current option
 */
static tSuccess
opt_set(tOptions * opts, char * arg, int idx, bool disable, tOptState * st)
{
    tOptDesc * pOD = opts->pOptDesc + idx;

    if (SKIP_OPT(pOD)) {
        if ((opts->fOptSet & OPTPROC_ERRSTOP) == 0)
            return FAILURE;

        fprintf(stderr, zDisabledErr, opts->pzProgName, pOD->pz_Name);
        if (pOD->pzText != NULL)
            fprintf(stderr, SET_OFF_FMT, pOD->pzText);
        fputc(NL, stderr);
        (*opts->pUsageProc)(opts, EXIT_FAILURE);
        /* NOTREACHED */
        _exit(EXIT_FAILURE); /* to be certain */
    }

    /*
     *  IF we found a disablement name,
     *  THEN set the bit in the callers' flag word
     */
    if (disable)
        st->flags |= OPTST_DISABLED;

    st->pOD      = pOD;
    st->pzOptArg = arg;
    st->optType  = TOPT_LONG;

    return SUCCESS;
}
Example #6
0
/**
 * recognize flag options.  These go at the end.
 * At the end, emit code to handle options we don't recognize.
 *
 * @param[in] opts  the program options
 */
static void
emit_flag(tOptions * opts)
{
    tOptDesc * od = opts->pOptDesc;
    int        opt_ct = opts->optCt;

    fputs(zOptionCase, stdout);

    for (;opt_ct > 0; od++, --opt_ct) {

        if (SKIP_OPT(od) || ! IS_GRAPHIC_CHAR(od->optValue))
            continue;

        printf(zOptionFlag, od->optValue);
        emit_action(opts, od);
    }
    printf(UNK_OPT_FMT, FLAG_STR, opts->pzPROGNAME);
}
Example #7
0
static void
emitFlag( tOptions* pOpts )
{
    tOptDesc* pOptDesc = pOpts->pOptDesc;
    int       optionCt = pOpts->optCt;

    fputs( zOptionCase, stdout );

    for (;optionCt > 0; pOptDesc++, --optionCt) {

        if (SKIP_OPT(pOptDesc))
            continue;

        if (IS_GRAPHIC_CHAR(pOptDesc->optValue)) {
            printf( zOptionFlag, pOptDesc->optValue );
            printOptionAction( pOpts, pOptDesc );
        }
    }
    printf( zOptionUnknown, "flag", pOpts->pzPROGNAME );
}
Example #8
0
static void
emit_flag(tOptions * pOpts)
{
    tOptDesc* pOptDesc = pOpts->pOptDesc;
    int       optionCt = pOpts->optCt;

    fputs(zOptionCase, stdout);

    for (;optionCt > 0; pOptDesc++, --optionCt) {

        if (SKIP_OPT(pOptDesc))
            continue;

        if (IS_GRAPHIC_CHAR(pOptDesc->optValue)) {
            printf(zOptionFlag, pOptDesc->optValue);
            emit_action(pOpts, pOptDesc);
        }
    }
    printf(UNK_OPT_FMT, FLAG_STR, pOpts->pzPROGNAME);
}
Example #9
0
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *
 *  HUNT FOR OPTIONS IN THE ARGUMENT LIST
 *
 *  The next four procedures are "private" to nextOption().
 *  nextOption() uses findOptDesc() to find the next descriptor and it, in
 *  turn, uses longOptionFind() and shortOptionFind() to actually do the hunt.
 *
 *  longOptionFind
 *
 *  Find the long option descriptor for the current option
 */
LOCAL tSuccess
longOptionFind(tOptions* pOpts, char* pzOptName, tOptState* pOptState)
{
    ag_bool    disable  = AG_FALSE;
    char*      pzEq     = strchr(pzOptName, '=');
    tOptDesc*  pOD      = pOpts->pOptDesc;
    int        idx      = 0;
    int        idxLim   = pOpts->optCt;
    int        matchCt  = 0;
    int        matchIdx = 0;
    int        nameLen;
    char       opt_name_buf[128];

    /*
     *  IF the value is attached to the name,
     *  copy it off so we can NUL terminate.
     */
    if (pzEq != NULL) {
        nameLen = (int)(pzEq - pzOptName);
        if (nameLen >= sizeof(opt_name_buf))
            return FAILURE;
        memcpy(opt_name_buf, pzOptName, nameLen);
        opt_name_buf[nameLen] = NUL;
        pzOptName = opt_name_buf;
        pzEq++;

    } else nameLen = strlen(pzOptName);

    do  {
        /*
         *  If option disabled or a doc option, skip to next
         */
        if (pOD->pz_Name == NULL)
            continue;

        if (  SKIP_OPT(pOD)
           && (pOD->fOptState != (OPTST_OMITTED | OPTST_NO_INIT)))
            continue;

        if (strneqvcmp(pzOptName, pOD->pz_Name, nameLen) == 0) {
            /*
             *  IF we have a complete match
             *  THEN it takes priority over any already located partial
             */
            if (pOD->pz_Name[ nameLen ] == NUL) {
                matchCt  = 1;
                matchIdx = idx;
                break;
            }
        }

        /*
         *  IF       there is a disable name
         *     *AND* no argument value has been supplied
         *              (disabled options may have no argument)
         *     *AND* the option name matches the disable name
         *  THEN ...
         */
        else if (  (pOD->pz_DisableName != NULL)
                && (strneqvcmp(pzOptName, pOD->pz_DisableName, nameLen) == 0)
                )  {
            disable  = AG_TRUE;

            /*
             *  IF we have a complete match
             *  THEN it takes priority over any already located partial
             */
            if (pOD->pz_DisableName[ nameLen ] == NUL) {
                matchCt  = 1;
                matchIdx = idx;
                break;
            }
        }

        else
            continue;

        /*
         *  We found a partial match, either regular or disabling.
         *  Remember the index for later.
         */
        matchIdx = idx;

        if (++matchCt > 1)
            break;

    } while (pOD++, (++idx < idxLim));

    /*
     *  Make sure we either found an exact match or found only one partial
     */
    if (matchCt == 1) {
        pOD = pOpts->pOptDesc + matchIdx;

        if (SKIP_OPT(pOD)) {
            fprintf(stderr, zDisabledErr, pOpts->pzProgName, pOD->pz_Name);
            if (pOD->pzText != NULL)
                fprintf(stderr, " -- %s", pOD->pzText);
            fputc('\n', stderr);
            (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE);
            /* NOTREACHED */
        }

        /*
         *  IF we found a disablement name,
         *  THEN set the bit in the callers' flag word
         */
        if (disable)
            pOptState->flags |= OPTST_DISABLED;

        pOptState->pOD      = pOD;
        pOptState->pzOptArg = pzEq;
        pOptState->optType  = TOPT_LONG;
        return SUCCESS;
    }

    /*
     *  IF there is no equal sign
     *     *AND* we are using named arguments
     *     *AND* there is a default named option,
     *  THEN return that option.
     */
    if (  (pzEq == NULL)
       && NAMED_OPTS(pOpts)
       && (pOpts->specOptIdx.default_opt != NO_EQUIVALENT)) {
        pOptState->pOD = pOpts->pOptDesc + pOpts->specOptIdx.default_opt;

        pOptState->pzOptArg = pzOptName;
        pOptState->optType  = TOPT_DEFAULT;
        return SUCCESS;
    }

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

    return FAILURE;
}
Example #10
0
/**
 *  Emit the match text for a long option.  The passed in \a name may be
 *  either the enablement name or the disablement name.
 *
 * @param[in] name  The current name to check.
 * @param[in] cod   current option descriptor
 * @param[in] opts  the program options
 */
static void
emit_match_expr(char const * name, tOptDesc * cod, tOptions * opts)
{
    char name_bf[32];
    unsigned int    min_match_ct = 2;
    unsigned int    max_match_ct = strlen(name) - 1;

    if (max_match_ct >= sizeof(name_bf) - 1)
        goto leave;
    
    {
        tOptDesc *  od = opts->pOptDesc;
        int         ct = opts->optCt;

        for (; ct-- > 0; od++) {
            unsigned int match_ct = 0;

            /*
             *  Omit the current option, Doc opts and compiled out opts.
             */
            if ((od == cod) || SKIP_OPT(od))
                continue;

            /*
             *  Check each character of the name case insensitively.
             *  They must not be the same.  They cannot be, because it would
             *  not compile correctly if they were.
             */
            while (UPPER(od->pz_Name[match_ct]) == UPPER(name[match_ct]))
                match_ct++;

            if (match_ct > min_match_ct)
                min_match_ct = match_ct;

            /*
             *  Check the disablement name, too.
             */
            if (od->pz_DisableName == NULL)
                continue;

            match_ct = 0;
            while (  toupper((unsigned char)od->pz_DisableName[match_ct])
                  == toupper((unsigned char)name[match_ct]))
                match_ct++;
            if (match_ct > min_match_ct)
                min_match_ct = match_ct;
        }
    }

    /*
     *  Don't bother emitting partial matches if there is only one possible
     *  partial match.
     */
    if (min_match_ct < max_match_ct) {
        char *  pz    = name_bf + min_match_ct;
        int     nm_ix = min_match_ct;

        memcpy(name_bf, name, min_match_ct);

        for (;;) {
            *pz = NUL;
            printf(zOptionPartName, name_bf);
            *pz++ = name[nm_ix++];
            if (name[nm_ix] == NUL) {
                *pz = NUL;
                break;
            }
        }
    }

leave:
    printf(zOptionFullName, name);
}
Example #11
0
static void
emit_setup(tOptions * opts)
{
    tOptDesc *   od     = opts->pOptDesc;
    int          opt_ct = opts->presetOptCt;
    char const * fmt;
    char const * def_val;

    for (;opt_ct > 0; od++, --opt_ct) {
        char int_val_buf[32];

        /*
         *  Options that are either usage documentation or are compiled out
         *  are not to be processed.
         */
        if (SKIP_OPT(od) || (od->pz_NAME == NULL))
            continue;

        if (od->optMaxCt > 1)
             fmt = MULTI_DEF_FMT;
        else fmt = SGL_DEF_FMT;

        /*
         *  IF this is an enumeration/bitmask option, then convert the value
         *  to a string before printing the default value.
         */
        switch (OPTST_GET_ARGTYPE(od->fOptState)) {
        case OPARG_TYPE_ENUMERATION:
            (*(od->pOptProc))(OPTPROC_EMIT_SHELL, od );
            def_val = od->optArg.argString;
            break;

        /*
         *  Numeric and membership bit options are just printed as a number.
         */
        case OPARG_TYPE_NUMERIC:
            snprintf(int_val_buf, sizeof(int_val_buf), "%d",
                     (int)od->optArg.argInt);
            def_val = int_val_buf;
            break;

        case OPARG_TYPE_MEMBERSHIP:
            snprintf(int_val_buf, sizeof(int_val_buf), "%lu",
                     (unsigned long)od->optArg.argIntptr);
            def_val = int_val_buf;
            break;

        case OPARG_TYPE_BOOLEAN:
            def_val = (od->optArg.argBool) ? TRUE_STR : FALSE_STR;
            break;

        default:
            if (od->optArg.argString == NULL) {
                if (fmt == SGL_DEF_FMT)
                    fmt = SGL_NO_DEF_FMT;
                def_val = NULL;
            }
            else
                def_val = od->optArg.argString;
        }

        printf(fmt, opts->pzPROGNAME, od->pz_NAME, def_val);
    }
}
Example #12
0
/*=export_func  optionPutShell
 * what:  write a portable shell script to parse options
 * private:
 * arg:   tOptions*, pOpts, the program options descriptor
 * doc:   This routine will emit portable shell script text for parsing
 *        the options described in the option definitions.
=*/
void
optionPutShell(tOptions* pOpts)
{
    int  optIx = 0;
    tSCC zOptCtFmt[]  = "OPTION_CT=%d\nexport OPTION_CT\n";
    tSCC zOptDisabl[] = "%1$s_%2$s=%3$s\nexport %1$s_%2$s\n";
    tSCC zFullOptFmt[]= "%1$s_%2$s='%3$s'\nexport %1$s_%2$s\n";
    tSCC zEquivMode[] = "%1$s_%2$s_MODE='%3$s'\nexport %1$s_%2$s_MODE\n";

    printf(zOptCtFmt, pOpts->curOptIdx-1);

    do  {
        tOptDesc* pOD = pOpts->pOptDesc + optIx;

        if (SKIP_OPT(pOD))
            continue;

        /*
         *  Equivalence classes are hard to deal with.  Where the
         *  option data wind up kind of squishes around.  For the purposes
         *  of emitting shell state, they are not recommended, but we'll
         *  do something.  I guess we'll emit the equivalenced-to option
         *  at the point in time when the base option is found.
         */
        if (pOD->optEquivIndex != NO_EQUIVALENT)
            continue; /* equivalence to a different option */

        /*
         *  Equivalenced to a different option.  Process the current option
         *  as the equivalenced-to option.  Keep the persistent state bits,
         *  but copy over the set-state bits.
         */
        if (pOD->optActualIndex != optIx) {
            tOptDesc* p   = pOpts->pOptDesc + pOD->optActualIndex;
            p->optArg     = pOD->optArg;
            p->fOptState &= OPTST_PERSISTENT_MASK;
            p->fOptState |= pOD->fOptState & ~OPTST_PERSISTENT_MASK;
            printf(zEquivMode, pOpts->pzPROGNAME, pOD->pz_NAME, p->pz_NAME);
            pOD = p;
        }

        /*
         *  If the argument type is a set membership bitmask, then we always
         *  emit the thing.  We do this because it will always have some sort
         *  of bitmask value and we need to emit the bit values.
         */
        if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_MEMBERSHIP) {
            print_membership(pOpts, pOD);
            continue;
        }

        /*
         *  IF the option was either specified or it wakes up enabled,
         *  then we will emit information.  Otherwise, skip it.
         *  The idea is that if someone defines an option to initialize
         *  enabled, we should tell our shell script that it is enabled.
         */
        if (UNUSED_OPT(pOD) && DISABLED_OPT(pOD)) {
            continue;
        }

        /*
         *  Handle stacked arguments
         */
        if (  (pOD->fOptState & OPTST_STACKED)
           && (pOD->optCookie != NULL) )  {
            print_stacked_arg(pOpts, pOD);
            continue;
        }

        /*
         *  If the argument has been disabled,
         *  Then set its value to the disablement string
         */
        if ((pOD->fOptState & OPTST_DISABLED) != 0) {
            printf(zOptDisabl, pOpts->pzPROGNAME, pOD->pz_NAME,
                   (pOD->pz_DisablePfx != NULL)
                   ? pOD->pz_DisablePfx : "false");
            continue;
        }

        /*
         *  If the argument type is numeric, the last arg pointer
         *  is really the VALUE of the string that was pointed to.
         */
        if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_NUMERIC) {
            printf(zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME,
                   (int)pOD->optArg.argInt);
            continue;
        }

        /*
         *  If the argument type is an enumeration, then it is much
         *  like a text value, except we call the callback function
         *  to emit the value corresponding to the "optArg" number.
         */
        if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_ENUMERATION) {
            print_enumeration(pOpts, pOD);
            continue;
        }

        /*
         *  If the argument type is numeric, the last arg pointer
         *  is really the VALUE of the string that was pointed to.
         */
        if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_BOOLEAN) {
            printf(zFullOptFmt, pOpts->pzPROGNAME, pOD->pz_NAME,
                   (pOD->optArg.argBool == 0) ? "false" : "true");
            continue;
        }

        /*
         *  IF the option has an empty value,
         *  THEN we set the argument to the occurrence count.
         */
        if (  (pOD->optArg.argString == NULL)
           || (pOD->optArg.argString[0] == NUL) ) {

            printf(zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME,
                   pOD->optOccCt);
            continue;
        }

        /*
         *  This option has a text value
         */
        printf(zOptValFmt, pOpts->pzPROGNAME, pOD->pz_NAME);
        print_quot_str(pOD->optArg.argString);
        printf(zOptEnd, pOpts->pzPROGNAME, pOD->pz_NAME);

    } while (++optIx < pOpts->presetOptCt );

    if (  ((pOpts->fOptSet & OPTPROC_REORDER) != 0)
       && (pOpts->curOptIdx < pOpts->origArgCt))
        print_reordering(pOpts);

    fflush(stdout);
}
Example #13
0
/*
 *  Emit the match text for a long option
 */
static void
emitMatchExpr( tCC* pzMatchName, tOptDesc* pCurOpt, tOptions* pOpts )
{
    tOptDesc* pOD = pOpts->pOptDesc;
    int       oCt = pOpts->optCt;
    int       min = 1;
    char      zName[ 256 ];
    char*     pz  = zName;

    for (;;) {
        int matchCt = 0;

        /*
         *  Omit the current option, Documentation opts and compiled out opts.
         */
        if ((pOD == pCurOpt) || SKIP_OPT(pOD)){
            if (--oCt <= 0)
                break;
            pOD++;
            continue;
        }

        /*
         *  Check each character of the name case insensitively.
         *  They must not be the same.  They cannot be, because it would
         *  not compile correctly if they were.
         */
        while (  toupper( pOD->pz_Name[matchCt] )
              == toupper( pzMatchName[matchCt] ))
            matchCt++;

        if (matchCt > min)
            min = matchCt;

        /*
         *  Check the disablement name, too.
         */
        if (pOD->pz_DisableName != NULL) {
            matchCt = 0;
            while (  toupper( pOD->pz_DisableName[matchCt] )
                  == toupper( pzMatchName[matchCt] ))
                matchCt++;
            if (matchCt > min)
                min = matchCt;
        }
        if (--oCt <= 0)
            break;
        pOD++;
    }

    /*
     *  IF the 'min' is all or one short of the name length,
     *  THEN the entire string must be matched.
     */
    if (  (pzMatchName[min  ] == NUL)
       || (pzMatchName[min+1] == NUL) )
        printf( zOptionFullName, pzMatchName );

    else {
        int matchCt = 0;
        for (; matchCt <= min; matchCt++)
            *pz++ = pzMatchName[matchCt];

        for (;;) {
            *pz = NUL;
            printf( zOptionPartName, zName );
            *pz++ = pzMatchName[matchCt++];
            if (pzMatchName[matchCt] == NUL) {
                *pz = NUL;
                printf( zOptionFullName, zName );
                break;
            }
        }
    }
}
Example #14
0
static void
emitSetup( tOptions* pOpts )
{
    tOptDesc* pOptDesc = pOpts->pOptDesc;
    int       optionCt = pOpts->presetOptCt;
    char const* pzFmt;
    char const* pzDefault;

    for (;optionCt > 0; pOptDesc++, --optionCt) {
        char zVal[16];

        /*
         *  Options that are either usage documentation or are compiled out
         *  are not to be processed.
         */
        if (SKIP_OPT(pOptDesc) || (pOptDesc->pz_NAME == NULL))
            continue;

        if (pOptDesc->optMaxCt > 1)
             pzFmt = zMultiDef;
        else pzFmt = zSingleDef;

        /*
         *  IF this is an enumeration/bitmask option, then convert the value
         *  to a string before printing the default value.
         */
        switch (OPTST_GET_ARGTYPE(pOptDesc->fOptState)) {
        case OPARG_TYPE_ENUMERATION:
            (*(pOptDesc->pOptProc))(OPTPROC_EMIT_SHELL, pOptDesc );
            pzDefault = pOptDesc->optArg.argString;
            break;

        /*
         *  Numeric and membership bit options are just printed as a number.
         */
        case OPARG_TYPE_NUMERIC:
            snprintf( zVal, sizeof( zVal ), "%d",
                      (int)pOptDesc->optArg.argInt );
            pzDefault = zVal;
            break;

        case OPARG_TYPE_MEMBERSHIP:
            snprintf( zVal, sizeof( zVal ), "%lu",
                      (unsigned long)pOptDesc->optArg.argIntptr );
            pzDefault = zVal;
            break;

        case OPARG_TYPE_BOOLEAN:
            pzDefault = (pOptDesc->optArg.argBool) ? "true" : "false";
            break;

        default:
            if (pOptDesc->optArg.argString == NULL) {
                if (pzFmt == zSingleDef)
                    pzFmt = zSingleNoDef;
                pzDefault = NULL;
            }
            else
                pzDefault = pOptDesc->optArg.argString;
        }

        printf( pzFmt, pOpts->pzPROGNAME, pOptDesc->pz_NAME, pzDefault );
    }
}
Example #15
0
/*=export_func  optionPutShell
 * what:  write a portable shell script to parse options
 * private:
 * arg:   tOptions*, pOpts, the program options descriptor
 * doc:   This routine will emit portable shell script text for parsing
 *        the options described in the option definitions.
=*/
void
optionPutShell( tOptions* pOpts )
{
    int  optIx = 0;
    tSCC zOptCtFmt[]  = "OPTION_CT=%d\nexport OPTION_CT\n";
    tSCC zOptNumFmt[] = "%1$s_%2$s=%3$d # 0x%3$X\nexport %1$s_%2$s\n";
    tSCC zOptDisabl[] = "%1$s_%2$s=%3$s\nexport %1$s_%2$s\n";
    tSCC zOptValFmt[] = "%s_%s=";
    tSCC zOptEnd[]    = "\nexport %s_%s\n";
    tSCC zFullOptFmt[]= "%1$s_%2$s='%3$s'\nexport %1$s_%2$s\n";
    tSCC zEquivMode[] = "%1$s_%2$s_MODE='%3$s'\nexport %1$s_%2$s_MODE\n";

    printf( zOptCtFmt, pOpts->curOptIdx-1 );

    do  {
        tOptDesc* pOD = pOpts->pOptDesc + optIx;

        if (SKIP_OPT(pOD))
            continue;

        /*
         *  Equivalence classes are hard to deal with.  Where the
         *  option data wind up kind of squishes around.  For the purposes
         *  of emitting shell state, they are not recommended, but we'll
         *  do something.  I guess we'll emit the equivalenced-to option
         *  at the point in time when the base option is found.
         */
        if (pOD->optEquivIndex != NO_EQUIVALENT)
            continue; /* equivalence to a different option */

        /*
         *  Equivalenced to a different option.  Process the current option
         *  as the equivalenced-to option.  Keep the persistent state bits,
         *  but copy over the set-state bits.
         */
        if (pOD->optActualIndex != optIx) {
            tOptDesc* p   = pOpts->pOptDesc + pOD->optActualIndex;
            p->optArg     = pOD->optArg;
            p->fOptState &= OPTST_PERSISTENT_MASK;
            p->fOptState |= pOD->fOptState & ~OPTST_PERSISTENT_MASK;
            printf( zEquivMode, pOpts->pzPROGNAME, pOD->pz_NAME, p->pz_NAME );
            pOD = p;
        }

        /*
         *  If the argument type is a set membership bitmask, then we always
         *  emit the thing.  We do this because it will always have some sort
         *  of bitmask value and we need to emit the bit values.
         */
        if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_MEMBERSHIP) {
            char const * pz;
            uintptr_t val = 1;
            printf( zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME,
                    (int)(uintptr_t)(pOD->optCookie) );
            pOD->optCookie = (void*)(uintptr_t)~0UL;
            (*(pOD->pOptProc))( (tOptions*)2UL, pOD );

            /*
             *  We are building the typeset list.  The list returned starts with
             *  'none + ' for use by option saving stuff.  We must ignore that.
             */
            pz = pOD->optArg.argString + 7;
            while (*pz != NUL) {
                printf( "typeset -x -i %s_", pOD->pz_NAME );
                pz += strspn( pz, " +\t\n\f" );
                for (;;) {
                    int ch = *(pz++);
                         if (islower( ch ))  fputc( toupper( ch ), stdout );
                    else if (isalnum( ch ))  fputc( ch, stdout );
                    else if (isspace( ch )
                          || (ch == '+'))    goto name_done;
                    else if (ch == NUL)      { pz--; goto name_done; }
                    else fputc( '_', stdout );
                } name_done:;
                printf( "=%1$lu # 0x%1$lX\n", (unsigned long)val );
                val <<= 1;
            }

            AGFREE(pOD->optArg.argString);
            pOD->optArg.argString = NULL;
            pOD->fOptState &= ~OPTST_ALLOC_ARG;
            continue;
        }

        /*
         *  IF the option was either specified or it wakes up enabled,
         *  then we will emit information.  Otherwise, skip it.
         *  The idea is that if someone defines an option to initialize
         *  enabled, we should tell our shell script that it is enabled.
         */
        if (UNUSED_OPT( pOD ) && DISABLED_OPT( pOD ))
            continue;

        /*
         *  Handle stacked arguments
         */
        if (  (pOD->fOptState & OPTST_STACKED)
           && (pOD->optCookie != NULL) )  {
            tSCC zOptCookieCt[] = "%1$s_%2$s_CT=%3$d\nexport %1$s_%2$s_CT\n";

            tArgList*    pAL = (tArgList*)pOD->optCookie;
            tCC**        ppz = pAL->apzArgs;
            int          ct  = pAL->useCt;

            printf( zOptCookieCt, pOpts->pzPROGNAME, pOD->pz_NAME, ct );

            while (--ct >= 0) {
                tSCC numarg_z[] = "%s_%s_%d=";
                tSCC end_z[]    = "\nexport %s_%s_%d\n";

                printf( numarg_z, pOpts->pzPROGNAME, pOD->pz_NAME,
                        pAL->useCt - ct );
                putQuotedStr( *(ppz++) );
                printf( end_z, pOpts->pzPROGNAME, pOD->pz_NAME,
                        pAL->useCt - ct );
            }
        }

        /*
         *  If the argument has been disabled,
         *  Then set its value to the disablement string
         */
        else if ((pOD->fOptState & OPTST_DISABLED) != 0)
            printf( zOptDisabl, pOpts->pzPROGNAME, pOD->pz_NAME,
                    (pOD->pz_DisablePfx != NULL)
                    ? pOD->pz_DisablePfx : "false" );

        /*
         *  If the argument type is numeric, the last arg pointer
         *  is really the VALUE of the string that was pointed to.
         */
        else if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_NUMERIC)
            printf( zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME,
                    (int)pOD->optArg.argInt );

        /*
         *  If the argument type is an enumeration, then it is much
         *  like a text value, except we call the callback function
         *  to emit the value corresponding to the "optArg" number.
         */
        else if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_ENUMERATION) {
            printf( zOptValFmt, pOpts->pzPROGNAME, pOD->pz_NAME );
            fputc( '\'', stdout );
            (*(pOD->pOptProc))( (tOptions*)1UL, pOD );
            fputc( '\'', stdout );
            printf( zOptEnd, pOpts->pzPROGNAME, pOD->pz_NAME );
        }

        /*
         *  If the argument type is numeric, the last arg pointer
         *  is really the VALUE of the string that was pointed to.
         */
        else if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_BOOLEAN)
            printf( zFullOptFmt, pOpts->pzPROGNAME, pOD->pz_NAME,
                    (pOD->optArg.argBool == 0) ? "false" : "true" );

        /*
         *  IF the option has an empty value,
         *  THEN we set the argument to the occurrence count.
         */
        else if (  (pOD->optArg.argString == NULL)
                || (pOD->optArg.argString[0] == NUL) )

            printf( zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME,
                    pOD->optOccCt );

        /*
         *  This option has a text value
         */
        else {
            printf( zOptValFmt, pOpts->pzPROGNAME, pOD->pz_NAME );
            putQuotedStr( pOD->optArg.argString );
            printf( zOptEnd, pOpts->pzPROGNAME, pOD->pz_NAME );
        }
    } while (++optIx < pOpts->presetOptCt );

    if (  ((pOpts->fOptSet & OPTPROC_REORDER) != 0)
       && (pOpts->curOptIdx < pOpts->origArgCt)) {
        fputs( "set --", stdout );
        for (optIx = pOpts->curOptIdx; optIx < pOpts->origArgCt; optIx++) {
            char* pzArg = pOpts->origArgVect[ optIx ];
            if (strchr( pzArg, '\'' ) == NULL)
                printf( " '%s'", pzArg );
            else {
                fputs( " '", stdout );
                for (;;) {
                    char ch = *(pzArg++);
                    switch (ch) {
                    case '\'':  fputs( "'\\''", stdout ); break;
                    case NUL:   goto arg_done;
                    default:    fputc( ch, stdout ); break;
                    }
                } arg_done:;
                fputc( '\'', stdout );
            }
        }
        fputs( "\nOPTION_CT=0\n", stdout );
    }
}
Example #16
0
/**
 *  Determine the number of options that match the name
 *
 * @param pOpts      option data
 * @param opt_name   name of option to look for
 * @param nm_len     length of provided name
 * @param index      pointer to int for option index
 * @param disable    pointer to bool to mark disabled option
 * @return count of options that match
 */
static int
opt_match_ct(tOptions * opts, char const * name, int nm_len,
             int * ixp, bool * disable)
{
    int   matchCt  = 0;
    int   idx      = 0;
    int   idxLim   = opts->optCt;
    tOptDesc * pOD = opts->pOptDesc;

    do  {
        /*
         *  If option disabled or a doc option, skip to next
         */
        if (pOD->pz_Name == NULL)
            continue;

        if (  SKIP_OPT(pOD)
           && (pOD->fOptState != (OPTST_OMITTED | OPTST_NO_INIT)))
            continue;

        if (strneqvcmp(name, pOD->pz_Name, nm_len) == 0) {
            /*
             *  IF we have a complete match
             *  THEN it takes priority over any already located partial
             */
            if (pOD->pz_Name[ nm_len ] == NUL) {
                *ixp = idx;
                return 1;
            }
        }

        /*
         *  IF       there is a disable name
         *     *AND* the option name matches the disable name
         *  THEN ...
         */
        else if (  (pOD->pz_DisableName != NULL)
                && (strneqvcmp(name, pOD->pz_DisableName, nm_len) == 0)
                )  {
            *disable = true;

            /*
             *  IF we have a complete match
             *  THEN it takes priority over any already located partial
             */
            if (pOD->pz_DisableName[ nm_len ] == NUL) {
                *ixp = idx;
                return 1;
            }
        }

        else
            continue; /* does not match any option */

        /*
         *  We found a full or partial match, either regular or disabling.
         *  Remember the index for later.
         */
        *ixp = idx;
        ++matchCt;

    } while (pOD++, (++idx < idxLim));

    return matchCt;
}