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