Back to index

glibc  2.9
Functions
iofwide.c File Reference
#include <libioP.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>

Go to the source code of this file.

Functions

static enum __codecvt_result do_out (struct _IO_codecvt *codecvt, __mbstate_t *statep, const wchar_t *from_start, const wchar_t *from_end, const wchar_t **from_stop, char *to_start, char *to_end, char **to_stop)
static enum __codecvt_result do_unshift (struct _IO_codecvt *codecvt, __mbstate_t *statep, char *to_start, char *to_end, char **to_stop)
static enum __codecvt_result do_in (struct _IO_codecvt *codecvt, __mbstate_t *statep, const char *from_start, const char *from_end, const char **from_stop, wchar_t *to_start, wchar_t *to_end, wchar_t **to_stop)
static int do_encoding (struct _IO_codecvt *codecvt)
static int do_length (struct _IO_codecvt *codecvt, __mbstate_t *statep, const char *from_start, const char *from_end, _IO_size_t max)
static int do_max_length (struct _IO_codecvt *codecvt)
static int do_always_noconv (struct _IO_codecvt *codecvt)
int _IO_fwide (_IO_FILE *fp, int mode)

Function Documentation

int _IO_fwide ( _IO_FILE fp,
int  mode 
)

Definition at line 97 of file iofwide.c.

{
  /* Normalize the value.  */
  mode = mode < 0 ? -1 : (mode == 0 ? 0 : 1);

#if defined SHARED && defined _LIBC \
    && SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
  if (__builtin_expect (&_IO_stdin_used == NULL, 0)
      && (fp == _IO_stdin || fp == _IO_stdout || fp == _IO_stderr))
    /* This is for a stream in the glibc 2.0 format.  */
    return -1;
#endif

  /* The orientation already has been determined.  */
  if (fp->_mode != 0
      /* Or the caller simply wants to know about the current orientation.  */
      || mode == 0)
    return fp->_mode;

  /* Set the orientation appropriately.  */
  if (mode > 0)
    {
      struct _IO_codecvt *cc = fp->_codecvt = &fp->_wide_data->_codecvt;

      fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end;
      fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_write_base;

      /* Get the character conversion functions based on the currently
        selected locale for LC_CTYPE.  */
#ifdef _LIBC
      {
       /* Clear the state.  We start all over again.  */
       memset (&fp->_wide_data->_IO_state, '\0', sizeof (__mbstate_t));
       memset (&fp->_wide_data->_IO_last_state, '\0', sizeof (__mbstate_t));

       struct gconv_fcts fcts;
       __wcsmbs_clone_conv (&fcts);
       assert (fcts.towc_nsteps == 1);
       assert (fcts.tomb_nsteps == 1);

       /* The functions are always the same.  */
       *cc = __libio_codecvt;

       cc->__cd_in.__cd.__nsteps = fcts.towc_nsteps;
       cc->__cd_in.__cd.__steps = fcts.towc;

       cc->__cd_in.__cd.__data[0].__invocation_counter = 0;
       cc->__cd_in.__cd.__data[0].__internal_use = 1;
       cc->__cd_in.__cd.__data[0].__flags = __GCONV_IS_LAST;
       cc->__cd_in.__cd.__data[0].__statep = &fp->_wide_data->_IO_state;

       /* XXX For now no transliteration.  */
       cc->__cd_in.__cd.__data[0].__trans = NULL;

       cc->__cd_out.__cd.__nsteps = fcts.tomb_nsteps;
       cc->__cd_out.__cd.__steps = fcts.tomb;

       cc->__cd_out.__cd.__data[0].__invocation_counter = 0;
       cc->__cd_out.__cd.__data[0].__internal_use = 1;
       cc->__cd_out.__cd.__data[0].__flags = __GCONV_IS_LAST;
       cc->__cd_out.__cd.__data[0].__statep = &fp->_wide_data->_IO_state;

       /* And now the transliteration.  */
       cc->__cd_out.__cd.__data[0].__trans
         = (struct __gconv_trans_data  *) &__libio_translit;
      }
#else
# ifdef _GLIBCPP_USE_WCHAR_T
      {
       /* Determine internal and external character sets.

          XXX For now we make our life easy: we assume a fixed internal
          encoding (as most sane systems have; hi HP/UX!).  If somebody
          cares about systems which changing internal charsets they
          should come up with a solution for the determination of the
          currently used internal character set.  */
       const char *internal_ccs = _G_INTERNAL_CCS;
       const char *external_ccs = NULL;

#  ifdef HAVE_NL_LANGINFO
       external_ccs = nl_langinfo (CODESET);
#  endif
       if (external_ccs == NULL)
         external_ccs = "ISO-8859-1";

       cc->__cd_in = iconv_open (internal_ccs, external_ccs);
       if (cc->__cd_in != (iconv_t) -1)
         cc->__cd_out = iconv_open (external_ccs, internal_ccs);

       if (cc->__cd_in == (iconv_t) -1 || cc->__cd_out == (iconv_t) -1)
         {
           if (cc->__cd_in != (iconv_t) -1)
             iconv_close (cc->__cd_in);
           /* XXX */
           abort ();
         }
      }
# else
#  error "somehow determine this from LC_CTYPE"
# endif
#endif

      /* From now on use the wide character callback functions.  */
      ((struct _IO_FILE_plus *) fp)->vtable = fp->_wide_data->_wide_vtable;

      /* One last twist: we get the current stream position.  The wide
        char streams have much more problems with not knowing the
        current position and so we should disable the optimization
        which allows the functions without knowing the position.  */
      fp->_offset = _IO_SYSSEEK (fp, 0, _IO_seek_cur);
    }

  /* Set the mode now.  */
  fp->_mode = mode;

  return mode;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int do_always_noconv ( struct _IO_codecvt *  codecvt) [static]

Definition at line 459 of file iofwide.c.

{
  return 0;
}
static int do_encoding ( struct _IO_codecvt *  codecvt) [static]

Definition at line 437 of file iofwide.c.

{
#ifdef _LIBC
  /* See whether the encoding is stateful.  */
  if (codecvt->__cd_in.__cd.__steps[0].__stateful)
    return -1;
  /* Fortunately not.  Now determine the input bytes for the conversion
     necessary for each wide character.  */
  if (codecvt->__cd_in.__cd.__steps[0].__min_needed_from
      != codecvt->__cd_in.__cd.__steps[0].__max_needed_from)
    /* Not a constant value.  */
    return 0;

  return codecvt->__cd_in.__cd.__steps[0].__min_needed_from;
#else
  /* Worst case scenario.  */
  return -1;
#endif
}
static enum __codecvt_result do_in ( struct _IO_codecvt *  codecvt,
__mbstate_t statep,
const char *  from_start,
const char *  from_end,
const char **  from_stop,
wchar_t *  to_start,
wchar_t *  to_end,
wchar_t **  to_stop 
) [static]

Definition at line 361 of file iofwide.c.

{
  enum __codecvt_result result;

#ifdef _LIBC
  struct __gconv_step *gs = codecvt->__cd_in.__cd.__steps;
  int status;
  size_t dummy;
  const unsigned char *from_start_copy = (unsigned char *) from_start;

  codecvt->__cd_in.__cd.__data[0].__outbuf = (unsigned char *) to_start;
  codecvt->__cd_in.__cd.__data[0].__outbufend = (unsigned char *) to_end;
  codecvt->__cd_in.__cd.__data[0].__statep = statep;

  __gconv_fct fct = gs->__fct;
#ifdef PTR_DEMANGLE
  if (gs->__shlib_handle != NULL)
    PTR_DEMANGLE (fct);
#endif

  status = DL_CALL_FCT (fct,
                     (gs, codecvt->__cd_in.__cd.__data, &from_start_copy,
                      (const unsigned char *) from_end, NULL,
                      &dummy, 0, 0));

  *from_stop = (const char *) from_start_copy;
  *to_stop = (wchar_t *) codecvt->__cd_in.__cd.__data[0].__outbuf;

  switch (status)
    {
    case __GCONV_OK:
    case __GCONV_EMPTY_INPUT:
      result = __codecvt_ok;
      break;

    case __GCONV_FULL_OUTPUT:
    case __GCONV_INCOMPLETE_INPUT:
      result = __codecvt_partial;
      break;

    default:
      result = __codecvt_error;
      break;
    }
#else
# ifdef _GLIBCPP_USE_WCHAR_T
  size_t res;
  const char *from_start_copy = (const char *) from_start;
  size_t from_len = from_end - from_start;
  char *to_start_copy = (char *) from_start;
  size_t to_len = to_end - to_start;

  res = iconv (codecvt->__cd_in, &from_start_copy, &from_len,
              &to_start_copy, &to_len);

  if (res == 0)
    result = __codecvt_ok;
  else if (to_len == 0)
    result = __codecvt_partial;
  else if (from_len < codecvt->__codecvt_do_max_length (codecvt))
    result = __codecvt_partial;
  else
    result = __codecvt_error;
# else
  /* Decide what to do.  */
  result = __codecvt_error;
# endif
#endif

  return result;
}

Here is the call graph for this function:

static int do_length ( struct _IO_codecvt *  codecvt,
__mbstate_t statep,
const char *  from_start,
const char *  from_end,
_IO_size_t  max 
) [static]

Definition at line 466 of file iofwide.c.

{
  int result;
#ifdef _LIBC
  const unsigned char *cp = (const unsigned char *) from_start;
  wchar_t to_buf[max];
  struct __gconv_step *gs = codecvt->__cd_in.__cd.__steps;
  int status;
  size_t dummy;

  codecvt->__cd_in.__cd.__data[0].__outbuf = (unsigned char *) to_buf;
  codecvt->__cd_in.__cd.__data[0].__outbufend = (unsigned char *) &to_buf[max];
  codecvt->__cd_in.__cd.__data[0].__statep = statep;

  __gconv_fct fct = gs->__fct;
#ifdef PTR_DEMANGLE
  if (gs->__shlib_handle != NULL)
    PTR_DEMANGLE (fct);
#endif

  status = DL_CALL_FCT (fct,
                     (gs, codecvt->__cd_in.__cd.__data, &cp,
                      (const unsigned char *) from_end, NULL,
                      &dummy, 0, 0));

  result = cp - (const unsigned char *) from_start;
#else
# ifdef _GLIBCPP_USE_WCHAR_T
  const char *from_start_copy = (const char *) from_start;
  size_t from_len = from_end - from_start;
  wchar_t to_buf[max];
  size_t res;
  char *to_start = (char *) to_buf;

  res = iconv (codecvt->__cd_in, &from_start_copy, &from_len,
              &to_start, &max);

  result = from_start_copy - (char *) from_start;
# else
  /* Decide what to do.  */
  result = 0;
# endif
#endif

  return result;
}

Here is the call graph for this function:

static int do_max_length ( struct _IO_codecvt *  codecvt) [static]

Definition at line 516 of file iofwide.c.

{
#ifdef _LIBC
  return codecvt->__cd_in.__cd.__steps[0].__max_needed_from;
#else
  return MB_CUR_MAX;
#endif
}
static enum __codecvt_result do_out ( struct _IO_codecvt *  codecvt,
__mbstate_t statep,
const wchar_t *  from_start,
const wchar_t *  from_end,
const wchar_t **  from_stop,
char *  to_start,
char *  to_end,
char **  to_stop 
) [static]

Definition at line 219 of file iofwide.c.

{
  enum __codecvt_result result;

#ifdef _LIBC
  struct __gconv_step *gs = codecvt->__cd_out.__cd.__steps;
  int status;
  size_t dummy;
  const unsigned char *from_start_copy = (unsigned char *) from_start;

  codecvt->__cd_out.__cd.__data[0].__outbuf = (unsigned char *) to_start;
  codecvt->__cd_out.__cd.__data[0].__outbufend = (unsigned char *) to_end;
  codecvt->__cd_out.__cd.__data[0].__statep = statep;

  __gconv_fct fct = gs->__fct;
#ifdef PTR_DEMANGLE
  if (gs->__shlib_handle != NULL)
    PTR_DEMANGLE (fct);
#endif

  status = DL_CALL_FCT (fct,
                     (gs, codecvt->__cd_out.__cd.__data, &from_start_copy,
                      (const unsigned char *) from_end, NULL,
                      &dummy, 0, 0));

  *from_stop = (wchar_t *) from_start_copy;
  *to_stop = (char *) codecvt->__cd_out.__cd.__data[0].__outbuf;

  switch (status)
    {
    case __GCONV_OK:
    case __GCONV_EMPTY_INPUT:
      result = __codecvt_ok;
      break;

    case __GCONV_FULL_OUTPUT:
    case __GCONV_INCOMPLETE_INPUT:
      result = __codecvt_partial;
      break;

    default:
      result = __codecvt_error;
      break;
    }
#else
# ifdef _GLIBCPP_USE_WCHAR_T
  size_t res;
  const char *from_start_copy = (const char *) from_start;
  size_t from_len = from_end - from_start;
  char *to_start_copy = to_start;
  size_t to_len = to_end - to_start;
  res = iconv (codecvt->__cd_out, &from_start_copy, &from_len,
              &to_start_copy, &to_len);

  if (res == 0 || from_len == 0)
    result = __codecvt_ok;
  else if (to_len < codecvt->__codecvt_do_max_length (codecvt))
    result = __codecvt_partial;
  else
    result = __codecvt_error;

# else
  /* Decide what to do.  */
  result = __codecvt_error;
# endif
#endif

  return result;
}

Here is the call graph for this function:

static enum __codecvt_result do_unshift ( struct _IO_codecvt *  codecvt,
__mbstate_t statep,
char *  to_start,
char *  to_end,
char **  to_stop 
) [static]

Definition at line 294 of file iofwide.c.

{
  enum __codecvt_result result;

#ifdef _LIBC
  struct __gconv_step *gs = codecvt->__cd_out.__cd.__steps;
  int status;
  size_t dummy;

  codecvt->__cd_out.__cd.__data[0].__outbuf = (unsigned char *) to_start;
  codecvt->__cd_out.__cd.__data[0].__outbufend = (unsigned char *) to_end;
  codecvt->__cd_out.__cd.__data[0].__statep = statep;

  __gconv_fct fct = gs->__fct;
#ifdef PTR_DEMANGLE
  if (gs->__shlib_handle != NULL)
    PTR_DEMANGLE (fct);
#endif

  status = DL_CALL_FCT (fct,
                     (gs, codecvt->__cd_out.__cd.__data, NULL, NULL,
                      NULL, &dummy, 1, 0));

  *to_stop = (char *) codecvt->__cd_out.__cd.__data[0].__outbuf;

  switch (status)
    {
    case __GCONV_OK:
    case __GCONV_EMPTY_INPUT:
      result = __codecvt_ok;
      break;

    case __GCONV_FULL_OUTPUT:
    case __GCONV_INCOMPLETE_INPUT:
      result = __codecvt_partial;
      break;

    default:
      result = __codecvt_error;
      break;
    }
#else
# ifdef _GLIBCPP_USE_WCHAR_T
  size_t res;
  char *to_start_copy = (char *) to_start;
  size_t to_len = to_end - to_start;

  res = iconv (codecvt->__cd_out, NULL, NULL, &to_start_copy, &to_len);

  if (res == 0)
    result = __codecvt_ok;
  else if (to_len < codecvt->__codecvt_do_max_length (codecvt))
    result = __codecvt_partial;
  else
    result = __codecvt_error;
# else
  /* Decide what to do.  */
  result = __codecvt_error;
# endif
#endif

  return result;
}

Here is the call graph for this function: