mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-02-08 18:19:08 +08:00
104 lines
3.4 KiB
C
104 lines
3.4 KiB
C
|
/*************************************************************************\
|
||
|
* Copyright (C) Michael Kerrisk, 2018. *
|
||
|
* *
|
||
|
* This program is free software. You may use, modify, and redistribute it *
|
||
|
* under the terms of the GNU Lesser General Public License as published *
|
||
|
* by the Free Software Foundation, either version 3 or (at your option) *
|
||
|
* any later version. This program is distributed without any warranty. *
|
||
|
* See the files COPYING.lgpl-v3 and COPYING.gpl-v3 for details. *
|
||
|
\*************************************************************************/
|
||
|
|
||
|
/* Listing 3-6 */
|
||
|
|
||
|
/* get_num.c
|
||
|
|
||
|
Functions to process numeric command-line arguments.
|
||
|
*/
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <limits.h>
|
||
|
#include <errno.h>
|
||
|
#include "get_num.h"
|
||
|
|
||
|
/* Print a diagnostic message that contains a function name ('fname'),
|
||
|
the value of a command-line argument ('arg'), the name of that
|
||
|
command-line argument ('name'), and a diagnostic error message ('msg'). */
|
||
|
|
||
|
static void
|
||
|
gnFail(const char *fname, const char *msg, const char *arg, const char *name)
|
||
|
{
|
||
|
fprintf(stderr, "%s error", fname);
|
||
|
if (name != NULL)
|
||
|
fprintf(stderr, " (in %s)", name);
|
||
|
fprintf(stderr, ": %s\n", msg);
|
||
|
if (arg != NULL && *arg != '\0')
|
||
|
fprintf(stderr, " offending text: %s\n", arg);
|
||
|
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
/* Convert a numeric command-line argument ('arg') into a long integer,
|
||
|
returned as the function result. 'flags' is a bit mask of flags controlling
|
||
|
how the conversion is done and what diagnostic checks are performed on the
|
||
|
numeric result; see get_num.h for details.
|
||
|
|
||
|
'fname' is the name of our caller, and 'name' is the name associated with
|
||
|
the command-line argument 'arg'. 'fname' and 'name' are used to print a
|
||
|
diagnostic message in case an error is detected when processing 'arg'. */
|
||
|
|
||
|
static long
|
||
|
getNum(const char *fname, const char *arg, int flags, const char *name)
|
||
|
{
|
||
|
long res;
|
||
|
char *endptr;
|
||
|
int base;
|
||
|
|
||
|
if (arg == NULL || *arg == '\0')
|
||
|
gnFail(fname, "null or empty string", arg, name);
|
||
|
|
||
|
base = (flags & GN_ANY_BASE) ? 0 : (flags & GN_BASE_8) ? 8 :
|
||
|
(flags & GN_BASE_16) ? 16 : 10;
|
||
|
|
||
|
errno = 0;
|
||
|
res = strtol(arg, &endptr, base);
|
||
|
if (errno != 0)
|
||
|
gnFail(fname, "strtol() failed", arg, name);
|
||
|
|
||
|
if (*endptr != '\0')
|
||
|
gnFail(fname, "nonnumeric characters", arg, name);
|
||
|
|
||
|
if ((flags & GN_NONNEG) && res < 0)
|
||
|
gnFail(fname, "negative value not allowed", arg, name);
|
||
|
|
||
|
if ((flags & GN_GT_0) && res <= 0)
|
||
|
gnFail(fname, "value must be > 0", arg, name);
|
||
|
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
/* Convert a numeric command-line argument string to a long integer. See the
|
||
|
comments for getNum() for a description of the arguments to this function. */
|
||
|
|
||
|
long
|
||
|
getLong(const char *arg, int flags, const char *name)
|
||
|
{
|
||
|
return getNum("getLong", arg, flags, name);
|
||
|
}
|
||
|
|
||
|
/* Convert a numeric command-line argument string to an integer. See the
|
||
|
comments for getNum() for a description of the arguments to this function. */
|
||
|
|
||
|
int
|
||
|
getInt(const char *arg, int flags, const char *name)
|
||
|
{
|
||
|
long res;
|
||
|
|
||
|
res = getNum("getInt", arg, flags, name);
|
||
|
|
||
|
if (res > INT_MAX || res < INT_MIN)
|
||
|
gnFail("getInt", "integer out of range", arg, name);
|
||
|
|
||
|
return (int) res;
|
||
|
}
|