1181834Sroberto
2285612Sdelphij/**
3285612Sdelphij * \file numeric.c
4285612Sdelphij *
5285612Sdelphij * Handle options with numeric (integer) arguments.
6285612Sdelphij *
7285612Sdelphij * @addtogroup autoopts
8285612Sdelphij * @{
9181834Sroberto */
10181834Sroberto/*
11285612Sdelphij *  This file is part of AutoOpts, a companion to AutoGen.
12285612Sdelphij *  AutoOpts is free software.
13285612Sdelphij *  AutoOpts is Copyright (C) 1992-2015 by Bruce Korb - all rights reserved
14181834Sroberto *
15285612Sdelphij *  AutoOpts is available under any one of two licenses.  The license
16285612Sdelphij *  in use must be one of these two and the choice is under the control
17285612Sdelphij *  of the user of the license.
18181834Sroberto *
19285612Sdelphij *   The GNU Lesser General Public License, version 3 or later
20285612Sdelphij *      See the files "COPYING.lgplv3" and "COPYING.gplv3"
21181834Sroberto *
22285612Sdelphij *   The Modified Berkeley Software Distribution License
23285612Sdelphij *      See the file "COPYING.mbsd"
24181834Sroberto *
25285612Sdelphij *  These files have the following sha256 sums:
26181834Sroberto *
27285612Sdelphij *  8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95  COPYING.gplv3
28285612Sdelphij *  4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b  COPYING.lgplv3
29285612Sdelphij *  13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239  COPYING.mbsd
30285612Sdelphij */
31285612Sdelphij
32285612Sdelphij/*=export_func  optionShowRange
33285612Sdelphij * private:
34181834Sroberto *
35285612Sdelphij * what:  Show info about range constraints
36285612Sdelphij * arg:   + tOptions * + pOpts     + program options descriptor  +
37285612Sdelphij * arg:   + tOptDesc * + pOptDesc  + the descriptor for this arg +
38285612Sdelphij * arg:   + void *     + rng_table + the value range tables      +
39285612Sdelphij * arg:   + int        + rng_count + the number of entries       +
40181834Sroberto *
41285612Sdelphij * doc:
42285612Sdelphij *   Show information about a numeric option with range constraints.
43285612Sdelphij=*/
44285612Sdelphijvoid
45285612SdelphijoptionShowRange(tOptions * pOpts, tOptDesc * pOD, void * rng_table, int rng_ct)
46285612Sdelphij{
47285612Sdelphij    const struct {long const rmin, rmax;} * rng = rng_table;
48181834Sroberto
49285612Sdelphij    char const * pz_indent = zTabHyp + tab_skip_ct;
50285612Sdelphij
51285612Sdelphij    /*
52285612Sdelphij     * The range is shown only for full usage requests and an error
53285612Sdelphij     * in this particular option.
54285612Sdelphij     */
55285612Sdelphij    if (pOpts != OPTPROC_EMIT_USAGE) {
56285612Sdelphij        if (pOpts <= OPTPROC_EMIT_LIMIT)
57285612Sdelphij            return;
58285612Sdelphij        pz_indent = ONE_TAB_STR;
59285612Sdelphij
60285612Sdelphij        fprintf(option_usage_fp, zRangeErr, pOpts->pzProgName,
61285612Sdelphij                pOD->pz_Name, pOD->optArg.argInt);
62285612Sdelphij        pz_indent = "";
63285612Sdelphij    }
64285612Sdelphij
65285612Sdelphij    if (pOD->fOptState & OPTST_SCALED_NUM)
66285612Sdelphij        fprintf(option_usage_fp, zRangeScaled, pz_indent);
67285612Sdelphij
68285612Sdelphij    fprintf(option_usage_fp, (rng_ct > 1) ? zRangeLie : zRangeOnly, pz_indent);
69285612Sdelphij    pz_indent = (pOpts != OPTPROC_EMIT_USAGE)
70285612Sdelphij        ? ONE_TAB_STR
71285612Sdelphij        : (zTabSpace + tab_skip_ct);
72285612Sdelphij
73285612Sdelphij    for (;;) {
74285612Sdelphij        if (rng->rmax == LONG_MIN)
75285612Sdelphij            fprintf(option_usage_fp, zRangeExact, pz_indent, rng->rmin);
76285612Sdelphij        else if (rng->rmin == LONG_MIN)
77285612Sdelphij            fprintf(option_usage_fp, zRangeUpto, pz_indent, rng->rmax);
78285612Sdelphij        else if (rng->rmax == LONG_MAX)
79285612Sdelphij            fprintf(option_usage_fp, zRangeAbove, pz_indent, rng->rmin);
80285612Sdelphij        else
81285612Sdelphij            fprintf(option_usage_fp, zRange, pz_indent, rng->rmin,
82285612Sdelphij                    rng->rmax);
83285612Sdelphij
84285612Sdelphij        if  (--rng_ct <= 0) {
85285612Sdelphij            fputc(NL, option_usage_fp);
86285612Sdelphij            break;
87285612Sdelphij        }
88285612Sdelphij        fputs(zRangeOr, option_usage_fp);
89285612Sdelphij        rng++;
90285612Sdelphij    }
91285612Sdelphij
92285612Sdelphij    if (pOpts > OPTPROC_EMIT_LIMIT)
93285612Sdelphij        pOpts->pUsageProc(pOpts, EXIT_FAILURE);
94285612Sdelphij}
95285612Sdelphij
96181834Sroberto/*=export_func  optionNumericVal
97181834Sroberto * private:
98181834Sroberto *
99285612Sdelphij * what:  process an option with a numeric value.
100285612Sdelphij * arg:   + tOptions * + opts + program options descriptor +
101285612Sdelphij * arg:   + tOptDesc * + od   + the descriptor for this arg +
102181834Sroberto *
103181834Sroberto * doc:
104181834Sroberto *  Decipher a numeric value.
105181834Sroberto=*/
106181834Srobertovoid
107285612SdelphijoptionNumericVal(tOptions * opts, tOptDesc * od)
108181834Sroberto{
109285612Sdelphij    char * pz;
110285612Sdelphij    long   val;
111181834Sroberto
112181834Sroberto    /*
113285612Sdelphij     *  Guard against all the different ways this procedure might get invoked
114285612Sdelphij     *  when there is no string argument provided.
115285612Sdelphij     */
116285612Sdelphij    if (INQUERY_CALL(opts, od) || (od->optArg.argString == NULL))
117285612Sdelphij        return;
118285612Sdelphij
119285612Sdelphij    /*
120181834Sroberto     *  Numeric options may have a range associated with it.
121181834Sroberto     *  If it does, the usage procedure requests that it be
122285612Sdelphij     *  emitted by passing a NULL od pointer.  Also bail out
123285612Sdelphij     *  if there is no option argument or if we are being reset.
124181834Sroberto     */
125285612Sdelphij    if (  (od == NULL)
126285612Sdelphij       || (od->optArg.argString == NULL)
127285612Sdelphij       || ((od->fOptState & OPTST_RESET) != 0))
128181834Sroberto        return;
129181834Sroberto
130285612Sdelphij    errno = 0;
131285612Sdelphij    val = strtol(od->optArg.argString, &pz, 0);
132285612Sdelphij    if ((pz == od->optArg.argString) || (errno != 0))
133285612Sdelphij        goto bad_number;
134181834Sroberto
135285612Sdelphij    if ((od->fOptState & OPTST_SCALED_NUM) != 0)
136285612Sdelphij        switch (*(pz++)) {
137285612Sdelphij        case NUL:  pz--; break;
138285612Sdelphij        case 't':  val *= 1000;
139285612Sdelphij        case 'g':  val *= 1000;
140285612Sdelphij        case 'm':  val *= 1000;
141285612Sdelphij        case 'k':  val *= 1000; break;
142285612Sdelphij
143285612Sdelphij        case 'T':  val *= 1024;
144285612Sdelphij        case 'G':  val *= 1024;
145285612Sdelphij        case 'M':  val *= 1024;
146285612Sdelphij        case 'K':  val *= 1024; break;
147285612Sdelphij
148285612Sdelphij        default:   goto bad_number;
149285612Sdelphij        }
150285612Sdelphij
151285612Sdelphij    if (*pz != NUL)
152285612Sdelphij        goto bad_number;
153285612Sdelphij
154285612Sdelphij    if (od->fOptState & OPTST_ALLOC_ARG) {
155285612Sdelphij        AGFREE(od->optArg.argString);
156285612Sdelphij        od->fOptState &= ~OPTST_ALLOC_ARG;
157181834Sroberto    }
158181834Sroberto
159285612Sdelphij    od->optArg.argInt = val;
160285612Sdelphij    return;
161285612Sdelphij
162285612Sdelphij    bad_number:
163285612Sdelphij
164285612Sdelphij    fprintf( stderr, zNotNumber, opts->pzProgName, od->optArg.argString );
165285612Sdelphij    if ((opts->fOptSet & OPTPROC_ERRSTOP) != 0)
166285612Sdelphij        (*(opts->pUsageProc))(opts, EXIT_FAILURE);
167285612Sdelphij
168285612Sdelphij    errno = EINVAL;
169285612Sdelphij    od->optArg.argInt = ~0;
170181834Sroberto}
171285612Sdelphij
172285612Sdelphij/** @}
173285612Sdelphij *
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