init/Kconfig: fix EXPERT menu list
[linux-2.6/next.git] / lib / kstrtox.c
bloba235f3cc471c6d427fd4c2e713a701fa0b1e7e1b
1 /*
2 * Convert integer string representation to an integer.
3 * If an integer doesn't fit into specified type, -E is returned.
5 * Integer starts with optional sign.
6 * kstrtou*() functions do not accept sign "-".
8 * Radix 0 means autodetection: leading "0x" implies radix 16,
9 * leading "0" implies radix 8, otherwise radix is 10.
10 * Autodetection hints work after optional sign, but not before.
12 * If -E is returned, result is not touched.
14 #include <linux/ctype.h>
15 #include <linux/errno.h>
16 #include <linux/kernel.h>
17 #include <linux/math64.h>
18 #include <linux/module.h>
19 #include <linux/types.h>
21 static inline char _tolower(const char c)
23 return c | 0x20;
26 static int _kstrtoull(const char *s, unsigned int base, unsigned long long *res)
28 unsigned long long acc;
29 int ok;
31 if (base == 0) {
32 if (s[0] == '0') {
33 if (_tolower(s[1]) == 'x' && isxdigit(s[2]))
34 base = 16;
35 else
36 base = 8;
37 } else
38 base = 10;
40 if (base == 16 && s[0] == '0' && _tolower(s[1]) == 'x')
41 s += 2;
43 acc = 0;
44 ok = 0;
45 while (*s) {
46 unsigned int val;
48 if ('0' <= *s && *s <= '9')
49 val = *s - '0';
50 else if ('a' <= _tolower(*s) && _tolower(*s) <= 'f')
51 val = _tolower(*s) - 'a' + 10;
52 else if (*s == '\n' && *(s + 1) == '\0')
53 break;
54 else
55 return -EINVAL;
57 if (val >= base)
58 return -EINVAL;
59 if (acc > div_u64(ULLONG_MAX - val, base))
60 return -ERANGE;
61 acc = acc * base + val;
62 ok = 1;
64 s++;
66 if (!ok)
67 return -EINVAL;
68 *res = acc;
69 return 0;
72 int kstrtoull(const char *s, unsigned int base, unsigned long long *res)
74 if (s[0] == '+')
75 s++;
76 return _kstrtoull(s, base, res);
78 EXPORT_SYMBOL(kstrtoull);
80 int kstrtoll(const char *s, unsigned int base, long long *res)
82 unsigned long long tmp;
83 int rv;
85 if (s[0] == '-') {
86 rv = _kstrtoull(s + 1, base, &tmp);
87 if (rv < 0)
88 return rv;
89 if ((long long)(-tmp) >= 0)
90 return -ERANGE;
91 *res = -tmp;
92 } else {
93 rv = kstrtoull(s, base, &tmp);
94 if (rv < 0)
95 return rv;
96 if ((long long)tmp < 0)
97 return -ERANGE;
98 *res = tmp;
100 return 0;
102 EXPORT_SYMBOL(kstrtoll);
104 /* Internal, do not use. */
105 int _kstrtoul(const char *s, unsigned int base, unsigned long *res)
107 unsigned long long tmp;
108 int rv;
110 rv = kstrtoull(s, base, &tmp);
111 if (rv < 0)
112 return rv;
113 if (tmp != (unsigned long long)(unsigned long)tmp)
114 return -ERANGE;
115 *res = tmp;
116 return 0;
118 EXPORT_SYMBOL(_kstrtoul);
120 /* Internal, do not use. */
121 int _kstrtol(const char *s, unsigned int base, long *res)
123 long long tmp;
124 int rv;
126 rv = kstrtoll(s, base, &tmp);
127 if (rv < 0)
128 return rv;
129 if (tmp != (long long)(long)tmp)
130 return -ERANGE;
131 *res = tmp;
132 return 0;
134 EXPORT_SYMBOL(_kstrtol);
136 int kstrtouint(const char *s, unsigned int base, unsigned int *res)
138 unsigned long long tmp;
139 int rv;
141 rv = kstrtoull(s, base, &tmp);
142 if (rv < 0)
143 return rv;
144 if (tmp != (unsigned long long)(unsigned int)tmp)
145 return -ERANGE;
146 *res = tmp;
147 return 0;
149 EXPORT_SYMBOL(kstrtouint);
151 int kstrtoint(const char *s, unsigned int base, int *res)
153 long long tmp;
154 int rv;
156 rv = kstrtoll(s, base, &tmp);
157 if (rv < 0)
158 return rv;
159 if (tmp != (long long)(int)tmp)
160 return -ERANGE;
161 *res = tmp;
162 return 0;
164 EXPORT_SYMBOL(kstrtoint);
166 int kstrtou16(const char *s, unsigned int base, u16 *res)
168 unsigned long long tmp;
169 int rv;
171 rv = kstrtoull(s, base, &tmp);
172 if (rv < 0)
173 return rv;
174 if (tmp != (unsigned long long)(u16)tmp)
175 return -ERANGE;
176 *res = tmp;
177 return 0;
179 EXPORT_SYMBOL(kstrtou16);
181 int kstrtos16(const char *s, unsigned int base, s16 *res)
183 long long tmp;
184 int rv;
186 rv = kstrtoll(s, base, &tmp);
187 if (rv < 0)
188 return rv;
189 if (tmp != (long long)(s16)tmp)
190 return -ERANGE;
191 *res = tmp;
192 return 0;
194 EXPORT_SYMBOL(kstrtos16);
196 int kstrtou8(const char *s, unsigned int base, u8 *res)
198 unsigned long long tmp;
199 int rv;
201 rv = kstrtoull(s, base, &tmp);
202 if (rv < 0)
203 return rv;
204 if (tmp != (unsigned long long)(u8)tmp)
205 return -ERANGE;
206 *res = tmp;
207 return 0;
209 EXPORT_SYMBOL(kstrtou8);
211 int kstrtos8(const char *s, unsigned int base, s8 *res)
213 long long tmp;
214 int rv;
216 rv = kstrtoll(s, base, &tmp);
217 if (rv < 0)
218 return rv;
219 if (tmp != (long long)(s8)tmp)
220 return -ERANGE;
221 *res = tmp;
222 return 0;
224 EXPORT_SYMBOL(kstrtos8);