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:
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;
+}