Home | History | Annotate | Line # | Download | only in libopts
      1 /*	$NetBSD: numeric.c,v 1.9 2024/08/18 20:47:24 christos Exp $	*/
      2 
      3 
      4 /**
      5  * \file numeric.c
      6  *
      7  * Handle options with numeric (integer) arguments.
      8  *
      9  * @addtogroup autoopts
     10  * @{
     11  */
     12 /*
     13  *  This file is part of AutoOpts, a companion to AutoGen.
     14  *  AutoOpts is free software.
     15  *  AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved
     16  *
     17  *  AutoOpts is available under any one of two licenses.  The license
     18  *  in use must be one of these two and the choice is under the control
     19  *  of the user of the license.
     20  *
     21  *   The GNU Lesser General Public License, version 3 or later
     22  *      See the files "COPYING.lgplv3" and "COPYING.gplv3"
     23  *
     24  *   The Modified Berkeley Software Distribution License
     25  *      See the file "COPYING.mbsd"
     26  *
     27  *  These files have the following sha256 sums:
     28  *
     29  *  8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95  COPYING.gplv3
     30  *  4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b  COPYING.lgplv3
     31  *  13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239  COPYING.mbsd
     32  */
     33 
     34 /*=export_func  optionShowRange
     35  * private:
     36  *
     37  * what:  Show info about range constraints
     38  * arg:   + tOptions * + pOpts     + program options descriptor  +
     39  * arg:   + tOptDesc * + pOptDesc  + the descriptor for this arg +
     40  * arg:   + void *     + rng_table + the value range tables      +
     41  * arg:   + int        + rng_count + the number of entries       +
     42  *
     43  * doc:
     44  *   Show information about a numeric option with range constraints.
     45 =*/
     46 void
     47 optionShowRange(tOptions * pOpts, tOptDesc * pOD, void * rng_table, int rng_ct)
     48 {
     49     const struct {long const rmin, rmax;} * rng = rng_table;
     50 
     51     char const * pz_indent = zTabHyp + tab_skip_ct;
     52 
     53     /*
     54      * The range is shown only for full usage requests and an error
     55      * in this particular option.
     56      */
     57     if (pOpts != OPTPROC_EMIT_USAGE) {
     58         if (pOpts <= OPTPROC_EMIT_LIMIT)
     59             return;
     60         pz_indent = ONE_TAB_STR;
     61 
     62         fprintf(option_usage_fp, zRangeErr, pOpts->pzProgName,
     63                 pOD->pz_Name, pOD->optArg.argInt);
     64         pz_indent = "";
     65     }
     66 
     67     if (pOD->fOptState & OPTST_SCALED_NUM)
     68         fprintf(option_usage_fp, zRangeScaled, pz_indent);
     69 
     70     fprintf(option_usage_fp, (rng_ct > 1) ? zRangeLie : zRangeOnly, pz_indent);
     71     pz_indent = (pOpts != OPTPROC_EMIT_USAGE)
     72         ? ONE_TAB_STR
     73         : (zTabSpace + tab_skip_ct);
     74 
     75     for (;;) {
     76         if (rng->rmax == LONG_MIN)
     77             fprintf(option_usage_fp, zRangeExact, pz_indent, rng->rmin);
     78         else if (rng->rmin == LONG_MIN)
     79             fprintf(option_usage_fp, zRangeUpto, pz_indent, rng->rmax);
     80         else if (rng->rmax == LONG_MAX)
     81             fprintf(option_usage_fp, zRangeAbove, pz_indent, rng->rmin);
     82         else
     83             fprintf(option_usage_fp, zRange, pz_indent, rng->rmin,
     84                     rng->rmax);
     85 
     86         if  (--rng_ct <= 0) {
     87             fputc(NL, option_usage_fp);
     88             break;
     89         }
     90         fputs(zRangeOr, option_usage_fp);
     91         rng++;
     92     }
     93 
     94     if (pOpts > OPTPROC_EMIT_LIMIT)
     95         pOpts->pUsageProc(pOpts, EXIT_FAILURE);
     96 }
     97 
     98 /*=export_func  optionNumericVal
     99  * private:
    100  *
    101  * what:  process an option with a numeric value.
    102  * arg:   + tOptions * + opts + program options descriptor +
    103  * arg:   + tOptDesc * + od   + the descriptor for this arg +
    104  *
    105  * doc:
    106  *  Decipher a numeric value.
    107 =*/
    108 void
    109 optionNumericVal(tOptions * opts, tOptDesc * od)
    110 {
    111     char * pz;
    112     long   val;
    113 
    114     /*
    115      *  Guard against all the different ways this procedure might get invoked
    116      *  when there is no string argument provided.
    117      */
    118     if (INQUERY_CALL(opts, od) || (od->optArg.argString == NULL))
    119         return;
    120 
    121     /*
    122      *  Numeric options may have a range associated with it.
    123      *  If it does, the usage procedure requests that it be
    124      *  emitted by passing a NULL od pointer.  Also bail out
    125      *  if there is no option argument or if we are being reset.
    126      */
    127     if (  (od == NULL)
    128        || (od->optArg.argString == NULL)
    129        || ((od->fOptState & OPTST_RESET) != 0)
    130        || (opts <= OPTPROC_EMIT_LIMIT))
    131         return;
    132 
    133     errno = 0;
    134     val = strtol(od->optArg.argString, &pz, 0);
    135     if ((pz == od->optArg.argString) || (errno != 0))
    136         goto bad_number;
    137 
    138     if ((od->fOptState & OPTST_SCALED_NUM) != 0)
    139         switch (*(pz++)) {
    140         case NUL:  pz--; break;
    141         case 't':  val *= 1000; /* FALLTHROUGH */
    142         case 'g':  val *= 1000; /* FALLTHROUGH */
    143         case 'm':  val *= 1000; /* FALLTHROUGH */
    144         case 'k':  val *= 1000; break;
    145 
    146         case 'T':  val *= 1024; /* FALLTHROUGH */
    147         case 'G':  val *= 1024; /* FALLTHROUGH */
    148         case 'M':  val *= 1024; /* FALLTHROUGH */
    149         case 'K':  val *= 1024; break;
    150 
    151         default:   goto bad_number;
    152         }
    153 
    154     if (*pz != NUL)
    155         goto bad_number;
    156 
    157     if (od->fOptState & OPTST_ALLOC_ARG) {
    158         AGFREE(od->optArg.argString);
    159         od->fOptState &= ~OPTST_ALLOC_ARG;
    160     }
    161 
    162     od->optArg.argInt = val;
    163     return;
    164 
    165     bad_number:
    166 
    167     fprintf( stderr, zNotNumber, opts->pzProgName, od->optArg.argString );
    168     if ((opts->fOptSet & OPTPROC_ERRSTOP) != 0)
    169         (*(opts->pUsageProc))(opts, EXIT_FAILURE);
    170 
    171     errno = EINVAL;
    172     od->optArg.argInt = ~0;
    173 }
    174 
    175 /** @}
    176  *
    177  * Local Variables:
    178  * mode: C
    179  * c-file-style: "stroustrup"
    180  * indent-tabs-mode: nil
    181  * End:
    182  * end of autoopts/numeric.c */
    183