opcodes/i386: remove trailing whitespace from insns with zero operands
[binutils-gdb.git] / gdb / disasm.c
index bfccbfcddcd949f17b629a4e02eec16625f3b99a..f2df5ef7bc5b7c3e07f13cf8eda85c09abbcf4e7 100644 (file)
@@ -171,7 +171,23 @@ gdb_disassembler::dis_asm_fprintf (void *stream, const char *format, ...)
   va_list args;
 
   va_start (args, format);
-  vfprintf_filtered ((struct ui_file *) stream, format, args);
+  gdb_vprintf ((struct ui_file *) stream, format, args);
+  va_end (args);
+  /* Something non -ve.  */
+  return 0;
+}
+
+/* See disasm.h.  */
+
+int
+gdb_disassembler::dis_asm_styled_fprintf (void *stream,
+                                         enum disassembler_style style,
+                                         const char *format, ...)
+{
+  va_list args;
+
+  va_start (args, format);
+  gdb_vprintf ((struct ui_file *) stream, format, args);
   va_end (args);
   /* Something non -ve.  */
   return 0;
@@ -782,9 +798,13 @@ get_all_disassembler_options (struct gdbarch *gdbarch)
 gdb_disassembler::gdb_disassembler (struct gdbarch *gdbarch,
                                    struct ui_file *file,
                                    di_read_memory_ftype read_memory_func)
-  : m_gdbarch (gdbarch)
+  : m_gdbarch (gdbarch),
+    m_buffer (!use_ext_lang_colorization_p && disassembler_styling
+             && file->can_emit_style_escape ()),
+    m_dest (file)
 {
-  init_disassemble_info (&m_di, file, dis_asm_fprintf);
+  init_disassemble_info (&m_di, &m_buffer, dis_asm_fprintf,
+                        dis_asm_styled_fprintf);
   m_di.flavour = bfd_target_unknown_flavour;
   m_di.memory_error_func = dis_asm_memory_error;
   m_di.print_address_func = dis_asm_print_address;
@@ -813,14 +833,65 @@ gdb_disassembler::~gdb_disassembler ()
   disassemble_free_target (&m_di);
 }
 
+/* See disasm.h.  */
+
+bool gdb_disassembler::use_ext_lang_colorization_p = true;
+
+/* See disasm.h.  */
+
 int
 gdb_disassembler::print_insn (CORE_ADDR memaddr,
                              int *branch_delay_insns)
 {
   m_err_memaddr.reset ();
+  m_buffer.clear ();
 
   int length = gdbarch_print_insn (arch (), memaddr, &m_di);
 
+  /* If we have successfully disassembled an instruction, styling is on, we
+     think that the extension language might be able to perform styling for
+     us, and the destination can support styling, then lets call into the
+     extension languages in order to style this output.  */
+  if (length > 0 && disassembler_styling
+      && use_ext_lang_colorization_p
+      && m_dest->can_emit_style_escape ())
+    {
+      gdb::optional<std::string> ext_contents;
+      ext_contents = ext_lang_colorize_disasm (m_buffer.string (), arch ());
+      if (ext_contents.has_value ())
+       m_buffer = std::move (*ext_contents);
+      else
+       {
+         /* The extension language failed to add styling to the
+            disassembly output.  Set the static flag so that next time we
+            disassemble we don't even bother attempting to use the
+            extension language for styling.  */
+         use_ext_lang_colorization_p = false;
+
+         /* The instruction we just disassembled, and the extension
+            languages failed to style, might have otherwise had some
+            minimal styling applied by GDB.  To regain that styling we
+            need to recreate m_buffer, but this time with styling support.
+
+            To do this we perform an in-place new, but this time turn on
+            the styling support, then we can re-disassembly the
+            instruction, and gain any minimal styling GDB might add.  */
+         gdb_static_assert ((std::is_same<decltype (m_buffer),
+                             string_file>::value));
+         gdb_assert (!m_buffer.term_out ());
+         m_buffer.~string_file ();
+         new (&m_buffer) string_file (true);
+         length = gdbarch_print_insn (arch (), memaddr, &m_di);
+         gdb_assert (length > 0);
+       }
+    }
+
+  /* Push any disassemble output to the real destination stream.  We do
+     this even if the disassembler reported failure (-1) as the
+     disassembler may have printed something to its output stream.  */
+  m_di.fprintf_func (m_dest, "%s", m_buffer.c_str ());
+
+  /* If the disassembler failed then report an appropriate error.  */
   if (length < 0)
     {
       if (m_err_memaddr.has_value ())
@@ -891,16 +962,36 @@ gdb_insn_length (struct gdbarch *gdbarch, CORE_ADDR addr)
   return gdb_print_insn (gdbarch, addr, &null_stream, NULL);
 }
 
-/* fprintf-function for gdb_buffered_insn_length.  This function is a
-   nop, we don't want to print anything, we just want to compute the
-   length of the insn.  */
+/* An fprintf-function for use by the disassembler when we know we don't
+   want to print anything.  Always returns success.  */
 
 static int ATTRIBUTE_PRINTF (2, 3)
-gdb_buffered_insn_length_fprintf (void *stream, const char *format, ...)
+gdb_disasm_null_printf (void *stream, const char *format, ...)
 {
   return 0;
 }
 
+/* An fprintf-function for use by the disassembler when we know we don't
+   want to print anything, and the disassembler is using style.  Always
+   returns success.  */
+
+static int ATTRIBUTE_PRINTF (3, 4)
+gdb_disasm_null_styled_printf (void *stream,
+                              enum disassembler_style style,
+                              const char *format, ...)
+{
+  return 0;
+}
+
+/* See disasm.h.  */
+
+void
+init_disassemble_info_for_no_printing (struct disassemble_info *dinfo)
+{
+  init_disassemble_info (dinfo, nullptr, gdb_disasm_null_printf,
+                        gdb_disasm_null_styled_printf);
+}
+
 /* Initialize a struct disassemble_info for gdb_buffered_insn_length.
    Upon return, *DISASSEMBLER_OPTIONS_HOLDER owns the string pointed
    to by DI.DISASSEMBLER_OPTIONS.  */
@@ -912,7 +1003,7 @@ gdb_buffered_insn_length_init_dis (struct gdbarch *gdbarch,
                                   CORE_ADDR addr,
                                   std::string *disassembler_options_holder)
 {
-  init_disassemble_info (di, NULL, gdb_buffered_insn_length_fprintf);
+  init_disassemble_info_for_no_printing (di);
 
   /* init_disassemble_info installs buffer_read_memory, etc.
      so we don't need to do that here.
@@ -987,7 +1078,7 @@ set_disassembler_options (const char *prospective_options)
   valid_options_and_args = gdbarch_valid_disassembler_options (gdbarch);
   if (valid_options_and_args == NULL)
     {
-      fprintf_filtered (gdb_stderr, _("\
+      gdb_printf (gdb_stderr, _("\
 'set disassembler-options ...' is not supported on this architecture.\n"));
       return;
     }
@@ -1023,9 +1114,9 @@ set_disassembler_options (const char *prospective_options)
          break;
       if (valid_options->name[i] == NULL)
        {
-         fprintf_filtered (gdb_stderr,
-                           _("Invalid disassembler option value: '%s'.\n"),
-                           opt);
+         gdb_printf (gdb_stderr,
+                     _("Invalid disassembler option value: '%s'.\n"),
+                     opt);
          return;
        }
     }
@@ -1054,22 +1145,22 @@ show_disassembler_options_sfunc (struct ui_file *file, int from_tty,
   if (options == NULL)
     options = "";
 
-  fprintf_filtered (file, _("The current disassembler options are '%s'\n\n"),
-                   options);
+  gdb_printf (file, _("The current disassembler options are '%s'\n\n"),
+             options);
 
   valid_options_and_args = gdbarch_valid_disassembler_options (gdbarch);
 
   if (valid_options_and_args == NULL)
     {
-      fputs_filtered (_("There are no disassembler options available "
-                       "for this architecture.\n"),
-                     file);
+      gdb_puts (_("There are no disassembler options available "
+                 "for this architecture.\n"),
+               file);
       return;
     }
 
   valid_options = &valid_options_and_args->options;
 
-  fprintf_filtered (file, _("\
+  gdb_printf (file, _("\
 The following disassembler options are supported for use with the\n\
 'set disassembler-options OPTION [,OPTION]...' command:\n"));
 
@@ -1077,7 +1168,7 @@ The following disassembler options are supported for use with the\n\
     {
       size_t i, max_len = 0;
 
-      fprintf_filtered (file, "\n");
+      gdb_printf (file, "\n");
 
       /* Compute the length of the longest option name.  */
       for (i = 0; valid_options->name[i] != NULL; i++)
@@ -1092,35 +1183,35 @@ The following disassembler options are supported for use with the\n\
 
       for (i = 0, max_len++; valid_options->name[i] != NULL; i++)
        {
-         fprintf_filtered (file, "  %s", valid_options->name[i]);
+         gdb_printf (file, "  %s", valid_options->name[i]);
          if (valid_options->arg != NULL && valid_options->arg[i] != NULL)
-           fprintf_filtered (file, "%s", valid_options->arg[i]->name);
+           gdb_printf (file, "%s", valid_options->arg[i]->name);
          if (valid_options->description[i] != NULL)
            {
              size_t len = strlen (valid_options->name[i]);
 
              if (valid_options->arg != NULL && valid_options->arg[i] != NULL)
                len += strlen (valid_options->arg[i]->name);
-             fprintf_filtered (file, "%*c %s", (int) (max_len - len), ' ',
-                               valid_options->description[i]);
+             gdb_printf (file, "%*c %s", (int) (max_len - len), ' ',
+                         valid_options->description[i]);
            }
-         fprintf_filtered (file, "\n");
+         gdb_printf (file, "\n");
        }
     }
   else
     {
       size_t i;
-      fprintf_filtered (file, "  ");
+      gdb_printf (file, "  ");
       for (i = 0; valid_options->name[i] != NULL; i++)
        {
-         fprintf_filtered (file, "%s", valid_options->name[i]);
+         gdb_printf (file, "%s", valid_options->name[i]);
          if (valid_options->arg != NULL && valid_options->arg[i] != NULL)
-           fprintf_filtered (file, "%s", valid_options->arg[i]->name);
+           gdb_printf (file, "%s", valid_options->arg[i]->name);
          if (valid_options->name[i + 1] != NULL)
-           fprintf_filtered (file, ", ");
+           gdb_printf (file, ", ");
          file->wrap_here (2);
        }
-      fprintf_filtered (file, "\n");
+      gdb_printf (file, "\n");
     }
 
   valid_args = valid_options_and_args->args;
@@ -1130,15 +1221,15 @@ The following disassembler options are supported for use with the\n\
 
       for (i = 0; valid_args[i].name != NULL; i++)
        {
-         fprintf_filtered (file, _("\n\
+         gdb_printf (file, _("\n\
   For the options above, the following values are supported for \"%s\":\n   "),
-                           valid_args[i].name);
+                     valid_args[i].name);
          for (j = 0; valid_args[i].values[j] != NULL; j++)
            {
-             fprintf_filtered (file, " %s", valid_args[i].values[j]);
+             gdb_printf (file, " %s", valid_args[i].values[j]);
              file->wrap_here (3);
            }
-         fprintf_filtered (file, "\n");
+         gdb_printf (file, "\n");
        }
     }
 }