[v3,5/8] Rewrite Ada character printer

Message ID 20251228-string-printing-2-v3-5-ec5cc9dd0c71@tromey.com
State New
Headers
Series Refactor character printing |

Commit Message

Tom Tromey Dec. 28, 2025, 8:13 p.m. UTC
  This adds a Ada-specific subclass of wchar_printer and arranges to
use it.
---
 gdb/ada-lang.c     |  60 +++++++++++++++++++++--
 gdb/ada-lang.h     |   8 ---
 gdb/ada-valprint.c | 141 ++---------------------------------------------------
 3 files changed, 60 insertions(+), 149 deletions(-)
  

Patch

diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 7cee3ac381344022f8598a060f4c09e60be74e50..e6e2bf1b9833450dc87b48bdedc47baab04af441 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -64,6 +64,7 @@ 
 #include "ada-exp.h"
 #include "charset.h"
 #include "ax-gdb.h"
+#include "char-print.h"
 
 static struct type *desc_base_type (struct type *);
 
@@ -13480,6 +13481,56 @@  ada_get_symbol_name_matcher (const lookup_name_info &lookup_name)
     }
 }
 
+class ada_wchar_printer : public wchar_printer
+{
+public:
+
+  using wchar_printer::wchar_printer;
+
+protected:
+
+  bool printable (gdb_wchar_t w) const override
+  {
+    return gdb_iswprint (w);
+  }
+
+  void print_char (gdb_wchar_t w) override;
+  void print_escape (const gdb_byte *orig, int orig_len) override;
+};
+
+void
+ada_wchar_printer::print_char (gdb_wchar_t w)
+{
+  if (w == gdb_btowc (m_quoter) && m_quoter == '"')
+    m_file.write (LCST ("\"\""));
+  else
+    m_file.write (w);
+}
+
+void
+ada_wchar_printer::print_escape (const gdb_byte *orig, int orig_len)
+{
+  int i;
+
+  for (i = 0; i + m_width <= orig_len; i += m_width)
+    {
+      ULONGEST value = extract_unsigned_integer (&orig[i], m_width,
+						 m_byte_order);
+      /* Follow GNAT's lead here and only use 6 digits for
+	 wide_wide_character.  */
+      gdb_printf (&m_file, "[\"%0*lx\"]",
+		  std::min (6, m_width * 2),
+		  (unsigned long) value);
+    }
+
+  /* If we somehow have extra bytes, print them now.  */
+  while (i < orig_len)
+    {
+      gdb_printf (&m_file, "[\"%02x\"]", orig[i] & 0xff);
+      ++i;
+    }
+}
+
 /* Class representing the Ada language.  */
 
 class ada_language : public language_defn
@@ -13896,7 +13947,8 @@  class ada_language : public language_defn
   void printchar (int ch, struct type *chtype,
 		  struct ui_file *stream) const override
   {
-    ada_printchar (ch, chtype, stream);
+    ada_wchar_printer printer (chtype, '\'');
+    printer.print (ch, stream);
   }
 
   /* See language.h.  */
@@ -13913,8 +13965,10 @@  class ada_language : public language_defn
       generic_printstr (stream, elttype, string, length, encoding,
 			force_ellipses, '"', 0, options);
     else
-      ada_printstr (stream, elttype, string, length, encoding,
-		    force_ellipses, options);
+      {
+	ada_wchar_printer printer (elttype, '"', encoding);
+	printer.print (stream, string, length, force_ellipses, 0, options);
+      }
   }
 
   /* See language.h.  */
diff --git a/gdb/ada-lang.h b/gdb/ada-lang.h
index 6a5cc553275447e18089b631767f55ae115da62c..8699bde26a12a4db2dfb6be9ce54ed896c8e2afb 100644
--- a/gdb/ada-lang.h
+++ b/gdb/ada-lang.h
@@ -172,14 +172,6 @@  extern void ada_value_print (struct value *, struct ui_file *,
 
 				/* Defined in ada-lang.c */
 
-extern void ada_emit_char (int, struct type *, struct ui_file *, int, int);
-
-extern void ada_printchar (int, struct type *, struct ui_file *);
-
-extern void ada_printstr (struct ui_file *, struct type *, const gdb_byte *,
-			  unsigned int, const char *, int,
-			  const struct value_print_options *);
-
 struct value *ada_convert_actual (struct value *actual,
 				  struct type *formal_type0);
 
diff --git a/gdb/ada-valprint.c b/gdb/ada-valprint.c
index c198fa519f86066c22a8448df8ddb864f58ce51f..072ba20cb49a01da586fae9b3fbc896cfe3d10f7 100644
--- a/gdb/ada-valprint.c
+++ b/gdb/ada-valprint.c
@@ -253,35 +253,6 @@  val_print_packed_array_elements (struct type *type, const gdb_byte *valaddr,
     }
 }
 
-/* Print the character C on STREAM as part of the contents of a literal
-   string whose delimiter is QUOTER.  TYPE_LEN is the length in bytes
-   of the character.  */
-
-void
-ada_emit_char (int c, struct type *type, struct ui_file *stream,
-	       int quoter, int type_len)
-{
-  /* If this character fits in the normal ASCII range, and is
-     a printable character, then print the character as if it was
-     an ASCII character, even if this is a wide character.
-     The UCHAR_MAX check is necessary because the c_isascii function
-     requires that its argument have a value of an unsigned char,
-     or EOF (EOF is obviously not printable).  */
-  if (c <= UCHAR_MAX && c_isascii (c) && c_isprint (c))
-    {
-      if (c == quoter && c == '"')
-	gdb_printf (stream, "\"\"");
-      else
-	gdb_printf (stream, "%c", c);
-    }
-  else
-    {
-      /* Follow GNAT's lead here and only use 6 digits for
-	 wide_wide_character.  */
-      gdb_printf (stream, "[\"%0*x\"]", std::min (6, type_len * 2), c);
-    }
-}
-
 /* Character #I of STRING, given that TYPE_LEN is the size in bytes
    of a character.  */
 
@@ -357,14 +328,6 @@  ada_print_floating (const gdb_byte *valaddr, struct type *type,
     gdb_printf (stream, "%s", &s[skip_count]);
 }
 
-void
-ada_printchar (int c, struct type *type, struct ui_file *stream)
-{
-  gdb_puts ("'", stream);
-  ada_emit_char (c, type, stream, '\'', type->length ());
-  gdb_puts ("'", stream);
-}
-
 /* [From print_type_scalar in typeprint.c].   Print VAL on STREAM in a
    form appropriate for TYPE, if non-NULL.  If TYPE is NULL, print VAL
    like a default signed integer.  */
@@ -433,104 +396,6 @@  ada_print_scalar (struct type *type, LONGEST val, struct ui_file *stream)
     }
 }
 
-/* Print the character string STRING, printing at most LENGTH characters.
-   Printing stops early if the number hits print_max; repeat counts
-   are printed as appropriate.  Print ellipses at the end if we
-   had to stop before printing LENGTH characters, or if FORCE_ELLIPSES.
-   TYPE_LEN is the length (1 or 2) of the character type.  */
-
-static void
-printstr (struct ui_file *stream, struct type *elttype, const gdb_byte *string,
-	  unsigned int length, int force_ellipses, int type_len,
-	  const struct value_print_options *options)
-{
-  enum bfd_endian byte_order = type_byte_order (elttype);
-  unsigned int i;
-  unsigned int things_printed = 0;
-  int in_quotes = 0;
-  int need_comma = 0;
-
-  if (length == 0)
-    {
-      gdb_puts ("\"\"", stream);
-      return;
-    }
-
-  unsigned int print_max_chars = get_print_max_chars (options);
-  for (i = 0; i < length && things_printed < print_max_chars; i += 1)
-    {
-      /* Position of the character we are examining
-	 to see whether it is repeated.  */
-      unsigned int rep1;
-      /* Number of repetitions we have detected so far.  */
-      unsigned int reps;
-
-      QUIT;
-
-      if (need_comma)
-	{
-	  gdb_puts (", ", stream);
-	  need_comma = 0;
-	}
-
-      rep1 = i + 1;
-      reps = 1;
-      while (rep1 < length
-	     && char_at (string, rep1, type_len, byte_order)
-		== char_at (string, i, type_len, byte_order))
-	{
-	  rep1 += 1;
-	  reps += 1;
-	}
-
-      if (reps > options->repeat_count_threshold)
-	{
-	  if (in_quotes)
-	    {
-	      gdb_puts ("\", ", stream);
-	      in_quotes = 0;
-	    }
-	  gdb_puts ("'", stream);
-	  ada_emit_char (char_at (string, i, type_len, byte_order),
-			 elttype, stream, '\'', type_len);
-	  gdb_puts ("'", stream);
-	  gdb_printf (stream, _(" %p[<repeats %u times>%p]"),
-		      metadata_style.style ().ptr (), reps, nullptr);
-	  i = rep1 - 1;
-	  things_printed += options->repeat_count_threshold;
-	  need_comma = 1;
-	}
-      else
-	{
-	  if (!in_quotes)
-	    {
-	      gdb_puts ("\"", stream);
-	      in_quotes = 1;
-	    }
-	  ada_emit_char (char_at (string, i, type_len, byte_order),
-			 elttype, stream, '"', type_len);
-	  things_printed += 1;
-	}
-    }
-
-  /* Terminate the quotes if necessary.  */
-  if (in_quotes)
-    gdb_puts ("\"", stream);
-
-  if (force_ellipses || i < length)
-    gdb_puts ("...", stream);
-}
-
-void
-ada_printstr (struct ui_file *stream, struct type *type,
-	      const gdb_byte *string, unsigned int length,
-	      const char *encoding, int force_ellipses,
-	      const struct value_print_options *options)
-{
-  printstr (stream, type, string, length, force_ellipses, type->length (),
-	    options);
-}
-
 static int
 print_variant_part (struct value *value, int field_num,
 		    struct value *outer_value,
@@ -705,8 +570,8 @@  ada_val_print_string (struct type *type, const gdb_byte *valaddr,
       len = temp_len;
     }
 
-  printstr (stream, elttype, valaddr + offset_aligned, len, 0,
-	    eltlen, options);
+  current_language->printstr (stream, elttype, valaddr + offset_aligned,
+			      len, nullptr, 0, options);
 }
 
 /* Implement Ada value_print'ing for the case where TYPE is a
@@ -800,7 +665,7 @@  ada_value_print_num (struct value *val, struct ui_file *stream, int recurse,
 
 	      gdb_puts (" ", stream);
 	      c = unpack_long (type, valaddr);
-	      ada_printchar (c, type, stream);
+	      current_language->printchar (c, type, stream);
 	    }
 	}
       return;