/* Character set conversion support for GDB.
- Copyright (C) 2001, 2003, 2007, 2008, 2009, 2010
- Free Software Foundation, Inc.
+ Copyright (C) 2001, 2003, 2007-2012 Free Software Foundation, Inc.
This file is part of GDB.
#include "vec.h"
#include "environ.h"
#include "arch-utils.h"
+#include "gdb_vecs.h"
#include <stddef.h>
#include "gdb_string.h"
#define EILSEQ ENOENT
#endif
-iconv_t
+static iconv_t
phony_iconv_open (const char *to, const char *from)
{
/* We allow conversions from UTF-32BE, wchar_t, and the host charset.
return !strcmp (from, "UTF-32BE");
}
-int
+static int
phony_iconv_close (iconv_t arg)
{
return 0;
}
-size_t
+static size_t
phony_iconv (iconv_t utf_flag, const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft)
{
desc = iconv_open (target_wide_cset, host_cset);
if (desc == (iconv_t) -1)
- error ("Cannot convert between character sets `%s' and `%s'",
+ error (_("Cannot convert between character sets `%s' and `%s'"),
target_wide_cset, host_cset);
iconv_close (desc);
desc = iconv_open (target_cset, host_cset);
if (desc == (iconv_t) -1)
- error ("Cannot convert between character sets `%s' and `%s'",
+ error (_("Cannot convert between character sets `%s' and `%s'"),
target_cset, host_cset);
iconv_close (desc);
desc = iconv_open (to, from);
if (desc == (iconv_t) -1)
- perror_with_name ("Converting character sets");
+ perror_with_name (_("Converting character sets"));
cleanups = make_cleanup (cleanup_iconv, &desc);
inleft = num_bytes;
/* Invalid input sequence. */
if (translit == translit_none)
- error (_("Could not convert character to `%s' character set"),
- to);
+ error (_("Could not convert character "
+ "to `%s' character set"), to);
/* We emit escape sequence for the bytes, skip them,
and try again. */
{
char octal[5];
- sprintf (octal, "\\%.3o", *inp & 0xff);
+ xsnprintf (octal, sizeof (octal), "\\%.3o", *inp & 0xff);
obstack_grow_str (output, octal);
++inp;
break;
default:
- perror_with_name ("Internal error while converting character sets");
+ perror_with_name (_("Internal error while "
+ "converting character sets"));
}
}
}
desc = iconv_open (INTERMEDIATE_ENCODING, charset);
if (desc == (iconv_t) -1)
- perror_with_name ("Converting character sets");
+ perror_with_name (_("Converting character sets"));
result = XNEW (struct wchar_iterator);
result->desc = desc;
return 0;
default:
- perror_with_name ("Internal error while converting character sets");
+ perror_with_name (_("Internal error while "
+ "converting character sets"));
}
}
extern initialize_file_ftype _initialize_charset; /* -Wmissing-prototype */
-DEF_VEC_P (char_ptr);
-
static VEC (char_ptr) *charsets;
#ifdef PHONY_ICONV
char *args[3];
int err, status;
int fail = 1;
+ int flags;
struct gdb_environ *iconv_env;
+ char *iconv_program;
/* Older iconvs, e.g. 2.2.2, don't omit the intro text if stdout is
not a tty. We need to recognize it and ignore it. This text is
child = pex_init (PEX_USE_PIPES, "iconv", NULL);
- args[0] = "iconv";
+#ifdef ICONV_BIN
+ {
+ char *iconv_dir = relocate_gdb_directory (ICONV_BIN,
+ ICONV_BIN_RELOCATABLE);
+ iconv_program = concat (iconv_dir, SLASH_STRING, "iconv", NULL);
+ xfree (iconv_dir);
+ }
+#else
+ iconv_program = xstrdup ("iconv");
+#endif
+ args[0] = iconv_program;
args[1] = "-l";
args[2] = NULL;
+ flags = PEX_STDERR_TO_STDOUT;
+#ifndef ICONV_BIN
+ flags |= PEX_SEARCH;
+#endif
/* Note that we simply ignore errors here. */
- if (!pex_run_in_environment (child, PEX_SEARCH | PEX_STDERR_TO_STDOUT,
- "iconv", args, environ_vector (iconv_env),
+ if (!pex_run_in_environment (child, flags,
+ args[0], args, environ_vector (iconv_env),
NULL, NULL, &err))
{
FILE *in = pex_read_output (child, 0);
parse the glibc and libiconv formats; feel free to add others
as needed. */
- while (!feof (in))
+ while (in != NULL && !feof (in))
{
/* The size of buf is chosen arbitrarily. */
char buf[1024];
}
+ xfree (iconv_program);
pex_free (child);
free_environ (iconv_env);
if (fail)
{
/* Some error occurred, so drop the vector. */
- int ix;
- char *elt;
- for (ix = 0; VEC_iterate (char_ptr, charsets, ix, elt); ++ix)
- xfree (elt);
- VEC_truncate (char_ptr, charsets, 0);
+ free_char_ptr_vec (charsets);
+ charsets = NULL;
}
else
VEC_safe_push (char_ptr, charsets, NULL);
return GDB_DEFAULT_TARGET_WIDE_CHARSET;
}
+
+#ifdef USE_INTERMEDIATE_ENCODING_FUNCTION
+/* Macro used for UTF or UCS endianness suffix. */
+#if WORDS_BIGENDIAN
+#define ENDIAN_SUFFIX "BE"
+#else
+#define ENDIAN_SUFFIX "LE"
+#endif
+
+/* The code below serves to generate a compile time error if
+ gdb_wchar_t type is not of size 2 nor 4, despite the fact that
+ macro __STDC_ISO_10646__ is defined.
+ This is better than a gdb_assert call, because GDB cannot handle
+ strings correctly if this size is different. */
+
+extern char your_gdb_wchar_t_is_bogus[(sizeof (gdb_wchar_t) == 2
+ || sizeof (gdb_wchar_t) == 4)
+ ? 1 : -1];
+
+/* intermediate_encoding returns the charset unsed internally by
+ GDB to convert between target and host encodings. As the test above
+ compiled, sizeof (gdb_wchar_t) is either 2 or 4 bytes.
+ UTF-16/32 is tested first, UCS-2/4 is tested as a second option,
+ otherwise an error is generated. */
+
+const char *
+intermediate_encoding (void)
+{
+ iconv_t desc;
+ static const char *stored_result = NULL;
+ char *result;
+ int i;
+
+ if (stored_result)
+ return stored_result;
+ result = xstrprintf ("UTF-%d%s", (int) (sizeof (gdb_wchar_t) * 8),
+ ENDIAN_SUFFIX);
+ /* Check that the name is supported by iconv_open. */
+ desc = iconv_open (result, host_charset ());
+ if (desc != (iconv_t) -1)
+ {
+ iconv_close (desc);
+ stored_result = result;
+ return result;
+ }
+ /* Not valid, free the allocated memory. */
+ xfree (result);
+ /* Second try, with UCS-2 type. */
+ result = xstrprintf ("UCS-%d%s", (int) sizeof (gdb_wchar_t),
+ ENDIAN_SUFFIX);
+ /* Check that the name is supported by iconv_open. */
+ desc = iconv_open (result, host_charset ());
+ if (desc != (iconv_t) -1)
+ {
+ iconv_close (desc);
+ stored_result = result;
+ return result;
+ }
+ /* Not valid, free the allocated memory. */
+ xfree (result);
+ /* No valid charset found, generate error here. */
+ error (_("Unable to find a vaild charset for string conversions"));
+}
+
+#endif /* USE_INTERMEDIATE_ENCODING_FUNCTION */
+
void
_initialize_charset (void)
{
auto_target_charset_name = auto_host_charset_name;
#elif defined (USE_WIN32API)
{
- static char w32_host_default_charset[16]; /* "CP" + x<=5 digits + paranoia. */
+ /* "CP" + x<=5 digits + paranoia. */
+ static char w32_host_default_charset[16];
snprintf (w32_host_default_charset, sizeof w32_host_default_charset,
"CP%d", GetACP());
_("\
Set the target wide character set."), _("\
Show the target wide character set."), _("\
-The `target wide character set' is the one used by the program being debugged.\n\
-In particular it is the encoding used by `wchar_t'.\n\
+The `target wide character set' is the one used by the program being debugged.\
+\nIn particular it is the encoding used by `wchar_t'.\n\
GDB translates characters and strings between the host and target\n\
character sets as needed.\n\
To see a list of the character sets GDB supports, type\n\