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