diff options
Diffstat (limited to 'winsup/cygwin/socket_tests/lib/get_num.c')
-rw-r--r-- | winsup/cygwin/socket_tests/lib/get_num.c | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/winsup/cygwin/socket_tests/lib/get_num.c b/winsup/cygwin/socket_tests/lib/get_num.c new file mode 100644 index 000000000..e8e1ad225 --- /dev/null +++ b/winsup/cygwin/socket_tests/lib/get_num.c @@ -0,0 +1,103 @@ +/*************************************************************************\ +* 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; +} |