about summary refs log tree commit diff
path: root/wcsmbs/wcrtomb.c
diff options
context:
space:
mode:
Diffstat (limited to 'wcsmbs/wcrtomb.c')
-rw-r--r--wcsmbs/wcrtomb.c62
1 files changed, 42 insertions, 20 deletions
diff --git a/wcsmbs/wcrtomb.c b/wcsmbs/wcrtomb.c
index 9069fb105c..eb007a69b9 100644
--- a/wcsmbs/wcrtomb.c
+++ b/wcsmbs/wcrtomb.c
@@ -1,6 +1,6 @@
 /* Copyright (C) 1996 Free Software Foundation, Inc.
 This file is part of the GNU C Library.
-Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>
+Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1996.
 
 The GNU C Library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Library General Public License as
@@ -24,46 +24,68 @@ Boston, MA 02111-1307, USA.  */
 #define EILSEQ EINVAL
 #endif
 
+static const wchar_t encoding_mask[] =
+{
+  ~0x7ff, ~0xffff, ~0x1fffff, ~0x3ffffff
+};
+
+static const unsigned char encoding_byte[] =
+{
+  0xc0, 0xe0, 0xf0, 0xf8, 0xfc
+};
 
+/* The state is for this UTF8 encoding not used.  */
 static mbstate_t internal;
 
 size_t
-wcrtomb (s, wc, ps)
-     char *s;
-     wchar_t wc;
-     mbstate_t *ps;
+wcrtomb (char *s, wchar_t wc, mbstate_t *ps)
 {
   char fake[1];
+  size_t written = 0;
 
   if (ps == NULL)
     ps = &internal;
 
-  /*************************************************************\
-  |* This is no complete implementation.  While the multi-byte *|
-  |* character handling is not finished this will do.	       *|
-  \*************************************************************/
-
   if (s == NULL)
     {
       s = fake;
       wc = L'\0';
     }
 
-  if (wc == L'\0')
+  /* Store the UTF8 representation of WC.  */
+  if (wc < 0 || wc > 0x7fffffff)
     {
-      /* FIXME Write any shift sequence to get to *PS == NULL.  */
-      *ps = 0;
-      *s = '\0';
+      /* This is no correct ISO 10646 character.  */
+      errno = EILSEQ;
+      return (size_t) -1;
+    }
+
+  if (wc < 0x80)
+    {
+      /* It's a one byte sequence.  */
+      if (s != NULL)
+	*s = (char) wc;
       return 1;
     }
 
-  /* FIXME For now we don't handle real multi-byte encodings.  */
-  if ((wc & ~0xff) != 0)
+  for (written = 2; written < 6; ++written)
+    if ((wc & encoding_mask[written - 2]) == 0)
+      break;
+
+  if (s != NULL)
     {
-      errno = EILSEQ;
-      return (size_t) -1;
+      size_t cnt = written;
+      s[0] = encoding_byte[cnt - 2];
+
+      --cnt;
+      do
+	{
+	  s[cnt] = 0x80 | (wc & 0x3f);
+	  wc >>= 6;
+	}
+      while (--cnt > 0);
+      s[0] |= wc;
     }
 
-  *s = (char) wc;
-  return 1;
+  return written;
 }