From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22885 invoked by alias); 2 Mar 2010 22:55:50 -0000 Received: (qmail 22611 invoked by uid 22791); 2 Mar 2010 22:55:26 -0000 X-SWARE-Spam-Status: No, hits=-7.0 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_HI,SPF_HELO_PASS X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 02 Mar 2010 22:55:13 +0000 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o22MtBut024701 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 2 Mar 2010 17:55:12 -0500 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o22MtA22004141; Tue, 2 Mar 2010 17:55:11 -0500 Received: from opsy.redhat.com (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id o22Mt9df020900; Tue, 2 Mar 2010 17:55:10 -0500 Received: by opsy.redhat.com (Postfix, from userid 500) id 0BEED379963; Tue, 2 Mar 2010 15:55:08 -0700 (MST) From: Tom Tromey To: gdb-patches@sourceware.org Subject: Re: [RFA] defs.h: Define GDB_DEFAULT_TARGET_[WIDE_]CHARSET for Cygwin and MingW builds References: <20100228130500.GG5683@calimero.vinschen.de> <20100228142905.GB1556@caradoc.them.org> <20100228150318.GA32463@calimero.vinschen.de> <20100228184749.GA17375@caradoc.them.org> <20100228192159.GP5683@calimero.vinschen.de> <20100228222702.GC29360@caradoc.them.org> <20100301103125.GB9730@calimero.vinschen.de> <20100301173054.GD5683@calimero.vinschen.de> <20100301193126.GA9416@caradoc.them.org> Reply-To: tromey@redhat.com Date: Tue, 02 Mar 2010 22:55:00 -0000 In-Reply-To: (Tom Tromey's message of "Tue, 02 Mar 2010 10:58:53 -0700") Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2010-03/txt/msg00087.txt.bz2 >>>>> "Tom" == Tom Tromey writes: Tom> I agree, we need a gdbarch method. Tom> I'll look into this today. Here's a patch, please let me know what you think. This patch nearly works -- it regresses on a Python test that looks at gdb.parameter('target-charset') directly and then gets confused by "auto". I think the only solution for this is to add a new Python API. (It would be easy enough to just hack the test case somehow -- but the libstdc++ printers use this same idiom, so a real solution is needed.) I wasn't sure where to put the Cygwin override; I took Daniel's suggestion of i386_cygwin_init_abi; but Corinna's earlier patches changed all Windows targets, not just Cygwin, and I didn't see a good place to do that. Also, given that Cygwin implements nl_langinfo(CODESET), I figured we only needed to override the target wide charset default in this case. I do think this patch is largely an improvement. In particular, I agree with Daniel that the current MI use of parse_escape is suspect, so it was good to flush that out. Tom 2010-03-02 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. * 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. diff --git a/gdb/arch-utils.h b/gdb/arch-utils.h index d5d7f1d..dbeb67f 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 d620881..fefd675 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 8977f27..f383b00 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 (); @@ -874,14 +926,12 @@ _initialize_charset (void) 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; #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 +959,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 +971,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 7700168..bd93d01 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 7400967..bc79258 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 c1dafb4..d8ec100 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 b8973b3..cb15d0e 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/gdbarch.c b/gdb/gdbarch.c index cfb042b..f482572 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) @@ -720,6 +728,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *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)); fprintf_unfiltered (file, @@ -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 1353ab1..83281f4 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 0eaa0ef..441c515 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 f0d8d4b..ef24670 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 f91e5bd..a904c32 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 8548b67..c3f5eeb 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 9994ca2..888bd20 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 481624a..c034fbb 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 c8cb35c..1e644d8 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 4ccf97f..aed8fff 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/utils.c b/gdb/utils.c index 52596ca..22eefee 100644 --- a/gdb/utils.c +++ b/gdb/utils.c @@ -1652,7 +1652,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; @@ -1662,7 +1662,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) @@ -1691,7 +1691,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)++; @@ -1757,11 +1757,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; }