| /* | |
| * linux/lib/vsprintf.c | |
| * | |
| * Copyright (C) 1991, 1992 Linus Torvalds | |
| */ | |
| /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */ | |
| /* | |
| * Wirzenius wrote this portably, Torvalds fucked it up :-) | |
| */ | |
| #include <common.h> | |
| #include <errno.h> | |
| #include <linux/ctype.h> | |
| unsigned long simple_strtoul(const char *cp, char **endp, | |
| unsigned int base) | |
| { | |
| unsigned long result = 0; | |
| unsigned long value; | |
| if (*cp == '0') { | |
| cp++; | |
| if ((*cp == 'x') && isxdigit(cp[1])) { | |
| base = 16; | |
| cp++; | |
| } | |
| if (!base) | |
| base = 8; | |
| } | |
| if (!base) | |
| base = 10; | |
| while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) | |
| ? toupper(*cp) : *cp)-'A'+10) < base) { | |
| result = result*base + value; | |
| cp++; | |
| } | |
| if (endp) | |
| *endp = (char *)cp; | |
| return result; | |
| } | |
| int strict_strtoul(const char *cp, unsigned int base, unsigned long *res) | |
| { | |
| char *tail; | |
| unsigned long val; | |
| size_t len; | |
| *res = 0; | |
| len = strlen(cp); | |
| if (len == 0) | |
| return -EINVAL; | |
| val = simple_strtoul(cp, &tail, base); | |
| if (tail == cp) | |
| return -EINVAL; | |
| if ((*tail == '\0') || | |
| ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) { | |
| *res = val; | |
| return 0; | |
| } | |
| return -EINVAL; | |
| } | |
| long simple_strtol(const char *cp, char **endp, unsigned int base) | |
| { | |
| if (*cp == '-') | |
| return -simple_strtoul(cp + 1, endp, base); | |
| return simple_strtoul(cp, endp, base); | |
| } | |
| unsigned long ustrtoul(const char *cp, char **endp, unsigned int base) | |
| { | |
| unsigned long result = simple_strtoul(cp, endp, base); | |
| switch (**endp) { | |
| case 'G': | |
| result *= 1024; | |
| /* fall through */ | |
| case 'M': | |
| result *= 1024; | |
| /* fall through */ | |
| case 'K': | |
| case 'k': | |
| result *= 1024; | |
| if ((*endp)[1] == 'i') { | |
| if ((*endp)[2] == 'B') | |
| (*endp) += 3; | |
| else | |
| (*endp) += 2; | |
| } | |
| } | |
| return result; | |
| } | |
| unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base) | |
| { | |
| unsigned long long result = simple_strtoull(cp, endp, base); | |
| switch (**endp) { | |
| case 'G': | |
| result *= 1024; | |
| /* fall through */ | |
| case 'M': | |
| result *= 1024; | |
| /* fall through */ | |
| case 'K': | |
| case 'k': | |
| result *= 1024; | |
| if ((*endp)[1] == 'i') { | |
| if ((*endp)[2] == 'B') | |
| (*endp) += 3; | |
| else | |
| (*endp) += 2; | |
| } | |
| } | |
| return result; | |
| } | |
| unsigned long long simple_strtoull(const char *cp, char **endp, | |
| unsigned int base) | |
| { | |
| unsigned long long result = 0, value; | |
| if (*cp == '0') { | |
| cp++; | |
| if ((*cp == 'x') && isxdigit(cp[1])) { | |
| base = 16; | |
| cp++; | |
| } | |
| if (!base) | |
| base = 8; | |
| } | |
| if (!base) | |
| base = 10; | |
| while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp - '0' | |
| : (islower(*cp) ? toupper(*cp) : *cp) - 'A' + 10) < base) { | |
| result = result * base + value; | |
| cp++; | |
| } | |
| if (endp) | |
| *endp = (char *) cp; | |
| return result; | |
| } | |
| long trailing_strtoln(const char *str, const char *end) | |
| { | |
| const char *p; | |
| if (!end) | |
| end = str + strlen(str); | |
| if (isdigit(end[-1])) { | |
| for (p = end - 1; p > str; p--) { | |
| if (!isdigit(*p)) | |
| return simple_strtoul(p + 1, NULL, 10); | |
| } | |
| } | |
| return -1; | |
| } | |
| long trailing_strtol(const char *str) | |
| { | |
| return trailing_strtoln(str, NULL); | |
| } |