(root)/
tar-1.35/
gnu/
mbrtowc.c
       1  /* Convert multibyte character to wide character.
       2     Copyright (C) 1999-2002, 2005-2023 Free Software Foundation, Inc.
       3     Written by Bruno Haible <bruno@clisp.org>, 2008.
       4  
       5     This file is free software: you can redistribute it and/or modify
       6     it under the terms of the GNU Lesser General Public License as
       7     published by the Free Software Foundation; either version 2.1 of the
       8     License, or (at your option) any later version.
       9  
      10     This file is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13     GNU Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public License
      16     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      17  
      18  #include <config.h>
      19  
      20  /* Specification.  */
      21  #include <wchar.h>
      22  
      23  #if GNULIB_defined_mbstate_t
      24  /* Implement mbrtowc() on top of mbtowc() for the non-UTF-8 locales
      25     and directly for the UTF-8 locales.  */
      26  
      27  # include <errno.h>
      28  # include <stdint.h>
      29  # include <stdlib.h>
      30  
      31  # if defined _WIN32 && !defined __CYGWIN__
      32  
      33  #  define WIN32_LEAN_AND_MEAN  /* avoid including junk */
      34  #  include <windows.h>
      35  
      36  # elif HAVE_PTHREAD_API
      37  
      38  #  include <pthread.h>
      39  #  if HAVE_THREADS_H && HAVE_WEAK_SYMBOLS
      40  #   include <threads.h>
      41  #   pragma weak thrd_exit
      42  #   define c11_threads_in_use() (thrd_exit != NULL)
      43  #  else
      44  #   define c11_threads_in_use() 0
      45  #  endif
      46  
      47  # elif HAVE_THREADS_H
      48  
      49  #  include <threads.h>
      50  
      51  # endif
      52  
      53  # include "attribute.h"
      54  # include "lc-charset-dispatch.h"
      55  # include "mbtowc-lock.h"
      56  
      57  static_assert (sizeof (mbstate_t) >= 4);
      58  static char internal_state[4];
      59  
      60  size_t
      61  mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)
      62  {
      63  # define FITS_IN_CHAR_TYPE(wc)  ((wc) <= WCHAR_MAX)
      64  # include "mbrtowc-impl.h"
      65  }
      66  
      67  #else
      68  /* Override the system's mbrtowc() function.  */
      69  
      70  # if MBRTOWC_IN_C_LOCALE_MAYBE_EILSEQ
      71  #  include "hard-locale.h"
      72  #  include <locale.h>
      73  # endif
      74  
      75  # undef mbrtowc
      76  
      77  size_t
      78  rpl_mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)
      79  {
      80    size_t ret;
      81    wchar_t wc;
      82  
      83  # if MBRTOWC_NULL_ARG2_BUG || MBRTOWC_RETVAL_BUG || MBRTOWC_EMPTY_INPUT_BUG
      84    if (s == NULL)
      85      {
      86        pwc = NULL;
      87        s = "";
      88        n = 1;
      89      }
      90  # endif
      91  
      92  # if MBRTOWC_EMPTY_INPUT_BUG
      93    if (n == 0)
      94      return (size_t) -2;
      95  # endif
      96  
      97    if (! pwc)
      98      pwc = &wc;
      99  
     100  # if MBRTOWC_RETVAL_BUG
     101    {
     102      static mbstate_t internal_state;
     103  
     104      /* Override mbrtowc's internal state.  We cannot call mbsinit() on the
     105         hidden internal state, but we can call it on our variable.  */
     106      if (ps == NULL)
     107        ps = &internal_state;
     108  
     109      if (!mbsinit (ps))
     110        {
     111          /* Parse the rest of the multibyte character byte for byte.  */
     112          size_t count = 0;
     113          for (; n > 0; s++, n--)
     114            {
     115              ret = mbrtowc (&wc, s, 1, ps);
     116  
     117              if (ret == (size_t)(-1))
     118                return (size_t)(-1);
     119              count++;
     120              if (ret != (size_t)(-2))
     121                {
     122                  /* The multibyte character has been completed.  */
     123                  *pwc = wc;
     124                  return (wc == 0 ? 0 : count);
     125                }
     126            }
     127          return (size_t)(-2);
     128        }
     129    }
     130  # endif
     131  
     132  # if MBRTOWC_STORES_INCOMPLETE_BUG
     133    ret = mbrtowc (&wc, s, n, ps);
     134    if (ret < (size_t) -2 && pwc != NULL)
     135      *pwc = wc;
     136  # else
     137    ret = mbrtowc (pwc, s, n, ps);
     138  # endif
     139  
     140  # if MBRTOWC_NUL_RETVAL_BUG
     141    if (ret < (size_t) -2 && !*pwc)
     142      return 0;
     143  # endif
     144  
     145  # if MBRTOWC_IN_C_LOCALE_MAYBE_EILSEQ
     146    if ((size_t) -2 <= ret && n != 0 && ! hard_locale (LC_CTYPE))
     147      {
     148        unsigned char uc = *s;
     149        *pwc = uc;
     150        return 1;
     151      }
     152  # endif
     153  
     154    return ret;
     155  }
     156  
     157  #endif