+2020-01-21 Tom Tromey <tromey@adacore.com>
+
+ * source-cache.c (source_cache::ensure): Call ext_lang_colorize.
+ * python/python.c (python_extension_ops): Update.
+ (gdbpy_colorize): New function.
+ * python/lib/gdb/__init__.py (colorize): New function.
+ * extension.h (ext_lang_colorize): Declare.
+ * extension.c (ext_lang_colorize): New function.
+ * extension-priv.h (struct extension_language_ops) <colorize>: New
+ member.
+ * cli/cli-style.c (_initialize_cli_style): Update help text.
+
2020-01-21 Luis Machado <luis.machado@linaro.org>
* aarch64-tdep.c (struct aarch64_displaced_step_closure)
"Note that source styling only works if styling in general is enabled,\n\
see \"show style enabled\"."
#else
-"Source highlighting is disabled in this installation of gdb, because\n\
-it was not linked against GNU Source Highlight."
+"Source highlighting may be disabled in this installation of gdb, because\n\
+it was not linked against GNU Source Highlight. However, it might still be\n\
+available if the appropriate extension is available at runtime."
#endif
), set_style_enabled, show_style_sources,
&style_set_list, &style_show_list);
struct type *obj_type,
const char *method_name,
std::vector<xmethod_worker_up> *dm_vec);
+
+ /* Colorize a source file. NAME is the source file's name, and
+ CONTENTS is the contents of the file. This should either return
+ colorized (using ANSI terminal escapes) version of the contents,
+ or an empty option. */
+ gdb::optional<std::string> (*colorize) (const std::string &name,
+ const std::string &contents);
};
/* State necessary to restore a signal handler to its previous value. */
return result_type;
}
+/* See extension.h. */
+
+gdb::optional<std::string>
+ext_lang_colorize (const std::string &filename, const std::string &contents)
+{
+ int i;
+ const struct extension_language_defn *extlang;
+ gdb::optional<std::string> result;
+
+ ALL_ENABLED_EXTENSION_LANGUAGES (i, extlang)
+ {
+ if (extlang->ops->colorize == nullptr)
+ continue;
+ result = extlang->ops->colorize (filename, contents);
+ 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,
#include "mi/mi-cmds.h" /* For PRINT_NO_VALUES, etc. */
#include "gdbsupport/array-view.h"
+#include "gdbsupport/gdb_optional.h"
struct breakpoint;
struct command_line;
(struct type *type, const char *method_name,
std::vector<xmethod_worker_up> *workers);
+/* Try to colorize some source code. FILENAME is the name of the file
+ holding the code. CONTENTS is the source code itself. This will
+ either a colorized (using ANSI terminal escapes) version of the
+ source code, or an empty value if colorizing could not be done. */
+
+extern gdb::optional<std::string> ext_lang_colorize
+ (const std::string &filename, const std::string &contents);
+
#endif /* EXTENSION_H */
"""find_pc_line (pc) -> Symtab_and_line.
Return the gdb.Symtab_and_line object corresponding to the pc value."""
return current_progspace().find_pc_line(pc)
+
+try:
+ from pygments import formatters, lexers, highlight
+ def colorize(filename, contents):
+ # Don't want any errors.
+ try:
+ lexer = lexers.get_lexer_for_filename(filename)
+ formatter = formatters.TerminalFormatter()
+ return highlight(contents, lexer, formatter)
+ except:
+ return None
+except:
+ def colorize(filename, contents):
+ return None
static int gdbpy_check_quit_flag (const struct extension_language_defn *);
static enum ext_lang_rc gdbpy_before_prompt_hook
(const struct extension_language_defn *, const char *current_gdb_prompt);
+static gdb::optional<std::string> gdbpy_colorize
+ (const std::string &filename, const std::string &contents);
/* The interface between gdb proper and loading of python scripts. */
gdbpy_before_prompt_hook,
gdbpy_get_matching_xmethod_workers,
+
+ gdbpy_colorize,
};
/* Architecture and language to be used in callbacks from
return EXT_LANG_RC_NOP;
}
+/* This is the extension_language_ops.colorize "method". */
+
+static gdb::optional<std::string>
+gdbpy_colorize (const std::string &filename, const std::string &contents)
+{
+ if (!gdb_python_initialized)
+ return {};
+
+ gdbpy_enter enter_py (get_current_arch (), current_language);
+
+ if (gdb_python_module == nullptr
+ || !PyObject_HasAttrString (gdb_python_module, "colorize"))
+ return {};
+
+ gdbpy_ref<> hook (PyObject_GetAttrString (gdb_python_module, "colorize"));
+ if (hook == nullptr)
+ {
+ gdbpy_print_stack ();
+ return {};
+ }
+
+ if (!PyCallable_Check (hook.get ()))
+ return {};
+
+ gdbpy_ref<> fname_arg (PyString_FromString (filename.c_str ()));
+ if (fname_arg == nullptr)
+ {
+ gdbpy_print_stack ();
+ return {};
+ }
+ gdbpy_ref<> contents_arg (PyString_FromString (contents.c_str ()));
+ if (contents_arg == nullptr)
+ {
+ gdbpy_print_stack ();
+ return {};
+ }
+
+ gdbpy_ref<> result (PyObject_CallFunctionObjArgs (hook.get (),
+ fname_arg.get (),
+ contents_arg.get (),
+ nullptr));
+ if (result == nullptr)
+ {
+ gdbpy_print_stack ();
+ return {};
+ }
+
+ if (!gdbpy_is_string (result.get ()))
+ return {};
+
+ gdbpy_ref<> unic = python_string_to_unicode (result.get ());
+ if (unic == nullptr)
+ {
+ gdbpy_print_stack ();
+ return {};
+ }
+ gdbpy_ref<> host_str (PyUnicode_AsEncodedString (unic.get (),
+ host_charset (),
+ nullptr));
+ if (host_str == nullptr)
+ {
+ gdbpy_print_stack ();
+ return {};
+ }
+
+ return std::string (PyBytes_AsString (host_str.get ()));
+}
+
\f
/* Printing. */
std::string contents = get_plain_source_lines (s, fullname);
-#ifdef HAVE_SOURCE_HIGHLIGHT
if (source_styling && gdb_stdout->can_emit_style_escape ())
{
+#ifdef HAVE_SOURCE_HIGHLIGHT
+ bool already_styled = false;
const char *lang_name = get_language_name (SYMTAB_LANGUAGE (s));
if (lang_name != nullptr)
{
std::ostringstream output;
highlighter->highlight (input, output, lang_name, fullname);
contents = output.str ();
+ already_styled = true;
}
catch (...)
{
un-highlighted text. */
}
}
- }
+
+ if (!already_styled)
#endif /* HAVE_SOURCE_HIGHLIGHT */
+ {
+ gdb::optional<std::string> ext_contents;
+ ext_contents = ext_lang_colorize (fullname, contents);
+ if (ext_contents.has_value ())
+ contents = std::move (*ext_contents);
+ }
+ }
source_text result = { std::move (fullname), std::move (contents) };
m_source_map.push_back (std::move (result));