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