mirror of
https://git.planet-casio.com/Vhex-Kernel-Core/fxlibc.git
synced 2024-12-28 04:23:38 +01:00
stdlib: add a test strtol, strtoul, strtoll (DONE)
The presumed bug where the value computed without the sign overflows even though the negative result can be represented is not actually a problem, because this only happens with signed results and the temporary value is computed as unsigned (thus with extra range).
This commit is contained in:
parent
5042236392
commit
06f975f75c
7 changed files with 51 additions and 10 deletions
|
@ -107,6 +107,9 @@ set(SOURCES
|
|||
src/libc/stdlib/lldiv.c
|
||||
src/libc/stdlib/reallocarray.c
|
||||
src/libc/stdlib/strto_int.c
|
||||
src/libc/stdlib/strtol.c
|
||||
src/libc/stdlib/strtoll.c
|
||||
src/libc/stdlib/strtoul.c
|
||||
src/libc/stdlib/strtoull.c
|
||||
# string
|
||||
src/libc/string/strchr.c
|
||||
|
|
3
STATUS
3
STATUS
|
@ -100,8 +100,7 @@ DONE: Function/symbol/macro is defined, builds, links, and is tested
|
|||
7.20.1.1 atof: TODO
|
||||
7.20.1.2 atoi, atol, atoll: TODO
|
||||
7.20.1.3 strtod, strtof, strtold: TODO
|
||||
7.20.1.4 strtol, strtoul, strtoll: TODO
|
||||
strtoull: DONE
|
||||
7.20.1.4 strtol, strtoul, strtoll, strtoull: DONE
|
||||
7.20.2 Pseudo-random sequence generation functions: TODO
|
||||
7.20.3 Memory management functions: TODO (check existing code first)
|
||||
7.20.4 Communication with the environment: TODO
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __STDLIB_P_H__
|
||||
# define __STDLIB_P_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/* Parse an integer from a string. This is the base function for strtol,
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
|
||||
/* Parse an integer from a string. Base function for strtol, strtoul, strtoll,
|
||||
and strtoull. This function:
|
||||
|
@ -55,12 +56,6 @@ int strto_int(char const * restrict ptr, char ** restrict endptr, int base,
|
|||
valid = true;
|
||||
|
||||
/* (x = base*x + v) but with overflow checks */
|
||||
|
||||
/*
|
||||
** TODO FIXME: There is a bug with overflows if the unsigned
|
||||
** value cannot be represented but the signed value can (which
|
||||
** is the case only for LONG_MIN and LLONG_MIN)
|
||||
*/
|
||||
if(outl) {
|
||||
if(__builtin_umull_overflow(xl, base, &xl))
|
||||
errno_value = ERANGE;
|
||||
|
@ -77,7 +72,7 @@ int strto_int(char const * restrict ptr, char ** restrict endptr, int base,
|
|||
ptr++;
|
||||
}
|
||||
|
||||
/* Handle the sign */
|
||||
/* Handle sign and range */
|
||||
if(negative) {
|
||||
/* Only -0 can be represented as unsigned */
|
||||
if(outl && use_unsigned && xl != 0)
|
||||
|
@ -85,9 +80,21 @@ int strto_int(char const * restrict ptr, char ** restrict endptr, int base,
|
|||
if(outll && use_unsigned && xll != 0)
|
||||
errno_value = ERANGE;
|
||||
|
||||
/* Handle signed range. Don't use -[L]LONG_MIN, it overflows */
|
||||
if(outl && !use_unsigned && xl > LONG_MAX * 1ul + 1)
|
||||
errno_value = ERANGE;
|
||||
if(outll && !use_unsigned && xll > LLONG_MAX * 1ull + 1)
|
||||
errno_value = ERANGE;
|
||||
|
||||
xl = -xl;
|
||||
xll = -xll;
|
||||
}
|
||||
else {
|
||||
if(outl && !use_unsigned && xl > LONG_MAX * 1ul)
|
||||
errno_value = ERANGE;
|
||||
if(outll && !use_unsigned && xll > LLONG_MAX * 1ull)
|
||||
errno_value = ERANGE;
|
||||
}
|
||||
|
||||
if(outl) *outl = xl;
|
||||
if(outll) *outll = xll;
|
||||
|
|
10
src/libc/stdlib/strtol.c
Normal file
10
src/libc/stdlib/strtol.c
Normal file
|
@ -0,0 +1,10 @@
|
|||
#include "stdlib_p.h"
|
||||
#include <errno.h>
|
||||
|
||||
long int strtol(char const * restrict ptr, char ** restrict endptr, int base)
|
||||
{
|
||||
long n = 0;
|
||||
int err = strto_int(ptr, endptr, base, &n, NULL, false);
|
||||
if(err != 0) errno = err;
|
||||
return n;
|
||||
}
|
11
src/libc/stdlib/strtoll.c
Normal file
11
src/libc/stdlib/strtoll.c
Normal file
|
@ -0,0 +1,11 @@
|
|||
#include "stdlib_p.h"
|
||||
#include <errno.h>
|
||||
|
||||
long long int strtoll(char const * restrict ptr, char ** restrict endptr,
|
||||
int base)
|
||||
{
|
||||
long long n = 0;
|
||||
int err = strto_int(ptr, endptr, base, NULL, &n, false);
|
||||
if(err != 0) errno = err;
|
||||
return n;
|
||||
}
|
11
src/libc/stdlib/strtoul.c
Normal file
11
src/libc/stdlib/strtoul.c
Normal file
|
@ -0,0 +1,11 @@
|
|||
#include "stdlib_p.h"
|
||||
#include <errno.h>
|
||||
|
||||
unsigned long int strtoul(char const * restrict ptr, char ** restrict endptr,
|
||||
int base)
|
||||
{
|
||||
unsigned long n = 0;
|
||||
int err = strto_int(ptr, endptr, base, (long *)&n, NULL, true);
|
||||
if(err != 0) errno = err;
|
||||
return n;
|
||||
}
|
Loading…
Reference in a new issue