This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFA: default charsets -vs- gdbarch


This needs a doc review.

This is the reworked "default charsets in gdbarch" patch.  It includes
the test suite fixes, new Python APIs, and the various fixes Corinna
made.

Built and regtested on x86-64 (compile farm).

Let me know what you think.

Tom

2010-03-05  Corinna Vinschen  <vinschen@redhat.com>
	    Tom Tromey  <tromey@redhat.com>

	* 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  Tom Tromey  <tromey@redhat.com>

	* gdb.texinfo (Basic Python): Document target_charset and
	target_wide_charset.

2010-03-05  Tom Tromey  <tromey@redhat.com>

	* gdb.python/py-prettyprint.py (pp_nullstr.to_string): Use
	gdb.target_charset.
	(pp_ns.to_string): Likewise.

diff --git a/gdb/NEWS b/gdb/NEWS
index 6cec32a..d165713 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -5,8 +5,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 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..9c1e7f4 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 <stddef.h>
 #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 <TAB>'.
 			&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'<TAB>
 			&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 <ctype.h>
 #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/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 6bb7d52..d7a1b63 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -19631,6 +19631,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 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 <ctype.h>
 #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/python/python.c b/gdb/python/python.c
index 3d38de6..9a89eed 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/gdb.python/py-prettyprint.py b/gdb/testsuite/gdb.python/py-prettyprint.py
index 9a0d107..979d4ad 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 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;
 }
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]