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
16*48d1b0a5SRob Clark /* from lib/kstrtox.c */
_parse_integer_fixup_radix(const char * s,unsigned int * base)17*48d1b0a5SRob Clark static const char *_parse_integer_fixup_radix(const char *s, unsigned int *base)
18*48d1b0a5SRob Clark {
19*48d1b0a5SRob Clark if (*base == 0) {
20*48d1b0a5SRob Clark if (s[0] == '0') {
21*48d1b0a5SRob Clark if (tolower(s[1]) == 'x' && isxdigit(s[2]))
22*48d1b0a5SRob Clark *base = 16;
23*48d1b0a5SRob Clark else
24*48d1b0a5SRob Clark *base = 8;
25*48d1b0a5SRob Clark } else
26*48d1b0a5SRob Clark *base = 10;
27*48d1b0a5SRob Clark }
28*48d1b0a5SRob Clark if (*base == 16 && s[0] == '0' && tolower(s[1]) == 'x')
29*48d1b0a5SRob Clark s += 2;
30*48d1b0a5SRob Clark return s;
31*48d1b0a5SRob Clark }
32*48d1b0a5SRob Clark
simple_strtoul(const char * cp,char ** endp,unsigned int base)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
39*48d1b0a5SRob 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
strict_strtoul(const char * cp,unsigned int base,unsigned long * res)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
simple_strtol(const char * cp,char ** endp,unsigned int base)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
ustrtoul(const char * cp,char ** endp,unsigned int base)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);
88e4c5383eSSjoerd Simons switch (**endp) {
89e4c5383eSSjoerd Simons case 'G':
90e4c5383eSSjoerd Simons result *= 1024;
91e4c5383eSSjoerd Simons /* fall through */
92e4c5383eSSjoerd Simons case 'M':
93e4c5383eSSjoerd Simons result *= 1024;
94e4c5383eSSjoerd Simons /* fall through */
95e4c5383eSSjoerd Simons case 'K':
96e4c5383eSSjoerd Simons case 'k':
97e4c5383eSSjoerd Simons result *= 1024;
98e4c5383eSSjoerd Simons if ((*endp)[1] == 'i') {
99e4c5383eSSjoerd Simons if ((*endp)[2] == 'B')
100e4c5383eSSjoerd Simons (*endp) += 3;
101e4c5383eSSjoerd Simons else
102e4c5383eSSjoerd Simons (*endp) += 2;
103e4c5383eSSjoerd Simons }
104e4c5383eSSjoerd Simons }
105e4c5383eSSjoerd Simons return result;
106e4c5383eSSjoerd Simons }
107e4c5383eSSjoerd Simons
ustrtoull(const char * cp,char ** endp,unsigned int base)108e4c5383eSSjoerd Simons unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base)
109e4c5383eSSjoerd Simons {
110e4c5383eSSjoerd Simons unsigned long long result = simple_strtoull(cp, endp, base);
111e4c5383eSSjoerd Simons switch (**endp) {
112e4c5383eSSjoerd Simons case 'G':
113e4c5383eSSjoerd Simons result *= 1024;
114e4c5383eSSjoerd Simons /* fall through */
115e4c5383eSSjoerd Simons case 'M':
116e4c5383eSSjoerd Simons result *= 1024;
117e4c5383eSSjoerd Simons /* fall through */
118e4c5383eSSjoerd Simons case 'K':
119e4c5383eSSjoerd Simons case 'k':
120e4c5383eSSjoerd Simons result *= 1024;
121e4c5383eSSjoerd Simons if ((*endp)[1] == 'i') {
122e4c5383eSSjoerd Simons if ((*endp)[2] == 'B')
123e4c5383eSSjoerd Simons (*endp) += 3;
124e4c5383eSSjoerd Simons else
125e4c5383eSSjoerd Simons (*endp) += 2;
126e4c5383eSSjoerd Simons }
127e4c5383eSSjoerd Simons }
128e4c5383eSSjoerd Simons return result;
129e4c5383eSSjoerd Simons }
130e4c5383eSSjoerd Simons
simple_strtoull(const char * cp,char ** endp,unsigned int base)131e4c5383eSSjoerd Simons unsigned long long simple_strtoull(const char *cp, char **endp,
132e4c5383eSSjoerd Simons unsigned int base)
133e4c5383eSSjoerd Simons {
134e4c5383eSSjoerd Simons unsigned long long result = 0, value;
135e4c5383eSSjoerd Simons
136*48d1b0a5SRob Clark cp = _parse_integer_fixup_radix(cp, &base);
137e4c5383eSSjoerd Simons
138e4c5383eSSjoerd Simons while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp - '0'
139e4c5383eSSjoerd Simons : (islower(*cp) ? toupper(*cp) : *cp) - 'A' + 10) < base) {
140e4c5383eSSjoerd Simons result = result * base + value;
141e4c5383eSSjoerd Simons cp++;
142e4c5383eSSjoerd Simons }
143e4c5383eSSjoerd Simons
144e4c5383eSSjoerd Simons if (endp)
145e4c5383eSSjoerd Simons *endp = (char *) cp;
146e4c5383eSSjoerd Simons
147e4c5383eSSjoerd Simons return result;
148e4c5383eSSjoerd Simons }
149e4c5383eSSjoerd Simons
trailing_strtoln(const char * str,const char * end)150e4c5383eSSjoerd Simons long trailing_strtoln(const char *str, const char *end)
151e4c5383eSSjoerd Simons {
152e4c5383eSSjoerd Simons const char *p;
153e4c5383eSSjoerd Simons
154e4c5383eSSjoerd Simons if (!end)
155e4c5383eSSjoerd Simons end = str + strlen(str);
156b91c6a12SSimon Glass if (isdigit(end[-1])) {
157e4c5383eSSjoerd Simons for (p = end - 1; p > str; p--) {
158e4c5383eSSjoerd Simons if (!isdigit(*p))
159e4c5383eSSjoerd Simons return simple_strtoul(p + 1, NULL, 10);
160e4c5383eSSjoerd Simons }
161b91c6a12SSimon Glass }
162e4c5383eSSjoerd Simons
163e4c5383eSSjoerd Simons return -1;
164e4c5383eSSjoerd Simons }
165e4c5383eSSjoerd Simons
trailing_strtol(const char * str)166e4c5383eSSjoerd Simons long trailing_strtol(const char *str)
167e4c5383eSSjoerd Simons {
168e4c5383eSSjoerd Simons return trailing_strtoln(str, NULL);
169e4c5383eSSjoerd Simons }
170