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
optionShowRange(tOptions * pOpts,tOptDesc * pOD,void * rng_table,int rng_ct)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
optionNumericVal(tOptions * opts,tOptDesc * od)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