]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gdb/python: make use of gdb.Style for shipped Python commands
authorAndrew Burgess <aburgess@redhat.com>
Sun, 5 Oct 2025 17:51:12 +0000 (18:51 +0100)
committerAndrew Burgess <aburgess@redhat.com>
Tue, 7 Oct 2025 15:35:44 +0000 (16:35 +0100)
With the recent addition of the gdb.Style Python API, this commit goes
through the gdb.Command sub-classes which we ship with GDB and adds
some styling support.

This adds 'title' style in a couple of places where we layout tables.
And uses 'filename' style where we are printing filenames.

While I was making these changes I've made a couple of related fixes.

In 'info frame-filter', 'info missing-objfile-handlers', 'info
pretty-printer', and 'info xmethod', we would sometimes print the
gdb.Progspace.filename unconditionally, even though this field can
sometimes be None.  To better handle this case, I now check for None,
and print '<no-file>' instead.  We already printed that same string
for the program space name in at least one other case, so this change
makes things a little more consistent.

I don't format the '<no-file>' string with the filename style, only if
we have an actual filename does the string get formatted.

The other fix I made was in 'maint info python-disassemblers'.  Here
I've added an extra space between the two columns in the output
table.  The two columns are 'Architecture' and 'Disassembler Name'.
Given that one column contains a white space, it was rather confusing
having a single space between columns.  Luckily the tests don't depend
on a single space, so nothing needs updating for this change.

Additionally, in 'info frame-filter' I've updated the exception
handling to use the gdb.warning function, rather than just printing a
line of output.  This means that should this case occur we get the
neat little emoji.  We have no tests that trigger this warning, and I
couldn't figure out how to write one.  In this end, I just hacked the
Python code to raise an exception and checked the output looked
reasonable.  I suspect this warning might be a hard one to trigger!

Approved-By: Tom Tromey <tom@tromey.com>
gdb/python/lib/gdb/command/frame_filters.py
gdb/python/lib/gdb/command/missing_files.py
gdb/python/lib/gdb/command/pretty_printers.py
gdb/python/lib/gdb/command/xmethods.py
gdb/python/lib/gdb/disassembler.py

index be7be9aa5fc5477c08cadb58b663f4b6bee2ad9c..4b2d214d697f17b49c5e37f0a6b779264c4508eb 100644 (file)
@@ -68,7 +68,11 @@ class InfoFrameFilter(gdb.Command):
             return 0
 
         print(title)
-        print("  Priority  Enabled  Name")
+        style = gdb.Style("title")
+        print(
+            "  %s  %s  %s"
+            % (style.apply("Priority"), style.apply("Enabled"), style.apply("Name"))
+        )
         for frame_filter in sorted_frame_filters:
             name = frame_filter[0]
             try:
@@ -77,9 +81,8 @@ class InfoFrameFilter(gdb.Command):
                     self.enabled_string(gdb.frames.get_enabled(frame_filter[1]))
                 )
                 print("  %s  %s  %s" % (priority, enabled, name))
-            except Exception:
-                e = sys.exc_info()[1]
-                print("  Error printing filter '" + name + "': " + str(e))
+            except Exception as e:
+                gdb.warning("Error printing filter '" + name + "': " + str(e))
         if blank_line:
             print("")
         return 1
@@ -87,14 +90,20 @@ class InfoFrameFilter(gdb.Command):
     def invoke(self, arg, from_tty):
         any_printed = self.print_list("global frame-filters:", gdb.frame_filters, True)
 
+        file_style = gdb.Style("filename")
         cp = gdb.current_progspace()
+        cp_filename = cp.filename
+        if cp_filename is None:
+            cp_filename = "<no-file>"
+        else:
+            cp_filename = file_style.apply(cp_filename)
         any_printed += self.print_list(
-            "progspace %s frame-filters:" % cp.filename, cp.frame_filters, True
+            "progspace %s frame-filters:" % cp_filename, cp.frame_filters, True
         )
 
         for objfile in gdb.objfiles():
             any_printed += self.print_list(
-                "objfile %s frame-filters:" % objfile.filename,
+                "objfile %s frame-filters:" % file_style.apply(objfile.filename),
                 objfile.frame_filters,
                 False,
             )
index 09d9684dca2636203280ebc194e025a092a72713..b2477ce0efbd12c59b2f32c05503fbc9138201ba 100644 (file)
@@ -118,10 +118,16 @@ class InfoMissingFileHandlers(gdb.Command):
     def invoke(self, arg, from_tty):
         locus_re, name_re = parse_missing_file_command_args(arg)
 
+        file_style = gdb.Style("filename")
         if locus_re.match("progspace") and locus_re.pattern != "":
             cp = gdb.current_progspace()
+            cp_filename = cp.filename
+            if cp.filename is None:
+                cp_filename = "<no-file>"
+            else:
+                cp_filename = file_style.apply(cp_filename)
             self.list_handlers(
-                "Progspace %s:" % cp.filename, cp.missing_file_handlers, name_re
+                "Progspace %s:" % cp_filename, cp.missing_file_handlers, name_re
             )
 
         for progspace in gdb.progspaces():
@@ -133,7 +139,7 @@ class InfoMissingFileHandlers(gdb.Command):
                     else:
                         msg = "Progspace <no-file>:"
                 else:
-                    msg = "Progspace %s:" % filename
+                    msg = "Progspace %s:" % file_style.apply(filename)
                 self.list_handlers(
                     msg,
                     progspace.missing_file_handlers,
index f62d329c54df022c2f1bb6139d1b0093878edd38..cdf90543cac1e50df94943583483da175fd3485c 100644 (file)
@@ -161,9 +161,15 @@ class InfoPrettyPrinter(gdb.Command):
             name_re,
             subname_re,
         )
+        file_style = gdb.Style("filename")
         cp = gdb.current_progspace()
+        cp_filename = cp.filename
+        if cp_filename is None:
+            cp_filename = "<no-file>"
+        else:
+            cp_filename = file_style.apply(cp_filename)
         self.invoke1(
-            "progspace %s pretty-printers:" % cp.filename,
+            "progspace %s pretty-printers:" % cp_filename,
             cp.pretty_printers,
             "progspace",
             object_re,
@@ -172,7 +178,7 @@ class InfoPrettyPrinter(gdb.Command):
         )
         for objfile in gdb.objfiles():
             self.invoke1(
-                "objfile %s pretty-printers:" % objfile.filename,
+                "objfile %s pretty-printers:" % file_style.apply(objfile.filename),
                 objfile.pretty_printers,
                 objfile.filename,
                 object_re,
index 719c1463d4a48165b262ba97bb714870f7101334..2f870746bdc46896f730b9c6ca8eee05268947e0 100644 (file)
@@ -101,6 +101,7 @@ def get_method_matchers_in_loci(loci, locus_re, matcher_re):
         A dict of matching xmethod matchers.  The keys of the dict are the
         filenames of the loci the xmethod matchers belong to.
     """
+    file_style = gdb.Style("filename")
     xm_dict = {}
     for locus in loci:
         if isinstance(locus, gdb.Progspace):
@@ -111,7 +112,12 @@ def get_method_matchers_in_loci(loci, locus_re, matcher_re):
             if not locus_re.match(locus.filename):
                 continue
             locus_type = "objfile"
-        locus_str = "%s %s" % (locus_type, locus.filename)
+        filename = locus.filename
+        if filename is None:
+            filename = "<no-file>"
+        else:
+            filename = file_style.apply(filename)
+        locus_str = "%s %s" % (locus_type, filename)
         xm_dict[locus_str] = [m for m in locus.xmethods if matcher_re.match(m.name)]
     return xm_dict
 
index 8f8e768f6378c8c76e49a27c3e3a7b6b7d5922d1..595667882104176d63799e98479e9fd42bd5fe2e 100644 (file)
@@ -155,9 +155,21 @@ class maint_info_py_disassemblers_cmd(gdb.Command):
         # Now print the dictionary of registered disassemblers out to
         # the user.
         match_tag = "\t(Matches current architecture)"
-        fmt_len = max(longest_arch_name, len("Architecture"))
-        format_string = "{:" + str(fmt_len) + "s} {:s}"
-        print(format_string.format("Architecture", "Disassember Name"))
+        arch_title = "Architecture"
+        fmt_len = max(longest_arch_name, len(arch_title))
+        format_string = "{:" + str(fmt_len) + "s}  {:s}"
+        padding_string = " " * (fmt_len - len(arch_title))
+        title_style = gdb.Style("title")
+        # We cannot use FORMAT_STRING to layout the title line, as
+        # Python is unable to calculate the length of a styled string.
+        # Instead use PADDING_STRING to manually layout the columns.
+        print(
+            "{:s}{:s}  {:s}".format(
+                title_style.apply(arch_title),
+                padding_string,
+                title_style.apply("Disassember Name"),
+            )
+        )
         for architecture in _disassemblers_dict:
             if architecture is not None:
                 name = _disassemblers_dict[architecture].name