blob: a6c01574dac3f6994cc3121f5d15082ad44e5155 [file] [log] [blame]
Sjoerd Simonse4c53832015-12-04 23:27:39 +01001/*
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
16unsigned long simple_strtoul(const char *cp, char **endp,
17 unsigned int base)
18{
19 unsigned long result = 0;
20 unsigned long value;
21
22 if (*cp == '0') {
23 cp++;
24 if ((*cp == 'x') && isxdigit(cp[1])) {
25 base = 16;
26 cp++;
27 }
28
29 if (!base)
30 base = 8;
31 }
32
33 if (!base)
34 base = 10;
35
36 while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
37 ? toupper(*cp) : *cp)-'A'+10) < base) {
38 result = result*base + value;
39 cp++;
40 }
41
42 if (endp)
43 *endp = (char *)cp;
44
45 return result;
46}
47
48int strict_strtoul(const char *cp, unsigned int base, unsigned long *res)
49{
50 char *tail;
51 unsigned long val;
52 size_t len;
53
54 *res = 0;
55 len = strlen(cp);
56 if (len == 0)
57 return -EINVAL;
58
59 val = simple_strtoul(cp, &tail, base);
60 if (tail == cp)
61 return -EINVAL;
62
63 if ((*tail == '\0') ||
64 ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
65 *res = val;
66 return 0;
67 }
68
69 return -EINVAL;
70}
71
72long simple_strtol(const char *cp, char **endp, unsigned int base)
73{
74 if (*cp == '-')
75 return -simple_strtoul(cp + 1, endp, base);
76
77 return simple_strtoul(cp, endp, base);
78}
79
80unsigned long ustrtoul(const char *cp, char **endp, unsigned int base)
81{
82 unsigned long result = simple_strtoul(cp, endp, base);
83 switch (**endp) {
84 case 'G':
85 result *= 1024;
86 /* fall through */
87 case 'M':
88 result *= 1024;
89 /* fall through */
90 case 'K':
91 case 'k':
92 result *= 1024;
93 if ((*endp)[1] == 'i') {
94 if ((*endp)[2] == 'B')
95 (*endp) += 3;
96 else
97 (*endp) += 2;
98 }
99 }
100 return result;
101}
102
103unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base)
104{
105 unsigned long long result = simple_strtoull(cp, endp, base);
106 switch (**endp) {
107 case 'G':
108 result *= 1024;
109 /* fall through */
110 case 'M':
111 result *= 1024;
112 /* fall through */
113 case 'K':
114 case 'k':
115 result *= 1024;
116 if ((*endp)[1] == 'i') {
117 if ((*endp)[2] == 'B')
118 (*endp) += 3;
119 else
120 (*endp) += 2;
121 }
122 }
123 return result;
124}
125
126unsigned long long simple_strtoull(const char *cp, char **endp,
127 unsigned int base)
128{
129 unsigned long long result = 0, value;
130
131 if (*cp == '0') {
132 cp++;
133 if ((*cp == 'x') && isxdigit(cp[1])) {
134 base = 16;
135 cp++;
136 }
137
138 if (!base)
139 base = 8;
140 }
141
142 if (!base)
143 base = 10;
144
145 while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp - '0'
146 : (islower(*cp) ? toupper(*cp) : *cp) - 'A' + 10) < base) {
147 result = result * base + value;
148 cp++;
149 }
150
151 if (endp)
152 *endp = (char *) cp;
153
154 return result;
155}
156
157long trailing_strtoln(const char *str, const char *end)
158{
159 const char *p;
160
161 if (!end)
162 end = str + strlen(str);
163 for (p = end - 1; p > str; p--) {
164 if (!isdigit(*p))
165 return simple_strtoul(p + 1, NULL, 10);
166 }
167
168 return -1;
169}
170
171long trailing_strtol(const char *str)
172{
173 return trailing_strtoln(str, NULL);
174}