X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=src%2Flibpspp%2Fi18n.c;h=ffaa40489b042c7460480a0989bd6730a37c5e9b;hb=a486e7cbf4f95d19bb208796e4c92a040cf48f65;hp=bcac52cf58b35b062aa6a45503887d84cc68c780;hpb=655bf3a3917cdf16f99fcbb680d2bf3159126a93;p=pspp diff --git a/src/libpspp/i18n.c b/src/libpspp/i18n.c index bcac52cf58..ffaa40489b 100644 --- a/src/libpspp/i18n.c +++ b/src/libpspp/i18n.c @@ -1,6 +1,5 @@ /* PSPP - computes sample statistics. Copyright (C) 2006 Free Software Foundation, Inc. - Written by John Darrington This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -21,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +28,7 @@ #include "i18n.h" #include +#include "xstrndup.h" static char *locale = 0; @@ -36,6 +37,26 @@ static const char *charset; static iconv_t convertor[n_CONV]; + +/* A wrapper around iconv_open */ +static iconv_t +create_iconv (const char* tocode, const char* fromcode) +{ + iconv_t conv = iconv_open (tocode, fromcode); + + /* I don't think it's safe to translate this string or to use messaging + as the convertors have not yet been set up */ + if ( (iconv_t) -1 == conv) + { + const int err = errno; + fprintf (stderr, + "Warning: cannot create a convertor for \"%s\" to \"%s\": %s\n", + fromcode, tocode, strerror (err)); + } + + return conv; +} + /* Return a string based on TEXT converted according to HOW. If length is not -1, then it must be the number of bytes in TEXT. The returned string must be freed when no longer required. @@ -54,11 +75,17 @@ recode_string(enum conv_id how, const char *text, int length) /* FIXME: Need to ensure that this char is valid in the target encoding */ const char fallbackchar = '?'; + if ( text == NULL ) + return NULL; + if ( length == -1 ) length = strlen(text); assert(how < n_CONV); + if (convertor[how] == (iconv_t) -1) + return xstrndup (text, length); + for ( outbufferlength = 1 ; outbufferlength != 0; outbufferlength <<= 1 ) if ( outbufferlength > length) break; @@ -71,8 +98,6 @@ recode_string(enum conv_id how, const char *text, int length) inbytes = length; do { - - result = iconv(convertor[how], &ip, &inbytes, &op, &outbytes); @@ -108,11 +133,17 @@ recode_string(enum conv_id how, const char *text, int length) } } - } while ( -1 == result ); + if (outbytes == 0 ) + { + char *const oldaddr = outbuf; + outbuf = xrealloc(outbuf, outbufferlength + 1); + + op += (outbuf - oldaddr) ; + } + *op = '\0'; - return outbuf; } @@ -144,10 +175,10 @@ set_pspp_locale(const char *l) setlocale(LC_CTYPE, current_locale); iconv_close(convertor[CONV_PSPP_TO_UTF8]); - convertor[CONV_PSPP_TO_UTF8] = iconv_open("UTF-8", charset); + convertor[CONV_PSPP_TO_UTF8] = create_iconv ("UTF-8", charset); iconv_close(convertor[CONV_SYSTEM_TO_PSPP]); - convertor[CONV_SYSTEM_TO_PSPP] = iconv_open(charset, current_charset); + convertor[CONV_SYSTEM_TO_PSPP] = create_iconv (charset, current_charset); } void @@ -159,8 +190,8 @@ i18n_init(void) setlocale(LC_CTYPE, locale); charset = locale_charset(); - convertor[CONV_PSPP_TO_UTF8] = iconv_open("UTF-8", charset); - convertor[CONV_SYSTEM_TO_PSPP] = iconv_open(charset, charset); + convertor[CONV_PSPP_TO_UTF8] = create_iconv ("UTF-8", charset); + convertor[CONV_SYSTEM_TO_PSPP] = create_iconv (charset, charset); } @@ -172,5 +203,10 @@ i18n_done(void) locale = 0; for(i = 0 ; i < n_CONV; ++i ) - iconv_close(convertor[i]); + { + if ( (iconv_t) -1 == convertor[i] ) + continue; + iconv_close(convertor[i]); + } } +