xref: /netbsd-src/external/bsd/ntp/dist/sntp/libopts/numeric.c (revision ba65fde2d7fefa7d39838fa5fa855e62bd606b5e)
1 /*	$NetBSD: numeric.c,v 1.2 2012/02/01 20:48:01 kardel Exp $	*/
2 
3 
4 /**
5  * \file numeric.c
6  *
7  *  Time-stamp:      "2011-03-25 16:26:10 bkorb"
8  *
9  *  This file is part of AutoOpts, a companion to AutoGen.
10  *  AutoOpts is free software.
11  *  AutoOpts is Copyright (c) 1992-2011 by Bruce Korb - all rights reserved
12  *
13  *  AutoOpts is available under any one of two licenses.  The license
14  *  in use must be one of these two and the choice is under the control
15  *  of the user of the license.
16  *
17  *   The GNU Lesser General Public License, version 3 or later
18  *      See the files "COPYING.lgplv3" and "COPYING.gplv3"
19  *
20  *   The Modified Berkeley Software Distribution License
21  *      See the file "COPYING.mbsd"
22  *
23  *  These files have the following md5sums:
24  *
25  *  43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3
26  *  06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3
27  *  66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd
28  */
29 
30 /*=export_func  optionShowRange
31  * private:
32  *
33  * what:
34  * arg:   + tOptions* + pOpts     + program options descriptor  +
35  * arg:   + tOptDesc* + pOptDesc  + the descriptor for this arg +
36  * arg:   + void *    + rng_table + the value range tables      +
37  * arg:   + int       + rng_count + the number of entries       +
38  *
39  * doc:
40  *   Show information about a numeric option with range constraints.
41 =*/
42 void
43 optionShowRange(tOptions* pOpts, tOptDesc* pOD, const void * rng_table, int rng_ct)
44 {
45     static char const bullet[] = "\t\t\t\t- ";
46     static char const deepin[] = "\t\t\t\t  ";
47     static char const onetab[] = "\t";
48 
49     const struct {long const rmin, rmax;} * rng = rng_table;
50 
51     char const * pz_indent    = bullet;
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 = onetab;
61 
62         fprintf(option_usage_fp, zRangeErr, pOpts->pzProgName,
63                 pOD->pz_Name, pOD->optArg.argString);
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) ? onetab : deepin;
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('\n', 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* + pOpts    + program options descriptor +
101  * arg:   + tOptDesc* + pOptDesc + the descriptor for this arg +
102  *
103  * doc:
104  *  Decipher a numeric value.
105 =*/
106 void
107 optionNumericVal(tOptions* pOpts, tOptDesc* pOD )
108 {
109     char* pz;
110     long  val;
111 
112     /*
113      *  Numeric options may have a range associated with it.
114      *  If it does, the usage procedure requests that it be
115      *  emitted by passing a NULL pOD pointer.  Also bail out
116      *  if there is no option argument or if we are being reset.
117      */
118     if (  (pOD == NULL)
119        || (pOD->optArg.argString == NULL)
120        || ((pOD->fOptState & OPTST_RESET) != 0))
121         return;
122 
123     errno = 0;
124     val = strtol(pOD->optArg.argString, &pz, 0);
125     if ((pz == pOD->optArg.argString) || (errno != 0))
126         goto bad_number;
127 
128     if ((pOD->fOptState & OPTST_SCALED_NUM) != 0)
129         switch (*(pz++)) {
130         case '\0': pz--; break;
131         case 't':  val *= 1000;
132         case 'g':  val *= 1000;
133         case 'm':  val *= 1000;
134         case 'k':  val *= 1000; break;
135 
136         case 'T':  val *= 1024;
137         case 'G':  val *= 1024;
138         case 'M':  val *= 1024;
139         case 'K':  val *= 1024; break;
140 
141         default:   goto bad_number;
142         }
143 
144     if (*pz != NUL)
145         goto bad_number;
146 
147     if (pOD->fOptState & OPTST_ALLOC_ARG) {
148         AGFREE(pOD->optArg.argString);
149         pOD->fOptState &= ~OPTST_ALLOC_ARG;
150     }
151 
152     pOD->optArg.argInt = val;
153     return;
154 
155     bad_number:
156 
157     fprintf( stderr, zNotNumber, pOpts->pzProgName, pOD->optArg.argString );
158     if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0)
159         (*(pOpts->pUsageProc))(pOpts, EXIT_FAILURE);
160 
161     errno = EINVAL;
162     pOD->optArg.argInt = ~0;
163 }
164 
165 /*
166  * Local Variables:
167  * mode: C
168  * c-file-style: "stroustrup"
169  * indent-tabs-mode: nil
170  * End:
171  * end of autoopts/numeric.c */
172