diff options
Diffstat (limited to 'newlib/libc/iconv/lib/iconv.c')
-rw-r--r-- | newlib/libc/iconv/lib/iconv.c | 210 |
1 files changed, 57 insertions, 153 deletions
diff --git a/newlib/libc/iconv/lib/iconv.c b/newlib/libc/iconv/lib/iconv.c index ee7124b41..7127aaa22 100644 --- a/newlib/libc/iconv/lib/iconv.c +++ b/newlib/libc/iconv/lib/iconv.c @@ -1,6 +1,6 @@ -/* - * Copyright (c) 2003-2004, Artem B. Bityuckiy - * Copyright (c) 1999,2000, Konstantin Chuguev. All rights reserved. +/*- + * Copyright (c) 1999,2000 + * Konstantin Chuguev. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -22,6 +22,8 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + * + * iconv (Charset Conversion Library) v2.0 */ /* @@ -97,18 +99,18 @@ TRAD_SYNOPSIS DESCRIPTION The function <<iconv>> converts characters from <[in]> which are in one -encoding to characters of another encoding, outputting them to <[out]>. -The value <[inleft]> specifies the number of input bytes to convert whereas -the value <[outleft]> specifies the size remaining in the <[out]> buffer. -The conversion descriptor <[cd]> specifies the conversion being performed -and is created via <<iconv_open>>. +character set and converts them to characters of another character set, +outputting them to <[out]>. The value <[inleft]> specifies the number +of input bytes to convert whereas the value <[outleft]> specifies the +size remaining in the <[out]> buffer. The conversion descriptor <[cd]> +specifies the conversion being performed and is created via <<iconv_open>>. An <<iconv>> conversion stops if: the input bytes are exhausted, the output buffer is full, an invalid input character sequence occurs, or the conversion specifier is invalid. The function <<iconv_open>> is used to specify a conversion from one -encoding: <[from]> to another: <[to]>. The result of the call is +character set: <[from]> to another: <[to]>. The result of the call is to create a conversion specifier that can be used with <<iconv>>. The function <<iconv_close>> is used to close a conversion specifier after @@ -139,32 +141,22 @@ by the Single Unix specification. No supporting OS subroutine calls are required. */ -#include <_ansi.h> + #include <reent.h> -#include <sys/types.h> #include <errno.h> -#include <string.h> #include <stdlib.h> +#include <string.h> #include <iconv.h> -#include <wchar.h> -#include <sys/iconvnls.h> #include "local.h" -#include "conv.h" -#include "ucsconv.h" - -/* - * iconv interface functions as specified by Single Unix specification. - */ iconv_t _DEFUN(iconv_open, (to, from), _CONST char *to _AND _CONST char *from) { - return _iconv_open_r (_REENT, to, from); + return _iconv_open_r(_REENT, to, from); } - size_t _DEFUN(iconv, (cd, inbuf, inbytesleft, outbuf, outbytesleft), iconv_t cd _AND @@ -173,17 +165,15 @@ _DEFUN(iconv, (cd, inbuf, inbytesleft, outbuf, outbytesleft), char **outbuf _AND size_t *outbytesleft) { - return _iconv_r (_REENT, cd, inbuf, inbytesleft, outbuf, outbytesleft); + return _iconv_r(_REENT, cd, inbuf, inbytesleft, outbuf, outbytesleft); } - int _DEFUN(iconv_close, (cd), iconv_t cd) { - return _iconv_close_r (_REENT, cd); + return _iconv_close_r(_REENT, cd); } - #ifndef _REENT_ONLY iconv_t _DEFUN(_iconv_open_r, (rptr, to, from), @@ -191,51 +181,33 @@ _DEFUN(_iconv_open_r, (rptr, to, from), _CONST char *to _AND _CONST char *from) { - iconv_conversion_t *ic; - - if (to == NULL || from == NULL || *to == '\0' || *from == '\0') - return (iconv_t)-1; - - if ((to = (_CONST char *)_iconv_resolve_encoding_name (rptr, to)) == NULL) - return (iconv_t)-1; + iconv_converter_t *ic; + _CONST char *nlspath; - if ((from = (_CONST char *)_iconv_resolve_encoding_name (rptr, from)) == NULL) - { - _free_r (rptr, (_VOID_PTR)to); - return (iconv_t)-1; - } - - ic = (iconv_conversion_t *)_malloc_r (rptr, sizeof (iconv_conversion_t)); - if (ic == NULL) - return (iconv_t)-1; - - /* Select which conversion type to use */ - if (strcmp (from, to) == 0) - { - /* Use null conversion */ - ic->handlers = &_iconv_null_conversion_handlers; - ic->data = ic->handlers->open (rptr, to, from); - } - else - { - /* Use UCS-based conversion */ - ic->handlers = &_iconv_ucs_conversion_handlers; - ic->data = ic->handlers->open (rptr, to, from); - } + if(!to || !from) + return (iconv_t)(-1); - _free_r (rptr, (_VOID_PTR)to); - _free_r (rptr, (_VOID_PTR)from); + if ((nlspath = _getenv_r(rptr, NLS_ENVVAR_NAME)) == NULL || + *nlspath == '\0') + nlspath = NLS_DEFAULT_NLSPATH; - if (ic->data == NULL) + if ((to = _iconv_resolve_cs_name(rptr, (_CONST char *)to, + (_CONST char *)nlspath)) == NULL) + return (iconv_t)(-1); + if ((from = _iconv_resolve_cs_name(rptr, (_CONST char *)from, + (_CONST char *)nlspath)) == NULL) { - _free_r (rptr, (_VOID_PTR)ic); - return (iconv_t)-1; + _free_r(rptr, (_VOID_PTR)to); + return (iconv_t)(-1); } - return (_VOID_PTR)ic; + ic = strcmp(from, to) ? _iconv_unicode_conv_init(rptr, to, from) + : _iconv_null_conv_init(rptr, to, from); + _free_r(rptr, (_VOID_PTR)to); + _free_r(rptr, (_VOID_PTR)from); + return ic ? (iconv_t)(ic) : (iconv_t)(-1); } - size_t _DEFUN(_iconv_r, (rptr, cd, inbuf, inbytesleft, outbuf, outbytesleft), struct _reent *rptr _AND @@ -245,104 +217,36 @@ _DEFUN(_iconv_r, (rptr, cd, inbuf, inbytesleft, outbuf, outbytesleft), char **outbuf _AND size_t *outbytesleft) { - iconv_conversion_t *ic = (iconv_conversion_t *)cd; - - if ((_VOID_PTR)cd == NULL || cd == (iconv_t)-1 || ic->data == NULL - || (ic->handlers != &_iconv_null_conversion_handlers - && ic->handlers != &_iconv_ucs_conversion_handlers)) - { - __errno_r (rptr) = EBADF; - return (size_t)-1; - } - - if (inbuf == NULL || *inbuf == NULL) - { - mbstate_t state_null = ICONV_ZERO_MB_STATE_T; - - if (!ic->handlers->is_stateful(ic->data, 1)) - return (size_t)0; - - if (outbuf == NULL || *outbuf == NULL) - { - /* Reset shift state */ - ic->handlers->set_state (ic->data, &state_null, 1); - - return (size_t)0; - } - - if (outbytesleft != NULL) - { - mbstate_t state_save = ICONV_ZERO_MB_STATE_T; - - /* Save current shift state */ - ic->handlers->get_state (ic->data, &state_save, 1); - - /* Reset shift state */ - ic->handlers->set_state (ic->data, &state_null, 1); - - /* Get initial shift state sequence and it's length */ - ic->handlers->get_state (ic->data, &state_null, 1); - - if (*outbytesleft >= state_null.__count) - { - memcpy ((_VOID_PTR)(*outbuf), (_VOID_PTR)&state_null, state_null.__count); - - *outbuf += state_null.__count; - *outbytesleft -= state_null.__count; - - return (size_t)0; - } - - /* Restore shift state if output buffer is too small */ - ic->handlers->set_state (ic->data, &state_save, 1); - } - - __errno_r (rptr) = E2BIG; - return (size_t)-1; - } - - if (*inbytesleft == 0) - { - __errno_r (rptr) = EINVAL; - return (size_t)-1; + if ((_VOID_PTR)cd == NULL) { + __errno_r(rptr) = EBADF; + return (size_t)(-1); } - - if (*outbytesleft == 0 || *outbuf == NULL) - { - __errno_r (rptr) = E2BIG; - return (size_t)-1; + if (outbytesleft == NULL || + outbuf == NULL || *outbuf == 0) { + __errno_r(rptr) = E2BIG; + return (size_t)(-1); } - - return ic->handlers->convert (rptr, - ic->data, - (_CONST unsigned char**)inbuf, - inbytesleft, - (unsigned char**)outbuf, - outbytesleft, - 0); + return ((iconv_converter_t *)cd)->convert(rptr, (iconv_converter_t *)cd + 1, + (_CONST unsigned char**)inbuf, + inbytesleft, + (unsigned char**)outbuf, + outbytesleft); } - int _DEFUN(_iconv_close_r, (rptr, cd), struct _reent *rptr _AND iconv_t cd) { - int res; - iconv_conversion_t *ic = (iconv_conversion_t *)cd; - - if ((_VOID_PTR)cd == NULL || cd == (iconv_t)-1 || ic->data == NULL - || (ic->handlers != &_iconv_null_conversion_handlers - && ic->handlers != &_iconv_ucs_conversion_handlers)) - { - __errno_r (rptr) = EBADF; - return -1; - } - - res = (int)ic->handlers->close (rptr, ic->data); - - _free_r (rptr, (_VOID_PTR)cd); + int res; - return res; + if ((_VOID_PTR)cd == NULL || cd == (iconv_t)-1) { + __errno_r(rptr) = EBADF; + return -1; + } + res = ((iconv_converter_t *)cd)->close(rptr, (iconv_converter_t *)cd + 1); + _free_r(rptr, (_VOID_PTR)cd); + return res ? -1 : 0; } -#endif /* !_REENT_ONLY */ +#endif /* #ifndef _REENT_ONLY */ + |