Ejemplo n.º 1
0
/**
 *  check for preset values from a config files or envrionment variables
 *
 * @param[in,out] opts  the structure with the option names to check
 */
static tSuccess
do_presets(tOptions * opts)
{
    tOptDesc * od = NULL;

    if (! SUCCESSFUL(immediate_opts(opts)))
        return FAILURE;

    /*
     *  IF this option set has a --save-opts option, then it also
     *  has a --load-opts option.  See if a command line option has disabled
     *  option presetting.
     */
    if (  (opts->specOptIdx.save_opts != NO_EQUIVALENT)
       && (opts->specOptIdx.save_opts != 0)) {
        od = opts->pOptDesc + opts->specOptIdx.save_opts + 1;
        if (DISABLED_OPT(od))
            return SUCCESS;
    }

    /*
     *  Until we return from this procedure, disable non-presettable opts
     */
    opts->fOptSet |= OPTPROC_PRESETTING;
    /*
     *  IF there are no config files,
     *  THEN do any environment presets and leave.
     */
    if (opts->papzHomeList == NULL) {
        env_presets(opts, ENV_ALL);
    }
    else {
        env_presets(opts, ENV_IMM);

        /*
         *  Check to see if environment variables have disabled presetting.
         */
        if ((od != NULL) && ! DISABLED_OPT(od))
            intern_file_load(opts);

        /*
         *  ${PROGRAM_LOAD_OPTS} value of "no" cannot disable other environment
         *  variable options.  Only the loading of .rc files.
         */
        env_presets(opts, ENV_NON_IMM);
    }
    opts->fOptSet &= ~OPTPROC_PRESETTING;

    return SUCCESS;
}
Ejemplo n.º 2
0
/*=export_func  optionLoadOpt
 * private:
 *
 * what:  Load an option rc/ini file
 * arg:   + tOptions* + pOpts    + program options descriptor +
 * arg:   + tOptDesc* + pOptDesc + the descriptor for this arg +
 *
 * doc:
 *  Processes the options found in the file named with
 *  pOptDesc->optArg.argString.
=*/
void
optionLoadOpt( tOptions* pOpts, tOptDesc* pOptDesc )
{
    /*
     *  IF the option is not being disabled, THEN load the file.  There must
     *  be a file.  (If it is being disabled, then the disablement processing
     *  already took place.  It must be done to suppress preloading of ini/rc
     *  files.)
     */
    if (! DISABLED_OPT( pOptDesc )) {
        struct stat sb;
        if (stat( pOptDesc->optArg.argString, &sb ) != 0) {
            if ((pOpts->fOptSet & OPTPROC_ERRSTOP) == 0)
                return;

            fprintf( stderr, zFSErrOptLoad, errno, strerror( errno ),
                     pOptDesc->optArg.argString );
            exit(EX_NOINPUT);
            /* NOT REACHED */
        }

        if (! S_ISREG( sb.st_mode )) {
            if ((pOpts->fOptSet & OPTPROC_ERRSTOP) == 0)
                return;

            fprintf( stderr, zNotFile, pOptDesc->optArg.argString );
            exit(EX_NOINPUT);
            /* NOT REACHED */
        }

        filePreset(pOpts, pOptDesc->optArg.argString, DIRECTION_CALLED);
    }
}
Ejemplo n.º 3
0
static void
prt_no_arg_opt(FILE * fp, tOptDesc * p, tOptDesc * pOD)
{
    /*
     * The aliased to argument indicates whether or not the option
     * is "disabled".  However, the original option has the name
     * string, so we get that there, not with "p".
     */
    char const * pznm =
        (DISABLED_OPT(p)) ? pOD->pz_DisableName : pOD->pz_Name;
    /*
     *  If the option was disabled and the disablement name is NULL,
     *  then the disablement was caused by aliasing.
     *  Use the name as the string to emit.
     */
    if (pznm == NULL)
        pznm = pOD->pz_Name;

    fprintf(fp, "%s\n", pznm);
}
Ejemplo n.º 4
0
/*=export_func  optionLoadOpt
 * private:
 *
 * what:  Load an option rc/ini file
 * arg:   + tOptions* + opts  + program options descriptor +
 * arg:   + tOptDesc* + odesc + the descriptor for this arg +
 *
 * doc:
 *  Processes the options found in the file named with
 *  odesc->optArg.argString.
=*/
void
optionLoadOpt(tOptions * opts, tOptDesc * odesc)
{
    struct stat sb;

    if (opts <= OPTPROC_EMIT_LIMIT)
        return;

    /*
     *  IF the option is not being disabled, THEN load the file.  There must
     *  be a file.  (If it is being disabled, then the disablement processing
     *  already took place.  It must be done to suppress preloading of ini/rc
     *  files.)
     */
    if (  DISABLED_OPT(odesc)
       || ((odesc->fOptState & OPTST_RESET) != 0))
        return;

    if (stat(odesc->optArg.argString, &sb) != 0) {
        if ((opts->fOptSet & OPTPROC_ERRSTOP) == 0)
            return;

        fserr_exit(opts->pzProgName, "stat", odesc->optArg.argString);
        /* NOT REACHED */
    }

    if (! S_ISREG(sb.st_mode)) {
        if ((opts->fOptSet & OPTPROC_ERRSTOP) == 0)
            return;
        errno = EINVAL;
        fserr_exit(opts->pzProgName, "stat", odesc->optArg.argString);
        /* NOT REACHED */
    }

    file_preset(opts, odesc->optArg.argString, DIRECTION_CALLED);
}
Ejemplo n.º 5
0
/**
 *  Load a configuration file.  This may be invoked either from
 *  scanning the "homerc" list, or from a specific file request.
 *  (see "optionFileLoad()", the implementation for --load-opts)
 */
LOCAL void
intern_file_load(tOptions * opts)
{
    uint32_t  svfl;
    int       idx;
    int       inc;
    char      f_name[ AG_PATH_MAX+1 ];

    if (opts->papzHomeList == NULL)
        return;

    svfl = opts->fOptSet;
    inc  = DIRECTION_PRESET;

    /*
     *  Never stop on errors in config files.
     */
    opts->fOptSet &= ~OPTPROC_ERRSTOP;

    /*
     *  Find the last RC entry (highest priority entry)
     */
    for (idx = 0; opts->papzHomeList[ idx+1 ] != NULL; ++idx)  ;

    /*
     *  For every path in the home list, ...  *TWICE* We start at the last
     *  (highest priority) entry, work our way down to the lowest priority,
     *  handling the immediate options.
     *  Then we go back up, doing the normal options.
     */
    for (;;) {
        struct stat sb;
        cch_t *  path;

        /*
         *  IF we've reached the bottom end, change direction
         */
        if (idx < 0) {
            inc = DIRECTION_PROCESS;
            idx = 0;
        }

        path = opts->papzHomeList[ idx ];

        /*
         *  IF we've reached the top end, bail out
         */
        if (path == NULL)
            break;

        idx += inc;

        if (! optionMakePath(f_name, (int)sizeof(f_name),
                             path, opts->pzProgPath))
            continue;

        /*
         *  IF the file name we constructed is a directory,
         *  THEN append the Resource Configuration file name
         *  ELSE we must have the complete file name
         */
        if (stat(f_name, &sb) != 0)
            continue; /* bogus name - skip the home list entry */

        if (S_ISDIR(sb.st_mode)) {
            size_t len = strlen(f_name);
            size_t nln = strlen(opts->pzRcName) + 1;
            char * pz  = f_name + len;

            if (len + 1 + nln >= sizeof(f_name))
                continue;

            if (pz[-1] != DIRCH)
                *(pz++) = DIRCH;
            memcpy(pz, opts->pzRcName, nln);
        }

        file_preset(opts, f_name, inc);

        /*
         *  IF we are now to skip config files AND we are presetting,
         *  THEN change direction.  We must go the other way.
         */
        {
            tOptDesc * od = opts->pOptDesc + opts->specOptIdx.save_opts + 1;
            if (DISABLED_OPT(od) && PRESETTING(inc)) {
                idx -= inc;  /* go back and reprocess current file */
                inc =  DIRECTION_PROCESS;
            }
        }
    } /* twice for every path in the home list, ... */

    opts->fOptSet = svfl;
}
Ejemplo n.º 6
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;

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

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

        if ((pOD->fOptState & OPTST_NO_OUTPUT_MASK) != 0)
            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(OPT_VAL_FMT, pOpts->pzPROGNAME, pOD->pz_NAME);
        print_quot_str(pOD->optArg.argString);
        printf(OPT_END_FMT, pOpts->pzPROGNAME, pOD->pz_NAME);

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

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

    fflush(stdout);
}
Ejemplo n.º 7
0
/*  internalFileLoad
 *
 *  Load a configuration file.  This may be invoked either from
 *  scanning the "homerc" list, or from a specific file request.
 *  (see "optionFileLoad()", the implementation for --load-opts)
 */
LOCAL void
internalFileLoad( tOptions* pOpts )
{
    int     idx;
    int     inc = DIRECTION_PRESET;
    char    zFileName[ AG_PATH_MAX+1 ];

    if (pOpts->papzHomeList == NULL)
        return;

    /*
     *  Find the last RC entry (highest priority entry)
     */
    for (idx = 0; pOpts->papzHomeList[ idx+1 ] != NULL; ++idx)  ;

    /*
     *  For every path in the home list, ...  *TWICE* We start at the last
     *  (highest priority) entry, work our way down to the lowest priority,
     *  handling the immediate options.
     *  Then we go back up, doing the normal options.
     */
    for (;;) {
        struct stat StatBuf;
        cch_t*  pzPath;

        /*
         *  IF we've reached the bottom end, change direction
         */
        if (idx < 0) {
            inc = DIRECTION_PROCESS;
            idx = 0;
        }

        pzPath = pOpts->papzHomeList[ idx ];

        /*
         *  IF we've reached the top end, bail out
         */
        if (pzPath == NULL)
            break;

        idx += inc;

        if (! optionMakePath( zFileName, (int)sizeof(zFileName),
                              pzPath, pOpts->pzProgPath ))
            continue;

        /*
         *  IF the file name we constructed is a directory,
         *  THEN append the Resource Configuration file name
         *  ELSE we must have the complete file name
         */
        if (stat( zFileName, &StatBuf ) != 0)
            continue; /* bogus name - skip the home list entry */

        if (S_ISDIR( StatBuf.st_mode )) {
            size_t len = strlen( zFileName );
            char* pz;

            if (len + 1 + strlen( pOpts->pzRcName ) >= sizeof( zFileName ))
                continue;

            pz = zFileName + len;
            if (pz[-1] != DIRCH)
                *(pz++) = DIRCH;
            strcpy( pz, pOpts->pzRcName );
        }

        filePreset( pOpts, zFileName, inc );

        /*
         *  IF we are now to skip config files AND we are presetting,
         *  THEN change direction.  We must go the other way.
         */
        {
            tOptDesc * pOD = pOpts->pOptDesc + pOpts->specOptIdx.save_opts+1;
            if (DISABLED_OPT(pOD) && PRESETTING(inc)) {
                idx -= inc;  /* go back and reprocess current file */
                inc =  DIRECTION_PROCESS;
            }
        }
    } /* twice for every path in the home list, ... */
}
Ejemplo n.º 8
0
/**
 * print one option entry to the save file.
 *
 * @param[in] fp    the file pointer for the save file
 * @param[in] od    the option descriptor to print
 * @param[in] l_arg the last argument for the option
 */
static void
prt_entry(FILE * fp, tOptDesc * od, char const * l_arg)
{
    int space_ct;

    /*
     *  There is an argument.  Pad the name so values line up.
     *  Not disabled *OR* this got equivalenced to another opt,
     *  then use current option name.
     *  Otherwise, there must be a disablement name.
     */
    {
        char const * pz =
            (! DISABLED_OPT(od) || (od->optEquivIndex != NO_EQUIVALENT))
            ? od->pz_Name
            : od->pz_DisableName;
        space_ct = 17 - strlen(pz);
        fputs(pz, fp);
    }

    if (  (l_arg == NULL)
       && (OPTST_GET_ARGTYPE(od->fOptState) != OPARG_TYPE_NUMERIC))
        goto end_entry;

    fputs(" = ", fp);
    while (space_ct-- > 0)  fputc(' ', fp);

    /*
     *  IF the option is numeric only,
     *  THEN the char pointer is really the number
     */
    if (OPTST_GET_ARGTYPE(od->fOptState) == OPARG_TYPE_NUMERIC)
        fprintf(fp, "%d", (int)(t_word)l_arg);

    else {
        for (;;) {
            char const * eol = strchr(l_arg, NL);

            /*
             *  IF this is the last line
             *  THEN bail and print it
             */
            if (eol == NULL)
                break;

            /*
             *  Print the continuation and the text from the current line
             */
            (void)fwrite(l_arg, (size_t)(eol - l_arg), (size_t)1, fp);
            l_arg = eol+1; /* advance the Last Arg pointer */
            fputs("\\\n", fp);
        }

        /*
         *  Terminate the entry
         */
        fputs(l_arg, fp);
    }

end_entry:
    fputc(NL, fp);
}
Ejemplo n.º 9
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 );
    }
}
Ejemplo n.º 10
0
/*=export_func  optionSaveFile
 *
 * what:  saves the option state to a file
 *
 * arg:   tOptions*,   pOpts,  program options descriptor
 *
 * doc:
 *
 * This routine will save the state of option processing to a file.  The name
 * of that file can be specified with the argument to the @code{--save-opts}
 * option, or by appending the @code{rcfile} attribute to the last
 * @code{homerc} attribute.  If no @code{rcfile} attribute was specified, it
 * will default to @code{.@i{programname}rc}.  If you wish to specify another
 * file, you should invoke the @code{SET_OPT_SAVE_OPTS( @i{filename} )} macro.
 *
 * err:
 *
 * If no @code{homerc} file was specified, this routine will silently return
 * and do nothing.  If the output file cannot be created or updated, a message
 * will be printed to @code{stderr} and the routine will return.
=*/
void
optionSaveFile( tOptions* pOpts )
{
    tOptDesc* pOD;
    int       ct;
    FILE*     fp;

    {
        int   free_name = 0;
        tCC*  pzFName = findFileName( pOpts, &free_name );
        if (pzFName == NULL)
            return;

        fp = fopen( pzFName, "w" FOPEN_BINARY_FLAG );
        if (fp == NULL) {
            fprintf( stderr, zWarn, pOpts->pzProgName );
            fprintf( stderr, zNoCreat, errno, strerror( errno ), pzFName );
            if (free_name)
                AGFREE((void*) pzFName );
            return;
        }

        if (free_name)
            AGFREE( (void*)pzFName );
    }

    {
        char const*  pz = pOpts->pzUsageTitle;
        fputs( "#  ", fp );
        do { fputc( *pz, fp ); } while (*(pz++) != '\n');
    }

    {
        time_t  timeVal = time( NULL );
        char*   pzTime  = ctime( &timeVal );

        fprintf( fp, zPresetFile, pzTime );
#ifdef HAVE_ALLOCATED_CTIME
        /*
         *  The return values for ctime(), localtime(), and gmtime()
         *  normally point to static data that is overwritten by each call.
         *  The test to detect allocated ctime, so we leak the memory.
         */
        AGFREE( (void*)pzTime );
#endif
    }

    /*
     *  FOR each of the defined options, ...
     */
    ct  = pOpts->presetOptCt;
    pOD = pOpts->pOptDesc;
    do  {
        int arg_state;
        tOptDesc*  p;

        /*
         *  IF    the option has not been defined
         *     OR it does not take an initialization value
         *     OR it is equivalenced to another option
         *  THEN continue (ignore it)
         */
        if (UNUSED_OPT( pOD ))
            continue;

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

        if (  (pOD->optEquivIndex != NO_EQUIVALENT)
              && (pOD->optEquivIndex != pOD->optIndex))
            continue;

        /*
         *  Set a temporary pointer to the real option description
         *  (i.e. account for equivalencing)
         */
        p = ((pOD->fOptState & OPTST_EQUIVALENCE) != 0)
            ? (pOpts->pOptDesc + pOD->optActualIndex) : pOD;

        /*
         *  IF    no arguments are allowed
         *  THEN just print the name and continue
         */
        if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_NONE) {
            char const * pznm =
                (DISABLED_OPT( p )) ? p->pz_DisableName : p->pz_Name;
            /*
             *  If the option was disabled and the disablement name is NULL,
             *  then the disablement was caused by aliasing.
             *  Use the name as the string to emit.
             */
            if (pznm == NULL)
                pznm = p->pz_Name;

            fprintf(fp, "%s\n", pznm);
            continue;
        }

        arg_state = OPTST_GET_ARGTYPE(p->fOptState);
        switch (arg_state) {
        case 0:
        case OPARG_TYPE_NUMERIC:
            printEntry( fp, p, (void*)(p->optArg.argInt));
            break;

        case OPARG_TYPE_STRING:
            if (p->fOptState & OPTST_STACKED) {
                tArgList*  pAL = (tArgList*)p->optCookie;
                int        uct = pAL->useCt;
                tCC**      ppz = pAL->apzArgs;

                /*
                 *  Disallow multiple copies of disabled options.
                 */
                if (uct > 1)
                    p->fOptState &= ~OPTST_DISABLED;

                while (uct-- > 0)
                    printEntry( fp, p, *(ppz++) );
            } else {
                printEntry( fp, p, p->optArg.argString );
            }
            break;

        case OPARG_TYPE_ENUMERATION:
        case OPARG_TYPE_MEMBERSHIP:
        {
            uintptr_t val = p->optArg.argEnum;
            /*
             *  This is a magic incantation that will convert the
             *  bit flag values back into a string suitable for printing.
             */
            (*(p->pOptProc))( (tOptions*)2UL, p );
            printEntry( fp, p, (void*)(p->optArg.argString));

            if (  (p->optArg.argString != NULL)
               && (arg_state != OPARG_TYPE_ENUMERATION)) {
                /*
                 *  set membership strings get allocated
                 */
                AGFREE( (void*)p->optArg.argString );
                p->fOptState &= ~OPTST_ALLOC_ARG;
            }

            p->optArg.argEnum = val;
            break;
        }

        case OPARG_TYPE_BOOLEAN:
            printEntry( fp, p, p->optArg.argBool ? "true" : "false" );
            break;

        default:
            break; /* cannot handle - skip it */
        }
    } while ( (pOD++), (--ct > 0));

    fclose( fp );
}
Ejemplo n.º 11
0
static void
printEntry(
    FILE *     fp,
    tOptDesc * p,
    tCC*       pzLA )
{
    /*
     *  There is an argument.  Pad the name so values line up.
     *  Not disabled *OR* this got equivalenced to another opt,
     *  then use current option name.
     *  Otherwise, there must be a disablement name.
     */
    {
        char const * pz;
        if (! DISABLED_OPT(p) || (p->optEquivIndex != NO_EQUIVALENT))
            pz = p->pz_Name;
        else
            pz = p->pz_DisableName;

        fprintf(fp, "%-18s", pz);
    }
    /*
     *  IF the option is numeric only,
     *  THEN the char pointer is really the number
     */
    if (OPTST_GET_ARGTYPE(p->fOptState) == OPARG_TYPE_NUMERIC)
        fprintf( fp, "  %d\n", (int)(t_word)pzLA );

    /*
     *  OTHERWISE, FOR each line of the value text, ...
     */
    else if (pzLA == NULL)
        fputc( '\n', fp );

    else {
        fputc( ' ', fp ); fputc( ' ', fp );
        for (;;) {
            tCC* pzNl = strchr( pzLA, '\n' );

            /*
             *  IF this is the last line
             *  THEN bail and print it
             */
            if (pzNl == NULL)
                break;

            /*
             *  Print the continuation and the text from the current line
             */
            (void)fwrite( pzLA, (size_t)(pzNl - pzLA), (size_t)1, fp );
            pzLA = pzNl+1; /* advance the Last Arg pointer */
            fputs( "\\\n", fp );
        }

        /*
         *  Terminate the entry
         */
        fputs( pzLA, fp );
        fputc( '\n', fp );
    }
}