scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

commit 1f90172f8e7790879ee606e450ec84d0d638062a
parent 1c715ade1420db7b2aea9beaca48eaf48ef6ea1f
Author: Quentin Rameau <quinq@fifth.space>
Date:   Fri, 28 Dec 2018 23:43:50 +0100

[libc] Add strtol[l]

Diffstat:
Msrc/libc/stdlib/Makefile | 2++
Asrc/libc/stdlib/strtol.c | 68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/libc/stdlib/strtoll.c | 68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 138 insertions(+), 0 deletions(-)

diff --git a/src/libc/stdlib/Makefile b/src/libc/stdlib/Makefile @@ -19,6 +19,8 @@ OBJS = abort.o\ qsort.o\ rand.o\ realloc.o\ + strtol.o\ + strtoll.o\ strtoul.o\ strtoull.o\ diff --git a/src/libc/stdlib/strtol.c b/src/libc/stdlib/strtol.c @@ -0,0 +1,68 @@ +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <stdlib.h> +#include <string.h> + +#undef strtol + +long +strtol(const char *s, char **end, int base) +{ + int d, sign = -1; + long n; + static const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + const char *t, *p; + + if (end) + *end = s; + + while (isspace(*s)) + ++s; + + switch (*s) { + case '-': + sign = 1; + case '+': + ++s; + } + + if (base == 0) { + if (*s == '0') + base = toupper(s[1]) == 'X' ? 16 : 8; + else + base = 10; + } + if (base == 16 && *s == '0' && toupper(s[1]) == 'X') + s += 2; + + n = 0; + /* Compute n as a negative number to avoid overflow on LONG_MIN */ + for (t = s; p = strchr(digits, toupper(*t)); ++t) { + if ((d = p - digits) >= base) + break; + if (n < LONG_MIN/base) + goto overflow; + n *= base; + if (-d < LONG_MIN - n) + goto overflow; + n -= d; + } + + if (n == LONG_MIN && sign < 0) { + --t; + goto overflow; + } + + if (end && t != s) + *end = t; + + return n*sign; + +overflow: + if (end) + *end = t; + errno = ERANGE; + + return sign < 0 ? LONG_MAX : LONG_MIN; +} diff --git a/src/libc/stdlib/strtoll.c b/src/libc/stdlib/strtoll.c @@ -0,0 +1,68 @@ +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <stdlib.h> +#include <string.h> + +#undef strtoll + +long long +strtoll(const char *s, char **end, int base) +{ + int d, sign = -1; + long long n; + static const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + const char *t, *p; + + if (end) + *end = s; + + while (isspace(*s)) + ++s; + + switch (*s) { + case '-': + sign = 1; + case '+': + ++s; + } + + if (base == 0) { + if (*s == '0') + base = toupper(s[1]) == 'X' ? 16 : 8; + else + base = 10; + } + if (base == 16 && *s == '0' && toupper(s[1]) == 'X') + s += 2; + + n = 0; + /* Compute n as a negative number to avoid overflow on LLONG_MIN */ + for (t = s; p = strchr(digits, toupper(*t)); ++t) { + if ((d = p - digits) >= base) + break; + if (n < LLONG_MIN/base) + goto overflow; + n *= base; + if (-d < LLONG_MIN - n) + goto overflow; + n -= d; + } + + if (n == LLONG_MIN && sign < 0) { + --t; + goto overflow; + } + + if (end && t != s) + *end = t; + + return n*sign; + +overflow: + if (end) + *end = t; + errno = ERANGE; + + return sign < 0 ? LLONG_MAX : LLONG_MIN; +}