xref: /freebsd-src/contrib/ntp/sntp/libopts/numeric.c (revision a466cc55373fc3cf86837f09da729535b57e69a1)
1ea906c41SOllivier Robert 
22b15cb3dSCy Schubert /**
32b15cb3dSCy Schubert  * \file numeric.c
42b15cb3dSCy Schubert  *
52b15cb3dSCy Schubert  * Handle options with numeric (integer) arguments.
62b15cb3dSCy Schubert  *
72b15cb3dSCy Schubert  * @addtogroup autoopts
82b15cb3dSCy Schubert  * @{
92b15cb3dSCy Schubert  */
10ea906c41SOllivier Robert /*
112b15cb3dSCy Schubert  *  This file is part of AutoOpts, a companion to AutoGen.
122b15cb3dSCy Schubert  *  AutoOpts is free software.
13*a466cc55SCy Schubert  *  AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved
142b15cb3dSCy Schubert  *
152b15cb3dSCy Schubert  *  AutoOpts is available under any one of two licenses.  The license
162b15cb3dSCy Schubert  *  in use must be one of these two and the choice is under the control
172b15cb3dSCy Schubert  *  of the user of the license.
182b15cb3dSCy Schubert  *
192b15cb3dSCy Schubert  *   The GNU Lesser General Public License, version 3 or later
202b15cb3dSCy Schubert  *      See the files "COPYING.lgplv3" and "COPYING.gplv3"
212b15cb3dSCy Schubert  *
222b15cb3dSCy Schubert  *   The Modified Berkeley Software Distribution License
232b15cb3dSCy Schubert  *      See the file "COPYING.mbsd"
242b15cb3dSCy Schubert  *
252b15cb3dSCy Schubert  *  These files have the following sha256 sums:
262b15cb3dSCy Schubert  *
272b15cb3dSCy Schubert  *  8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95  COPYING.gplv3
282b15cb3dSCy Schubert  *  4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b  COPYING.lgplv3
292b15cb3dSCy Schubert  *  13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239  COPYING.mbsd
30ea906c41SOllivier Robert  */
31ea906c41SOllivier Robert 
322b15cb3dSCy Schubert /*=export_func  optionShowRange
332b15cb3dSCy Schubert  * private:
342b15cb3dSCy Schubert  *
352b15cb3dSCy Schubert  * what:  Show info about range constraints
362b15cb3dSCy Schubert  * arg:   + tOptions * + pOpts     + program options descriptor  +
372b15cb3dSCy Schubert  * arg:   + tOptDesc * + pOptDesc  + the descriptor for this arg +
382b15cb3dSCy Schubert  * arg:   + void *     + rng_table + the value range tables      +
392b15cb3dSCy Schubert  * arg:   + int        + rng_count + the number of entries       +
402b15cb3dSCy Schubert  *
412b15cb3dSCy Schubert  * doc:
422b15cb3dSCy Schubert  *   Show information about a numeric option with range constraints.
432b15cb3dSCy Schubert =*/
442b15cb3dSCy Schubert void
optionShowRange(tOptions * pOpts,tOptDesc * pOD,void * rng_table,int rng_ct)45276da39aSCy Schubert optionShowRange(tOptions * pOpts, tOptDesc * pOD, void * rng_table, int rng_ct)
462b15cb3dSCy Schubert {
472b15cb3dSCy Schubert     const struct {long const rmin, rmax;} * rng = rng_table;
482b15cb3dSCy Schubert 
492b15cb3dSCy Schubert     char const * pz_indent = zTabHyp + tab_skip_ct;
502b15cb3dSCy Schubert 
51ea906c41SOllivier Robert     /*
522b15cb3dSCy Schubert      * The range is shown only for full usage requests and an error
532b15cb3dSCy Schubert      * in this particular option.
54ea906c41SOllivier Robert      */
552b15cb3dSCy Schubert     if (pOpts != OPTPROC_EMIT_USAGE) {
562b15cb3dSCy Schubert         if (pOpts <= OPTPROC_EMIT_LIMIT)
572b15cb3dSCy Schubert             return;
582b15cb3dSCy Schubert         pz_indent = ONE_TAB_STR;
592b15cb3dSCy Schubert 
602b15cb3dSCy Schubert         fprintf(option_usage_fp, zRangeErr, pOpts->pzProgName,
612b15cb3dSCy Schubert                 pOD->pz_Name, pOD->optArg.argInt);
622b15cb3dSCy Schubert         pz_indent = "";
632b15cb3dSCy Schubert     }
642b15cb3dSCy Schubert 
652b15cb3dSCy Schubert     if (pOD->fOptState & OPTST_SCALED_NUM)
662b15cb3dSCy Schubert         fprintf(option_usage_fp, zRangeScaled, pz_indent);
672b15cb3dSCy Schubert 
682b15cb3dSCy Schubert     fprintf(option_usage_fp, (rng_ct > 1) ? zRangeLie : zRangeOnly, pz_indent);
692b15cb3dSCy Schubert     pz_indent = (pOpts != OPTPROC_EMIT_USAGE)
702b15cb3dSCy Schubert         ? ONE_TAB_STR
712b15cb3dSCy Schubert         : (zTabSpace + tab_skip_ct);
722b15cb3dSCy Schubert 
732b15cb3dSCy Schubert     for (;;) {
742b15cb3dSCy Schubert         if (rng->rmax == LONG_MIN)
752b15cb3dSCy Schubert             fprintf(option_usage_fp, zRangeExact, pz_indent, rng->rmin);
762b15cb3dSCy Schubert         else if (rng->rmin == LONG_MIN)
772b15cb3dSCy Schubert             fprintf(option_usage_fp, zRangeUpto, pz_indent, rng->rmax);
782b15cb3dSCy Schubert         else if (rng->rmax == LONG_MAX)
792b15cb3dSCy Schubert             fprintf(option_usage_fp, zRangeAbove, pz_indent, rng->rmin);
802b15cb3dSCy Schubert         else
812b15cb3dSCy Schubert             fprintf(option_usage_fp, zRange, pz_indent, rng->rmin,
822b15cb3dSCy Schubert                     rng->rmax);
832b15cb3dSCy Schubert 
842b15cb3dSCy Schubert         if  (--rng_ct <= 0) {
852b15cb3dSCy Schubert             fputc(NL, option_usage_fp);
862b15cb3dSCy Schubert             break;
872b15cb3dSCy Schubert         }
882b15cb3dSCy Schubert         fputs(zRangeOr, option_usage_fp);
892b15cb3dSCy Schubert         rng++;
902b15cb3dSCy Schubert     }
912b15cb3dSCy Schubert 
922b15cb3dSCy Schubert     if (pOpts > OPTPROC_EMIT_LIMIT)
932b15cb3dSCy Schubert         pOpts->pUsageProc(pOpts, EXIT_FAILURE);
942b15cb3dSCy Schubert }
95ea906c41SOllivier Robert 
96ea906c41SOllivier Robert /*=export_func  optionNumericVal
97ea906c41SOllivier Robert  * private:
98ea906c41SOllivier Robert  *
992b15cb3dSCy Schubert  * what:  process an option with a numeric value.
1002b15cb3dSCy Schubert  * arg:   + tOptions * + opts + program options descriptor +
1012b15cb3dSCy Schubert  * arg:   + tOptDesc * + od   + the descriptor for this arg +
102ea906c41SOllivier Robert  *
103ea906c41SOllivier Robert  * doc:
104ea906c41SOllivier Robert  *  Decipher a numeric value.
105ea906c41SOllivier Robert =*/
106ea906c41SOllivier Robert void
optionNumericVal(tOptions * opts,tOptDesc * od)1072b15cb3dSCy Schubert optionNumericVal(tOptions * opts, tOptDesc * od)
108ea906c41SOllivier Robert {
109ea906c41SOllivier Robert     char * pz;
110ea906c41SOllivier Robert     long   val;
111ea906c41SOllivier Robert 
112ea906c41SOllivier Robert     /*
1132b15cb3dSCy Schubert      *  Guard against all the different ways this procedure might get invoked
1142b15cb3dSCy Schubert      *  when there is no string argument provided.
115ea906c41SOllivier Robert      */
1162b15cb3dSCy Schubert     if (INQUERY_CALL(opts, od) || (od->optArg.argString == NULL))
117ea906c41SOllivier Robert         return;
118ea906c41SOllivier Robert 
119ea906c41SOllivier Robert     /*
1202b15cb3dSCy Schubert      *  Numeric options may have a range associated with it.
1212b15cb3dSCy Schubert      *  If it does, the usage procedure requests that it be
1222b15cb3dSCy Schubert      *  emitted by passing a NULL od pointer.  Also bail out
1232b15cb3dSCy Schubert      *  if there is no option argument or if we are being reset.
1242b15cb3dSCy Schubert      */
1252b15cb3dSCy Schubert     if (  (od == NULL)
1262b15cb3dSCy Schubert        || (od->optArg.argString == NULL)
127*a466cc55SCy Schubert        || ((od->fOptState & OPTST_RESET) != 0)
128*a466cc55SCy Schubert        || (opts <= OPTPROC_EMIT_LIMIT))
1292b15cb3dSCy Schubert         return;
1302b15cb3dSCy Schubert 
1312b15cb3dSCy Schubert     errno = 0;
1322b15cb3dSCy Schubert     val = strtol(od->optArg.argString, &pz, 0);
1332b15cb3dSCy Schubert     if ((pz == od->optArg.argString) || (errno != 0))
1342b15cb3dSCy Schubert         goto bad_number;
1352b15cb3dSCy Schubert 
1362b15cb3dSCy Schubert     if ((od->fOptState & OPTST_SCALED_NUM) != 0)
1372b15cb3dSCy Schubert         switch (*(pz++)) {
1382b15cb3dSCy Schubert         case NUL:  pz--; break;
139*a466cc55SCy Schubert         case 't':  val *= 1000; /* FALLTHROUGH */
140*a466cc55SCy Schubert         case 'g':  val *= 1000; /* FALLTHROUGH */
141*a466cc55SCy Schubert         case 'm':  val *= 1000; /* FALLTHROUGH */
1422b15cb3dSCy Schubert         case 'k':  val *= 1000; break;
1432b15cb3dSCy Schubert 
144*a466cc55SCy Schubert         case 'T':  val *= 1024; /* FALLTHROUGH */
145*a466cc55SCy Schubert         case 'G':  val *= 1024; /* FALLTHROUGH */
146*a466cc55SCy Schubert         case 'M':  val *= 1024; /* FALLTHROUGH */
1472b15cb3dSCy Schubert         case 'K':  val *= 1024; break;
1482b15cb3dSCy Schubert 
1492b15cb3dSCy Schubert         default:   goto bad_number;
1502b15cb3dSCy Schubert         }
1512b15cb3dSCy Schubert 
1522b15cb3dSCy Schubert     if (*pz != NUL)
1532b15cb3dSCy Schubert         goto bad_number;
1542b15cb3dSCy Schubert 
1552b15cb3dSCy Schubert     if (od->fOptState & OPTST_ALLOC_ARG) {
1562b15cb3dSCy Schubert         AGFREE(od->optArg.argString);
1572b15cb3dSCy Schubert         od->fOptState &= ~OPTST_ALLOC_ARG;
1582b15cb3dSCy Schubert     }
1592b15cb3dSCy Schubert 
1602b15cb3dSCy Schubert     od->optArg.argInt = val;
1612b15cb3dSCy Schubert     return;
1622b15cb3dSCy Schubert 
1632b15cb3dSCy Schubert     bad_number:
1642b15cb3dSCy Schubert 
1652b15cb3dSCy Schubert     fprintf( stderr, zNotNumber, opts->pzProgName, od->optArg.argString );
1662b15cb3dSCy Schubert     if ((opts->fOptSet & OPTPROC_ERRSTOP) != 0)
1672b15cb3dSCy Schubert         (*(opts->pUsageProc))(opts, EXIT_FAILURE);
1682b15cb3dSCy Schubert 
1692b15cb3dSCy Schubert     errno = EINVAL;
1702b15cb3dSCy Schubert     od->optArg.argInt = ~0;
1712b15cb3dSCy Schubert }
1722b15cb3dSCy Schubert 
1732b15cb3dSCy Schubert /** @}
1742b15cb3dSCy Schubert  *
175ea906c41SOllivier Robert  * Local Variables:
176ea906c41SOllivier Robert  * mode: C
177ea906c41SOllivier Robert  * c-file-style: "stroustrup"
178ea906c41SOllivier Robert  * indent-tabs-mode: nil
179ea906c41SOllivier Robert  * End:
180ea906c41SOllivier Robert  * end of autoopts/numeric.c */
181