summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mk/mbrlen.d1
-rw-r--r--mk/mbrtowc.d1
-rw-r--r--mk/mbsinit.d1
-rw-r--r--mk/mbsrtowcs.d1
-rw-r--r--mk/wcrtomb.d2
-rw-r--r--mk/wcsrtombs.d1
-rw-r--r--src/wchar/_wchar.h53
-rw-r--r--src/wchar/mbrlen.c10
-rw-r--r--src/wchar/mbrtowc.c24
-rw-r--r--src/wchar/mbsinit.c13
-rw-r--r--src/wchar/mbsrtowcs.c24
-rw-r--r--src/wchar/mbstate_t.h2
-rw-r--r--src/wchar/wcrtomb.c19
-rw-r--r--src/wchar/wcsrtombs.c22
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