1e4c5383eSSjoerd Simons /* 2e4c5383eSSjoerd Simons * linux/lib/vsprintf.c 3e4c5383eSSjoerd Simons * 4e4c5383eSSjoerd Simons * Copyright (C) 1991, 1992 Linus Torvalds 5e4c5383eSSjoerd Simons */ 6e4c5383eSSjoerd Simons 7e4c5383eSSjoerd Simons /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */ 8e4c5383eSSjoerd Simons /* 9e4c5383eSSjoerd Simons * Wirzenius wrote this portably, Torvalds fucked it up :-) 10e4c5383eSSjoerd Simons */ 11e4c5383eSSjoerd Simons 12e4c5383eSSjoerd Simons #include <common.h> 13e4c5383eSSjoerd Simons #include <errno.h> 14e4c5383eSSjoerd Simons #include <linux/ctype.h> 15e4c5383eSSjoerd Simons 16e4c5383eSSjoerd Simons unsigned long simple_strtoul(const char *cp, char **endp, 17e4c5383eSSjoerd Simons unsigned int base) 18e4c5383eSSjoerd Simons { 19e4c5383eSSjoerd Simons unsigned long result = 0; 20e4c5383eSSjoerd Simons unsigned long value; 21e4c5383eSSjoerd Simons 22e4c5383eSSjoerd Simons if (*cp == '0') { 23e4c5383eSSjoerd Simons cp++; 24e4c5383eSSjoerd Simons if ((*cp == 'x') && isxdigit(cp[1])) { 25e4c5383eSSjoerd Simons base = 16; 26e4c5383eSSjoerd Simons cp++; 27e4c5383eSSjoerd Simons } 28e4c5383eSSjoerd Simons 29e4c5383eSSjoerd Simons if (!base) 30e4c5383eSSjoerd Simons base = 8; 31e4c5383eSSjoerd Simons } 32e4c5383eSSjoerd Simons 33e4c5383eSSjoerd Simons if (!base) 34e4c5383eSSjoerd Simons base = 10; 35e4c5383eSSjoerd Simons 36e4c5383eSSjoerd Simons while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) 37e4c5383eSSjoerd Simons ? toupper(*cp) : *cp)-'A'+10) < base) { 38e4c5383eSSjoerd Simons result = result*base + value; 39e4c5383eSSjoerd Simons cp++; 40e4c5383eSSjoerd Simons } 41e4c5383eSSjoerd Simons 42e4c5383eSSjoerd Simons if (endp) 43e4c5383eSSjoerd Simons *endp = (char *)cp; 44e4c5383eSSjoerd Simons 45e4c5383eSSjoerd Simons return result; 46e4c5383eSSjoerd Simons } 47e4c5383eSSjoerd Simons 48e4c5383eSSjoerd Simons int strict_strtoul(const char *cp, unsigned int base, unsigned long *res) 49e4c5383eSSjoerd Simons { 50e4c5383eSSjoerd Simons char *tail; 51e4c5383eSSjoerd Simons unsigned long val; 52e4c5383eSSjoerd Simons size_t len; 53e4c5383eSSjoerd Simons 54e4c5383eSSjoerd Simons *res = 0; 55e4c5383eSSjoerd Simons len = strlen(cp); 56e4c5383eSSjoerd Simons if (len == 0) 57e4c5383eSSjoerd Simons return -EINVAL; 58e4c5383eSSjoerd Simons 59e4c5383eSSjoerd Simons val = simple_strtoul(cp, &tail, base); 60e4c5383eSSjoerd Simons if (tail == cp) 61e4c5383eSSjoerd Simons return -EINVAL; 62e4c5383eSSjoerd Simons 63e4c5383eSSjoerd Simons if ((*tail == '\0') || 64e4c5383eSSjoerd Simons ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) { 65e4c5383eSSjoerd Simons *res = val; 66e4c5383eSSjoerd Simons return 0; 67e4c5383eSSjoerd Simons } 68e4c5383eSSjoerd Simons 69e4c5383eSSjoerd Simons return -EINVAL; 70e4c5383eSSjoerd Simons } 71e4c5383eSSjoerd Simons 72e4c5383eSSjoerd Simons long simple_strtol(const char *cp, char **endp, unsigned int base) 73e4c5383eSSjoerd Simons { 74e4c5383eSSjoerd Simons if (*cp == '-') 75e4c5383eSSjoerd Simons return -simple_strtoul(cp + 1, endp, base); 76e4c5383eSSjoerd Simons 77e4c5383eSSjoerd Simons return simple_strtoul(cp, endp, base); 78e4c5383eSSjoerd Simons } 79e4c5383eSSjoerd Simons 80e4c5383eSSjoerd Simons unsigned long ustrtoul(const char *cp, char **endp, unsigned int base) 81e4c5383eSSjoerd Simons { 82e4c5383eSSjoerd Simons unsigned long result = simple_strtoul(cp, endp, base); 83e4c5383eSSjoerd Simons switch (**endp) { 84e4c5383eSSjoerd Simons case 'G': 85e4c5383eSSjoerd Simons result *= 1024; 86e4c5383eSSjoerd Simons /* fall through */ 87e4c5383eSSjoerd Simons case 'M': 88e4c5383eSSjoerd Simons result *= 1024; 89e4c5383eSSjoerd Simons /* fall through */ 90e4c5383eSSjoerd Simons case 'K': 91e4c5383eSSjoerd Simons case 'k': 92e4c5383eSSjoerd Simons result *= 1024; 93e4c5383eSSjoerd Simons if ((*endp)[1] == 'i') { 94e4c5383eSSjoerd Simons if ((*endp)[2] == 'B') 95e4c5383eSSjoerd Simons (*endp) += 3; 96e4c5383eSSjoerd Simons else 97e4c5383eSSjoerd Simons (*endp) += 2; 98e4c5383eSSjoerd Simons } 99e4c5383eSSjoerd Simons } 100e4c5383eSSjoerd Simons return result; 101e4c5383eSSjoerd Simons } 102e4c5383eSSjoerd Simons 103e4c5383eSSjoerd Simons unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base) 104e4c5383eSSjoerd Simons { 105e4c5383eSSjoerd Simons unsigned long long result = simple_strtoull(cp, endp, base); 106e4c5383eSSjoerd Simons switch (**endp) { 107e4c5383eSSjoerd Simons case 'G': 108e4c5383eSSjoerd Simons result *= 1024; 109e4c5383eSSjoerd Simons /* fall through */ 110e4c5383eSSjoerd Simons case 'M': 111e4c5383eSSjoerd Simons result *= 1024; 112e4c5383eSSjoerd Simons /* fall through */ 113e4c5383eSSjoerd Simons case 'K': 114e4c5383eSSjoerd Simons case 'k': 115e4c5383eSSjoerd Simons result *= 1024; 116e4c5383eSSjoerd Simons if ((*endp)[1] == 'i') { 117e4c5383eSSjoerd Simons if ((*endp)[2] == 'B') 118e4c5383eSSjoerd Simons (*endp) += 3; 119e4c5383eSSjoerd Simons else 120e4c5383eSSjoerd Simons (*endp) += 2; 121e4c5383eSSjoerd Simons } 122e4c5383eSSjoerd Simons } 123e4c5383eSSjoerd Simons return result; 124e4c5383eSSjoerd Simons } 125e4c5383eSSjoerd Simons 126e4c5383eSSjoerd Simons unsigned long long simple_strtoull(const char *cp, char **endp, 127e4c5383eSSjoerd Simons unsigned int base) 128e4c5383eSSjoerd Simons { 129e4c5383eSSjoerd Simons unsigned long long result = 0, value; 130e4c5383eSSjoerd Simons 131e4c5383eSSjoerd Simons if (*cp == '0') { 132e4c5383eSSjoerd Simons cp++; 133e4c5383eSSjoerd Simons if ((*cp == 'x') && isxdigit(cp[1])) { 134e4c5383eSSjoerd Simons base = 16; 135e4c5383eSSjoerd Simons cp++; 136e4c5383eSSjoerd Simons } 137e4c5383eSSjoerd Simons 138e4c5383eSSjoerd Simons if (!base) 139e4c5383eSSjoerd Simons base = 8; 140e4c5383eSSjoerd Simons } 141e4c5383eSSjoerd Simons 142e4c5383eSSjoerd Simons if (!base) 143e4c5383eSSjoerd Simons base = 10; 144e4c5383eSSjoerd Simons 145e4c5383eSSjoerd Simons while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp - '0' 146e4c5383eSSjoerd Simons : (islower(*cp) ? toupper(*cp) : *cp) - 'A' + 10) < base) { 147e4c5383eSSjoerd Simons result = result * base + value; 148e4c5383eSSjoerd Simons cp++; 149e4c5383eSSjoerd Simons } 150e4c5383eSSjoerd Simons 151e4c5383eSSjoerd Simons if (endp) 152e4c5383eSSjoerd Simons *endp = (char *) cp; 153e4c5383eSSjoerd Simons 154e4c5383eSSjoerd Simons return result; 155e4c5383eSSjoerd Simons } 156e4c5383eSSjoerd Simons 157e4c5383eSSjoerd Simons long trailing_strtoln(const char *str, const char *end) 158e4c5383eSSjoerd Simons { 159e4c5383eSSjoerd Simons const char *p; 160e4c5383eSSjoerd Simons 161e4c5383eSSjoerd Simons if (!end) 162e4c5383eSSjoerd Simons end = str + strlen(str); 163*b91c6a12SSimon Glass if (isdigit(end[-1])) { 164e4c5383eSSjoerd Simons for (p = end - 1; p > str; p--) { 165e4c5383eSSjoerd Simons if (!isdigit(*p)) 166e4c5383eSSjoerd Simons return simple_strtoul(p + 1, NULL, 10); 167e4c5383eSSjoerd Simons } 168*b91c6a12SSimon Glass } 169e4c5383eSSjoerd Simons 170e4c5383eSSjoerd Simons return -1; 171e4c5383eSSjoerd Simons } 172e4c5383eSSjoerd Simons 173e4c5383eSSjoerd Simons long trailing_strtol(const char *str) 174e4c5383eSSjoerd Simons { 175e4c5383eSSjoerd Simons return trailing_strtoln(str, NULL); 176e4c5383eSSjoerd Simons } 177