]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Use ui-out tables in some "maint print" commands
authorTom Tromey <tom@tromey.com>
Wed, 9 Oct 2024 21:25:06 +0000 (15:25 -0600)
committerTom Tromey <tom@tromey.com>
Wed, 4 Dec 2024 01:42:57 +0000 (18:42 -0700)
This changes various "maint print" register commands to use ui-out
tables rather than the current printf approach.

Approved-By: Andrew Burgess <aburgess@redhat.com>
gdb/regcache-dump.c
gdb/regcache.c
gdb/regcache.h
gdb/testsuite/gdb.base/maint.exp
gdb/testsuite/gdb.server/server-run.exp

index e25302d79ca26c3f66ae878a859d6d3c1ede9bc4..9be694dc2ab4dd4fa215dab4177a2165cd52eb9f 100644 (file)
@@ -38,43 +38,45 @@ public:
   }
 
 protected:
-  void dump_reg (ui_file *file, int regnum) override
+
+  int num_additional_headers () override
+  { return 1; }
+
+  void additional_headers (ui_out *out) override
   {
-    if (regnum < 0)
+    out->table_header (0, ui_left, "value",
+                      m_dump_pseudo ? "Cooked value" : "Raw value");
+  }
+
+  void dump_reg (ui_out *out, int regnum) override
+  {
+    if (regnum < gdbarch_num_regs (m_gdbarch) || m_dump_pseudo)
       {
-       if (m_dump_pseudo)
-         gdb_printf (file, "Cooked value");
+       auto size = register_size (m_gdbarch, regnum);
+
+       if (size == 0)
+         return;
+
+       gdb::byte_vector buf (size);
+       auto status = m_regcache->cooked_read (regnum, buf.data ());
+
+       if (status == REG_UNKNOWN)
+         out->field_string ("value", "<invalid>");
+       else if (status == REG_UNAVAILABLE)
+         out->field_string ("value", "<unavailable>");
        else
-         gdb_printf (file, "Raw value");
+         {
+           string_file str;
+           print_hex_chars (&str, buf.data (), size,
+                            gdbarch_byte_order (m_gdbarch), true);
+           out->field_stream ("value", str);
+         }
       }
     else
       {
-       if (regnum < gdbarch_num_regs (m_gdbarch) || m_dump_pseudo)
-         {
-           auto size = register_size (m_gdbarch, regnum);
-
-           if (size == 0)
-             return;
-
-           gdb::byte_vector buf (size);
-           auto status = m_regcache->cooked_read (regnum, buf.data ());
-
-           if (status == REG_UNKNOWN)
-             gdb_printf (file, "<invalid>");
-           else if (status == REG_UNAVAILABLE)
-             gdb_printf (file, "<unavailable>");
-           else
-             {
-               print_hex_chars (file, buf.data (), size,
-                                gdbarch_byte_order (m_gdbarch), true);
-             }
-         }
-       else
-         {
-           /* Just print "<cooked>" for pseudo register when
-              regcache_dump_raw.  */
-           gdb_printf (file, "<cooked>");
-         }
+       /* Just print "<cooked>" for pseudo register when
+          regcache_dump_raw.  */
+       out->field_string ("value", "<cooked>");
       }
   }
 
@@ -97,39 +99,39 @@ public:
   }
 
 protected:
-  void dump_reg (ui_file *file, int regnum) override
+
+  int num_additional_headers () override
+  { return 1; }
+
+  void additional_headers (ui_out *out) override
   {
-    if (regnum < 0)
-      {
-       if (m_has_pseudo)
-         gdb_printf (file, "Cooked value");
-       else
-         gdb_printf (file, "Raw value");
-      }
-    else
+    out->table_header (0, ui_left, "value",
+                      m_has_pseudo ? "Cooked value" : "Raw value");
+  }
+
+  void dump_reg (ui_out *out, int regnum) override
+  {
+    if (regnum < gdbarch_num_regs (m_gdbarch) || m_has_pseudo)
       {
-       if (regnum < gdbarch_num_regs (m_gdbarch) || m_has_pseudo)
-         {
-           auto size = register_size (m_gdbarch, regnum);
+       auto size = register_size (m_gdbarch, regnum);
 
-           if (size == 0)
-             return;
+       if (size == 0)
+         return;
 
-           auto status = get_register_status (regnum);
+       auto status = get_register_status (regnum);
 
-           gdb_assert (status != REG_VALID);
+       gdb_assert (status != REG_VALID);
 
-           if (status == REG_UNKNOWN)
-             gdb_printf (file, "<invalid>");
-           else
-             gdb_printf (file, "<unavailable>");
-         }
+       if (status == REG_UNKNOWN)
+         out->field_string ("value", "<invalid>");
        else
-         {
-           /* Just print "<cooked>" for pseudo register when
-              regcache_dump_raw.  */
-           gdb_printf (file, "<cooked>");
-         }
+         out->field_string ("value", "<unavailable>");
+      }
+    else
+      {
+       /* Just print "<cooked>" for pseudo register when
+          regcache_dump_raw.  */
+       out->field_string ("value", "<cooked>");
       }
   }
 };
@@ -144,7 +146,14 @@ public:
   {}
 
 protected:
-  void dump_reg (ui_file *file, int regnum) override
+
+  int num_additional_headers () override
+  { return 0; }
+
+  void additional_headers (ui_out *out) override
+  { }
+
+  void dump_reg (ui_out *out, int regnum) override
   {}
 };
 
@@ -158,24 +167,38 @@ public:
   {}
 
 protected:
-  void dump_reg (ui_file *file, int regnum) override
+
+  int num_additional_headers () override
+  { return 3; }
+
+  void additional_headers (ui_out *out) override
+  {
+    out->table_header (7, ui_left, "remnum", "Rmt Nr");
+    out->table_header (11, ui_left, "goffset", "g/G Offset");
+    out->table_header (3, ui_left, "expedited", "Expedited");
+  }
+
+  void dump_reg (ui_out *out, int regnum) override
   {
-    if (regnum < 0)
+    int pnum, poffset;
+
+    if (regnum < gdbarch_num_regs (m_gdbarch)
+       && remote_register_number_and_offset (m_gdbarch, regnum,
+                                             &pnum, &poffset))
       {
-       gdb_printf (file, "Rmt Nr  g/G Offset  Expedited");
+       out->field_signed ("remnum", pnum);
+       out->field_signed ("goffset", poffset);
+
+       if (remote_register_is_expedited (regnum))
+         out->field_string ("expedited", "yes");
+       else
+         out->field_skip ("expedited");
       }
-    else if (regnum < gdbarch_num_regs (m_gdbarch))
+    else
       {
-       int pnum, poffset;
-
-       if (remote_register_number_and_offset (m_gdbarch, regnum,
-                                              &pnum, &poffset))
-         {
-           if (remote_register_is_expedited (regnum))
-             gdb_printf (file, "%7d %11d  yes", pnum, poffset);
-           else
-             gdb_printf (file, "%7d %11d", pnum, poffset);
-         }
+       out->field_skip ("remnum");
+       out->field_skip ("goffset");
+       out->field_skip ("expedited");
       }
   }
 };
@@ -190,22 +213,28 @@ public:
   {}
 
 protected:
-  void dump_reg (ui_file *file, int regnum) override
+
+  int num_additional_headers () override
+  { return 1; }
+
+  void additional_headers (ui_out *out) override
   {
-    if (regnum < 0)
-      gdb_printf (file, "Groups");
-    else
+    out->table_header (0, ui_left, "groups", "Groups");
+  }
+
+  void dump_reg (ui_out *out, int regnum) override
+  {
+    string_file file;
+    const char *sep = "";
+    for (const struct reggroup *group : gdbarch_reggroups (m_gdbarch))
       {
-       const char *sep = "";
-       for (const struct reggroup *group : gdbarch_reggroups (m_gdbarch))
+       if (gdbarch_register_reggroup_p (m_gdbarch, regnum, group))
          {
-           if (gdbarch_register_reggroup_p (m_gdbarch, regnum, group))
-             {
-               gdb_printf (file, "%s%s", sep, group->name ());
-               sep = ",";
-             }
+           gdb_printf (&file, "%s%s", sep, group->name ());
+           sep = ",";
          }
       }
+    out->field_stream ("groups", file);
   }
 };
 
@@ -221,15 +250,13 @@ regcache_print (const char *args, enum regcache_dump_what what_to_dump)
 {
   /* Where to send output.  */
   stdio_file file;
-  ui_file *out;
+  std::optional<ui_out_redirect_pop> redirect;
 
-  if (args == NULL)
-    out = gdb_stdout;
-  else
+  if (args != nullptr)
     {
       if (!file.open (args, "w"))
        perror_with_name (_("maintenance print architecture"));
-      out = &file;
+      redirect.emplace (current_uiout, &file);
     }
 
   std::unique_ptr<register_dump> dump;
@@ -241,20 +268,25 @@ regcache_print (const char *args, enum regcache_dump_what what_to_dump)
   else
     gdbarch = current_inferior ()->arch ();
 
+  const char *name;
   switch (what_to_dump)
     {
     case regcache_dump_none:
       dump = std::make_unique<register_dump_none> (gdbarch);
+      name = "Registers";
       break;
     case regcache_dump_remote:
       dump = std::make_unique<register_dump_remote> (gdbarch);
+      name = "RegisterRemote";
       break;
     case regcache_dump_groups:
       dump = std::make_unique<register_dump_groups> (gdbarch);
+      name = "RegisterGroups";
       break;
     case regcache_dump_raw:
     case regcache_dump_cooked:
       {
+       name = "RegisterDump";
        auto dump_pseudo = (what_to_dump == regcache_dump_cooked);
 
        if (target_has_registers ())
@@ -272,7 +304,7 @@ regcache_print (const char *args, enum regcache_dump_what what_to_dump)
       break;
     }
 
-  dump->dump (out);
+  dump->dump (current_uiout, name);
 }
 
 static void
index ab3f61601f7abecc46e31c85e1cd03a5cb28a5fe..f2c403b88d0c58352d0e11d3e2c2c92ce2b0c40d 100644 (file)
@@ -1519,7 +1519,7 @@ reg_flush_command (const char *command, int from_tty)
 }
 
 void
-register_dump::dump (ui_file *file)
+register_dump::dump (ui_out *out, const char *name)
 {
   auto descr = regcache_descr (m_gdbarch);
   int regnum;
@@ -1531,107 +1531,91 @@ register_dump::dump (ui_file *file)
   gdb_assert (descr->nr_cooked_registers
              == gdbarch_num_cooked_regs (m_gdbarch));
 
-  for (regnum = -1; regnum < descr->nr_cooked_registers; regnum++)
+  ui_out_emit_table table (out, 6 + num_additional_headers (), -1, name);
+  out->table_header (10, ui_left, "name", "Name");
+  out->table_header (4, ui_left, "num", "Nr");
+  out->table_header (4, ui_left, "relnum", "Rel");
+  out->table_header (8, ui_left, "offset", "Offset");
+  out->table_header (5, ui_left, "size", "Size");
+  out->table_header (15, ui_left, "type", "Type");
+  additional_headers (out);
+  out->table_body ();
+
+  for (regnum = 0; regnum < descr->nr_cooked_registers; regnum++)
     {
-      /* Name.  */
-      if (regnum < 0)
-       gdb_printf (file, " %-10s", "Name");
-      else
-       {
-         const char *p = gdbarch_register_name (m_gdbarch, regnum);
+      ui_out_emit_tuple tuple_emitter (out, nullptr);
 
-         if (p[0] == '\0')
-           p = "''";
-         gdb_printf (file, " %-10s", p);
-       }
+      /* Name.  */
+      const char *p = gdbarch_register_name (m_gdbarch, regnum);
+      if (p[0] == '\0')
+       p = "''";
+      out->field_string ("name", p);
 
       /* Number.  */
-      if (regnum < 0)
-       gdb_printf (file, " %4s", "Nr");
-      else
-       gdb_printf (file, " %4d", regnum);
+      out->field_signed ("num", regnum);
 
       /* Relative number.  */
-      if (regnum < 0)
-       gdb_printf (file, " %4s", "Rel");
-      else if (regnum < gdbarch_num_regs (m_gdbarch))
-       gdb_printf (file, " %4d", regnum);
+      if (regnum < gdbarch_num_regs (m_gdbarch))
+       out->field_signed ("relnum", regnum);
       else
-       gdb_printf (file, " %4d",
-                   (regnum - gdbarch_num_regs (m_gdbarch)));
+       out->field_signed ("relnum", (regnum - gdbarch_num_regs (m_gdbarch)));
 
       /* Offset.  */
-      if (regnum < 0)
-       gdb_printf (file, " %6s  ", "Offset");
-      else
+      if (register_offset != descr->register_offset[regnum]
+         || (regnum > 0
+             && (descr->register_offset[regnum]
+                 != (descr->register_offset[regnum - 1]
+                     + descr->sizeof_register[regnum - 1]))))
        {
-         gdb_printf (file, " %6ld",
-                     descr->register_offset[regnum]);
-         if (register_offset != descr->register_offset[regnum]
-             || (regnum > 0
-                 && (descr->register_offset[regnum]
-                     != (descr->register_offset[regnum - 1]
-                         + descr->sizeof_register[regnum - 1])))
-             )
-           {
-             if (!footnote_register_offset)
-               footnote_register_offset = ++footnote_nr;
-             gdb_printf (file, "*%d", footnote_register_offset);
-           }
-         else
-           gdb_printf (file, "  ");
-         register_offset = (descr->register_offset[regnum]
-                            + descr->sizeof_register[regnum]);
+         if (!footnote_register_offset)
+           footnote_register_offset = ++footnote_nr;
+         std::string val = string_printf ("%ld*%d",
+                                          descr->register_offset[regnum],
+                                          footnote_register_offset);
+         out->field_string ("offset", val);
        }
+      else
+       out->field_signed ("offset", descr->register_offset[regnum]);
+      register_offset = (descr->register_offset[regnum]
+                        + descr->sizeof_register[regnum]);
 
       /* Size.  */
-      if (regnum < 0)
-       gdb_printf (file, " %5s ", "Size");
-      else
-       gdb_printf (file, " %5ld", descr->sizeof_register[regnum]);
+      out->field_signed ("size", descr->sizeof_register[regnum]);
 
       /* Type.  */
       {
        const char *t;
        std::string name_holder;
 
-       if (regnum < 0)
-         t = "Type";
-       else
+       static const char blt[] = "builtin_type";
+
+       t = register_type (m_gdbarch, regnum)->name ();
+       if (t == NULL)
          {
-           static const char blt[] = "builtin_type";
-
-           t = register_type (m_gdbarch, regnum)->name ();
-           if (t == NULL)
-             {
-               if (!footnote_register_type_name_null)
-                 footnote_register_type_name_null = ++footnote_nr;
-               name_holder = string_printf ("*%d",
-                                            footnote_register_type_name_null);
-               t = name_holder.c_str ();
-             }
-           /* Chop a leading builtin_type.  */
-           if (startswith (t, blt))
-             t += strlen (blt);
+           if (!footnote_register_type_name_null)
+             footnote_register_type_name_null = ++footnote_nr;
+           name_holder = string_printf ("*%d",
+                                        footnote_register_type_name_null);
+           t = name_holder.c_str ();
          }
-       gdb_printf (file, " %-15s", t);
-      }
+       /* Chop a leading builtin_type.  */
+       if (startswith (t, blt))
+         t += strlen (blt);
 
-      /* Leading space always present.  */
-      gdb_printf (file, " ");
+       out->field_string ("type", t);
+      }
 
-      dump_reg (file, regnum);
+      dump_reg (out, regnum);
 
-      gdb_printf (file, "\n");
+      out->text ("\n");
     }
 
   if (footnote_register_offset)
-    gdb_printf (file, "*%d: Inconsistent register offsets.\n",
-               footnote_register_offset);
+    out->message ("*%d: Inconsistent register offsets.\n",
+                 footnote_register_offset);
   if (footnote_register_type_name_null)
-    gdb_printf (file,
-               "*%d: Register type's name NULL.\n",
-               footnote_register_type_name_null);
+    out->message ("*%d: Register type's name NULL.\n",
+                 footnote_register_type_name_null);
 }
 
 #if GDB_SELF_TEST
index 8d026e0b4fe82d735709cd227cc66c291c8cadd4..7123698fb3bb47d5d33cc37184641701ece3eefb 100644 (file)
@@ -31,6 +31,7 @@ struct gdbarch;
 class thread_info;
 struct process_stratum_target;
 struct inferior;
+class ui_out;
 
 extern struct regcache *get_thread_regcache (process_stratum_target *target,
                                             ptid_t ptid);
@@ -536,7 +537,7 @@ extern void registers_changed_thread (thread_info *thread);
 class register_dump
 {
 public:
-  void dump (ui_file *file);
+  void dump (ui_out *out, const char *name);
   virtual ~register_dump () = default;
 
 protected:
@@ -544,9 +545,14 @@ protected:
     : m_gdbarch (arch)
   {}
 
-  /* Dump the register REGNUM contents.  If REGNUM is -1, print the
-     header.  */
-  virtual void dump_reg (ui_file *file, int regnum) = 0;
+  /* Number of additional table headers.  */
+  virtual int num_additional_headers () = 0;
+
+  /* Add the additional headers to OUT.  */
+  virtual void additional_headers (ui_out *out) = 0;
+
+  /* Dump the register REGNUM contents.  */
+  virtual void dump_reg (ui_out *out, int regnum) = 0;
 
   gdbarch *m_gdbarch;
 };
index f1e1b8774807423a73b265583a3e0119172c76fc..2c58ffa36c5c73159d7eafacdf0e82f0eded5436 100644 (file)
@@ -70,11 +70,11 @@ set saw_registers 0
 set saw_headers 0
 set test "maint print registers"
 gdb_test_multiple $test $test {
-    -re "\[^\r\n\]+Name\[^\r\n\]+Nr\[^\r\n\]+Rel\[^\r\n\]+Offset\[^\r\n\]+Size\[^\r\n\]+Type\[^\r\n\]+\r\n" {
+    -re "Name\[^\r\n\]+Nr\[^\r\n\]+Rel\[^\r\n\]+Offset\[^\r\n\]+Size\[^\r\n\]+Type\[^\r\n\]+\r\n" {
        set saw_headers 1
        exp_continue
     }
-    -re "^\[^\r\n\]+\[0-9\]+\[^\r\n\]+\[0-9\]+\[^\r\n\]+\[0-9\]+\[^\r\n\]+\[0-9\]+\[^\r\n\]+\r\n" {
+    -re "\[0-9\]+\[^\r\n\]+\[0-9\]+\[^\r\n\]+\[0-9\]+\[^\r\n\]+\[0-9\]+\[^\r\n\]+\r\n" {
         set saw_registers 1
         exp_continue
     }
index af5a5f53ca03f1bd9507f8b7284d70ddb7f12915..e81384f0dfb4fb5b187631ce131eb5e801c758a4 100644 (file)
@@ -74,7 +74,7 @@ if { [info exists pc_regname] } {
     set seen_line false
     gdb_test_multiple "maintenance print remote-registers" \
             $expedited_pc_test_name -lbl {
-       -re " ${pc_regname}\[\[:space:\]\]+${decimal}.*${decimal}  yes" {
+       -re "${pc_regname}\[\[:space:\]\]+${decimal}.*${decimal}\[\[:space:\]\]+yes" {
            set seen_line true
            exp_continue
        }