Blame gnulib/lib/mbrtowc.c

Packit Service a2ae7a
/* Convert multibyte character to wide character.
Packit Service a2ae7a
   Copyright (C) 1999-2002, 2005-2019 Free Software Foundation, Inc.
Packit Service a2ae7a
   Written by Bruno Haible <bruno@clisp.org>, 2008.
Packit Service a2ae7a
Packit Service a2ae7a
   This program is free software: you can redistribute it and/or modify
Packit Service a2ae7a
   it under the terms of the GNU Lesser General Public License as published by
Packit Service a2ae7a
   the Free Software Foundation; either version 2.1 of the License, or
Packit Service a2ae7a
   (at your option) any later version.
Packit Service a2ae7a
Packit Service a2ae7a
   This program is distributed in the hope that it will be useful,
Packit Service a2ae7a
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service a2ae7a
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service a2ae7a
   GNU Lesser General Public License for more details.
Packit Service a2ae7a
Packit Service a2ae7a
   You should have received a copy of the GNU Lesser General Public License
Packit Service a2ae7a
   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
Packit Service a2ae7a
Packit Service a2ae7a
#include <config.h>
Packit Service a2ae7a
Packit Service a2ae7a
/* Specification.  */
Packit Service a2ae7a
#include <wchar.h>
Packit Service a2ae7a
Packit Service a2ae7a
#if C_LOCALE_MAYBE_EILSEQ
Packit Service a2ae7a
# include "hard-locale.h"
Packit Service a2ae7a
# include <locale.h>
Packit Service a2ae7a
#endif
Packit Service a2ae7a
Packit Service a2ae7a
#if GNULIB_defined_mbstate_t
Packit Service a2ae7a
/* Implement mbrtowc() on top of mbtowc().  */
Packit Service a2ae7a
Packit Service a2ae7a
# include <errno.h>
Packit Service a2ae7a
# include <stdlib.h>
Packit Service a2ae7a
Packit Service a2ae7a
# include "localcharset.h"
Packit Service a2ae7a
# include "streq.h"
Packit Service a2ae7a
# include "verify.h"
Packit Service a2ae7a
Packit Service a2ae7a
# ifndef FALLTHROUGH
Packit Service a2ae7a
#  if __GNUC__ < 7
Packit Service a2ae7a
#   define FALLTHROUGH ((void) 0)
Packit Service a2ae7a
#  else
Packit Service a2ae7a
#   define FALLTHROUGH __attribute__ ((__fallthrough__))
Packit Service a2ae7a
#  endif
Packit Service a2ae7a
# endif
Packit Service a2ae7a
Packit Service a2ae7a
/* Returns a classification of special values of the encoding of the current
Packit Service a2ae7a
   locale.  */
Packit Service a2ae7a
typedef enum {
Packit Service a2ae7a
  enc_other,      /* other */
Packit Service a2ae7a
  enc_utf8,       /* UTF-8 */
Packit Service a2ae7a
  enc_eucjp,      /* EUC-JP */
Packit Service a2ae7a
  enc_94,         /* EUC-KR, GB2312, BIG5 */
Packit Service a2ae7a
  enc_euctw,      /* EUC-TW */
Packit Service a2ae7a
  enc_gb18030,    /* GB18030 */
Packit Service a2ae7a
  enc_sjis        /* SJIS */
Packit Service a2ae7a
} enc_t;
Packit Service a2ae7a
static inline enc_t
Packit Service a2ae7a
locale_enc (void)
Packit Service a2ae7a
{
Packit Service a2ae7a
  const char *encoding = locale_charset ();
Packit Service a2ae7a
  if (STREQ_OPT (encoding, "UTF-8", 'U', 'T', 'F', '-', '8', 0, 0, 0, 0))
Packit Service a2ae7a
    return enc_utf8;
Packit Service a2ae7a
  if (STREQ_OPT (encoding, "EUC-JP", 'E', 'U', 'C', '-', 'J', 'P', 0, 0, 0))
Packit Service a2ae7a
    return enc_eucjp;
Packit Service a2ae7a
  if (STREQ_OPT (encoding, "EUC-KR", 'E', 'U', 'C', '-', 'K', 'R', 0, 0, 0)
Packit Service a2ae7a
      || STREQ_OPT (encoding, "GB2312", 'G', 'B', '2', '3', '1', '2', 0, 0, 0)
Packit Service a2ae7a
      || STREQ_OPT (encoding, "BIG5", 'B', 'I', 'G', '5', 0, 0, 0, 0, 0))
Packit Service a2ae7a
    return enc_94;
Packit Service a2ae7a
  if (STREQ_OPT (encoding, "EUC-TW", 'E', 'U', 'C', '-', 'T', 'W', 0, 0, 0))
Packit Service a2ae7a
    return enc_euctw;
Packit Service a2ae7a
  if (STREQ_OPT (encoding, "GB18030", 'G', 'B', '1', '8', '0', '3', '0', 0, 0))
Packit Service a2ae7a
    return enc_gb18030;
Packit Service a2ae7a
  if (STREQ_OPT (encoding, "SJIS", 'S', 'J', 'I', 'S', 0, 0, 0, 0, 0))
Packit Service a2ae7a
    return enc_sjis;
Packit Service a2ae7a
  return enc_other;
Packit Service a2ae7a
}
Packit Service a2ae7a
Packit Service a2ae7a
#if GNULIB_WCHAR_SINGLE
Packit Service a2ae7a
/* When we know that the locale does not change, provide a speedup by
Packit Service a2ae7a
   caching the value of locale_enc.  */
Packit Service a2ae7a
static int cached_locale_enc = -1;
Packit Service a2ae7a
static inline enc_t
Packit Service a2ae7a
locale_enc_cached (void)
Packit Service a2ae7a
{
Packit Service a2ae7a
  if (cached_locale_enc < 0)
Packit Service a2ae7a
    cached_locale_enc = locale_enc ();
Packit Service a2ae7a
  return cached_locale_enc;
Packit Service a2ae7a
}
Packit Service a2ae7a
#else
Packit Service a2ae7a
/* By default, don't make assumptions, hence no caching.  */
Packit Service a2ae7a
# define locale_enc_cached locale_enc
Packit Service a2ae7a
#endif
Packit Service a2ae7a
Packit Service a2ae7a
verify (sizeof (mbstate_t) >= 4);
Packit Service a2ae7a
Packit Service a2ae7a
static char internal_state[4];
Packit Service a2ae7a
Packit Service a2ae7a
size_t
Packit Service a2ae7a
mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)
Packit Service a2ae7a
{
Packit Service a2ae7a
  char *pstate = (char *)ps;
Packit Service a2ae7a
Packit Service a2ae7a
  if (s == NULL)
Packit Service a2ae7a
    {
Packit Service a2ae7a
      pwc = NULL;
Packit Service a2ae7a
      s = "";
Packit Service a2ae7a
      n = 1;
Packit Service a2ae7a
    }
Packit Service a2ae7a
Packit Service a2ae7a
  if (n == 0)
Packit Service a2ae7a
    return (size_t)(-2);
Packit Service a2ae7a
Packit Service a2ae7a
  /* Here n > 0.  */
Packit Service a2ae7a
Packit Service a2ae7a
  if (pstate == NULL)
Packit Service a2ae7a
    pstate = internal_state;
Packit Service a2ae7a
Packit Service a2ae7a
  {
Packit Service a2ae7a
    size_t nstate = pstate[0];
Packit Service a2ae7a
    char buf[4];
Packit Service a2ae7a
    const char *p;
Packit Service a2ae7a
    size_t m;
Packit Service a2ae7a
Packit Service a2ae7a
    switch (nstate)
Packit Service a2ae7a
      {
Packit Service a2ae7a
      case 0:
Packit Service a2ae7a
        p = s;
Packit Service a2ae7a
        m = n;
Packit Service a2ae7a
        break;
Packit Service a2ae7a
      case 3:
Packit Service a2ae7a
        buf[2] = pstate[3];
Packit Service a2ae7a
        FALLTHROUGH;
Packit Service a2ae7a
      case 2:
Packit Service a2ae7a
        buf[1] = pstate[2];
Packit Service a2ae7a
        FALLTHROUGH;
Packit Service a2ae7a
      case 1:
Packit Service a2ae7a
        buf[0] = pstate[1];
Packit Service a2ae7a
        p = buf;
Packit Service a2ae7a
        m = nstate;
Packit Service a2ae7a
        buf[m++] = s[0];
Packit Service a2ae7a
        if (n >= 2 && m < 4)
Packit Service a2ae7a
          {
Packit Service a2ae7a
            buf[m++] = s[1];
Packit Service a2ae7a
            if (n >= 3 && m < 4)
Packit Service a2ae7a
              buf[m++] = s[2];
Packit Service a2ae7a
          }
Packit Service a2ae7a
        break;
Packit Service a2ae7a
      default:
Packit Service a2ae7a
        errno = EINVAL;
Packit Service a2ae7a
        return (size_t)(-1);
Packit Service a2ae7a
      }
Packit Service a2ae7a
Packit Service a2ae7a
    /* Here m > 0.  */
Packit Service a2ae7a
Packit Service a2ae7a
# if __GLIBC__ || defined __UCLIBC__
Packit Service a2ae7a
    /* Work around bug <https://sourceware.org/bugzilla/show_bug.cgi?id=9674> */
Packit Service a2ae7a
    mbtowc (NULL, NULL, 0);
Packit Service a2ae7a
# endif
Packit Service a2ae7a
    {
Packit Service a2ae7a
      int res = mbtowc (pwc, p, m);
Packit Service a2ae7a
Packit Service a2ae7a
      if (res >= 0)
Packit Service a2ae7a
        {
Packit Service a2ae7a
          if (pwc != NULL && ((*pwc == 0) != (res == 0)))
Packit Service a2ae7a
            abort ();
Packit Service a2ae7a
          if (nstate >= (res > 0 ? res : 1))
Packit Service a2ae7a
            abort ();
Packit Service a2ae7a
          res -= nstate;
Packit Service a2ae7a
          pstate[0] = 0;
Packit Service a2ae7a
          return res;
Packit Service a2ae7a
        }
Packit Service a2ae7a
Packit Service a2ae7a
      /* mbtowc does not distinguish between invalid and incomplete multibyte
Packit Service a2ae7a
         sequences.  But mbrtowc needs to make this distinction.
Packit Service a2ae7a
         There are two possible approaches:
Packit Service a2ae7a
           - Use iconv() and its return value.
Packit Service a2ae7a
           - Use built-in knowledge about the possible encodings.
Packit Service a2ae7a
         Given the low quality of implementation of iconv() on the systems that
Packit Service a2ae7a
         lack mbrtowc(), we use the second approach.
Packit Service a2ae7a
         The possible encodings are:
Packit Service a2ae7a
           - 8-bit encodings,
Packit Service a2ae7a
           - EUC-JP, EUC-KR, GB2312, EUC-TW, BIG5, GB18030, SJIS,
Packit Service a2ae7a
           - UTF-8.
Packit Service a2ae7a
         Use specialized code for each.  */
Packit Service a2ae7a
      if (m >= 4 || m >= MB_CUR_MAX)
Packit Service a2ae7a
        goto invalid;
Packit Service a2ae7a
      /* Here MB_CUR_MAX > 1 and 0 < m < 4.  */
Packit Service a2ae7a
      switch (locale_enc_cached ())
Packit Service a2ae7a
        {
Packit Service a2ae7a
        case enc_utf8: /* UTF-8 */
Packit Service a2ae7a
          {
Packit Service a2ae7a
            /* Cf. unistr/u8-mblen.c.  */
Packit Service a2ae7a
            unsigned char c = (unsigned char) p[0];
Packit Service a2ae7a
Packit Service a2ae7a
            if (c >= 0xc2)
Packit Service a2ae7a
              {
Packit Service a2ae7a
                if (c < 0xe0)
Packit Service a2ae7a
                  {
Packit Service a2ae7a
                    if (m == 1)
Packit Service a2ae7a
                      goto incomplete;
Packit Service a2ae7a
                  }
Packit Service a2ae7a
                else if (c < 0xf0)
Packit Service a2ae7a
                  {
Packit Service a2ae7a
                    if (m == 1)
Packit Service a2ae7a
                      goto incomplete;
Packit Service a2ae7a
                    if (m == 2)
Packit Service a2ae7a
                      {
Packit Service a2ae7a
                        unsigned char c2 = (unsigned char) p[1];
Packit Service a2ae7a
Packit Service a2ae7a
                        if ((c2 ^ 0x80) < 0x40
Packit Service a2ae7a
                            && (c >= 0xe1 || c2 >= 0xa0)
Packit Service a2ae7a
                            && (c != 0xed || c2 < 0xa0))
Packit Service a2ae7a
                          goto incomplete;
Packit Service a2ae7a
                      }
Packit Service a2ae7a
                  }
Packit Service a2ae7a
                else if (c <= 0xf4)
Packit Service a2ae7a
                  {
Packit Service a2ae7a
                    if (m == 1)
Packit Service a2ae7a
                      goto incomplete;
Packit Service a2ae7a
                    else /* m == 2 || m == 3 */
Packit Service a2ae7a
                      {
Packit Service a2ae7a
                        unsigned char c2 = (unsigned char) p[1];
Packit Service a2ae7a
Packit Service a2ae7a
                        if ((c2 ^ 0x80) < 0x40
Packit Service a2ae7a
                            && (c >= 0xf1 || c2 >= 0x90)
Packit Service a2ae7a
                            && (c < 0xf4 || (c == 0xf4 && c2 < 0x90)))
Packit Service a2ae7a
                          {
Packit Service a2ae7a
                            if (m == 2)
Packit Service a2ae7a
                              goto incomplete;
Packit Service a2ae7a
                            else /* m == 3 */
Packit Service a2ae7a
                              {
Packit Service a2ae7a
                                unsigned char c3 = (unsigned char) p[2];
Packit Service a2ae7a
Packit Service a2ae7a
                                if ((c3 ^ 0x80) < 0x40)
Packit Service a2ae7a
                                  goto incomplete;
Packit Service a2ae7a
                              }
Packit Service a2ae7a
                          }
Packit Service a2ae7a
                      }
Packit Service a2ae7a
                  }
Packit Service a2ae7a
              }
Packit Service a2ae7a
            goto invalid;
Packit Service a2ae7a
          }
Packit Service a2ae7a
Packit Service a2ae7a
        /* As a reference for this code, you can use the GNU libiconv
Packit Service a2ae7a
           implementation.  Look for uses of the RET_TOOFEW macro.  */
Packit Service a2ae7a
Packit Service a2ae7a
        case enc_eucjp: /* EUC-JP */
Packit Service a2ae7a
          {
Packit Service a2ae7a
            if (m == 1)
Packit Service a2ae7a
              {
Packit Service a2ae7a
                unsigned char c = (unsigned char) p[0];
Packit Service a2ae7a
Packit Service a2ae7a
                if ((c >= 0xa1 && c < 0xff) || c == 0x8e || c == 0x8f)
Packit Service a2ae7a
                  goto incomplete;
Packit Service a2ae7a
              }
Packit Service a2ae7a
            if (m == 2)
Packit Service a2ae7a
              {
Packit Service a2ae7a
                unsigned char c = (unsigned char) p[0];
Packit Service a2ae7a
Packit Service a2ae7a
                if (c == 0x8f)
Packit Service a2ae7a
                  {
Packit Service a2ae7a
                    unsigned char c2 = (unsigned char) p[1];
Packit Service a2ae7a
Packit Service a2ae7a
                    if (c2 >= 0xa1 && c2 < 0xff)
Packit Service a2ae7a
                      goto incomplete;
Packit Service a2ae7a
                  }
Packit Service a2ae7a
              }
Packit Service a2ae7a
            goto invalid;
Packit Service a2ae7a
          }
Packit Service a2ae7a
Packit Service a2ae7a
        case enc_94: /* EUC-KR, GB2312, BIG5 */
Packit Service a2ae7a
          {
Packit Service a2ae7a
            if (m == 1)
Packit Service a2ae7a
              {
Packit Service a2ae7a
                unsigned char c = (unsigned char) p[0];
Packit Service a2ae7a
Packit Service a2ae7a
                if (c >= 0xa1 && c < 0xff)
Packit Service a2ae7a
                  goto incomplete;
Packit Service a2ae7a
              }
Packit Service a2ae7a
            goto invalid;
Packit Service a2ae7a
          }
Packit Service a2ae7a
Packit Service a2ae7a
        case enc_euctw: /* EUC-TW */
Packit Service a2ae7a
          {
Packit Service a2ae7a
            if (m == 1)
Packit Service a2ae7a
              {
Packit Service a2ae7a
                unsigned char c = (unsigned char) p[0];
Packit Service a2ae7a
Packit Service a2ae7a
                if ((c >= 0xa1 && c < 0xff) || c == 0x8e)
Packit Service a2ae7a
                  goto incomplete;
Packit Service a2ae7a
              }
Packit Service a2ae7a
            else /* m == 2 || m == 3 */
Packit Service a2ae7a
              {
Packit Service a2ae7a
                unsigned char c = (unsigned char) p[0];
Packit Service a2ae7a
Packit Service a2ae7a
                if (c == 0x8e)
Packit Service a2ae7a
                  goto incomplete;
Packit Service a2ae7a
              }
Packit Service a2ae7a
            goto invalid;
Packit Service a2ae7a
          }
Packit Service a2ae7a
Packit Service a2ae7a
        case enc_gb18030: /* GB18030 */
Packit Service a2ae7a
          {
Packit Service a2ae7a
            if (m == 1)
Packit Service a2ae7a
              {
Packit Service a2ae7a
                unsigned char c = (unsigned char) p[0];
Packit Service a2ae7a
Packit Service a2ae7a
                if ((c >= 0x90 && c <= 0xe3) || (c >= 0xf8 && c <= 0xfe))
Packit Service a2ae7a
                  goto incomplete;
Packit Service a2ae7a
              }
Packit Service a2ae7a
            else /* m == 2 || m == 3 */
Packit Service a2ae7a
              {
Packit Service a2ae7a
                unsigned char c = (unsigned char) p[0];
Packit Service a2ae7a
Packit Service a2ae7a
                if (c >= 0x90 && c <= 0xe3)
Packit Service a2ae7a
                  {
Packit Service a2ae7a
                    unsigned char c2 = (unsigned char) p[1];
Packit Service a2ae7a
Packit Service a2ae7a
                    if (c2 >= 0x30 && c2 <= 0x39)
Packit Service a2ae7a
                      {
Packit Service a2ae7a
                        if (m == 2)
Packit Service a2ae7a
                          goto incomplete;
Packit Service a2ae7a
                        else /* m == 3 */
Packit Service a2ae7a
                          {
Packit Service a2ae7a
                            unsigned char c3 = (unsigned char) p[2];
Packit Service a2ae7a
Packit Service a2ae7a
                            if (c3 >= 0x81 && c3 <= 0xfe)
Packit Service a2ae7a
                              goto incomplete;
Packit Service a2ae7a
                          }
Packit Service a2ae7a
                      }
Packit Service a2ae7a
                  }
Packit Service a2ae7a
              }
Packit Service a2ae7a
            goto invalid;
Packit Service a2ae7a
          }
Packit Service a2ae7a
Packit Service a2ae7a
        case enc_sjis: /* SJIS */
Packit Service a2ae7a
          {
Packit Service a2ae7a
            if (m == 1)
Packit Service a2ae7a
              {
Packit Service a2ae7a
                unsigned char c = (unsigned char) p[0];
Packit Service a2ae7a
Packit Service a2ae7a
                if ((c >= 0x81 && c <= 0x9f) || (c >= 0xe0 && c <= 0xea)
Packit Service a2ae7a
                    || (c >= 0xf0 && c <= 0xf9))
Packit Service a2ae7a
                  goto incomplete;
Packit Service a2ae7a
              }
Packit Service a2ae7a
            goto invalid;
Packit Service a2ae7a
          }
Packit Service a2ae7a
Packit Service a2ae7a
        default:
Packit Service a2ae7a
          /* An unknown multibyte encoding.  */
Packit Service a2ae7a
          goto incomplete;
Packit Service a2ae7a
        }
Packit Service a2ae7a
Packit Service a2ae7a
     incomplete:
Packit Service a2ae7a
      {
Packit Service a2ae7a
        size_t k = nstate;
Packit Service a2ae7a
        /* Here 0 <= k < m < 4.  */
Packit Service a2ae7a
        pstate[++k] = s[0];
Packit Service a2ae7a
        if (k < m)
Packit Service a2ae7a
          {
Packit Service a2ae7a
            pstate[++k] = s[1];
Packit Service a2ae7a
            if (k < m)
Packit Service a2ae7a
              pstate[++k] = s[2];
Packit Service a2ae7a
          }
Packit Service a2ae7a
        if (k != m)
Packit Service a2ae7a
          abort ();
Packit Service a2ae7a
      }
Packit Service a2ae7a
      pstate[0] = m;
Packit Service a2ae7a
      return (size_t)(-2);
Packit Service a2ae7a
Packit Service a2ae7a
     invalid:
Packit Service a2ae7a
      errno = EILSEQ;
Packit Service a2ae7a
      /* The conversion state is undefined, says POSIX.  */
Packit Service a2ae7a
      return (size_t)(-1);
Packit Service a2ae7a
    }
Packit Service a2ae7a
  }
Packit Service a2ae7a
}
Packit Service a2ae7a
Packit Service a2ae7a
#else
Packit Service a2ae7a
/* Override the system's mbrtowc() function.  */
Packit Service a2ae7a
Packit Service a2ae7a
# undef mbrtowc
Packit Service a2ae7a
Packit Service a2ae7a
size_t
Packit Service a2ae7a
rpl_mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)
Packit Service a2ae7a
{
Packit Service a2ae7a
  size_t ret;
Packit Service a2ae7a
  wchar_t wc;
Packit Service a2ae7a
Packit Service a2ae7a
# if MBRTOWC_NULL_ARG2_BUG || MBRTOWC_RETVAL_BUG || MBRTOWC_EMPTY_INPUT_BUG
Packit Service a2ae7a
  if (s == NULL)
Packit Service a2ae7a
    {
Packit Service a2ae7a
      pwc = NULL;
Packit Service a2ae7a
      s = "";
Packit Service a2ae7a
      n = 1;
Packit Service a2ae7a
    }
Packit Service a2ae7a
# endif
Packit Service a2ae7a
Packit Service a2ae7a
# if MBRTOWC_EMPTY_INPUT_BUG
Packit Service a2ae7a
  if (n == 0)
Packit Service a2ae7a
    return (size_t) -2;
Packit Service a2ae7a
# endif
Packit Service a2ae7a
Packit Service a2ae7a
  if (! pwc)
Packit Service a2ae7a
    pwc = &wc;
Packit Service a2ae7a
Packit Service a2ae7a
# if MBRTOWC_RETVAL_BUG
Packit Service a2ae7a
  {
Packit Service a2ae7a
    static mbstate_t internal_state;
Packit Service a2ae7a
Packit Service a2ae7a
    /* Override mbrtowc's internal state.  We cannot call mbsinit() on the
Packit Service a2ae7a
       hidden internal state, but we can call it on our variable.  */
Packit Service a2ae7a
    if (ps == NULL)
Packit Service a2ae7a
      ps = &internal_state;
Packit Service a2ae7a
Packit Service a2ae7a
    if (!mbsinit (ps))
Packit Service a2ae7a
      {
Packit Service a2ae7a
        /* Parse the rest of the multibyte character byte for byte.  */
Packit Service a2ae7a
        size_t count = 0;
Packit Service a2ae7a
        for (; n > 0; s++, n--)
Packit Service a2ae7a
          {
Packit Service a2ae7a
            ret = mbrtowc (&wc, s, 1, ps);
Packit Service a2ae7a
Packit Service a2ae7a
            if (ret == (size_t)(-1))
Packit Service a2ae7a
              return (size_t)(-1);
Packit Service a2ae7a
            count++;
Packit Service a2ae7a
            if (ret != (size_t)(-2))
Packit Service a2ae7a
              {
Packit Service a2ae7a
                /* The multibyte character has been completed.  */
Packit Service a2ae7a
                *pwc = wc;
Packit Service a2ae7a
                return (wc == 0 ? 0 : count);
Packit Service a2ae7a
              }
Packit Service a2ae7a
          }
Packit Service a2ae7a
        return (size_t)(-2);
Packit Service a2ae7a
      }
Packit Service a2ae7a
  }
Packit Service a2ae7a
# endif
Packit Service a2ae7a
Packit Service a2ae7a
  ret = mbrtowc (pwc, s, n, ps);
Packit Service a2ae7a
Packit Service a2ae7a
# if MBRTOWC_NUL_RETVAL_BUG
Packit Service a2ae7a
  if (ret < (size_t) -2 && !*pwc)
Packit Service a2ae7a
    return 0;
Packit Service a2ae7a
# endif
Packit Service a2ae7a
Packit Service a2ae7a
# if C_LOCALE_MAYBE_EILSEQ
Packit Service a2ae7a
  if ((size_t) -2 <= ret && n != 0 && ! hard_locale (LC_CTYPE))
Packit Service a2ae7a
    {
Packit Service a2ae7a
      unsigned char uc = *s;
Packit Service a2ae7a
      *pwc = uc;
Packit Service a2ae7a
      return 1;
Packit Service a2ae7a
    }
Packit Service a2ae7a
# endif
Packit Service a2ae7a
Packit Service a2ae7a
  return ret;
Packit Service a2ae7a
}
Packit Service a2ae7a
Packit Service a2ae7a
#endif