diff --git a/lib/mbrtowc-factory.c b/lib/mbrtowc-factory.c
new file mode 100644
index 0000000..8786382
--- /dev/null
+++ b/lib/mbrtowc-factory.c
@@ -0,0 +1,580 @@
+/* Factory that produces an mbrtowc-like function for a given locale.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+ Written by Bruno Haible
, 2018.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see . */
+
+#include
+
+/* Specification. */
+#include
+
+#include
+#include
+#include
+
+#include "localcharset.h"
+
+#if __GLIBC__ >= 2
+
+static mbstate_t internal_state;
+
+static size_t
+utf8_mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)
+{
+ if (s == NULL)
+ {
+ pwc = NULL;
+ s = "";
+ n = 1;
+ }
+
+ if (n == 0)
+ return (size_t)(-2);
+
+ /* Here n > 0. */
+
+ if (ps == NULL)
+ ps = &internal_state;
+
+ /* ps->__count is
+ (number of bytes already read) + (number of total bytes expected) << 8,
+ ps->__value.__wch is the part already read. */
+ size_t read = ps->__count & 0xff;
+ unsigned int wc;
+
+ if (read == 0)
+ {
+ if (!(ps->__count == 0))
+ abort ();
+ unsigned char c = (unsigned char) s[0];
+ if (c < 0x80)
+ {
+ if (pwc != NULL)
+ *pwc = c;
+ return 1;
+ }
+ else if (c >= 0xc2)
+ {
+ if (c < 0xe0)
+ {
+ if (n >= 2)
+ {
+ unsigned char c2 = (unsigned char) s[1];
+
+ if ((c2 ^ 0x80) < 0x40)
+ {
+ if (pwc != NULL)
+ *pwc = ((unsigned int) (c & 0x1f) << 6)
+ | (unsigned int) (c2 ^ 0x80);
+ return 2;
+ }
+ else
+ goto invalid;
+ }
+ else /* n == 1 */
+ {
+ ps->__count = 0x0201;
+ ps->__value.__wch = (unsigned int) (c & 0x1f) << 6;
+ return (size_t)(-2);
+ }
+ }
+ else if (c < 0xf0)
+ {
+ if (n >= 3)
+ {
+ unsigned char c2 = (unsigned char) s[1];
+
+ if ((c2 ^ 0x80) < 0x40
+ && (c >= 0xe1 || c2 >= 0xa0)
+ && (c != 0xed || c2 < 0xa0))
+ {
+ unsigned char c3 = (unsigned char) s[2];
+
+ if ((c3 ^ 0x80) < 0x40)
+ {
+ if (pwc != NULL)
+ *pwc = ((unsigned int) (c & 0x0f) << 12)
+ | ((unsigned int) (c2 ^ 0x80) << 6)
+ | (unsigned int) (c3 ^ 0x80);
+ return 3;
+ }
+ else
+ goto invalid;
+ }
+ else
+ goto invalid;
+ }
+ else if (n == 2)
+ {
+ unsigned char c2 = (unsigned char) s[1];
+
+ if ((c2 ^ 0x80) < 0x40
+ && (c >= 0xe1 || c2 >= 0xa0)
+ && (c != 0xed || c2 < 0xa0))
+ {
+ ps->__count = 0x0302;
+ ps->__value.__wch = ((unsigned int) (c & 0x0f) << 12)
+ | ((unsigned int) (c2 ^ 0x80) << 6);
+ return (size_t)(-2);
+ }
+ else
+ goto invalid;
+ }
+ else /* n == 1 */
+ {
+ ps->__count = 0x0301;
+ ps->__value.__wch = (unsigned int) (c & 0x0f) << 12;
+ return (size_t)(-2);
+ }
+ }
+ else if (c <= 0xf4)
+ {
+ if (n >= 4)
+ {
+ unsigned char c2 = (unsigned char) s[1];
+
+ if ((c2 ^ 0x80) < 0x40
+ && (c >= 0xf1 || c2 >= 0x90)
+ && (c < 0xf4 || (c == 0xf4 && c2 < 0x90)))
+ {
+ unsigned char c3 = (unsigned char) s[2];
+
+ if ((c3 ^ 0x80) < 0x40)
+ {
+ unsigned char c4 = (unsigned char) s[3];
+
+ if ((c4 ^ 0x80) < 0x40)
+ {
+ if (pwc != NULL)
+ *pwc = ((unsigned int) (c & 0x07) << 18)
+ | ((unsigned int) (c2 ^ 0x80) << 12)
+ | ((unsigned int) (c3 ^ 0x80) << 6)
+ | (unsigned int) (c4 ^ 0x80);
+ return 4;
+ }
+ else
+ goto invalid;
+ }
+ else
+ goto invalid;
+ }
+ else
+ goto invalid;
+ }
+ else if (n == 3)
+ {
+ unsigned char c2 = (unsigned char) s[1];
+
+ if ((c2 ^ 0x80) < 0x40
+ && (c >= 0xf1 || c2 >= 0x90)
+ && (c < 0xf4 || (c == 0xf4 && c2 < 0x90)))
+ {
+ unsigned char c3 = (unsigned char) s[2];
+
+ if ((c3 ^ 0x80) < 0x40)
+ {
+ ps->__count = 0x0403;
+ ps->__value.__wch = ((unsigned int) (c & 0x07) << 18)
+ | ((unsigned int) (c2 ^ 0x80) << 12)
+ | ((unsigned int) (c3 ^ 0x80) << 6);
+ return (size_t)(-2);
+ }
+ else
+ goto invalid;
+ }
+ else
+ goto invalid;
+ }
+ else if (n == 2)
+ {
+ unsigned char c2 = (unsigned char) s[1];
+
+ if ((c2 ^ 0x80) < 0x40
+ && (c >= 0xf1 || c2 >= 0x90)
+ && (c < 0xf4 || (c == 0xf4 && c2 < 0x90)))
+ {
+ ps->__count = 0x0402;
+ ps->__value.__wch = ((unsigned int) (c & 0x07) << 18)
+ | ((unsigned int) (c2 ^ 0x80) << 12);
+ return (size_t)(-2);
+ }
+ else
+ goto invalid;
+ }
+ else /* n == 1 */
+ {
+ ps->__count = 0x0401;
+ ps->__value.__wch = (unsigned int) (c & 0x07) << 18;
+ return (size_t)(-2);
+ }
+ }
+ else
+ goto invalid;
+ }
+ else
+ goto invalid;
+ }
+ else
+ {
+ size_t expected = ps->__count >> 8;
+ if (!(expected > read && expected <= 4))
+ abort ();
+ wc = ps->__value.__wch;
+ {
+ unsigned char c = (unsigned char) s[0];
+ if (!(c >= 0x80 && c < 0xc0))
+ goto invalid;
+ c = c & 0x3f;
+ wc |= c << (6 * (expected - read - 1));
+ }
+ if (read == 1)
+ {
+ if (expected == 3)
+ {
+ if (!(wc >= 0x800 && !(wc >= 0xd800 && wc < 0xe000)))
+ goto invalid;
+ }
+ if (expected == 4)
+ {
+ if (!(wc >= 0x10000 && wc < 0x110000))
+ goto invalid;
+ }
+ }
+ size_t orig_read = read;
+ for (;;)
+ {
+ read++;
+ if (read == expected)
+ {
+ if (pwc != NULL)
+ *pwc = wc;
+ ps->__count = 0;
+ return read - orig_read;
+ }
+ n--;
+ if (n == 0)
+ break;
+ s++;
+ {
+ unsigned char c = (unsigned char) s[0];
+ if (!(c >= 0x80 && c < 0xc0))
+ goto invalid;
+ c = c & 0x3f;
+ wc |= c << (6 * (expected - read - 1));
+ }
+ }
+ ps->__count = (expected << 8) | read;
+ ps->__value.__wch = wc;
+ return (size_t)(-2);
+ }
+
+ invalid:
+ errno = EILSEQ;
+ /* The conversion state is undefined, says POSIX. */
+ return (size_t)(-1);
+}
+
+#endif
+
+#if defined __APPLE__ && defined __MACH__ /* macOS 10.13 */
+
+static mbstate_t internal_state;
+
+typedef struct
+{
+ unsigned int wc_part; /* Part of wc, (number of bytes read) * 6 bits */
+ unsigned int remaining; /* Number of remaining bytes */
+ /* In Mac OS X 10.13: 0xBF80 if (number of bytes read) == 1, otherwise 0.
+ In Mac OS X 10.5: 0x80 or 0x800 or 0x10000, depending on number of total bytes expected. */
+ unsigned int flag;
+} real_mbstate_t;
+
+static size_t
+utf8_mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)
+{
+ if (s == NULL)
+ {
+ pwc = NULL;
+ s = "";
+ n = 1;
+ }
+
+ if (n == 0)
+ return (size_t)(-2);
+
+ /* Here n > 0. */
+
+ if (ps == NULL)
+ ps = &internal_state;
+
+ real_mbstate_t *pstate = (real_mbstate_t *) ps;
+ size_t remaining = pstate->remaining;
+ unsigned int wc;
+
+ if (remaining == 0)
+ {
+ if (!(pstate->wc_part == 0 && pstate->flag == 0))
+ abort ();
+ unsigned char c = (unsigned char) s[0];
+ if (c < 0x80)
+ {
+ if (pwc != NULL)
+ *pwc = c;
+ return 1;
+ }
+ else if (c >= 0xc2)
+ {
+ if (c < 0xe0)
+ {
+ if (n >= 2)
+ {
+ unsigned char c2 = (unsigned char) s[1];
+
+ if ((c2 ^ 0x80) < 0x40)
+ {
+ if (pwc != NULL)
+ *pwc = ((unsigned int) (c & 0x1f) << 6)
+ | (unsigned int) (c2 ^ 0x80);
+ return 2;
+ }
+ else
+ goto invalid;
+ }
+ else /* n == 1 */
+ {
+ pstate->wc_part = (unsigned int) (c & 0x1f);
+ pstate->remaining = 1;
+ pstate->flag = 0xBF80;
+ return (size_t)(-2);
+ }
+ }
+ else if (c < 0xf0)
+ {
+ if (n >= 3)
+ {
+ unsigned char c2 = (unsigned char) s[1];
+
+ if ((c2 ^ 0x80) < 0x40
+ && (c >= 0xe1 || c2 >= 0xa0)
+ && (c != 0xed || c2 < 0xa0))
+ {
+ unsigned char c3 = (unsigned char) s[2];
+
+ if ((c3 ^ 0x80) < 0x40)
+ {
+ if (pwc != NULL)
+ *pwc = ((unsigned int) (c & 0x0f) << 12)
+ | ((unsigned int) (c2 ^ 0x80) << 6)
+ | (unsigned int) (c3 ^ 0x80);
+ return 3;
+ }
+ else
+ goto invalid;
+ }
+ else
+ goto invalid;
+ }
+ else if (n == 2)
+ {
+ unsigned char c2 = (unsigned char) s[1];
+
+ if ((c2 ^ 0x80) < 0x40
+ && (c >= 0xe1 || c2 >= 0xa0)
+ && (c != 0xed || c2 < 0xa0))
+ {
+ pstate->wc_part = ((unsigned int) (c & 0x0f) << 6)
+ | (unsigned int) (c2 ^ 0x80);
+ pstate->remaining = 1;
+ pstate->flag = 0;
+ return (size_t)(-2);
+ }
+ else
+ goto invalid;
+ }
+ else /* n == 1 */
+ {
+ pstate->wc_part = (unsigned int) (c & 0x0f);
+ pstate->remaining = 2;
+ pstate->flag = 0xBF80;
+ return (size_t)(-2);
+ }
+ }
+ else if (c <= 0xf4)
+ {
+ if (n >= 4)
+ {
+ unsigned char c2 = (unsigned char) s[1];
+
+ if ((c2 ^ 0x80) < 0x40
+ && (c >= 0xf1 || c2 >= 0x90)
+ && (c < 0xf4 || (c == 0xf4 && c2 < 0x90)))
+ {
+ unsigned char c3 = (unsigned char) s[2];
+
+ if ((c3 ^ 0x80) < 0x40)
+ {
+ unsigned char c4 = (unsigned char) s[3];
+
+ if ((c4 ^ 0x80) < 0x40)
+ {
+ if (pwc != NULL)
+ *pwc = ((unsigned int) (c & 0x07) << 18)
+ | ((unsigned int) (c2 ^ 0x80) << 12)
+ | ((unsigned int) (c3 ^ 0x80) << 6)
+ | (unsigned int) (c4 ^ 0x80);
+ return 4;
+ }
+ else
+ goto invalid;
+ }
+ else
+ goto invalid;
+ }
+ else
+ goto invalid;
+ }
+ else if (n == 3)
+ {
+ unsigned char c2 = (unsigned char) s[1];
+
+ if ((c2 ^ 0x80) < 0x40
+ && (c >= 0xf1 || c2 >= 0x90)
+ && (c < 0xf4 || (c == 0xf4 && c2 < 0x90)))
+ {
+ unsigned char c3 = (unsigned char) s[2];
+
+ if ((c3 ^ 0x80) < 0x40)
+ {
+ pstate->wc_part = ((unsigned int) (c & 0x07) << 12)
+ | ((unsigned int) (c2 ^ 0x80) << 6)
+ | (unsigned int) (c3 ^ 0x80);
+ pstate->remaining = 1;
+ pstate->flag = 0;
+ return (size_t)(-2);
+ }
+ else
+ goto invalid;
+ }
+ else
+ goto invalid;
+ }
+ else if (n == 2)
+ {
+ unsigned char c2 = (unsigned char) s[1];
+
+ if ((c2 ^ 0x80) < 0x40
+ && (c >= 0xf1 || c2 >= 0x90)
+ && (c < 0xf4 || (c == 0xf4 && c2 < 0x90)))
+ {
+ pstate->wc_part = ((unsigned int) (c & 0x07) << 6)
+ | (unsigned int) (c2 ^ 0x80);
+ pstate->remaining = 2;
+ pstate->flag = 0;
+ return (size_t)(-2);
+ }
+ else
+ goto invalid;
+ }
+ else /* n == 1 */
+ {
+ pstate->wc_part = (unsigned int) (c & 0x07);
+ pstate->remaining = 3;
+ pstate->flag = 0xBF80;
+ return (size_t)(-2);
+ }
+ }
+ else
+ goto invalid;
+ }
+ else
+ goto invalid;
+ }
+ else
+ {
+ if (!(remaining <= 3))
+ abort ();
+ wc = pstate->wc_part << (6 * pstate->remaining);
+ {
+ unsigned char c = (unsigned char) s[0];
+ if (!(c >= 0x80 && c < 0xc0))
+ goto invalid;
+ c = c & 0x3f;
+ wc |= c << (6 * (remaining - 1));
+ }
+ if (pstate->flag)
+ {
+ if (remaining == 2)
+ {
+ if (!(wc >= 0x800 && !(wc >= 0xd800 && wc < 0xe000)))
+ goto invalid;
+ }
+ if (remaining == 3)
+ {
+ if (!(wc >= 0x10000 && wc < 0x110000))
+ goto invalid;
+ }
+ }
+ const char *orig_s = s;
+ for (;;)
+ {
+ s++;
+ remaining--;
+ if (remaining == 0)
+ {
+ if (pwc != NULL)
+ *pwc = wc;
+ pstate->wc_part = 0;
+ pstate->remaining = 0;
+ pstate->flag = 0;
+ return s - orig_s;
+ }
+ n--;
+ if (n == 0)
+ break;
+ {
+ unsigned char c = (unsigned char) s[0];
+ if (!(c >= 0x80 && c < 0xc0))
+ goto invalid;
+ c = c & 0x3f;
+ wc |= c << (6 * (remaining - 1));
+ }
+ }
+ pstate->wc_part = wc >> (6 * remaining);
+ pstate->remaining = remaining;
+ pstate->flag = 0;
+ return (size_t)(-2);
+ }
+
+ invalid:
+ errno = EILSEQ;
+ /* The conversion state is undefined, says POSIX. */
+ return (size_t)(-1);
+}
+
+#endif
+
+mbrtowc_func_t
+get_optimized_mbrtowc (void)
+{
+#if __GLIBC__ >= 2 || (defined __APPLE__ && defined __MACH__)
+ const char *encoding = locale_charset ();
+
+ if (strcmp (encoding, "UTF-8") == 0)
+ return utf8_mbrtowc;
+ else
+#endif
+ /* No optimization. */
+ return mbrtowc;
+}
diff --git a/lib/mbsinit-factory.c b/lib/mbsinit-factory.c
new file mode 100644
index 0000000..137cd23
--- /dev/null
+++ b/lib/mbsinit-factory.c
@@ -0,0 +1,28 @@
+/* Factory that produces an mbsinit-like function for a given locale.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+ Written by Bruno Haible , 2018.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see . */
+
+#include
+
+/* Specification. */
+#include
+
+mbsinit_func_t
+get_optimized_mbsinit (void)
+{
+ /* No optimization is needed. */
+ return mbsinit;
+}
diff --git a/lib/mbsreset-factory.c b/lib/mbsreset-factory.c
new file mode 100644
index 0000000..2114027
--- /dev/null
+++ b/lib/mbsreset-factory.c
@@ -0,0 +1,65 @@
+/* Factory that produces an mbsreset-like function for a given locale.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+ Written by Bruno Haible , 2018.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see . */
+
+#include
+
+/* Specification. */
+#include
+
+#include
+
+#include "localcharset.h"
+
+/* sizeof (mbstate_t) is 128 on macOS. But only the first few bytes of the
+ state actually matter. */
+
+#if defined __APPLE__ && defined __MACH__
+
+typedef struct
+{
+ unsigned int wc_part;
+ unsigned int remaining;
+ unsigned int flag;
+} real_mbstate_t;
+
+static void
+utf8_mbsreset (mbstate_t *ps)
+{
+ memset (ps, '\0', sizeof (real_mbstate_t));
+}
+
+#endif
+
+static void
+generic_mbsreset (mbstate_t *ps)
+{
+ memset (ps, '\0', sizeof (mbstate_t));
+}
+
+mbsreset_func_t
+get_optimized_mbsreset (void)
+{
+#if defined __APPLE__ && defined __MACH__
+ const char *encoding = locale_charset ();
+
+ if (strcmp (encoding, "UTF-8") == 0)
+ return utf8_mbsreset;
+ else
+#endif
+ /* No optimization. */
+ return generic_mbsreset;
+}
diff --git a/lib/wchar.in.h b/lib/wchar.in.h
index 655340c..679992a 100644
--- a/lib/wchar.in.h
+++ b/lib/wchar.in.h
@@ -1067,6 +1067,25 @@ _GL_WARN_ON_USE (wcsftime, "wcsftime is unportable - "
#endif
+/* Factories that produce functions for a given locale. */
+#if @GNULIB_MBRTOWC_FACTORY@
+typedef size_t (*mbrtowc_func_t) (wchar_t *, const char *, size_t, mbstate_t *);
+_GL_FUNCDECL_SYS (get_optimized_mbrtowc, mbrtowc_func_t, (void));
+#endif
+#if @GNULIB_MBSINIT_FACTORY@
+typedef int (*mbsinit_func_t) (const mbstate_t *);
+_GL_FUNCDECL_SYS (get_optimized_mbsinit, mbsinit_func_t, (void));
+#endif
+#if @GNULIB_MBSRESET_FACTORY@
+typedef void (*mbsreset_func_t) (mbstate_t *);
+_GL_FUNCDECL_SYS (get_optimized_mbsreset, mbsreset_func_t, (void));
+#endif
+#if @GNULIB_WCWIDTH_FACTORY@
+typedef int (*wcwidth_func_t) (wchar_t);
+_GL_FUNCDECL_SYS (get_optimized_wcwidth, wcwidth_func_t, (void));
+#endif
+
+
#endif /* _@GUARD_PREFIX@_WCHAR_H */
#endif /* _@GUARD_PREFIX@_WCHAR_H */
#endif
diff --git a/lib/wcwidth-factory.c b/lib/wcwidth-factory.c
new file mode 100644
index 0000000..611bf40
--- /dev/null
+++ b/lib/wcwidth-factory.c
@@ -0,0 +1,56 @@
+/* Factory that produces a wcwidth-like function for a given locale.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+ Written by Bruno Haible , 2018.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see . */
+
+#include
+
+/* Specification. */
+#include
+
+#include
+
+#include "localcharset.h"
+#include "uniwidth.h"
+
+static int
+utf8_wcwidth (wchar_t wc)
+{
+ return uc_width (wc, "UTF-8");
+}
+
+#if !HAVE_WCWIDTH
+static int
+fallback_wcwidth (wchar_t wc)
+{
+ return wc == 0 ? 0 : iswprint (wc) ? 1 : -1;
+}
+#endif
+
+wcwidth_func_t
+get_optimized_wcwidth (void)
+{
+ const char *encoding = locale_charset ();
+
+ if (strcmp (encoding, "UTF-8") == 0)
+ return utf8_wcwidth;
+ else
+ /* No optimization. */
+#if HAVE_WCWIDTH
+ return wcwidth;
+#else
+ return fallback_wcwidth;
+#endif
+}
diff --git a/m4/wchar_h.m4 b/m4/wchar_h.m4
index 416e0a1..ca415a9 100644
--- a/m4/wchar_h.m4
+++ b/m4/wchar_h.m4
@@ -7,7 +7,7 @@ dnl with or without modifications, as long as this notice is preserved.
dnl Written by Eric Blake.
-# wchar_h.m4 serial 42
+# wchar_h.m4 serial 43
AC_DEFUN([gl_WCHAR_H],
[
@@ -180,6 +180,10 @@ AC_DEFUN([gl_WCHAR_H_DEFAULTS],
GNULIB_WCSTOK=0; AC_SUBST([GNULIB_WCSTOK])
GNULIB_WCSWIDTH=0; AC_SUBST([GNULIB_WCSWIDTH])
GNULIB_WCSFTIME=0; AC_SUBST([GNULIB_WCSFTIME])
+ GNULIB_MBRTOWC_FACTORY=0; AC_SUBST([GNULIB_MBRTOWC_FACTORY])
+ GNULIB_MBSINIT_FACTORY=0; AC_SUBST([GNULIB_MBSINIT_FACTORY])
+ GNULIB_MBSRESET_FACTORY=0; AC_SUBST([GNULIB_MBSRESET_FACTORY])
+ GNULIB_WCWIDTH_FACTORY=0; AC_SUBST([GNULIB_WCWIDTH_FACTORY])
dnl Assume proper GNU behavior unless another module says otherwise.
HAVE_BTOWC=1; AC_SUBST([HAVE_BTOWC])
HAVE_MBSINIT=1; AC_SUBST([HAVE_MBSINIT])
diff --git a/modules/mbrtowc-factory b/modules/mbrtowc-factory
new file mode 100644
index 0000000..90d348d
--- /dev/null
+++ b/modules/mbrtowc-factory
@@ -0,0 +1,24 @@
+Description:
+Factory that produces an mbrtowc-like function for a given locale.
+
+Files:
+lib/mbrtowc-factory.c
+
+Depends-on:
+wchar
+mbrtowc
+
+configure.ac:
+gl_WCHAR_MODULE_INDICATOR([mbrtowc-factory])
+
+Makefile.am:
+lib_SOURCES += mbrtowc-factory.c
+
+Include:
+
+
+License:
+LGPLv2+
+
+Maintainer:
+all
diff --git a/modules/mbsinit-factory b/modules/mbsinit-factory
new file mode 100644
index 0000000..5c311a8
--- /dev/null
+++ b/modules/mbsinit-factory
@@ -0,0 +1,24 @@
+Description:
+Factory that produces an mbsinit-like function for a given locale.
+
+Files:
+lib/mbsinit-factory.c
+
+Depends-on:
+wchar
+mbsinit
+
+configure.ac:
+gl_WCHAR_MODULE_INDICATOR([mbsinit-factory])
+
+Makefile.am:
+lib_SOURCES += mbsinit-factory.c
+
+Include:
+
+
+License:
+LGPLv2+
+
+Maintainer:
+all
diff --git a/modules/mbsreset-factory b/modules/mbsreset-factory
new file mode 100644
index 0000000..dd08563
--- /dev/null
+++ b/modules/mbsreset-factory
@@ -0,0 +1,23 @@
+Description:
+Factory that produces an mbsreset-like function for a given locale.
+
+Files:
+lib/mbsreset-factory.c
+
+Depends-on:
+wchar
+
+configure.ac:
+gl_WCHAR_MODULE_INDICATOR([mbsreset-factory])
+
+Makefile.am:
+lib_SOURCES += mbsreset-factory.c
+
+Include:
+
+
+License:
+LGPLv2+
+
+Maintainer:
+all
diff --git a/modules/wchar b/modules/wchar
index 31770d8..3a83b63 100644
--- a/modules/wchar
+++ b/modules/wchar
@@ -73,6 +73,10 @@ wchar.h: wchar.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H)
-e 's/@''GNULIB_WCSTOK''@/$(GNULIB_WCSTOK)/g' \
-e 's/@''GNULIB_WCSWIDTH''@/$(GNULIB_WCSWIDTH)/g' \
-e 's/@''GNULIB_WCSFTIME''@/$(GNULIB_WCSFTIME)/g' \
+ -e 's/@''GNULIB_MBRTOWC_FACTORY''@/$(GNULIB_MBRTOWC_FACTORY)/g' \
+ -e 's/@''GNULIB_MBSINIT_FACTORY''@/$(GNULIB_MBSINIT_FACTORY)/g' \
+ -e 's/@''GNULIB_MBSRESET_FACTORY''@/$(GNULIB_MBSRESET_FACTORY)/g' \
+ -e 's/@''GNULIB_WCWIDTH_FACTORY''@/$(GNULIB_WCWIDTH_FACTORY)/g' \
< $(srcdir)/wchar.in.h | \
sed -e 's|@''HAVE_WINT_T''@|$(HAVE_WINT_T)|g' \
-e 's|@''HAVE_BTOWC''@|$(HAVE_BTOWC)|g' \
diff --git a/modules/wcwidth-factory b/modules/wcwidth-factory
new file mode 100644
index 0000000..b91e76c
--- /dev/null
+++ b/modules/wcwidth-factory
@@ -0,0 +1,24 @@
+Description:
+Factory that produces a wcwidth-like function for a given locale.
+
+Files:
+lib/wcwidth-factory.c
+
+Depends-on:
+wchar
+wcwidth
+
+configure.ac:
+gl_WCHAR_MODULE_INDICATOR([wcwidth-factory])
+
+Makefile.am:
+lib_SOURCES += wcwidth-factory.c
+
+Include:
+
+
+License:
+LGPLv2+
+
+Maintainer:
+all