diff options
Diffstat (limited to 'libio')
-rw-r--r-- | libio/fileops.c | 120 | ||||
-rw-r--r-- | libio/iofclose.c | 12 | ||||
-rw-r--r-- | libio/iofwide.c | 23 |
3 files changed, 101 insertions, 54 deletions
diff --git a/libio/fileops.c b/libio/fileops.c index 03f71d71c0..3947fa8d6c 100644 --- a/libio/fileops.c +++ b/libio/fileops.c @@ -31,6 +31,7 @@ # define _POSIX_SOURCE #endif #include "libioP.h" +#include <assert.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> @@ -42,6 +43,8 @@ #endif #if _LIBC # include "../wcsmbs/wcsmbsload.h" +# include "../iconv/gconv_charset.h" +# include "../iconv/gconv_int.h" # include <shlib-compat.h> #endif #ifndef errno @@ -74,6 +77,12 @@ extern int errno; # define _IO_new_file_xsputn _IO_file_xsputn #endif + +#ifdef _LIBC +extern struct __gconv_trans_data __libio_translit; +#endif + + /* An fstream can be in at most one of put mode, get mode, or putback mode. Putback mode is a variant of get mode. @@ -238,8 +247,9 @@ _IO_new_file_fopen (fp, filename, mode, is32not64) int oprot = 0666; int i; _IO_FILE *result; -#if _LIBC +#ifdef _LIBC const char *cs; + const char *last_recognized; #endif if (_IO_file_is_open (fp)) @@ -264,6 +274,9 @@ _IO_new_file_fopen (fp, filename, mode, is32not64) __set_errno (EINVAL); return NULL; } +#ifdef _LIBC + last_recognized = mode; +#endif for (i = 1; i < 4; ++i) { switch (*++mode) @@ -273,11 +286,20 @@ _IO_new_file_fopen (fp, filename, mode, is32not64) case '+': omode = O_RDWR; read_write &= _IO_IS_APPENDING; +#ifdef _LIBC + last_recognized = mode; +#endif continue; case 'x': oflags |= O_EXCL; +#ifdef _LIBC + last_recognized = mode; +#endif continue; case 'b': +#ifdef _LIBC + last_recognized = mode; +#endif default: /* Ignore. */ continue; @@ -289,48 +311,78 @@ _IO_new_file_fopen (fp, filename, mode, is32not64) is32not64); -#if _LIBC - /* Test whether the mode string specifies the conversion. */ - cs = strstr (mode, ",ccs="); - if (cs != NULL) +#ifdef _LIBC + if (result != NULL) { - /* Yep. Load the appropriate conversions and set the orientation - to wide. */ - struct gconv_fcts fcts; - struct _IO_codecvt *cc; + /* Test whether the mode string specifies the conversion. */ + cs = strstr (last_recognized + 1, ",ccs="); + if (cs != NULL) + { + /* Yep. Load the appropriate conversions and set the orientation + to wide. */ + struct gconv_fcts fcts; + struct _IO_codecvt *cc; + char *endp = __strchrnul (cs + 5, ','); + char ccs[endp - (cs + 5) + 3]; + + *((char *) __mempcpy (ccs, cs + 5, endp - (cs + 5))) = '\0'; + strip (ccs, ccs); + + if (__wcsmbs_named_conv (&fcts, ccs[2] == '\0' + ? upstr (ccs, cs + 5) : ccs) != 0) + { + /* Something went wrong, we cannot load the conversion modules. + This means we cannot proceed since the user explicitly asked + for these. */ + __set_errno (EINVAL); + return NULL; + } - if (! _IO_CHECK_WIDE (fp) || __wcsmbs_named_conv (&fcts, cs + 5) != 0) - { - /* Something went wrong, we cannot load the conversion modules. - This means we cannot proceed since the user explicitly asked - for these. */ - _IO_new_fclose (result); - return NULL; - } + assert (fcts.towc_nsteps == 1); + assert (fcts.tomb_nsteps == 1); + + fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end; + fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_write_base; + + /* 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)); + + cc = fp->_codecvt = &fp->_wide_data->_codecvt; - cc = fp->_codecvt = &fp->_wide_data->_codecvt; + /* The functions are always the same. */ + *cc = __libio_codecvt; - /* 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.__nsteps = 1; /* Only one step allowed. */ - 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 = &result->_wide_data->_IO_state; - 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 = &result->_wide_data->_IO_state; + /* XXX For now no transliteration. */ + cc->__cd_in.__cd.__data[0].__trans = NULL; - cc->__cd_out.__cd.__nsteps = 1; /* Only one step allowed. */ - cc->__cd_out.__cd.__steps = fcts.tomb; + 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 = &result->_wide_data->_IO_state; + 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 = + &result->_wide_data->_IO_state; - /* Set the mode now. */ - result->_mode = 1; + /* And now the transliteration. */ + cc->__cd_out.__cd.__data[0].__trans = &__libio_translit; + + /* Set the mode now. */ + result->_mode = 1; + + /* We don't need the step data structure anymore. */ + __gconv_release_cache (fcts.towc, fcts.towc_nsteps); + __gconv_release_cache (fcts.tomb, fcts.tomb_nsteps); + } } #endif /* GNU libc */ diff --git a/libio/iofclose.c b/libio/iofclose.c index 660c118359..45bd0afa7d 100644 --- a/libio/iofclose.c +++ b/libio/iofclose.c @@ -72,16 +72,8 @@ _IO_new_fclose (fp) the conversion functions. */ struct _IO_codecvt *cc = fp->_codecvt; - if (cc->__cd_in.__cd.__steps->__shlib_handle != NULL) - { - --cc->__cd_in.__cd.__steps->__counter; - __gconv_close_transform (cc->__cd_in.__cd.__steps, 1); - } - if (cc->__cd_out.__cd.__steps->__shlib_handle != NULL) - { - --cc->__cd_out.__cd.__steps->__counter; - __gconv_close_transform (cc->__cd_out.__cd.__steps, 1); - } + __gconv_release_step (cc->__cd_in.__cd.__steps); + __gconv_release_step (cc->__cd_out.__cd.__steps); #endif } _IO_cleanup_region_end (0); diff --git a/libio/iofwide.c b/libio/iofwide.c index d191baaf99..aa314fe671 100644 --- a/libio/iofwide.c +++ b/libio/iofwide.c @@ -30,6 +30,7 @@ # include <dlfcn.h> # include <wchar.h> #endif +#include <assert.h> #include <stdlib.h> #include <string.h> @@ -81,7 +82,7 @@ struct _IO_codecvt __libio_codecvt = #ifdef _LIBC -static struct __gconv_trans_data libio_translit = +struct __gconv_trans_data __libio_translit = { .__trans_fct = __gconv_transliterate }; @@ -134,11 +135,13 @@ _IO_fwide (fp, mode) memset (&fp->_wide_data->_IO_last_state, '\0', sizeof (__mbstate_t)); __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 = 1; /* Only one step allowed. */ + cc->__cd_in.__cd.__nsteps = fcts.towc_nsteps; cc->__cd_in.__cd.__steps = fcts.towc; cc->__cd_in.__cd.__data[0].__invocation_counter = 0; @@ -149,7 +152,7 @@ _IO_fwide (fp, mode) /* XXX For now no transliteration. */ cc->__cd_in.__cd.__data[0].__trans = NULL; - cc->__cd_out.__cd.__nsteps = 1; /* Only one step allowed. */ + cc->__cd_out.__cd.__nsteps = fcts.tomb_nsteps; cc->__cd_out.__cd.__steps = fcts.tomb; cc->__cd_out.__cd.__data[0].__invocation_counter = 0; @@ -158,11 +161,7 @@ _IO_fwide (fp, mode) cc->__cd_out.__cd.__data[0].__statep = &fp->_wide_data->_IO_state; /* And now the transliteration. */ -#ifdef _LIBC - cc->__cd_out.__cd.__data[0].__trans = &libio_translit; -#else - cc->__cd_out.__cd.__data[0].__trans = NULL; -#endif + cc->__cd_out.__cd.__data[0].__trans = &__libio_translit; } #else # ifdef _GLIBCPP_USE_WCHAR_T @@ -188,8 +187,12 @@ _IO_fwide (fp, mode) cc->__cd_out = iconv_open (external_ccs, internal_ccs); if (cc->__cd_in == (iconv_t) -1 || cc->__cd_out == (iconv_t) -1) - /* XXX */ - abort (); + { + if (cc->__cd_in != (iconv_t) -1) + iconv_close (cc->__cd_in); + /* XXX */ + abort (); + } } # else # error "somehow determine this from LC_CTYPE" |