Rename fprintf_symbol_filtered
[binutils-gdb.git] / gdb / extension.c
index 8637bc53f2efdf420767b025f38a07f16a847f9e..8f39b86e952563fb57b334356ae63d4ff40062ca 100644 (file)
@@ -1,6 +1,6 @@
 /* Interface between gdb and its extension languages.
 
-   Copyright (C) 2014-2019 Free Software Foundation, Inc.
+   Copyright (C) 2014-2022 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "cli/cli-script.h"
 #include "python/python.h"
 #include "guile/guile.h"
-
-/* Iterate over all external extension languages, regardless of whether the
-   support has been compiled in or not.
-   This does not include GDB's own scripting language.  */
-
-#define ALL_EXTENSION_LANGUAGES(i, extlang) \
-  for (/*int*/ i = 0, extlang = extension_languages[0]; \
-       extlang != NULL; \
-       extlang = extension_languages[++i])
-
-/* Iterate over all external extension languages that are supported.
-   This does not include GDB's own scripting language.  */
-
-#define ALL_ENABLED_EXTENSION_LANGUAGES(i, extlang) \
-  for (/*int*/ i = 0, extlang = extension_languages[0]; \
-       extlang != NULL; \
-       extlang = extension_languages[++i]) \
-    if (extlang->ops != NULL)
+#include <array>
 
 static script_sourcer_func source_gdb_script;
 static objfile_script_sourcer_func source_gdb_objfile_script;
@@ -99,12 +82,11 @@ const struct extension_language_defn extension_language_gdb =
    pretty-printed value is the one that is used.  This algorithm is employed
    throughout.  */
 
-static const struct extension_language_defn * const extension_languages[] =
+static const std::array<const extension_language_defn *, 2> extension_languages
 {
   /* To preserve existing behaviour, python should always appear first.  */
   &extension_language_python,
   &extension_language_guile,
-  NULL
 };
 
 /* Return a pointer to the struct extension_language_defn object of
@@ -115,15 +97,12 @@ static const struct extension_language_defn * const extension_languages[] =
 const struct extension_language_defn *
 get_ext_lang_defn (enum extension_language lang)
 {
-  int i;
-  const struct extension_language_defn *extlang;
-
   gdb_assert (lang != EXT_LANG_NONE);
 
   if (lang == EXT_LANG_GDB)
     return &extension_language_gdb;
 
-  ALL_EXTENSION_LANGUAGES (i, extlang)
+  for (const struct extension_language_defn *extlang : extension_languages)
     {
       if (extlang->language == lang)
        return extlang;
@@ -151,10 +130,10 @@ has_extension (const char *file, const char *extension)
 const struct extension_language_defn *
 get_ext_lang_of_file (const char *file)
 {
-  int i;
-  const struct extension_language_defn *extlang;
+  if (has_extension (file, extension_language_gdb.suffix))
+    return &extension_language_gdb;
 
-  ALL_EXTENSION_LANGUAGES (i, extlang)
+  for (const struct extension_language_defn *extlang : extension_languages)
     {
       if (has_extension (file, extlang->suffix))
        return extlang;
@@ -303,14 +282,13 @@ ext_lang_objfile_script_executor
   return extlang->script_ops->objfile_script_executor;
 }
 
-/* Return non-zero if auto-loading of EXTLANG scripts is enabled.
-   Zero is returned if support for this language isn't compiled in.  */
+/* See extension.h.  */
 
-int
+bool
 ext_lang_auto_load_enabled (const struct extension_language_defn *extlang)
 {
   if (extlang->script_ops == NULL)
-    return 0;
+    return false;
 
   /* The extension language is required to implement this function.  */
   gdb_assert (extlang->script_ops->auto_load_enabled != NULL);
@@ -318,23 +296,47 @@ ext_lang_auto_load_enabled (const struct extension_language_defn *extlang)
   return extlang->script_ops->auto_load_enabled (extlang);
 }
 \f
+
+/* RAII class used to temporarily return SIG to its default handler.  */
+
+template<int SIG>
+struct scoped_default_signal
+{
+  scoped_default_signal ()
+  { m_old_sig_handler = signal (SIG, SIG_DFL); }
+
+  ~scoped_default_signal ()
+  { signal (SIG, m_old_sig_handler); }
+
+  DISABLE_COPY_AND_ASSIGN (scoped_default_signal);
+
+private:
+  /* The previous signal handler that needs to be restored.  */
+  sighandler_t m_old_sig_handler;
+};
+
+/* Class to temporarily return SIGINT to its default handler.  */
+
+using scoped_default_sigint = scoped_default_signal<SIGINT>;
+
 /* Functions that iterate over all extension languages.
    These only iterate over external extension languages, not including
    GDB's own extension/scripting language, unless otherwise indicated.  */
 
-/* Wrapper to call the extension_language_ops.finish_initialization "method"
-   for each compiled-in extension language.  */
+/* Wrapper to call the extension_language_ops.initialize "method" for each
+   compiled-in extension language.  */
 
 void
-finish_ext_lang_initialization (void)
+ext_lang_initialization (void)
 {
-  int i;
-  const struct extension_language_defn *extlang;
-
-  ALL_ENABLED_EXTENSION_LANGUAGES (i, extlang)
+  for (const struct extension_language_defn *extlang : extension_languages)
     {
-      if (extlang->ops->finish_initialization != NULL)
-       extlang->ops->finish_initialization (extlang);
+      if (extlang->ops != nullptr
+         && extlang->ops->initialize != NULL)
+       {
+         scoped_default_sigint set_sigint_to_default_handler;
+         extlang->ops->initialize (extlang);
+       }
     }
 }
 
@@ -352,10 +354,7 @@ finish_ext_lang_initialization (void)
 void
 eval_ext_lang_from_control_command (struct command_line *cmd)
 {
-  int i;
-  const struct extension_language_defn *extlang;
-
-  ALL_EXTENSION_LANGUAGES (i, extlang)
+  for (const struct extension_language_defn *extlang : extension_languages)
     {
       if (extlang->cli_control_type == cmd->control_type)
        {
@@ -382,16 +381,14 @@ eval_ext_lang_from_control_command (struct command_line *cmd)
 void
 auto_load_ext_lang_scripts_for_objfile (struct objfile *objfile)
 {
-  int i;
-  const struct extension_language_defn *extlang;
-
-  extlang = &extension_language_gdb;
-  if (ext_lang_auto_load_enabled (extlang))
-    auto_load_objfile_script (objfile, extlang);
+  const struct extension_language_defn *gdb = &extension_language_gdb;
+  if (ext_lang_auto_load_enabled (gdb))
+    auto_load_objfile_script (objfile, gdb);
 
-  ALL_ENABLED_EXTENSION_LANGUAGES (i, extlang)
+  for (const struct extension_language_defn *extlang : extension_languages)
     {
-      if (ext_lang_auto_load_enabled (extlang))
+      if (extlang->ops != nullptr
+         && ext_lang_auto_load_enabled (extlang))
        auto_load_objfile_script (objfile, extlang);
     }
 }
@@ -407,12 +404,10 @@ auto_load_ext_lang_scripts_for_objfile (struct objfile *objfile)
 
 ext_lang_type_printers::ext_lang_type_printers ()
 {
-  int i;
-  const struct extension_language_defn *extlang;
-
-  ALL_ENABLED_EXTENSION_LANGUAGES (i, extlang)
+  for (const struct extension_language_defn *extlang : extension_languages)
     {
-      if (extlang->ops->start_type_printers != NULL)
+      if (extlang->ops != nullptr
+         && extlang->ops->start_type_printers != NULL)
        extlang->ops->start_type_printers (extlang, this);
     }
 }
@@ -426,15 +421,13 @@ char *
 apply_ext_lang_type_printers (struct ext_lang_type_printers *printers,
                              struct type *type)
 {
-  int i;
-  const struct extension_language_defn *extlang;
-
-  ALL_ENABLED_EXTENSION_LANGUAGES (i, extlang)
+  for (const struct extension_language_defn *extlang : extension_languages)
     {
       char *result = NULL;
       enum ext_lang_rc rc;
 
-      if (extlang->ops->apply_type_printers == NULL)
+      if (extlang->ops == nullptr
+         || extlang->ops->apply_type_printers == NULL)
        continue;
       rc = extlang->ops->apply_type_printers (extlang, printers, type,
                                              &result);
@@ -457,22 +450,17 @@ apply_ext_lang_type_printers (struct ext_lang_type_printers *printers,
 
 ext_lang_type_printers::~ext_lang_type_printers ()
 {
-  int i;
-  const struct extension_language_defn *extlang;
-
-  ALL_ENABLED_EXTENSION_LANGUAGES (i, extlang)
+  for (const struct extension_language_defn *extlang : extension_languages)
     {
-      if (extlang->ops->free_type_printers != NULL)
+      if (extlang->ops != nullptr
+         && extlang->ops->free_type_printers != NULL)
        extlang->ops->free_type_printers (extlang, this);
     }
 }
 \f
-/* Try to pretty-print a value of type TYPE located at VAL's contents
-   buffer + EMBEDDED_OFFSET, which came from the inferior at address
-   ADDRESS + EMBEDDED_OFFSET, onto stdio stream STREAM according to
-   OPTIONS.
-   VAL is the whole object that came from ADDRESS.
-   Returns non-zero if the value was successfully pretty-printed.
+/* Try to pretty-print a value onto stdio stream STREAM according to
+   OPTIONS.  VAL is the object to print.  Returns non-zero if the
+   value was successfully pretty-printed.
 
    Extension languages are tried in the order specified by
    extension_languages.  The first one to provide a pretty-printed
@@ -485,26 +473,20 @@ ext_lang_type_printers::~ext_lang_type_printers ()
    errors that trigger an exception in the extension language.  */
 
 int
-apply_ext_lang_val_pretty_printer (struct type *type,
-                                  LONGEST embedded_offset, CORE_ADDR address,
+apply_ext_lang_val_pretty_printer (struct value *val,
                                   struct ui_file *stream, int recurse,
-                                  struct value *val,
                                   const struct value_print_options *options,
                                   const struct language_defn *language)
 {
-  int i;
-  const struct extension_language_defn *extlang;
-
-  ALL_ENABLED_EXTENSION_LANGUAGES (i, extlang)
+  for (const struct extension_language_defn *extlang : extension_languages)
     {
       enum ext_lang_rc rc;
 
-      if (extlang->ops->apply_val_pretty_printer == NULL)
+      if (extlang->ops == nullptr
+         || extlang->ops->apply_val_pretty_printer == NULL)
        continue;
-      rc = extlang->ops->apply_val_pretty_printer (extlang, type,
-                                                  embedded_offset, address,
-                                                  stream, recurse, val,
-                                                  options, language);
+      rc = extlang->ops->apply_val_pretty_printer (extlang, val, stream,
+                                                  recurse, options, language);
       switch (rc)
        {
        case EXT_LANG_RC_OK:
@@ -548,14 +530,12 @@ apply_ext_lang_frame_filter (struct frame_info *frame,
                             struct ui_out *out,
                             int frame_low, int frame_high)
 {
-  int i;
-  const struct extension_language_defn *extlang;
-
-  ALL_ENABLED_EXTENSION_LANGUAGES (i, extlang)
+  for (const struct extension_language_defn *extlang : extension_languages)
     {
       enum ext_lang_bt_status status;
 
-      if (extlang->ops->apply_frame_filter == NULL)
+      if (extlang->ops == nullptr
+         || extlang->ops->apply_frame_filter == NULL)
        continue;
       status = extlang->ops->apply_frame_filter (extlang, frame, flags,
                                               args_type, out,
@@ -581,12 +561,10 @@ apply_ext_lang_frame_filter (struct frame_info *frame,
 void
 preserve_ext_lang_values (struct objfile *objfile, htab_t copied_types)
 {
-  int i;
-  const struct extension_language_defn *extlang;
-
-  ALL_ENABLED_EXTENSION_LANGUAGES (i, extlang)
+  for (const struct extension_language_defn *extlang : extension_languages)
     {
-      if (extlang->ops->preserve_values != NULL)
+      if (extlang->ops != nullptr
+         && extlang->ops->preserve_values != NULL)
        extlang->ops->preserve_values (extlang, objfile, copied_types);
     }
 }
@@ -604,12 +582,10 @@ const struct extension_language_defn *
 get_breakpoint_cond_ext_lang (struct breakpoint *b,
                              enum extension_language skip_lang)
 {
-  int i;
-  const struct extension_language_defn *extlang;
-
-  ALL_ENABLED_EXTENSION_LANGUAGES (i, extlang)
+  for (const struct extension_language_defn *extlang : extension_languages)
     {
-      if (extlang->language != skip_lang
+      if (extlang->ops != nullptr
+         && extlang->language != skip_lang
          && extlang->ops->breakpoint_has_cond != NULL
          && extlang->ops->breakpoint_has_cond (extlang, b))
        return extlang;
@@ -624,18 +600,17 @@ get_breakpoint_cond_ext_lang (struct breakpoint *b,
 int
 breakpoint_ext_lang_cond_says_stop (struct breakpoint *b)
 {
-  int i;
-  const struct extension_language_defn *extlang;
   enum ext_lang_bp_stop stop = EXT_LANG_BP_STOP_UNSET;
 
-  ALL_ENABLED_EXTENSION_LANGUAGES (i, extlang)
+  for (const struct extension_language_defn *extlang : extension_languages)
     {
       /* There is a rule that a breakpoint can have at most one of any of a
         CLI or extension language condition.  However, Python hacks in "finish
         breakpoints" on top of the "stop" check, so we have to call this for
         every language, even if we could first determine whether a "stop"
         method exists.  */
-      if (extlang->ops->breakpoint_cond_says_stop != NULL)
+      if (extlang->ops != nullptr
+         && extlang->ops->breakpoint_cond_says_stop != NULL)
        {
          enum ext_lang_bp_stop this_stop
            = extlang->ops->breakpoint_cond_says_stop (extlang, b);
@@ -707,6 +682,12 @@ install_gdb_sigint_handler (struct signal_handler *previous)
     previous->handler_saved = 0;
 }
 
+#if GDB_SELF_TEST
+namespace selftests {
+void (*hook_set_active_ext_lang) () = nullptr;
+}
+#endif
+
 /* Set the currently active extension language to NOW_ACTIVE.
    The result is a pointer to a malloc'd block of memory to pass to
    restore_active_ext_lang.
@@ -733,6 +714,11 @@ install_gdb_sigint_handler (struct signal_handler *previous)
 struct active_ext_lang_state *
 set_active_ext_lang (const struct extension_language_defn *now_active)
 {
+#if GDB_SELF_TEST
+  if (selftests::hook_set_active_ext_lang)
+    selftests::hook_set_active_ext_lang ();
+#endif
+
   struct active_ext_lang_state *previous
     = XCNEW (struct active_ext_lang_state);
 
@@ -817,12 +803,12 @@ set_quit_flag (void)
 int
 check_quit_flag (void)
 {
-  int i, result = 0;
-  const struct extension_language_defn *extlang;
+  int result = 0;
 
-  ALL_ENABLED_EXTENSION_LANGUAGES (i, extlang)
+  for (const struct extension_language_defn *extlang : extension_languages)
     {
-      if (extlang->ops->check_quit_flag != NULL)
+      if (extlang->ops != nullptr
+         && extlang->ops->check_quit_flag != NULL)
        if (extlang->ops->check_quit_flag (extlang) != 0)
          result = 1;
     }
@@ -847,16 +833,14 @@ void
 get_matching_xmethod_workers (struct type *type, const char *method_name,
                              std::vector<xmethod_worker_up> *workers)
 {
-  int i;
-  const struct extension_language_defn *extlang;
-
-  ALL_ENABLED_EXTENSION_LANGUAGES (i, extlang)
+  for (const struct extension_language_defn *extlang : extension_languages)
     {
       enum ext_lang_rc rc;
 
       /* If an extension language does not support xmethods, ignore
         it.  */
-      if (extlang->ops->get_matching_xmethod_workers == NULL)
+      if (extlang->ops == nullptr
+         || extlang->ops->get_matching_xmethod_workers == NULL)
        continue;
 
       rc = extlang->ops->get_matching_xmethod_workers (extlang,
@@ -900,6 +884,46 @@ xmethod_worker::get_result_type (value *object, gdb::array_view<value *> args)
   return result_type;
 }
 
+/* See extension.h.  */
+
+gdb::optional<std::string>
+ext_lang_colorize (const std::string &filename, const std::string &contents)
+{
+  gdb::optional<std::string> result;
+
+  for (const struct extension_language_defn *extlang : extension_languages)
+    {
+      if (extlang->ops == nullptr
+         || extlang->ops->colorize == nullptr)
+       continue;
+      result = extlang->ops->colorize (filename, contents);
+      if (result.has_value ())
+       return result;
+    }
+
+  return result;
+}
+
+/* See extension.h.  */
+
+gdb::optional<std::string>
+ext_lang_colorize_disasm (const std::string &content, gdbarch *gdbarch)
+{
+  gdb::optional<std::string> result;
+
+  for (const struct extension_language_defn *extlang : extension_languages)
+    {
+      if (extlang->ops == nullptr
+         || extlang->ops->colorize_disasm == nullptr)
+       continue;
+      result = extlang->ops->colorize_disasm (content, gdbarch);
+      if (result.has_value ())
+       return result;
+    }
+
+  return result;
+}
+
 /* Called via an observer before gdb prints its prompt.
    Iterate over the extension languages giving them a chance to
    change the prompt.  The first one to change the prompt wins,
@@ -908,14 +932,12 @@ xmethod_worker::get_result_type (value *object, gdb::array_view<value *> args)
 static void
 ext_lang_before_prompt (const char *current_gdb_prompt)
 {
-  int i;
-  const struct extension_language_defn *extlang;
-
-  ALL_ENABLED_EXTENSION_LANGUAGES (i, extlang)
+  for (const struct extension_language_defn *extlang : extension_languages)
     {
       enum ext_lang_rc rc;
 
-      if (extlang->ops->before_prompt == NULL)
+      if (extlang->ops == nullptr
+         || extlang->ops->before_prompt == NULL)
        continue;
       rc = extlang->ops->before_prompt (extlang, current_gdb_prompt);
       switch (rc)
@@ -931,8 +953,9 @@ ext_lang_before_prompt (const char *current_gdb_prompt)
     }
 }
 
+void _initialize_extension ();
 void
-_initialize_extension (void)
+_initialize_extension ()
 {
-  gdb::observers::before_prompt.attach (ext_lang_before_prompt);
+  gdb::observers::before_prompt.attach (ext_lang_before_prompt, "extension");
 }