X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fcharset.c;h=1af43fffa05859500a366d6fee99ab93b41a22c8;hb=2301204a3b3cd6553f7490498b3adc5973157c1b;hp=8a67c5c209dd67f48c2ead1bae71d58db68b0007;hpb=a9762ec78a53fbe9209fe1654db42df0cd328d50;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/charset.c b/gdb/charset.c index 8a67c5c209..1af43fffa0 100644 --- a/gdb/charset.c +++ b/gdb/charset.c @@ -1,6 +1,6 @@ /* Character set conversion support for GDB. - Copyright (C) 2001, 2003, 2007 Free Software Foundation, Inc. + Copyright (C) 2001-2020 Free Software Foundation, Inc. This file is part of GDB. @@ -20,28 +20,34 @@ #include "defs.h" #include "charset.h" #include "gdbcmd.h" -#include "gdb_assert.h" - -#include -#include "gdb_string.h" +#include "gdb_obstack.h" +#include "gdbsupport/gdb_wait.h" +#include "charset-list.h" +#include "gdbsupport/environ.h" +#include "arch-utils.h" +#include "gdbsupport/gdb_vecs.h" #include -#ifdef HAVE_ICONV -#include +#ifdef USE_WIN32API +#include #endif - /* How GDB's character set support works - GDB has two global settings: + GDB has three global settings: - The `current host character set' is the character set GDB should use in talking to the user, and which (hopefully) the user's - terminal knows how to display properly. + terminal knows how to display properly. Most users should not + change this. - The `current target character set' is the character set the program being debugged uses. + - The `current target wide character set' is the wide character set + the program being debugged uses, that is, the encoding used for + wchar_t. + There are commands to set each of these, and mechanisms for choosing reasonable default values. GDB has a global list of character sets that it can use as its host or target character @@ -57,1183 +63,976 @@ characters the user enters in expressions (mostly host->target conversions), - and so on. + and so on. + + To avoid excessive code duplication and maintenance efforts, + GDB simply requires a capable iconv function. Users on platforms + without a suitable iconv can use the GNU iconv library. */ - Now, many of these operations are specific to a particular - host/target character set pair. If GDB supports N character sets, - there are N^2 possible pairs. This means that, the larger GDB's - repertoire of character sets gets, the more expensive it gets to add - new character sets. + +#ifdef PHONY_ICONV - To make sure that GDB can do the right thing for every possible - pairing of host and target character set, while still allowing - GDB's repertoire to scale, we use a two-tiered approach: +/* Provide a phony iconv that does as little as possible. Also, + arrange for there to be a single available character set. */ - - We maintain a global table of "translations" --- groups of - functions specific to a particular pair of character sets. +#undef GDB_DEFAULT_HOST_CHARSET +#ifdef USE_WIN32API +# define GDB_DEFAULT_HOST_CHARSET "CP1252" +#else +# define GDB_DEFAULT_HOST_CHARSET "ISO-8859-1" +#endif +#define GDB_DEFAULT_TARGET_CHARSET GDB_DEFAULT_HOST_CHARSET +#define GDB_DEFAULT_TARGET_WIDE_CHARSET "UTF-32" +#undef DEFAULT_CHARSET_NAMES +#define DEFAULT_CHARSET_NAMES GDB_DEFAULT_HOST_CHARSET , + +#undef iconv_t +#define iconv_t int +#undef iconv_open +#define iconv_open phony_iconv_open +#undef iconv +#define iconv phony_iconv +#undef iconv_close +#define iconv_close phony_iconv_close + +#undef ICONV_CONST +#define ICONV_CONST const + +/* We allow conversions from UTF-32, wchar_t, and the host charset. + We allow conversions to wchar_t and the host charset. + Return 1 if we are converting from UTF-32BE, 2 if from UTF32-LE, + 0 otherwise. This is used as a flag in calls to iconv. */ + +static iconv_t +phony_iconv_open (const char *to, const char *from) +{ + if (strcmp (to, "wchar_t") && strcmp (to, GDB_DEFAULT_HOST_CHARSET)) + return -1; - - However, a translation can be incomplete: some functions can be - omitted. Where there is not a translation to specify exactly - what function to use, we provide reasonable defaults. The - default behaviors try to use the "iconv" library functions, which - support a wide range of character sets. However, even if iconv - is not available, there are fallbacks to support trivial - translations: when the host and target character sets are the - same. */ + if (!strcmp (from, "UTF-32BE") || !strcmp (from, "UTF-32")) + return 1; - -/* The character set and translation structures. */ + if (!strcmp (from, "UTF-32LE")) + return 2; + if (strcmp (from, "wchar_t") && strcmp (from, GDB_DEFAULT_HOST_CHARSET)) + return -1; + + return 0; +} -/* A character set GDB knows about. GDB only supports character sets - with stateless encodings, in which every character is one byte - long. */ -struct charset { +static int +phony_iconv_close (iconv_t arg) +{ + return 0; +} - /* A singly-linked list of all known charsets. */ - struct charset *next; +static size_t +phony_iconv (iconv_t utf_flag, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + if (utf_flag) + { + enum bfd_endian endian + = utf_flag == 1 ? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE; + while (*inbytesleft >= 4) + { + unsigned long c + = extract_unsigned_integer ((const gdb_byte *)*inbuf, 4, endian); + + if (c >= 256) + { + errno = EILSEQ; + return -1; + } + if (*outbytesleft < 1) + { + errno = E2BIG; + return -1; + } + **outbuf = c & 0xff; + ++*outbuf; + --*outbytesleft; + + *inbuf += 4; + *inbytesleft -= 4; + } + if (*inbytesleft) + { + /* Partial sequence on input. */ + errno = EINVAL; + return -1; + } + } + else + { + /* In all other cases we simply copy input bytes to the + output. */ + size_t amt = *inbytesleft; + + if (amt > *outbytesleft) + amt = *outbytesleft; + memcpy (*outbuf, *inbuf, amt); + *inbuf += amt; + *outbuf += amt; + *inbytesleft -= amt; + *outbytesleft -= amt; + if (*inbytesleft) + { + errno = E2BIG; + return -1; + } + } - /* The name of the character set. Comparisons on character set - names are case-sensitive. */ - const char *name; + /* The number of non-reversible conversions -- but they were all + reversible. */ + return 0; +} - /* Non-zero iff this character set can be used as a host character - set. At present, GDB basically assumes that the host character - set is a superset of ASCII. */ - int valid_host_charset; +#else /* PHONY_ICONV */ - /* Pointers to charset-specific functions that depend only on a - single character set, and data pointers to pass to them. */ - int (*host_char_print_literally) (void *baton, - int host_char); - void *host_char_print_literally_baton; +/* On systems that don't have EILSEQ, GNU iconv's iconv.h defines it + to ENOENT, while gnulib defines it to a different value. Always + map ENOENT to gnulib's EILSEQ, leaving callers agnostic. */ - int (*target_char_to_control_char) (void *baton, - int target_char, - int *target_ctrl_char); - void *target_char_to_control_char_baton; -}; +static size_t +gdb_iconv (iconv_t utf_flag, ICONV_CONST char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + size_t ret; + ret = iconv (utf_flag, inbuf, inbytesleft, outbuf, outbytesleft); + if (errno == ENOENT) + errno = EILSEQ; + return ret; +} -/* A translation from one character set to another. */ -struct translation { - - /* A singly-linked list of all known translations. */ - struct translation *next; - - /* This structure describes functions going from the FROM character - set to the TO character set. Comparisons on character set names - are case-sensitive. */ - const char *from, *to; - - /* Pointers to translation-specific functions, and data pointers to - pass to them. These pointers can be zero, indicating that GDB - should fall back on the default behavior. We hope the default - behavior will be correct for many from/to pairs, reducing the - number of translations that need to be registered explicitly. */ - - /* TARGET_CHAR is in the `from' charset. - Returns a string in the `to' charset. */ - const char *(*c_target_char_has_backslash_escape) (void *baton, - int target_char); - void *c_target_char_has_backslash_escape_baton; - - /* HOST_CHAR is in the `from' charset. - TARGET_CHAR points to a char in the `to' charset. */ - int (*c_parse_backslash) (void *baton, int host_char, int *target_char); - void *c_parse_backslash_baton; - - /* This is used for the host_char_to_target and target_char_to_host - functions. */ - int (*convert_char) (void *baton, int from, int *to); - void *convert_char_baton; -}; +#undef iconv +#define iconv gdb_iconv +#endif /* PHONY_ICONV */ /* The global lists of character sets and translations. */ -#ifndef GDB_DEFAULT_HOST_CHARSET -#define GDB_DEFAULT_HOST_CHARSET "ISO-8859-1" -#endif - #ifndef GDB_DEFAULT_TARGET_CHARSET #define GDB_DEFAULT_TARGET_CHARSET "ISO-8859-1" #endif -static const char *host_charset_name = GDB_DEFAULT_HOST_CHARSET; +#ifndef GDB_DEFAULT_TARGET_WIDE_CHARSET +#define GDB_DEFAULT_TARGET_WIDE_CHARSET "UTF-32" +#endif + +static const char *auto_host_charset_name = GDB_DEFAULT_HOST_CHARSET; +static const char *host_charset_name = "auto"; static void show_host_charset_name (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - fprintf_filtered (file, _("The host character set is \"%s\".\n"), value); + if (!strcmp (value, "auto")) + fprintf_filtered (file, + _("The host character set is \"auto; currently %s\".\n"), + auto_host_charset_name); + else + fprintf_filtered (file, _("The host character set is \"%s\".\n"), value); } -static const char *target_charset_name = GDB_DEFAULT_TARGET_CHARSET; +static const char *target_charset_name = "auto"; static void show_target_charset_name (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - fprintf_filtered (file, _("The target character set is \"%s\".\n"), - value); + if (!strcmp (value, "auto")) + fprintf_filtered (file, + _("The target character set is \"auto; " + "currently %s\".\n"), + gdbarch_auto_charset (get_current_arch ())); + else + fprintf_filtered (file, _("The target character set is \"%s\".\n"), + value); } - -static const char *host_charset_enum[] = -{ - "ASCII", - "ISO-8859-1", - 0 -}; - -static const char *target_charset_enum[] = -{ - "ASCII", - "ISO-8859-1", - "EBCDIC-US", - "IBM1047", - 0 -}; - -/* The global list of all the charsets GDB knows about. */ -static struct charset *all_charsets; - - +static const char *target_wide_charset_name = "auto"; static void -register_charset (struct charset *cs) +show_target_wide_charset_name (struct ui_file *file, + int from_tty, + struct cmd_list_element *c, + const char *value) { - struct charset **ptr; - - /* Put the new charset on the end, so that the list ends up in the - same order as the registrations in the _initialize function. */ - for (ptr = &all_charsets; *ptr; ptr = &(*ptr)->next) - ; - - cs->next = 0; - *ptr = cs; + if (!strcmp (value, "auto")) + fprintf_filtered (file, + _("The target wide character set is \"auto; " + "currently %s\".\n"), + gdbarch_auto_wide_charset (get_current_arch ())); + else + fprintf_filtered (file, _("The target wide character set is \"%s\".\n"), + value); } - -static struct charset * -lookup_charset (const char *name) +static const char *default_charset_names[] = { - struct charset *cs; - - for (cs = all_charsets; cs; cs = cs->next) - if (! strcmp (name, cs->name)) - return cs; + DEFAULT_CHARSET_NAMES + 0 +}; - return NULL; -} +static const char **charset_enum; + +/* If the target wide character set has big- or little-endian + variants, these are the corresponding names. */ +static const char *target_wide_charset_be_name; +static const char *target_wide_charset_le_name; -/* The global list of translations. */ -static struct translation *all_translations; +/* The architecture for which the BE- and LE-names are valid. */ +static struct gdbarch *be_le_arch; +/* A helper function which sets the target wide big- and little-endian + character set names, if possible. */ static void -register_translation (struct translation *t) -{ - t->next = all_translations; - all_translations = t; -} - - -static struct translation * -lookup_translation (const char *from, const char *to) +set_be_le_names (struct gdbarch *gdbarch) { - struct translation *t; - - for (t = all_translations; t; t = t->next) - if (! strcmp (from, t->from) - && ! strcmp (to, t->to)) - return t; - - return 0; + if (be_le_arch == gdbarch) + return; + be_le_arch = gdbarch; + +#ifdef PHONY_ICONV + /* Match the wide charset names recognized by phony_iconv_open. */ + target_wide_charset_le_name = "UTF-32LE"; + target_wide_charset_be_name = "UTF-32BE"; +#else + int i, len; + const char *target_wide; + + target_wide_charset_le_name = NULL; + target_wide_charset_be_name = NULL; + + target_wide = target_wide_charset_name; + if (!strcmp (target_wide, "auto")) + target_wide = gdbarch_auto_wide_charset (gdbarch); + + len = strlen (target_wide); + for (i = 0; charset_enum[i]; ++i) + { + if (strncmp (target_wide, charset_enum[i], len)) + continue; + if ((charset_enum[i][len] == 'B' + || charset_enum[i][len] == 'L') + && charset_enum[i][len + 1] == 'E' + && charset_enum[i][len + 2] == '\0') + { + if (charset_enum[i][len] == 'B') + target_wide_charset_be_name = charset_enum[i]; + else + target_wide_charset_le_name = charset_enum[i]; + } + } +# endif /* PHONY_ICONV */ } +/* 'Set charset', 'set host-charset', 'set target-charset', 'set + target-wide-charset', 'set charset' sfunc's. */ - -/* Constructing charsets. */ - -/* Allocate, initialize and return a straightforward charset. - Use this function, rather than creating the structures yourself, - so that we can add new fields to the structure in the future without - having to tweak all the old charset descriptions. */ -static struct charset * -simple_charset (const char *name, - int valid_host_charset, - int (*host_char_print_literally) (void *baton, int host_char), - void *host_char_print_literally_baton, - int (*target_char_to_control_char) (void *baton, - int target_char, - int *target_ctrl_char), - void *target_char_to_control_char_baton) +static void +validate (struct gdbarch *gdbarch) { - struct charset *cs = xmalloc (sizeof (*cs)); - - memset (cs, 0, sizeof (*cs)); - cs->name = name; - cs->valid_host_charset = valid_host_charset; - cs->host_char_print_literally = host_char_print_literally; - cs->host_char_print_literally_baton = host_char_print_literally_baton; - cs->target_char_to_control_char = target_char_to_control_char; - cs->target_char_to_control_char_baton = target_char_to_control_char_baton; - - return cs; + iconv_t desc; + const char *host_cset = host_charset (); + const char *target_cset = target_charset (gdbarch); + const char *target_wide_cset = target_wide_charset_name; + + if (!strcmp (target_wide_cset, "auto")) + target_wide_cset = gdbarch_auto_wide_charset (gdbarch); + + desc = iconv_open (target_wide_cset, host_cset); + if (desc == (iconv_t) -1) + 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'"), + target_cset, host_cset); + iconv_close (desc); + + /* Clear the cache. */ + be_le_arch = NULL; } - - -/* ASCII functions. */ - -static int -ascii_print_literally (void *baton, int c) +/* This is the sfunc for the 'set charset' command. */ +static void +set_charset_sfunc (const char *charset, int from_tty, + struct cmd_list_element *c) { - c &= 0xff; - - return (0x20 <= c && c <= 0x7e); + /* CAREFUL: set the target charset here as well. */ + target_charset_name = host_charset_name; + validate (get_current_arch ()); } - -static int -ascii_to_control (void *baton, int c, int *ctrl_char) +/* 'set host-charset' command sfunc. We need a wrapper here because + the function needs to have a specific signature. */ +static void +set_host_charset_sfunc (const char *charset, int from_tty, + struct cmd_list_element *c) { - *ctrl_char = (c & 037); - return 1; + validate (get_current_arch ()); } - -/* ISO-8859 family functions. */ - - -static int -iso_8859_print_literally (void *baton, int c) +/* Wrapper for the 'set target-charset' command. */ +static void +set_target_charset_sfunc (const char *charset, int from_tty, + struct cmd_list_element *c) { - c &= 0xff; - - return ((0x20 <= c && c <= 0x7e) /* ascii printables */ - || (! sevenbit_strings && 0xA0 <= c)); /* iso 8859 printables */ + validate (get_current_arch ()); } - -static int -iso_8859_to_control (void *baton, int c, int *ctrl_char) +/* Wrapper for the 'set target-wide-charset' command. */ +static void +set_target_wide_charset_sfunc (const char *charset, int from_tty, + struct cmd_list_element *c) { - *ctrl_char = (c & 0200) | (c & 037); - return 1; + validate (get_current_arch ()); } - -/* Construct an ISO-8859-like character set. */ -static struct charset * -iso_8859_family_charset (const char *name) +/* sfunc for the 'show charset' command. */ +static void +show_charset (struct ui_file *file, int from_tty, + struct cmd_list_element *c, + const char *name) { - return simple_charset (name, 1, - iso_8859_print_literally, 0, - iso_8859_to_control, 0); + show_host_charset_name (file, from_tty, c, host_charset_name); + show_target_charset_name (file, from_tty, c, target_charset_name); + show_target_wide_charset_name (file, from_tty, c, + target_wide_charset_name); } - -/* EBCDIC family functions. */ - +/* Accessor functions. */ -static int -ebcdic_print_literally (void *baton, int c) +const char * +host_charset (void) { - c &= 0xff; - - return (64 <= c && c <= 254); + if (!strcmp (host_charset_name, "auto")) + return auto_host_charset_name; + return host_charset_name; } - -static int -ebcdic_to_control (void *baton, int c, int *ctrl_char) +const char * +target_charset (struct gdbarch *gdbarch) { - /* There are no control character equivalents in EBCDIC. Use - numeric escapes. */ - return 0; + if (!strcmp (target_charset_name, "auto")) + return gdbarch_auto_charset (gdbarch); + return target_charset_name; } - -/* Construct an EBCDIC-like character set. */ -static struct charset * -ebcdic_family_charset (const char *name) +const char * +target_wide_charset (struct gdbarch *gdbarch) { - return simple_charset (name, 0, - ebcdic_print_literally, 0, - ebcdic_to_control, 0); -} - - - - - -/* Fallback functions using iconv. */ + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); -#if defined(HAVE_ICONV) - -struct cached_iconv { - struct charset *from, *to; - iconv_t i; -}; - - -/* Make sure the iconv cache *CI contains an iconv descriptor - translating from FROM to TO. If it already does, fine; otherwise, - close any existing descriptor, and open up a new one. On success, - return zero; on failure, return -1 and set errno. */ -static int -check_iconv_cache (struct cached_iconv *ci, - struct charset *from, - struct charset *to) -{ - iconv_t i; - - /* Does the cached iconv descriptor match the conversion we're trying - to do now? */ - if (ci->from == from - && ci->to == to - && ci->i != (iconv_t) 0) - return 0; - - /* It doesn't. If we actually had any iconv descriptor open at - all, close it now. */ - if (ci->i != (iconv_t) 0) + set_be_le_names (gdbarch); + if (byte_order == BFD_ENDIAN_BIG) { - i = ci->i; - ci->i = (iconv_t) 0; - - if (iconv_close (i) == -1) - error (_("Error closing `iconv' descriptor for " - "`%s'-to-`%s' character conversion: %s"), - ci->from->name, ci->to->name, safe_strerror (errno)); + if (target_wide_charset_be_name) + return target_wide_charset_be_name; } - - /* Open a new iconv descriptor for the required conversion. */ - i = iconv_open (to->name, from->name); - if (i == (iconv_t) -1) - return -1; - - ci->i = i; - ci->from = from; - ci->to = to; - - return 0; -} - - -/* Convert FROM_CHAR using the cached iconv conversion *CI. Return - non-zero if the conversion was successful, zero otherwise. */ -static int -cached_iconv_convert (struct cached_iconv *ci, int from_char, int *to_char) -{ - char from; - ICONV_CONST char *from_ptr = &from; - char to, *to_ptr = &to; - size_t from_left = sizeof (from), to_left = sizeof (to); - - gdb_assert (ci->i != (iconv_t) 0); - - from = from_char; - if (iconv (ci->i, &from_ptr, &from_left, &to_ptr, &to_left) - == (size_t) -1) + else { - /* These all suggest that the input or output character sets - have multi-byte encodings of some characters, which means - it's unsuitable for use as a GDB character set. We should - never have selected it. */ - gdb_assert (errno != E2BIG && errno != EINVAL); - - /* This suggests a bug in the code managing *CI. */ - gdb_assert (errno != EBADF); - - /* This seems to mean that there is no equivalent character in - the `to' character set. */ - if (errno == EILSEQ) - return 0; - - /* Anything else is mysterious. */ - internal_error (__FILE__, __LINE__, - _("Error converting character `%d' from `%s' to `%s' " - "character set: %s"), - from_char, ci->from->name, ci->to->name, - safe_strerror (errno)); + if (target_wide_charset_le_name) + return target_wide_charset_le_name; } - /* If the pointers weren't advanced across the input, that also - suggests something was wrong. */ - gdb_assert (from_left == 0 && to_left == 0); + if (!strcmp (target_wide_charset_name, "auto")) + return gdbarch_auto_wide_charset (gdbarch); - *to_char = (unsigned char) to; - return 1; + return target_wide_charset_name; } - -static void -register_iconv_charsets (void) -{ - /* Here we should check whether various character sets were - recognized by the local iconv implementation. - - The first implementation registered a bunch of character sets - recognized by iconv, but then we discovered that iconv on Solaris - and iconv on GNU/Linux had no character sets in common. So we - replaced them with the hard-coded tables that appear later in the - file. */ -} - -#endif /* defined (HAVE_ICONV) */ - -/* Fallback routines for systems without iconv. */ +/* Host character set management. For the time being, we assume that + the host character set is some superset of ASCII. */ -#if ! defined (HAVE_ICONV) -struct cached_iconv { char nothing; }; - -static int -check_iconv_cache (struct cached_iconv *ci, - struct charset *from, - struct charset *to) +char +host_letter_to_control_character (char c) { - errno = EINVAL; - return -1; + if (c == '?') + return 0177; + return c & 0237; } -static int -cached_iconv_convert (struct cached_iconv *ci, int from_char, int *to_char) -{ - /* This function should never be called. */ - gdb_assert (0); -} +/* Convert a host character, C, to its hex value. C must already have + been validated using isxdigit. */ -static void -register_iconv_charsets (void) +int +host_hex_value (char c) { + if (isdigit (c)) + return c - '0'; + if (c >= 'a' && c <= 'f') + return 10 + c - 'a'; + gdb_assert (c >= 'A' && c <= 'F'); + return 10 + c - 'A'; } -#endif /* ! defined(HAVE_ICONV) */ - -/* Default trivial conversion functions. */ +/* Public character management functions. */ -static int -identity_either_char_to_other (void *baton, int either_char, int *other_char) +class iconv_wrapper { - *other_char = either_char; - return 1; -} +public: + iconv_wrapper (const char *to, const char *from) + { + m_desc = iconv_open (to, from); + if (m_desc == (iconv_t) -1) + perror_with_name (_("Converting character sets")); + } - -/* Default non-trivial conversion functions. */ + ~iconv_wrapper () + { + iconv_close (m_desc); + } + size_t convert (ICONV_CONST char **inp, size_t *inleft, char **outp, + size_t *outleft) + { + return iconv (m_desc, inp, inleft, outp, outleft); + } -static char backslashable[] = "abfnrtv"; -static char *backslashed[] = {"a", "b", "f", "n", "r", "t", "v", "0"}; -static char represented[] = "\a\b\f\n\r\t\v"; +private: + iconv_t m_desc; +}; -/* Translate TARGET_CHAR into the host character set, and see if it - matches any of our standard escape sequences. */ -static const char * -default_c_target_char_has_backslash_escape (void *baton, int target_char) +void +convert_between_encodings (const char *from, const char *to, + const gdb_byte *bytes, unsigned int num_bytes, + int width, struct obstack *output, + enum transliterations translit) { - int host_char; - const char *ix; - - /* If target_char has no equivalent in the host character set, - assume it doesn't have a backslashed form. */ - if (! target_char_to_host (target_char, &host_char)) - return NULL; + size_t inleft; + ICONV_CONST char *inp; + unsigned int space_request; - ix = strchr (represented, host_char); - if (ix) - return backslashed[ix - represented]; - else - return NULL; -} + /* Often, the host and target charsets will be the same. */ + if (!strcmp (from, to)) + { + obstack_grow (output, bytes, num_bytes); + return; + } + iconv_wrapper desc (to, from); -/* Translate the backslash the way we would in the host character set, - and then try to translate that into the target character set. */ -static int -default_c_parse_backslash (void *baton, int host_char, int *target_char) -{ - const char *ix; + inleft = num_bytes; + inp = (ICONV_CONST char *) bytes; - ix = strchr (backslashable, host_char); + space_request = num_bytes; - if (! ix) - return 0; - else - return host_char_to_target (represented[ix - backslashable], - target_char); + while (inleft > 0) + { + char *outp; + size_t outleft, r; + int old_size; + + old_size = obstack_object_size (output); + obstack_blank (output, space_request); + + outp = (char *) obstack_base (output) + old_size; + outleft = space_request; + + r = desc.convert (&inp, &inleft, &outp, &outleft); + + /* Now make sure that the object on the obstack only includes + bytes we have converted. */ + obstack_blank_fast (output, -(ssize_t) outleft); + + if (r == (size_t) -1) + { + switch (errno) + { + case EILSEQ: + { + int i; + + /* Invalid input sequence. */ + if (translit == translit_none) + error (_("Could not convert character " + "to `%s' character set"), to); + + /* We emit escape sequence for the bytes, skip them, + and try again. */ + for (i = 0; i < width; ++i) + { + char octal[5]; + + xsnprintf (octal, sizeof (octal), "\\%.3o", *inp & 0xff); + obstack_grow_str (output, octal); + + ++inp; + --inleft; + } + } + break; + + case E2BIG: + /* We ran out of space in the output buffer. Make it + bigger next time around. */ + space_request *= 2; + break; + + case EINVAL: + /* Incomplete input sequence. FIXME: ought to report this + to the caller somehow. */ + inleft = 0; + break; + + default: + perror_with_name (_("Internal error while " + "converting character sets")); + } + } + } } + -/* Convert using a cached iconv descriptor. */ -static int -iconv_convert (void *baton, int from_char, int *to_char) +/* Create a new iterator. */ +wchar_iterator::wchar_iterator (const gdb_byte *input, size_t bytes, + const char *charset, size_t width) +: m_input (input), + m_bytes (bytes), + m_width (width), + m_out (1) { - struct cached_iconv *ci = baton; - return cached_iconv_convert (ci, from_char, to_char); + m_desc = iconv_open (INTERMEDIATE_ENCODING, charset); + if (m_desc == (iconv_t) -1) + perror_with_name (_("Converting character sets")); } - - -/* Conversion tables. */ - - -/* I'd much rather fall back on iconv whenever possible. But the - character set names you use with iconv aren't standardized at all, - a lot of platforms have really meager character set coverage, etc. - I wanted to have at least something we could use to exercise the - test suite on all platforms. - - In the long run, we should have a configure-time process explore - somehow which character sets the host platform supports, and some - arrangement that allows GDB users to use platform-indepedent names - for character sets. */ - - -/* We generated these tables using iconv on a GNU/Linux machine. */ - - -static int ascii_to_iso_8859_1_table[] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 16 */ - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* 32 */ - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, /* 48 */ - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, /* 64 */ - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, /* 80 */ - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, /* 96 */ - 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, /* 112 */ - 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, /* 128 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 144 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 160 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 176 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 192 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 208 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 224 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 240 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 256 */ -}; - - -static int ascii_to_ebcdic_us_table[] = { - 0, 1, 2, 3, 55, 45, 46, 47, 22, 5, 37, 11, 12, 13, 14, 15, /* 16 */ - 16, 17, 18, 19, 60, 61, 50, 38, 24, 25, 63, 39, 28, 29, 30, 31, /* 32 */ - 64, 90,127,123, 91,108, 80,125, 77, 93, 92, 78,107, 96, 75, 97, /* 48 */ - 240,241,242,243,244,245,246,247,248,249,122, 94, 76,126,110,111, /* 64 */ - 124,193,194,195,196,197,198,199,200,201,209,210,211,212,213,214, /* 80 */ - 215,216,217,226,227,228,229,230,231,232,233, -1,224, -1, -1,109, /* 96 */ - 121,129,130,131,132,133,134,135,136,137,145,146,147,148,149,150, /* 112 */ - 151,152,153,162,163,164,165,166,167,168,169,192, 79,208,161, 7, /* 128 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 144 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 160 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 176 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 192 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 208 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 224 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 240 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 256 */ -}; - - -static int ascii_to_ibm1047_table[] = { - 0, 1, 2, 3, 55, 45, 46, 47, 22, 5, 37, 11, 12, 13, 14, 15, /* 16 */ - 16, 17, 18, 19, 60, 61, 50, 38, 24, 25, 63, 39, 28, 29, 30, 31, /* 32 */ - 64, 90,127,123, 91,108, 80,125, 77, 93, 92, 78,107, 96, 75, 97, /* 48 */ - 240,241,242,243,244,245,246,247,248,249,122, 94, 76,126,110,111, /* 64 */ - 124,193,194,195,196,197,198,199,200,201,209,210,211,212,213,214, /* 80 */ - 215,216,217,226,227,228,229,230,231,232,233,173,224,189, 95,109, /* 96 */ - 121,129,130,131,132,133,134,135,136,137,145,146,147,148,149,150, /* 112 */ - 151,152,153,162,163,164,165,166,167,168,169,192, 79,208,161, 7, /* 128 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 144 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 160 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 176 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 192 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 208 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 224 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 240 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 256 */ -}; - - -static int iso_8859_1_to_ascii_table[] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 16 */ - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* 32 */ - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, /* 48 */ - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, /* 64 */ - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, /* 80 */ - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, /* 96 */ - 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, /* 112 */ - 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, /* 128 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 144 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 160 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 176 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 192 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 208 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 224 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 240 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 256 */ -}; - - -static int iso_8859_1_to_ebcdic_us_table[] = { - 0, 1, 2, 3, 55, 45, 46, 47, 22, 5, 37, 11, 12, 13, 14, 15, /* 16 */ - 16, 17, 18, 19, 60, 61, 50, 38, 24, 25, 63, 39, 28, 29, 30, 31, /* 32 */ - 64, 90,127,123, 91,108, 80,125, 77, 93, 92, 78,107, 96, 75, 97, /* 48 */ - 240,241,242,243,244,245,246,247,248,249,122, 94, 76,126,110,111, /* 64 */ - 124,193,194,195,196,197,198,199,200,201,209,210,211,212,213,214, /* 80 */ - 215,216,217,226,227,228,229,230,231,232,233, -1,224, -1, -1,109, /* 96 */ - 121,129,130,131,132,133,134,135,136,137,145,146,147,148,149,150, /* 112 */ - 151,152,153,162,163,164,165,166,167,168,169,192, 79,208,161, 7, /* 128 */ - 32, 33, 34, 35, 36, 21, 6, 23, 40, 41, 42, 43, 44, 9, 10, 27, /* 144 */ - 48, 49, 26, 51, 52, 53, 54, 8, 56, 57, 58, 59, 4, 20, 62,255, /* 160 */ - -1, -1, 74, -1, -1, -1,106, -1, -1, -1, -1, -1, 95, -1, -1, -1, /* 176 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 192 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 208 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 224 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 240 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 256 */ -}; - - -static int iso_8859_1_to_ibm1047_table[] = { - 0, 1, 2, 3, 55, 45, 46, 47, 22, 5, 37, 11, 12, 13, 14, 15, /* 16 */ - 16, 17, 18, 19, 60, 61, 50, 38, 24, 25, 63, 39, 28, 29, 30, 31, /* 32 */ - 64, 90,127,123, 91,108, 80,125, 77, 93, 92, 78,107, 96, 75, 97, /* 48 */ - 240,241,242,243,244,245,246,247,248,249,122, 94, 76,126,110,111, /* 64 */ - 124,193,194,195,196,197,198,199,200,201,209,210,211,212,213,214, /* 80 */ - 215,216,217,226,227,228,229,230,231,232,233,173,224,189, 95,109, /* 96 */ - 121,129,130,131,132,133,134,135,136,137,145,146,147,148,149,150, /* 112 */ - 151,152,153,162,163,164,165,166,167,168,169,192, 79,208,161, 7, /* 128 */ - 32, 33, 34, 35, 36, 21, 6, 23, 40, 41, 42, 43, 44, 9, 10, 27, /* 144 */ - 48, 49, 26, 51, 52, 53, 54, 8, 56, 57, 58, 59, 4, 20, 62,255, /* 160 */ - 65,170, 74,177,159,178,106,181,187,180,154,138,176,202,175,188, /* 176 */ - 144,143,234,250,190,160,182,179,157,218,155,139,183,184,185,171, /* 192 */ - 100,101, 98,102, 99,103,158,104,116,113,114,115,120,117,118,119, /* 208 */ - 172,105,237,238,235,239,236,191,128,253,254,251,252,186,174, 89, /* 224 */ - 68, 69, 66, 70, 67, 71,156, 72, 84, 81, 82, 83, 88, 85, 86, 87, /* 240 */ - 140, 73,205,206,203,207,204,225,112,221,222,219,220,141,142,223 /* 256 */ -}; - - -static int ebcdic_us_to_ascii_table[] = { - 0, 1, 2, 3, -1, 9, -1,127, -1, -1, -1, 11, 12, 13, 14, 15, /* 16 */ - 16, 17, 18, 19, -1, -1, 8, -1, 24, 25, -1, -1, 28, 29, 30, 31, /* 32 */ - -1, -1, -1, -1, -1, 10, 23, 27, -1, -1, -1, -1, -1, 5, 6, 7, /* 48 */ - -1, -1, 22, -1, -1, -1, -1, 4, -1, -1, -1, -1, 20, 21, -1, 26, /* 64 */ - 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 46, 60, 40, 43,124, /* 80 */ - 38, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, 36, 42, 41, 59, -1, /* 96 */ - 45, 47, -1, -1, -1, -1, -1, -1, -1, -1, -1, 44, 37, 95, 62, 63, /* 112 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, 96, 58, 35, 64, 39, 61, 34, /* 128 */ - -1, 97, 98, 99,100,101,102,103,104,105, -1, -1, -1, -1, -1, -1, /* 144 */ - -1,106,107,108,109,110,111,112,113,114, -1, -1, -1, -1, -1, -1, /* 160 */ - -1,126,115,116,117,118,119,120,121,122, -1, -1, -1, -1, -1, -1, /* 176 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 192 */ - 123, 65, 66, 67, 68, 69, 70, 71, 72, 73, -1, -1, -1, -1, -1, -1, /* 208 */ - 125, 74, 75, 76, 77, 78, 79, 80, 81, 82, -1, -1, -1, -1, -1, -1, /* 224 */ - 92, -1, 83, 84, 85, 86, 87, 88, 89, 90, -1, -1, -1, -1, -1, -1, /* 240 */ - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, -1, -1, -1, -1, -1 /* 256 */ -}; - - -static int ebcdic_us_to_iso_8859_1_table[] = { - 0, 1, 2, 3,156, 9,134,127,151,141,142, 11, 12, 13, 14, 15, /* 16 */ - 16, 17, 18, 19,157,133, 8,135, 24, 25,146,143, 28, 29, 30, 31, /* 32 */ - 128,129,130,131,132, 10, 23, 27,136,137,138,139,140, 5, 6, 7, /* 48 */ - 144,145, 22,147,148,149,150, 4,152,153,154,155, 20, 21,158, 26, /* 64 */ - 32, -1, -1, -1, -1, -1, -1, -1, -1, -1,162, 46, 60, 40, 43,124, /* 80 */ - 38, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, 36, 42, 41, 59,172, /* 96 */ - 45, 47, -1, -1, -1, -1, -1, -1, -1, -1,166, 44, 37, 95, 62, 63, /* 112 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, 96, 58, 35, 64, 39, 61, 34, /* 128 */ - -1, 97, 98, 99,100,101,102,103,104,105, -1, -1, -1, -1, -1, -1, /* 144 */ - -1,106,107,108,109,110,111,112,113,114, -1, -1, -1, -1, -1, -1, /* 160 */ - -1,126,115,116,117,118,119,120,121,122, -1, -1, -1, -1, -1, -1, /* 176 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 192 */ - 123, 65, 66, 67, 68, 69, 70, 71, 72, 73, -1, -1, -1, -1, -1, -1, /* 208 */ - 125, 74, 75, 76, 77, 78, 79, 80, 81, 82, -1, -1, -1, -1, -1, -1, /* 224 */ - 92, -1, 83, 84, 85, 86, 87, 88, 89, 90, -1, -1, -1, -1, -1, -1, /* 240 */ - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, -1, -1, -1, -1,159 /* 256 */ -}; - - -static int ebcdic_us_to_ibm1047_table[] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 16 */ - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* 32 */ - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, /* 48 */ - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, /* 64 */ - 64, -1, -1, -1, -1, -1, -1, -1, -1, -1, 74, 75, 76, 77, 78, 79, /* 80 */ - 80, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, 92, 93, 94,176, /* 96 */ - 96, 97, -1, -1, -1, -1, -1, -1, -1, -1,106,107,108,109,110,111, /* 112 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1,121,122,123,124,125,126,127, /* 128 */ - -1,129,130,131,132,133,134,135,136,137, -1, -1, -1, -1, -1, -1, /* 144 */ - -1,145,146,147,148,149,150,151,152,153, -1, -1, -1, -1, -1, -1, /* 160 */ - -1,161,162,163,164,165,166,167,168,169, -1, -1, -1, -1, -1, -1, /* 176 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 192 */ - 192,193,194,195,196,197,198,199,200,201, -1, -1, -1, -1, -1, -1, /* 208 */ - 208,209,210,211,212,213,214,215,216,217, -1, -1, -1, -1, -1, -1, /* 224 */ - 224, -1,226,227,228,229,230,231,232,233, -1, -1, -1, -1, -1, -1, /* 240 */ - 240,241,242,243,244,245,246,247,248,249, -1, -1, -1, -1, -1,255 /* 256 */ -}; - - -static int ibm1047_to_ascii_table[] = { - 0, 1, 2, 3, -1, 9, -1,127, -1, -1, -1, 11, 12, 13, 14, 15, /* 16 */ - 16, 17, 18, 19, -1, -1, 8, -1, 24, 25, -1, -1, 28, 29, 30, 31, /* 32 */ - -1, -1, -1, -1, -1, 10, 23, 27, -1, -1, -1, -1, -1, 5, 6, 7, /* 48 */ - -1, -1, 22, -1, -1, -1, -1, 4, -1, -1, -1, -1, 20, 21, -1, 26, /* 64 */ - 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 46, 60, 40, 43,124, /* 80 */ - 38, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, 36, 42, 41, 59, 94, /* 96 */ - 45, 47, -1, -1, -1, -1, -1, -1, -1, -1, -1, 44, 37, 95, 62, 63, /* 112 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, 96, 58, 35, 64, 39, 61, 34, /* 128 */ - -1, 97, 98, 99,100,101,102,103,104,105, -1, -1, -1, -1, -1, -1, /* 144 */ - -1,106,107,108,109,110,111,112,113,114, -1, -1, -1, -1, -1, -1, /* 160 */ - -1,126,115,116,117,118,119,120,121,122, -1, -1, -1, 91, -1, -1, /* 176 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 93, -1, -1, /* 192 */ - 123, 65, 66, 67, 68, 69, 70, 71, 72, 73, -1, -1, -1, -1, -1, -1, /* 208 */ - 125, 74, 75, 76, 77, 78, 79, 80, 81, 82, -1, -1, -1, -1, -1, -1, /* 224 */ - 92, -1, 83, 84, 85, 86, 87, 88, 89, 90, -1, -1, -1, -1, -1, -1, /* 240 */ - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, -1, -1, -1, -1, -1 /* 256 */ -}; - - -static int ibm1047_to_iso_8859_1_table[] = { - 0, 1, 2, 3,156, 9,134,127,151,141,142, 11, 12, 13, 14, 15, /* 16 */ - 16, 17, 18, 19,157,133, 8,135, 24, 25,146,143, 28, 29, 30, 31, /* 32 */ - 128,129,130,131,132, 10, 23, 27,136,137,138,139,140, 5, 6, 7, /* 48 */ - 144,145, 22,147,148,149,150, 4,152,153,154,155, 20, 21,158, 26, /* 64 */ - 32,160,226,228,224,225,227,229,231,241,162, 46, 60, 40, 43,124, /* 80 */ - 38,233,234,235,232,237,238,239,236,223, 33, 36, 42, 41, 59, 94, /* 96 */ - 45, 47,194,196,192,193,195,197,199,209,166, 44, 37, 95, 62, 63, /* 112 */ - 248,201,202,203,200,205,206,207,204, 96, 58, 35, 64, 39, 61, 34, /* 128 */ - 216, 97, 98, 99,100,101,102,103,104,105,171,187,240,253,254,177, /* 144 */ - 176,106,107,108,109,110,111,112,113,114,170,186,230,184,198,164, /* 160 */ - 181,126,115,116,117,118,119,120,121,122,161,191,208, 91,222,174, /* 176 */ - 172,163,165,183,169,167,182,188,189,190,221,168,175, 93,180,215, /* 192 */ - 123, 65, 66, 67, 68, 69, 70, 71, 72, 73,173,244,246,242,243,245, /* 208 */ - 125, 74, 75, 76, 77, 78, 79, 80, 81, 82,185,251,252,249,250,255, /* 224 */ - 92,247, 83, 84, 85, 86, 87, 88, 89, 90,178,212,214,210,211,213, /* 240 */ - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,179,219,220,217,218,159 /* 256 */ -}; - - -static int ibm1047_to_ebcdic_us_table[] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 16 */ - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* 32 */ - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, /* 48 */ - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, /* 64 */ - 64, -1, -1, -1, -1, -1, -1, -1, -1, -1, 74, 75, 76, 77, 78, 79, /* 80 */ - 80, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, 92, 93, 94, -1, /* 96 */ - 96, 97, -1, -1, -1, -1, -1, -1, -1, -1,106,107,108,109,110,111, /* 112 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1,121,122,123,124,125,126,127, /* 128 */ - -1,129,130,131,132,133,134,135,136,137, -1, -1, -1, -1, -1, -1, /* 144 */ - -1,145,146,147,148,149,150,151,152,153, -1, -1, -1, -1, -1, -1, /* 160 */ - -1,161,162,163,164,165,166,167,168,169, -1, -1, -1, -1, -1, -1, /* 176 */ - 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 192 */ - 192,193,194,195,196,197,198,199,200,201, -1, -1, -1, -1, -1, -1, /* 208 */ - 208,209,210,211,212,213,214,215,216,217, -1, -1, -1, -1, -1, -1, /* 224 */ - 224, -1,226,227,228,229,230,231,232,233, -1, -1, -1, -1, -1, -1, /* 240 */ - 240,241,242,243,244,245,246,247,248,249, -1, -1, -1, -1, -1,255 /* 256 */ -}; - - -static int -table_convert_char (void *baton, int from, int *to) +wchar_iterator::~wchar_iterator () { - int *table = (int *) baton; + if (m_desc != (iconv_t) -1) + iconv_close (m_desc); +} - if (0 <= from && from <= 255 - && table[from] != -1) +int +wchar_iterator::iterate (enum wchar_iterate_result *out_result, + gdb_wchar_t **out_chars, + const gdb_byte **ptr, + size_t *len) +{ + size_t out_request; + + /* Try to convert some characters. At first we try to convert just + a single character. The reason for this is that iconv does not + necessarily update its outgoing arguments when it encounters an + invalid input sequence -- but we want to reliably report this to + our caller so it can emit an escape sequence. */ + out_request = 1; + while (m_bytes > 0) { - *to = table[from]; - return 1; + ICONV_CONST char *inptr = (ICONV_CONST char *) m_input; + char *outptr = (char *) m_out.data (); + const gdb_byte *orig_inptr = m_input; + size_t orig_in = m_bytes; + size_t out_avail = out_request * sizeof (gdb_wchar_t); + size_t num; + size_t r = iconv (m_desc, &inptr, &m_bytes, &outptr, &out_avail); + + m_input = (gdb_byte *) inptr; + + if (r == (size_t) -1) + { + switch (errno) + { + case EILSEQ: + /* Invalid input sequence. We still might have + converted a character; if so, return it. */ + if (out_avail < out_request * sizeof (gdb_wchar_t)) + break; + + /* Otherwise skip the first invalid character, and let + the caller know about it. */ + *out_result = wchar_iterate_invalid; + *ptr = m_input; + *len = m_width; + m_input += m_width; + m_bytes -= m_width; + return 0; + + case E2BIG: + /* We ran out of space. We still might have converted a + character; if so, return it. Otherwise, grow the + buffer and try again. */ + if (out_avail < out_request * sizeof (gdb_wchar_t)) + break; + + ++out_request; + if (out_request > m_out.size ()) + m_out.resize (out_request); + continue; + + case EINVAL: + /* Incomplete input sequence. Let the caller know, and + arrange for future calls to see EOF. */ + *out_result = wchar_iterate_incomplete; + *ptr = m_input; + *len = m_bytes; + m_bytes = 0; + return 0; + + default: + perror_with_name (_("Internal error while " + "converting character sets")); + } + } + + /* We converted something. */ + num = out_request - out_avail / sizeof (gdb_wchar_t); + *out_result = wchar_iterate_ok; + *out_chars = m_out.data (); + *ptr = orig_inptr; + *len = orig_in - m_bytes; + return num; } - else - return 0; -} - -static struct translation * -table_translation (const char *from, const char *to, int *table, - const char *(*c_target_char_has_backslash_escape) - (void *baton, int target_char), - void *c_target_char_has_backslash_escape_baton, - int (*c_parse_backslash) (void *baton, - int host_char, - int *target_char), - void *c_parse_backslash_baton) -{ - struct translation *t = xmalloc (sizeof (*t)); - - memset (t, 0, sizeof (*t)); - t->from = from; - t->to = to; - t->c_target_char_has_backslash_escape = c_target_char_has_backslash_escape; - t->c_target_char_has_backslash_escape_baton - = c_target_char_has_backslash_escape_baton; - t->c_parse_backslash = c_parse_backslash; - t->c_parse_backslash_baton = c_parse_backslash_baton; - t->convert_char = table_convert_char; - t->convert_char_baton = (void *) table; - - return t; + /* Really done. */ + *out_result = wchar_iterate_eof; + return -1; } - -static struct translation * -simple_table_translation (const char *from, const char *to, int *table) +struct charset_vector { - return table_translation (from, to, table, 0, 0, 0, 0); -} - - - -/* Setting and retrieving the host and target charsets. */ - + ~charset_vector () + { + clear (); + } -/* The current host and target character sets. */ -static struct charset *current_host_charset, *current_target_charset; + void clear () + { + for (char *c : charsets) + xfree (c); -/* The current functions and batons we should use for the functions in - charset.h. */ + charsets.clear (); + } -static const char *(*c_target_char_has_backslash_escape_func) - (void *baton, int target_char); -static void *c_target_char_has_backslash_escape_baton; + std::vector charsets; +}; -static int (*c_parse_backslash_func) (void *baton, - int host_char, - int *target_char); -static void *c_parse_backslash_baton; +static charset_vector charsets; -static int (*host_char_to_target_func) (void *baton, - int host_char, - int *target_char); -static void *host_char_to_target_baton; +#ifdef PHONY_ICONV -static int (*target_char_to_host_func) (void *baton, - int target_char, - int *host_char); -static void *target_char_to_host_baton; +static void +find_charset_names (void) +{ + charsets.charsets.push_back (xstrdup (GDB_DEFAULT_HOST_CHARSET)); + charsets.charsets.push_back (NULL); +} +#else /* PHONY_ICONV */ -/* Cached iconv conversions, that might be useful to fallback - routines. */ -static struct cached_iconv cached_iconv_host_to_target; -static struct cached_iconv cached_iconv_target_to_host; +/* Sometimes, libiconv redefines iconvlist as libiconvlist -- but + provides different symbols in the static and dynamic libraries. + So, configure may see libiconvlist but not iconvlist. But, calling + iconvlist is the right thing to do and will work. Hence we do a + check here but unconditionally call iconvlist below. */ +#if defined (HAVE_ICONVLIST) || defined (HAVE_LIBICONVLIST) - -/* Charset structures manipulation functions. */ +/* A helper function that adds some character sets to the vector of + all character sets. This is a callback function for iconvlist. */ -static struct charset * -lookup_charset_or_error (const char *name) +static int +add_one (unsigned int count, const char *const *names, void *data) { - struct charset *cs = lookup_charset (name); - - if (! cs) - error (_("GDB doesn't know of any character set named `%s'."), name); + unsigned int i; - return cs; -} + for (i = 0; i < count; ++i) + charsets.charsets.push_back (xstrdup (names[i])); -static void -check_valid_host_charset (struct charset *cs) -{ - if (! cs->valid_host_charset) - error (_("GDB can't use `%s' as its host character set."), cs->name); + return 0; } -/* Set the host and target character sets to HOST and TARGET. */ static void -set_host_and_target_charsets (struct charset *host, struct charset *target) +find_charset_names (void) { - struct translation *h2t, *t2h; - - /* If they're not both initialized yet, then just do nothing for - now. As soon as we're done running our initialize function, - everything will be initialized. */ - if (! host || ! target) - { - current_host_charset = host; - current_target_charset = target; - return; - } - - h2t = lookup_translation (host->name, target->name); - t2h = lookup_translation (target->name, host->name); + iconvlist (add_one, NULL); - /* If the translations don't provide conversion functions, make sure - iconv can back them up. Do this *before* modifying any state. */ - if (host != target) - { - if (! h2t || ! h2t->convert_char) - { - if (check_iconv_cache (&cached_iconv_host_to_target, host, target) - < 0) - error (_("GDB can't convert from the `%s' character set to `%s'."), - host->name, target->name); - } - if (! t2h || ! t2h->convert_char) - { - if (check_iconv_cache (&cached_iconv_target_to_host, target, host) - < 0) - error (_("GDB can't convert from the `%s' character set to `%s'."), - target->name, host->name); - } - } + charsets.charsets.push_back (NULL); +} - if (t2h && t2h->c_target_char_has_backslash_escape) - { - c_target_char_has_backslash_escape_func - = t2h->c_target_char_has_backslash_escape; - c_target_char_has_backslash_escape_baton - = t2h->c_target_char_has_backslash_escape_baton; - } - else - c_target_char_has_backslash_escape_func - = default_c_target_char_has_backslash_escape; +#else - if (h2t && h2t->c_parse_backslash) - { - c_parse_backslash_func = h2t->c_parse_backslash; - c_parse_backslash_baton = h2t->c_parse_backslash_baton; - } - else - c_parse_backslash_func = default_c_parse_backslash; +/* Return non-zero if LINE (output from iconv) should be ignored. + Older iconv programs (e.g. 2.2.2) include the human readable + introduction even when stdout is not a tty. Newer versions omit + the intro if stdout is not a tty. */ - if (h2t && h2t->convert_char) - { - host_char_to_target_func = h2t->convert_char; - host_char_to_target_baton = h2t->convert_char_baton; - } - else if (host == target) - host_char_to_target_func = identity_either_char_to_other; - else +static int +ignore_line_p (const char *line) +{ + /* This table is used to filter the output. If this text appears + anywhere in the line, it is ignored (strstr is used). */ + static const char * const ignore_lines[] = { - host_char_to_target_func = iconv_convert; - host_char_to_target_baton = &cached_iconv_host_to_target; - } + "The following", + "not necessarily", + "the FROM and TO", + "listed with several", + NULL + }; + int i; - if (t2h && t2h->convert_char) + for (i = 0; ignore_lines[i] != NULL; ++i) { - target_char_to_host_func = t2h->convert_char; - target_char_to_host_baton = t2h->convert_char_baton; + if (strstr (line, ignore_lines[i]) != NULL) + return 1; } - else if (host == target) - target_char_to_host_func = identity_either_char_to_other; - else - { - target_char_to_host_func = iconv_convert; - target_char_to_host_baton = &cached_iconv_target_to_host; - } - - current_host_charset = host; - current_target_charset = target; -} - -/* Do the real work of setting the host charset. */ -static void -set_host_charset (const char *charset) -{ - struct charset *cs = lookup_charset_or_error (charset); - check_valid_host_charset (cs); - set_host_and_target_charsets (cs, current_target_charset); -} - -/* Do the real work of setting the target charset. */ -static void -set_target_charset (const char *charset) -{ - struct charset *cs = lookup_charset_or_error (charset); - set_host_and_target_charsets (current_host_charset, cs); + return 0; } - -/* 'Set charset', 'set host-charset', 'set target-charset', 'show - charset' sfunc's. */ - -/* This is the sfunc for the 'set charset' command. */ static void -set_charset_sfunc (char *charset, int from_tty, struct cmd_list_element *c) +find_charset_names (void) { - struct charset *cs = lookup_charset_or_error (host_charset_name); - check_valid_host_charset (cs); - /* CAREFUL: set the target charset here as well. */ - target_charset_name = host_charset_name; - set_host_and_target_charsets (cs, cs); -} + struct pex_obj *child; + const char *args[3]; + int err, status; + int fail = 1; + int flags; + gdb_environ iconv_env = gdb_environ::from_host_environ (); + 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 + subject to translation, so force LANGUAGE=C. */ + iconv_env.set ("LANGUAGE", "C"); + iconv_env.set ("LC_ALL", "C"); + + child = pex_init (PEX_USE_PIPES, "iconv", NULL); + +#ifdef ICONV_BIN + { + std::string iconv_dir = relocate_gdb_directory (ICONV_BIN, + ICONV_BIN_RELOCATABLE); + iconv_program = concat (iconv_dir.c_str(), SLASH_STRING, "iconv", NULL); + } +#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, flags, + args[0], const_cast (args), + iconv_env.envp (), + NULL, NULL, &err)) + { + FILE *in = pex_read_output (child, 0); + + /* POSIX says that iconv -l uses an unspecified format. We + parse the glibc and libiconv formats; feel free to add others + as needed. */ + + while (in != NULL && !feof (in)) + { + /* The size of buf is chosen arbitrarily. */ + char buf[1024]; + char *start, *r; + int len; + + r = fgets (buf, sizeof (buf), in); + if (!r) + break; + len = strlen (r); + if (len <= 3) + continue; + if (ignore_line_p (r)) + continue; + + /* Strip off the newline. */ + --len; + /* Strip off one or two '/'s. glibc will print lines like + "8859_7//", but also "10646-1:1993/UCS4/". */ + if (buf[len - 1] == '/') + --len; + if (buf[len - 1] == '/') + --len; + buf[len] = '\0'; + + /* libiconv will print multiple entries per line, separated + by spaces. Older iconvs will print multiple entries per + line, indented by two spaces, and separated by ", " + (i.e. the human readable form). */ + start = buf; + while (1) + { + int keep_going; + char *p; + + /* Skip leading blanks. */ + for (p = start; *p && *p == ' '; ++p) + ; + start = p; + /* Find the next space, comma, or end-of-line. */ + for ( ; *p && *p != ' ' && *p != ','; ++p) + ; + /* Ignore an empty result. */ + if (p == start) + break; + keep_going = *p; + *p = '\0'; + charsets.charsets.push_back (xstrdup (start)); + if (!keep_going) + break; + /* Skip any extra spaces. */ + for (start = p + 1; *start && *start == ' '; ++start) + ; + } + } + + if (pex_get_status (child, 1, &status) + && WIFEXITED (status) && !WEXITSTATUS (status)) + fail = 0; -/* 'set host-charset' command sfunc. We need a wrapper here because - the function needs to have a specific signature. */ -static void -set_host_charset_sfunc (char *charset, int from_tty, - struct cmd_list_element *c) -{ - set_host_charset (host_charset_name); -} + } -/* Wrapper for the 'set target-charset' command. */ -static void -set_target_charset_sfunc (char *charset, int from_tty, - struct cmd_list_element *c) -{ - set_target_charset (target_charset_name); -} + xfree (iconv_program); + pex_free (child); -/* sfunc for the 'show charset' command. */ -static void -show_charset (struct ui_file *file, int from_tty, struct cmd_list_element *c, - const char *name) -{ - if (current_host_charset == current_target_charset) - fprintf_filtered (file, - _("The current host and target character set is `%s'.\n"), - host_charset ()); - else + if (fail) { - fprintf_filtered (file, _("The current host character set is `%s'.\n"), - host_charset ()); - fprintf_filtered (file, _("The current target character set is `%s'.\n"), - target_charset ()); + /* Some error occurred, so drop the vector. */ + charsets.clear (); } + else + charsets.charsets.push_back (NULL); } - -/* Accessor functions. */ +#endif /* HAVE_ICONVLIST || HAVE_LIBICONVLIST */ +#endif /* PHONY_ICONV */ -const char * -host_charset (void) -{ - return current_host_charset->name; -} +/* The "auto" target charset used by default_auto_charset. */ +static const char *auto_target_charset_name = GDB_DEFAULT_TARGET_CHARSET; const char * -target_charset (void) +default_auto_charset (void) { - return current_target_charset->name; + return auto_target_charset_name; } - - -/* Public character management functions. */ - - const char * -c_target_char_has_backslash_escape (int target_char) -{ - return ((*c_target_char_has_backslash_escape_func) - (c_target_char_has_backslash_escape_baton, target_char)); -} - - -int -c_parse_backslash (int host_char, int *target_char) +default_auto_wide_charset (void) { - return (*c_parse_backslash_func) (c_parse_backslash_baton, - host_char, target_char); + return GDB_DEFAULT_TARGET_WIDE_CHARSET; } -int -host_char_print_literally (int host_char) -{ - return ((*current_host_charset->host_char_print_literally) - (current_host_charset->host_char_print_literally_baton, - host_char)); -} - - -int -target_char_to_control_char (int target_char, int *target_ctrl_char) -{ - return ((*current_target_charset->target_char_to_control_char) - (current_target_charset->target_char_to_control_char_baton, - target_char, target_ctrl_char)); -} +#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 +/* GDB cannot handle strings correctly if this size is different. */ -int -host_char_to_target (int host_char, int *target_char) -{ - return ((*host_char_to_target_func) - (host_char_to_target_baton, host_char, target_char)); -} +gdb_static_assert (sizeof (gdb_wchar_t) == 2 || sizeof (gdb_wchar_t) == 4); +/* intermediate_encoding returns the charset used 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. */ -int -target_char_to_host (int target_char, int *host_char) +const char * +intermediate_encoding (void) { - return ((*target_char_to_host_func) - (target_char_to_host_baton, target_char, host_char)); + iconv_t desc; + static const char *stored_result = NULL; + char *result; + + 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")); } - - -/* The charset.c module initialization function. */ - -extern initialize_file_ftype _initialize_charset; /* -Wmissing-prototype */ +#endif /* USE_INTERMEDIATE_ENCODING_FUNCTION */ void _initialize_charset (void) { - struct cmd_list_element *new_cmd; - - /* Register all the character set GDB knows about. - - You should use the same names that iconv does, where possible, to - take advantage of the iconv-based default behaviors. - - CAUTION: if you register a character set, you must also register - as many translations as are necessary to make that character set - interoperate correctly with all the other character sets. We do - provide default behaviors when no translation is available, or - when a translation's function pointer for a particular operation - is zero. Hopefully, these defaults will be correct often enough - that we won't need to provide too many translations. */ - register_charset (simple_charset ("ASCII", 1, - ascii_print_literally, 0, - ascii_to_control, 0)); - register_charset (iso_8859_family_charset ("ISO-8859-1")); - register_charset (ebcdic_family_charset ("EBCDIC-US")); - register_charset (ebcdic_family_charset ("IBM1047")); - register_iconv_charsets (); + /* The first element is always "auto". */ + charsets.charsets.push_back (xstrdup ("auto")); + find_charset_names (); + if (charsets.charsets.size () > 1) + charset_enum = (const char **) charsets.charsets.data (); + else + charset_enum = default_charset_names; + +#ifndef PHONY_ICONV +#ifdef HAVE_LANGINFO_CODESET + /* The result of nl_langinfo may be overwritten later. This may + leak a little memory, if the user later changes the host charset, + but that doesn't matter much. */ + auto_host_charset_name = xstrdup (nl_langinfo (CODESET)); + /* Solaris will return `646' here -- but the Solaris iconv then does + not accept this. Darwin (and maybe FreeBSD) may return "" here, + which GNU libiconv doesn't like (infinite loop). */ + if (!strcmp (auto_host_charset_name, "646") || !*auto_host_charset_name) + auto_host_charset_name = "ASCII"; + auto_target_charset_name = auto_host_charset_name; +#elif defined (USE_WIN32API) { - struct { char *from; char *to; int *table; } tlist[] = { - { "ASCII", "ISO-8859-1", ascii_to_iso_8859_1_table }, - { "ASCII", "EBCDIC-US", ascii_to_ebcdic_us_table }, - { "ASCII", "IBM1047", ascii_to_ibm1047_table }, - { "ISO-8859-1", "ASCII", iso_8859_1_to_ascii_table }, - { "ISO-8859-1", "EBCDIC-US", iso_8859_1_to_ebcdic_us_table }, - { "ISO-8859-1", "IBM1047", iso_8859_1_to_ibm1047_table }, - { "EBCDIC-US", "ASCII", ebcdic_us_to_ascii_table }, - { "EBCDIC-US", "ISO-8859-1", ebcdic_us_to_iso_8859_1_table }, - { "EBCDIC-US", "IBM1047", ebcdic_us_to_ibm1047_table }, - { "IBM1047", "ASCII", ibm1047_to_ascii_table }, - { "IBM1047", "ISO-8859-1", ibm1047_to_iso_8859_1_table }, - { "IBM1047", "EBCDIC-US", ibm1047_to_ebcdic_us_table } - }; + /* "CP" + x<=5 digits + paranoia. */ + static char w32_host_default_charset[16]; - int i; - - for (i = 0; i < (sizeof (tlist) / sizeof (tlist[0])); i++) - register_translation (simple_table_translation (tlist[i].from, - tlist[i].to, - tlist[i].table)); + snprintf (w32_host_default_charset, sizeof w32_host_default_charset, + "CP%d", GetACP()); + auto_host_charset_name = w32_host_default_charset; + auto_target_charset_name = auto_host_charset_name; } - - set_host_charset (host_charset_name); - set_target_charset (target_charset_name); +#endif +#endif add_setshow_enum_cmd ("charset", class_support, - host_charset_enum, &host_charset_name, _("\ + charset_enum, &host_charset_name, _("\ Set the host and target character sets."), _("\ Show the host and target character sets."), _("\ The `host character set' is the one used by the system GDB is running on.\n\ @@ -1249,7 +1048,7 @@ To see a list of the character sets GDB supports, type `set charset '."), &setlist, &showlist); add_setshow_enum_cmd ("host-charset", class_support, - host_charset_enum, &host_charset_name, _("\ + charset_enum, &host_charset_name, _("\ Set the host character set."), _("\ Show the host character set."), _("\ The `host character set' is the one used by the system GDB is running on.\n\ @@ -1261,7 +1060,7 @@ To see a list of the character sets GDB supports, type `set host-charset '. &setlist, &showlist); add_setshow_enum_cmd ("target-charset", class_support, - target_charset_enum, &target_charset_name, _("\ + charset_enum, &target_charset_name, _("\ Set the target character set."), _("\ Show the target character set."), _("\ The `target character set' is the one used by the program being debugged.\n\ @@ -1271,4 +1070,19 @@ To see a list of the character sets GDB supports, type `set target-charset' set_target_charset_sfunc, show_target_charset_name, &setlist, &showlist); + + add_setshow_enum_cmd ("target-wide-charset", class_support, + charset_enum, &target_wide_charset_name, + _("\ +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.\ +\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\ +`set target-wide-charset'"), + set_target_wide_charset_sfunc, + show_target_wide_charset_name, + &setlist, &showlist); }