1181834Sroberto
2290001Sglebius/**
3290001Sglebius * \file numeric.c
4290001Sglebius *
5290001Sglebius * Handle options with numeric (integer) arguments.
6290001Sglebius *
7290001Sglebius * @addtogroup autoopts
8290001Sglebius * @{
9181834Sroberto */
10181834Sroberto/*
11290001Sglebius *  This file is part of AutoOpts, a companion to AutoGen.
12290001Sglebius *  AutoOpts is free software.
13290001Sglebius *  AutoOpts is Copyright (C) 1992-2015 by Bruce Korb - all rights reserved
14181834Sroberto *
15290001Sglebius *  AutoOpts is available under any one of two licenses.  The license
16290001Sglebius *  in use must be one of these two and the choice is under the control
17290001Sglebius *  of the user of the license.
18181834Sroberto *
19290001Sglebius *   The GNU Lesser General Public License, version 3 or later
20290001Sglebius *      See the files "COPYING.lgplv3" and "COPYING.gplv3"
21181834Sroberto *
22290001Sglebius *   The Modified Berkeley Software Distribution License
23290001Sglebius *      See the file "COPYING.mbsd"
24181834Sroberto *
25290001Sglebius *  These files have the following sha256 sums:
26181834Sroberto *
27290001Sglebius *  8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95  COPYING.gplv3
28290001Sglebius *  4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b  COPYING.lgplv3
29290001Sglebius *  13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239  COPYING.mbsd
30290001Sglebius */
31290001Sglebius
32290001Sglebius/*=export_func  optionShowRange
33290001Sglebius * private:
34181834Sroberto *
35290001Sglebius * what:  Show info about range constraints
36290001Sglebius * arg:   + tOptions * + pOpts     + program options descriptor  +
37290001Sglebius * arg:   + tOptDesc * + pOptDesc  + the descriptor for this arg +
38290001Sglebius * arg:   + void *     + rng_table + the value range tables      +
39290001Sglebius * arg:   + int        + rng_count + the number of entries       +
40181834Sroberto *
41290001Sglebius * doc:
42290001Sglebius *   Show information about a numeric option with range constraints.
43290001Sglebius=*/
44290001Sglebiusvoid
45290001SglebiusoptionShowRange(tOptions * pOpts, tOptDesc * pOD, void * rng_table, int rng_ct)
46290001Sglebius{
47290001Sglebius    const struct {long const rmin, rmax;} * rng = rng_table;
48181834Sroberto
49290001Sglebius    char const * pz_indent = zTabHyp + tab_skip_ct;
50290001Sglebius
51290001Sglebius    /*
52290001Sglebius     * The range is shown only for full usage requests and an error
53290001Sglebius     * in this particular option.
54290001Sglebius     */
55290001Sglebius    if (pOpts != OPTPROC_EMIT_USAGE) {
56290001Sglebius        if (pOpts <= OPTPROC_EMIT_LIMIT)
57290001Sglebius            return;
58290001Sglebius        pz_indent = ONE_TAB_STR;
59290001Sglebius
60290001Sglebius        fprintf(option_usage_fp, zRangeErr, pOpts->pzProgName,
61290001Sglebius                pOD->pz_Name, pOD->optArg.argInt);
62290001Sglebius        pz_indent = "";
63290001Sglebius    }
64290001Sglebius
65290001Sglebius    if (pOD->fOptState & OPTST_SCALED_NUM)
66290001Sglebius        fprintf(option_usage_fp, zRangeScaled, pz_indent);
67290001Sglebius
68290001Sglebius    fprintf(option_usage_fp, (rng_ct > 1) ? zRangeLie : zRangeOnly, pz_indent);
69290001Sglebius    pz_indent = (pOpts != OPTPROC_EMIT_USAGE)
70290001Sglebius        ? ONE_TAB_STR
71290001Sglebius        : (zTabSpace + tab_skip_ct);
72290001Sglebius
73290001Sglebius    for (;;) {
74290001Sglebius        if (rng->rmax == LONG_MIN)
75290001Sglebius            fprintf(option_usage_fp, zRangeExact, pz_indent, rng->rmin);
76290001Sglebius        else if (rng->rmin == LONG_MIN)
77290001Sglebius            fprintf(option_usage_fp, zRangeUpto, pz_indent, rng->rmax);
78290001Sglebius        else if (rng->rmax == LONG_MAX)
79290001Sglebius            fprintf(option_usage_fp, zRangeAbove, pz_indent, rng->rmin);
80290001Sglebius        else
81290001Sglebius            fprintf(option_usage_fp, zRange, pz_indent, rng->rmin,
82290001Sglebius                    rng->rmax);
83290001Sglebius
84290001Sglebius        if  (--rng_ct <= 0) {
85290001Sglebius            fputc(NL, option_usage_fp);
86290001Sglebius            break;
87290001Sglebius        }
88290001Sglebius        fputs(zRangeOr, option_usage_fp);
89290001Sglebius        rng++;
90290001Sglebius    }
91290001Sglebius
92290001Sglebius    if (pOpts > OPTPROC_EMIT_LIMIT)
93290001Sglebius        pOpts->pUsageProc(pOpts, EXIT_FAILURE);
94290001Sglebius}
95290001Sglebius
96181834Sroberto/*=export_func  optionNumericVal
97181834Sroberto * private:
98181834Sroberto *
99290001Sglebius * what:  process an option with a numeric value.
100290001Sglebius * arg:   + tOptions * + opts + program options descriptor +
101290001Sglebius * arg:   + tOptDesc * + od   + the descriptor for this arg +
102181834Sroberto *
103181834Sroberto * doc:
104181834Sroberto *  Decipher a numeric value.
105181834Sroberto=*/
106181834Srobertovoid
107290001SglebiusoptionNumericVal(tOptions * opts, tOptDesc * od)
108181834Sroberto{
109290001Sglebius    char * pz;
110290001Sglebius    long   val;
111181834Sroberto
112181834Sroberto    /*
113290001Sglebius     *  Guard against all the different ways this procedure might get invoked
114290001Sglebius     *  when there is no string argument provided.
115290001Sglebius     */
116290001Sglebius    if (INQUERY_CALL(opts, od) || (od->optArg.argString == NULL))
117290001Sglebius        return;
118290001Sglebius
119290001Sglebius    /*
120181834Sroberto     *  Numeric options may have a range associated with it.
121181834Sroberto     *  If it does, the usage procedure requests that it be
122290001Sglebius     *  emitted by passing a NULL od pointer.  Also bail out
123290001Sglebius     *  if there is no option argument or if we are being reset.
124181834Sroberto     */
125290001Sglebius    if (  (od == NULL)
126290001Sglebius       || (od->optArg.argString == NULL)
127290001Sglebius       || ((od->fOptState & OPTST_RESET) != 0))
128181834Sroberto        return;
129181834Sroberto
130290001Sglebius    errno = 0;
131290001Sglebius    val = strtol(od->optArg.argString, &pz, 0);
132290001Sglebius    if ((pz == od->optArg.argString) || (errno != 0))
133290001Sglebius        goto bad_number;
134181834Sroberto
135290001Sglebius    if ((od->fOptState & OPTST_SCALED_NUM) != 0)
136290001Sglebius        switch (*(pz++)) {
137290001Sglebius        case NUL:  pz--; break;
138290001Sglebius        case 't':  val *= 1000;
139290001Sglebius        case 'g':  val *= 1000;
140290001Sglebius        case 'm':  val *= 1000;
141290001Sglebius        case 'k':  val *= 1000; break;
142290001Sglebius
143290001Sglebius        case 'T':  val *= 1024;
144290001Sglebius        case 'G':  val *= 1024;
145290001Sglebius        case 'M':  val *= 1024;
146290001Sglebius        case 'K':  val *= 1024; break;
147290001Sglebius
148290001Sglebius        default:   goto bad_number;
149290001Sglebius        }
150290001Sglebius
151290001Sglebius    if (*pz != NUL)
152290001Sglebius        goto bad_number;
153290001Sglebius
154290001Sglebius    if (od->fOptState & OPTST_ALLOC_ARG) {
155290001Sglebius        AGFREE(od->optArg.argString);
156290001Sglebius        od->fOptState &= ~OPTST_ALLOC_ARG;
157181834Sroberto    }
158181834Sroberto
159290001Sglebius    od->optArg.argInt = val;
160290001Sglebius    return;
161290001Sglebius
162290001Sglebius    bad_number:
163290001Sglebius
164290001Sglebius    fprintf( stderr, zNotNumber, opts->pzProgName, od->optArg.argString );
165290001Sglebius    if ((opts->fOptSet & OPTPROC_ERRSTOP) != 0)
166290001Sglebius        (*(opts->pUsageProc))(opts, EXIT_FAILURE);
167290001Sglebius
168290001Sglebius    errno = EINVAL;
169290001Sglebius    od->optArg.argInt = ~0;
170181834Sroberto}
171290001Sglebius
172290001Sglebius/** @}
173290001Sglebius *
174181834Sroberto * Local Variables:
175181834Sroberto * mode: C
176181834Sroberto * c-file-style: "stroustrup"
177181834Sroberto * indent-tabs-mode: nil
178181834Sroberto * End:
179181834Sroberto * end of autoopts/numeric.c */
180