X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flibpspp%2Fi18n.c;h=29148a0e7a9789cf9cbee7c5d6ac764c83f8ff10;hb=f5099c58d17e8f66a74a84918e688ef17936d392;hp=60dc693db6585a967ddae3cc82c37f26455587eb;hpb=2b84fc2b70df7767ee9a279fffab5db1b3c8023e;p=pspp-builds.git
diff --git a/src/libpspp/i18n.c b/src/libpspp/i18n.c
index 60dc693d..29148a0e 100644
--- a/src/libpspp/i18n.c
+++ b/src/libpspp/i18n.c
@@ -1,5 +1,5 @@
/* PSPP - a program for statistical analysis.
- Copyright (C) 2006, 2009, 2010 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2009, 2010, 2011 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -15,31 +15,30 @@
along with this program. If not, see . */
#include
-#include
+
+#include "libpspp/i18n.h"
+
#include
+#include
+#include
+#include
+#include
#include
-#include
#include
+#include
#include
-#include
-#include
-#include
-#include
-#include "assertion.h"
-#include "hmapx.h"
-#include "hash-functions.h"
-#include "pool.h"
-
-#include "i18n.h"
-#include "version.h"
+#include "libpspp/assertion.h"
+#include "libpspp/hmapx.h"
+#include "libpspp/hash-functions.h"
+#include "libpspp/pool.h"
+#include "libpspp/str.h"
+#include "libpspp/version.h"
-#include
-#include "xstrndup.h"
-
-#if HAVE_NL_LANGINFO
-#include
-#endif
+#include "gl/localcharset.h"
+#include "gl/xalloc.h"
+#include "gl/relocatable.h"
+#include "gl/xstrndup.h"
struct converter
{
@@ -86,6 +85,20 @@ create_iconv (const char* tocode, const char* fromcode)
return converter->conv;
}
+/* Converts the single byte C from encoding FROM to TO, returning the first
+ byte of the result.
+
+ This function probably shouldn't be used at all, but some code still does
+ use it. */
+char
+recode_byte (const char *to, const char *from, char c)
+{
+ char x;
+ char *s = recode_string (to, from, &c, 1);
+ x = s[0];
+ free (s);
+ return x;
+}
/* Similar to recode_string_pool, but allocates the returned value on the heap
instead of in a pool. It is the caller's responsibility to free the
@@ -97,18 +110,31 @@ recode_string (const char *to, const char *from,
return recode_string_pool (to, from, text, length, NULL);
}
+/* Returns the length, in bytes, of the string that a similar recode_string()
+ call would return. */
+size_t
+recode_string_len (const char *to, const char *from,
+ const char *text, int length)
+{
+ char *s = recode_string (to, from, text, length);
+ size_t len = strlen (s);
+ free (s);
+ return len;
+}
/* Uses CONV to convert the INBYTES starting at IP into the OUTBYTES starting
at OP, and appends a null terminator to the output.
- Returns true if successful, false if the output buffer is too small. */
-static bool
+ Returns the output length if successful, -1 if the output buffer is too
+ small. */
+static ssize_t
try_recode (iconv_t conv,
const char *ip, size_t inbytes,
- char *op, size_t outbytes)
+ char *op_, size_t outbytes)
{
/* FIXME: Need to ensure that this char is valid in the target encoding */
const char fallbackchar = '?';
+ char *op = op_;
/* Put the converter into the initial shift state, in case there was any
state information left over from its last usage. */
@@ -120,14 +146,14 @@ try_recode (iconv_t conv,
{
case EINVAL:
if (outbytes < 2)
- return false;
+ return -1;
*op++ = fallbackchar;
- *op++ = '\0';
- return true;
+ *op = '\0';
+ return op - op_;
case EILSEQ:
if (outbytes == 0)
- return false;
+ return -1;
*op++ = fallbackchar;
outbytes--;
ip++;
@@ -135,7 +161,7 @@ try_recode (iconv_t conv,
break;
case E2BIG:
- return false;
+ return -1;
default:
/* should never happen */
@@ -145,10 +171,10 @@ try_recode (iconv_t conv,
}
if (outbytes == 0)
- return false;
+ return -1;
*op = '\0';
- return true;
+ return op - op_;
}
/* Converts the string TEXT, which should be encoded in FROM-encoding, to a
@@ -167,14 +193,34 @@ char *
recode_string_pool (const char *to, const char *from,
const char *text, int length, struct pool *pool)
{
- size_t outbufferlength;
- iconv_t conv ;
+ struct substring out;
if ( text == NULL )
return NULL;
if ( length == -1 )
- length = strlen(text);
+ length = strlen (text);
+
+ out = recode_substring_pool (to, from, ss_buffer (text, length), pool);
+ return out.string;
+}
+
+/* Converts the string TEXT, which should be encoded in FROM-encoding, to a
+ dynamically allocated string in TO-encoding. Any characters which cannot be
+ converted will be represented by '?'.
+
+ The returned string will be null-terminated and allocated on POOL.
+
+ This function's behaviour differs from that of g_convert_with_fallback
+ provided by GLib. The GLib function will fail (returns NULL) if any part of
+ the input string is not valid in the declared input encoding. This function
+ however perseveres even in the presence of badly encoded input. */
+struct substring
+recode_substring_pool (const char *to, const char *from,
+ struct substring text, struct pool *pool)
+{
+ size_t outbufferlength;
+ iconv_t conv ;
if (to == NULL)
to = default_encoding;
@@ -185,14 +231,20 @@ recode_string_pool (const char *to, const char *from,
conv = create_iconv (to, from);
if ( (iconv_t) -1 == conv )
- return xstrdup (text);
+ {
+ struct substring out;
+ ss_alloc_substring_pool (&out, text, pool);
+ return out;
+ }
for ( outbufferlength = 1 ; outbufferlength != 0; outbufferlength <<= 1 )
- if ( outbufferlength > length)
+ if ( outbufferlength > text.length)
{
char *output = pool_malloc (pool, outbufferlength);
- if (try_recode (conv, text, length, output, outbufferlength))
- return output;
+ ssize_t output_len = try_recode (conv, text.string, text.length,
+ output, outbufferlength);
+ if (output_len >= 0)
+ return ss_buffer (output, output_len);
pool_free (pool, output);
}
@@ -202,17 +254,13 @@ recode_string_pool (const char *to, const char *from,
void
i18n_init (void)
{
-#if ENABLE_NLS
setlocale (LC_CTYPE, "");
-#ifdef LC_MESSAGES
setlocale (LC_MESSAGES, "");
-#endif
#if HAVE_LC_PAPER
setlocale (LC_PAPER, "");
#endif
bindtextdomain (PACKAGE, relocate(locale_dir));
textdomain (PACKAGE);
-#endif /* ENABLE_NLS */
assert (default_encoding == NULL);
default_encoding = xstrdup (locale_charset ());
@@ -302,7 +350,7 @@ i18n_done (void)
bool
valid_encoding (const char *enc)
{
- iconv_t conv = iconv_open ("UTF8", enc);
+ iconv_t conv = iconv_open (UTF8, enc);
if ( conv == (iconv_t) -1)
return false;
@@ -340,3 +388,12 @@ get_system_decimal (void)
return radix_char;
}
+const char *
+uc_name (ucs4_t uc, char buffer[16])
+{
+ if (uc >= 0x20 && uc < 0x7f)
+ snprintf (buffer, 16, "`%c'", uc);
+ else
+ snprintf (buffer, 16, "U+%04X", uc);
+ return buffer;
+}