1 /*
2  *  linux/lib/vsprintf.c
3  *
4  *  Copyright (C) 1991, 1992  Linus Torvalds
5  */
6 
7 /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
8 /*
9  * Wirzenius wrote this portably, Torvalds fucked it up :-)
10  */
11 
12 #include <common.h>
13 #include <errno.h>
14 #include <malloc.h>
15 #include <linux/ctype.h>
16 
17 /* from lib/kstrtox.c */
_parse_integer_fixup_radix(const char * s,uint * basep)18 static const char *_parse_integer_fixup_radix(const char *s, uint *basep)
19 {
20 	/* Look for a 0x prefix */
21 	if (s[0] == '0') {
22 		int ch = tolower(s[1]);
23 
24 		if (ch == 'x') {
25 			*basep = 16;
26 			s += 2;
27 		} else if (!*basep) {
28 			/* Only select octal if we don't have a base */
29 			*basep = 8;
30 		}
31 	}
32 
33 	/* Use decimal by default */
34 	if (!*basep)
35 		*basep = 10;
36 
37 	return s;
38 }
39 
40 /**
41  * decode_digit() - Decode a single character into its numeric digit value
42  *
43  * This ignore case
44  *
45  * @ch: Character to convert (expects '0'..'9', 'a'..'f' or 'A'..'F')
46  * Return: value of digit (0..0xf) or 255 if the character is invalid
47  */
decode_digit(int ch)48 static uint decode_digit(int ch)
49 {
50 	if (!isxdigit(ch))
51 		return 256;
52 
53 	ch = tolower(ch);
54 
55 	return ch <= '9' ? ch - '0' : ch - 'a' + 0xa;
56 }
57 
simple_strtoul(const char * cp,char ** endp,uint base)58 ulong simple_strtoul(const char *cp, char **endp, uint base)
59 {
60 	ulong result = 0;
61 	uint value;
62 
63 	cp = _parse_integer_fixup_radix(cp, &base);
64 
65 	while (value = decode_digit(*cp), value < base) {
66 		result = result * base + value;
67 		cp++;
68 	}
69 
70 	if (endp)
71 		*endp = (char *)cp;
72 
73 	return result;
74 }
75 
hextoul(const char * cp,char ** endp)76 ulong hextoul(const char *cp, char **endp)
77 {
78 	return simple_strtoul(cp, endp, 16);
79 }
80 
dectoul(const char * cp,char ** endp)81 ulong dectoul(const char *cp, char **endp)
82 {
83 	return simple_strtoul(cp, endp, 10);
84 }
85 
strict_strtoul(const char * cp,unsigned int base,unsigned long * res)86 int strict_strtoul(const char *cp, unsigned int base, unsigned long *res)
87 {
88 	char *tail;
89 	unsigned long val;
90 	size_t len;
91 
92 	*res = 0;
93 	len = strlen(cp);
94 	if (len == 0)
95 		return -EINVAL;
96 
97 	val = simple_strtoul(cp, &tail, base);
98 	if (tail == cp)
99 		return -EINVAL;
100 
101 	if ((*tail == '\0') ||
102 		((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
103 		*res = val;
104 		return 0;
105 	}
106 
107 	return -EINVAL;
108 }
109 
simple_strtol(const char * cp,char ** endp,unsigned int base)110 long simple_strtol(const char *cp, char **endp, unsigned int base)
111 {
112 	if (*cp == '-')
113 		return -simple_strtoul(cp + 1, endp, base);
114 
115 	return simple_strtoul(cp, endp, base);
116 }
117 
ustrtoul(const char * cp,char ** endp,unsigned int base)118 unsigned long ustrtoul(const char *cp, char **endp, unsigned int base)
119 {
120 	unsigned long result = simple_strtoul(cp, endp, base);
121 	switch (tolower(**endp)) {
122 	case 'g':
123 		result *= 1024;
124 		/* fall through */
125 	case 'm':
126 		result *= 1024;
127 		/* fall through */
128 	case 'k':
129 		result *= 1024;
130 		(*endp)++;
131 		if (**endp == 'i')
132 			(*endp)++;
133 		if (**endp == 'B')
134 			(*endp)++;
135 	}
136 	return result;
137 }
138 
ustrtoull(const char * cp,char ** endp,unsigned int base)139 unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base)
140 {
141 	unsigned long long result = simple_strtoull(cp, endp, base);
142 	switch (tolower(**endp)) {
143 	case 'g':
144 		result *= 1024;
145 		/* fall through */
146 	case 'm':
147 		result *= 1024;
148 		/* fall through */
149 	case 'k':
150 		result *= 1024;
151 		(*endp)++;
152 		if (**endp == 'i')
153 			(*endp)++;
154 		if (**endp == 'B')
155 			(*endp)++;
156 	}
157 	return result;
158 }
159 
simple_strtoull(const char * cp,char ** endp,unsigned int base)160 unsigned long long simple_strtoull(const char *cp, char **endp,
161 					unsigned int base)
162 {
163 	unsigned long long result = 0;
164 	uint value;
165 
166 	cp = _parse_integer_fixup_radix(cp, &base);
167 
168 	while (value = decode_digit(*cp), value < base) {
169 		result = result * base + value;
170 		cp++;
171 	}
172 
173 	if (endp)
174 		*endp = (char *) cp;
175 
176 	return result;
177 }
178 
simple_strtoll(const char * cp,char ** endp,unsigned int base)179 long long simple_strtoll(const char *cp, char **endp, unsigned int base)
180 {
181 	if (*cp == '-')
182 		return -simple_strtoull(cp + 1, endp, base);
183 
184 	return simple_strtoull(cp, endp, base);
185 }
186 
trailing_strtoln_end(const char * str,const char * end,char const ** endp)187 long trailing_strtoln_end(const char *str, const char *end, char const **endp)
188 {
189 	const char *p;
190 
191 	if (!end)
192 		end = str + strlen(str);
193 	p = end - 1;
194 	if (p > str && isdigit(*p)) {
195 		do {
196 			if (!isdigit(p[-1])) {
197 				if (endp)
198 					*endp = p;
199 				return dectoul(p, NULL);
200 			}
201 		} while (--p > str);
202 	}
203 	if (endp)
204 		*endp = end;
205 
206 	return -1;
207 }
208 
trailing_strtoln(const char * str,const char * end)209 long trailing_strtoln(const char *str, const char *end)
210 {
211 	return trailing_strtoln_end(str, end, NULL);
212 }
213 
trailing_strtol(const char * str)214 long trailing_strtol(const char *str)
215 {
216 	return trailing_strtoln(str, NULL);
217 }
218 
str_to_upper(const char * in,char * out,size_t len)219 void str_to_upper(const char *in, char *out, size_t len)
220 {
221 	for (; len > 0 && *in; len--)
222 		*out++ = toupper(*in++);
223 	if (len)
224 		*out = '\0';
225 }
226 
str_to_list(const char * instr)227 const char **str_to_list(const char *instr)
228 {
229 	const char **ptr;
230 	char *str, *p;
231 	int count, i;
232 
233 	/* don't allocate if the string is empty */
234 	str = *instr ? strdup(instr) : (char *)instr;
235 	if (!str)
236 		return NULL;
237 
238 	/* count the number of space-separated strings */
239 	for (count = *str != '\0', p = str; *p; p++) {
240 		if (*p == ' ') {
241 			count++;
242 			*p = '\0';
243 		}
244 	}
245 
246 	/* allocate the pointer array, allowing for a NULL terminator */
247 	ptr = calloc(count + 1, sizeof(char *));
248 	if (!ptr) {
249 		if (*str)
250 			free(str);
251 		return NULL;
252 	}
253 
254 	for (i = 0, p = str; i < count; p += strlen(p) + 1, i++)
255 		ptr[i] = p;
256 
257 	return ptr;
258 }
259 
str_free_list(const char ** ptr)260 void str_free_list(const char **ptr)
261 {
262 	if (ptr)
263 		free((char *)ptr[0]);
264 	free(ptr);
265 }
266