public inbox for archer-commits@sourceware.org
help / color / mirror / Atom feed
* [SCM]  archer-tromey-charset: implement %ls and %lc printf formats
@ 2009-01-09 18:04 tromey
  0 siblings, 0 replies; only message in thread
From: tromey @ 2009-01-09 18:04 UTC (permalink / raw)
  To: archer-commits

The branch, archer-tromey-charset has been updated
       via  dee452204073d6bf0ceffd150dfaf3391be01bd2 (commit)
      from  3db781d3884e7b03393020d1851a58985fbe82ab (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email.

- Log -----------------------------------------------------------------
commit dee452204073d6bf0ceffd150dfaf3391be01bd2
Author: Tom Tromey <tromey@redhat.com>
Date:   Fri Jan 9 11:03:24 2009 -0700

    implement %ls and %lc printf formats

-----------------------------------------------------------------------

Summary of changes:
 gdb/c-lang.c   |    9 +++--
 gdb/charset.c  |   61 ++++++++++++++++++++++----------------
 gdb/charset.h  |   20 +++++++++---
 gdb/printcmd.c |   89 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
 gdb/utils.c    |    2 +-
 5 files changed, 141 insertions(+), 40 deletions(-)

First 500 lines of diff:
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index 746071f..86c1b6d 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -56,7 +56,7 @@ c_emit_char (int c, struct ui_file *stream, int quoter)
   cleanups = make_cleanup_obstack_free (&host_data);
 
   convert_between_encodings (target_charset (), host_charset (),
-			     &the_char, 1, &host_data, 1);
+			     &the_char, 1, &host_data, translit_char);
 
   if (obstack_object_size (&host_data) == 1)
     {
@@ -257,7 +257,7 @@ c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
   cleanup = make_cleanup_obstack_free (&internal);
 
   convert_between_encodings (encoding, "wchar_t", string, length * width,
-			     &internal, 1);
+			     &internal, translit_wchar);
 
   new_len = obstack_object_size (&internal) / sizeof (wchar_t);
   obj = (wchar_t *) obstack_base (&internal);
@@ -392,7 +392,8 @@ convert_ucn (char *p, struct obstack *output, int length)
       result >>= 8;
     }
 
-  convert_between_encodings ("UCS-2BE", target_charset (), data, 4, output, 0);
+  convert_between_encodings ("UCS-2BE", target_charset (), data, 4, output,
+			     translit_none);
 }
 
 static void
@@ -513,7 +514,7 @@ parse_one_string (struct obstack *output, char *data, int len,
       /* If we saw a run of characters, convert them all.  */
       if (p > data)
 	convert_between_encodings (host_charset (), dest_charset,
-				   data, p - data, output, 0);
+				   data, p - data, output, translit_none);
       /* If we saw an escape, convert it.  */
       if (p < limit)
 	p = convert_escape (type, dest_charset, p, limit, output);
diff --git a/gdb/charset.c b/gdb/charset.c
index 1631bed..fcf54df 100644
--- a/gdb/charset.c
+++ b/gdb/charset.c
@@ -318,7 +318,8 @@ cleanup_iconv (void *p)
 void
 convert_between_encodings (const char *from, const char *to,
 			   const gdb_byte *bytes, unsigned int num_bytes,
-			   struct obstack *output, int translit)
+			   struct obstack *output,
+			   enum transliterations translit)
 {
   iconv_t desc;
   struct cleanup *cleanups;
@@ -370,31 +371,41 @@ convert_between_encodings (const char *from, const char *to,
 	    case EILSEQ:
 	      {
 		/* Invalid input sequence.  */
-		if (translit)
+		switch (translit)
 		  {
-		    /* We emit an escape sequence for the byte, skip
-		       it, and try again.  */
-		    char hex[5];
-		    int i;
-
-		    /* Translit is only available when converting to
-		       the host wchar_t.  */
-		    gdb_assert (!strcmp (to, "wchar_t"));
-		    sprintf (hex, "\\x%02x", *inp);
-		    for (i = 0; hex[i]; ++i)
-		      {
-			wchar_t w = btowc (hex[i]);
-			obstack_grow (output, &w, sizeof (wchar_t));
-		      }
-
-		    ++inp;
-		  }
-		else
-		  {
-		    /* We are converting from host to target and
-		       cannot convert a character.  There is nothing
-		       good to do here.  FIXME: ought to show the char
-		       or its position.  */
+		  case translit_wchar:
+		    {
+		      /* We emit an escape sequence for the byte, skip
+			 it, and try again.  */
+		      char hex[5];
+		      int i;
+
+		      /* Translit is only available when converting to
+			 the host wchar_t.  */
+		      gdb_assert (!strcmp (to, "wchar_t"));
+		      sprintf (hex, "\\x%02x", *inp);
+		      for (i = 0; hex[i]; ++i)
+			{
+			  wchar_t w = btowc (hex[i]);
+			  obstack_grow (output, &w, sizeof (wchar_t));
+			}
+
+		      ++inp;
+		    }
+		    break;
+		  case translit_char:
+		    {
+		      /* We emit an escape sequence for the byte, skip
+			 it, and try again.  */
+		      char hex[5];
+
+		      sprintf (hex, "\\x%02x", *inp);
+		      obstack_grow_str (output, hex);
+
+		      ++inp;
+		    }
+		    break;
+		  case translit_none:
 		    error ("Could not convert character");
 		  }
 	      }
diff --git a/gdb/charset.h b/gdb/charset.h
index 09a5ae4..6802753 100644
--- a/gdb/charset.h
+++ b/gdb/charset.h
@@ -37,6 +37,18 @@ const char *host_charset (void);
 const char *target_charset (void);
 const char *target_wide_charset (void);
 
+/* These values are used to specify the type of transliteration done
+   by convert_between_encodings.  */
+enum transliterations
+  {
+    /* Error on failure to convert.  */
+    translit_none,
+    /* Transliterate to host wchar_t.  */
+    translit_wchar,
+    /* Transliterate to host char.  */
+    translit_char
+  };
+
 /* Convert between two encodings.
 
    FROM is the name of the source encoding.
@@ -47,13 +59,11 @@ const char *target_wide_charset (void);
    OUTPUT is an obstack where the converted data is written.  The
    caller is responsible for initializing the obstack, and for
    destroying the obstack should an error occur.
-   TRANSLIT is true if unrecognized characters should be
-   transliterated into escape sequences.  This is only valid if the
-   destination character set is the host character set.  If false,
-   this function will raise an error on an invalid conversion.  */
+   TRANSLIT specifies how invalid conversions should be handled.  */
 void convert_between_encodings (const char *from, const char *to,
 				const gdb_byte *bytes, unsigned int num_bytes,
-				struct obstack *output, int translit);
+				struct obstack *output,
+				enum transliterations translit);
 
 \f
 
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index 588f6e2..d0429b3 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -43,6 +43,7 @@
 #include "disasm.h"
 #include "dfp.h"
 #include "valprint.h"
+#include "charset.h"
 
 #ifdef TUI
 #include "tui/tui.h"		/* For tui_active et.al.   */
@@ -1864,7 +1865,8 @@ printf_command (char *arg, int from_tty)
 
     enum argclass
       {
-	int_arg, long_arg, long_long_arg, ptr_arg, string_arg,
+	int_arg, long_arg, long_long_arg, ptr_arg,
+	string_arg, wide_string_arg, wide_char_arg,
 	double_arg, long_double_arg, decfloat_arg
       };
     enum argclass *argclass;
@@ -1996,8 +1998,8 @@ printf_command (char *arg, int from_tty)
 	      break;
 
 	    case 'c':
-	      this_argclass = int_arg;
-	      if (lcount || seen_h || seen_big_l)
+	      this_argclass = lcount == 0 ? int_arg : wide_char_arg;
+	      if (lcount > 1 || seen_h || seen_big_l)
 		bad = 1;
 	      if (seen_prec || seen_zero || seen_space || seen_plus)
 		bad = 1;
@@ -2012,8 +2014,8 @@ printf_command (char *arg, int from_tty)
 	      break;
 
 	    case 's':
-	      this_argclass = string_arg;
-	      if (lcount || seen_h || seen_big_l)
+	      this_argclass = lcount == 0 ? string_arg : wide_string_arg;
+	      if (lcount > 1 || seen_h || seen_big_l)
 		bad = 1;
 	      if (seen_zero || seen_space || seen_plus)
 		bad = 1;
@@ -2065,6 +2067,15 @@ printf_command (char *arg, int from_tty)
 		last_arg[length_before_ll + lcount];
 	      current_substring += length_before_ll + 4;
 	    }
+	  else if (this_argclass == wide_string_arg
+		   || this_argclass == wide_char_arg)
+	    {
+	      /* Convert %ls or %lc to %s.  */
+	      int length_before_ls = f - last_arg - 2;
+	      strncpy (current_substring, last_arg, length_before_ls);
+	      strcpy (current_substring + length_before_ls, "s");
+	      current_substring += length_before_ls + 2;
+	    }
 	  else
 	    {
 	      strncpy (current_substring, last_arg, f - last_arg);
@@ -2129,6 +2140,74 @@ printf_command (char *arg, int from_tty)
 	      printf_filtered (current_substring, (char *) str);
 	    }
 	    break;
+	  case wide_string_arg:
+	    {
+	      gdb_byte *str;
+	      CORE_ADDR tem;
+	      int j;
+	      struct type *wctype = lookup_typename ("wchar_t", NULL, 0);
+	      int wcwidth = TYPE_LENGTH (wctype);
+	      gdb_byte *buf = alloca (wcwidth);
+	      struct obstack output;
+	      struct cleanup *inner_cleanup;
+
+	      tem = value_as_address (val_args[i]);
+
+	      /* This is a %s argument.  Find the length of the string.  */
+	      for (j = 0;; j += wcwidth)
+		{
+		  QUIT;
+		  read_memory (tem + j, buf, wcwidth);
+		  if (extract_unsigned_integer (buf, wcwidth) == 0)
+		    break;
+		}
+
+	      /* Copy the string contents into a string inside GDB.  */
+	      str = (gdb_byte *) alloca (j + wcwidth);
+	      if (j != 0)
+		read_memory (tem, str, j);
+	      memset (&str[j], 0, wcwidth);
+
+	      obstack_init (&output);
+	      inner_cleanup = make_cleanup_obstack_free (&output);
+
+	      convert_between_encodings (target_wide_charset (),
+					 host_charset (),
+					 str, j, &output, translit_char);
+	      obstack_grow_str0 (&output, "");
+
+	      printf_filtered (current_substring, obstack_base (&output));
+	      do_cleanups (inner_cleanup);
+	    }
+	    break;
+	  case wide_char_arg:
+	    {
+	      struct type *wctype = lookup_typename ("wchar_t", NULL, 0);
+	      struct type *valtype;
+	      struct obstack output;
+	      struct cleanup *inner_cleanup;
+	      const gdb_byte *bytes;
+
+	      valtype = value_type (val_args[i]);
+	      if (TYPE_LENGTH (valtype) != TYPE_LENGTH (wctype)
+		  || TYPE_CODE (valtype) != TYPE_CODE_INT)
+		error (_("expected wchar_t argument for %%lc"));
+
+	      bytes = value_contents (val_args[i]);
+
+	      obstack_init (&output);
+	      inner_cleanup = make_cleanup_obstack_free (&output);
+
+	      convert_between_encodings (target_wide_charset (),
+					 host_charset (),
+					 bytes, TYPE_LENGTH (valtype),
+					 &output, translit_char);
+	      obstack_grow_str0 (&output, "");
+
+	      printf_filtered (current_substring, obstack_base (&output));
+	      do_cleanups (inner_cleanup);
+	    }
+	    break;
 	  case double_arg:
 	    {
 	      struct type *type = value_type (val_args[i]);
diff --git a/gdb/utils.c b/gdb/utils.c
index 5f2c0d8..c84a007 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -1504,7 +1504,7 @@ host_char_to_target (int c, int *target_c)
   cleanups = make_cleanup_obstack_free (&host_data);
 
   convert_between_encodings (target_charset (), host_charset (),
-			     &the_char, 1, &host_data, 0);
+			     &the_char, 1, &host_data, translit_none);
 
   if (obstack_object_size (&host_data) == 1)
     {


hooks/post-receive
--
Repository for Project Archer.


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2009-01-09 18:04 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-01-09 18:04 [SCM] archer-tromey-charset: implement %ls and %lc printf formats tromey

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).