Blame src/libopts/numeric.c

Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * \file numeric.c
Packit 549fdc
 *
Packit 549fdc
 * Handle options with numeric (integer) arguments.
Packit 549fdc
 *
Packit 549fdc
 * @addtogroup autoopts
Packit 549fdc
 * @{
Packit 549fdc
 */
Packit 549fdc
/*
Packit 549fdc
 *  This file is part of AutoOpts, a companion to AutoGen.
Packit 549fdc
 *  AutoOpts is free software.
Packit 549fdc
 *  AutoOpts is Copyright (C) 1992-2015 by Bruce Korb - all rights reserved
Packit 549fdc
 *
Packit 549fdc
 *  AutoOpts is available under any one of two licenses.  The license
Packit 549fdc
 *  in use must be one of these two and the choice is under the control
Packit 549fdc
 *  of the user of the license.
Packit 549fdc
 *
Packit 549fdc
 *   The GNU Lesser General Public License, version 3 or later
Packit 549fdc
 *      See the files "COPYING.lgplv3" and "COPYING.gplv3"
Packit 549fdc
 *
Packit 549fdc
 *   The Modified Berkeley Software Distribution License
Packit 549fdc
 *      See the file "COPYING.mbsd"
Packit 549fdc
 *
Packit 549fdc
 *  These files have the following sha256 sums:
Packit 549fdc
 *
Packit 549fdc
 *  8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95  COPYING.gplv3
Packit 549fdc
 *  4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b  COPYING.lgplv3
Packit 549fdc
 *  13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239  COPYING.mbsd
Packit 549fdc
 */
Packit 549fdc
Packit 549fdc
/*=export_func  optionShowRange
Packit 549fdc
 * private:
Packit 549fdc
 *
Packit 549fdc
 * what:  Show info about range constraints
Packit 549fdc
 * arg:   + tOptions * + pOpts     + program options descriptor  +
Packit 549fdc
 * arg:   + tOptDesc * + pOptDesc  + the descriptor for this arg +
Packit 549fdc
 * arg:   + void *     + rng_table + the value range tables      +
Packit 549fdc
 * arg:   + int        + rng_count + the number of entries       +
Packit 549fdc
 *
Packit 549fdc
 * doc:
Packit 549fdc
 *   Show information about a numeric option with range constraints.
Packit 549fdc
=*/
Packit 549fdc
void
Packit 549fdc
optionShowRange(tOptions * pOpts, tOptDesc * pOD, void * rng_table, int rng_ct)
Packit 549fdc
{
Packit 549fdc
    const struct {long const rmin, rmax;} * rng = rng_table;
Packit 549fdc
Packit 549fdc
    char const * pz_indent = zTabHyp + tab_skip_ct;
Packit 549fdc
Packit 549fdc
    /*
Packit 549fdc
     * The range is shown only for full usage requests and an error
Packit 549fdc
     * in this particular option.
Packit 549fdc
     */
Packit 549fdc
    if (pOpts != OPTPROC_EMIT_USAGE) {
Packit 549fdc
        if (pOpts <= OPTPROC_EMIT_LIMIT)
Packit 549fdc
            return;
Packit 549fdc
        pz_indent = ONE_TAB_STR;
Packit 549fdc
Packit 549fdc
        fprintf(option_usage_fp, zRangeErr, pOpts->pzProgName,
Packit 549fdc
                pOD->pz_Name, pOD->optArg.argInt);
Packit 549fdc
        pz_indent = "";
Packit 549fdc
    }
Packit 549fdc
Packit 549fdc
    if (pOD->fOptState & OPTST_SCALED_NUM)
Packit 549fdc
        fprintf(option_usage_fp, zRangeScaled, pz_indent);
Packit 549fdc
Packit 549fdc
    fprintf(option_usage_fp, (rng_ct > 1) ? zRangeLie : zRangeOnly, pz_indent);
Packit 549fdc
    pz_indent = (pOpts != OPTPROC_EMIT_USAGE)
Packit 549fdc
        ? ONE_TAB_STR
Packit 549fdc
        : (zTabSpace + tab_skip_ct);
Packit 549fdc
Packit 549fdc
    for (;;) {
Packit 549fdc
        if (rng->rmax == LONG_MIN)
Packit 549fdc
            fprintf(option_usage_fp, zRangeExact, pz_indent, rng->rmin);
Packit 549fdc
        else if (rng->rmin == LONG_MIN)
Packit 549fdc
            fprintf(option_usage_fp, zRangeUpto, pz_indent, rng->rmax);
Packit 549fdc
        else if (rng->rmax == LONG_MAX)
Packit 549fdc
            fprintf(option_usage_fp, zRangeAbove, pz_indent, rng->rmin);
Packit 549fdc
        else
Packit 549fdc
            fprintf(option_usage_fp, zRange, pz_indent, rng->rmin,
Packit 549fdc
                    rng->rmax);
Packit 549fdc
Packit 549fdc
        if  (--rng_ct <= 0) {
Packit 549fdc
            fputc(NL, option_usage_fp);
Packit 549fdc
            break;
Packit 549fdc
        }
Packit 549fdc
        fputs(zRangeOr, option_usage_fp);
Packit 549fdc
        rng++;
Packit 549fdc
    }
Packit 549fdc
Packit 549fdc
    if (pOpts > OPTPROC_EMIT_LIMIT)
Packit 549fdc
        pOpts->pUsageProc(pOpts, EXIT_FAILURE);
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/*=export_func  optionNumericVal
Packit 549fdc
 * private:
Packit 549fdc
 *
Packit 549fdc
 * what:  process an option with a numeric value.
Packit 549fdc
 * arg:   + tOptions * + opts + program options descriptor +
Packit 549fdc
 * arg:   + tOptDesc * + od   + the descriptor for this arg +
Packit 549fdc
 *
Packit 549fdc
 * doc:
Packit 549fdc
 *  Decipher a numeric value.
Packit 549fdc
=*/
Packit 549fdc
void
Packit 549fdc
optionNumericVal(tOptions * opts, tOptDesc * od)
Packit 549fdc
{
Packit 549fdc
    char * pz;
Packit 549fdc
    long   val;
Packit 549fdc
Packit 549fdc
    /*
Packit 549fdc
     *  Guard against all the different ways this procedure might get invoked
Packit 549fdc
     *  when there is no string argument provided.
Packit 549fdc
     */
Packit 549fdc
    if (INQUERY_CALL(opts, od) || (od->optArg.argString == NULL))
Packit 549fdc
        return;
Packit 549fdc
Packit 549fdc
    /*
Packit 549fdc
     *  Numeric options may have a range associated with it.
Packit 549fdc
     *  If it does, the usage procedure requests that it be
Packit 549fdc
     *  emitted by passing a NULL od pointer.  Also bail out
Packit 549fdc
     *  if there is no option argument or if we are being reset.
Packit 549fdc
     */
Packit 549fdc
    if (  (od == NULL)
Packit 549fdc
       || (od->optArg.argString == NULL)
Packit 549fdc
       || ((od->fOptState & OPTST_RESET) != 0)
Packit 549fdc
       || (opts <= OPTPROC_EMIT_LIMIT))
Packit 549fdc
        return;
Packit 549fdc
Packit 549fdc
    errno = 0;
Packit 549fdc
    val = strtol(od->optArg.argString, &pz, 0);
Packit 549fdc
    if ((pz == od->optArg.argString) || (errno != 0))
Packit 549fdc
        goto bad_number;
Packit 549fdc
Packit 549fdc
    if ((od->fOptState & OPTST_SCALED_NUM) != 0)
Packit 549fdc
        switch (*(pz++)) {
Packit 549fdc
        case NUL:  pz--; break;
Packit 549fdc
        case 't':  val *= 1000;
Packit 549fdc
        case 'g':  val *= 1000;
Packit 549fdc
        case 'm':  val *= 1000;
Packit 549fdc
        case 'k':  val *= 1000; break;
Packit 549fdc
Packit 549fdc
        case 'T':  val *= 1024;
Packit 549fdc
        case 'G':  val *= 1024;
Packit 549fdc
        case 'M':  val *= 1024;
Packit 549fdc
        case 'K':  val *= 1024; break;
Packit 549fdc
Packit 549fdc
        default:   goto bad_number;
Packit 549fdc
        }
Packit 549fdc
Packit 549fdc
    if (*pz != NUL)
Packit 549fdc
        goto bad_number;
Packit 549fdc
Packit 549fdc
    if (od->fOptState & OPTST_ALLOC_ARG) {
Packit 549fdc
        AGFREE(od->optArg.argString);
Packit 549fdc
        od->fOptState &= ~OPTST_ALLOC_ARG;
Packit 549fdc
    }
Packit 549fdc
Packit 549fdc
    od->optArg.argInt = val;
Packit 549fdc
    return;
Packit 549fdc
Packit 549fdc
    bad_number:
Packit 549fdc
Packit 549fdc
    fprintf( stderr, zNotNumber, opts->pzProgName, od->optArg.argString );
Packit 549fdc
    if ((opts->fOptSet & OPTPROC_ERRSTOP) != 0)
Packit 549fdc
        (*(opts->pUsageProc))(opts, EXIT_FAILURE);
Packit 549fdc
Packit 549fdc
    errno = EINVAL;
Packit 549fdc
    od->optArg.argInt = ~0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/** @}
Packit 549fdc
 *
Packit 549fdc
 * Local Variables:
Packit 549fdc
 * mode: C
Packit 549fdc
 * c-file-style: "stroustrup"
Packit 549fdc
 * indent-tabs-mode: nil
Packit 549fdc
 * End:
Packit 549fdc
 * end of autoopts/numeric.c */