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