From f870a310ee7fbfd6ccaea95d632063cbdbd2b9c9 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Fri, 5 Mar 2010 20:18:19 +0000 Subject: [PATCH] gdb 2010-03-05 Corinna Vinschen Tom Tromey * utils.c (host_char_to_target): Add 'gdbarch' argument. (parse_escape): Likewise. * python/py-utils.c (unicode_to_target_string): Update. (unicode_to_target_python_string): Update. (target_string_to_unicode): Update. * printcmd.c (printf_command): Update. * p-exp.y (yylex): Update. * objc-exp.y (yylex): Update. * mi/mi-parse.c: Include charset.h. (mi_parse_escape): New function. (mi_parse_argv): Use it. * jv-exp.y (yylex): Update. * i386-cygwin-tdep.c (i386_cygwin_auto_wide_charset): New function. (i386_cygwin_init_abi): Call set_gdbarch_auto_wide_charset. * gdbarch.sh (auto_charset, auto_wide_charset): New. * gdbarch.c: Rebuild. * gdbarch.h: Rebuild. * defs.h (parse_escape): Update. * cli/cli-setshow.c: Include arch-utils.h. (do_setshow_command): Update. * cli/cli-cmds.c (echo_command): Update. * charset.h (target_charset, target_wide_charset): Update. * charset.c: Include arch-utils.h. (target_charset_name): Default to "auto". (target_wide_charset_name): Likewise. (show_target_charset_name): Handle "auto". (show_target_wide_charset_name): Likewise. (be_le_arch): New global. (set_be_le_names): Add 'gdbarch' argument. (validate): Likewise. Don't call set_be_le_names. (set_charset_sfunc, set_host_charset_sfunc) (set_target_charset_sfunc, set_target_wide_charset_sfunc): Update. (target_charset): Add 'gdbarch' argument. (target_wide_charset): Likewise. Remove 'byte_order' argument. (auto_target_charset_name): New global. (default_auto_charset, default_auto_wide_charset): New functions. (_initialize_charset): Set auto_target_charset_name. Allow "auto" for target charsets. Copy result of nl_langinfo. Use GetACP if USE_WIN32API. * c-lang.c (charset_for_string_type): Add 'gdbarch' argument, remove 'byte_order' argument. Update. (classify_type): Likewise. (c_emit_char): Update. (c_printchar): Update. (c_printstr): Update. (c_get_string): Update. (evaluate_subexp_c): Update. * arch-utils.h (default_auto_charset, default_auto_wide_charset): Declare. * python/python.c (gdbpy_target_charset): New function. (gdbpy_target_wide_charset): Likewise. (GdbMethods): Update. * NEWS: Update. gdb/doc * gdb.texinfo (Basic Python): Document target_charset and target_wide_charset. gdb/testsuite * gdb.python/py-prettyprint.py (pp_nullstr.to_string): Use gdb.target_charset. (pp_ns.to_string): Likewise. --- gdb/ChangeLog | 59 ++++++++++ gdb/NEWS | 6 +- gdb/arch-utils.h | 3 + gdb/c-lang.c | 27 +++-- gdb/charset.c | 126 +++++++++++++++------ gdb/charset.h | 4 +- gdb/cli/cli-cmds.c | 2 +- gdb/cli/cli-setshow.c | 3 +- gdb/defs.h | 2 +- gdb/doc/ChangeLog | 5 + gdb/doc/gdb.texinfo | 15 +++ gdb/gdbarch.c | 48 ++++++++ gdb/gdbarch.h | 12 ++ gdb/gdbarch.sh | 5 + gdb/i386-cygwin-tdep.c | 8 ++ gdb/jv-exp.y | 4 +- gdb/mi/mi-parse.c | 77 ++++++++++++- gdb/objc-exp.y | 4 +- gdb/p-exp.y | 4 +- gdb/printcmd.c | 4 +- gdb/python/py-utils.c | 8 +- gdb/python/python.c | 25 ++++ gdb/testsuite/ChangeLog | 6 + gdb/testsuite/gdb.python/py-prettyprint.py | 4 +- gdb/utils.c | 10 +- 25 files changed, 398 insertions(+), 73 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index d922c27e9f1..5b9f6082cce 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,62 @@ +2010-03-05 Corinna Vinschen + Tom Tromey + + * utils.c (host_char_to_target): Add 'gdbarch' argument. + (parse_escape): Likewise. + * python/py-utils.c (unicode_to_target_string): Update. + (unicode_to_target_python_string): Update. + (target_string_to_unicode): Update. + * printcmd.c (printf_command): Update. + * p-exp.y (yylex): Update. + * objc-exp.y (yylex): Update. + * mi/mi-parse.c: Include charset.h. + (mi_parse_escape): New function. + (mi_parse_argv): Use it. + * jv-exp.y (yylex): Update. + * i386-cygwin-tdep.c (i386_cygwin_auto_wide_charset): New + function. + (i386_cygwin_init_abi): Call set_gdbarch_auto_wide_charset. + * gdbarch.sh (auto_charset, auto_wide_charset): New. + * gdbarch.c: Rebuild. + * gdbarch.h: Rebuild. + * defs.h (parse_escape): Update. + * cli/cli-setshow.c: Include arch-utils.h. + (do_setshow_command): Update. + * cli/cli-cmds.c (echo_command): Update. + * charset.h (target_charset, target_wide_charset): Update. + * charset.c: Include arch-utils.h. + (target_charset_name): Default to "auto". + (target_wide_charset_name): Likewise. + (show_target_charset_name): Handle "auto". + (show_target_wide_charset_name): Likewise. + (be_le_arch): New global. + (set_be_le_names): Add 'gdbarch' argument. + (validate): Likewise. Don't call set_be_le_names. + (set_charset_sfunc, set_host_charset_sfunc) + (set_target_charset_sfunc, set_target_wide_charset_sfunc): + Update. + (target_charset): Add 'gdbarch' argument. + (target_wide_charset): Likewise. Remove 'byte_order' argument. + (auto_target_charset_name): New global. + (default_auto_charset, default_auto_wide_charset): New functions. + (_initialize_charset): Set auto_target_charset_name. Allow "auto" + for target charsets. Copy result of nl_langinfo. Use GetACP if + USE_WIN32API. + * c-lang.c (charset_for_string_type): Add 'gdbarch' argument, + remove 'byte_order' argument. Update. + (classify_type): Likewise. + (c_emit_char): Update. + (c_printchar): Update. + (c_printstr): Update. + (c_get_string): Update. + (evaluate_subexp_c): Update. + * arch-utils.h (default_auto_charset, default_auto_wide_charset): + Declare. + * python/python.c (gdbpy_target_charset): New function. + (gdbpy_target_wide_charset): Likewise. + (GdbMethods): Update. + * NEWS: Update. + 2010-03-05 Ulrich Weigand * symfile.c (build_section_addr_info_from_objfile): Do not mask diff --git a/gdb/NEWS b/gdb/NEWS index e8c1935abbe..7e33caa17d9 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -13,8 +13,10 @@ * Python scripting -The GDB Python API now has access to symbols, symbol tables, and -frame's code blocks. +** The GDB Python API now has access to symbols, symbol tables, and + frame's code blocks. + +** New methods gdb.target_charset and gdb.target_wide_charset. * New targets diff --git a/gdb/arch-utils.h b/gdb/arch-utils.h index d5d7f1db54f..dbeb67f7379 100644 --- a/gdb/arch-utils.h +++ b/gdb/arch-utils.h @@ -162,4 +162,7 @@ extern int default_fast_tracepoint_valid_at (struct gdbarch *gdbarch, extern void default_remote_breakpoint_from_pc (struct gdbarch *, CORE_ADDR *pcptr, int *kindptr); +extern const char *default_auto_charset (void); +extern const char *default_auto_wide_charset (void); + #endif diff --git a/gdb/c-lang.c b/gdb/c-lang.c index d620881b0d8..fefd6755645 100644 --- a/gdb/c-lang.c +++ b/gdb/c-lang.c @@ -43,23 +43,23 @@ extern void _initialize_c_language (void); static const char * charset_for_string_type (enum c_string_type str_type, - enum bfd_endian byte_order) + struct gdbarch *gdbarch) { switch (str_type & ~C_CHAR) { case C_STRING: - return target_charset (); + return target_charset (gdbarch); case C_WIDE_STRING: - return target_wide_charset (byte_order); + return target_wide_charset (gdbarch); case C_STRING_16: /* FIXME: UTF-16 is not always correct. */ - if (byte_order == BFD_ENDIAN_BIG) + if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) return "UTF-16BE"; else return "UTF-16LE"; case C_STRING_32: /* FIXME: UTF-32 is not always correct. */ - if (byte_order == BFD_ENDIAN_BIG) + if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) return "UTF-32BE"; else return "UTF-32LE"; @@ -73,7 +73,7 @@ charset_for_string_type (enum c_string_type str_type, characters of this type in target BYTE_ORDER to the host character set. */ static enum c_string_type -classify_type (struct type *elttype, enum bfd_endian byte_order, +classify_type (struct type *elttype, struct gdbarch *gdbarch, const char **encoding) { struct type *saved_type; @@ -134,7 +134,7 @@ classify_type (struct type *elttype, enum bfd_endian byte_order, done: if (encoding) - *encoding = charset_for_string_type (result, byte_order); + *encoding = charset_for_string_type (result, gdbarch); return result; } @@ -264,7 +264,7 @@ c_emit_char (int c, struct type *type, struct ui_file *stream, int quoter) struct wchar_iterator *iter; int need_escape = 0; - classify_type (type, byte_order, &encoding); + classify_type (type, get_type_arch (type), &encoding); buf = alloca (TYPE_LENGTH (type)); pack_long (buf, type, c); @@ -340,7 +340,7 @@ c_printchar (int c, struct type *type, struct ui_file *stream) { enum c_string_type str_type; - str_type = classify_type (type, BFD_ENDIAN_UNKNOWN, NULL); + str_type = classify_type (type, get_type_arch (type), NULL); switch (str_type) { case C_CHAR: @@ -396,7 +396,8 @@ c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string, width, byte_order) == 0)) length--; - str_type = classify_type (type, byte_order, &type_encoding) & ~C_CHAR; + str_type = (classify_type (type, get_type_arch (type), &type_encoding) + & ~C_CHAR); switch (str_type) { case C_STRING: @@ -659,7 +660,7 @@ c_get_string (struct value *value, gdb_byte **buffer, int *length, if (! c_textual_element_type (element_type, 0)) goto error; kind = classify_type (element_type, - gdbarch_byte_order (get_type_arch (element_type)), + get_type_arch (element_type), charset); width = TYPE_LENGTH (element_type); @@ -942,7 +943,6 @@ evaluate_subexp_c (struct type *expect_type, struct expression *exp, struct value *result; enum c_string_type dest_type; const char *dest_charset; - enum bfd_endian byte_order; obstack_init (&output); cleanup = make_cleanup_obstack_free (&output); @@ -979,8 +979,7 @@ evaluate_subexp_c (struct type *expect_type, struct expression *exp, /* Ensure TYPE_LENGTH is valid for TYPE. */ check_typedef (type); - byte_order = gdbarch_byte_order (exp->gdbarch); - dest_charset = charset_for_string_type (dest_type, byte_order); + dest_charset = charset_for_string_type (dest_type, exp->gdbarch); ++*pos; while (*pos < limit) diff --git a/gdb/charset.c b/gdb/charset.c index 8977f272e58..9c1e7f48e70 100644 --- a/gdb/charset.c +++ b/gdb/charset.c @@ -27,6 +27,7 @@ #include "charset-list.h" #include "vec.h" #include "environ.h" +#include "arch-utils.h" #include #include "gdb_string.h" @@ -213,22 +214,34 @@ show_host_charset_name (struct ui_file *file, int from_tty, 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 *target_wide_charset_name = GDB_DEFAULT_TARGET_WIDE_CHARSET; +static const char *target_wide_charset_name = "auto"; static void show_target_wide_charset_name (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - fprintf_filtered (file, _("The target wide character set is \"%s\".\n"), - value); + 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 const char *default_charset_names[] = @@ -245,21 +258,33 @@ static const char **charset_enum; static const char *target_wide_charset_be_name; static const char *target_wide_charset_le_name; -/* A helper function for validate which sets the target wide big- and - little-endian character set names, if possible. */ +/* 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 -set_be_le_names (void) +set_be_le_names (struct gdbarch *gdbarch) { int i, len; + const char *target_wide; + + if (be_le_arch == gdbarch) + return; + be_le_arch = gdbarch; target_wide_charset_le_name = NULL; target_wide_charset_be_name = NULL; - len = strlen (target_wide_charset_name); + 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_name, charset_enum[i], len)) + if (strncmp (target_wide, charset_enum[i], len)) continue; if ((charset_enum[i][len] == 'B' || charset_enum[i][len] == 'L') @@ -278,24 +303,29 @@ set_be_le_names (void) target-wide-charset', 'set charset' sfunc's. */ static void -validate (void) +validate (struct gdbarch *gdbarch) { 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_charset_name, host_cset); + desc = iconv_open (target_wide_cset, host_cset); if (desc == (iconv_t) -1) error ("Cannot convert between character sets `%s' and `%s'", - target_wide_charset_name, host_cset); + target_wide_cset, host_cset); iconv_close (desc); - desc = iconv_open (target_charset_name, host_cset); + desc = iconv_open (target_cset, host_cset); if (desc == (iconv_t) -1) error ("Cannot convert between character sets `%s' and `%s'", - target_charset_name, host_cset); + target_cset, host_cset); iconv_close (desc); - set_be_le_names (); + /* Clear the cache. */ + be_le_arch = NULL; } /* This is the sfunc for the 'set charset' command. */ @@ -304,7 +334,7 @@ set_charset_sfunc (char *charset, int from_tty, struct cmd_list_element *c) { /* CAREFUL: set the target charset here as well. */ target_charset_name = host_charset_name; - validate (); + validate (get_current_arch ()); } /* 'set host-charset' command sfunc. We need a wrapper here because @@ -313,7 +343,7 @@ static void set_host_charset_sfunc (char *charset, int from_tty, struct cmd_list_element *c) { - validate (); + validate (get_current_arch ()); } /* Wrapper for the 'set target-charset' command. */ @@ -321,7 +351,7 @@ static void set_target_charset_sfunc (char *charset, int from_tty, struct cmd_list_element *c) { - validate (); + validate (get_current_arch ()); } /* Wrapper for the 'set target-wide-charset' command. */ @@ -329,7 +359,7 @@ static void set_target_wide_charset_sfunc (char *charset, int from_tty, struct cmd_list_element *c) { - validate (); + validate (get_current_arch ()); } /* sfunc for the 'show charset' command. */ @@ -354,14 +384,19 @@ host_charset (void) } const char * -target_charset (void) +target_charset (struct gdbarch *gdbarch) { + if (!strcmp (target_charset_name, "auto")) + return gdbarch_auto_charset (gdbarch); return target_charset_name; } const char * -target_wide_charset (enum bfd_endian byte_order) +target_wide_charset (struct gdbarch *gdbarch) { + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + + set_be_le_names (gdbarch); if (byte_order == BFD_ENDIAN_BIG) { if (target_wide_charset_be_name) @@ -373,6 +408,9 @@ target_wide_charset (enum bfd_endian byte_order) return target_wide_charset_le_name; } + if (!strcmp (target_wide_charset_name, "auto")) + return gdbarch_auto_wide_charset (gdbarch); + return target_wide_charset_name; } @@ -851,13 +889,27 @@ find_charset_names (void) #endif /* HAVE_ICONVLIST || HAVE_LIBICONVLIST */ #endif /* PHONY_ICONV */ +/* The "auto" target charset used by default_auto_charset. */ +static const char *auto_target_charset_name = GDB_DEFAULT_TARGET_CHARSET; + +const char * +default_auto_charset (void) +{ + return auto_target_charset_name; +} + +const char * +default_auto_wide_charset (void) +{ + return GDB_DEFAULT_TARGET_WIDE_CHARSET; +} + void _initialize_charset (void) { struct cmd_list_element *new_cmd; - /* The first element is always "auto"; then we skip it for the - commands where it is not allowed. */ + /* The first element is always "auto". */ VEC_safe_push (char_ptr, charsets, xstrdup ("auto")); find_charset_names (); @@ -868,20 +920,30 @@ _initialize_charset (void) #ifndef PHONY_ICONV #ifdef HAVE_LANGINFO_CODESET - auto_host_charset_name = nl_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"; - target_charset_name = auto_host_charset_name; - - set_be_le_names (); + auto_target_charset_name = auto_host_charset_name; +#elif defined (USE_WIN32API) + { + static w32_host_default_charset[16]; /* "CP" + x<=5 digits + paranoia. */ + + 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; + } #endif #endif add_setshow_enum_cmd ("charset", class_support, - &charset_enum[1], &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\ @@ -909,7 +971,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, - &charset_enum[1], &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\ @@ -921,7 +983,7 @@ To see a list of the character sets GDB supports, type `set target-charset' &setlist, &showlist); add_setshow_enum_cmd ("target-wide-charset", class_support, - &charset_enum[1], &target_wide_charset_name, + charset_enum, &target_wide_charset_name, _("\ Set the target wide character set."), _("\ Show the target wide character set."), _("\ diff --git a/gdb/charset.h b/gdb/charset.h index 77001685de6..bd93d01d7d0 100644 --- a/gdb/charset.h +++ b/gdb/charset.h @@ -33,8 +33,8 @@ result is owned by the charset module; the caller should not free it. */ const char *host_charset (void); -const char *target_charset (void); -const char *target_wide_charset (enum bfd_endian byte_order); +const char *target_charset (struct gdbarch *gdbarch); +const char *target_wide_charset (struct gdbarch *gdbarch); /* These values are used to specify the type of transliteration done by convert_between_encodings. */ diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c index 74009673757..bc792587a15 100644 --- a/gdb/cli/cli-cmds.c +++ b/gdb/cli/cli-cmds.c @@ -618,7 +618,7 @@ echo_command (char *text, int from_tty) if (*p == 0) return; - c = parse_escape (&p); + c = parse_escape (get_current_arch (), &p); if (c >= 0) printf_filtered ("%c", c); } diff --git a/gdb/cli/cli-setshow.c b/gdb/cli/cli-setshow.c index c1dafb4b320..d8ec10025c1 100644 --- a/gdb/cli/cli-setshow.c +++ b/gdb/cli/cli-setshow.c @@ -21,6 +21,7 @@ #include "value.h" #include #include "gdb_string.h" +#include "arch-utils.h" #include "ui-out.h" @@ -152,7 +153,7 @@ do_setshow_command (char *arg, int from_tty, struct cmd_list_element *c) right before a newline. */ if (*p == 0) break; - ch = parse_escape (&p); + ch = parse_escape (get_current_arch (), &p); if (ch == 0) break; /* C loses */ else if (ch > 0) diff --git a/gdb/defs.h b/gdb/defs.h index ca903b819b9..5983289f7a1 100644 --- a/gdb/defs.h +++ b/gdb/defs.h @@ -899,7 +899,7 @@ extern char *xstrvprintf (const char *format, va_list ap) extern int xsnprintf (char *str, size_t size, const char *format, ...) ATTR_FORMAT (printf, 3, 4); -extern int parse_escape (char **); +extern int parse_escape (struct gdbarch *, char **); /* Message to be printed before the error message, when an error occurs. */ diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 2bd09a898ac..bbd7895fb76 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,8 @@ +2010-03-05 Tom Tromey + + * gdb.texinfo (Basic Python): Document target_charset and + target_wide_charset. + 2010-03-05 Tom Tromey * gdb.texinfo (Data): Link to pretty-printing. diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 6ea3a60e00f..41b11b63ec7 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -19634,6 +19634,21 @@ Flush @value{GDBN}'s paginated standard output stream. Flushing function. @end defun +@findex gdb.target_charset +@defun target_charset +Return the name of the current target character set (@pxref{Character +Sets}). This differs from @code{gdb.parameter('target-charset')} in +that @samp{auto} is never returned. +@end defun + +@findex gdb.target_wide_charset +@defun target_wide_charset +Return the name of the current target wide character set +(@pxref{Character Sets}). This differs from +@code{gdb.parameter('target-wide-charset')} in that @samp{auto} is +never returned. +@end defun + @node Exception Handling @subsubsection Exception Handling @cindex python exceptions diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index cfb042b3265..f482572cfe8 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -253,6 +253,8 @@ struct gdbarch gdbarch_has_shared_address_space_ftype *has_shared_address_space; gdbarch_fast_tracepoint_valid_at_ftype *fast_tracepoint_valid_at; const char * qsupported; + gdbarch_auto_charset_ftype *auto_charset; + gdbarch_auto_wide_charset_ftype *auto_wide_charset; }; @@ -397,6 +399,8 @@ struct gdbarch startup_gdbarch = default_has_shared_address_space, /* has_shared_address_space */ default_fast_tracepoint_valid_at, /* fast_tracepoint_valid_at */ 0, /* qsupported */ + default_auto_charset, /* auto_charset */ + default_auto_wide_charset, /* auto_wide_charset */ /* startup_gdbarch() */ }; @@ -483,6 +487,8 @@ gdbarch_alloc (const struct gdbarch_info *info, gdbarch->target_signal_to_host = default_target_signal_to_host; gdbarch->has_shared_address_space = default_has_shared_address_space; gdbarch->fast_tracepoint_valid_at = default_fast_tracepoint_valid_at; + gdbarch->auto_charset = default_auto_charset; + gdbarch->auto_wide_charset = default_auto_wide_charset; /* gdbarch_alloc() */ return gdbarch; @@ -664,6 +670,8 @@ verify_gdbarch (struct gdbarch *gdbarch) /* Skip verify of has_shared_address_space, invalid_p == 0 */ /* Skip verify of fast_tracepoint_valid_at, invalid_p == 0 */ /* Skip verify of qsupported, invalid_p == 0 */ + /* Skip verify of auto_charset, invalid_p == 0 */ + /* Skip verify of auto_wide_charset, invalid_p == 0 */ buf = ui_file_xstrdup (log, &length); make_cleanup (xfree, buf); if (length > 0) @@ -719,6 +727,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) fprintf_unfiltered (file, "gdbarch_dump: adjust_breakpoint_address = <%s>\n", host_address_to_string (gdbarch->adjust_breakpoint_address)); + fprintf_unfiltered (file, + "gdbarch_dump: auto_charset = <%s>\n", + host_address_to_string (gdbarch->auto_charset)); + fprintf_unfiltered (file, + "gdbarch_dump: auto_wide_charset = <%s>\n", + host_address_to_string (gdbarch->auto_wide_charset)); fprintf_unfiltered (file, "gdbarch_dump: believe_pcc_promotion = %s\n", plongest (gdbarch->believe_pcc_promotion)); @@ -3599,6 +3613,40 @@ set_gdbarch_qsupported (struct gdbarch *gdbarch, gdbarch->qsupported = qsupported; } +const char * +gdbarch_auto_charset (struct gdbarch *gdbarch) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->auto_charset != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_auto_charset called\n"); + return gdbarch->auto_charset (); +} + +void +set_gdbarch_auto_charset (struct gdbarch *gdbarch, + gdbarch_auto_charset_ftype auto_charset) +{ + gdbarch->auto_charset = auto_charset; +} + +const char * +gdbarch_auto_wide_charset (struct gdbarch *gdbarch) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->auto_wide_charset != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_auto_wide_charset called\n"); + return gdbarch->auto_wide_charset (); +} + +void +set_gdbarch_auto_wide_charset (struct gdbarch *gdbarch, + gdbarch_auto_wide_charset_ftype auto_wide_charset) +{ + gdbarch->auto_wide_charset = auto_wide_charset; +} + /* Keep a registry of per-architecture data-pointers required by GDB modules. */ diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index 1353ab1b6d5..83281f46f64 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -928,6 +928,18 @@ extern void set_gdbarch_fast_tracepoint_valid_at (struct gdbarch *gdbarch, gdbar extern const char * gdbarch_qsupported (struct gdbarch *gdbarch); extern void set_gdbarch_qsupported (struct gdbarch *gdbarch, const char * qsupported); +/* Return the "auto" target charset. */ + +typedef const char * (gdbarch_auto_charset_ftype) (void); +extern const char * gdbarch_auto_charset (struct gdbarch *gdbarch); +extern void set_gdbarch_auto_charset (struct gdbarch *gdbarch, gdbarch_auto_charset_ftype *auto_charset); + +/* Return the "auto" target wide charset. */ + +typedef const char * (gdbarch_auto_wide_charset_ftype) (void); +extern const char * gdbarch_auto_wide_charset (struct gdbarch *gdbarch); +extern void set_gdbarch_auto_wide_charset (struct gdbarch *gdbarch, gdbarch_auto_wide_charset_ftype *auto_wide_charset); + /* Definition for an unknown syscall, used basically in error-cases. */ #define UNKNOWN_SYSCALL (-1) diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh index 0eaa0ef56fb..441c515966c 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -769,6 +769,11 @@ m:int:fast_tracepoint_valid_at:CORE_ADDR addr, int *isize, char **msg:addr, isiz # Not NULL if a target has additonal field for qSupported. v:const char *:qsupported:::0:0::0:gdbarch->qsupported + +# Return the "auto" target charset. +f:const char *:auto_charset:void::default_auto_charset:default_auto_charset::0 +# Return the "auto" target wide charset. +f:const char *:auto_wide_charset:void::default_auto_wide_charset:default_auto_wide_charset::0 EOF } diff --git a/gdb/i386-cygwin-tdep.c b/gdb/i386-cygwin-tdep.c index f0d8d4b904c..ef24670fbf3 100644 --- a/gdb/i386-cygwin-tdep.c +++ b/gdb/i386-cygwin-tdep.c @@ -205,6 +205,12 @@ i386_cygwin_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc) return i386_pe_skip_trampoline_code (frame, pc, NULL); } +static const char * +i386_cygwin_auto_wide_charset (void) +{ + return "UTF-16"; +} + static void i386_cygwin_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { @@ -227,6 +233,8 @@ i386_cygwin_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) (gdbarch, i386_windows_regset_from_core_section); set_gdbarch_core_xfer_shared_libraries (gdbarch, windows_core_xfer_shared_libraries); + + set_gdbarch_auto_wide_charset (gdbarch, i386_cygwin_auto_wide_charset); } static enum gdb_osabi diff --git a/gdb/jv-exp.y b/gdb/jv-exp.y index f91e5bd5568..a904c3295f5 100644 --- a/gdb/jv-exp.y +++ b/gdb/jv-exp.y @@ -898,7 +898,7 @@ yylex (void) lexptr++; c = *lexptr++; if (c == '\\') - c = parse_escape (&lexptr); + c = parse_escape (parse_gdbarch, &lexptr); else if (c == '\'') error (_("Empty character constant")); @@ -1061,7 +1061,7 @@ yylex (void) break; case '\\': tokptr++; - c = parse_escape (&tokptr); + c = parse_escape (parse_gdbarch, &tokptr); if (c == -1) { continue; diff --git a/gdb/mi/mi-parse.c b/gdb/mi/mi-parse.c index 8548b67dbe5..c3f5eeb1611 100644 --- a/gdb/mi/mi-parse.c +++ b/gdb/mi/mi-parse.c @@ -23,10 +23,83 @@ #include "defs.h" #include "mi-cmds.h" #include "mi-parse.h" +#include "charset.h" #include #include "gdb_string.h" +/* Like parse_escape, but leave the results as a host char, not a + target char. */ + +static int +mi_parse_escape (char **string_ptr) +{ + int c = *(*string_ptr)++; + switch (c) + { + case '\n': + return -2; + case 0: + (*string_ptr)--; + return 0; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + { + int i = host_hex_value (c); + int count = 0; + while (++count < 3) + { + c = (**string_ptr); + if (isdigit (c) && c != '8' && c != '9') + { + (*string_ptr)++; + i *= 8; + i += host_hex_value (c); + } + else + { + break; + } + } + return i; + } + + case 'a': + c = '\a'; + break; + case 'b': + c = '\b'; + break; + case 'f': + c = '\f'; + break; + case 'n': + c = '\n'; + break; + case 'r': + c = '\r'; + break; + case 't': + c = '\t'; + break; + case 'v': + c = '\v'; + break; + + default: + break; + } + + return c; +} + static void mi_parse_argv (char *args, struct mi_parse *parse) { @@ -60,7 +133,7 @@ mi_parse_argv (char *args, struct mi_parse *parse) if (*chp == '\\') { chp++; - if (parse_escape (&chp) <= 0) + if (mi_parse_escape (&chp) <= 0) { /* Do not allow split lines or "\000" */ freeargv (argv); @@ -93,7 +166,7 @@ mi_parse_argv (char *args, struct mi_parse *parse) if (*chp == '\\') { chp++; - arg[len] = parse_escape (&chp); + arg[len] = mi_parse_escape (&chp); } else arg[len] = *chp++; diff --git a/gdb/objc-exp.y b/gdb/objc-exp.y index 9994ca25afe..888bd201e4f 100644 --- a/gdb/objc-exp.y +++ b/gdb/objc-exp.y @@ -1276,7 +1276,7 @@ yylex () lexptr++; c = *lexptr++; if (c == '\\') - c = parse_escape (&lexptr); + c = parse_escape (parse_gdbarch, &lexptr); else if (c == '\'') error ("Empty character constant."); @@ -1506,7 +1506,7 @@ yylex () break; case '\\': tokptr++; - c = parse_escape (&tokptr); + c = parse_escape (parse_gdbarch, &tokptr); if (c == -1) { continue; diff --git a/gdb/p-exp.y b/gdb/p-exp.y index 481624a04b9..c034fbbdd4d 100644 --- a/gdb/p-exp.y +++ b/gdb/p-exp.y @@ -1138,7 +1138,7 @@ yylex () lexptr++; c = *lexptr++; if (c == '\\') - c = parse_escape (&lexptr); + c = parse_escape (parse_gdbarch, &lexptr); else if (c == '\'') error ("Empty character constant."); @@ -1303,7 +1303,7 @@ yylex () break; case '\\': tokptr++; - c = parse_escape (&tokptr); + c = parse_escape (parse_gdbarch, &tokptr); if (c == -1) { continue; diff --git a/gdb/printcmd.c b/gdb/printcmd.c index 346c2e27008..bfe847996aa 100644 --- a/gdb/printcmd.c +++ b/gdb/printcmd.c @@ -2372,7 +2372,7 @@ printf_command (char *arg, int from_tty) obstack_init (&output); inner_cleanup = make_cleanup_obstack_free (&output); - convert_between_encodings (target_wide_charset (byte_order), + convert_between_encodings (target_wide_charset (gdbarch), host_charset (), str, j, wcwidth, &output, translit_char); @@ -2404,7 +2404,7 @@ printf_command (char *arg, int from_tty) obstack_init (&output); inner_cleanup = make_cleanup_obstack_free (&output); - convert_between_encodings (target_wide_charset (byte_order), + convert_between_encodings (target_wide_charset (gdbarch), host_charset (), bytes, TYPE_LENGTH (valtype), TYPE_LENGTH (valtype), diff --git a/gdb/python/py-utils.c b/gdb/python/py-utils.c index 4ccf97f4a6f..aed8fffd49f 100644 --- a/gdb/python/py-utils.c +++ b/gdb/python/py-utils.c @@ -129,7 +129,8 @@ unicode_to_encoded_python_string (PyObject *unicode_str, const char *charset) char * unicode_to_target_string (PyObject *unicode_str) { - return unicode_to_encoded_string (unicode_str, target_charset ()); + return unicode_to_encoded_string (unicode_str, + target_charset (python_gdbarch)); } /* Returns a PyObject with the contents of the given unicode string @@ -139,7 +140,8 @@ unicode_to_target_string (PyObject *unicode_str) PyObject * unicode_to_target_python_string (PyObject *unicode_str) { - return unicode_to_encoded_python_string (unicode_str, target_charset ()); + return unicode_to_encoded_python_string (unicode_str, + target_charset (python_gdbarch)); } /* Converts a python string (8-bit or unicode) to a target string in @@ -208,7 +210,7 @@ target_string_to_unicode (const gdb_byte *str, int length) if (length == -1) length = strlen (str); - return PyUnicode_Decode (str, length, target_charset (), NULL); + return PyUnicode_Decode (str, length, target_charset (python_gdbarch), NULL); } /* Return true if OBJ is a Python string or unicode object, false diff --git a/gdb/python/python.c b/gdb/python/python.c index 3d38de60265..9a89eed142e 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -283,6 +283,24 @@ gdbpy_parameter (PyObject *self, PyObject *args) return parameter_to_python (cmd); } +/* Wrapper for target_charset. */ + +static PyObject * +gdbpy_target_charset (PyObject *self, PyObject *args) +{ + const char *cset = target_charset (python_gdbarch); + return PyUnicode_Decode (cset, strlen (cset), host_charset (), NULL); +} + +/* Wrapper for target_wide_charset. */ + +static PyObject * +gdbpy_target_wide_charset (PyObject *self, PyObject *args) +{ + const char *cset = target_wide_charset (python_gdbarch); + return PyUnicode_Decode (cset, strlen (cset), host_charset (), NULL); +} + /* A Python function which evaluates a string using the gdb CLI. */ static PyObject * @@ -740,6 +758,13 @@ a boolean indicating if name is a field of the current implied argument\n\ Parse String as an expression, evaluate it, and return the result as a Value." }, + { "target_charset", gdbpy_target_charset, METH_NOARGS, + "target_charset () -> string.\n\ +Return the name of the current target charset." }, + { "target_wide_charset", gdbpy_target_wide_charset, METH_NOARGS, + "target_wide_charset () -> string.\n\ +Return the name of the current target wide charset." }, + { "write", gdbpy_write, METH_VARARGS, "Write a string using gdb's filtered stream." }, { "flush", gdbpy_flush, METH_NOARGS, diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index b5e4c986bd0..3efd2be14f1 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2010-03-05 Tom Tromey + + * gdb.python/py-prettyprint.py (pp_nullstr.to_string): Use + gdb.target_charset. + (pp_ns.to_string): Likewise. + 2010-03-04 Keith Seitz * gdb.cp/overload.exp: Test that the filename portion of a linespec diff --git a/gdb/testsuite/gdb.python/py-prettyprint.py b/gdb/testsuite/gdb.python/py-prettyprint.py index 9a0d1072b2d..979d4ad0184 100644 --- a/gdb/testsuite/gdb.python/py-prettyprint.py +++ b/gdb/testsuite/gdb.python/py-prettyprint.py @@ -97,7 +97,7 @@ class pp_nullstr: self.val = val def to_string(self): - return self.val['s'].string(gdb.parameter('target-charset')) + return self.val['s'].string(gdb.target_charset()) class pp_ns: "Print a std::basic_string of some kind" @@ -107,7 +107,7 @@ class pp_ns: def to_string(self): len = self.val['length'] - return self.val['null_str'].string (gdb.parameter ('target-charset'), length = len) + return self.val['null_str'].string (gdb.target_charset(), length = len) def display_hint (self): return 'string' diff --git a/gdb/utils.c b/gdb/utils.c index 0b74e2b1ae6..8054f0355e0 100644 --- a/gdb/utils.c +++ b/gdb/utils.c @@ -1653,7 +1653,7 @@ query (const char *ctlstr, ...) function returns 1. Otherwise, the function returns 0. */ static int -host_char_to_target (int c, int *target_c) +host_char_to_target (struct gdbarch *gdbarch, int c, int *target_c) { struct obstack host_data; char the_char = c; @@ -1663,7 +1663,7 @@ host_char_to_target (int c, int *target_c) obstack_init (&host_data); cleanups = make_cleanup_obstack_free (&host_data); - convert_between_encodings (target_charset (), host_charset (), + convert_between_encodings (target_charset (gdbarch), host_charset (), &the_char, 1, 1, &host_data, translit_none); if (obstack_object_size (&host_data) == 1) @@ -1692,7 +1692,7 @@ host_char_to_target (int c, int *target_c) after the zeros. A value of 0 does not mean end of string. */ int -parse_escape (char **string_ptr) +parse_escape (struct gdbarch *gdbarch, char **string_ptr) { int target_char = -2; /* initialize to avoid GCC warnings */ int c = *(*string_ptr)++; @@ -1758,11 +1758,11 @@ parse_escape (char **string_ptr) break; } - if (!host_char_to_target (c, &target_char)) + if (!host_char_to_target (gdbarch, c, &target_char)) error ("The escape sequence `\%c' is equivalent to plain `%c', which" " has no equivalent\n" "in the `%s' character set.", c, c, - target_charset ()); + target_charset (gdbarch)); return target_char; } -- 2.30.2