diff options
author | Jakob Kaivo <jkk@ung.org> | 2024-06-05 14:35:40 -0400 |
---|---|---|
committer | Jakob Kaivo <jkk@ung.org> | 2024-06-05 14:35:40 -0400 |
commit | d105976002aa32a3cbe42b7f06a0dcba5d176afd (patch) | |
tree | ccd57fa63807cb15cc08eb43231b15b60c660d5f | |
parent | 9252dc08f0a9ac7507b28e55b8ae7e4df605c79d (diff) |
implement tracking mechanisms for mbstate_t
-rw-r--r-- | mk/mbrlen.d | 1 | ||||
-rw-r--r-- | mk/mbrtowc.d | 1 | ||||
-rw-r--r-- | mk/mbsinit.d | 1 | ||||
-rw-r--r-- | mk/mbsrtowcs.d | 1 | ||||
-rw-r--r-- | mk/wcrtomb.d | 2 | ||||
-rw-r--r-- | mk/wcsrtombs.d | 1 | ||||
-rw-r--r-- | src/wchar/_wchar.h | 53 | ||||
-rw-r--r-- | src/wchar/mbrlen.c | 10 | ||||
-rw-r--r-- | src/wchar/mbrtowc.c | 24 | ||||
-rw-r--r-- | src/wchar/mbsinit.c | 13 | ||||
-rw-r--r-- | src/wchar/mbsrtowcs.c | 24 | ||||
-rw-r--r-- | src/wchar/mbstate_t.h | 2 | ||||
-rw-r--r-- | src/wchar/wcrtomb.c | 19 | ||||
-rw-r--r-- | src/wchar/wcsrtombs.c | 22 |
14 files changed, 128 insertions, 46 deletions
diff --git a/mk/mbrlen.d b/mk/mbrlen.d index 56861395..8947624b 100644 --- a/mk/mbrlen.d +++ b/mk/mbrlen.d @@ -3,6 +3,7 @@ libc.a(mbrlen.o): $(OBJDIR)/mbrlen.o @$(AR) $(ARFLAGS) $@ $(OBJDIR)/$% $(OBJDIR)/mbrlen.o: src/wchar/mbrlen.c +$(OBJDIR)/mbrlen.o: src/wchar/_wchar.h $(OBJDIR)/mbrlen.o: @mkdir -p $(@D) $(CC) -c -o $@ $(CFLAGS) src/wchar/mbrlen.c diff --git a/mk/mbrtowc.d b/mk/mbrtowc.d index e1f78ce3..fd9fc657 100644 --- a/mk/mbrtowc.d +++ b/mk/mbrtowc.d @@ -3,6 +3,7 @@ libc.a(mbrtowc.o): $(OBJDIR)/mbrtowc.o @$(AR) $(ARFLAGS) $@ $(OBJDIR)/$% $(OBJDIR)/mbrtowc.o: src/wchar/mbrtowc.c +$(OBJDIR)/mbrtowc.o: src/wchar/_wchar.h $(OBJDIR)/mbrtowc.o: @mkdir -p $(@D) $(CC) -c -o $@ $(CFLAGS) src/wchar/mbrtowc.c diff --git a/mk/mbsinit.d b/mk/mbsinit.d index 14774370..7086193c 100644 --- a/mk/mbsinit.d +++ b/mk/mbsinit.d @@ -3,6 +3,7 @@ libc.a(mbsinit.o): $(OBJDIR)/mbsinit.o @$(AR) $(ARFLAGS) $@ $(OBJDIR)/$% $(OBJDIR)/mbsinit.o: src/wchar/mbsinit.c +$(OBJDIR)/mbsinit.o: src/wchar/_wchar.h $(OBJDIR)/mbsinit.o: @mkdir -p $(@D) $(CC) -c -o $@ $(CFLAGS) src/wchar/mbsinit.c diff --git a/mk/mbsrtowcs.d b/mk/mbsrtowcs.d index a94d8a58..f63bcb3d 100644 --- a/mk/mbsrtowcs.d +++ b/mk/mbsrtowcs.d @@ -3,6 +3,7 @@ libc.a(mbsrtowcs.o): $(OBJDIR)/mbsrtowcs.o @$(AR) $(ARFLAGS) $@ $(OBJDIR)/$% $(OBJDIR)/mbsrtowcs.o: src/wchar/mbsrtowcs.c +$(OBJDIR)/mbsrtowcs.o: src/wchar/_wchar.h $(OBJDIR)/mbsrtowcs.o: @mkdir -p $(@D) $(CC) -c -o $@ $(CFLAGS) src/wchar/mbsrtowcs.c diff --git a/mk/wcrtomb.d b/mk/wcrtomb.d index e83f788b..9224692e 100644 --- a/mk/wcrtomb.d +++ b/mk/wcrtomb.d @@ -3,7 +3,7 @@ libc.a(wcrtomb.o): $(OBJDIR)/wcrtomb.o @$(AR) $(ARFLAGS) $@ $(OBJDIR)/$% $(OBJDIR)/wcrtomb.o: src/wchar/wcrtomb.c -$(OBJDIR)/wcrtomb.o: src/_safety.h +$(OBJDIR)/wcrtomb.o: src/wchar/_wchar.h $(OBJDIR)/wcrtomb.o: @mkdir -p $(@D) $(CC) -c -o $@ $(CFLAGS) src/wchar/wcrtomb.c diff --git a/mk/wcsrtombs.d b/mk/wcsrtombs.d index f9cf789d..2272dbfc 100644 --- a/mk/wcsrtombs.d +++ b/mk/wcsrtombs.d @@ -3,6 +3,7 @@ libc.a(wcsrtombs.o): $(OBJDIR)/wcsrtombs.o @$(AR) $(ARFLAGS) $@ $(OBJDIR)/$% $(OBJDIR)/wcsrtombs.o: src/wchar/wcsrtombs.c +$(OBJDIR)/wcsrtombs.o: src/wchar/_wchar.h $(OBJDIR)/wcsrtombs.o: @mkdir -p $(@D) $(CC) -c -o $@ $(CFLAGS) src/wchar/wcsrtombs.c diff --git a/src/wchar/_wchar.h b/src/wchar/_wchar.h new file mode 100644 index 00000000..e5d87c7e --- /dev/null +++ b/src/wchar/_wchar.h @@ -0,0 +1,53 @@ +#ifndef ___WCHAR_H__ +#define ___WCHAR_H__ + +#include <wchar.h> +#include <stdlib.h> +#include "_safety.h" +#include "locale/_locale.h" + +struct __mbstate_t { + unsigned int ctype_epoch; + enum { NONE, WTOMB, MBTOW } dir; + const char *mbs; + const wchar_t *wcs; +}; + +/* use mbstate_t: mbrlen, mbrtowc, wcrtomb, mbsrtowcs, wcsrtombs */ +/* TODO: save a pool of reusable struct __mbstate_t objects to avoid massive leakage */ +#define SET_MBSTATE(__m, __d, __s, __w) do { \ + if (__m->__impl == NULL) { \ + __m->__impl = malloc(sizeof(*__m->__impl)); \ + } \ + __m->__impl->ctype_epoch = __get_locale()->ctype_epoch; \ + __m->__impl->dir = __d; \ + __m->__impl->mbs = __s; \ + __m->__impl->wcs = __w; \ +} while (0) + +#ifndef NDEBUG +#define ASSERT_MBSTATE(__m, __d, __s, __w) do { \ + if (__m != NULL && __m->__impl != NULL) { \ + struct __mbstate_t *_m = __m->__impl; \ + if (_m->ctype_epoch != 0 && _m->ctype_epoch != __get_locale()->ctype_epoch) { \ + UNDEFINED("LC_CTYPE has changed since last intermediate use of %s", #__m); \ + } \ + if (_m->dir == WTOMB && __d == MBTOW) { \ + UNDEFINED("%s is tracking wide to multi-byte conversion", #__m); \ + } \ + if (_m->dir == MBTOW && __d == WTOMB) { \ + UNDEFINED("%s is tracking multi-byte to wide conversion", #__m); \ + } \ + if (_m->dir == MBTOW && _m->mbs != (const char *) __s) { \ + UNDEFINED("%s is tracking a different multi-byte string", #__m); \ + } \ + if (_m->dir == WTOMB && _m->wcs != (const wchar_t *) __w) { \ + UNDEFINED("%s is tracking a different wide character string", #__m); \ + } \ + } \ +} while (0) +#else +#define ASSERT_MBSTATE(__m, __d, __s, __w) (void)(__m) +#endif + +#endif diff --git a/src/wchar/mbrlen.c b/src/wchar/mbrlen.c index 135a56b2..06caa81b 100644 --- a/src/wchar/mbrlen.c +++ b/src/wchar/mbrlen.c @@ -1,20 +1,16 @@ -#if 0 - #include <wchar.h> +#include "_wchar.h" size_t mbrlen(const char * restrict s, size_t n, mbstate_t * restrict ps) { - + static mbstate_t internal = {0}; SIGNAL_SAFE(0); + ASSERT_MBSTATE(ps, MBTOW, NULL, NULL); /* TODO: overlap */ - static mbstate_t internal = 0; return mbrtowc(NULL, s, n, ps != NULL ? ps : &internal); } /* STDC(199409) */ - - -#endif diff --git a/src/wchar/mbrtowc.c b/src/wchar/mbrtowc.c index 16e2a937..aa7c4803 100644 --- a/src/wchar/mbrtowc.c +++ b/src/wchar/mbrtowc.c @@ -1,27 +1,29 @@ -#if 0 - #include <wchar.h> +#include "_wchar.h" +GCC_SSE_HACK size_t mbrtowc(wchar_t * restrict pwc, const char * restrict s, size_t n, mbstate_t * restrict ps) { + static struct __mbstate_t internal = { 0 }; + static mbstate_t ip = { &internal }; + + if (ps == NULL) { + ps = &ip; + } + SIGNAL_SAFE(0); + ASSERT_MBSTATE(ps, MBTOW, s, pwc); /* TODO: overlap */ - (void)ps; (void)pwc; (void)n; - if (s == NULL) { - s = ""; - n = 1; + return mbrtowc(NULL, "", 1, ps); } - /* TODO */ + SET_MBSTATE(ps, MBTOW, s, pwc); - return 0; + return n; } /* STDC(199409) */ - - -#endif diff --git a/src/wchar/mbsinit.c b/src/wchar/mbsinit.c index 52640483..9b41e2a2 100644 --- a/src/wchar/mbsinit.c +++ b/src/wchar/mbsinit.c @@ -1,12 +1,16 @@ -#if 0 - #include <wchar.h> +#include "_wchar.h" int mbsinit(const mbstate_t * ps) { SIGNAL_SAFE(0); - if (ps == NULL || *ps == 0) { + if (ps == NULL || ps->__impl == NULL) { + return 1; + } + + struct __mbstate_t *m = ps->__impl; + if (m->ctype_epoch == 0 && m->dir == NONE && m->mbs == NULL && m->wcs == NULL) { return 1; } @@ -16,6 +20,3 @@ int mbsinit(const mbstate_t * ps) /* STDC(199409) */ - - -#endif diff --git a/src/wchar/mbsrtowcs.c b/src/wchar/mbsrtowcs.c index 2f273598..a23402b3 100644 --- a/src/wchar/mbsrtowcs.c +++ b/src/wchar/mbsrtowcs.c @@ -1,19 +1,27 @@ -#if 0 - #include <wchar.h> +#include "_wchar.h" -size_t mbsrtowcs(wchar_t * restrict dst, const char * restrict src, size_t len, mbstate_t * restrict ps) +GCC_SSE_HACK +size_t mbsrtowcs(wchar_t * restrict dst, const char ** restrict src, size_t len, mbstate_t * restrict ps) { + static struct __mbstate_t internal = { 0 }; + static mbstate_t ip = { &internal }; + + if (ps == NULL) { + ps = &ip; + } + SIGNAL_SAFE(0); + ASSERT_MBSTATE(ps, MBTOW, *src, dst); /* TODO: overlap */ - (void)dst; (void)src; (void)len; (void)ps; - return 0; + SET_MBSTATE(ps, MBTOW, *src, dst); + + /* TODO: implement */ + + return len; } /* STDC(199409) */ - - -#endif diff --git a/src/wchar/mbstate_t.h b/src/wchar/mbstate_t.h index d29ecfa5..a0185f99 100644 --- a/src/wchar/mbstate_t.h +++ b/src/wchar/mbstate_t.h @@ -1,5 +1,5 @@ #include <wchar.h> -typedef int mbstate_t; +typedef struct { struct __mbstate_t *__impl; } mbstate_t; /* STDC(199409) diff --git a/src/wchar/wcrtomb.c b/src/wchar/wcrtomb.c index 20cbe235..c73cdce8 100644 --- a/src/wchar/wcrtomb.c +++ b/src/wchar/wcrtomb.c @@ -1,18 +1,27 @@ #include <wchar.h> #include <limits.h> -#include "_safety.h" +#include "_wchar.h" +GCC_SSE_HACK size_t wcrtomb(char * restrict s, wchar_t wc, mbstate_t * restrict ps) { + static struct __mbstate_t internal = { 0 }; + static mbstate_t ip = { &internal }; + + if (ps == NULL) { + ps = &ip; + } + SIGNAL_SAFE(0); + ASSERT_MBSTATE(ps, WTOMB, s, &wc); /* TODO: overlap */ - char buf[MB_LEN_MAX+1]; if (s == NULL) { - s = buf; - wc = L'\0'; + char buf[MB_LEN_MAX+1]; + return wcrtomb(buf, L'\0', ps); } - (void)wc; (void)ps; + + SET_MBSTATE(ps, WTOMB, s, &wc); /* do stuff */ return 0; diff --git a/src/wchar/wcsrtombs.c b/src/wchar/wcsrtombs.c index 9a3c6c87..c094de80 100644 --- a/src/wchar/wcsrtombs.c +++ b/src/wchar/wcsrtombs.c @@ -1,19 +1,27 @@ -#if 0 - #include <wchar.h> +#include "_wchar.h" +GCC_SSE_HACK size_t wcsrtombs(char * restrict dst, const wchar_t ** restrict src, size_t len, mbstate_t * restrict ps) { + static struct __mbstate_t internal = { 0 }; + static mbstate_t ip = { &internal }; + + if (ps == NULL) { + ps = &ip; + } + SIGNAL_SAFE(0); + ASSERT_MBSTATE(ps, WTOMB, dst, src); /* TODO: overlap */ - (void)dst; (void)src; (void)len; (void)ps; - return 0; + SET_MBSTATE(ps, WTOMB, dst, *src); + + /* TODO: conversion */ + + return len; } /* STDC(199409) */ - - -#endif |