scc

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

commit 492c04a4cd57971750b36eb742aaccc2eed1e796
parent 9e266893d0b4715684a076dd07a8bbe974a15a34
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Tue, 23 May 2023 11:34:51 +0200

libc: Add inttypes functions

Diffstat:
Minclude/inttypes.h | 14++++++++++++++
Msrc/libc/Makefile | 1+
Asrc/libc/inttypes/Makefile | 14++++++++++++++
Asrc/libc/inttypes/deps.mk | 0
Asrc/libc/inttypes/imaxabs.c | 9+++++++++
Asrc/libc/inttypes/imaxdiv.c | 9+++++++++
Asrc/libc/inttypes/strtoimax.c | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/libc/inttypes/strtoumax.c | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8 files changed, 172 insertions(+), 0 deletions(-)

diff --git a/include/inttypes.h b/include/inttypes.h @@ -4,4 +4,18 @@ #include <stdint.h> #include <arch/inttypes.h> +typedef struct { + intmax_t quot, rem; +} imaxdiv_t; + +extern intmax_t imaxabs(intmax_t); +extern imaxdiv_t imaxdiv(intmax_t, intmax_t); +extern intmax_t strtoimax(const char * restrict, char ** restrict, int); +extern uintmax_t strtoumax(const char * restrict, char ** restrict, int); + +#ifdef _NEED_WCHART +extern intmax_t wcstoimax(const wchar_t * restrict, wchar_t ** restrict, int); +extern uintmax_t wcstoumax(const wchar_t * restrict, wchar_t ** restrict, int); +#endif + #endif diff --git a/src/libc/Makefile b/src/libc/Makefile @@ -4,6 +4,7 @@ PROJECTDIR = ../.. DIRS =\ assert\ ctype\ + inttypes\ locale\ stdio\ stdlib\ diff --git a/src/libc/inttypes/Makefile b/src/libc/inttypes/Makefile @@ -0,0 +1,14 @@ +.POSIX: +PROJECTDIR =../../.. +include $(PROJECTDIR)/scripts/rules.mk +include ../rules.mk + +OBJS =\ + imaxabs.o\ + imaxdiv.o\ + strtoimax.o\ + strtoumax.o\ + +all: $(OBJS) + +include deps.mk diff --git a/src/libc/inttypes/deps.mk b/src/libc/inttypes/deps.mk diff --git a/src/libc/inttypes/imaxabs.c b/src/libc/inttypes/imaxabs.c @@ -0,0 +1,9 @@ +#include <inttypes.h> + +#undef imaxabs + +intmax_t +imaxabs(intmax_t n) +{ + return (n < 0) ? -n : n; +} diff --git a/src/libc/inttypes/imaxdiv.c b/src/libc/inttypes/imaxdiv.c @@ -0,0 +1,9 @@ +#include <inttypes.h> + +#undef imaxdiv + +imaxdiv_t +imaxdiv(intmax_t num, intmax_t den) +{ + return (imaxdiv_t) {num/den, num%den}; +} diff --git a/src/libc/inttypes/strtoimax.c b/src/libc/inttypes/strtoimax.c @@ -0,0 +1,64 @@ +#include <ctype.h> +#include <errno.h> +#include <inttypes.h> +#include <limits.h> +#include <stdlib.h> + +#include "../libc.h" + +#undef strtoimax + +intmax_t +strtol(const char * restrict ptr, char ** restrict end, int base) +{ + int d, sign = -1; + intmax_t n; + char *t, *s = (char *) ptr; + + 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; (d = _dtoi(*t)) < base; ++t) { + if (n < INTMAX_MIN/base) + goto overflow; + n *= base; + if (-d < INTMAX_MIN - n) + goto overflow; + n -= d; + if (n == INTMAX_MIN && sign < 0) + goto overflow; + } + + if (end && t != s) + *end = t; + + return n*sign; + +overflow: + if (end) + *end = t; + errno = ERANGE; + + return sign < 0 ? INTMAX_MAX : INTMAX_MIN; +} diff --git a/src/libc/inttypes/strtoumax.c b/src/libc/inttypes/strtoumax.c @@ -0,0 +1,61 @@ +#include <ctype.h> +#include <errno.h> +#include <inttypes.h> +#include <limits.h> +#include <string.h> + +#include "../libc.h" + +#undef strtoumax + +uintmax_t +strtoumax(const char * restrict ptr, char ** restrict end, int base) +{ + int d, sign = 1; + uintmax_t n; + char *t, *s = (char *) ptr; + + 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; + for (t = s; (d = _dtoi(*t)) < base; ++t) { + if (n > UINTMAX_MAX/base) + goto overflow; + n *= base; + if (d > UINTMAX_MAX - n) + goto overflow; + n += d; + } + + if (end && t != s) + *end = t; + + return n*sign; + +overflow: + if (end) + *end = t; + errno = ERANGE; + + return UINTMAX_MAX; +}