xref: /netbsd-src/external/bsd/ntp/dist/sntp/libopts/numeric.c (revision 6a493d6bc668897c91594964a732d38505b70cbb)
1 /*	$NetBSD: numeric.c,v 1.3 2013/12/28 03:20:15 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-2013 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, const 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      *  Numeric options may have a range associated with it.
116      *  If it does, the usage procedure requests that it be
117      *  emitted by passing a NULL od pointer.  Also bail out
118      *  if there is no option argument or if we are being reset.
119      */
120     if (  (od == NULL)
121        || (od->optArg.argString == NULL)
122        || ((od->fOptState & OPTST_RESET) != 0))
123         return;
124 
125     errno = 0;
126     val = strtol(od->optArg.argString, &pz, 0);
127     if ((pz == od->optArg.argString) || (errno != 0))
128         goto bad_number;
129 
130     if ((od->fOptState & OPTST_SCALED_NUM) != 0)
131         switch (*(pz++)) {
132         case NUL:  pz--; break;
133         case 't':  val *= 1000;
134         case 'g':  val *= 1000;
135         case 'm':  val *= 1000;
136         case 'k':  val *= 1000; break;
137 
138         case 'T':  val *= 1024;
139         case 'G':  val *= 1024;
140         case 'M':  val *= 1024;
141         case 'K':  val *= 1024; break;
142 
143         default:   goto bad_number;
144         }
145 
146     if (*pz != NUL)
147         goto bad_number;
148 
149     if (od->fOptState & OPTST_ALLOC_ARG) {
150         AGFREE(od->optArg.argString);
151         od->fOptState &= ~OPTST_ALLOC_ARG;
152     }
153 
154     od->optArg.argInt = val;
155     return;
156 
157     bad_number:
158 
159     fprintf( stderr, zNotNumber, opts->pzProgName, od->optArg.argString );
160     if ((opts->fOptSet & OPTPROC_ERRSTOP) != 0)
161         (*(opts->pUsageProc))(opts, EXIT_FAILURE);
162 
163     errno = EINVAL;
164     od->optArg.argInt = ~0;
165 }
166 
167 /** @}
168  *
169  * Local Variables:
170  * mode: C
171  * c-file-style: "stroustrup"
172  * indent-tabs-mode: nil
173  * End:
174  * end of autoopts/numeric.c */
175