blob: 53886722138aa884537f4ee76a70dbec7f25413c [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
Rob Clark2e794612017-09-11 16:53:08 -040016/* from lib/kstrtox.c */
17static const char *_parse_integer_fixup_radix(const char *s, unsigned int *base)
18{
19 if (*base == 0) {
20 if (s[0] == '0') {
Simon Glass96b23442021-07-24 09:03:32 -060021 if (tolower(s[1]) == 'x')
Rob Clark2e794612017-09-11 16:53:08 -040022 *base = 16;
23 else
24 *base = 8;
Sean Anderson1fae7412020-06-07 01:36:45 -040025 } else
Rob Clark2e794612017-09-11 16:53:08 -040026 *base = 10;
27 }
28 if (*base == 16 && s[0] == '0' && tolower(s[1]) == 'x')
29 s += 2;
30 return s;
31}
32
Simon Glass7e5f4602021-07-24 09:03:29 -060033ulong simple_strtoul(const char *cp, char **endp, uint base)
Sjoerd Simonse4c53832015-12-04 23:27:39 +010034{
Simon Glass7e5f4602021-07-24 09:03:29 -060035 ulong result = 0;
36 ulong value;
Sjoerd Simonse4c53832015-12-04 23:27:39 +010037
Rob Clark2e794612017-09-11 16:53:08 -040038 cp = _parse_integer_fixup_radix(cp, &base);
Sjoerd Simonse4c53832015-12-04 23:27:39 +010039
40 while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
41 ? toupper(*cp) : *cp)-'A'+10) < base) {
42 result = result*base + value;
43 cp++;
44 }
45
46 if (endp)
47 *endp = (char *)cp;
48
49 return result;
50}
51
Simon Glass7e5f4602021-07-24 09:03:29 -060052ulong hextoul(const char *cp, char **endp)
53{
54 return simple_strtoul(cp, endp, 16);
55}
56
Simon Glass0b1284e2021-07-24 09:03:30 -060057ulong dectoul(const char *cp, char **endp)
58{
59 return simple_strtoul(cp, endp, 10);
60}
61
Sjoerd Simonse4c53832015-12-04 23:27:39 +010062int strict_strtoul(const char *cp, unsigned int base, unsigned long *res)
63{
64 char *tail;
65 unsigned long val;
66 size_t len;
67
68 *res = 0;
69 len = strlen(cp);
70 if (len == 0)
71 return -EINVAL;
72
73 val = simple_strtoul(cp, &tail, base);
74 if (tail == cp)
75 return -EINVAL;
76
77 if ((*tail == '\0') ||
78 ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
79 *res = val;
80 return 0;
81 }
82
83 return -EINVAL;
84}
85
86long simple_strtol(const char *cp, char **endp, unsigned int base)
87{
88 if (*cp == '-')
89 return -simple_strtoul(cp + 1, endp, base);
90
91 return simple_strtoul(cp, endp, base);
92}
93
94unsigned long ustrtoul(const char *cp, char **endp, unsigned int base)
95{
96 unsigned long result = simple_strtoul(cp, endp, base);
Miquel Raynala353e6a2018-09-06 09:08:43 +020097 switch (tolower(**endp)) {
98 case 'g':
Sjoerd Simonse4c53832015-12-04 23:27:39 +010099 result *= 1024;
100 /* fall through */
Miquel Raynala353e6a2018-09-06 09:08:43 +0200101 case 'm':
Sjoerd Simonse4c53832015-12-04 23:27:39 +0100102 result *= 1024;
103 /* fall through */
Sjoerd Simonse4c53832015-12-04 23:27:39 +0100104 case 'k':
105 result *= 1024;
Miquel Raynalb87b0d82018-09-06 09:08:44 +0200106 (*endp)++;
107 if (**endp == 'i')
108 (*endp)++;
109 if (**endp == 'B')
110 (*endp)++;
Sjoerd Simonse4c53832015-12-04 23:27:39 +0100111 }
112 return result;
113}
114
115unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base)
116{
117 unsigned long long result = simple_strtoull(cp, endp, base);
Miquel Raynala353e6a2018-09-06 09:08:43 +0200118 switch (tolower(**endp)) {
119 case 'g':
Sjoerd Simonse4c53832015-12-04 23:27:39 +0100120 result *= 1024;
121 /* fall through */
Miquel Raynala353e6a2018-09-06 09:08:43 +0200122 case 'm':
Sjoerd Simonse4c53832015-12-04 23:27:39 +0100123 result *= 1024;
124 /* fall through */
Sjoerd Simonse4c53832015-12-04 23:27:39 +0100125 case 'k':
126 result *= 1024;
Miquel Raynalb87b0d82018-09-06 09:08:44 +0200127 (*endp)++;
128 if (**endp == 'i')
129 (*endp)++;
130 if (**endp == 'B')
131 (*endp)++;
Sjoerd Simonse4c53832015-12-04 23:27:39 +0100132 }
133 return result;
134}
135
136unsigned long long simple_strtoull(const char *cp, char **endp,
137 unsigned int base)
138{
139 unsigned long long result = 0, value;
140
Rob Clark2e794612017-09-11 16:53:08 -0400141 cp = _parse_integer_fixup_radix(cp, &base);
Sjoerd Simonse4c53832015-12-04 23:27:39 +0100142
143 while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp - '0'
144 : (islower(*cp) ? toupper(*cp) : *cp) - 'A' + 10) < base) {
145 result = result * base + value;
146 cp++;
147 }
148
149 if (endp)
150 *endp = (char *) cp;
151
152 return result;
153}
154
Roland Gaudig0b016422021-07-23 12:29:18 +0000155long long simple_strtoll(const char *cp, char **endp, unsigned int base)
156{
157 if (*cp == '-')
158 return -simple_strtoull(cp + 1, endp, base);
159
160 return simple_strtoull(cp, endp, base);
161}
162
Sjoerd Simonse4c53832015-12-04 23:27:39 +0100163long trailing_strtoln(const char *str, const char *end)
164{
165 const char *p;
166
167 if (!end)
168 end = str + strlen(str);
Simon Glassb91c6a12016-10-05 20:42:11 -0600169 if (isdigit(end[-1])) {
170 for (p = end - 1; p > str; p--) {
171 if (!isdigit(*p))
Simon Glass0b1284e2021-07-24 09:03:30 -0600172 return dectoul(p + 1, NULL);
Simon Glassb91c6a12016-10-05 20:42:11 -0600173 }
Sjoerd Simonse4c53832015-12-04 23:27:39 +0100174 }
175
176 return -1;
177}
178
179long trailing_strtol(const char *str)
180{
181 return trailing_strtoln(str, NULL);
182}
Simon Glassfdc79a62020-04-08 08:32:56 -0600183
184void str_to_upper(const char *in, char *out, size_t len)
185{
186 for (; len > 0 && *in; len--)
187 *out++ = toupper(*in++);
188 if (len)
189 *out = '\0';
190}