aboutsummaryrefslogtreecommitdiff
path: root/gdb/cli
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/cli')
-rw-r--r--gdb/cli/cli-cmds.c6
-rw-r--r--gdb/cli/cli-decode.c174
-rw-r--r--gdb/cli/cli-decode.h21
-rw-r--r--gdb/cli/cli-option.c42
-rw-r--r--gdb/cli/cli-option.h21
-rw-r--r--gdb/cli/cli-setshow.c21
-rw-r--r--gdb/cli/cli-style.c49
-rw-r--r--gdb/cli/cli-style.h4
8 files changed, 296 insertions, 42 deletions
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index 0140c71..69a7e8b 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -2398,6 +2398,11 @@ value_from_setting (const setting &var, struct gdbarch *gdbarch)
return current_language->value_string (gdbarch, value, len);
}
+ case var_color:
+ {
+ std::string s = var.get<ui_file_style::color> ().to_string ();
+ return current_language->value_string (gdbarch, s.c_str (), s.size ());
+ }
default:
gdb_assert_not_reached ("bad var_type");
}
@@ -2445,6 +2450,7 @@ str_value_from_setting (const setting &var, struct gdbarch *gdbarch)
case var_pinteger:
case var_boolean:
case var_auto_boolean:
+ case var_color:
{
std::string cmd_val = get_setshow_command_value_string (var);
diff --git a/gdb/cli/cli-decode.c b/gdb/cli/cli-decode.c
index 4fbbfcb..2c52922 100644
--- a/gdb/cli/cli-decode.c
+++ b/gdb/cli/cli-decode.c
@@ -23,6 +23,7 @@
#include "cli/cli-cmds.h"
#include "cli/cli-decode.h"
#include "cli/cli-style.h"
+#include "cli/cli-utils.h"
#include <optional>
/* Prototypes for local functions. */
@@ -740,6 +741,87 @@ add_setshow_enum_cmd (const char *name, command_class theclass,
}
/* See cli-decode.h. */
+
+void
+complete_on_color (completion_tracker &tracker,
+ const char *text, const char *word)
+{
+ complete_on_enum (tracker, ui_file_style::basic_color_enums.data (),
+ text, word);
+ if (*text == '\0')
+ {
+ /* Convenience to let the user know what the option
+ can accept. Note there's no common prefix between
+ the strings on purpose, so that complete_on_enum doesn't do
+ a partial match. */
+ tracker.add_completion (make_unique_xstrdup ("NUMBER"));
+ tracker.add_completion (make_unique_xstrdup ("#RRGGBB"));
+ }
+}
+
+/* Completer used in color commands. */
+
+static void
+color_completer (struct cmd_list_element *ignore,
+ completion_tracker &tracker,
+ const char *text, const char *word)
+{
+ complete_on_color (tracker, text, word);
+}
+
+
+/* Add element named NAME to command list LIST (the list for set or
+ some sublist thereof). CLASS is as in add_cmd. VAR is address
+ of the variable which will contain the color. */
+
+set_show_commands
+add_setshow_color_cmd (const char *name,
+ enum command_class theclass,
+ ui_file_style::color *var,
+ const char *set_doc,
+ const char *show_doc,
+ const char *help_doc,
+ cmd_func_ftype *set_func,
+ show_value_ftype *show_func,
+ struct cmd_list_element **set_list,
+ struct cmd_list_element **show_list)
+{
+ set_show_commands commands = add_setshow_cmd_full<ui_file_style::color>
+ (name, theclass, var_color, var,
+ set_doc, show_doc, help_doc,
+ nullptr, nullptr, set_func, show_func,
+ set_list, show_list);
+
+ set_cmd_completer (commands.set, color_completer);
+
+ return commands;
+}
+
+/* Same as above but using a getter and a setter function instead of a pointer
+ to a global storage buffer. */
+
+set_show_commands
+add_setshow_color_cmd (const char *name, command_class theclass,
+ const char *set_doc, const char *show_doc,
+ const char *help_doc,
+ setting_func_types<ui_file_style::color>::set set_func,
+ setting_func_types<ui_file_style::color>::get get_func,
+ show_value_ftype *show_func,
+ cmd_list_element **set_list,
+ cmd_list_element **show_list)
+{
+ auto cmds = add_setshow_cmd_full<ui_file_style::color>
+ (name, theclass, var_color, nullptr,
+ set_doc, show_doc, help_doc,
+ set_func, get_func, nullptr, show_func,
+ set_list, show_list);
+
+ set_cmd_completer (cmds.set, color_completer);
+
+ return cmds;
+}
+
+/* See cli-decode.h. */
const char * const auto_boolean_enums[] = { "on", "off", "auto", NULL };
/* Add an auto-boolean command named NAME to both the set and show
@@ -2756,3 +2838,95 @@ cli_user_command_p (struct cmd_list_element *cmd)
{
return cmd->theclass == class_user && cmd->func == do_simple_func;
}
+
+/* See cli-decode.h. */
+
+ui_file_style::color
+parse_cli_var_color (const char **args)
+{
+ /* Do a "set" command. ARG is nullptr if no argument, or the
+ text of the argument. */
+
+ if (args == nullptr || *args == nullptr || **args == '\0')
+ {
+ std::string msg;
+
+ for (size_t i = 0; ui_file_style::basic_color_enums[i]; ++i)
+ {
+ msg.append ("\"");
+ msg.append (ui_file_style::basic_color_enums[i]);
+ msg.append ("\", ");
+ }
+
+ error (_("Requires an argument. Valid arguments are %sinteger from -1 "
+ "to 255 or an RGB hex triplet in a format #RRGGBB"),
+ msg.c_str ());
+ }
+
+ const char *p = skip_to_space (*args);
+ size_t len = p - *args;
+
+ int nmatches = 0;
+ ui_file_style::basic_color match = ui_file_style::NONE;
+ for (int i = 0; ui_file_style::basic_color_enums[i]; ++i)
+ if (strncmp (*args, ui_file_style::basic_color_enums[i], len) == 0)
+ {
+ match = static_cast<ui_file_style::basic_color> (i - 1);
+ if (ui_file_style::basic_color_enums[i][len] == '\0')
+ {
+ nmatches = 1;
+ break; /* Exact match. */
+ }
+ else
+ nmatches++;
+ }
+
+ if (nmatches == 1)
+ {
+ *args += len;
+ return ui_file_style::color (match);
+ }
+
+ if (nmatches > 1)
+ error (_("Ambiguous item \"%.*s\"."), (int) len, *args);
+
+ if (**args != '#')
+ {
+ ULONGEST num = get_ulongest (args);
+ if (num > 255)
+ error (_("integer %s out of range"), pulongest (num));
+ return ui_file_style::color (color_space::XTERM_256COLOR,
+ static_cast<int> (num));
+ }
+
+ /* Try to parse #RRGGBB string. */
+ if (len != 7)
+ error_no_arg (_("invalid RGB hex triplet format"));
+
+ uint8_t r, g, b;
+ int scanned_chars = 0;
+ int parsed_args = sscanf (*args, "#%2" SCNx8 "%2" SCNx8 "%2" SCNx8 "%n",
+ &r, &g, &b, &scanned_chars);
+
+ if (parsed_args != 3 || scanned_chars != 7)
+ error_no_arg (_("invalid RGB hex triplet format"));
+
+ *args += len;
+ return ui_file_style::color (r, g, b);
+}
+
+/* See cli-decode.h. */
+
+ui_file_style::color
+parse_var_color (const char *arg)
+{
+ const char *end_arg = arg;
+ ui_file_style::color color = parse_cli_var_color (&end_arg);
+
+ int len = end_arg - arg;
+ const char *after = skip_spaces (end_arg);
+ if (*after != '\0')
+ error (_("Junk after item \"%.*s\": %s"), len, arg, after);
+
+ return color;
+}
diff --git a/gdb/cli/cli-decode.h b/gdb/cli/cli-decode.h
index ec73c11..18ea05d 100644
--- a/gdb/cli/cli-decode.h
+++ b/gdb/cli/cli-decode.h
@@ -309,6 +309,27 @@ extern const char * const boolean_enums[];
/* The enums of auto-boolean commands. */
extern const char * const auto_boolean_enums[];
+/* Add the different possible completions of TEXT with color.
+
+ WORD points in the same buffer as TEXT, and completions should be
+ returned relative to this position. For example, suppose TEXT is "foo"
+ and we want to complete to "foobar". If WORD is "oo", return
+ "oobar"; if WORD is "baz/foo", return "baz/foobar". */
+
+extern void complete_on_color (completion_tracker &tracker,
+ const char *text, const char *word);
+
+/* Parse ARGS, an option to a var_color variable.
+ *
+ Either returns the parsed value on success or throws an error. ARGS may be
+ one of strings {none, black, red, green, yellow, blue, magenta,
+ cyan, white}, or color number from 0 to 255, or RGB hex triplet #RRGGBB.
+ */
+extern ui_file_style::color parse_cli_var_color (const char **args);
+
+/* Same as above but additionally check that there is no junk in the end. */
+extern ui_file_style::color parse_var_color (const char *arg);
+
/* Verify whether a given cmd_list_element is a user-defined command.
Return 1 if it is user-defined. Return 0 otherwise. */
diff --git a/gdb/cli/cli-option.c b/gdb/cli/cli-option.c
index fa00b91..10a5944 100644
--- a/gdb/cli/cli-option.c
+++ b/gdb/cli/cli-option.c
@@ -45,6 +45,9 @@ union option_value
/* For var_string and var_filename options. This is allocated with new. */
std::string *string;
+
+ /* For var_color options. */
+ ui_file_style::color color = ui_file_style::NONE;
};
/* Holds an options definition and its value. */
@@ -433,6 +436,35 @@ parse_option (gdb::array_view<const option_def_group> options_group,
val.enumeration = parse_cli_var_enum (args, match->enums);
return option_def_and_value {*match, match_ctx, val};
}
+ case var_color:
+ {
+ if (completion != nullptr)
+ {
+ const char *after_arg = skip_to_space (*args);
+ if (*after_arg == '\0')
+ {
+ complete_on_color (completion->tracker, *args, *args);
+
+ if (completion->tracker.have_completions ())
+ return {};
+ }
+ }
+
+ if (check_for_argument (args, "--"))
+ {
+ /* Treat e.g., "backtrace -entry-values --" as if there
+ was no argument after "-entry-values". This makes
+ parse_cli_var_color throw an error with a suggestion of
+ what are the valid options. */
+ args = nullptr;
+ }
+
+ option_value val;
+ ui_file_style::color color = parse_cli_var_color (args);
+ ui_file_style::color approx_color = color.approximate (colorsupport ());
+ val.color = approx_color;
+ return option_def_and_value {*match, match_ctx, val};
+ }
case var_string:
{
if (check_for_argument (args, "--"))
@@ -683,6 +715,10 @@ save_option_value_in_ctx (std::optional<option_def_and_value> &ov)
*ov->option.var_address.enumeration (ov->option, ov->ctx)
= ov->value->enumeration;
break;
+ case var_color:
+ *ov->option.var_address.color (ov->option, ov->ctx)
+ = ov->value->color;
+ break;
case var_string:
case var_filename:
*ov->option.var_address.string (ov->option, ov->ctx)
@@ -789,6 +825,12 @@ append_val_type_str (std::string &help, const option_def &opt,
}
}
break;
+ case var_color:
+ help += ' ';
+ for (size_t i = 0; ui_file_style::basic_color_enums[i]; ++i)
+ help.append (ui_file_style::basic_color_enums[i]).append ("|");
+ help += "NUMBER|#RRGGBB";
+ break;
case var_string:
help += "STRING";
break;
diff --git a/gdb/cli/cli-option.h b/gdb/cli/cli-option.h
index dd3db8b..ac614c3 100644
--- a/gdb/cli/cli-option.h
+++ b/gdb/cli/cli-option.h
@@ -91,6 +91,7 @@ public:
int *(*integer) (const option_def &, void *ctx);
const char **(*enumeration) (const option_def &, void *ctx);
std::string *(*string) (const option_def &, void *ctx);
+ ui_file_style::color *(*color) (const option_def &, void *ctx);
}
var_address;
@@ -328,6 +329,26 @@ struct filename_option_def : option_def
}
};
+/* A var_color command line option. */
+
+template<typename Context>
+struct color_option_def : option_def
+{
+ color_option_def (const char *long_option_,
+ ui_file_style::color *(*get_var_address_cb_) (Context *),
+ show_value_ftype *show_cmd_cb_,
+ const char *set_doc_,
+ const char *show_doc_ = nullptr,
+ const char *help_doc_ = nullptr)
+ : option_def (long_option_, var_color,
+ (erased_get_var_address_ftype *) get_var_address_cb_,
+ show_cmd_cb_,
+ set_doc_, show_doc_, help_doc_)
+ {
+ var_address.color = detail::get_var_address<ui_file_style::color, Context>;
+ }
+};
+
/* A group of options that all share the same context pointer to pass
to the options' get-current-value callbacks. */
struct option_def_group
diff --git a/gdb/cli/cli-setshow.c b/gdb/cli/cli-setshow.c
index bcc793b..a8f22c9 100644
--- a/gdb/cli/cli-setshow.c
+++ b/gdb/cli/cli-setshow.c
@@ -443,6 +443,13 @@ do_set_command (const char *arg, int from_tty, struct cmd_list_element *c)
option_changed = c->var->set<const char *> (match);
}
break;
+ case var_color:
+ {
+ ui_file_style::color color = parse_var_color (arg);
+ ui_file_style::color approx_color = color.approximate (colorsupport ());
+ option_changed = c->var->set<ui_file_style::color> (approx_color);
+ }
+ break;
default:
error (_("gdb internal error: bad var_type in do_setshow_command"));
}
@@ -520,6 +527,14 @@ do_set_command (const char *arg, int from_tty, struct cmd_list_element *c)
interps_notify_param_changed
(name, c->var->get<const char *> ());
break;
+ case var_color:
+ {
+ const ui_file_style::color &color
+ = c->var->get<ui_file_style::color> ();
+ interps_notify_param_changed
+ (name, color.to_string ().c_str ());
+ }
+ break;
case var_boolean:
{
const char *opt = c->var->get<bool> () ? "on" : "off";
@@ -585,6 +600,12 @@ get_setshow_command_value_string (const setting &var)
stb.puts (value);
}
break;
+ case var_color:
+ {
+ const ui_file_style::color &value = var.get<ui_file_style::color> ();
+ stb.puts (value.to_string ().c_str ());
+ }
+ break;
case var_boolean:
stb.puts (var.get<bool> () ? "on" : "off");
break;
diff --git a/gdb/cli/cli-style.c b/gdb/cli/cli-style.c
index fa582a7..4151082 100644
--- a/gdb/cli/cli-style.c
+++ b/gdb/cli/cli-style.c
@@ -42,20 +42,6 @@ bool source_styling = true;
bool disassembler_styling = true;
-/* Name of colors; must correspond to ui_file_style::basic_color. */
-static const char * const cli_colors[] = {
- "none",
- "black",
- "red",
- "green",
- "yellow",
- "blue",
- "magenta",
- "cyan",
- "white",
- nullptr
-};
-
/* Names of intensities; must correspond to
ui_file_style::intensity. */
static const char * const cli_intensities[] = {
@@ -139,8 +125,8 @@ cli_style_option::cli_style_option (const char *name,
ui_file_style::intensity intensity)
: changed (name),
m_name (name),
- m_foreground (cli_colors[fg - ui_file_style::NONE]),
- m_background (cli_colors[0]),
+ m_foreground (fg),
+ m_background (ui_file_style::NONE),
m_intensity (cli_intensities[intensity])
{
}
@@ -151,32 +137,17 @@ cli_style_option::cli_style_option (const char *name,
ui_file_style::intensity i)
: changed (name),
m_name (name),
- m_foreground (cli_colors[0]),
- m_background (cli_colors[0]),
+ m_foreground (ui_file_style::NONE),
+ m_background (ui_file_style::NONE),
m_intensity (cli_intensities[i])
{
}
-/* Return the color number corresponding to COLOR. */
-
-static int
-color_number (const char *color)
-{
- for (int i = 0; i < ARRAY_SIZE (cli_colors); ++i)
- {
- if (color == cli_colors[i])
- return i - 1;
- }
- gdb_assert_not_reached ("color not found");
-}
-
/* See cli-style.h. */
ui_file_style
cli_style_option::style () const
{
- int fg = color_number (m_foreground);
- int bg = color_number (m_background);
ui_file_style::intensity intensity = ui_file_style::NORMAL;
for (int i = 0; i < ARRAY_SIZE (cli_intensities); ++i)
@@ -188,7 +159,7 @@ cli_style_option::style () const
}
}
- return ui_file_style (fg, bg, intensity);
+ return ui_file_style (m_foreground, m_background, intensity);
}
/* See cli-style.h. */
@@ -261,9 +232,8 @@ cli_style_option::add_setshow_commands (enum command_class theclass,
set_show_commands commands;
- commands = add_setshow_enum_cmd
- ("foreground", theclass, cli_colors,
- &m_foreground,
+ commands = add_setshow_color_cmd
+ ("foreground", theclass, &m_foreground,
_("Set the foreground color for this property."),
_("Show the foreground color for this property."),
nullptr,
@@ -273,9 +243,8 @@ cli_style_option::add_setshow_commands (enum command_class theclass,
commands.set->set_context (this);
commands.show->set_context (this);
- commands = add_setshow_enum_cmd
- ("background", theclass, cli_colors,
- &m_background,
+ commands = add_setshow_color_cmd
+ ("background", theclass, &m_background,
_("Set the background color for this property."),
_("Show the background color for this property."),
nullptr,
diff --git a/gdb/cli/cli-style.h b/gdb/cli/cli-style.h
index 171ec71..a1e538b 100644
--- a/gdb/cli/cli-style.h
+++ b/gdb/cli/cli-style.h
@@ -67,9 +67,9 @@ private:
const char *m_name;
/* The foreground. */
- const char *m_foreground;
+ ui_file_style::color m_foreground;
/* The background. */
- const char *m_background;
+ ui_file_style::color m_background;
/* The intensity. */
const char *m_intensity;