]> Savannah Git Hosting - gnulib.git/commitdiff
mbszero: New module.
authorBruno Haible <bruno@clisp.org>
Sun, 16 Jul 2023 05:30:15 +0000 (07:30 +0200)
committerBruno Haible <bruno@clisp.org>
Sun, 16 Jul 2023 08:29:12 +0000 (10:29 +0200)
* lib/wchar.in.h: Include <string.h>.
(_GL_MBSTATE_INIT_SIZE, _GL_MBSTATE_ZERO_SIZE): New macros.
(mbszero): New declaration.
* lib/mbrtoc16.c: Update comments.
* lib/mbszero.c: New file.
* m4/wchar_h.m4 (gl_WCHAR_H_REQUIRE_DEFAULTS): Initialize
GNULIB_MBSZERO.
* modules/wchar (Depends-on): Add extern-inline.
(Makefile.am): Substitute GNULIB_MBSZERO.
* modules/mbszero: New file.

ChangeLog
lib/mbrtoc16.c
lib/mbszero.c [new file with mode: 0644]
lib/wchar.in.h
m4/wchar_h.m4
modules/mbszero [new file with mode: 0644]
modules/wchar

index 68235627fb8d47b06793a9368f58e55b2c0007f7..151d9b45376768a9c688429c45b6d69f06b60169 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2023-07-16  Bruno Haible  <bruno@clisp.org>
+
+       mbszero: New module.
+       * lib/wchar.in.h: Include <string.h>.
+       (_GL_MBSTATE_INIT_SIZE, _GL_MBSTATE_ZERO_SIZE): New macros.
+       (mbszero): New declaration.
+       * lib/mbrtoc16.c: Update comments.
+       * lib/mbszero.c: New file.
+       * m4/wchar_h.m4 (gl_WCHAR_H_REQUIRE_DEFAULTS): Initialize
+       GNULIB_MBSZERO.
+       * modules/wchar (Depends-on): Add extern-inline.
+       (Makefile.am): Substitute GNULIB_MBSZERO.
+       * modules/mbszero: New file.
+
 2023-07-15  Bruno Haible  <bruno@clisp.org>
 
        mbsinit: Fix module description.
index eb73e7d4471a5fd9774f29da533fe2fb9a883963..1afcde44ccb09ad1de0c9f90e7788a9092d3c5da 100644 (file)
@@ -54,24 +54,26 @@ static_assert (sizeof (mbstate_t) >= 4);
 /* macOS, FreeBSD, NetBSD, OpenBSD, Minix */
 /* On macOS, mbstate_t is defined in <machine/_types.h>.
    It is an opaque aligned 128-byte struct, of which at most the first
-   20 bytes are used (the members are at most: 2x wchar_t, 2x int, 4x char).
+   12 bytes are used.
    For more details, see the __mbsinit implementations in
    Libc-<version>/locale/FreeBSD/
    {ascii,none,euc,mskanji,big5,gb2312,gbk,gb18030,utf8,utf2}.c.  */
 /* On FreeBSD, mbstate_t is defined in src/sys/sys/_types.h.
    It is an opaque aligned 128-byte struct, of which at most the first
-   20 bytes are used (the members are at most: 2x wchar_t, 2x int, 4x char).
+   12 bytes are used.
    For more details, see the __mbsinit implementations in
    src/lib/libc/locale/
    {ascii,none,euc,mskanji,big5,gb2312,gbk,gb18030,utf8}.c.  */
 /* On NetBSD, mbstate_t is defined in src/sys/sys/ansi.h.
    It is an opaque aligned 128-byte struct, of which at most the first
-   24 bytes are used (the members are at most: 3x int, 12x char).
+   28 bytes are used.
    For more details, see the *State types in
-   src/lib/libc/citrus/modules/citrus_*.c.  */
+   src/lib/libc/citrus/modules/citrus_*.c
+   (ignoring citrus_{hz,iso2022,utf7,viqr,zw}.c, since these implement
+   stateful encodings, not usable as locale encodings).  */
 /* On OpenBSD, mbstate_t is defined in src/sys/sys/_types.h.
    It is an opaque aligned 128-byte struct, of which at most the first
-   12 bytes are used (the members are at most: 2x wchar_t, 1x int).
+   12 bytes are used.
    For more details, see src/lib/libc/citrus/citrus_*.c.  */
 /* Minix has borrowed its mbstate_t type and mbrtowc implementation from the
    BSDs.  */
@@ -84,7 +86,7 @@ static_assert (sizeof (mbstate_t) >= 4);
 #elif defined __sun                                       /* Solaris */
 /* On Solaris, mbstate_t is defined in <wchar_impl.h>.
    It is an opaque aligned 24-byte or 32-byte struct, of which at most the first
-   20 bytes are used (the members are at most: 2x wchar_t, 2x int, 4x char).
+   20 or 28 bytes are used.
    For more details, see the *State types in
    illumos-gate/usr/src/lib/libc/port/locale/
    {none,euc,mskanji,big5,gb2312,gbk,gb18030,utf8}.c.  */
diff --git a/lib/mbszero.c b/lib/mbszero.c
new file mode 100644 (file)
index 0000000..6da91c6
--- /dev/null
@@ -0,0 +1,23 @@
+/* Put an mbstate_t into an initial conversion state.
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+   This file is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   This file 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 Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2023.  */
+
+#include <config.h>
+
+#define IN_MBSZERO
+/* Specification and implementation.  */
+#include <wchar.h>
index 2c878ff8157a674e941cbd12e00afa064cc0a112..7d2c5ecd12c6018371f53c79e849e730bdaf7b28 100644 (file)
@@ -232,6 +232,13 @@ _GL_EXTERN_C void free (void *);
 # endif
 #endif
 
+
+#if @GNULIB_MBSZERO@
+/* Get memset().  */
+# include <string.h>
+#endif
+
+
 /* Convert a single-byte character to a wide character.  */
 #if @GNULIB_BTOWC@
 # if @REPLACE_BTOWC@
@@ -315,6 +322,203 @@ _GL_WARN_ON_USE (mbsinit, "mbsinit is unportable - "
 #endif
 
 
+/* Put *PS into an initial state.  */
+#if @GNULIB_MBSZERO@
+/* ISO C 23 ยง 7.31.6.(3) says that zeroing an mbstate_t is a way to put the
+   mbstate_t into an initial state.  However, on many platforms an mbstate_t
+   is large, and it is possible - as an optimization - to get away with zeroing
+   only part of it.  So, instead of
+
+        mbstate_t state = { 0 };
+
+   or
+
+        mbstate_t state;
+        memset (&state, 0, sizeof (mbstate_t));
+
+   we can write this faster code:
+
+        mbstate_t state;
+        mbszero (&state);
+ */
+/* _GL_MBSTATE_INIT_SIZE describes how mbsinit() behaves: It is the number of
+   bytes at the beginning of an mbstate_t that need to be zero, for mbsinit()
+   to return true.
+   _GL_MBSTATE_ZERO_SIZE is the number of bytes at the beginning of an mbstate_t
+   that need to be zero,
+     - for mbsinit() to return true, and
+     - for all other multibyte-aware functions to operate properly.
+   0 < _GL_MBSTATE_INIT_SIZE <= _GL_MBSTATE_ZERO_SIZE <= sizeof (mbstate_t).
+   These values are determined by source code inspection.  */
+# if GNULIB_defined_mbstate_t                             /* AIX, IRIX */
+/* mbstate_t has at least 4 bytes.  They are used as coded in
+   gnulib/lib/mbrtowc.c.  */
+#  define _GL_MBSTATE_INIT_SIZE 1
+/* Note that 4 is not the correct value: it causes test failures.  */
+#  define _GL_MBSTATE_ZERO_SIZE sizeof (mbstate_t)
+# elif __GLIBC__ >= 2                                     /* glibc */
+/* mbstate_t is defined in <bits/types/__mbstate_t.h>.
+   For more details, see glibc/iconv/skeleton.c.  */
+#  define _GL_MBSTATE_INIT_SIZE 4
+#  define _GL_MBSTATE_ZERO_SIZE /* 8 */ sizeof (mbstate_t)
+# elif defined MUSL_LIBC                                  /* musl libc */
+/* mbstate_t is defined in <bits/alltypes.h>.
+   It is an opaque aligned 8-byte struct, of which at most the first
+   4 bytes are used.
+   For more details, see src/multibyte/mbrtowc.c.  */
+#  define _GL_MBSTATE_INIT_SIZE 4
+#  define _GL_MBSTATE_ZERO_SIZE 4
+# elif defined __APPLE__ && defined __MACH__              /* macOS */
+/* On macOS, mbstate_t is defined in <machine/_types.h>.
+   It is an opaque aligned 128-byte struct, of which at most the first
+   12 bytes are used.
+   For more details, see the __mbsinit implementations in
+   Libc-<version>/locale/FreeBSD/
+   {ascii,none,euc,mskanji,big5,gb2312,gbk,gb18030,utf8,utf2}.c.  */
+/* File       INIT_SIZE  ZERO_SIZE
+   ascii.c        0          0
+   none.c         0          0
+   euc.c         12         12
+   mskanji.c      4          4
+   big5.c         4          4
+   gb2312.c       4          6
+   gbk.c          4          4
+   gb18030.c      4          8
+   utf8.c         8         10
+   utf2.c         8         12 */
+#  define _GL_MBSTATE_INIT_SIZE 12
+#  define _GL_MBSTATE_ZERO_SIZE 12
+# elif defined __FreeBSD__                                /* FreeBSD */
+/* On FreeBSD, mbstate_t is defined in src/sys/sys/_types.h.
+   It is an opaque aligned 128-byte struct, of which at most the first
+   12 bytes are used.
+   For more details, see the __mbsinit implementations in
+   src/lib/libc/locale/
+   {ascii,none,euc,mskanji,big5,gb2312,gbk,gb18030,utf8}.c.  */
+/* File       INIT_SIZE  ZERO_SIZE
+   ascii.c        0          0
+   none.c         0          0
+   euc.c         12         12
+   mskanji.c      4          4
+   big5.c         4          4
+   gb2312.c       4          6
+   gbk.c          4          4
+   gb18030.c      4          8
+   utf8.c         8         12 */
+#  define _GL_MBSTATE_INIT_SIZE 12
+#  define _GL_MBSTATE_ZERO_SIZE 12
+# elif defined __NetBSD__                                 /* NetBSD */
+/* On NetBSD, mbstate_t is defined in src/sys/sys/ansi.h.
+   It is an opaque aligned 128-byte struct, of which at most the first
+   28 bytes are used.
+   For more details, see the *State types in
+   src/lib/libc/citrus/modules/citrus_*.c
+   (ignoring citrus_{hz,iso2022,utf7,viqr,zw}.c, since these implement
+   stateful encodings, not usable as locale encodings).  */
+/* File                                ZERO_SIZE
+   citrus/citrus_none.c                    0
+   citrus/modules/citrus_euc.c             8
+   citrus/modules/citrus_euctw.c           8
+   citrus/modules/citrus_mskanji.c         8
+   citrus/modules/citrus_big5.c            8
+   citrus/modules/citrus_gbk2k.c           8
+   citrus/modules/citrus_dechanyu.c        8
+   citrus/modules/citrus_johab.c           6
+   citrus/modules/citrus_utf8.c           12 */
+/* But 12 is not the correct value: we get test failures for values < 28.  */
+#  define _GL_MBSTATE_INIT_SIZE 28
+#  define _GL_MBSTATE_ZERO_SIZE 28
+# elif defined __OpenBSD__                                /* OpenBSD */
+/* On OpenBSD, mbstate_t is defined in src/sys/sys/_types.h.
+   It is an opaque aligned 128-byte struct, of which at most the first
+   12 bytes are used.
+   For more details, see src/lib/libc/citrus/citrus_*.c.  */
+/* File           INIT_SIZE  ZERO_SIZE
+   citrus_none.c      0          0
+   citrus_utf8.c     12         12 */
+#  define _GL_MBSTATE_INIT_SIZE 12
+#  define _GL_MBSTATE_ZERO_SIZE 12
+# elif defined __minix                                    /* Minix */
+/* On Minix, mbstate_t is defined in sys/sys/ansi.h.
+   It is an opaque aligned 128-byte struct.
+   For more details, see the *State types in
+   lib/libc/citrus/citrus_*.c.  */
+/* File           INIT_SIZE  ZERO_SIZE
+   citrus_none.c      0          0 */
+#  define _GL_MBSTATE_INIT_SIZE 1
+#  define _GL_MBSTATE_ZERO_SIZE 1
+# elif defined __sun                                      /* Solaris */
+/* On Solaris, mbstate_t is defined in <wchar_impl.h>.
+   It is an opaque aligned 24-byte or 32-byte struct, of which at most the first
+   20 or 28 bytes are used.
+   For more details, see the *State types in
+   illumos-gate/usr/src/lib/libc/port/locale/
+   {none,euc,mskanji,big5,gb2312,gbk,gb18030,utf8}.c.  */
+/* File       INIT_SIZE  ZERO_SIZE
+   none.c         0          0
+   euc.c         12         12
+   mskanji.c      4          4
+   big5.c         4          4
+   gb2312.c       4          6
+   gbk.c          4          4
+   gb18030.c      4          8
+   utf8.c        12         12 */
+/* But 12 is not the correct value: we get test failures
+     - in OpenIndiana and OmniOS: for values < 16,
+     - in Solaris 10 and 11: for values < 20 (in 32-bit mode)
+       or < 28 (in 64-bit mode).  */
+#  if defined _LP64
+#   define _GL_MBSTATE_INIT_SIZE 28
+#   define _GL_MBSTATE_ZERO_SIZE 28
+#  else
+#   define _GL_MBSTATE_INIT_SIZE 20
+#   define _GL_MBSTATE_ZERO_SIZE 20
+#  endif
+# elif defined __CYGWIN__                                 /* Cygwin */
+/* On Cygwin, mbstate_t is defined in <sys/_types.h>.
+   For more details, see newlib/libc/stdlib/mbtowc_r.c and
+   winsup/cygwin/strfuncs.cc.  */
+#  define _GL_MBSTATE_INIT_SIZE 4
+#  define _GL_MBSTATE_ZERO_SIZE 8
+# elif defined _WIN32 && !defined __CYGWIN__              /* Native Windows.  */
+/* MSVC defines 'mbstate_t' as an aligned 8-byte struct.
+   On mingw, 'mbstate_t' is sometimes defined as 'int', sometimes defined
+   as an aligned 8-byte struct, of which the first 4 bytes matter.  */
+#  define _GL_MBSTATE_INIT_SIZE sizeof (mbstate_t)
+#  define _GL_MBSTATE_ZERO_SIZE sizeof (mbstate_t)
+# elif defined __ANDROID__                                /* Android */
+/* Android defines 'mbstate_t' in <bits/mbstate_t.h>.
+   It is an opaque 4-byte or 8-byte struct.
+   For more details, see
+   bionic/libc/private/bionic_mbstate.h
+   bionic/libc/bionic/mbrtoc32.cpp
+   bionic/libc/bionic/mbrtoc16.cpp
+ */
+#  define _GL_MBSTATE_INIT_SIZE 4
+#  define _GL_MBSTATE_ZERO_SIZE 4
+# else
+/* On platforms where we don't know how the multibyte functions behave, use
+   these safe values.  */
+#  define _GL_MBSTATE_INIT_SIZE sizeof (mbstate_t)
+#  define _GL_MBSTATE_ZERO_SIZE sizeof (mbstate_t)
+# endif
+_GL_BEGIN_C_LINKAGE
+# if defined IN_MBSZERO
+_GL_EXTERN_INLINE
+# else
+_GL_INLINE
+# endif
+_GL_ARG_NONNULL ((1)) void
+mbszero (mbstate_t *ps)
+{
+  memset (ps, 0, _GL_MBSTATE_ZERO_SIZE);
+}
+_GL_END_C_LINKAGE
+_GL_CXXALIAS_SYS (mbszero, void, (mbstate_t *ps));
+_GL_CXXALIASWARN (mbszero);
+#endif
+
+
 /* Convert a multibyte character to a wide character.  */
 #if @GNULIB_MBRTOWC@
 # if @REPLACE_MBRTOWC@
index 442932be44df75567afb3ae3b5eaf86bb3996022..31f5b0794d97805247af77e91600024d406e1316 100644 (file)
@@ -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 60
+# wchar_h.m4 serial 61
 
 AC_DEFUN_ONCE([gl_WCHAR_H],
 [
@@ -147,6 +147,7 @@ AC_DEFUN([gl_WCHAR_H_REQUIRE_DEFAULTS],
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_BTOWC])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_WCTOB])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MBSINIT])
+    gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MBSZERO])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MBRTOWC])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MBRLEN])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MBSRTOWCS])
diff --git a/modules/mbszero b/modules/mbszero
new file mode 100644 (file)
index 0000000..002fa75
--- /dev/null
@@ -0,0 +1,29 @@
+Description:
+mbszero() function: put an mbstate_t into an initial conversion state.
+
+Files:
+lib/mbszero.c
+m4/mbstate_t.m4
+m4/mbrtowc.m4
+m4/musl.m4
+
+Depends-on:
+wchar
+
+configure.ac:
+AC_REQUIRE([AC_TYPE_MBSTATE_T])
+gl_MBSTATE_T_BROKEN
+gl_MUSL_LIBC
+gl_WCHAR_MODULE_INDICATOR([mbszero])
+
+Makefile.am:
+lib_SOURCES += mbszero.c
+
+Include:
+<wchar.h>
+
+License:
+LGPLv2+
+
+Maintainer:
+all
index 6a17e53034955153b0f5caf91d128b1686d5bf21..ebdd0ece614c65e5e48a8768e9b0ae5804c5f430 100644 (file)
@@ -13,6 +13,7 @@ include_next
 snippet/arg-nonnull
 snippet/c++defs
 snippet/warn-on-use
+extern-inline
 inttypes-incomplete
 stddef
 stdlib
@@ -42,6 +43,7 @@ wchar.h: wchar.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H)
              -e 's/@''GNULIB_BTOWC''@/$(GNULIB_BTOWC)/g' \
              -e 's/@''GNULIB_WCTOB''@/$(GNULIB_WCTOB)/g' \
              -e 's/@''GNULIB_MBSINIT''@/$(GNULIB_MBSINIT)/g' \
+             -e 's/@''GNULIB_MBSZERO''@/$(GNULIB_MBSZERO)/g' \
              -e 's/@''GNULIB_MBRTOWC''@/$(GNULIB_MBRTOWC)/g' \
              -e 's/@''GNULIB_MBRLEN''@/$(GNULIB_MBRLEN)/g' \
              -e 's/@''GNULIB_MBSRTOWCS''@/$(GNULIB_MBSRTOWCS)/g' \