blob: 3b9134a7443470bcc32938e832234844180ab994 [file] [log] [blame]
Eric Andersenaad1a882001-03-16 22:47:14 +00001/* vi: set sw=4 ts=4: */
2/*
Manuel Novoa III cad53642003-03-19 09:13:01 +00003 * bb_xparse_number implementation for busybox
Eric Andersenaad1a882001-03-16 22:47:14 +00004 *
Manuel Novoa III cad53642003-03-19 09:13:01 +00005 * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
Eric Andersenaad1a882001-03-16 22:47:14 +00006 *
"Robert P. J. Day"5d8843e2006-07-10 11:41:19 +00007 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
Eric Andersenaad1a882001-03-16 22:47:14 +00008 */
9
Eric Andersenaad1a882001-03-16 22:47:14 +000010#include <stdlib.h>
Manuel Novoa III cad53642003-03-19 09:13:01 +000011#include <string.h>
12#include <limits.h>
13#include <errno.h>
14#include <assert.h>
Eric Andersenaad1a882001-03-16 22:47:14 +000015#include "libbb.h"
16
Manuel Novoa III cad53642003-03-19 09:13:01 +000017unsigned long bb_xparse_number(const char *numstr,
18 const struct suffix_mult *suffixes)
Eric Andersenaad1a882001-03-16 22:47:14 +000019{
Manuel Novoa III cad53642003-03-19 09:13:01 +000020 unsigned long int r;
21 char *e;
22 int old_errno;
Eric Andersenc7bda1c2004-03-15 08:29:22 +000023
Manuel Novoa III cad53642003-03-19 09:13:01 +000024 /* Since this is a lib function, we're not allowed to reset errno to 0.
25 * Doing so could break an app that is deferring checking of errno.
26 * So, save the old value so that we can restore it if successful. */
27 old_errno = errno;
28 errno = 0;
29 r = strtoul(numstr, &e, 10);
30
31 if ((numstr != e) && !errno) {
32 errno = old_errno; /* Ok. So restore errno. */
33 if (!*e) {
34 return r;
Eric Andersenaad1a882001-03-16 22:47:14 +000035 }
Manuel Novoa III cad53642003-03-19 09:13:01 +000036 if (suffixes) {
37 assert(suffixes->suffix); /* No nul suffixes. */
38 do {
39 if (strcmp(suffixes->suffix, e) == 0) {
40 if (ULONG_MAX / suffixes->mult < r) { /* Overflow! */
41 break;
42 }
43 return r * suffixes->mult;
44 }
45 ++suffixes;
46 } while (suffixes->suffix);
47 }
Eric Andersenaad1a882001-03-16 22:47:14 +000048 }
Manuel Novoa III cad53642003-03-19 09:13:01 +000049 bb_error_msg_and_die("invalid number `%s'", numstr);
Eric Andersenaad1a882001-03-16 22:47:14 +000050}