Skip to content

Commit 61ddf63

Browse files
committed
added __strtoi and __strtoui
1 parent 7a02b04 commit 61ddf63

File tree

2 files changed

+155
-6
lines changed

2 files changed

+155
-6
lines changed

src/libc/strtol.src

Lines changed: 63 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,40 @@
11
assume adl=1
22

3+
;-------------------------------------------------------------------------------
4+
5+
section .text
6+
7+
public ___strtoi
8+
9+
___strtoi:
10+
; Similar to strtol, except that it will raise ERANGE and return INT_MIN/INT_MAX when out of range
11+
call __strtol_common
12+
; overflow occured if B is non-zero
13+
djnz .out_of_range
14+
inc e
15+
dec e
16+
jr nz, .out_of_range
17+
ld b, a
18+
inc b
19+
ex de, hl
20+
sbc hl, hl
21+
djnz .positive
22+
sbc hl, de
23+
ret m ; INT_MIN <= x < 0
24+
; no underflow if x is zero
25+
jr nz, .out_of_range
26+
.positive:
27+
adc hl, de
28+
ret p ; 0 <= x <= INT_MAX
29+
.out_of_range:
30+
or a, a ; test sign (Z = negative)
31+
ld hl, 5 ; ERANGE
32+
ld (_errno), hl
33+
ld hl, $7FFFFF ; overflow
34+
ret nz
35+
inc hl ; underflow
36+
ret
37+
338
;-------------------------------------------------------------------------------
439

540
section .text
@@ -45,23 +80,44 @@ _strtol:
4580

4681
section .text
4782

48-
public _strtoul
83+
public ___strtoui
4984

50-
_strtoul:
85+
___strtoui:
86+
; Similar to strtoul, except that it will raise ERANGE and return UINT_MAX when out of range
5187
call __strtol_common
5288
; overflow occured if B is non-zero
53-
djnz .out_of_range
54-
ret nz
55-
jp __lneg
89+
djnz _strtoul.out_of_range
90+
call z, __ineg
91+
inc e
92+
dec e
93+
ret z
5694

57-
.out_of_range:
95+
require _strtoul.out_of_range
96+
97+
;-------------------------------------------------------------------------------
98+
99+
section .text
100+
101+
private _strtoul.out_of_range
102+
_strtoul.out_of_range:
58103
ld hl, 5 ; ERANGE
59104
ld (_errno), hl
60105
ld l, h ; ld hl, 0
61106
dec hl
62107
ld e, l
63108
ret
64109

110+
section .text
111+
112+
public _strtoul
113+
114+
_strtoul:
115+
call __strtol_common
116+
; overflow occured if B is non-zero
117+
djnz _strtoul.out_of_range
118+
ret nz
119+
jp __lneg
120+
65121
;-------------------------------------------------------------------------------
66122

67123
section .text
@@ -274,5 +330,6 @@ __strtol_common:
274330
ret
275331

276332
extern _errno
333+
extern __ineg
277334
extern __lneg
278335
extern __lmulu_b

test/standalone/strtol/src/main.c

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,14 @@
4444

4545
#define NO_ERR 0
4646

47+
//------------------------------------------------------------------------------
48+
// Internal functions
49+
//------------------------------------------------------------------------------
50+
51+
int __strtoi(const char *__restrict nptr, char **__restrict endptr, int base) __attribute__((nonnull(1)));
52+
53+
unsigned int __strtoui(const char *__restrict nptr, char **__restrict endptr, int base) __attribute__((nonnull(1)));
54+
4755
//------------------------------------------------------------------------------
4856
// Char to digit
4957
//------------------------------------------------------------------------------
@@ -99,6 +107,14 @@ long long atoint_atoll(const char* nptr) {
99107
return (long long)atoll(nptr);
100108
}
101109

110+
long long atoint_strtoi(const char* nptr) {
111+
return (long long)__strtoi(nptr, NULL, 10);
112+
}
113+
114+
long long atoint_strtoui(const char* nptr) {
115+
return (long long)((int)__strtoui(nptr, NULL, 10));
116+
}
117+
102118
long long atoint_strtol(const char* nptr) {
103119
return (long long)strtol(nptr, NULL, 10);
104120
}
@@ -160,6 +176,14 @@ int atoint_test(atoint_func const func) {
160176

161177
typedef long long (*strtoint_func)(const char* nptr, char** endptr, int base);
162178

179+
long long strtoint_strtoi(const char* nptr, char** endptr, int base) {
180+
return (long long)__strtoi(nptr, endptr, base);
181+
}
182+
183+
long long strtoint_strtoui(const char* nptr, char** endptr, int base) {
184+
return (long long)((int)__strtoui(nptr, endptr, base));
185+
}
186+
163187
long long strtoint_strtol(const char* nptr, char** endptr, int base) {
164188
return (long long)strtol(nptr, endptr, base);
165189
}
@@ -315,6 +339,68 @@ int test_atoll(void) {
315339
return 0;
316340
}
317341

342+
int test_strtoi(void) {
343+
strtoint_func func = strtoint_strtoi;
344+
345+
C(strtoint_verify( INT_MIN, "-8388608", 8, func, 10, NO_ERR));
346+
C(strtoint_verify( INT_MAX, "8388608" , 7, func, 10, ERANGE));
347+
C(strtoint_verify( INT_MAX, "8388607" , 7, func, 10, NO_ERR));
348+
C(strtoint_verify( INT_MAX, "+8388607", 8, func, 10, NO_ERR));
349+
C(strtoint_verify(-INT_MAX, "-8388607", 8, func, 10, NO_ERR));
350+
351+
C(strtoint_verify( INT_MIN, "-16777216", 9, func, 10, ERANGE));
352+
C(strtoint_verify( INT_MAX, "16777216" , 8, func, 10, ERANGE));
353+
C(strtoint_verify( INT_MAX, "16777215" , 8, func, 10, ERANGE));
354+
C(strtoint_verify( INT_MAX, "+16777215", 9, func, 10, ERANGE));
355+
C(strtoint_verify( INT_MIN, "-16777215", 9, func, 10, ERANGE));
356+
357+
C(strtoint_verify( INT_MIN, "-100000000000000000000000", 25, func, 2, NO_ERR));
358+
C(strtoint_verify( INT_MAX, " 100000000000000000000000", 25, func, 2, ERANGE));
359+
C(strtoint_verify( INT_MAX, "0b11111111111111111111111", 25, func, 0, NO_ERR));
360+
C(strtoint_verify(-INT_MAX, " -11111111111111111111111", 25, func, 2, NO_ERR));
361+
362+
C(strtoint_verify( INT_MIN, "-1000000000000000000000000", 26, func, 2, ERANGE));
363+
C(strtoint_verify( INT_MAX, " 1000000000000000000000000", 26, func, 2, ERANGE));
364+
C(strtoint_verify( INT_MAX, "0b111111111111111111111111", 26, func, 0, ERANGE));
365+
C(strtoint_verify( INT_MIN, " -111111111111111111111111", 26, func, 2, ERANGE));
366+
367+
C(strtoint_verify( INT_MIN, "-1qaz2WSX3edc4RFV5tgb", 21, func, 36, ERANGE));
368+
C(strtoint_verify( INT_MAX, "+1qaz2WSX3edc4RFV5tgb", 21, func, 36, ERANGE));
369+
370+
return 0;
371+
}
372+
373+
int test_strtoui(void) {
374+
strtoint_func func = strtoint_strtoui;
375+
376+
C(strtoint_verify( INT_MIN, "-8388608", 8, func, 10, NO_ERR));
377+
C(strtoint_verify( INT_MIN, "8388608" , 7, func, 10, NO_ERR));
378+
C(strtoint_verify( INT_MAX, "8388607" , 7, func, 10, NO_ERR));
379+
C(strtoint_verify( INT_MAX, "+8388607", 8, func, 10, NO_ERR));
380+
C(strtoint_verify(-INT_MAX, "-8388607", 8, func, 10, NO_ERR));
381+
382+
C(strtoint_verify( -1, "-16777216", 9, func, 10, ERANGE));
383+
C(strtoint_verify( -1, "16777216" , 8, func, 10, ERANGE));
384+
C(strtoint_verify( -1, "16777215" , 8, func, 10, NO_ERR));
385+
C(strtoint_verify( -1, "+16777215", 9, func, 10, NO_ERR));
386+
C(strtoint_verify( 1, "-16777215", 9, func, 10, NO_ERR));
387+
388+
C(strtoint_verify( INT_MIN, "-100000000000000000000000", 25, func, 2, NO_ERR));
389+
C(strtoint_verify( INT_MIN, " 100000000000000000000000", 25, func, 2, NO_ERR));
390+
C(strtoint_verify( INT_MAX, "0b11111111111111111111111", 25, func, 0, NO_ERR));
391+
C(strtoint_verify(-INT_MAX, " -11111111111111111111111", 25, func, 2, NO_ERR));
392+
393+
C(strtoint_verify( -1, "-1000000000000000000000000", 26, func, 2, ERANGE));
394+
C(strtoint_verify( -1, " 1000000000000000000000000", 26, func, 2, ERANGE));
395+
C(strtoint_verify( -1, "0b111111111111111111111111", 26, func, 0, NO_ERR));
396+
C(strtoint_verify( 1, " -111111111111111111111111", 26, func, 2, NO_ERR));
397+
398+
C(strtoint_verify( -1, "-1qaz2WSX3edc4RFV5tgb", 21, func, 36, ERANGE));
399+
C(strtoint_verify( -1, "+1qaz2WSX3edc4RFV5tgb", 21, func, 36, ERANGE));
400+
401+
return 0;
402+
}
403+
318404
int test_strtol(void) {
319405
strtoint_func func = strtoint_strtol;
320406

@@ -450,12 +536,16 @@ int run_tests(void) {
450536
TEST_NAME(atoint_test(atoint_atoi ), "atoi" );
451537
TEST_NAME(atoint_test(atoint_atol ), "atol" );
452538
TEST_NAME(atoint_test(atoint_atoll ), "atoll" );
539+
TEST_NAME(atoint_test(atoint_strtoi ), "strtoi" );
540+
TEST_NAME(atoint_test(atoint_strtoui ), "strtoui" );
453541
TEST_NAME(atoint_test(atoint_strtol ), "strtol" );
454542
TEST_NAME(atoint_test(atoint_strtoul ), "strtoul" );
455543
TEST_NAME(atoint_test(atoint_strtoll ), "strtoll" );
456544
TEST_NAME(atoint_test(atoint_strtoull), "strtoull");
457545

458546
/* basic tests of strto* routines */
547+
TEST_NAME(strtoint_test(strtoint_strtol ), "strtoi" );
548+
TEST_NAME(strtoint_test(strtoint_strtoul ), "strtoui" );
459549
TEST_NAME(strtoint_test(strtoint_strtol ), "strtol" );
460550
TEST_NAME(strtoint_test(strtoint_strtoul ), "strtoul" );
461551
TEST_NAME(strtoint_test(strtoint_strtoll ), "strtoll" );
@@ -466,6 +556,8 @@ int run_tests(void) {
466556
TEST(test_atol());
467557
TEST(test_atoll());
468558
TEST(test_strtol());
559+
TEST(test_strtoi());
560+
TEST(test_strtoui());
469561
TEST(test_strtoul());
470562
TEST(test_strtoll());
471563
TEST(test_strtoull());

0 commit comments

Comments
 (0)