This source file includes following definitions.
- bkm_scale
- bkm_scale_by_power
- __xstrtol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #ifndef __strtol
22 # define __strtol strtol
23 # define __strtol_t long int
24 # define __xstrtol xstrtol
25 # define STRTOL_T_MINIMUM LONG_MIN
26 # define STRTOL_T_MAXIMUM LONG_MAX
27 #endif
28
29 #include <config.h>
30
31 #include "xstrtol.h"
32
33
34
35 #include <stdio.h>
36
37 #include <ctype.h>
38 #include <errno.h>
39 #include <limits.h>
40 #include <stdlib.h>
41 #include <string.h>
42
43 #include "assure.h"
44
45 #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
46
47 static strtol_error
48 bkm_scale (__strtol_t *x, int scale_factor)
49 {
50 if (TYPE_SIGNED (__strtol_t) && *x < STRTOL_T_MINIMUM / scale_factor)
51 {
52 *x = STRTOL_T_MINIMUM;
53 return LONGINT_OVERFLOW;
54 }
55 if (STRTOL_T_MAXIMUM / scale_factor < *x)
56 {
57 *x = STRTOL_T_MAXIMUM;
58 return LONGINT_OVERFLOW;
59 }
60 *x *= scale_factor;
61 return LONGINT_OK;
62 }
63
64 static strtol_error
65 bkm_scale_by_power (__strtol_t *x, int base, int power)
66 {
67 strtol_error err = LONGINT_OK;
68 while (power--)
69 err |= bkm_scale (x, base);
70 return err;
71 }
72
73
74
75 strtol_error
76 __xstrtol (const char *s, char **ptr, int strtol_base,
77 __strtol_t *val, const char *valid_suffixes)
78 {
79 char *t_ptr;
80 char **p;
81 __strtol_t tmp;
82 strtol_error err = LONGINT_OK;
83
84 assure (0 <= strtol_base && strtol_base <= 36);
85
86 p = (ptr ? ptr : &t_ptr);
87
88 errno = 0;
89
90 if (! TYPE_SIGNED (__strtol_t))
91 {
92 const char *q = s;
93 unsigned char ch = *q;
94 while (isspace (ch))
95 ch = *++q;
96 if (ch == '-')
97 return LONGINT_INVALID;
98 }
99
100 tmp = __strtol (s, p, strtol_base);
101
102 if (*p == s)
103 {
104
105
106 if (valid_suffixes && **p && strchr (valid_suffixes, **p))
107 tmp = 1;
108 else
109 return LONGINT_INVALID;
110 }
111 else if (errno != 0)
112 {
113 if (errno != ERANGE)
114 return LONGINT_INVALID;
115 err = LONGINT_OVERFLOW;
116 }
117
118
119
120
121 if (!valid_suffixes)
122 {
123 *val = tmp;
124 return err;
125 }
126
127 if (**p != '\0')
128 {
129 int base = 1024;
130 int suffixes = 1;
131 strtol_error overflow;
132
133 if (!strchr (valid_suffixes, **p))
134 {
135 *val = tmp;
136 return err | LONGINT_INVALID_SUFFIX_CHAR;
137 }
138
139 switch (**p)
140 {
141 case 'E': case 'G': case 'g': case 'k': case 'K': case 'M': case 'm':
142 case 'P': case 'T': case 't': case 'Y': case 'Z':
143
144
145
146
147
148
149
150
151 if (strchr (valid_suffixes, '0'))
152 switch (p[0][1])
153 {
154 case 'i':
155 if (p[0][2] == 'B')
156 suffixes += 2;
157 break;
158
159 case 'B':
160 case 'D':
161 base = 1000;
162 suffixes++;
163 break;
164 }
165 }
166
167 switch (**p)
168 {
169 case 'b':
170 overflow = bkm_scale (&tmp, 512);
171 break;
172
173 case 'B':
174
175
176
177 overflow = bkm_scale (&tmp, 1024);
178 break;
179
180 case 'c':
181 overflow = LONGINT_OK;
182 break;
183
184 case 'E':
185 overflow = bkm_scale_by_power (&tmp, base, 6);
186 break;
187
188 case 'G':
189 case 'g':
190 overflow = bkm_scale_by_power (&tmp, base, 3);
191 break;
192
193 case 'k':
194 case 'K':
195 overflow = bkm_scale_by_power (&tmp, base, 1);
196 break;
197
198 case 'M':
199 case 'm':
200 overflow = bkm_scale_by_power (&tmp, base, 2);
201 break;
202
203 case 'P':
204 overflow = bkm_scale_by_power (&tmp, base, 5);
205 break;
206
207 case 'T':
208 case 't':
209 overflow = bkm_scale_by_power (&tmp, base, 4);
210 break;
211
212 case 'w':
213 overflow = bkm_scale (&tmp, 2);
214 break;
215
216 case 'Y':
217 overflow = bkm_scale_by_power (&tmp, base, 8);
218 break;
219
220 case 'Z':
221 overflow = bkm_scale_by_power (&tmp, base, 7);
222 break;
223
224 default:
225 *val = tmp;
226 return err | LONGINT_INVALID_SUFFIX_CHAR;
227 }
228
229 err |= overflow;
230 *p += suffixes;
231 if (**p)
232 err |= LONGINT_INVALID_SUFFIX_CHAR;
233 }
234
235 *val = tmp;
236 return err;
237 }