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 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 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