(root)/
glibc-2.38/
wcsmbs/
wctob.c
       1  /* Copyright (C) 1996-2023 Free Software Foundation, Inc.
       2     This file is part of the GNU C Library.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public
       6     License as published by the Free Software Foundation; either
       7     version 2.1 of the License, or (at your option) any later version.
       8  
       9     The GNU C Library is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; if not, see
      16     <https://www.gnu.org/licenses/>.  */
      17  
      18  #include <dlfcn.h>
      19  #include <gconv.h>
      20  #include <stdio.h>
      21  #include <string.h>
      22  #include <wchar.h>
      23  #include <wcsmbsload.h>
      24  
      25  #include <pointer_guard.h>
      26  
      27  
      28  int
      29  wctob (wint_t c)
      30  {
      31    unsigned char buf[MB_LEN_MAX];
      32    struct __gconv_step_data data;
      33    wchar_t inbuf[1];
      34    wchar_t *inptr = inbuf;
      35    size_t dummy;
      36    int status;
      37    const struct gconv_fcts *fcts;
      38  
      39    if (c == WEOF)
      40      return EOF;
      41  
      42    /* We know that only ASCII compatible encodings are used for the
      43       locale and that the wide character encoding is ISO 10646.  */
      44    if (c >= L'\0' && c <= L'\x7f')
      45      return (int) c;
      46  
      47    /* Tell where we want the result.  */
      48    data.__outbuf = buf;
      49    data.__outbufend = buf + MB_LEN_MAX;
      50    data.__invocation_counter = 0;
      51    data.__internal_use = 1;
      52    data.__flags = __GCONV_IS_LAST;
      53    data.__statep = &data.__state;
      54  
      55    /* Make sure we start in the initial state.  */
      56    memset (&data.__state, '\0', sizeof (mbstate_t));
      57  
      58    /* Get the conversion functions.  */
      59    fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE));
      60  
      61    /* Create the input string.  */
      62    inbuf[0] = c;
      63  
      64    const unsigned char *argptr = (const unsigned char *) inptr;
      65    __gconv_fct fct = fcts->tomb->__fct;
      66    if (fcts->tomb->__shlib_handle != NULL)
      67      PTR_DEMANGLE (fct);
      68    status = DL_CALL_FCT (fct,
      69  			(fcts->tomb, &data, &argptr,
      70  			 argptr + sizeof (inbuf[0]), NULL, &dummy, 0, 1));
      71  
      72    /* The conversion failed or the output is too long.  */
      73    if ((status != __GCONV_OK && status != __GCONV_FULL_OUTPUT
      74         && status != __GCONV_EMPTY_INPUT)
      75        || data.__outbuf != (unsigned char *) (buf + 1))
      76      return EOF;
      77  
      78    return buf[0];
      79  }