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 162e794614SRob Clark /* from lib/kstrtox.c */ 172e794614SRob Clark static const char *_parse_integer_fixup_radix(const char *s, unsigned int *base) 182e794614SRob Clark { 192e794614SRob Clark if (*base == 0) { 202e794614SRob Clark if (s[0] == '0') { 212e794614SRob Clark if (tolower(s[1]) == 'x' && isxdigit(s[2])) 222e794614SRob Clark *base = 16; 232e794614SRob Clark else 242e794614SRob Clark *base = 8; 252e794614SRob Clark } else 262e794614SRob Clark *base = 10; 272e794614SRob Clark } 282e794614SRob Clark if (*base == 16 && s[0] == '0' && tolower(s[1]) == 'x') 292e794614SRob Clark s += 2; 302e794614SRob Clark return s; 312e794614SRob Clark } 322e794614SRob Clark 33e4c5383eSSjoerd Simons unsigned long simple_strtoul(const char *cp, char **endp, 34e4c5383eSSjoerd Simons unsigned int base) 35e4c5383eSSjoerd Simons { 36e4c5383eSSjoerd Simons unsigned long result = 0; 37e4c5383eSSjoerd Simons unsigned long value; 38e4c5383eSSjoerd Simons 392e794614SRob Clark cp = _parse_integer_fixup_radix(cp, &base); 40e4c5383eSSjoerd Simons 41e4c5383eSSjoerd Simons while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) 42e4c5383eSSjoerd Simons ? toupper(*cp) : *cp)-'A'+10) < base) { 43e4c5383eSSjoerd Simons result = result*base + value; 44e4c5383eSSjoerd Simons cp++; 45e4c5383eSSjoerd Simons } 46e4c5383eSSjoerd Simons 47e4c5383eSSjoerd Simons if (endp) 48e4c5383eSSjoerd Simons *endp = (char *)cp; 49e4c5383eSSjoerd Simons 50e4c5383eSSjoerd Simons return result; 51e4c5383eSSjoerd Simons } 52e4c5383eSSjoerd Simons 53e4c5383eSSjoerd Simons int strict_strtoul(const char *cp, unsigned int base, unsigned long *res) 54e4c5383eSSjoerd Simons { 55e4c5383eSSjoerd Simons char *tail; 56e4c5383eSSjoerd Simons unsigned long val; 57e4c5383eSSjoerd Simons size_t len; 58e4c5383eSSjoerd Simons 59e4c5383eSSjoerd Simons *res = 0; 60e4c5383eSSjoerd Simons len = strlen(cp); 61e4c5383eSSjoerd Simons if (len == 0) 62e4c5383eSSjoerd Simons return -EINVAL; 63e4c5383eSSjoerd Simons 64e4c5383eSSjoerd Simons val = simple_strtoul(cp, &tail, base); 65e4c5383eSSjoerd Simons if (tail == cp) 66e4c5383eSSjoerd Simons return -EINVAL; 67e4c5383eSSjoerd Simons 68e4c5383eSSjoerd Simons if ((*tail == '\0') || 69e4c5383eSSjoerd Simons ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) { 70e4c5383eSSjoerd Simons *res = val; 71e4c5383eSSjoerd Simons return 0; 72e4c5383eSSjoerd Simons } 73e4c5383eSSjoerd Simons 74e4c5383eSSjoerd Simons return -EINVAL; 75e4c5383eSSjoerd Simons } 76e4c5383eSSjoerd Simons 77e4c5383eSSjoerd Simons long simple_strtol(const char *cp, char **endp, unsigned int base) 78e4c5383eSSjoerd Simons { 79e4c5383eSSjoerd Simons if (*cp == '-') 80e4c5383eSSjoerd Simons return -simple_strtoul(cp + 1, endp, base); 81e4c5383eSSjoerd Simons 82e4c5383eSSjoerd Simons return simple_strtoul(cp, endp, base); 83e4c5383eSSjoerd Simons } 84e4c5383eSSjoerd Simons 85e4c5383eSSjoerd Simons unsigned long ustrtoul(const char *cp, char **endp, unsigned int base) 86e4c5383eSSjoerd Simons { 87e4c5383eSSjoerd Simons unsigned long result = simple_strtoul(cp, endp, base); 88*a353e6aaSMiquel Raynal switch (tolower(**endp)) { 89*a353e6aaSMiquel Raynal case 'g': 90e4c5383eSSjoerd Simons result *= 1024; 91e4c5383eSSjoerd Simons /* fall through */ 92*a353e6aaSMiquel Raynal case 'm': 93e4c5383eSSjoerd Simons result *= 1024; 94e4c5383eSSjoerd Simons /* fall through */ 95e4c5383eSSjoerd Simons case 'k': 96e4c5383eSSjoerd Simons result *= 1024; 97e4c5383eSSjoerd Simons if ((*endp)[1] == 'i') { 98e4c5383eSSjoerd Simons if ((*endp)[2] == 'B') 99e4c5383eSSjoerd Simons (*endp) += 3; 100e4c5383eSSjoerd Simons else 101e4c5383eSSjoerd Simons (*endp) += 2; 102e4c5383eSSjoerd Simons } 103e4c5383eSSjoerd Simons } 104e4c5383eSSjoerd Simons return result; 105e4c5383eSSjoerd Simons } 106e4c5383eSSjoerd Simons 107e4c5383eSSjoerd Simons unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base) 108e4c5383eSSjoerd Simons { 109e4c5383eSSjoerd Simons unsigned long long result = simple_strtoull(cp, endp, base); 110*a353e6aaSMiquel Raynal switch (tolower(**endp)) { 111*a353e6aaSMiquel Raynal case 'g': 112e4c5383eSSjoerd Simons result *= 1024; 113e4c5383eSSjoerd Simons /* fall through */ 114*a353e6aaSMiquel Raynal case 'm': 115e4c5383eSSjoerd Simons result *= 1024; 116e4c5383eSSjoerd Simons /* fall through */ 117e4c5383eSSjoerd Simons case 'k': 118e4c5383eSSjoerd Simons result *= 1024; 119e4c5383eSSjoerd Simons if ((*endp)[1] == 'i') { 120e4c5383eSSjoerd Simons if ((*endp)[2] == 'B') 121e4c5383eSSjoerd Simons (*endp) += 3; 122e4c5383eSSjoerd Simons else 123e4c5383eSSjoerd Simons (*endp) += 2; 124e4c5383eSSjoerd Simons } 125e4c5383eSSjoerd Simons } 126e4c5383eSSjoerd Simons return result; 127e4c5383eSSjoerd Simons } 128e4c5383eSSjoerd Simons 129e4c5383eSSjoerd Simons unsigned long long simple_strtoull(const char *cp, char **endp, 130e4c5383eSSjoerd Simons unsigned int base) 131e4c5383eSSjoerd Simons { 132e4c5383eSSjoerd Simons unsigned long long result = 0, value; 133e4c5383eSSjoerd Simons 1342e794614SRob Clark cp = _parse_integer_fixup_radix(cp, &base); 135e4c5383eSSjoerd Simons 136e4c5383eSSjoerd Simons while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp - '0' 137e4c5383eSSjoerd Simons : (islower(*cp) ? toupper(*cp) : *cp) - 'A' + 10) < base) { 138e4c5383eSSjoerd Simons result = result * base + value; 139e4c5383eSSjoerd Simons cp++; 140e4c5383eSSjoerd Simons } 141e4c5383eSSjoerd Simons 142e4c5383eSSjoerd Simons if (endp) 143e4c5383eSSjoerd Simons *endp = (char *) cp; 144e4c5383eSSjoerd Simons 145e4c5383eSSjoerd Simons return result; 146e4c5383eSSjoerd Simons } 147e4c5383eSSjoerd Simons 148e4c5383eSSjoerd Simons long trailing_strtoln(const char *str, const char *end) 149e4c5383eSSjoerd Simons { 150e4c5383eSSjoerd Simons const char *p; 151e4c5383eSSjoerd Simons 152e4c5383eSSjoerd Simons if (!end) 153e4c5383eSSjoerd Simons end = str + strlen(str); 154b91c6a12SSimon Glass if (isdigit(end[-1])) { 155e4c5383eSSjoerd Simons for (p = end - 1; p > str; p--) { 156e4c5383eSSjoerd Simons if (!isdigit(*p)) 157e4c5383eSSjoerd Simons return simple_strtoul(p + 1, NULL, 10); 158e4c5383eSSjoerd Simons } 159b91c6a12SSimon Glass } 160e4c5383eSSjoerd Simons 161e4c5383eSSjoerd Simons return -1; 162e4c5383eSSjoerd Simons } 163e4c5383eSSjoerd Simons 164e4c5383eSSjoerd Simons long trailing_strtol(const char *str) 165e4c5383eSSjoerd Simons { 166e4c5383eSSjoerd Simons return trailing_strtoln(str, NULL); 167e4c5383eSSjoerd Simons } 168