xref: /openbmc/u-boot/lib/strto.c (revision 592cd5defd4f71d34ffcbd8dd3326bc10f662e20)
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 */
_parse_integer_fixup_radix(const char * s,unsigned int * base)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 
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 
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 
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);
88a353e6aaSMiquel Raynal 	switch (tolower(**endp)) {
89a353e6aaSMiquel Raynal 	case 'g':
90e4c5383eSSjoerd Simons 		result *= 1024;
91e4c5383eSSjoerd Simons 		/* fall through */
92a353e6aaSMiquel Raynal 	case 'm':
93e4c5383eSSjoerd Simons 		result *= 1024;
94e4c5383eSSjoerd Simons 		/* fall through */
95e4c5383eSSjoerd Simons 	case 'k':
96e4c5383eSSjoerd Simons 		result *= 1024;
97*b87b0d8dSMiquel Raynal 		(*endp)++;
98*b87b0d8dSMiquel Raynal 		if (**endp == 'i')
99*b87b0d8dSMiquel Raynal 			(*endp)++;
100*b87b0d8dSMiquel Raynal 		if (**endp == 'B')
101*b87b0d8dSMiquel Raynal 			(*endp)++;
102e4c5383eSSjoerd Simons 	}
103e4c5383eSSjoerd Simons 	return result;
104e4c5383eSSjoerd Simons }
105e4c5383eSSjoerd Simons 
ustrtoull(const char * cp,char ** endp,unsigned int base)106e4c5383eSSjoerd Simons unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base)
107e4c5383eSSjoerd Simons {
108e4c5383eSSjoerd Simons 	unsigned long long result = simple_strtoull(cp, endp, base);
109a353e6aaSMiquel Raynal 	switch (tolower(**endp)) {
110a353e6aaSMiquel Raynal 	case 'g':
111e4c5383eSSjoerd Simons 		result *= 1024;
112e4c5383eSSjoerd Simons 		/* fall through */
113a353e6aaSMiquel Raynal 	case 'm':
114e4c5383eSSjoerd Simons 		result *= 1024;
115e4c5383eSSjoerd Simons 		/* fall through */
116e4c5383eSSjoerd Simons 	case 'k':
117e4c5383eSSjoerd Simons 		result *= 1024;
118*b87b0d8dSMiquel Raynal 		(*endp)++;
119*b87b0d8dSMiquel Raynal 		if (**endp == 'i')
120*b87b0d8dSMiquel Raynal 			(*endp)++;
121*b87b0d8dSMiquel Raynal 		if (**endp == 'B')
122*b87b0d8dSMiquel Raynal 			(*endp)++;
123e4c5383eSSjoerd Simons 	}
124e4c5383eSSjoerd Simons 	return result;
125e4c5383eSSjoerd Simons }
126e4c5383eSSjoerd Simons 
simple_strtoull(const char * cp,char ** endp,unsigned int base)127e4c5383eSSjoerd Simons unsigned long long simple_strtoull(const char *cp, char **endp,
128e4c5383eSSjoerd Simons 					unsigned int base)
129e4c5383eSSjoerd Simons {
130e4c5383eSSjoerd Simons 	unsigned long long result = 0, value;
131e4c5383eSSjoerd Simons 
1322e794614SRob Clark 	cp = _parse_integer_fixup_radix(cp, &base);
133e4c5383eSSjoerd Simons 
134e4c5383eSSjoerd Simons 	while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp - '0'
135e4c5383eSSjoerd Simons 		: (islower(*cp) ? toupper(*cp) : *cp) - 'A' + 10) < base) {
136e4c5383eSSjoerd Simons 		result = result * base + value;
137e4c5383eSSjoerd Simons 		cp++;
138e4c5383eSSjoerd Simons 	}
139e4c5383eSSjoerd Simons 
140e4c5383eSSjoerd Simons 	if (endp)
141e4c5383eSSjoerd Simons 		*endp = (char *) cp;
142e4c5383eSSjoerd Simons 
143e4c5383eSSjoerd Simons 	return result;
144e4c5383eSSjoerd Simons }
145e4c5383eSSjoerd Simons 
trailing_strtoln(const char * str,const char * end)146e4c5383eSSjoerd Simons long trailing_strtoln(const char *str, const char *end)
147e4c5383eSSjoerd Simons {
148e4c5383eSSjoerd Simons 	const char *p;
149e4c5383eSSjoerd Simons 
150e4c5383eSSjoerd Simons 	if (!end)
151e4c5383eSSjoerd Simons 		end = str + strlen(str);
152b91c6a12SSimon Glass 	if (isdigit(end[-1])) {
153e4c5383eSSjoerd Simons 		for (p = end - 1; p > str; p--) {
154e4c5383eSSjoerd Simons 			if (!isdigit(*p))
155e4c5383eSSjoerd Simons 				return simple_strtoul(p + 1, NULL, 10);
156e4c5383eSSjoerd Simons 		}
157b91c6a12SSimon Glass 	}
158e4c5383eSSjoerd Simons 
159e4c5383eSSjoerd Simons 	return -1;
160e4c5383eSSjoerd Simons }
161e4c5383eSSjoerd Simons 
trailing_strtol(const char * str)162e4c5383eSSjoerd Simons long trailing_strtol(const char *str)
163e4c5383eSSjoerd Simons {
164e4c5383eSSjoerd Simons 	return trailing_strtoln(str, NULL);
165e4c5383eSSjoerd Simons }
166