From 82e60758d286043fbeca68ac04f782bc46b4bc34 Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Tue, 22 Feb 2011 14:01:29 +0100
Subject: [PATCH] New module 'mbtowc'.

* lib/stdlib.in.h (mbtowc): New declaration.
* lib/mbtowc.c: New file.
* lib/mbtowc-impl.h: New file, from libutf8 with modifications
* m4/mbtowc.m4: New file.
* m4/stdlib_h.m4 (gl_STDLIB_H_DEFAULTS): Initialize GNULIB_MBTOWC,
REPLACE_MBTOWC.
* modules/stdlib (Makefile.am): Substitute GNULIB_MBTOWC,
REPLACE_MBTOWC.
* modules/mbtowc: New file.
* tests/test-stdlib-c++.cc: Test signature of mbtowc.
* doc/posix-functions/mbtowc.texi: Mention the new module.
* modules/btowc (Depends-on): Add mbtowc.
---
 ChangeLog                       | 16 ++++++++++++
 doc/posix-functions/mbtowc.texi |  2 +-
 lib/mbtowc-impl.h               | 44 +++++++++++++++++++++++++++++++++
 lib/mbtowc.c                    | 26 +++++++++++++++++++
 lib/stdlib.in.h                 | 15 +++++++++++
 m4/mbtowc.m4                    | 23 +++++++++++++++++
 m4/stdlib_h.m4                  |  4 ++-
 modules/btowc                   |  1 +
 modules/mbtowc                  | 26 +++++++++++++++++++
 modules/stdlib                  |  2 ++
 tests/test-stdlib-c++.cc        |  5 ++++
 11 files changed, 162 insertions(+), 2 deletions(-)
 create mode 100644 lib/mbtowc-impl.h
 create mode 100644 lib/mbtowc.c
 create mode 100644 m4/mbtowc.m4
 create mode 100644 modules/mbtowc

diff --git a/ChangeLog b/ChangeLog
index f1d7070faf..bfda52a39c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2011-02-22  Bruno Haible  <bruno@clisp.org>
+
+	New module 'mbtowc'.
+	* lib/stdlib.in.h (mbtowc): New declaration.
+	* lib/mbtowc.c: New file.
+	* lib/mbtowc-impl.h: New file, from libutf8 with modifications.
+	* m4/mbtowc.m4: New file.
+	* m4/stdlib_h.m4 (gl_STDLIB_H_DEFAULTS): Initialize GNULIB_MBTOWC,
+	REPLACE_MBTOWC.
+	* modules/stdlib (Makefile.am): Substitute GNULIB_MBTOWC,
+	REPLACE_MBTOWC.
+	* modules/mbtowc: New file.
+	* tests/test-stdlib-c++.cc: Test signature of mbtowc.
+	* doc/posix-functions/mbtowc.texi: Mention the new module.
+	* modules/btowc (Depends-on): Add mbtowc.
+
 2011-02-22  Bruno Haible  <bruno@clisp.org>
 
 	wcrtomb: Add more tests for native Windows platforms.
diff --git a/doc/posix-functions/mbtowc.texi b/doc/posix-functions/mbtowc.texi
index 1e90906c5c..2359480be7 100644
--- a/doc/posix-functions/mbtowc.texi
+++ b/doc/posix-functions/mbtowc.texi
@@ -4,7 +4,7 @@
 
 POSIX specification:@* @url{http://www.opengroup.org/onlinepubs/9699919799/functions/mbtowc.html}
 
-Gnulib module: ---
+Gnulib module: mbtowc
 
 Portability problems fixed by Gnulib:
 @itemize
diff --git a/lib/mbtowc-impl.h b/lib/mbtowc-impl.h
new file mode 100644
index 0000000000..1645eb5dcd
--- /dev/null
+++ b/lib/mbtowc-impl.h
@@ -0,0 +1,44 @@
+/* Convert multibyte character to wide character.
+   Copyright (C) 2011 Free Software Foundation, Inc.
+   Written by Bruno Haible <bruno@clisp.org>, 2011.
+
+   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 <http://www.gnu.org/licenses/>.  */
+
+/* We don't need a static internal state, because the encoding is not state
+   dependent, and when mbrtowc returns (size_t)(-2). we throw the result
+   away. */
+
+int
+mbtowc (wchar_t *pwc, const char *s, size_t n)
+{
+  if (s == NULL)
+    return 0;
+  else
+    {
+      mbstate_t state;
+      wchar_t wc;
+      size_t result;
+
+      memset (&state, 0, sizeof (mbstate_t));
+      result = mbrtowc (&wc, s, n, &state);
+      if (result == (size_t)-1 || result == (size_t)-2)
+        {
+          errno = EILSEQ;
+          return -1;
+        }
+      if (pwc != NULL)
+        *pwc = wc;
+      return (wc == 0 ? 0 : result);
+    }
+}
diff --git a/lib/mbtowc.c b/lib/mbtowc.c
new file mode 100644
index 0000000000..b3848a1249
--- /dev/null
+++ b/lib/mbtowc.c
@@ -0,0 +1,26 @@
+/* Convert multibyte character to wide character.
+   Copyright (C) 2011 Free Software Foundation, Inc.
+   Written by Bruno Haible <bruno@clisp.org>, 2011.
+
+   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 <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <errno.h>
+#include <string.h>
+#include <wchar.h>
+
+#include "mbtowc-impl.h"
diff --git a/lib/stdlib.in.h b/lib/stdlib.in.h
index 62d18c6281..91eb4d68c1 100644
--- a/lib/stdlib.in.h
+++ b/lib/stdlib.in.h
@@ -274,6 +274,21 @@ _GL_WARN_ON_USE (malloc, "malloc is not POSIX compliant everywhere - "
                  "use gnulib module malloc-posix for portability");
 #endif
 
+/* Convert a multibyte character to a wide character.  */
+#if @GNULIB_MBTOWC@
+# if @REPLACE_MBTOWC@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef mbtowc
+#   define mbtowc rpl_mbtowc
+#  endif
+_GL_FUNCDECL_RPL (mbtowc, int, (wchar_t *pwc, const char *s, size_t n));
+_GL_CXXALIAS_RPL (mbtowc, int, (wchar_t *pwc, const char *s, size_t n));
+# else
+_GL_CXXALIAS_SYS (mbtowc, int, (wchar_t *pwc, const char *s, size_t n));
+# endif
+_GL_CXXALIASWARN (mbtowc);
+#endif
+
 #if @GNULIB_MKDTEMP@
 /* Create a unique temporary directory from TEMPLATE.
    The last six characters of TEMPLATE must be "XXXXXX";
diff --git a/m4/mbtowc.m4 b/m4/mbtowc.m4
new file mode 100644
index 0000000000..9215892f6f
--- /dev/null
+++ b/m4/mbtowc.m4
@@ -0,0 +1,23 @@
+# mbtowc.m4 serial 1
+dnl Copyright (C) 2011 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_MBTOWC],
+[
+  AC_REQUIRE([gl_STDLIB_H_DEFAULTS])
+
+  if false; then
+    REPLACE_MBTOWC=1
+  fi
+  if test $REPLACE_MBTOWC = 1; then
+    AC_LIBOBJ([mbtowc])
+    gl_PREREQ_MBTOWC
+  fi
+])
+
+# Prerequisites of lib/mbtowc.c.
+AC_DEFUN([gl_PREREQ_MBTOWC], [
+  :
+])
diff --git a/m4/stdlib_h.m4 b/m4/stdlib_h.m4
index d28b552e90..7fa7d311db 100644
--- a/m4/stdlib_h.m4
+++ b/m4/stdlib_h.m4
@@ -1,4 +1,4 @@
-# stdlib_h.m4 serial 36
+# stdlib_h.m4 serial 37
 dnl Copyright (C) 2007-2011 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -44,6 +44,7 @@ AC_DEFUN([gl_STDLIB_H_DEFAULTS],
   GNULIB_GETSUBOPT=0;     AC_SUBST([GNULIB_GETSUBOPT])
   GNULIB_GRANTPT=0;       AC_SUBST([GNULIB_GRANTPT])
   GNULIB_MALLOC_POSIX=0;  AC_SUBST([GNULIB_MALLOC_POSIX])
+  GNULIB_MBTOWC=0;        AC_SUBST([GNULIB_MBTOWC])
   GNULIB_MKDTEMP=0;       AC_SUBST([GNULIB_MKDTEMP])
   GNULIB_MKOSTEMP=0;      AC_SUBST([GNULIB_MKOSTEMP])
   GNULIB_MKOSTEMPS=0;     AC_SUBST([GNULIB_MKOSTEMPS])
@@ -91,6 +92,7 @@ AC_DEFUN([gl_STDLIB_H_DEFAULTS],
   REPLACE_CALLOC=0;          AC_SUBST([REPLACE_CALLOC])
   REPLACE_CANONICALIZE_FILE_NAME=0;  AC_SUBST([REPLACE_CANONICALIZE_FILE_NAME])
   REPLACE_MALLOC=0;          AC_SUBST([REPLACE_MALLOC])
+  REPLACE_MBTOWC=0;          AC_SUBST([REPLACE_MBTOWC])
   REPLACE_MKSTEMP=0;         AC_SUBST([REPLACE_MKSTEMP])
   REPLACE_PUTENV=0;          AC_SUBST([REPLACE_PUTENV])
   REPLACE_REALLOC=0;         AC_SUBST([REPLACE_REALLOC])
diff --git a/modules/btowc b/modules/btowc
index 6b08366bfa..10c5f3f9a5 100644
--- a/modules/btowc
+++ b/modules/btowc
@@ -8,6 +8,7 @@ m4/locale-fr.m4
 
 Depends-on:
 wchar
+mbtowc
 
 configure.ac:
 gl_FUNC_BTOWC
diff --git a/modules/mbtowc b/modules/mbtowc
new file mode 100644
index 0000000000..7e287680cd
--- /dev/null
+++ b/modules/mbtowc
@@ -0,0 +1,26 @@
+Description:
+mbtowc() function: convert multibyte character to wide character.
+
+Files:
+lib/mbtowc.c
+lib/mbtowc-impl.h
+m4/mbtowc.m4
+
+Depends-on:
+stdlib
+mbrtowc
+
+configure.ac:
+gl_FUNC_MBTOWC
+gl_STDLIB_MODULE_INDICATOR([mbtowc])
+
+Makefile.am:
+
+Include:
+<stdlib.h>
+
+License:
+LGPLv2+
+
+Maintainer:
+Bruno Haible
diff --git a/modules/stdlib b/modules/stdlib
index 7d7e769a2a..c870e4d9f9 100644
--- a/modules/stdlib
+++ b/modules/stdlib
@@ -36,6 +36,7 @@ stdlib.h: stdlib.in.h $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
 	      -e 's|@''GNULIB_GETSUBOPT''@|$(GNULIB_GETSUBOPT)|g' \
 	      -e 's|@''GNULIB_GRANTPT''@|$(GNULIB_GRANTPT)|g' \
 	      -e 's|@''GNULIB_MALLOC_POSIX''@|$(GNULIB_MALLOC_POSIX)|g' \
+	      -e 's|@''GNULIB_MBTOWC''@|$(GNULIB_MBTOWC)|g' \
 	      -e 's|@''GNULIB_MKDTEMP''@|$(GNULIB_MKDTEMP)|g' \
 	      -e 's|@''GNULIB_MKOSTEMP''@|$(GNULIB_MKOSTEMP)|g' \
 	      -e 's|@''GNULIB_MKOSTEMPS''@|$(GNULIB_MKOSTEMPS)|g' \
@@ -82,6 +83,7 @@ stdlib.h: stdlib.in.h $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
 	      -e 's|@''REPLACE_CALLOC''@|$(REPLACE_CALLOC)|g' \
 	      -e 's|@''REPLACE_CANONICALIZE_FILE_NAME''@|$(REPLACE_CANONICALIZE_FILE_NAME)|g' \
 	      -e 's|@''REPLACE_MALLOC''@|$(REPLACE_MALLOC)|g' \
+	      -e 's|@''REPLACE_MBTOWC''@|$(REPLACE_MBTOWC)|g' \
 	      -e 's|@''REPLACE_MKSTEMP''@|$(REPLACE_MKSTEMP)|g' \
 	      -e 's|@''REPLACE_PUTENV''@|$(REPLACE_PUTENV)|g' \
 	      -e 's|@''REPLACE_REALLOC''@|$(REPLACE_REALLOC)|g' \
diff --git a/tests/test-stdlib-c++.cc b/tests/test-stdlib-c++.cc
index b8595f5637..419e547002 100644
--- a/tests/test-stdlib-c++.cc
+++ b/tests/test-stdlib-c++.cc
@@ -60,6 +60,11 @@ SIGNATURE_CHECK (GNULIB_NAMESPACE::grantpt, int, (int));
 SIGNATURE_CHECK (GNULIB_NAMESPACE::malloc, void *, (size_t));
 #endif
 
+#if GNULIB_TEST_MBTOWC
+SIGNATURE_CHECK (GNULIB_NAMESPACE::mbtowc, int,
+                 (wchar_t *, const char *, size_t));
+#endif
+
 #if GNULIB_TEST_MKDTEMP
 SIGNATURE_CHECK (GNULIB_NAMESPACE::mkdtemp, char *, (char *));
 #endif
-- 
2.39.5