]>
Commit | Line | Data |
---|---|---|
e4c5383e SS |
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 <linux/ctype.h> | |
15 | ||
2e794614 | 16 | /* from lib/kstrtox.c */ |
e6951139 | 17 | static const char *_parse_integer_fixup_radix(const char *s, uint *basep) |
2e794614 | 18 | { |
e6951139 SG |
19 | /* Look for a 0x prefix */ |
20 | if (s[0] == '0') { | |
21 | int ch = tolower(s[1]); | |
22 | ||
23 | if (ch == 'x') { | |
24 | *basep = 16; | |
25 | s += 2; | |
26 | } else if (!*basep) { | |
27 | /* Only select octal if we don't have a base */ | |
28 | *basep = 8; | |
29 | } | |
2e794614 | 30 | } |
e6951139 SG |
31 | |
32 | /* Use decimal by default */ | |
33 | if (!*basep) | |
34 | *basep = 10; | |
35 | ||
2e794614 RC |
36 | return s; |
37 | } | |
38 | ||
5a94546e SG |
39 | /** |
40 | * decode_digit() - Decode a single character into its numeric digit value | |
41 | * | |
42 | * This ignore case | |
43 | * | |
44 | * @ch: Character to convert (expects '0'..'9', 'a'..'f' or 'A'..'F') | |
185f812c | 45 | * Return: value of digit (0..0xf) or 255 if the character is invalid |
5a94546e SG |
46 | */ |
47 | static uint decode_digit(int ch) | |
48 | { | |
49 | if (!isxdigit(ch)) | |
50 | return 256; | |
51 | ||
52 | ch = tolower(ch); | |
53 | ||
54 | return ch <= '9' ? ch - '0' : ch - 'a' + 0xa; | |
55 | } | |
56 | ||
7e5f460e | 57 | ulong simple_strtoul(const char *cp, char **endp, uint base) |
e4c5383e | 58 | { |
7e5f460e | 59 | ulong result = 0; |
5a94546e | 60 | uint value; |
e4c5383e | 61 | |
2e794614 | 62 | cp = _parse_integer_fixup_radix(cp, &base); |
e4c5383e | 63 | |
5a94546e SG |
64 | while (value = decode_digit(*cp), value < base) { |
65 | result = result * base + value; | |
e4c5383e SS |
66 | cp++; |
67 | } | |
68 | ||
69 | if (endp) | |
70 | *endp = (char *)cp; | |
71 | ||
72 | return result; | |
73 | } | |
74 | ||
7e5f460e SG |
75 | ulong hextoul(const char *cp, char **endp) |
76 | { | |
77 | return simple_strtoul(cp, endp, 16); | |
78 | } | |
79 | ||
0b1284eb SG |
80 | ulong dectoul(const char *cp, char **endp) |
81 | { | |
82 | return simple_strtoul(cp, endp, 10); | |
83 | } | |
84 | ||
e4c5383e SS |
85 | int strict_strtoul(const char *cp, unsigned int base, unsigned long *res) |
86 | { | |
87 | char *tail; | |
88 | unsigned long val; | |
89 | size_t len; | |
90 | ||
91 | *res = 0; | |
92 | len = strlen(cp); | |
93 | if (len == 0) | |
94 | return -EINVAL; | |
95 | ||
96 | val = simple_strtoul(cp, &tail, base); | |
97 | if (tail == cp) | |
98 | return -EINVAL; | |
99 | ||
100 | if ((*tail == '\0') || | |
101 | ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) { | |
102 | *res = val; | |
103 | return 0; | |
104 | } | |
105 | ||
106 | return -EINVAL; | |
107 | } | |
108 | ||
109 | long simple_strtol(const char *cp, char **endp, unsigned int base) | |
110 | { | |
111 | if (*cp == '-') | |
112 | return -simple_strtoul(cp + 1, endp, base); | |
113 | ||
114 | return simple_strtoul(cp, endp, base); | |
115 | } | |
116 | ||
117 | unsigned long ustrtoul(const char *cp, char **endp, unsigned int base) | |
118 | { | |
119 | unsigned long result = simple_strtoul(cp, endp, base); | |
a353e6aa MR |
120 | switch (tolower(**endp)) { |
121 | case 'g': | |
e4c5383e SS |
122 | result *= 1024; |
123 | /* fall through */ | |
a353e6aa | 124 | case 'm': |
e4c5383e SS |
125 | result *= 1024; |
126 | /* fall through */ | |
e4c5383e SS |
127 | case 'k': |
128 | result *= 1024; | |
b87b0d8d MR |
129 | (*endp)++; |
130 | if (**endp == 'i') | |
131 | (*endp)++; | |
132 | if (**endp == 'B') | |
133 | (*endp)++; | |
e4c5383e SS |
134 | } |
135 | return result; | |
136 | } | |
137 | ||
138 | unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base) | |
139 | { | |
140 | unsigned long long result = simple_strtoull(cp, endp, base); | |
a353e6aa MR |
141 | switch (tolower(**endp)) { |
142 | case 'g': | |
e4c5383e SS |
143 | result *= 1024; |
144 | /* fall through */ | |
a353e6aa | 145 | case 'm': |
e4c5383e SS |
146 | result *= 1024; |
147 | /* fall through */ | |
e4c5383e SS |
148 | case 'k': |
149 | result *= 1024; | |
b87b0d8d MR |
150 | (*endp)++; |
151 | if (**endp == 'i') | |
152 | (*endp)++; | |
153 | if (**endp == 'B') | |
154 | (*endp)++; | |
e4c5383e SS |
155 | } |
156 | return result; | |
157 | } | |
158 | ||
159 | unsigned long long simple_strtoull(const char *cp, char **endp, | |
160 | unsigned int base) | |
161 | { | |
5a94546e SG |
162 | unsigned long long result = 0; |
163 | uint value; | |
e4c5383e | 164 | |
2e794614 | 165 | cp = _parse_integer_fixup_radix(cp, &base); |
e4c5383e | 166 | |
5a94546e | 167 | while (value = decode_digit(*cp), value < base) { |
e4c5383e SS |
168 | result = result * base + value; |
169 | cp++; | |
170 | } | |
171 | ||
172 | if (endp) | |
173 | *endp = (char *) cp; | |
174 | ||
175 | return result; | |
176 | } | |
177 | ||
0b016428 RG |
178 | long long simple_strtoll(const char *cp, char **endp, unsigned int base) |
179 | { | |
180 | if (*cp == '-') | |
181 | return -simple_strtoull(cp + 1, endp, base); | |
182 | ||
183 | return simple_strtoull(cp, endp, base); | |
184 | } | |
185 | ||
8565efd5 | 186 | long trailing_strtoln_end(const char *str, const char *end, char const **endp) |
e4c5383e SS |
187 | { |
188 | const char *p; | |
189 | ||
190 | if (!end) | |
191 | end = str + strlen(str); | |
d667a0d8 SG |
192 | p = end - 1; |
193 | if (p > str && isdigit(*p)) { | |
194 | do { | |
8565efd5 SG |
195 | if (!isdigit(p[-1])) { |
196 | if (endp) | |
197 | *endp = p; | |
d667a0d8 | 198 | return dectoul(p, NULL); |
8565efd5 | 199 | } |
d667a0d8 | 200 | } while (--p > str); |
e4c5383e | 201 | } |
8565efd5 SG |
202 | if (endp) |
203 | *endp = end; | |
e4c5383e SS |
204 | |
205 | return -1; | |
206 | } | |
207 | ||
8565efd5 SG |
208 | long trailing_strtoln(const char *str, const char *end) |
209 | { | |
210 | return trailing_strtoln_end(str, end, NULL); | |
211 | } | |
212 | ||
e4c5383e SS |
213 | long trailing_strtol(const char *str) |
214 | { | |
215 | return trailing_strtoln(str, NULL); | |
216 | } | |
fdc79a6b SG |
217 | |
218 | void str_to_upper(const char *in, char *out, size_t len) | |
219 | { | |
220 | for (; len > 0 && *in; len--) | |
221 | *out++ = toupper(*in++); | |
222 | if (len) | |
223 | *out = '\0'; | |
224 | } |