public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 02/16] Add a "context" argument to add_setshow_enum_cmd
  2018-11-28  0:16 [PATCH 00/16] Add styling to the gdb CLI and TUI Tom Tromey
                   ` (4 preceding siblings ...)
  2018-11-28  0:14 ` [PATCH 09/16] Style print_address_symbolic Tom Tromey
@ 2018-11-28  0:14 ` Tom Tromey
  2018-11-28  0:14 ` [PATCH 05/16] Add output styles to gdb Tom Tromey
                   ` (11 subsequent siblings)
  17 siblings, 0 replies; 99+ messages in thread
From: Tom Tromey @ 2018-11-28  0:14 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This adds a "context" argument to add_setshow_enum_cmd.  Now
add_setshow_enum_cmd will call set_cmd_context on both of the new
commands.  This is used in a later patch.

gdb/ChangeLog
2018-11-27  Tom Tromey  <tom@tromey.com>

	* command.h (add_setshow_enum_cmd): Add "context" argument.
	* cli/cli-decode.c (add_setshow_enum_cmd): Add "context"
	argument.  Call set_cmd_context.
---
 gdb/ChangeLog        |  6 ++++++
 gdb/cli/cli-decode.c | 10 +++++++---
 gdb/command.h        |  3 ++-
 3 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/gdb/cli/cli-decode.c b/gdb/cli/cli-decode.c
index 5d798e877e..e7b7a110fc 100644
--- a/gdb/cli/cli-decode.c
+++ b/gdb/cli/cli-decode.c
@@ -531,16 +531,20 @@ add_setshow_enum_cmd (const char *name,
 		      cmd_const_sfunc_ftype *set_func,
 		      show_value_ftype *show_func,
 		      struct cmd_list_element **set_list,
-		      struct cmd_list_element **show_list)
+		      struct cmd_list_element **show_list,
+		      void *context)
 {
-  struct cmd_list_element *c;
+  struct cmd_list_element *c, *show;
 
   add_setshow_cmd_full (name, theclass, var_enum, var,
 			set_doc, show_doc, help_doc,
 			set_func, show_func,
 			set_list, show_list,
-			&c, NULL);
+			&c, &show);
   c->enums = enumlist;
+
+  set_cmd_context (c, context);
+  set_cmd_context (show, context);
 }
 
 const char * const auto_boolean_enums[] = { "on", "off", "auto", NULL };
diff --git a/gdb/command.h b/gdb/command.h
index e3d55c2dcb..68514409ec 100644
--- a/gdb/command.h
+++ b/gdb/command.h
@@ -314,7 +314,8 @@ extern void add_setshow_enum_cmd (const char *name,
 				  cmd_const_sfunc_ftype *set_func,
 				  show_value_ftype *show_func,
 				  struct cmd_list_element **set_list,
-				  struct cmd_list_element **show_list);
+				  struct cmd_list_element **show_list,
+				  void *context = nullptr);
 
 extern void add_setshow_auto_boolean_cmd (const char *name,
 					  enum command_class theclass,
-- 
2.17.2

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 03/16] Introduce ui_file_style
  2018-11-28  0:16 [PATCH 00/16] Add styling to the gdb CLI and TUI Tom Tromey
  2018-11-28  0:14 ` [PATCH 06/16] Reset terminal styles Tom Tromey
  2018-11-28  0:14 ` [PATCH 10/16] Style the gdb welcome message Tom Tromey
@ 2018-11-28  0:14 ` Tom Tromey
  2018-12-24  3:40   ` Joel Brobecker
  2018-11-28  0:14 ` [PATCH 14/16] Use wclrtoeol in tui_show_source_line Tom Tromey
                   ` (14 subsequent siblings)
  17 siblings, 1 reply; 99+ messages in thread
From: Tom Tromey @ 2018-11-28  0:14 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This introduces the new ui_file_style class and various helpers.  This
class represents a terminal style and provides methods for parsing and
emitting the corresponding ANSI terminal escape sequences.

gdb/ChangeLog
2018-11-27  Tom Tromey  <tom@tromey.com>

	* unittests/style-selftests.c: New file.
	* ui-style.c: New file.
	* ui-style.h: New file.
	* ui-file.h: Include ui-style.h.
	* Makefile.in (COMMON_SFILES): Add ui-style.c.
	(HFILES_NO_SRCDIR): Add ui-style.h.
	(SUBDIR_UNITTESTS_SRCS): Add style-selftests.c.
---
 gdb/ChangeLog                   |  10 +
 gdb/Makefile.in                 |   3 +
 gdb/ui-file.h                   |   1 +
 gdb/ui-style.c                  | 412 ++++++++++++++++++++++++++++++++
 gdb/ui-style.h                  | 215 +++++++++++++++++
 gdb/unittests/style-selftests.c | 109 +++++++++
 6 files changed, 750 insertions(+)
 create mode 100644 gdb/ui-style.c
 create mode 100644 gdb/ui-style.h
 create mode 100644 gdb/unittests/style-selftests.c

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 3be058f052..ce0d799b7d 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -426,6 +426,7 @@ SUBDIR_UNITTESTS_SRCS = \
 	unittests/scoped_mmap-selftests.c \
 	unittests/scoped_restore-selftests.c \
 	unittests/string_view-selftests.c \
+	unittests/style-selftests.c \
 	unittests/tracepoint-selftests.c \
 	unittests/unpack-selftests.c \
 	unittests/utils-selftests.c \
@@ -1124,6 +1125,7 @@ COMMON_SFILES = \
 	typeprint.c \
 	ui-file.c \
 	ui-out.c \
+	ui-style.c \
 	user-regs.c \
 	utils.c \
 	valarith.c \
@@ -1397,6 +1399,7 @@ HFILES_NO_SRCDIR = \
 	typeprint.h \
 	ui-file.h \
 	ui-out.h \
+	ui-style.h \
 	user-regs.h \
 	utils.h \
 	valprint.h \
diff --git a/gdb/ui-file.h b/gdb/ui-file.h
index 2cf5f83d47..b780dff4d5 100644
--- a/gdb/ui-file.h
+++ b/gdb/ui-file.h
@@ -20,6 +20,7 @@
 #define UI_FILE_H
 
 #include <string>
+#include "ui-style.h"
 
 /* The abstract ui_file base class.  */
 
diff --git a/gdb/ui-style.c b/gdb/ui-style.c
new file mode 100644
index 0000000000..a6e102e7b2
--- /dev/null
+++ b/gdb/ui-style.c
@@ -0,0 +1,412 @@
+/* Styling for ui_file
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "ui-style.h"
+
+/* A regular expression that is used for matching ANSI terminal escape
+   sequences.  */
+
+static const char *ansi_regex_text =
+  /* Introduction.  */
+  "^\033\\["
+#define DATA_SUBEXP 1
+  /* Capture parameter and intermediate bytes.  */
+  "("
+  /* Parameter bytes.  */
+  "[\x30-\x3f]*"
+  /* Intermediate bytes.  */
+  "[\x20-\x2f]*"
+  /* End the first capture.  */
+  ")"
+  /* The final byte.  */
+#define FINAL_SUBEXP 2
+  "([\x40-\x7e])";
+
+/* The number of subexpressions to allocate space for, including the
+   "0th" whole match subexpression.  */
+#define NUM_SUBEXPRESSIONS 3
+
+/* The compiled form of ansi_regex_text.  */
+
+static regex_t ansi_regex;
+
+/* This maps bright colors to RGB triples.  The index is the bright
+   color index, starting with bright black.  The values come from
+   xterm.  */
+
+static const uint8_t bright_colors[][3] = {
+  { 127, 127, 127 },		/* Black.  */
+  { 255, 0, 0 },		/* Red.  */
+  { 0, 255, 0 },		/* Green.  */
+  { 255, 255, 0 },		/* Yellow.  */
+  { 92, 92, 255 },		/* Blue.  */
+  { 255, 0, 255 },		/* Magenta.  */
+  { 0, 255, 255 },		/* Cyan.  */
+  { 255, 255, 255 }		/* White.  */
+};
+
+/* See ui-style.h.  */
+
+bool
+ui_file_style::color::append_ansi (bool is_fg, std::string *str) const
+{
+  if (m_simple)
+    {
+      if (m_value >= BLACK && m_value <= WHITE)
+	str->append (std::to_string (m_value + (is_fg ? 30 : 40)));
+      else if (m_value > WHITE && m_value <= WHITE + 8)
+	str->append (std::to_string (m_value - WHITE + (is_fg ? 90 : 100)));
+      else if (m_value != -1)
+	{
+	  str->append (is_fg ? "38;5;" : "48;5;");
+	  str->append (std::to_string (m_value));
+	}
+      else
+	return false;
+    }
+  else
+    {
+      str->append (is_fg ? "38;2;" : "48;2;");
+      str->append (std::to_string (m_red)
+		   + ";" + std::to_string (m_green)
+		   + ";" + std::to_string (m_blue));
+    }
+  return true;
+}
+
+/* See ui-style.h.  */
+
+void
+ui_file_style::color::get_rgb (uint8_t *rgb) const
+{
+  if (m_simple)
+    {
+      /* Can't call this for a basic color.  */
+      if (m_value >= 8 && m_value <= 15)
+	memcpy (rgb, bright_colors[m_value - 8], 3 * sizeof (uint8_t));
+      else if (m_value >= 16 && m_value <= 231)
+	{
+	  int value = m_value;
+	  value -= 16;
+	  /* This obscure formula seems to be what terminals actually
+	     do.  */
+	  int component = value / 36;
+	  rgb[0] = component == 0 ? 0 : (55 + component * 40);
+	  value %= 36;
+	  component = value / 6;
+	  rgb[1] = component == 0 ? 0 : (55 + component * 40);
+	  value %= 6;
+	  rgb[2] = value == 0 ? 0 : (55 + value * 40);
+	}
+      else if (m_value >= 232)
+	{
+	  uint8_t v = (m_value - 232) * 10 + 8;
+	  rgb[0] = v;
+	  rgb[1] = v;
+	  rgb[2] = v;
+	}
+      else
+	gdb_assert_not_reached ("get_rgb called on invalid color");
+    }
+  else
+    {
+      rgb[0] = m_red;
+      rgb[1] = m_green;
+      rgb[2] = m_blue;
+    }
+}
+
+/* See ui-style.h.  */
+
+std::string
+ui_file_style::to_ansi () const
+{
+  std::string result ("\033[");
+  bool need_semi = m_foreground.append_ansi (true, &result);
+  if (!m_background.is_none ())
+    {
+      if (need_semi)
+	result.push_back (';');
+      m_background.append_ansi (false, &result);
+      need_semi = true;
+    }
+  if (m_intensity != NORMAL)
+    {
+      if (need_semi)
+	result.push_back (';');
+      result.append (std::to_string (m_intensity));
+      need_semi = true;
+    }
+  if (m_reverse)
+    {
+      if (need_semi)
+	result.push_back (';');
+      result.push_back ('7');
+    }
+  result.push_back ('m');
+  return result;
+}
+
+/* Read a ";" and a number from STRING.  Return the number of
+   characters read and put the number into *NUM.  */
+
+static bool
+read_semi_number (const char *string, int *idx, long *num)
+{
+  if (string[*idx] != ';')
+    return false;
+  ++*idx;
+  if (string[*idx] < '0' || string[*idx] > '9')
+    return false;
+  char *tail;
+  *num = strtol (string + *idx, &tail, 10);
+  *idx = tail - string;
+  return true;
+}
+
+/* A helper for ui_file_style::parse that reads an extended color
+   sequence; that is, and 8- or 24- bit color.  */
+
+static bool
+extended_color (const char *str, int *idx, ui_file_style::color *color)
+{
+  long value;
+
+  if (!read_semi_number (str, idx, &value))
+    return false;
+
+  if (value == 5)
+    {
+      /* 8-bit color.  */
+      if (!read_semi_number (str, idx, &value))
+	return false;
+
+      if (value >= 0 && value <= 255)
+	*color = ui_file_style::color (value);
+      else
+	return false;
+    }
+  else if (value == 2)
+    {
+      /* 24-bit color.  */
+      long r, g, b;
+      if (!read_semi_number (str, idx, &r)
+	  || r > 255
+	  || !read_semi_number (str, idx, &g)
+	  || g > 255
+	  || !read_semi_number (str, idx, &b)
+	  || b > 255)
+	return false;
+      *color = ui_file_style::color (r, g, b);
+    }
+  else
+    {
+      /* Unrecognized sequence.  */
+      return false;
+    }
+
+  return true;
+}
+
+/* See ui-style.h.  */
+
+bool
+ui_file_style::parse (const char *buf, size_t *n_read)
+{
+  regmatch_t subexps[NUM_SUBEXPRESSIONS];
+
+  int match = regexec (&ansi_regex, buf, ARRAY_SIZE (subexps), subexps, 0);
+  if (match == REG_NOMATCH)
+    {
+      *n_read = 0;
+      return false;
+    }
+  /* Other failures mean the regexp is broken.  */
+  gdb_assert (match == 0);
+  /* The regexp is anchored.  */
+  gdb_assert (subexps[0].rm_so == 0);
+  /* The final character exists.  */
+  gdb_assert (subexps[FINAL_SUBEXP].rm_eo - subexps[FINAL_SUBEXP].rm_so == 1);
+
+  if (buf[subexps[FINAL_SUBEXP].rm_so] != 'm')
+    {
+      /* We don't handle this sequence, so just drop it.  */
+      *n_read = subexps[0].rm_eo;
+      return false;
+    }
+
+  /* Examine each setting in the match and apply it to the result.
+     See the Select Graphic Rendition section of
+     https://en.wikipedia.org/wiki/ANSI_escape_code.  In essence each
+     code is just a number, separated by ";"; there are some more
+     wrinkles but we don't support them all..  */
+
+  /* "\033[m" means the same thing as "\033[0m", so handle that
+     specially here.  */
+  if (subexps[DATA_SUBEXP].rm_so == subexps[DATA_SUBEXP].rm_eo)
+    *this = ui_file_style ();
+
+  for (regoff_t i = subexps[DATA_SUBEXP].rm_so;
+       i < subexps[DATA_SUBEXP].rm_eo;
+       ++i)
+    {
+      if (buf[i] == ';')
+	{
+	  /* Skip.  */
+	}
+      else if (buf[i] >= '0' && buf[i] <= '9')
+	{
+	  char *tail;
+	  long value = strtol (buf + i, &tail, 10);
+	  i = tail - buf;
+
+	  switch (value)
+	    {
+	    case 0:
+	      /* Reset.  */
+	      *this = ui_file_style ();
+	      break;
+	    case 1:
+	      /* Bold.  */
+	      m_intensity = BOLD;
+	      break;
+	    case 2:
+	      /* Dim.  */
+	      m_intensity = DIM;
+	      break;
+	    case 7:
+	      /* Reverse.  */
+	      m_reverse = true;
+	      break;
+	    case 21:
+	      m_intensity = NORMAL;
+	      break;
+	    case 22:
+	      /* Normal.  */
+	      m_intensity = NORMAL;
+	      break;
+	    case 27:
+	      /* Inverse off.  */
+	      m_reverse = false;
+	      break;
+
+	    case 30:
+	    case 31:
+	    case 32:
+	    case 33:
+	    case 34:
+	    case 35:
+	    case 36:
+	    case 37:
+	      /* Note: not 38.  */
+	    case 39:
+	      m_foreground = color (value - 30);
+	      break;
+
+	    case 40:
+	    case 41:
+	    case 42:
+	    case 43:
+	    case 44:
+	    case 45:
+	    case 46:
+	    case 47:
+	      /* Note: not 48.  */
+	    case 49:
+	      m_background = color (value - 40);
+	      break;
+
+	    case 90:
+	    case 91:
+	    case 92:
+	    case 93:
+	    case 94:
+	    case 95:
+	    case 96:
+	    case 97:
+	      m_foreground = color (value - 90 + 8);
+	      break;
+
+	    case 100:
+	    case 101:
+	    case 102:
+	    case 103:
+	    case 104:
+	    case 105:
+	    case 106:
+	    case 107:
+	      m_background = color (value - 100 + 8);
+	      break;
+
+	    case 38:
+	      /* If we can't parse the extended color, fail.  */
+	      if (!extended_color (buf, &i, &m_foreground))
+		{
+		  *n_read = subexps[0].rm_eo;
+		  return false;
+		}
+	      break;
+
+	    case 48:
+	      /* If we can't parse the extended color, fail.  */
+	      if (!extended_color (buf, &i, &m_background))
+		{
+		  *n_read = subexps[0].rm_eo;
+		  return false;
+		}
+	      break;
+
+	    default:
+	      /* Ignore everything else.  */
+	      break;
+	    }
+	}
+      else
+	{
+	  /* Unknown, let's just ignore.  */
+	}
+    }
+
+  *n_read = subexps[0].rm_eo;
+  return true;
+}
+
+/* See ui-style.h.  */
+
+bool
+skip_ansi_escape (const char *buf, int *bytes)
+{
+  regmatch_t subexps[NUM_SUBEXPRESSIONS];
+
+  int match = regexec (&ansi_regex, buf, ARRAY_SIZE (subexps), subexps, 0);
+  if (match == REG_NOMATCH || buf[subexps[FINAL_SUBEXP].rm_so] != 'm')
+    return false;
+
+  *bytes = subexps[FINAL_SUBEXP].rm_eo;
+  return true;
+}
+
+void
+_initialize_ui_style ()
+{
+  int code = regcomp (&ansi_regex, ansi_regex_text, REG_EXTENDED);
+  /* If the regular expression was incorrect, it was a programming
+     error.  */
+  gdb_assert (code == 0);
+}
diff --git a/gdb/ui-style.h b/gdb/ui-style.h
new file mode 100644
index 0000000000..d08139cef2
--- /dev/null
+++ b/gdb/ui-style.h
@@ -0,0 +1,215 @@
+/* Styling for ui_file
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef UI_STYLE_H
+#define UI_STYLE_H
+
+/* Styles that can be applied to a ui_file.  */
+struct ui_file_style
+{
+  /* One of the simple colors that can be handled by ANSI
+     terminals.  */
+  enum simple_color
+  {
+    NONE = -1,
+    BLACK,
+    RED,
+    GREEN,
+    YELLOW,
+    BLUE,
+    MAGENTA,
+    CYAN,
+    WHITE
+  };
+
+  /* Representation of a terminal color.  */
+  class color
+  {
+  public:
+
+    color (simple_color c)
+      : m_simple (true),
+	m_value (c)
+    {
+    }
+
+    color (int c)
+      : m_simple (true),
+	m_value (c)
+    {
+      gdb_assert (c >= -1 && c <= 255);
+    }
+
+    color (uint8_t r, uint8_t g, uint8_t b)
+      : m_simple (false),
+	m_red (r),
+	m_green (g),
+	m_blue (b)
+    {
+    }
+
+    bool operator== (const color &other) const
+    {
+      if (m_simple != other.m_simple)
+	return false;
+      if (m_simple)
+	return m_value == other.m_value;
+      return (m_red == other.m_red && m_green == other.m_green
+	      && m_blue == other.m_blue);
+    }
+
+    bool operator< (const color &other) const
+    {
+      if (m_simple != other.m_simple)
+	return m_simple < other.m_simple;
+      if (m_simple)
+	return m_value < other.m_value;
+      if (m_red < other.m_red)
+	return true;
+      if (m_red == other.m_red)
+	{
+	  if (m_green < other.m_green)
+	    return true;
+	  if (m_green == other.m_green)
+	    return m_blue < other.m_blue;
+	}
+      return false;
+    }
+
+    /* Return true if this is the "NONE" color, false otherwise.  */
+    bool is_none () const
+    {
+      return m_simple && m_value == NONE;
+    }
+
+    /* Return true if this is one of the basic colors, false
+       otherwise.  */
+    bool is_basic () const
+    {
+      return m_simple && m_value >= BLACK && m_value <= WHITE;
+    }
+
+    /* Return the value of a basic color.  */
+    int get_value () const
+    {
+      gdb_assert (is_basic ());
+      return m_value;
+    }
+
+    /* Fill in RGB with the red/green/blue values for this color.
+       This may not be called for simple colors or for the "NONE"
+       color.  */
+    void get_rgb (uint8_t *rgb) const;
+
+    /* Append the ANSI terminal escape sequence for this color to STR.
+       IS_FG indicates whether this is a foreground or background
+       color.  Returns true if any characters were written; returns
+       false otherwise (which can only happen for the "NONE"
+       color).  */
+    bool append_ansi (bool is_fg, std::string *str) const;
+
+  private:
+
+    bool m_simple;
+    int m_value;
+    uint8_t m_red, m_green, m_blue;
+  };
+
+  /* Intensity settings that are available.  */
+  enum intensity
+  {
+    NORMAL = 0,
+    BOLD,
+    DIM
+  };
+
+  ui_file_style ()
+  {
+  }
+
+  ui_file_style (color f, color b, intensity i = NORMAL)
+    : m_foreground (f),
+      m_background (b),
+      m_intensity (i)
+  {
+  }
+
+  bool operator== (const ui_file_style &other) const
+  {
+    return (m_foreground == other.m_foreground
+	    && m_background == other.m_background
+	    && m_intensity == other.m_intensity
+	    && m_reverse == other.m_reverse);
+  }
+
+  bool operator!= (const ui_file_style &other) const
+  {
+    return !(*this == other);
+  }
+
+  /* Return the ANSI escape sequence for this style.  */
+  std::string to_ansi () const;
+
+  /* Return true if this style specified reverse display; false
+     otherwise.  */
+  bool is_reverse () const
+  {
+    return m_reverse;
+  }
+
+  /* Return the foreground color of this style.  */
+  const color &get_foreground () const
+  {
+    return m_foreground;
+  }
+
+  /* Return the background color of this style.  */
+  const color &get_background () const
+  {
+    return m_background;
+  }
+
+  /* Return the intensity of this style.  */
+  intensity get_intensity () const
+  {
+    return m_intensity;
+  }
+
+  /* Parse an ANSI escape sequence in BUF, modifying this style.  BUF
+     must begin with an ESC character.  Return true if an escape
+     sequence was successfully parsed; false otherwise.  In either
+     case, N_READ is updated to reflect the number of chars read from
+     BUF.  */
+  bool parse (const char *buf, size_t *n_read);
+
+private:
+
+  color m_foreground = NONE;
+  color m_background = NONE;
+  intensity m_intensity = NORMAL;
+  bool m_reverse = false;
+};
+
+/* Skip an ANSI escape sequence in BUF.  BUF must begin with an ESC
+   character.  Return true if an escape sequence was successfully
+   skipped; false otherwise.  In either case, N_READ is updated to
+   reflect the number of chars read from BUF.  */
+
+extern bool skip_ansi_escape (const char *buf, int *bytes);
+
+#endif /* UI_STYLE_H */
diff --git a/gdb/unittests/style-selftests.c b/gdb/unittests/style-selftests.c
new file mode 100644
index 0000000000..108ed6ccd2
--- /dev/null
+++ b/gdb/unittests/style-selftests.c
@@ -0,0 +1,109 @@
+/* Self tests for ui_file_style
+
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "selftest.h"
+#include "ui-style.h"
+
+namespace selftests {
+namespace style {
+
+#define CHECK_RGB(R, G, B) \
+  SELF_CHECK (rgb[0] == (R) && rgb[1] == (G) && rgb[2] == (B))
+
+static void
+run_tests ()
+{
+  ui_file_style style;
+  size_t n_read;
+  uint8_t rgb[3];
+
+  SELF_CHECK (style.parse ("\033[m", &n_read));
+  SELF_CHECK (n_read == 3);
+  SELF_CHECK (style.get_foreground ().is_none ());
+  SELF_CHECK (style.get_background ().is_none ());
+  SELF_CHECK (style.get_intensity () == ui_file_style::NORMAL);
+  SELF_CHECK (!style.is_reverse ());
+  SELF_CHECK (style.to_ansi () == "\033[m");
+
+  style = ui_file_style ();
+  SELF_CHECK (style.parse ("\033[0m", &n_read));
+  SELF_CHECK (n_read == 4);
+  SELF_CHECK (style.get_foreground ().is_none ());
+  SELF_CHECK (style.get_background ().is_none ());
+  SELF_CHECK (style.get_intensity () == ui_file_style::NORMAL);
+  SELF_CHECK (!style.is_reverse ());
+  /* This particular case does not round-trip identically, but the
+     difference is unimportant.  */
+  SELF_CHECK (style.to_ansi () == "\033[m");
+
+  SELF_CHECK (style.parse ("\033[7m", &n_read));
+  SELF_CHECK (n_read == 4);
+  SELF_CHECK (style.get_foreground ().is_none ());
+  SELF_CHECK (style.get_background ().is_none ());
+  SELF_CHECK (style.get_intensity () == ui_file_style::NORMAL);
+  SELF_CHECK (style.is_reverse ());
+  SELF_CHECK (style.to_ansi () == "\033[7m");
+
+  style = ui_file_style ();
+  SELF_CHECK (style.parse ("\033[32;1m", &n_read));
+  SELF_CHECK (n_read == 7);
+  SELF_CHECK (style.get_foreground ().is_basic ());
+  SELF_CHECK (style.get_foreground ().get_value () == ui_file_style::GREEN);
+  SELF_CHECK (style.get_background ().is_none ());
+  SELF_CHECK (style.get_intensity () == ui_file_style::BOLD);
+  SELF_CHECK (!style.is_reverse ());
+  SELF_CHECK (style.to_ansi () == "\033[32;1m");
+
+  style = ui_file_style ();
+  SELF_CHECK (style.parse ("\033[38;5;112;48;5;249m", &n_read));
+  SELF_CHECK (n_read == 20);
+  SELF_CHECK (!style.get_foreground ().is_basic ());
+  style.get_foreground ().get_rgb (rgb);
+  CHECK_RGB (0x87, 0xd7, 0);
+  SELF_CHECK (!style.get_background ().is_basic ());
+  style.get_background ().get_rgb (rgb);
+  CHECK_RGB (0xb2, 0xb2, 0xb2);
+  SELF_CHECK (style.get_intensity () == ui_file_style::NORMAL);
+  SELF_CHECK (!style.is_reverse ());
+  SELF_CHECK (style.to_ansi () == "\033[38;5;112;48;5;249m");
+
+  style = ui_file_style ();
+  SELF_CHECK (style.parse ("\033[38;2;83;84;85;48;2;0;1;254;2;7m", &n_read));
+  SELF_CHECK (n_read == 33);
+  SELF_CHECK (!style.get_foreground ().is_basic ());
+  style.get_foreground ().get_rgb (rgb);
+  CHECK_RGB (83, 84, 85);
+  SELF_CHECK (!style.get_background ().is_basic ());
+  style.get_background ().get_rgb (rgb);
+  CHECK_RGB (0, 1, 254);
+  SELF_CHECK (style.get_intensity () == ui_file_style::DIM);
+  SELF_CHECK (style.is_reverse ());
+  SELF_CHECK (style.to_ansi () == "\033[38;2;83;84;85;48;2;0;1;254;2;7m");
+}
+
+} /* namespace style */
+} /* namespace selftests */
+
+void
+_initialize_style_selftest ()
+{
+  selftests::register_test ("style",
+			    selftests::style::run_tests);
+}
-- 
2.17.2

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 14/16] Use wclrtoeol in tui_show_source_line
  2018-11-28  0:16 [PATCH 00/16] Add styling to the gdb CLI and TUI Tom Tromey
                   ` (2 preceding siblings ...)
  2018-11-28  0:14 ` [PATCH 03/16] Introduce ui_file_style Tom Tromey
@ 2018-11-28  0:14 ` Tom Tromey
  2018-12-24  8:03   ` Joel Brobecker
  2018-11-28  0:14 ` [PATCH 09/16] Style print_address_symbolic Tom Tromey
                   ` (13 subsequent siblings)
  17 siblings, 1 reply; 99+ messages in thread
From: Tom Tromey @ 2018-11-28  0:14 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This changes tui_show_source_line to use wclrtoeol rather than
manually emitting a sequence of spaces.

gdb/ChangeLog
2018-11-27  Tom Tromey  <tom@tromey.com>

	* tui/tui-winsource.c (tui_show_source_line): Use wclrtoeol.
---
 gdb/ChangeLog           | 4 ++++
 gdb/tui/tui-winsource.c | 8 +-------
 2 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/gdb/tui/tui-winsource.c b/gdb/tui/tui-winsource.c
index 49eb4ce6fc..0bf74383b1 100644
--- a/gdb/tui/tui-winsource.c
+++ b/gdb/tui/tui-winsource.c
@@ -272,7 +272,6 @@ static void
 tui_show_source_line (struct tui_win_info *win_info, int lineno)
 {
   struct tui_win_element *line;
-  int x;
 
   line = win_info->generic.content[lineno - 1];
   if (line->which_element.source.is_exec_point)
@@ -284,12 +283,7 @@ tui_show_source_line (struct tui_win_info *win_info, int lineno)
     wattroff (win_info->generic.handle, A_STANDOUT);
 
   /* Clear to end of line but stop before the border.  */
-  x = getcurx (win_info->generic.handle);
-  while (x + 1 < win_info->generic.width)
-    {
-      waddch (win_info->generic.handle, ' ');
-      x = getcurx (win_info->generic.handle);
-    }
+  wclrtoeol (win_info->generic.handle);
 }
 
 void
-- 
2.17.2

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 10/16] Style the gdb welcome message
  2018-11-28  0:16 [PATCH 00/16] Add styling to the gdb CLI and TUI Tom Tromey
  2018-11-28  0:14 ` [PATCH 06/16] Reset terminal styles Tom Tromey
@ 2018-11-28  0:14 ` Tom Tromey
  2018-11-28  0:14 ` [PATCH 03/16] Introduce ui_file_style Tom Tromey
                   ` (15 subsequent siblings)
  17 siblings, 0 replies; 99+ messages in thread
From: Tom Tromey @ 2018-11-28  0:14 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This changes gdb to style the welcome message that is shown by
default.  The styling is only done interactively.

gdb/ChangeLog
2018-11-27  Tom Tromey  <tom@tromey.com>

	* top.c (print_gdb_version): Style gdb version number.

gdb/testsuite/ChangeLog
2018-11-27  Tom Tromey  <tom@tromey.com>

	* gdb.base/style.exp: Add test for version number styling.
---
 gdb/ChangeLog                    | 4 ++++
 gdb/testsuite/ChangeLog          | 4 ++++
 gdb/testsuite/gdb.base/style.exp | 6 ++++++
 gdb/top.c                        | 9 ++++++++-
 4 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/gdb/testsuite/gdb.base/style.exp b/gdb/testsuite/gdb.base/style.exp
index 8b82ae99fa..a5bdc2795f 100644
--- a/gdb/testsuite/gdb.base/style.exp
+++ b/gdb/testsuite/gdb.base/style.exp
@@ -44,4 +44,10 @@ save_vars { env(TERM) } {
     gdb_test "break main" "file $base_file_expr.*"
 
     gdb_test "print &main" " = .* <$main_expr>"
+
+    gdb_exit
+    gdb_spawn
+
+    gdb_test "" "\033\\\[35;1mGNU gdb.*\033\\\[m.*" \
+	"version is styled"
 }
diff --git a/gdb/top.c b/gdb/top.c
index 4a0fedb6a8..50c6cff3d9 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -1281,7 +1281,14 @@ print_gdb_version (struct ui_file *stream, bool interactive)
      program to parse, and is just canonical program name and version
      number, which starts after last space.  */
 
-  fprintf_filtered (stream, "GNU gdb %s%s\n", PKGVERSION, version);
+  ui_file_style style;
+  if (interactive)
+    {
+      ui_file_style nstyle = { ui_file_style::MAGENTA, ui_file_style::NONE,
+			       ui_file_style::BOLD };
+      style = nstyle;
+    }
+  fprintf_styled (stream, style, "GNU gdb %s%s\n", PKGVERSION, version);
 
   /* Second line is a copyright notice.  */
 
-- 
2.17.2

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 05/16] Add output styles to gdb
  2018-11-28  0:16 [PATCH 00/16] Add styling to the gdb CLI and TUI Tom Tromey
                   ` (5 preceding siblings ...)
  2018-11-28  0:14 ` [PATCH 02/16] Add a "context" argument to add_setshow_enum_cmd Tom Tromey
@ 2018-11-28  0:14 ` Tom Tromey
  2018-12-24  4:08   ` Joel Brobecker
  2018-11-28  0:14 ` [PATCH 12/16] Style addresses Tom Tromey
                   ` (10 subsequent siblings)
  17 siblings, 1 reply; 99+ messages in thread
From: Tom Tromey @ 2018-11-28  0:14 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This adds some output styling to the CLI.

A style is currently a foreground color, a background color, and an
intensity (dim or bold).  (This list could be expanded depending on
terminal capabilities.)

A style can be applied while printing.  For ui-out, this is done by
passing the style constant as an argument.  For low-level cases,
fprintf_styled and fputs_styled are provided.

Users can control the style via a number of new set/show commands.  In
the interest of not typing many nearly-identical documentation
strings, I automated this.  On the down side, this is not very
i18n-friendly.

I've chose some default colors to use.  I think it would be good to
enable this by default, so that when users start the new gdb, they
will see the new feature.

Stylizing is done if TERM is set and is not "dumb".  This could be
improved when the TUI is available by using the curses has_colors
call.  That is, the lowest layer could call this without committing to
using curses everywhere; see my other patch for TUI colorizing.

I considered adding a new "set_style" method to ui_file.  However,
because the implementation had to interact with the pager code, I
didn't take this approach.  But, one idea might be to put the isatty
check there and then have it defer to the lower layers.

gdb/ChangeLog
2018-11-27  Tom Tromey  <tom@tromey.com>

	* utils.h (set_output_style, fprintf_styled)
	(fputs_styled): Declare.
	* utils.c (applied_style, desired_style): New globals.
	(emit_style_escape, set_output_style): New function.
	(prompt_for_continue): Emit style escapes.
	(fputs_maybe_filtered): Likewise.
	(fputs_styled, fprintf_styled): New functions.
	* ui-out.h (enum class ui_out_style_kind): New.
	(class ui_out) <field_string, field_stream, do_field_string>: Add
	style parameter.
	* ui-out.c (ui_out::field_stream, ui_out::field_string): Add style
	parameter.
	* tui/tui-out.h (class tui_ui_out) <do_field_string>: Add style
	parameter.
	* tui/tui-out.c (tui_ui_out::do_field_string): Add style
	parameter.
	(tui_ui_out::do_field_string): Update.
	* tracepoint.c (print_one_static_tracepoint_marker): Style
	output.
	* stack.c (print_frame_info, print_frame): Style output.
	* source.c (print_source_lines_base): Style output.
	* skip.c (info_skip_command): Style output.
	* record-btrace.c (btrace_call_history_src_line): Style output.
	(btrace_call_history): Likewise.
	* python/py-framefilter.c (py_print_frame): Style output.
	* mi/mi-out.h (class mi_ui_out) <do_field_string>: Add style
	parameter.
	* mi/mi-out.c (mi_ui_out::do_table_header)
	(mi_ui_out::do_field_int): Update.
	(mi_ui_out::do_field_string): Update.
	* disasm.c (gdb_pretty_print_disassembler::pretty_print_insn):
	Style output.
	* cli/cli-style.h: New file.
	* cli/cli-style.c: New file.
	* cli-out.h (class cli_ui_out) <do_field_string>: Add style
	parameter.
	* cli-out.c (cli_ui_out::do_table_header)
	(cli_ui_out::do_field_int, cli_ui_out::do_field_skip): Update.
	(cli_ui_out::do_field_string): Add style parameter.  Style the
	output.
	* breakpoint.c (print_breakpoint_location): Style output.
	(update_static_tracepoint): Likewise.
	* Makefile.in (SUBDIR_CLI_SRCS): Add cli-style.c.
	(HFILES_NO_SRCDIR): Add cli-style.h.

gdb/testsuite/ChangeLog
2018-11-27  Tom Tromey  <tom@tromey.com>

	* gdb.base/style.exp: New file.
	* gdb.base/style.c: New file.
---
 gdb/ChangeLog                    |  47 ++++++
 gdb/Makefile.in                  |   2 +
 gdb/breakpoint.c                 |  12 +-
 gdb/cli-out.c                    |  36 ++++-
 gdb/cli-out.h                    |   3 +-
 gdb/cli/cli-style.c              | 257 +++++++++++++++++++++++++++++++
 gdb/cli/cli-style.h              |  89 +++++++++++
 gdb/disasm.c                     |   3 +-
 gdb/mi/mi-out.c                  |  12 +-
 gdb/mi/mi-out.h                  |   3 +-
 gdb/python/py-framefilter.c      |   5 +-
 gdb/record-btrace.c              |  12 +-
 gdb/skip.c                       |   6 +-
 gdb/source.c                     |   3 +-
 gdb/stack.c                      |  13 +-
 gdb/testsuite/ChangeLog          |   5 +
 gdb/testsuite/gdb.base/style.c   |  22 +++
 gdb/testsuite/gdb.base/style.exp |  41 +++++
 gdb/tracepoint.c                 |   7 +-
 gdb/tui/tui-out.c                |   5 +-
 gdb/tui/tui-out.h                |   2 +-
 gdb/ui-out.c                     |  10 +-
 gdb/ui-out.h                     |  21 ++-
 gdb/utils.c                      |  80 +++++++++-
 gdb/utils.h                      |  16 ++
 25 files changed, 667 insertions(+), 45 deletions(-)
 create mode 100644 gdb/cli/cli-style.c
 create mode 100644 gdb/cli/cli-style.h
 create mode 100644 gdb/testsuite/gdb.base/style.c
 create mode 100644 gdb/testsuite/gdb.base/style.exp

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index ce0d799b7d..54baf96ea3 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -239,6 +239,7 @@ SUBDIR_CLI_SRCS = \
 	cli/cli-logging.c \
 	cli/cli-script.c \
 	cli/cli-setshow.c \
+	cli/cli-style.c \
 	cli/cli-utils.c
 
 SUBDIR_CLI_OBS = $(patsubst %.c,%.o,$(SUBDIR_CLI_SRCS))
@@ -1428,6 +1429,7 @@ HFILES_NO_SRCDIR = \
 	cli/cli-decode.h \
 	cli/cli-script.h \
 	cli/cli-setshow.h \
+	cli/cli-style.h \
 	cli/cli-utils.h \
 	common/buffer.h \
 	common/cleanups.h \
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 8af3d54a77..53763e0254 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -5860,13 +5860,15 @@ print_breakpoint_location (struct breakpoint *b,
       if (sym)
 	{
 	  uiout->text ("in ");
-	  uiout->field_string ("func", SYMBOL_PRINT_NAME (sym));
+	  uiout->field_string ("func", SYMBOL_PRINT_NAME (sym),
+			       ui_out_style_kind::FUNCTION);
 	  uiout->text (" ");
 	  uiout->wrap_hint (wrap_indent_at_field (uiout, "what"));
 	  uiout->text ("at ");
 	}
       uiout->field_string ("file",
-			   symtab_to_filename_for_display (loc->symtab));
+			   symtab_to_filename_for_display (loc->symtab),
+			   ui_out_style_kind::FILE);
       uiout->text (":");
 
       if (uiout->is_mi_like_p ())
@@ -13427,11 +13429,13 @@ update_static_tracepoint (struct breakpoint *b, struct symtab_and_line sal)
 	  uiout->text ("Now in ");
 	  if (sym)
 	    {
-	      uiout->field_string ("func", SYMBOL_PRINT_NAME (sym));
+	      uiout->field_string ("func", SYMBOL_PRINT_NAME (sym),
+				   ui_out_style_kind::FUNCTION);
 	      uiout->text (" at ");
 	    }
 	  uiout->field_string ("file",
-			       symtab_to_filename_for_display (sal2.symtab));
+			       symtab_to_filename_for_display (sal2.symtab),
+			       ui_out_style_kind::FILE);
 	  uiout->text (":");
 
 	  if (uiout->is_mi_like_p ())
diff --git a/gdb/cli-out.c b/gdb/cli-out.c
index 7e3ee3e54c..4b5fc17390 100644
--- a/gdb/cli-out.c
+++ b/gdb/cli-out.c
@@ -25,6 +25,7 @@
 #include "cli-out.h"
 #include "completer.h"
 #include "readline/readline.h"
+#include "cli/cli-style.h"
 
 /* These are the CLI output functions */
 
@@ -71,7 +72,8 @@ cli_ui_out::do_table_header (int width, ui_align alignment,
   if (m_suppress_output)
     return;
 
-  do_field_string (0, width, alignment, 0, col_hdr.c_str ());
+  do_field_string (0, width, alignment, 0, col_hdr.c_str (),
+		   ui_out_style_kind::DEFAULT);
 }
 
 /* Mark beginning of a list */
@@ -99,7 +101,8 @@ cli_ui_out::do_field_int (int fldno, int width, ui_align alignment,
 
   std::string str = string_printf ("%d", value);
 
-  do_field_string (fldno, width, alignment, fldname, str.c_str ());
+  do_field_string (fldno, width, alignment, fldname, str.c_str (),
+		   ui_out_style_kind::DEFAULT);
 }
 
 /* used to omit a field */
@@ -111,7 +114,8 @@ cli_ui_out::do_field_skip (int fldno, int width, ui_align alignment,
   if (m_suppress_output)
     return;
 
-  do_field_string (fldno, width, alignment, fldname, "");
+  do_field_string (fldno, width, alignment, fldname, "",
+		   ui_out_style_kind::DEFAULT);
 }
 
 /* other specific cli_field_* end up here so alignment and field
@@ -119,7 +123,8 @@ cli_ui_out::do_field_skip (int fldno, int width, ui_align alignment,
 
 void
 cli_ui_out::do_field_string (int fldno, int width, ui_align align,
-			     const char *fldname, const char *string)
+			     const char *fldname, const char *string,
+			     ui_out_style_kind style)
 {
   int before = 0;
   int after = 0;
@@ -154,7 +159,25 @@ cli_ui_out::do_field_string (int fldno, int width, ui_align align,
     spaces (before);
 
   if (string)
-    fputs_filtered (string, m_streams.back ());
+    {
+      ui_file_style fstyle;
+      switch (style)
+	{
+	case ui_out_style_kind::DEFAULT:
+	  /* Nothing.  */
+	  break;
+	case ui_out_style_kind::FILE:
+	  /* Nothing.  */
+	  fstyle = file_name_style.style ();
+	  break;
+	case ui_out_style_kind::FUNCTION:
+	  fstyle = function_name_style.style ();
+	  break;
+	default:
+	  gdb_assert_not_reached ("missing case");
+	}
+      fputs_styled (string, fstyle, m_streams.back ());
+    }
 
   if (after)
     spaces (after);
@@ -175,7 +198,8 @@ cli_ui_out::do_field_fmt (int fldno, int width, ui_align align,
 
   std::string str = string_vprintf (format, args);
 
-  do_field_string (fldno, width, align, fldname, str.c_str ());
+  do_field_string (fldno, width, align, fldname, str.c_str (),
+		   ui_out_style_kind::DEFAULT);
 }
 
 void
diff --git a/gdb/cli-out.h b/gdb/cli-out.h
index f701da7bf3..4fe10a40a2 100644
--- a/gdb/cli-out.h
+++ b/gdb/cli-out.h
@@ -51,7 +51,8 @@ protected:
 			      const char *fldname) override;
   virtual void do_field_string (int fldno, int width, ui_align align,
 				const char *fldname,
-				const char *string) override;
+				const char *string,
+				ui_out_style_kind style) override;
   virtual void do_field_fmt (int fldno, int width, ui_align align,
 			     const char *fldname, const char *format,
 			     va_list args)
diff --git a/gdb/cli/cli-style.c b/gdb/cli/cli-style.c
new file mode 100644
index 0000000000..de2866ce75
--- /dev/null
+++ b/gdb/cli/cli-style.c
@@ -0,0 +1,257 @@
+/* CLI colorizing
+
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "cli/cli-cmds.h"
+#include "cli/cli-style.h"
+
+/* True if styling is enabled.  */
+
+#if defined(_WIN32) || defined (__CYGWIN__)
+int cli_styling = 0;
+#else
+int cli_styling = 1;
+#endif
+
+/* Name of colors; must correspond to ui_file_style::simple_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[] = {
+  "normal",
+  "bold",
+  "dim",
+  nullptr
+};
+
+/* See cli-style.h.  */
+
+cli_style_option file_name_style (ui_file_style::GREEN);
+
+/* See cli-style.h.  */
+
+cli_style_option function_name_style (ui_file_style::YELLOW);
+
+/* See cli-style.h.  */
+
+cli_style_option::cli_style_option (ui_file_style::simple_color fg)
+  : m_foreground (cli_colors[fg - ui_file_style::NONE]),
+    m_background (cli_colors[0]),
+    m_intensity (cli_intensities[ui_file_style::NORMAL])
+{
+}
+
+/* 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)
+    {
+      if (m_intensity == cli_intensities[i])
+	{
+	  intensity = (ui_file_style::intensity) i;
+	  break;
+	}
+    }
+
+  return ui_file_style (fg, bg, intensity);
+}
+
+/* See cli-style.h.  */
+
+void
+cli_style_option::do_set (const char *args, int from_tty)
+{
+}
+
+/* See cli-style.h.  */
+
+void
+cli_style_option::do_show (const char *args, int from_tty)
+{
+}
+
+/* See cli-style.h.  */
+
+void
+cli_style_option::do_show_foreground (struct ui_file *file, int from_tty,
+				      struct cmd_list_element *cmd,
+				      const char *value)
+{
+  const char *name = (const char *) get_cmd_context (cmd);
+  fprintf_filtered (file, _("The \"%s\" foreground color is: %s\n"),
+		    name, value);
+}
+
+/* See cli-style.h.  */
+
+void
+cli_style_option::do_show_background (struct ui_file *file, int from_tty,
+				      struct cmd_list_element *cmd,
+				      const char *value)
+{
+  const char *name = (const char *) get_cmd_context (cmd);
+  fprintf_filtered (file, _("The \"%s\" background color is: %s\n"),
+		    name, value);
+}
+
+/* See cli-style.h.  */
+
+void
+cli_style_option::do_show_intensity (struct ui_file *file, int from_tty,
+				     struct cmd_list_element *cmd,
+				     const char *value)
+{
+  const char *name = (const char *) get_cmd_context (cmd);
+  fprintf_filtered (file, _("The \"%s\" display intensity is: %s\n"),
+		    name, value);
+}
+
+/* See cli-style.h.  */
+
+void
+cli_style_option::add_setshow_commands (const char *name,
+					enum command_class theclass,
+					const char *prefix_doc,
+					const char *prefixname,
+					struct cmd_list_element **set_list,
+					struct cmd_list_element **show_list)
+{
+  m_show_prefix = std::string ("set ") + prefixname + " ";
+  m_show_prefix = std::string ("show ") + prefixname + " ";
+
+  add_prefix_cmd (name, no_class, do_set, prefix_doc, &m_set_list, 
+		  m_show_prefix.c_str (), 0, set_list);
+  add_prefix_cmd (name, no_class, do_show, prefix_doc, &m_show_list,
+		  m_set_prefix.c_str (), 0, show_list);
+
+  add_setshow_enum_cmd ("foreground", theclass, cli_colors,
+			&m_foreground,
+			_("Set the foreground color for this property"),
+			_("Show the foreground color for this property"),
+			nullptr,
+			nullptr,
+			do_show_foreground,
+			&m_set_list, &m_show_list, (void *) name);
+  add_setshow_enum_cmd ("background", theclass, cli_colors,
+			&m_background,
+			_("Set the background color for this property"),
+			_("Show the background color for this property"),
+			nullptr,
+			nullptr,
+			do_show_background,
+			&m_set_list, &m_show_list, (void *) name);
+  add_setshow_enum_cmd ("intensity", theclass, cli_intensities,
+			&m_intensity,
+			_("Set the display intensity color for this property"),
+			_("\
+Show the display intensity color for this property"),
+			nullptr,
+			nullptr,
+			do_show_intensity,
+			&m_set_list, &m_show_list, (void *) name);
+}
+
+static void
+set_style (const char *arg, int from_tty)
+{
+}
+
+static void
+show_style (const char *arg, int from_tty)
+{
+}
+
+static void
+show_style_enabled (struct ui_file *file, int from_tty,
+		    struct cmd_list_element *c, const char *value)
+{
+  if (cli_styling)
+    fprintf_filtered (file, _("CLI output styling is enabled.\n"));
+  else
+    fprintf_filtered (file, _("CLI output styling is disabled.\n"));
+}
+
+void
+_initialize_cli_style ()
+{
+  static cmd_list_element *style_set_list;
+  static cmd_list_element *style_show_list;
+
+  add_prefix_cmd ("style", no_class, set_style, _("\
+Style-specific settings\n\
+Configure various style-related variables, such as colors"),
+		  &style_set_list, "set style ", 0, &setlist);
+  add_prefix_cmd ("style", no_class, show_style, _("\
+Style-specific settings\n\
+Configure various style-related variables, such as colors"),
+		  &style_show_list, "show style ", 0, &showlist);
+
+  add_setshow_boolean_cmd ("enabled", no_class, &cli_styling, _("\
+Set whether CLI styling is enabled."), _("\
+Show whether CLI is enabled."), _("\
+If enabled, output to the terminal is styled."),
+			   NULL, show_style_enabled,
+			   &style_set_list, &style_show_list);
+
+  file_name_style.add_setshow_commands ("filename", no_class,
+					_("\
+Filename display styling\n\
+Configure filename colors and display intensity."),
+					"style filename",
+					&style_set_list,
+					&style_show_list);
+  function_name_style.add_setshow_commands ("function", no_class,
+					    _("\
+Function name display styling\n\
+Configure function name colors and display intensity"),
+					    "style function",
+					    &style_set_list,
+					    &style_show_list);
+}
diff --git a/gdb/cli/cli-style.h b/gdb/cli/cli-style.h
new file mode 100644
index 0000000000..36845b2581
--- /dev/null
+++ b/gdb/cli/cli-style.h
@@ -0,0 +1,89 @@
+/* CLI stylizing
+
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef CLI_STYLE_H
+#define CLI_STYLE_H
+
+#include "ui-file.h"
+
+/* A single CLI style option.  */
+class cli_style_option
+{
+public:
+
+  /* Construct a CLI style option with a foreground color.  */
+  cli_style_option (ui_file_style::simple_color fg);
+
+  /* Return a ui_file_style corresponding to the settings in this CLI
+     style.  */
+  ui_file_style style () const;
+
+  /* Call once to register this CLI style with the CLI engine.  */
+  void add_setshow_commands (const char *name,
+			     enum command_class theclass,
+			     const char *prefix_doc,
+			     const char *prefixname,
+			     struct cmd_list_element **set_list,
+			     struct cmd_list_element **show_list);
+
+private:
+
+  /* The foreground.  */
+  const char *m_foreground;
+  /* The background.  */
+  const char *m_background;
+  /* The intensity.  */
+  const char *m_intensity;
+
+  /* Storage for prefixes needed when registering the commands.  */
+  std::string m_show_prefix;
+  std::string m_set_prefix;
+  /* Storage for command lists needed when registering
+     subcommands.  */
+  struct cmd_list_element *m_set_list = nullptr;
+  struct cmd_list_element *m_show_list = nullptr;
+
+  /* Callback to set a value.  */
+  static void do_set (const char *args, int from_tty);
+  /* Callback to show a value.  */
+  static void do_show (const char *args, int from_tty);
+  /* Callback to show the foreground.  */
+  static void do_show_foreground (struct ui_file *file, int from_tty,
+				  struct cmd_list_element *cmd,
+				  const char *value);
+  /* Callback to show the background.  */
+  static void do_show_background (struct ui_file *file, int from_tty,
+				  struct cmd_list_element *cmd,
+				  const char *value);
+  /* Callback to show the intensity.  */
+  static void do_show_intensity (struct ui_file *file, int from_tty,
+				 struct cmd_list_element *cmd,
+				 const char *value);
+};
+
+/* The file name style.  */
+extern cli_style_option file_name_style;
+
+/* The function name style.  */
+extern cli_style_option function_name_style;
+
+/* True if styling is enabled.  */
+extern int cli_styling;
+
+#endif /* CLI_STYLE_H */
diff --git a/gdb/disasm.c b/gdb/disasm.c
index 128c3abfde..5e016be79f 100644
--- a/gdb/disasm.c
+++ b/gdb/disasm.c
@@ -244,7 +244,8 @@ gdb_pretty_print_disassembler::pretty_print_insn (struct ui_out *uiout,
 	   the future.  */
 	uiout->text (" <");
 	if ((flags & DISASSEMBLY_OMIT_FNAME) == 0)
-	  uiout->field_string ("func-name", name.c_str ());
+	  uiout->field_string ("func-name", name.c_str (),
+			       ui_out_style_kind::FUNCTION);
 	uiout->text ("+");
 	uiout->field_int ("offset", offset);
 	uiout->text (">:\t");
diff --git a/gdb/mi/mi-out.c b/gdb/mi/mi-out.c
index 39b18b03a0..4aa4a5c601 100644
--- a/gdb/mi/mi-out.c
+++ b/gdb/mi/mi-out.c
@@ -65,8 +65,10 @@ mi_ui_out::do_table_header (int width, ui_align alignment,
   open (NULL, ui_out_type_tuple);
   do_field_int (0, 0, ui_center, "width", width);
   do_field_int (0, 0, ui_center, "alignment", alignment);
-  do_field_string (0, 0, ui_center, "col_name", col_name.c_str ());
-  do_field_string (0, width, alignment, "colhdr", col_hdr.c_str ());
+  do_field_string (0, 0, ui_center, "col_name", col_name.c_str (),
+		   ui_out_style_kind::DEFAULT);
+  do_field_string (0, width, alignment, "colhdr", col_hdr.c_str (),
+		   ui_out_style_kind::DEFAULT);
   close (ui_out_type_tuple);
 }
 
@@ -95,7 +97,8 @@ mi_ui_out::do_field_int (int fldno, int width, ui_align alignment,
   char buffer[20];	/* FIXME: how many chars long a %d can become? */
 
   xsnprintf (buffer, sizeof (buffer), "%d", value);
-  do_field_string (fldno, width, alignment, fldname, buffer);
+  do_field_string (fldno, width, alignment, fldname, buffer,
+		   ui_out_style_kind::DEFAULT);
 }
 
 /* Used to omit a field.  */
@@ -111,7 +114,8 @@ mi_ui_out::do_field_skip (int fldno, int width, ui_align alignment,
 
 void
 mi_ui_out::do_field_string (int fldno, int width, ui_align align,
-			    const char *fldname, const char *string)
+			    const char *fldname, const char *string,
+			    ui_out_style_kind style)
 {
   ui_file *stream = m_streams.back ();
   field_separator ();
diff --git a/gdb/mi/mi-out.h b/gdb/mi/mi-out.h
index 89ff88cd32..b576263d2b 100644
--- a/gdb/mi/mi-out.h
+++ b/gdb/mi/mi-out.h
@@ -57,7 +57,8 @@ protected:
   virtual void do_field_skip (int fldno, int width, ui_align align,
 			   const char *fldname) override;
   virtual void do_field_string (int fldno, int width, ui_align align,
-			     const char *fldname, const char *string) override;
+				const char *fldname, const char *string,
+				ui_out_style_kind style) override;
   virtual void do_field_fmt (int fldno, int width, ui_align align,
 			  const char *fldname, const char *format, va_list args)
     override ATTRIBUTE_PRINTF (6,0);
diff --git a/gdb/python/py-framefilter.c b/gdb/python/py-framefilter.c
index fe17b70f53..53ff5c822e 100644
--- a/gdb/python/py-framefilter.c
+++ b/gdb/python/py-framefilter.c
@@ -898,7 +898,7 @@ py_print_frame (PyObject *filter, frame_filter_flags flags,
 	  if (function == NULL)
 	    out->field_skip ("func");
 	  else
-	    out->field_string ("func", function);
+	    out->field_string ("func", function, ui_out_style_kind::FUNCTION);
 	}
     }
 
@@ -934,7 +934,8 @@ py_print_frame (PyObject *filter, frame_filter_flags flags,
 	      out->wrap_hint ("   ");
 	      out->text (" at ");
 	      annotate_frame_source_file ();
-	      out->field_string ("file", filename.get ());
+	      out->field_string ("file", filename.get (),
+				 ui_out_style_kind::FILE);
 	      annotate_frame_source_file_end ();
 	    }
 	}
diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index 814f080941..8e8ef15284 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -1091,7 +1091,8 @@ btrace_call_history_src_line (struct ui_out *uiout,
     return;
 
   uiout->field_string ("file",
-		       symtab_to_filename_for_display (symbol_symtab (sym)));
+		       symtab_to_filename_for_display (symbol_symtab (sym)),
+		       ui_out_style_kind::FILE);
 
   btrace_compute_src_line_range (bfun, &begin, &end);
   if (end < begin)
@@ -1182,11 +1183,14 @@ btrace_call_history (struct ui_out *uiout,
 	}
 
       if (sym != NULL)
-	uiout->field_string ("function", SYMBOL_PRINT_NAME (sym));
+	uiout->field_string ("function", SYMBOL_PRINT_NAME (sym),
+			     ui_out_style_kind::FUNCTION);
       else if (msym != NULL)
-	uiout->field_string ("function", MSYMBOL_PRINT_NAME (msym));
+	uiout->field_string ("function", MSYMBOL_PRINT_NAME (msym),
+			     ui_out_style_kind::FUNCTION);
       else if (!uiout->is_mi_like_p ())
-	uiout->field_string ("function", "??");
+	uiout->field_string ("function", "??",
+			     ui_out_style_kind::FUNCTION);
 
       if ((flags & RECORD_PRINT_INSN_RANGE) != 0)
 	{
diff --git a/gdb/skip.c b/gdb/skip.c
index 77373e85e6..a8f8ee1962 100644
--- a/gdb/skip.c
+++ b/gdb/skip.c
@@ -413,7 +413,8 @@ info_skip_command (const char *arg, int from_tty)
 
       current_uiout->field_string ("file",
 				   e.file ().empty () ? "<none>"
-				   : e.file ().c_str ()); /* 4 */
+				   : e.file ().c_str (),
+				   ui_out_style_kind::FILE); /* 4 */
       if (e.function_is_regexp ())
 	current_uiout->field_string ("regexp", "y"); /* 5 */
       else
@@ -421,7 +422,8 @@ info_skip_command (const char *arg, int from_tty)
 
       current_uiout->field_string ("function",
 				   e.function ().empty () ? "<none>"
-				   : e.function ().c_str ()); /* 6 */
+				   : e.function ().c_str (),
+				   ui_out_style_kind::FUNCTION); /* 6 */
 
       current_uiout->text ("\n");
     }
diff --git a/gdb/source.c b/gdb/source.c
index e295fbf49e..7552496f78 100644
--- a/gdb/source.c
+++ b/gdb/source.c
@@ -1320,7 +1320,8 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
 	     MI expects both fields.  ui_source_list is set only for CLI,
 	     not for TUI.  */
 	  if (uiout->is_mi_like_p () || uiout->test_flags (ui_source_list))
-	    uiout->field_string ("file", symtab_to_filename_for_display (s));
+	    uiout->field_string ("file", symtab_to_filename_for_display (s),
+				 ui_out_style_kind::FILE);
 	  if (uiout->is_mi_like_p () || !uiout->test_flags (ui_source_list))
  	    {
 	      const char *s_fullname = symtab_to_fullname (s);
diff --git a/gdb/stack.c b/gdb/stack.c
index f34d7b2a17..a718bf8901 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -824,16 +824,19 @@ print_frame_info (struct frame_info *frame, int print_level,
       if (get_frame_type (frame) == DUMMY_FRAME)
         {
           annotate_function_call ();
-          uiout->field_string ("func", "<function called from gdb>");
+          uiout->field_string ("func", "<function called from gdb>",
+			       ui_out_style_kind::FUNCTION);
 	}
       else if (get_frame_type (frame) == SIGTRAMP_FRAME)
         {
 	  annotate_signal_handler_caller ();
-          uiout->field_string ("func", "<signal handler called>");
+          uiout->field_string ("func", "<signal handler called>",
+			       ui_out_style_kind::FUNCTION);
         }
       else if (get_frame_type (frame) == ARCH_FRAME)
         {
-          uiout->field_string ("func", "<cross-architecture call>");
+          uiout->field_string ("func", "<cross-architecture call>",
+			       ui_out_style_kind::FUNCTION);
 	}
       uiout->text ("\n");
       annotate_frame_end ();
@@ -1182,7 +1185,7 @@ print_frame (struct frame_info *frame, int print_level,
     string_file stb;
     fprintf_symbol_filtered (&stb, funname ? funname.get () : "??",
 			     funlang, DMGL_ANSI);
-    uiout->field_stream ("func", stb);
+    uiout->field_stream ("func", stb, ui_out_style_kind::FUNCTION);
     uiout->wrap_hint ("   ");
     annotate_frame_args ();
       
@@ -1225,7 +1228,7 @@ print_frame (struct frame_info *frame, int print_level,
 	uiout->wrap_hint ("   ");
 	uiout->text (" at ");
 	annotate_frame_source_file ();
-	uiout->field_string ("file", filename_display);
+	uiout->field_string ("file", filename_display, ui_out_style_kind::FILE);
 	if (uiout->is_mi_like_p ())
 	  {
 	    const char *fullname = symtab_to_fullname (sal.symtab);
diff --git a/gdb/testsuite/gdb.base/style.c b/gdb/testsuite/gdb.base/style.c
new file mode 100644
index 0000000000..a7820831fd
--- /dev/null
+++ b/gdb/testsuite/gdb.base/style.c
@@ -0,0 +1,22 @@
+/* Copyright 2018 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+
+int
+main (int argc, char **argv)
+{
+  return 0; /* break here */
+}
diff --git a/gdb/testsuite/gdb.base/style.exp b/gdb/testsuite/gdb.base/style.exp
new file mode 100644
index 0000000000..859e50352f
--- /dev/null
+++ b/gdb/testsuite/gdb.base/style.exp
@@ -0,0 +1,41 @@
+# Copyright 2018 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test CLI output styling.
+
+standard_testfile
+
+save_vars { env(TERM) } {
+    # We need an ANSI-capable terminal to get the output.
+    setenv TERM ansi
+
+    if {[prepare_for_testing "failed to prepare" $testfile $srcfile]} {
+	return -1
+    }
+
+    if {![runto_main]} {
+	fail "style tests failed"
+	return
+    }
+
+    gdb_test_no_output "set style enabled on"
+    
+    set main_expr "\033\\\[33mmain\033\\\[m"
+    set file_expr "\033\\\[32m.*style\\.c\033\\\[m:\[0-9\]"
+
+    gdb_test "frame" \
+	"$main_expr.*$file_expr.*"
+    gdb_test "info breakpoints" "$main_expr at $file_expr.*"
+}
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index 8cd53374f9..5c1111297c 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -3684,8 +3684,8 @@ print_one_static_tracepoint_marker (int count,
   if (sym)
     {
       uiout->text ("in ");
-      uiout->field_string ("func",
-			   SYMBOL_PRINT_NAME (sym));
+      uiout->field_string ("func", SYMBOL_PRINT_NAME (sym),
+			   ui_out_style_kind::FUNCTION);
       uiout->wrap_hint (wrap_indent);
       uiout->text (" at ");
     }
@@ -3695,7 +3695,8 @@ print_one_static_tracepoint_marker (int count,
   if (sal.symtab != NULL)
     {
       uiout->field_string ("file",
-			   symtab_to_filename_for_display (sal.symtab));
+			   symtab_to_filename_for_display (sal.symtab),
+			   ui_out_style_kind::FILE);
       uiout->text (":");
 
       if (uiout->is_mi_like_p ())
diff --git a/gdb/tui/tui-out.c b/gdb/tui/tui-out.c
index 6d4e2363f3..29d7bfa84b 100644
--- a/gdb/tui/tui-out.c
+++ b/gdb/tui/tui-out.c
@@ -51,7 +51,8 @@ tui_ui_out::do_field_int (int fldno, int width, ui_align alignment,
 
 void
 tui_ui_out::do_field_string (int fldno, int width, ui_align align,
-			     const char *fldname, const char *string)
+			     const char *fldname, const char *string,
+			     ui_out_style_kind style)
 {
   if (suppress_output ())
     return;
@@ -68,7 +69,7 @@ tui_ui_out::do_field_string (int fldno, int width, ui_align align,
   
   m_start_of_line++;
 
-  cli_ui_out::do_field_string (fldno, width, align, fldname, string);
+  cli_ui_out::do_field_string (fldno, width, align, fldname, string, style);
 }
 
 void
diff --git a/gdb/tui/tui-out.h b/gdb/tui/tui-out.h
index d191c65810..a4903eef61 100644
--- a/gdb/tui/tui-out.h
+++ b/gdb/tui/tui-out.h
@@ -31,7 +31,7 @@ protected:
   void do_field_int (int fldno, int width, ui_align align, const char *fldname,
 		  int value) override;
   void do_field_string (int fldno, int width, ui_align align, const char *fldname,
-		     const char *string) override;
+			const char *string, ui_out_style_kind style) override;
   void do_field_fmt (int fldno, int width, ui_align align, const char *fldname,
 		  const char *format, va_list args) override
     ATTRIBUTE_PRINTF (6,0);
diff --git a/gdb/ui-out.c b/gdb/ui-out.c
index 3d74f78543..761d6c0745 100644
--- a/gdb/ui-out.c
+++ b/gdb/ui-out.c
@@ -473,10 +473,11 @@ ui_out::field_core_addr (const char *fldname, struct gdbarch *gdbarch,
 }
 
 void
-ui_out::field_stream (const char *fldname, string_file &stream)
+ui_out::field_stream (const char *fldname, string_file &stream,
+		      ui_out_style_kind style)
 {
   if (!stream.empty ())
-    field_string (fldname, stream.c_str ());
+    field_string (fldname, stream.c_str (), style);
   else
     field_skip (fldname);
   stream.clear ();
@@ -497,7 +498,8 @@ ui_out::field_skip (const char *fldname)
 }
 
 void
-ui_out::field_string (const char *fldname, const char *string)
+ui_out::field_string (const char *fldname, const char *string,
+		      ui_out_style_kind style)
 {
   int fldno;
   int width;
@@ -505,7 +507,7 @@ ui_out::field_string (const char *fldname, const char *string)
 
   verify_field (&fldno, &width, &align);
 
-  do_field_string (fldno, width, align, fldname, string);
+  do_field_string (fldno, width, align, fldname, string, style);
 }
 
 void
diff --git a/gdb/ui-out.h b/gdb/ui-out.h
index 81e2e0b20d..8604105c09 100644
--- a/gdb/ui-out.h
+++ b/gdb/ui-out.h
@@ -66,6 +66,18 @@ enum ui_out_type
     ui_out_type_list
   };
 
+/* Possible kinds of styling.  */
+
+enum class ui_out_style_kind
+{
+  /* The default (plain) style.  */
+  DEFAULT,
+  /* File name.  */
+  FILE,
+  /* Function name.  */
+  FUNCTION
+};
+
 class ui_out
 {
  public:
@@ -95,9 +107,11 @@ class ui_out
 		      int value);
   void field_core_addr (const char *fldname, struct gdbarch *gdbarch,
 			CORE_ADDR address);
-  void field_string (const char *fldname, const char *string);
+  void field_string (const char *fldname, const char *string,
+		     ui_out_style_kind style = ui_out_style_kind::DEFAULT);
   void field_string (const char *fldname, const std::string &string);
-  void field_stream (const char *fldname, string_file &stream);
+  void field_stream (const char *fldname, string_file &stream,
+		     ui_out_style_kind style = ui_out_style_kind::DEFAULT);
   void field_skip (const char *fldname);
   void field_fmt (const char *fldname, const char *format, ...)
     ATTRIBUTE_PRINTF (3, 4);
@@ -141,7 +155,8 @@ class ui_out
   virtual void do_field_skip (int fldno, int width, ui_align align,
 			      const char *fldname) = 0;
   virtual void do_field_string (int fldno, int width, ui_align align,
-				const char *fldname, const char *string) = 0;
+				const char *fldname, const char *string,
+				ui_out_style_kind style) = 0;
   virtual void do_field_fmt (int fldno, int width, ui_align align,
 			     const char *fldname, const char *format,
 			     va_list args)
diff --git a/gdb/utils.c b/gdb/utils.c
index 0f1953a66d..69c9e76576 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -71,6 +71,7 @@
 #include "cp-support.h"
 #include <algorithm>
 #include "common/pathstuff.h"
+#include "cli/cli-style.h"
 
 void (*deprecated_error_begin_hook) (void);
 
@@ -1422,6 +1423,46 @@ set_screen_width_and_height (int width, int height)
   set_width ();
 }
 
+/* The currently applied style.  */
+
+static ui_file_style applied_style;
+
+/* The currently desired style.  This can differ from the applied
+   style when showing the pagination prompt.  */
+
+static ui_file_style desired_style;
+
+/* Emit an ANSI style escape for STYLE to the wrap buffer.  */
+
+static void
+emit_style_escape (const ui_file_style &style)
+{
+  if (applied_style == style)
+    return;
+  applied_style = style;
+
+  wrap_buffer.append (style.to_ansi ());
+}
+
+/* Set the current output style.  This will affect future uses of the
+   _filtered output functions.  */
+
+static void
+set_output_style (struct ui_file *stream, const ui_file_style &style)
+{
+  if (stream != gdb_stdout
+      || !cli_styling
+      || style == desired_style
+      || !ui_file_isatty (stream))
+    return;
+  const char *term = getenv ("TERM");
+  if (term == nullptr || !strcmp (term, "dumb"))
+    return;
+
+  desired_style = style;
+  emit_style_escape (style);
+}
+
 /* Wait, so the user can read what's on the screen.  Prompt the user
    to continue by pressing RETURN.  'q' is also provided because
    telling users what to do in the prompt is more user-friendly than
@@ -1437,6 +1478,9 @@ prompt_for_continue (void)
   steady_clock::time_point prompt_started = steady_clock::now ();
   bool disable_pagination = pagination_disabled_for_command;
 
+  /* Clear the current styling.  */
+  emit_style_escape (ui_file_style ());
+
   if (annotation_level > 1)
     printf_unfiltered (("\n\032\032pre-prompt-for-continue\n"));
 
@@ -1481,6 +1525,9 @@ prompt_for_continue (void)
   reinitialize_more_filter ();
   pagination_disabled_for_command = disable_pagination;
 
+  /* Restore the current styling.  */
+  emit_style_escape (desired_style);
+
   dont_repeat ();		/* Forget prev cmd -- CR won't repeat it.  */
 }
 
@@ -1714,7 +1761,11 @@ fputs_maybe_filtered (const char *linebuffer, struct ui_file *stream,
 	         if chars_per_line is right, we probably just overflowed
 	         anyway; if it's wrong, let us keep going.  */
 	      if (wrap_column)
-		fputc_unfiltered ('\n', stream);
+		{
+		  emit_style_escape (ui_file_style ());
+		  flush_wrap_buffer (stream);
+		  fputc_unfiltered ('\n', stream);
+		}
 
 	      /* Possible new page.  Note that
 		 PAGINATION_DISABLED_FOR_COMMAND might be set during
@@ -1727,6 +1778,7 @@ fputs_maybe_filtered (const char *linebuffer, struct ui_file *stream,
 	      if (wrap_column)
 		{
 		  fputs_unfiltered (wrap_indent, stream);
+		  emit_style_escape (desired_style);
 		  flush_wrap_buffer (stream);
 		  /* FIXME, this strlen is what prevents wrap_indent from
 		     containing tabs.  However, if we recurse to print it
@@ -1759,6 +1811,17 @@ fputs_filtered (const char *linebuffer, struct ui_file *stream)
   fputs_maybe_filtered (linebuffer, stream, 1);
 }
 
+/* See utils.h.  */
+
+void
+fputs_styled (const char *linebuffer, const ui_file_style &style,
+	      struct ui_file *stream)
+{
+  set_output_style (stream, style);
+  fputs_maybe_filtered (linebuffer, stream, 1);
+  set_output_style (stream, ui_file_style ());
+}
+
 int
 putchar_unfiltered (int c)
 {
@@ -1986,6 +2049,21 @@ fprintfi_filtered (int spaces, struct ui_file *stream, const char *format,
   va_end (args);
 }
 
+/* See utils.h.  */
+
+void
+fprintf_styled (struct ui_file *stream, const ui_file_style &style,
+		const char *format, ...)
+{
+  va_list args;
+
+  set_output_style (stream, style);
+  va_start (args, format);
+  vfprintf_filtered (stream, format, args);
+  va_end (args);
+  set_output_style (stream, ui_file_style ());
+}
+
 
 void
 printf_filtered (const char *format, ...)
diff --git a/gdb/utils.h b/gdb/utils.h
index 08a29af1dc..9872a15fd7 100644
--- a/gdb/utils.h
+++ b/gdb/utils.h
@@ -423,6 +423,22 @@ extern void fputstrn_unfiltered (const char *str, int n, int quotr,
 /* Return nonzero if filtered printing is initialized.  */
 extern int filtered_printing_initialized (void);
 
+/* Like fprintf_filtered, but styles the output according to STYLE,
+   when appropriate.  */
+
+extern void fprintf_styled (struct ui_file *stream,
+			    const ui_file_style &style,
+			    const char *fmt,
+			    ...)
+  ATTRIBUTE_PRINTF (3, 4);
+
+/* Like fputs_filtered, but styles the output according to STYLE, when
+   appropriate.  */
+
+extern void fputs_styled (const char *linebuffer,
+			  const ui_file_style &style,
+			  struct ui_file *stream);
+
 /* Display the host ADDR on STREAM formatted as ``0x%x''.  */
 extern void gdb_print_host_address_1 (const void *addr, struct ui_file *stream);
 
-- 
2.17.2

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 12/16] Style addresses
  2018-11-28  0:16 [PATCH 00/16] Add styling to the gdb CLI and TUI Tom Tromey
                   ` (6 preceding siblings ...)
  2018-11-28  0:14 ` [PATCH 05/16] Add output styles to gdb Tom Tromey
@ 2018-11-28  0:14 ` Tom Tromey
  2018-11-28  0:16 ` [PATCH 08/16] Style locations when setting a breakpoint Tom Tromey
                   ` (9 subsequent siblings)
  17 siblings, 0 replies; 99+ messages in thread
From: Tom Tromey @ 2018-11-28  0:14 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This changes gdb to style addresses.

gdb/ChangeLog
2018-11-27  Tom Tromey  <tom@tromey.com>

	* ui-out.h (enum class ui_out_style_kind) <ADDRESS>: New
	constant.
	* ui-out.c (ui_out::field_core_addr): Add styling.
	* stack.c (print_frame): Add styling.
	* printcmd.c (print_address): Add styling.
	(print_address_demangle, info_address_command): Likewise.
	* cli/cli-style.h (address_style): Declare.
	* cli/cli-style.c (address_style): New global.
	(_initialize_cli_style): Register new commands.
	* cli-out.c (cli_ui_out::do_field_string): Update.

gdb/testsuite/ChangeLog
2018-11-27  Tom Tromey  <tom@tromey.com>

	* gdb.base/style.exp: Update test to check for address styling.
---
 gdb/ChangeLog                    | 13 ++++++++++++
 gdb/cli-out.c                    |  3 +++
 gdb/cli/cli-style.c              | 11 ++++++++++
 gdb/cli/cli-style.h              |  3 +++
 gdb/printcmd.c                   | 36 +++++++++++++++++++++-----------
 gdb/stack.c                      |  3 ++-
 gdb/testsuite/ChangeLog          |  4 ++++
 gdb/testsuite/gdb.base/style.exp |  2 +-
 gdb/ui-out.c                     |  3 ++-
 gdb/ui-out.h                     |  4 +++-
 10 files changed, 66 insertions(+), 16 deletions(-)

diff --git a/gdb/cli-out.c b/gdb/cli-out.c
index e1005e1b35..691f993bad 100644
--- a/gdb/cli-out.c
+++ b/gdb/cli-out.c
@@ -176,6 +176,9 @@ cli_ui_out::do_field_string (int fldno, int width, ui_align align,
 	case ui_out_style_kind::VARIABLE:
 	  fstyle = variable_name_style.style ();
 	  break;
+	case ui_out_style_kind::ADDRESS:
+	  fstyle = address_style.style ();
+	  break;
 	default:
 	  gdb_assert_not_reached ("missing case");
 	}
diff --git a/gdb/cli/cli-style.c b/gdb/cli/cli-style.c
index fd4a4fc477..74e3958eb8 100644
--- a/gdb/cli/cli-style.c
+++ b/gdb/cli/cli-style.c
@@ -66,6 +66,10 @@ cli_style_option variable_name_style (ui_file_style::CYAN);
 
 /* See cli-style.h.  */
 
+cli_style_option address_style (ui_file_style::BLUE);
+
+/* See cli-style.h.  */
+
 cli_style_option::cli_style_option (ui_file_style::simple_color fg)
   : m_foreground (cli_colors[fg - ui_file_style::NONE]),
     m_background (cli_colors[0]),
@@ -265,4 +269,11 @@ Variable name display styling\n\
 Configure variable name colors and display intensity"),
 					    &style_set_list,
 					    &style_show_list);
+  address_style.add_setshow_commands ("address", no_class,
+				      "style address",
+				      _("\
+Address display styling\n\
+Configure address colors and display intensity"),
+				      &style_set_list,
+				      &style_show_list);
 }
diff --git a/gdb/cli/cli-style.h b/gdb/cli/cli-style.h
index 3d5142e3de..b1e9e09d45 100644
--- a/gdb/cli/cli-style.h
+++ b/gdb/cli/cli-style.h
@@ -86,6 +86,9 @@ extern cli_style_option function_name_style;
 /* The variable name style.  */
 extern cli_style_option variable_name_style;
 
+/* The address style.  */
+extern cli_style_option address_style;
+
 /* True if styling is enabled.  */
 extern int cli_styling;
 
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index c5b6b1a75b..98f5b23ce5 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -693,7 +693,7 @@ void
 print_address (struct gdbarch *gdbarch,
 	       CORE_ADDR addr, struct ui_file *stream)
 {
-  fputs_filtered (paddress (gdbarch, addr), stream);
+  fputs_styled (paddress (gdbarch, addr), address_style.style (), stream);
   print_address_symbolic (gdbarch, addr, stream, asm_demangle, " ");
 }
 
@@ -726,7 +726,7 @@ print_address_demangle (const struct value_print_options *opts,
 {
   if (opts->addressprint)
     {
-      fputs_filtered (paddress (gdbarch, addr), stream);
+      fputs_styled (paddress (gdbarch, addr), address_style.style (), stream);
       print_address_symbolic (gdbarch, addr, stream, do_demangle, " ");
     }
   else
@@ -1404,14 +1404,17 @@ info_address_command (const char *exp, int from_tty)
 	  fprintf_symbol_filtered (gdb_stdout, exp,
 				   current_language->la_language, DMGL_ANSI);
 	  printf_filtered ("\" is at ");
-	  fputs_filtered (paddress (gdbarch, load_addr), gdb_stdout);
+	  fputs_styled (paddress (gdbarch, load_addr), address_style.style (),
+			gdb_stdout);
 	  printf_filtered (" in a file compiled without debugging");
 	  section = MSYMBOL_OBJ_SECTION (objfile, msymbol.minsym);
 	  if (section_is_overlay (section))
 	    {
 	      load_addr = overlay_unmapped_address (load_addr, section);
 	      printf_filtered (",\n -- loaded at ");
-	      fputs_filtered (paddress (gdbarch, load_addr), gdb_stdout);
+	      fputs_styled (paddress (gdbarch, load_addr),
+			    address_style.style (),
+			    gdb_stdout);
 	      printf_filtered (" in overlay section %s",
 			       section->the_bfd_section->name);
 	    }
@@ -1451,12 +1454,14 @@ info_address_command (const char *exp, int from_tty)
     case LOC_LABEL:
       printf_filtered ("a label at address ");
       load_addr = SYMBOL_VALUE_ADDRESS (sym);
-      fputs_filtered (paddress (gdbarch, load_addr), gdb_stdout);
+      fputs_styled (paddress (gdbarch, load_addr), address_style.style (),
+		    gdb_stdout);
       if (section_is_overlay (section))
 	{
 	  load_addr = overlay_unmapped_address (load_addr, section);
 	  printf_filtered (",\n -- loaded at ");
-	  fputs_filtered (paddress (gdbarch, load_addr), gdb_stdout);
+	  fputs_styled (paddress (gdbarch, load_addr), address_style.style (),
+			gdb_stdout);
 	  printf_filtered (" in overlay section %s",
 			   section->the_bfd_section->name);
 	}
@@ -1485,12 +1490,14 @@ info_address_command (const char *exp, int from_tty)
     case LOC_STATIC:
       printf_filtered (_("static storage at address "));
       load_addr = SYMBOL_VALUE_ADDRESS (sym);
-      fputs_filtered (paddress (gdbarch, load_addr), gdb_stdout);
+      fputs_styled (paddress (gdbarch, load_addr), address_style.style (),
+		    gdb_stdout);
       if (section_is_overlay (section))
 	{
 	  load_addr = overlay_unmapped_address (load_addr, section);
 	  printf_filtered (_(",\n -- loaded at "));
-	  fputs_filtered (paddress (gdbarch, load_addr), gdb_stdout);
+	  fputs_styled (paddress (gdbarch, load_addr), address_style.style (),
+			gdb_stdout);
 	  printf_filtered (_(" in overlay section %s"),
 			   section->the_bfd_section->name);
 	}
@@ -1522,12 +1529,14 @@ info_address_command (const char *exp, int from_tty)
     case LOC_BLOCK:
       printf_filtered (_("a function at address "));
       load_addr = BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (sym));
-      fputs_filtered (paddress (gdbarch, load_addr), gdb_stdout);
+      fputs_styled (paddress (gdbarch, load_addr), address_style.style (),
+		    gdb_stdout);
       if (section_is_overlay (section))
 	{
 	  load_addr = overlay_unmapped_address (load_addr, section);
 	  printf_filtered (_(",\n -- loaded at "));
-	  fputs_filtered (paddress (gdbarch, load_addr), gdb_stdout);
+	  fputs_styled (paddress (gdbarch, load_addr), address_style.style (),
+			gdb_stdout);
 	  printf_filtered (_(" in overlay section %s"),
 			   section->the_bfd_section->name);
 	}
@@ -1557,12 +1566,15 @@ info_address_command (const char *exp, int from_tty)
 	      {
 		load_addr = BMSYMBOL_VALUE_ADDRESS (msym);
 		printf_filtered (_("static storage at address "));
-		fputs_filtered (paddress (gdbarch, load_addr), gdb_stdout);
+		fputs_styled (paddress (gdbarch, load_addr),
+			      address_style.style (), gdb_stdout);
 		if (section_is_overlay (section))
 		  {
 		    load_addr = overlay_unmapped_address (load_addr, section);
 		    printf_filtered (_(",\n -- loaded at "));
-		    fputs_filtered (paddress (gdbarch, load_addr), gdb_stdout);
+		    fputs_styled (paddress (gdbarch, load_addr),
+				  address_style.style (),
+				  gdb_stdout);
 		    printf_filtered (_(" in overlay section %s"),
 				     section->the_bfd_section->name);
 		  }
diff --git a/gdb/stack.c b/gdb/stack.c
index 930d7d0b1e..819bb616f0 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -1176,7 +1176,8 @@ print_frame (struct frame_info *frame, int print_level,
 	  if (pc_p)
 	    uiout->field_core_addr ("addr", gdbarch, pc);
 	  else
-	    uiout->field_string ("addr", "<unavailable>");
+	    uiout->field_string ("addr", "<unavailable>",
+				 ui_out_style_kind::ADDRESS);
 	  annotate_frame_address_end ();
 	  uiout->text (" in ");
 	}
diff --git a/gdb/testsuite/gdb.base/style.exp b/gdb/testsuite/gdb.base/style.exp
index a44d78f236..b633340afe 100644
--- a/gdb/testsuite/gdb.base/style.exp
+++ b/gdb/testsuite/gdb.base/style.exp
@@ -43,7 +43,7 @@ save_vars { env(TERM) } {
 
     gdb_test "break main" "file $base_file_expr.*"
 
-    gdb_test "print &main" " = .* <$main_expr>"
+    gdb_test "print &main" " = .* \033\\\[34m$hex\033\\\[m <$main_expr>"
 
     gdb_exit
     gdb_spawn
diff --git a/gdb/ui-out.c b/gdb/ui-out.c
index 761d6c0745..49f04dd936 100644
--- a/gdb/ui-out.c
+++ b/gdb/ui-out.c
@@ -469,7 +469,8 @@ void
 ui_out::field_core_addr (const char *fldname, struct gdbarch *gdbarch,
 			 CORE_ADDR address)
 {
-  field_string (fldname, print_core_address (gdbarch, address));
+  field_string (fldname, print_core_address (gdbarch, address),
+		ui_out_style_kind::ADDRESS);
 }
 
 void
diff --git a/gdb/ui-out.h b/gdb/ui-out.h
index 93be9a91b2..96466d8023 100644
--- a/gdb/ui-out.h
+++ b/gdb/ui-out.h
@@ -77,7 +77,9 @@ enum class ui_out_style_kind
   /* Function name.  */
   FUNCTION,
   /* Variable name.  */
-  VARIABLE
+  VARIABLE,
+  /* Address.  */
+  ADDRESS
 };
 
 class ui_out
-- 
2.17.2

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 09/16] Style print_address_symbolic
  2018-11-28  0:16 [PATCH 00/16] Add styling to the gdb CLI and TUI Tom Tromey
                   ` (3 preceding siblings ...)
  2018-11-28  0:14 ` [PATCH 14/16] Use wclrtoeol in tui_show_source_line Tom Tromey
@ 2018-11-28  0:14 ` Tom Tromey
  2018-11-28  0:14 ` [PATCH 02/16] Add a "context" argument to add_setshow_enum_cmd Tom Tromey
                   ` (12 subsequent siblings)
  17 siblings, 0 replies; 99+ messages in thread
From: Tom Tromey @ 2018-11-28  0:14 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

print_address_symbolic does not use ui-out, so it did not style
function names.  This patch changes it to use the low-level style code
directly.

gdb/ChangeLog
2018-11-27  Tom Tromey  <tom@tromey.com>

	* printcmd.c (print_address_symbolic): Style function name.

gdb/testsuite/ChangeLog
2018-11-27  Tom Tromey  <tom@tromey.com>

	* gdb.base/style.exp: Add test for print_address_symbolic.
---
 gdb/ChangeLog                    | 4 ++++
 gdb/printcmd.c                   | 9 +++++----
 gdb/testsuite/ChangeLog          | 4 ++++
 gdb/testsuite/gdb.base/style.exp | 2 ++
 4 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index dd1626455b..c5b6b1a75b 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -50,6 +50,7 @@
 #include "format.h"
 #include "source.h"
 #include "common/byte-vector.h"
+#include "cli/cli-style.h"
 
 /* Last specified output format.  */
 
@@ -535,7 +536,7 @@ print_address_symbolic (struct gdbarch *gdbarch, CORE_ADDR addr,
     fputs_filtered ("<*", stream);
   else
     fputs_filtered ("<", stream);
-  fputs_filtered (name.c_str (), stream);
+  fputs_styled (name.c_str (), function_name_style.style (), stream);
   if (offset != 0)
     fprintf_filtered (stream, "+%u", (unsigned int) offset);
 
@@ -543,10 +544,10 @@ print_address_symbolic (struct gdbarch *gdbarch, CORE_ADDR addr,
      line # of this addr, if we have it; else line # of the nearest symbol.  */
   if (print_symbol_filename && !filename.empty ())
     {
+      fputs_filtered (line == -1 ? " in " : " at ", stream);
+      fputs_styled (filename.c_str (), file_name_style.style (), stream);
       if (line != -1)
-	fprintf_filtered (stream, " at %s:%d", filename.c_str (), line);
-      else
-	fprintf_filtered (stream, " in %s", filename.c_str ());
+	fprintf_filtered (stream, ":%d", line);
     }
   if (unmapped)
     fputs_filtered ("*>", stream);
diff --git a/gdb/testsuite/gdb.base/style.exp b/gdb/testsuite/gdb.base/style.exp
index df73e25a16..8b82ae99fa 100644
--- a/gdb/testsuite/gdb.base/style.exp
+++ b/gdb/testsuite/gdb.base/style.exp
@@ -42,4 +42,6 @@ save_vars { env(TERM) } {
     gdb_test "info breakpoints" "$main_expr at $file_expr.*"
 
     gdb_test "break main" "file $base_file_expr.*"
+
+    gdb_test "print &main" " = .* <$main_expr>"
 }
-- 
2.17.2

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 06/16] Reset terminal styles
  2018-11-28  0:16 [PATCH 00/16] Add styling to the gdb CLI and TUI Tom Tromey
@ 2018-11-28  0:14 ` Tom Tromey
  2018-12-24  4:16   ` Joel Brobecker
  2018-11-28  0:14 ` [PATCH 10/16] Style the gdb welcome message Tom Tromey
                   ` (16 subsequent siblings)
  17 siblings, 1 reply; 99+ messages in thread
From: Tom Tromey @ 2018-11-28  0:14 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This adds a function that can be used to reset terminal styles,
regardless of what style the low-levle output routines currently think
is applied.

This is used to make "echo" and "printf" work properly when emitting
ANSI terminal escapes -- now gdb will reset the style at the end of
the command.

gdb/ChangeLog
2018-11-27  Tom Tromey  <tom@tromey.com>

	* utils.h (reset_terminal_style): Declare.
	* utils.c (can_emit_style_escape): New function.
	(set_output_style): Use it.
	(reset_terminal_style): New function.
	* printcmd.c (printf_command): Call reset_terminal_style.
	* cli/cli-cmds.c (echo_command): Call reset_terminal_style.
---
 gdb/ChangeLog      |  9 +++++++++
 gdb/cli/cli-cmds.c |  2 ++
 gdb/printcmd.c     |  2 ++
 gdb/utils.c        | 37 +++++++++++++++++++++++++++++++------
 gdb/utils.h        |  4 ++++
 5 files changed, 48 insertions(+), 6 deletions(-)

diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index 135f550b80..12ac74c7e9 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -689,6 +689,8 @@ echo_command (const char *text, int from_tty)
 	  printf_filtered ("%c", c);
       }
 
+  reset_terminal_style (gdb_stdout);
+
   /* Force this output to appear now.  */
   wrap_here ("");
   gdb_flush (gdb_stdout);
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index 8c999188d7..79c3d2d2ff 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -2609,6 +2609,8 @@ static void
 printf_command (const char *arg, int from_tty)
 {
   ui_printf (arg, gdb_stdout);
+  reset_terminal_style (gdb_stdout);
+  wrap_here ("");
   gdb_flush (gdb_stdout);
 }
 
diff --git a/gdb/utils.c b/gdb/utils.c
index 69c9e76576..85b0fb14e3 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -1444,25 +1444,50 @@ emit_style_escape (const ui_file_style &style)
   wrap_buffer.append (style.to_ansi ());
 }
 
-/* Set the current output style.  This will affect future uses of the
-   _filtered output functions.  */
+/* Return true if ANSI escapes can be used on STREAM.  */
 
-static void
-set_output_style (struct ui_file *stream, const ui_file_style &style)
+static bool
+can_emit_style_escape (struct ui_file *stream)
 {
   if (stream != gdb_stdout
       || !cli_styling
-      || style == desired_style
       || !ui_file_isatty (stream))
-    return;
+    return false;
   const char *term = getenv ("TERM");
   if (term == nullptr || !strcmp (term, "dumb"))
+    return false;
+  return true;
+}
+
+/* Set the current output style.  This will affect future uses of the
+   _filtered output functions.  */
+
+static void
+set_output_style (struct ui_file *stream, const ui_file_style &style)
+{
+  if (!can_emit_style_escape (stream)
+      || style == desired_style)
     return;
 
   desired_style = style;
   emit_style_escape (style);
 }
 
+/* See utils.h.  */
+
+void
+reset_terminal_style (struct ui_file *stream)
+{
+  if (can_emit_style_escape (stream))
+    {
+      /* Force the setting, regardless of what we think the setting
+	 might already be.  */
+      desired_style = ui_file_style ();
+      applied_style = desired_style;
+      wrap_buffer.append (desired_style.to_ansi ());
+    }
+}
+
 /* Wait, so the user can read what's on the screen.  Prompt the user
    to continue by pressing RETURN.  'q' is also provided because
    telling users what to do in the prompt is more user-friendly than
diff --git a/gdb/utils.h b/gdb/utils.h
index 9872a15fd7..1f09ec2d47 100644
--- a/gdb/utils.h
+++ b/gdb/utils.h
@@ -439,6 +439,10 @@ extern void fputs_styled (const char *linebuffer,
 			  const ui_file_style &style,
 			  struct ui_file *stream);
 
+/* Reset the terminal style to the default, if needed.  */
+
+extern void reset_terminal_style (struct ui_file *stream);
+
 /* Display the host ADDR on STREAM formatted as ``0x%x''.  */
 extern void gdb_print_host_address_1 (const void *addr, struct ui_file *stream);
 
-- 
2.17.2

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 11/16] Style the "Reading symbols" message
  2018-11-28  0:16 [PATCH 00/16] Add styling to the gdb CLI and TUI Tom Tromey
                   ` (13 preceding siblings ...)
  2018-11-28  0:16 ` [PATCH 16/16] Document the "set style" commands Tom Tromey
@ 2018-11-28  0:16 ` Tom Tromey
  2018-11-28  0:19 ` [PATCH 01/16] Change wrap buffering to use a std::string Tom Tromey
                   ` (2 subsequent siblings)
  17 siblings, 0 replies; 99+ messages in thread
From: Tom Tromey @ 2018-11-28  0:16 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

The "Reading symbols" message does not use ui-out (perhaps it
should?), so this styles it using the low-level API.

gdb/ChangeLog
2018-11-27  Tom Tromey  <tom@tromey.com>

	* symfile.c (symbol_file_add_with_addrs): Style file name.

gdb/testsuite/ChangeLog
2018-11-27  Tom Tromey  <tom@tromey.com>

	* gdb.base/style.exp: Add test for styling of "Reading symbols"
	message.
---
 gdb/ChangeLog                    | 4 ++++
 gdb/symfile.c                    | 7 ++++++-
 gdb/testsuite/ChangeLog          | 5 +++++
 gdb/testsuite/gdb.base/style.exp | 4 ++++
 4 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/gdb/symfile.c b/gdb/symfile.c
index 8ab6a25de7..b5d888ee2b 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -58,6 +58,7 @@
 #include "cli/cli-utils.h"
 #include "common/byte-vector.h"
 #include "selftest.h"
+#include "cli/cli-style.h"
 
 #include <sys/types.h>
 #include <fcntl.h>
@@ -1110,7 +1111,11 @@ symbol_file_add_with_addrs (bfd *abfd, const char *name,
       if (deprecated_pre_add_symbol_hook)
 	deprecated_pre_add_symbol_hook (name);
       else
-	printf_filtered (_("Reading symbols from %s...\n"), name);
+	{
+	  puts_filtered (_("Reading symbols from "));
+	  fputs_styled (name, file_name_style.style (), gdb_stdout);
+	  puts_filtered ("...\n");
+	}
     }
   syms_from_objfile (objfile, addrs, add_flags);
 
diff --git a/gdb/testsuite/gdb.base/style.exp b/gdb/testsuite/gdb.base/style.exp
index a5bdc2795f..a44d78f236 100644
--- a/gdb/testsuite/gdb.base/style.exp
+++ b/gdb/testsuite/gdb.base/style.exp
@@ -50,4 +50,8 @@ save_vars { env(TERM) } {
 
     gdb_test "" "\033\\\[35;1mGNU gdb.*\033\\\[m.*" \
 	"version is styled"
+
+    set quoted [string_to_regexp $binfile]
+    gdb_test "file $binfile" \
+	"Reading symbols from \033\\\[32m${quoted}\033\\\[m..." \
 }
-- 
2.17.2

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 13/16] Make ANSI terminal escape sequences work in TUI
  2018-11-28  0:16 [PATCH 00/16] Add styling to the gdb CLI and TUI Tom Tromey
                   ` (11 preceding siblings ...)
  2018-11-28  0:16 ` [PATCH 15/16] Highlight source code using GNU Source Highlight Tom Tromey
@ 2018-11-28  0:16 ` Tom Tromey
  2018-12-24  8:02   ` Joel Brobecker
  2018-12-28 19:42   ` Tom Tromey
  2018-11-28  0:16 ` [PATCH 16/16] Document the "set style" commands Tom Tromey
                   ` (4 subsequent siblings)
  17 siblings, 2 replies; 99+ messages in thread
From: Tom Tromey @ 2018-11-28  0:16 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

PR tui/14126 notes that ANSI terminal escape sequences don't affect
the colors shown in the TUI.  A simple way to see this is to try the
extended-prompt example from the gdb manual.

Curses does not pass escape sequences through to the terminal.
Instead, it replaces non-printable characters with a visible
representation, for example "^[" for the ESC character.

This patch fixes the problem by adding a simple ANSI terminal sequence
parser to gdb.  These sequences are decoded and those that are
recognized are turned into the appropriate curses calls.

The curses approach to color handling is unusual and so there are some
oddities in the implementation.

Standard curses has no notion of the default colors of the terminal.
So, if you set the foreground color, it is not possible to reset it --
you have to pick some other color.  ncurses provides an extension to
handle this, so this patch updates configure and uses it when
available.

Second, in curses, colors always come in pairs: you cannot set just
the foreground.  This patch handles this by tracking actually-used
pairs of colors and keeping a table of these for reuse.

Third, there are a limited number of such pairs available.  In this
patch, if you try to use too many color combinations, gdb will just
ignore some color changes.

Finally, in addition to limiting the number of color pairs, curses
also limits the number of colors.  This means that, when using
extended 8- or 24-bit color sequences, it may be possible to exhaust
the curses color table.

I am very sour on the curses design now.

I do not know how to write a test for this, so I did not.

gdb/ChangeLog
2018-11-27  Tom Tromey  <tom@tromey.com>

	PR tui/14126:
	* tui/tui.c (tui_enable): Call start_color and
	use_default_colors.
	* tui/tui-io.c (struct color_pair): New.
	(color_pair_map, last_color_pair, last_style): New globals.
	(tui_setup_io): Clean up color map when shutting down.
	(curses_colors): New constant.
	(get_color_pair, apply_ansi_escape): New functions.
	(tui_write): Rewrite.
	(tui_puts_internal): New function, from tui_puts.  Add "height"
	parameter.
	(tui_puts): Use tui_puts_internal.
	(tui_redisplay_readline): Use tui_puts_internal.
	(_initialize_tui_io): New function.
	(color_map): New globals.
	(get_color): New function.
	* configure.ac: Check for use_default_colors.
	* config.in, configure: Rebuild.
---
 gdb/ChangeLog    |  21 +++++
 gdb/config.in    |   3 +
 gdb/configure    |   2 +-
 gdb/configure.ac |   2 +-
 gdb/tui/tui-io.c | 232 +++++++++++++++++++++++++++++++++++++++++++----
 gdb/tui/tui.c    |   9 ++
 6 files changed, 251 insertions(+), 18 deletions(-)

diff --git a/gdb/config.in b/gdb/config.in
index deb9d4a996..760db6b320 100644
--- a/gdb/config.in
+++ b/gdb/config.in
@@ -543,6 +543,9 @@
 /* Define to 1 if you have the <unistd.h> header file. */
 #undef HAVE_UNISTD_H
 
+/* Define to 1 if you have the `use_default_colors' function. */
+#undef HAVE_USE_DEFAULT_COLORS
+
 /* Define to 1 if you have the `vfork' function. */
 #undef HAVE_VFORK
 
diff --git a/gdb/configure b/gdb/configure
index 7665ba6531..44df6ebcfb 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -13320,7 +13320,7 @@ for ac_func in getauxval getrusage getuid getgid \
 		sigaction sigprocmask sigsetmask socketpair \
 		ttrace wborder wresize setlocale iconvlist libiconvlist btowc \
 		setrlimit getrlimit posix_madvise waitpid \
-		ptrace64 sigaltstack setns
+		ptrace64 sigaltstack setns use_default_colors
 do :
   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
 ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
diff --git a/gdb/configure.ac b/gdb/configure.ac
index e1ea60660b..56cd0927bb 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -1359,7 +1359,7 @@ AC_CHECK_FUNCS([getauxval getrusage getuid getgid \
 		sigaction sigprocmask sigsetmask socketpair \
 		ttrace wborder wresize setlocale iconvlist libiconvlist btowc \
 		setrlimit getrlimit posix_madvise waitpid \
-		ptrace64 sigaltstack setns])
+		ptrace64 sigaltstack setns use_default_colors])
 AM_LANGINFO_CODESET
 GDB_AC_COMMON
 
diff --git a/gdb/tui/tui-io.c b/gdb/tui/tui-io.c
index 7823688522..b1099246dd 100644
--- a/gdb/tui/tui-io.c
+++ b/gdb/tui/tui-io.c
@@ -40,6 +40,7 @@
 #include "filestuff.h"
 #include "completer.h"
 #include "gdb_curses.h"
+#include <map>
 
 /* This redefines CTRL if it is not already defined, so it must come
    after terminal state releated include files like <term.h> and
@@ -188,17 +189,219 @@ tui_putc (char c)
   update_cmdwin_start_line ();
 }
 
+/* This maps colors to their corresponding color index.  */
+
+static std::map<ui_file_style::color, int> color_map;
+
+/* This holds a pair of colors and is used to track the mapping
+   between a color pair index and the actual colors.  */
+
+struct color_pair
+{
+  int fg;
+  int bg;
+
+  bool operator< (const color_pair &o) const
+  {
+    return fg < o.fg || (fg == o.fg && bg < o.bg);
+  }
+};
+
+/* This maps pairs of colors to their corresponding color pair
+   index.  */
+
+static std::map<color_pair, int> color_pair_map;
+
+/* This is indexed by ANSI color offset from the base color, and holds
+   the corresponding curses color constant.  */
+
+static const int curses_colors[] = {
+  COLOR_BLACK,
+  COLOR_RED,
+  COLOR_GREEN,
+  COLOR_YELLOW,
+  COLOR_BLUE,
+  COLOR_MAGENTA,
+  COLOR_CYAN,
+  COLOR_WHITE
+};
+
+/* Given a color, find its index.  */
+
+static bool
+get_color (const ui_file_style::color &color, int *result)
+{
+  if (color.is_none ())
+    *result = 1;
+  else if (color.is_basic ())
+    *result = curses_colors[color.get_value ()];
+  else
+    {
+      auto it = color_map.find (color);
+      if (it == color_map.end ())
+	{
+	  /* The first 8 colors are standard.  */
+	  int next = color_map.size () + 8;
+	  if (next >= COLORS)
+	    return false;
+	  uint8_t rgb[3];
+	  color.get_rgb (rgb);
+	  /* We store RGB as 0..255, but curses wants 0..1000.  */
+	  if (init_color (next, rgb[0] * 1000 / 255, rgb[1] * 1000 / 255,
+			  rgb[2] * 1000 / 255) == ERR)
+	    return false;
+	  color_map[color] = next;
+	  *result = next;
+	}
+      else
+	*result = it->second;
+    }
+  return true;
+}
+
+/* The most recently emitted color pair.  */
+
+static int last_color_pair = -1;
+
+/* The most recently applied style.  */
+
+static ui_file_style last_style;
+
+/* Given two colors, return their color pair index; making a new one
+   if necessary.  */
+
+static int
+get_color_pair (int fg, int bg)
+{
+  color_pair c = { fg, bg };
+  auto it = color_pair_map.find (c);
+  if (it == color_pair_map.end ())
+    {
+      /* Color pair 0 is our default color, so new colors start at
+	 1.  */
+      int next = color_pair_map.size () + 1;
+      /* Curses has a limited number of available color pairs.  Fall
+	 back to the default if we've used too many.  */
+      if (next >= COLOR_PAIRS)
+	return 0;
+      init_pair (next, fg, bg);
+      color_pair_map[c] = next;
+      return next;
+    }
+  return it->second;
+}
+
+/* Apply an ANSI escape sequence from BUF to W.  BUF must start with
+   the ESC character.  If BUF does not start with an ANSI escape,
+   return 0.  Otherwise, apply the sequence if it is recognized, or
+   simply ignore it if not.  In this case, the number of bytes read
+   from BUF is returned.  */
+
+static size_t
+apply_ansi_escape (WINDOW *w, const char *buf)
+{
+  ui_file_style style = last_style;
+  size_t n_read;
+
+  if (!style.parse (buf, &n_read))
+    return n_read;
+
+  /* Reset.  */
+  wattron (w, A_NORMAL);
+  wattroff (w, A_BOLD);
+  wattroff (w, A_DIM);
+  wattroff (w, A_REVERSE);
+  if (last_color_pair != -1)
+    wattroff (w, COLOR_PAIR (last_color_pair));
+  wattron (w, COLOR_PAIR (0));
+
+  const ui_file_style::color &fg = style.get_foreground ();
+  const ui_file_style::color &bg = style.get_background ();
+  if (!fg.is_none () || !bg.is_none ())
+    {
+      int fgi, bgi;
+      if (get_color (fg, &fgi) && get_color (bg, &bgi))
+	{
+	  int pair = get_color_pair (fgi, bgi);
+	  if (last_color_pair != -1)
+	    wattroff (w, COLOR_PAIR (last_color_pair));
+	  wattron (w, COLOR_PAIR (pair));
+	  last_color_pair = pair;
+	}
+    }
+
+  switch (style.get_intensity ())
+    {
+    case ui_file_style::NORMAL:
+      break;
+
+    case ui_file_style::BOLD:
+      wattron (w, A_BOLD);
+      break;
+
+    case ui_file_style::DIM:
+      wattron (w, A_DIM);
+      break;
+
+    default:
+      gdb_assert_not_reached ("invalid intensity");
+    }
+
+  if (style.is_reverse ())
+    wattron (w, A_REVERSE);
+
+  last_style = style;
+  return n_read;
+}
+
 /* Print LENGTH characters from the buffer pointed to by BUF to the
    curses command window.  The output is buffered.  It is up to the
    caller to refresh the screen if necessary.  */
 
 void
 tui_write (const char *buf, size_t length)
+{
+  /* We need this to be \0-terminated for the regexp matching.  */
+  std::string copy (buf, length);
+  tui_puts (copy.c_str ());
+}
+
+static void
+tui_puts_internal (const char *string, int *height)
 {
   WINDOW *w = TUI_CMD_WIN->generic.handle;
+  char c;
+  int prev_col = 0;
 
-  for (size_t i = 0; i < length; i++)
-    do_tui_putc (w, buf[i]);
+  while ((c = *string++) != 0)
+    {
+      if (c == '\1' || c == '\2')
+	{
+	  /* Ignore these, they are readline escape-marking
+	     sequences.  */
+	}
+      else
+	{
+	  if (c == '\033')
+	    {
+	      size_t bytes_read = apply_ansi_escape (w, string - 1);
+	      if (bytes_read > 0)
+		{
+		  string = string + bytes_read - 1;
+		  continue;
+		}
+	    }
+	  do_tui_putc (w, c);
+
+	  if (height != nullptr)
+	    {
+	      int col = getcurx (w);
+	      if (col <= prev_col)
+		++*height;
+	      prev_col = col;
+	    }
+	}
+    }
   update_cmdwin_start_line ();
 }
 
@@ -209,12 +412,7 @@ tui_write (const char *buf, size_t length)
 void
 tui_puts (const char *string)
 {
-  WINDOW *w = TUI_CMD_WIN->generic.handle;
-  char c;
-
-  while ((c = *string++) != 0)
-    do_tui_putc (w, c);
-  update_cmdwin_start_line ();
+  tui_puts_internal (string, nullptr);
 }
 
 /* Readline callback.
@@ -254,14 +452,10 @@ tui_redisplay_readline (void)
   wmove (w, start_line, 0);
   prev_col = 0;
   height = 1;
-  for (in = 0; prompt && prompt[in]; in++)
-    {
-      waddch (w, prompt[in]);
-      col = getcurx (w);
-      if (col <= prev_col)
-        height++;
-      prev_col = col;
-    }
+  if (prompt != nullptr)
+    tui_puts_internal (prompt, &height);
+
+  prev_col = getcurx (w);
   for (in = 0; in <= rl_end; in++)
     {
       unsigned char c;
@@ -537,6 +731,12 @@ tui_setup_io (int mode)
 
       /* Save tty for SIGCONT.  */
       savetty ();
+
+      /* Clean up color information.  */
+      last_color_pair = -1;
+      last_style = ui_file_style ();
+      color_map.clear ();
+      color_pair_map.clear ();
     }
 }
 
diff --git a/gdb/tui/tui.c b/gdb/tui/tui.c
index 50cad22f16..2299824d97 100644
--- a/gdb/tui/tui.c
+++ b/gdb/tui/tui.c
@@ -437,6 +437,15 @@ tui_enable (void)
 		 gdb_getenv_term ());
 	}
       w = stdscr;
+      if (has_colors ())
+	{
+#ifdef HAVE_USE_DEFAULT_COLORS
+	  /* Ncurses extension to help with resetting to the default
+	     color.  */
+	  use_default_colors ();
+#endif
+	  start_color ();
+	}
 
       /* Check required terminal capabilities.  The MinGW port of
 	 ncurses does have them, but doesn't expose them through "cup".  */
-- 
2.17.2

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 07/16] Style variable names
  2018-11-28  0:16 [PATCH 00/16] Add styling to the gdb CLI and TUI Tom Tromey
                   ` (9 preceding siblings ...)
  2018-11-28  0:16 ` [PATCH 04/16] Change gdb test suite's TERM setting Tom Tromey
@ 2018-11-28  0:16 ` Tom Tromey
  2018-11-28  0:16 ` [PATCH 15/16] Highlight source code using GNU Source Highlight Tom Tromey
                   ` (6 subsequent siblings)
  17 siblings, 0 replies; 99+ messages in thread
From: Tom Tromey @ 2018-11-28  0:16 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This adds style support for variable names.  For the time being, this
is only done in backtraces, not in ptype or print; those places do not
use ui-out and so would need ad hoc changes.

This also adds styling to the names printed for local variables in
"backtrace full".  This code does not use ui-out, so the styling is
done using the low-level API.

gdb/ChangeLog
2018-11-27  Tom Tromey  <tom@tromey.com>

	* ui-out.h (enum class ui_out_style_kind) <VARIABLE>: New global.
	* stack.c (print_frame_arg): Style name.
	* printcmd.c (print_variable_and_value): Style variable name.
	* cli/cli-style.h (variable_name_style): Declare.
	* cli/cli-style.c (variable_name_style): New global.
	(_initialize_cli_style): Update.
	* cli-out.c (cli_ui_out::do_field_string): Update.

gdb/testsuite/ChangeLog
2018-11-27  Tom Tromey  <tom@tromey.com>

	* gdb.base/style.exp: Add test for variable names.
---
 gdb/ChangeLog                    | 10 ++++++++++
 gdb/cli-out.c                    |  3 +++
 gdb/cli/cli-style.c              | 11 +++++++++++
 gdb/cli/cli-style.h              |  3 +++
 gdb/printcmd.c                   |  6 +++++-
 gdb/stack.c                      |  2 +-
 gdb/testsuite/ChangeLog          |  4 ++++
 gdb/testsuite/gdb.base/style.exp |  3 ++-
 gdb/ui-out.h                     |  4 +++-
 9 files changed, 42 insertions(+), 4 deletions(-)

diff --git a/gdb/cli-out.c b/gdb/cli-out.c
index 4b5fc17390..e1005e1b35 100644
--- a/gdb/cli-out.c
+++ b/gdb/cli-out.c
@@ -173,6 +173,9 @@ cli_ui_out::do_field_string (int fldno, int width, ui_align align,
 	case ui_out_style_kind::FUNCTION:
 	  fstyle = function_name_style.style ();
 	  break;
+	case ui_out_style_kind::VARIABLE:
+	  fstyle = variable_name_style.style ();
+	  break;
 	default:
 	  gdb_assert_not_reached ("missing case");
 	}
diff --git a/gdb/cli/cli-style.c b/gdb/cli/cli-style.c
index de2866ce75..fd4a4fc477 100644
--- a/gdb/cli/cli-style.c
+++ b/gdb/cli/cli-style.c
@@ -62,6 +62,10 @@ cli_style_option function_name_style (ui_file_style::YELLOW);
 
 /* See cli-style.h.  */
 
+cli_style_option variable_name_style (ui_file_style::CYAN);
+
+/* See cli-style.h.  */
+
 cli_style_option::cli_style_option (ui_file_style::simple_color fg)
   : m_foreground (cli_colors[fg - ui_file_style::NONE]),
     m_background (cli_colors[0]),
@@ -254,4 +258,11 @@ Configure function name colors and display intensity"),
 					    "style function",
 					    &style_set_list,
 					    &style_show_list);
+  variable_name_style.add_setshow_commands ("variable", no_class,
+					    "style variable",
+					    _("\
+Variable name display styling\n\
+Configure variable name colors and display intensity"),
+					    &style_set_list,
+					    &style_show_list);
 }
diff --git a/gdb/cli/cli-style.h b/gdb/cli/cli-style.h
index 36845b2581..3d5142e3de 100644
--- a/gdb/cli/cli-style.h
+++ b/gdb/cli/cli-style.h
@@ -83,6 +83,9 @@ extern cli_style_option file_name_style;
 /* The function name style.  */
 extern cli_style_option function_name_style;
 
+/* The variable name style.  */
+extern cli_style_option variable_name_style;
+
 /* True if styling is enabled.  */
 extern int cli_styling;
 
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index 79c3d2d2ff..dd1626455b 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -46,6 +46,7 @@
 #include "arch-utils.h"
 #include "cli/cli-utils.h"
 #include "cli/cli-script.h"
+#include "cli/cli-style.h"
 #include "format.h"
 #include "source.h"
 #include "common/byte-vector.h"
@@ -2156,7 +2157,10 @@ print_variable_and_value (const char *name, struct symbol *var,
   if (!name)
     name = SYMBOL_PRINT_NAME (var);
 
-  fprintf_filtered (stream, "%s%s = ", n_spaces (2 * indent), name);
+  fputs_filtered (n_spaces (2 * indent), stream);
+  fputs_styled (name, variable_name_style.style (), stream);
+  fputs_filtered (" = ", stream);
+
   TRY
     {
       struct value *val;
diff --git a/gdb/stack.c b/gdb/stack.c
index a718bf8901..930d7d0b1e 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -256,7 +256,7 @@ print_frame_arg (const struct frame_arg *arg)
   if (arg->entry_kind == print_entry_values_only
       || arg->entry_kind == print_entry_values_compact)
     stb.puts ("@entry");
-  uiout->field_stream ("name", stb);
+  uiout->field_stream ("name", stb, ui_out_style_kind::VARIABLE);
   annotate_arg_name_end ();
   uiout->text ("=");
 
diff --git a/gdb/testsuite/gdb.base/style.exp b/gdb/testsuite/gdb.base/style.exp
index 859e50352f..1ab9d68431 100644
--- a/gdb/testsuite/gdb.base/style.exp
+++ b/gdb/testsuite/gdb.base/style.exp
@@ -34,8 +34,9 @@ save_vars { env(TERM) } {
     
     set main_expr "\033\\\[33mmain\033\\\[m"
     set file_expr "\033\\\[32m.*style\\.c\033\\\[m:\[0-9\]"
+    set arg_expr "\033\\\[36marg.\033\\\[m"
 
     gdb_test "frame" \
-	"$main_expr.*$file_expr.*"
+	"$main_expr.*$arg_expr.*$arg_expr.*$file_expr.*"
     gdb_test "info breakpoints" "$main_expr at $file_expr.*"
 }
diff --git a/gdb/ui-out.h b/gdb/ui-out.h
index 8604105c09..93be9a91b2 100644
--- a/gdb/ui-out.h
+++ b/gdb/ui-out.h
@@ -75,7 +75,9 @@ enum class ui_out_style_kind
   /* File name.  */
   FILE,
   /* Function name.  */
-  FUNCTION
+  FUNCTION,
+  /* Variable name.  */
+  VARIABLE
 };
 
 class ui_out
-- 
2.17.2

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 08/16] Style locations when setting a breakpoint
  2018-11-28  0:16 [PATCH 00/16] Add styling to the gdb CLI and TUI Tom Tromey
                   ` (7 preceding siblings ...)
  2018-11-28  0:14 ` [PATCH 12/16] Style addresses Tom Tromey
@ 2018-11-28  0:16 ` Tom Tromey
  2018-11-28  0:16 ` [PATCH 04/16] Change gdb test suite's TERM setting Tom Tromey
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 99+ messages in thread
From: Tom Tromey @ 2018-11-28  0:16 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

say_where does not use ui-out, so function and file names printed by
it were not styled.  This patch changes say_where to use the low-level
style code directly.

gdb/ChangeLog
2018-11-27  Tom Tromey  <tom@tromey.com>

	* breakpoint.c (say_where): Style file name.

gdb/testsuite/ChangeLog
2018-11-27  Tom Tromey  <tom@tromey.com>

	* gdb.base/style.exp: Add test for breakpoint setting.
---
 gdb/ChangeLog                    |  4 ++++
 gdb/breakpoint.c                 | 12 +++++++++---
 gdb/testsuite/ChangeLog          |  4 ++++
 gdb/testsuite/gdb.base/style.exp |  5 ++++-
 4 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 53763e0254..b99b0fb27c 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -68,6 +68,7 @@
 #include "format.h"
 #include "thread-fsm.h"
 #include "tid-parse.h"
+#include "cli/cli-style.h"
 
 /* readline include files */
 #include "readline/readline.h"
@@ -12195,9 +12196,14 @@ say_where (struct breakpoint *b)
 	  /* If there is a single location, we can print the location
 	     more nicely.  */
 	  if (b->loc->next == NULL)
-	    printf_filtered (": file %s, line %d.",
-			     symtab_to_filename_for_display (b->loc->symtab),
-			     b->loc->line_number);
+	    {
+	      puts_filtered (": file ");
+	      fputs_styled (symtab_to_filename_for_display (b->loc->symtab),
+			    file_name_style.style (),
+			    gdb_stdout);
+	      printf_filtered (", line %d.",
+			       b->loc->line_number);
+	    }
 	  else
 	    /* This is not ideal, but each location may have a
 	       different file name, and this at least reflects the
diff --git a/gdb/testsuite/gdb.base/style.exp b/gdb/testsuite/gdb.base/style.exp
index 1ab9d68431..df73e25a16 100644
--- a/gdb/testsuite/gdb.base/style.exp
+++ b/gdb/testsuite/gdb.base/style.exp
@@ -33,10 +33,13 @@ save_vars { env(TERM) } {
     gdb_test_no_output "set style enabled on"
     
     set main_expr "\033\\\[33mmain\033\\\[m"
-    set file_expr "\033\\\[32m.*style\\.c\033\\\[m:\[0-9\]"
+    set base_file_expr "\033\\\[32m.*style\\.c\033\\\[m"
+    set file_expr "$base_file_expr:\[0-9\]"
     set arg_expr "\033\\\[36marg.\033\\\[m"
 
     gdb_test "frame" \
 	"$main_expr.*$arg_expr.*$arg_expr.*$file_expr.*"
     gdb_test "info breakpoints" "$main_expr at $file_expr.*"
+
+    gdb_test "break main" "file $base_file_expr.*"
 }
-- 
2.17.2

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 15/16] Highlight source code using GNU Source Highlight
  2018-11-28  0:16 [PATCH 00/16] Add styling to the gdb CLI and TUI Tom Tromey
                   ` (10 preceding siblings ...)
  2018-11-28  0:16 ` [PATCH 07/16] Style variable names Tom Tromey
@ 2018-11-28  0:16 ` Tom Tromey
  2019-11-16  0:58   ` Andrew Pinski
  2018-11-28  0:16 ` [PATCH 13/16] Make ANSI terminal escape sequences work in TUI Tom Tromey
                   ` (5 subsequent siblings)
  17 siblings, 1 reply; 99+ messages in thread
From: Tom Tromey @ 2018-11-28  0:16 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This changes gdb to highlight source using GNU Source Highlight, if it
is available.

This affects the output of the "list" command and also the TUI source
window.

No new test because I didn't see a way to make it work when Source
Highlight is not found.

gdb/ChangeLog
2018-11-27  Tom Tromey  <tom@tromey.com>

	* utils.h (can_emit_style_escape): Declare.
	* utils.c (can_emit_style_escape): No longer static.
	* cli/cli-style.c (set_style_enabled): New function.
	(_initialize_cli_style): Use it.
	* tui/tui-winsource.c (tui_show_source_line): Use tui_puts.
	(tui_alloc_source_buffer): Change how source lines are allocated.
	* tui/tui-source.c (copy_source_line): New function.
	(tui_set_source_content): Use source cache.
	* tui/tui-io.h (tui_puts): Update.
	* tui/tui-io.c (tui_puts_internal): Add window parameter.
	(tui_puts): Likewise.
	(tui_redisplay_readline): Update.
	* tui/tui-data.c (free_content_elements): Change how source window
	contents are freed.
	* source.c (forget_cached_source_info): Clear the source cache.
	(print_source_lines_base): Use the source cache.
	* source-cache.h: New file.
	* source-cache.c: New file.
	* configure.ac: Check for GNU Source Highlight library.
	* configure: Update.
	* config.in: Update.
	* Makefile.in (SRCHIGH_LIBS, SRCHIGH_CFLAGS): New variables.
	(INTERNAL_CFLAGS_BASE): Add SRCHIGH_CFLAGS.
	(CLIBS): Add SRCHIGH_LIBS.
	(COMMON_SFILES): Add source-cache.c.
	(HFILES_NO_SRCDIR): Add source-cache.h.
---
 gdb/ChangeLog           |  29 ++++
 gdb/Makefile.in         |  12 +-
 gdb/cli/cli-style.c     |   9 +-
 gdb/config.in           |   3 +
 gdb/configure           |  30 ++++
 gdb/configure.ac        |  23 +++
 gdb/source-cache.c      | 209 +++++++++++++++++++++++++++
 gdb/source-cache.h      |  79 +++++++++++
 gdb/source.c            |  38 ++---
 gdb/tui/tui-data.c      |   5 +-
 gdb/tui/tui-io.c        |  11 +-
 gdb/tui/tui-io.h        |   4 +-
 gdb/tui/tui-source.c    | 302 +++++++++++++++++++---------------------
 gdb/tui/tui-winsource.c |  17 +--
 gdb/utils.c             |   4 +-
 gdb/utils.h             |   4 +
 16 files changed, 576 insertions(+), 203 deletions(-)
 create mode 100644 gdb/source-cache.c
 create mode 100644 gdb/source-cache.h

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 54baf96ea3..50d429d792 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -194,6 +194,10 @@ LIBIPT = @LIBIPT@
 # Where is libmpfr?  This will be empty if libmpfr was not available.
 LIBMPFR = @LIBMPFR@
 
+# GNU source highlight library.
+SRCHIGH_LIBS = @SRCHIGH_LIBS@
+SRCHIGH_CFLAGS = @SRCHIGH_CFLAGS@
+
 WARN_CFLAGS = @WARN_CFLAGS@
 WERROR_CFLAGS = @WERROR_CFLAGS@
 GDB_WARN_CFLAGS = $(WARN_CFLAGS)
@@ -565,7 +569,8 @@ INTERNAL_CFLAGS_BASE = \
 	$(CXXFLAGS) $(GLOBAL_CFLAGS) $(PROFILE_CFLAGS) \
 	$(GDB_CFLAGS) $(OPCODES_CFLAGS) $(READLINE_CFLAGS) $(ZLIBINC) \
 	$(BFD_CFLAGS) $(INCLUDE_CFLAGS) $(LIBDECNUMBER_CFLAGS) \
-	$(INTL_CFLAGS) $(INCGNU) $(ENABLE_CFLAGS) $(INTERNAL_CPPFLAGS)
+	$(INTL_CFLAGS) $(INCGNU) $(ENABLE_CFLAGS) $(INTERNAL_CPPFLAGS) \
+	$(SRCHIGH_CFLAGS)
 INTERNAL_WARN_CFLAGS = $(INTERNAL_CFLAGS_BASE) $(GDB_WARN_CFLAGS)
 INTERNAL_CFLAGS = $(INTERNAL_WARN_CFLAGS) $(GDB_WERROR_CFLAGS)
 
@@ -591,7 +596,8 @@ CLIBS = $(SIM) $(READLINE) $(OPCODES) $(BFD) $(ZLIB) $(INTL) $(LIBIBERTY) $(LIBD
 	$(XM_CLIBS) $(GDBTKLIBS) \
 	@LIBS@ @GUILE_LIBS@ @PYTHON_LIBS@ \
 	$(LIBEXPAT) $(LIBLZMA) $(LIBBABELTRACE) $(LIBIPT) \
-	$(LIBIBERTY) $(WIN32LIBS) $(LIBGNU) $(LIBICONV) $(LIBMPFR)
+	$(LIBIBERTY) $(WIN32LIBS) $(LIBGNU) $(LIBICONV) $(LIBMPFR) \
+	$(SRCHIGH_LIBS)
 CDEPS = $(NAT_CDEPS) $(SIM) $(BFD) $(READLINE_DEPS) \
 	$(OPCODES) $(INTL_DEPS) $(LIBIBERTY) $(CONFIG_DEPS) $(LIBGNU)
 
@@ -1101,6 +1107,7 @@ COMMON_SFILES = \
 	solib.c \
 	solib-target.c \
 	source.c \
+	source-cache.c \
 	stabsread.c \
 	stack.c \
 	std-regs.c \
@@ -1376,6 +1383,7 @@ HFILES_NO_SRCDIR = \
 	solib-target.h \
 	solist.h \
 	source.h \
+	source-cache.h \
 	sparc-nat.h \
 	sparc-ravenscar-thread.h \
 	sparc-tdep.h \
diff --git a/gdb/cli/cli-style.c b/gdb/cli/cli-style.c
index 74e3958eb8..16415e0f88 100644
--- a/gdb/cli/cli-style.c
+++ b/gdb/cli/cli-style.c
@@ -20,6 +20,7 @@
 #include "defs.h"
 #include "cli/cli-cmds.h"
 #include "cli/cli-style.h"
+#include "source-cache.h"
 
 /* True if styling is enabled.  */
 
@@ -216,6 +217,12 @@ show_style (const char *arg, int from_tty)
 {
 }
 
+static void
+set_style_enabled  (const char *args, int from_tty, struct cmd_list_element *c)
+{
+  g_source_cache.clear ();
+}
+
 static void
 show_style_enabled (struct ui_file *file, int from_tty,
 		    struct cmd_list_element *c, const char *value)
@@ -245,7 +252,7 @@ Configure various style-related variables, such as colors"),
 Set whether CLI styling is enabled."), _("\
 Show whether CLI is enabled."), _("\
 If enabled, output to the terminal is styled."),
-			   NULL, show_style_enabled,
+			   set_style_enabled, show_style_enabled,
 			   &style_set_list, &style_show_list);
 
   file_name_style.add_setshow_commands ("filename", no_class,
diff --git a/gdb/config.in b/gdb/config.in
index 760db6b320..ea907d2b56 100644
--- a/gdb/config.in
+++ b/gdb/config.in
@@ -426,6 +426,9 @@
 /* Define to 1 if the system has the type `socklen_t'. */
 #undef HAVE_SOCKLEN_T
 
+/* Define to 1 if the source-highlight library is available */
+#undef HAVE_SOURCE_HIGHLIGHT
+
 /* Define to 1 if you have the <stdint.h> header file. */
 #undef HAVE_STDINT_H
 
diff --git a/gdb/configure b/gdb/configure
index 44df6ebcfb..811664ed40 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -701,6 +701,8 @@ ALLOCA
 LTLIBIPT
 LIBIPT
 HAVE_LIBIPT
+SRCHIGH_CFLAGS
+SRCHIGH_LIBS
 HAVE_GUILE_FALSE
 HAVE_GUILE_TRUE
 GUILE_LIBS
@@ -11469,6 +11471,34 @@ else
 fi
 
 
+# ---------------------------- #
+# Check for source highlight.  #
+# ---------------------------- #
+
+SRCHIGH_LIBS=
+SRCHIGH_CFLAGS=
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for source highlight" >&5
+$as_echo_n "checking for source highlight... " >&6; }
+if test "${pkg_config_prog_path}" = "missing"; then
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no - pkg-config not found" >&5
+$as_echo "no - pkg-config not found" >&6; }
+else
+   if ${pkg_config_prog_path} --exists source-highlight; then
+      SRCHIGH_CFLAGS=`${pkg_config_prog_path} --cflags source-highlight`
+      SRCHIGH_LIBS=`${pkg_config_prog_path} --libs source-highlight`
+
+$as_echo "#define HAVE_SOURCE_HIGHLIGHT 1" >>confdefs.h
+
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+   else
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+   fi
+fi
+
+
+
 # --------------------- #
 # Check for libmcheck.  #
 # --------------------- #
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 56cd0927bb..7d2d39b710 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -1226,6 +1226,29 @@ AC_SUBST(GUILE_CPPFLAGS)
 AC_SUBST(GUILE_LIBS)
 AM_CONDITIONAL(HAVE_GUILE, test "${have_libguile}" != no)
 
+# ---------------------------- #
+# Check for source highlight.  #
+# ---------------------------- #
+
+SRCHIGH_LIBS=
+SRCHIGH_CFLAGS=
+AC_MSG_CHECKING([for the source-highlight library])
+if test "${pkg_config_prog_path}" = "missing"; then
+   AC_MSG_RESULT([no - pkg-config not found])
+else
+   if ${pkg_config_prog_path} --exists source-highlight; then
+      SRCHIGH_CFLAGS=`${pkg_config_prog_path} --cflags source-highlight`
+      SRCHIGH_LIBS=`${pkg_config_prog_path} --libs source-highlight`
+      AC_DEFINE([HAVE_SOURCE_HIGHLIGHT], 1,
+                [Define to 1 if the source-highlight library is available])
+      AC_MSG_RESULT([yes])
+   else
+      AC_MSG_RESULT([no])
+   fi
+fi
+AC_SUBST(SRCHIGH_LIBS)
+AC_SUBST(SRCHIGH_CFLAGS)
+
 # --------------------- #
 # Check for libmcheck.  #
 # --------------------- #
diff --git a/gdb/source-cache.c b/gdb/source-cache.c
new file mode 100644
index 0000000000..56851806e4
--- /dev/null
+++ b/gdb/source-cache.c
@@ -0,0 +1,209 @@
+/* Cache of styled source file text
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "source-cache.h"
+#include "common/scoped_fd.h"
+#include "source.h"
+#include "cli/cli-style.h"
+
+#ifdef HAVE_SOURCE_HIGHLIGHT
+#include <fstream>
+#include <sstream>
+#include <srchilite/sourcehighlight.h>
+#include <srchilite/langmap.h>
+#endif
+
+/* The number of source files we'll cache.  */
+
+#define MAX_ENTRIES 5
+
+/* See source-cache.h.  */
+
+source_cache g_source_cache;
+
+/* See source-cache.h.  */
+
+bool
+source_cache::get_plain_source_lines (struct symtab *s, int first_line,
+				      int last_line, std::string *lines)
+{
+  scoped_fd desc (open_source_file (s));
+  if (desc.get () < 0)
+    return false;
+
+  if (s->line_charpos == 0)
+    find_source_lines (s, desc.get ());
+
+  if (first_line < 1 || first_line > s->nlines || last_line < 1)
+    return false;
+
+  if (lseek (desc.get (), s->line_charpos[first_line - 1], SEEK_SET) < 0)
+    perror_with_name (symtab_to_filename_for_display (s));
+
+  int last_charpos;
+  if (last_line >= s->nlines)
+    {
+      struct stat st;
+
+      if (fstat (desc.get (), &st) < 0)
+	perror_with_name (symtab_to_filename_for_display (s));
+      /* We could cache this in line_charpos... */
+      last_charpos = st.st_size;
+    }
+  else
+    last_charpos = s->line_charpos[last_line];
+
+  lines->resize (last_charpos - s->line_charpos[first_line - 1]);
+  if (myread (desc.get (), &(*lines)[0], lines->size ()) < 0)
+    perror_with_name (symtab_to_filename_for_display (s));
+
+  return true;
+}
+
+/* See source-cache.h.  */
+
+bool
+source_cache::extract_lines (const struct source_text &text, int first_line,
+			     int last_line, std::string *lines)
+{
+  int lineno = 1;
+  std::string::size_type pos = 0;
+  std::string::size_type first_pos = std::string::npos;
+
+  while (pos != std::string::npos && lineno <= last_line)
+    {
+      std::string::size_type new_pos = text.contents.find ('\n', pos);
+
+      if (lineno == first_line)
+	first_pos = pos;
+
+      pos = new_pos;
+      if (lineno == last_line || pos == std::string::npos)
+	{
+	  if (pos == std::string::npos)
+	    pos = text.contents.size ();
+	  *lines = text.contents.substr (first_pos, pos - first_pos);
+	  return true;
+	}
+      ++lineno;
+      ++pos;
+    }
+
+  return false;
+}
+
+/* Return the Source Highlight language name, given a gdb language
+   LANG.  Returns NULL if the language is not known.  */
+
+static const char *
+get_language_name (enum language lang)
+{
+  switch (lang)
+    {
+    case language_c:
+    case language_objc:
+      return "c.lang";
+
+    case language_cplus:
+      return "cpp.lang";
+
+    case language_d:
+      return "d.lang";
+
+    case language_go:
+      return "go.lang";
+
+    case language_fortran:
+      return "fortran.lang";
+
+    case language_m2:
+      /* Not handled by Source Highlight.  */
+      break;
+
+    case language_asm:
+      return "asm.lang";
+
+    case language_pascal:
+      return "pascal.lang";
+
+    case language_opencl:
+      /* Not handled by Source Highlight.  */
+      break;
+
+    case language_rust:
+      /* Not handled by Source Highlight.  */
+      break;
+
+    case language_ada:
+      return "ada.lang";
+
+    default:
+      break;
+    }
+
+  return nullptr;
+}
+
+/* See source-cache.h.  */
+
+bool
+source_cache::get_source_lines (struct symtab *s, int first_line,
+				int last_line, std::string *lines)
+{
+  if (first_line < 1 || last_line < 1 || first_line > last_line)
+    return false;
+
+#ifdef HAVE_SOURCE_HIGHLIGHT
+  if (can_emit_style_escape (gdb_stdout))
+    {
+      const char *fullname = symtab_to_fullname (s);
+
+      for (const auto &item : m_source_map)
+	{
+	  if (item.fullname == fullname)
+	    return extract_lines (item, first_line, last_line, lines);
+	}
+
+      const char *lang_name = get_language_name (SYMTAB_LANGUAGE (s));
+      if (lang_name != nullptr)
+	{
+	  std::ifstream input (fullname);
+	  if (input.is_open ())
+	    {
+	      srchilite::SourceHighlight highlighter ("esc.outlang");
+	      highlighter.setStyleFile("esc.style");
+
+	      std::ostringstream output;
+	      highlighter.highlight (input, output, lang_name, fullname);
+
+	      source_text result = { fullname, output.str () };
+	      m_source_map.push_back (std::move (result));
+
+	      if (m_source_map.size () > MAX_ENTRIES)
+		m_source_map.erase (m_source_map.begin ());
+
+	      return extract_lines (m_source_map.back (), first_line,
+				    last_line, lines);
+	    }
+	}
+    }
+#endif /* HAVE_SOURCE_HIGHLIGHT */
+
+  return get_plain_source_lines (s, first_line, last_line, lines);
+}
diff --git a/gdb/source-cache.h b/gdb/source-cache.h
new file mode 100644
index 0000000000..2236d38846
--- /dev/null
+++ b/gdb/source-cache.h
@@ -0,0 +1,79 @@
+/* Cache of styled source file text
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef SOURCE_CACHE_H
+#define SOURCE_CACHE_H
+
+/* This caches highlighted source text, keyed by the source file's
+   full name.  A size-limited LRU cache is used.
+
+   Highlighting depends on the GNU Source Highlight library.  When not
+   available, this cache will fall back on reading plain text from the
+   appropriate file.  */
+class source_cache
+{
+public:
+
+  source_cache ()
+  {
+  }
+
+  /* Get the source text for the source file in symtab S.  FIRST_LINE
+     and LAST_LINE are the first and last lines to return; line
+     numbers are 1-based.  If the file cannot be read, false is
+     returned.  Otherwise, LINES is set to the desired text.  The
+     returned text may include ANSI terminal escapes.  */
+  bool get_source_lines (struct symtab *s, int first_line,
+			 int last_line, std::string *lines);
+
+  /* Remove all the items from the source cache.  */
+  void clear ()
+  {
+    m_source_map.clear ();
+  }
+
+private:
+
+  /* One element in the cache.  */
+  struct source_text
+  {
+    /* The full name of the file.  */
+    std::string fullname;
+    /* The contents of the file.  */
+    std::string contents;
+  };
+
+  /* A helper function for get_source_lines that is used when the
+     source lines are not highlighted.  The arguments and return value
+     are as for get_source_lines.  */
+  bool get_plain_source_lines (struct symtab *s, int first_line,
+			       int last_line, std::string *lines);
+  /* A helper function for get_plain_source_lines that extracts the
+     desired source lines from TEXT, putting them into LINES.  The
+     arguments and return value are as for get_source_lines.  */
+  bool extract_lines (const struct source_text &text, int first_line,
+		      int last_line, std::string *lines);
+
+  /* The contents of the cache.  */
+  std::vector<source_text> m_source_map;
+};
+
+/* The global source cache.  */
+extern source_cache g_source_cache;
+
+#endif /* SOURCE_CACHE_H */
diff --git a/gdb/source.c b/gdb/source.c
index 7552496f78..aa7eb8a6d4 100644
--- a/gdb/source.c
+++ b/gdb/source.c
@@ -45,6 +45,7 @@
 #include "common/scoped_fd.h"
 #include <algorithm>
 #include "common/pathstuff.h"
+#include "source-cache.h"
 
 #define OPEN_MODE (O_RDONLY | O_BINARY)
 #define FDOPEN_MODE FOPEN_RB
@@ -393,6 +394,7 @@ forget_cached_source_info (void)
       forget_cached_source_info_for_objfile (objfile);
     }
 
+  g_source_cache.clear ();
   last_source_visited = NULL;
 }
 
@@ -1344,25 +1346,18 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
 
   last_source_error = 0;
 
-  if (s->line_charpos == 0)
-    find_source_lines (s, desc.get ());
-
-  if (line < 1 || line > s->nlines)
+  std::string lines;
+  if (!g_source_cache.get_source_lines (s, line, stopline - 1, &lines))
     error (_("Line number %d out of range; %s has %d lines."),
 	   line, symtab_to_filename_for_display (s), s->nlines);
 
-  if (lseek (desc.get (), s->line_charpos[line - 1], 0) < 0)
-    perror_with_name (symtab_to_filename_for_display (s));
-
-  gdb_file_up stream = desc.to_file (FDOPEN_MODE);
-  clearerr (stream.get ());
-
+  const char *iter = lines.c_str ();
   while (nlines-- > 0)
     {
       char buf[20];
 
-      c = fgetc (stream.get ());
-      if (c == EOF)
+      c = *iter++;
+      if (c == '\0')
 	break;
       last_line_listed = current_source_line;
       if (flags & PRINT_SOURCE_LINES_FILENAME)
@@ -1374,7 +1369,7 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
       uiout->text (buf);
       do
 	{
-	  if (c < 040 && c != '\t' && c != '\n' && c != '\r')
+	  if (c < 040 && c != '\t' && c != '\n' && c != '\r' && c != '\033')
 	    {
 	      xsnprintf (buf, sizeof (buf), "^%c", c + 0100);
 	      uiout->text (buf);
@@ -1384,12 +1379,13 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
 	  else if (c == '\r')
 	    {
 	      /* Skip a \r character, but only before a \n.  */
-	      int c1 = fgetc (stream.get ());
-
-	      if (c1 != '\n')
+	      if (iter[1] == '\n')
+		{
+		  ++iter;
+		  c = '\n';
+		}
+	      else
 		printf_filtered ("^%c", c + 0100);
-	      if (c1 != EOF)
-		ungetc (c1, stream.get ());
 	    }
 	  else
 	    {
@@ -1397,8 +1393,12 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
 	      uiout->text (buf);
 	    }
 	}
-      while (c != '\n' && (c = fgetc (stream.get ())) >= 0);
+      while (c != '\n' && (c = *iter++) != '\0');
+      if (c == '\0')
+	break;
     }
+  if (lines.back () != '\n')
+    uiout->text ("\n");
 }
 \f
 /* Show source lines from the file of symtab S, starting with line
diff --git a/gdb/tui/tui-data.c b/gdb/tui/tui-data.c
index 4391f0d100..2b95f197fd 100644
--- a/gdb/tui/tui-data.c
+++ b/gdb/tui/tui-data.c
@@ -838,7 +838,7 @@ free_content_elements (tui_win_content content,
     {
       int i;
 
-      if (type == SRC_WIN || type == DISASSEM_WIN)
+      if (type == DISASSEM_WIN)
 	{
 	  /* Free whole source block.  */
 	  xfree (content[0]->which_element.source.line);
@@ -854,6 +854,9 @@ free_content_elements (tui_win_content content,
 		{
 		  switch (type)
 		    {
+		    case SRC_WIN:
+		      xfree (element->which_element.source.line);
+		      break;
 		    case DATA_WIN:
 		      xfree (element);
 		      break;
diff --git a/gdb/tui/tui-io.c b/gdb/tui/tui-io.c
index b1099246dd..0c7b88f1c7 100644
--- a/gdb/tui/tui-io.c
+++ b/gdb/tui/tui-io.c
@@ -367,9 +367,8 @@ tui_write (const char *buf, size_t length)
 }
 
 static void
-tui_puts_internal (const char *string, int *height)
+tui_puts_internal (WINDOW *w, const char *string, int *height)
 {
-  WINDOW *w = TUI_CMD_WIN->generic.handle;
   char c;
   int prev_col = 0;
 
@@ -410,9 +409,11 @@ tui_puts_internal (const char *string, int *height)
    necessary.  */
 
 void
-tui_puts (const char *string)
+tui_puts (const char *string, WINDOW *w)
 {
-  tui_puts_internal (string, nullptr);
+  if (w == nullptr)
+    w = TUI_CMD_WIN->generic.handle;
+  tui_puts_internal (w, string, nullptr);
 }
 
 /* Readline callback.
@@ -453,7 +454,7 @@ tui_redisplay_readline (void)
   prev_col = 0;
   height = 1;
   if (prompt != nullptr)
-    tui_puts_internal (prompt, &height);
+    tui_puts_internal (TUI_CMD_WIN->generic.handle, prompt, &height);
 
   prev_col = getcurx (w);
   for (in = 0; in <= rl_end; in++)
diff --git a/gdb/tui/tui-io.h b/gdb/tui/tui-io.h
index 11752d0845..95887639ec 100644
--- a/gdb/tui/tui-io.h
+++ b/gdb/tui/tui-io.h
@@ -22,11 +22,13 @@
 #ifndef TUI_IO_H
 #define TUI_IO_H
 
+#include "gdb_curses.h"
+
 struct ui_out;
 class cli_ui_out;
 
 /* Print the string in the curses command window.  */
-extern void tui_puts (const char *);
+extern void tui_puts (const char *, WINDOW * = nullptr);
 
 /* Print LENGTH characters from the buffer pointed to by BUF to the
    curses command window.  */
diff --git a/gdb/tui/tui-source.c b/gdb/tui/tui-source.c
index 3c4f06b01a..260b274297 100644
--- a/gdb/tui/tui-source.c
+++ b/gdb/tui/tui-source.c
@@ -28,14 +28,90 @@
 #include "symtab.h"
 #include "objfiles.h"
 #include "filenames.h"
+#include "source-cache.h"
 
 #include "tui/tui.h"
 #include "tui/tui-data.h"
+#include "tui/tui-io.h"
 #include "tui/tui-stack.h"
 #include "tui/tui-winsource.h"
 #include "tui/tui-source.h"
 #include "gdb_curses.h"
 
+/* A helper function for tui_set_source_content that extracts some
+   source text from PTR.  LINE_NO is the line number; FIRST_COL is the
+   first column to extract, and LINE_WIDTH is the number of characters
+   to display.  Returns a string holding the desired text.  */
+
+static std::string
+copy_source_line (const char **ptr, int line_no, int first_col,
+		  int line_width)
+{
+  const char *lineptr = *ptr;
+
+  /* Init the line with the line number.  */
+  std::string result = string_printf ("%-6d", line_no);
+  int len = result.size ();
+  len = len - ((len / tui_tab_width) * tui_tab_width);
+  result.append (len, ' ');
+
+  int column = 0;
+  char c;
+  do
+    {
+      int skip_bytes;
+
+      c = *lineptr;
+      if (c == '\033' && skip_ansi_escape (lineptr, &skip_bytes))
+	{
+	  /* We always have to preserve escapes.  */
+	  result.append (lineptr, lineptr + skip_bytes);
+	  lineptr += skip_bytes;
+	  continue;
+	}
+
+      ++lineptr;
+      ++column;
+      /* We have to process all the text in order to pick up all the
+	 escapes.  */
+      if (column < first_col || column > first_col + line_width)
+	continue;
+
+      if (c == '\n' || c == '\r' || c == '\0')
+	{
+	  /* Nothing.  */
+	}
+      else if (c < 040 && c != '\t')
+	{
+	  result.push_back ('^');
+	  result.push_back (c + 0100);
+	}
+      else if (c == 0177)
+	{
+	  result.push_back ('^');
+	  result.push_back ('?');
+	}
+      else if (c == '\t')
+	{
+	  int j, max_tab_len = tui_tab_width;
+
+	  for (j = column - ((column / max_tab_len) * max_tab_len);
+	       j < max_tab_len && column < first_col + line_width;
+	       column++, j++)
+	    result.push_back (' ');
+	}
+      else
+	result.push_back (c);
+    }
+  while (c != '\0' && c != '\n' && c != '\r');
+
+  if (c == '\r' && *lineptr == '\n')
+    ++lineptr;
+  *ptr = lineptr;
+
+  return result;
+}
+
 /* Function to display source in the source window.  */
 enum tui_status
 tui_set_source_content (struct symtab *s, 
@@ -46,8 +122,7 @@ tui_set_source_content (struct symtab *s,
 
   if (s != (struct symtab *) NULL)
     {
-      int i, c, line_width, nlines;
-      char *src_line = 0;
+      int line_width, nlines;
 
       if ((ret = tui_alloc_source_buffer (TUI_SRC_WIN)) == TUI_SUCCESS)
 	{
@@ -55,8 +130,10 @@ tui_set_source_content (struct symtab *s,
 	  /* Take hilite (window border) into account, when
 	     calculating the number of lines.  */
 	  nlines = (line_no + (TUI_SRC_WIN->generic.height - 2)) - line_no;
-	  scoped_fd desc = open_source_file (s);
-	  if (desc.get () < 0)
+
+	  std::string srclines;
+	  if (!g_source_cache.get_source_lines (s, line_no, line_no + nlines,
+						&srclines))
 	    {
 	      if (!noerror)
 		{
@@ -70,165 +147,68 @@ tui_set_source_content (struct symtab *s,
 	    }
 	  else
 	    {
-	      if (s->line_charpos == 0)
-		find_source_lines (s, desc.get ());
-
-	      if (line_no < 1 || line_no > s->nlines)
-		printf_unfiltered ("Line number %d out of range; "
-				   "%s has %d lines.\n",
-				   line_no,
-				   symtab_to_filename_for_display (s),
-				   s->nlines);
-	      else if (lseek (desc.get (), s->line_charpos[line_no - 1], 0)
-		       < 0)
-		perror_with_name (symtab_to_filename_for_display (s));
-	      else
+	      int cur_line_no, cur_line;
+	      struct tui_gen_win_info *locator
+		= tui_locator_win_info_ptr ();
+	      struct tui_source_info *src
+		= &TUI_SRC_WIN->detail.source_info;
+	      const char *s_filename = symtab_to_filename_for_display (s);
+
+	      if (TUI_SRC_WIN->generic.title)
+		xfree (TUI_SRC_WIN->generic.title);
+	      TUI_SRC_WIN->generic.title = xstrdup (s_filename);
+
+	      xfree (src->fullname);
+	      src->fullname = xstrdup (symtab_to_fullname (s));
+
+	      cur_line = 0;
+	      src->gdbarch = get_objfile_arch (SYMTAB_OBJFILE (s));
+	      src->start_line_or_addr.loa = LOA_LINE;
+	      cur_line_no = src->start_line_or_addr.u.line_no = line_no;
+
+	      const char *iter = srclines.c_str ();
+	      while (cur_line < nlines)
 		{
-		  int offset, cur_line_no, cur_line, cur_len, threshold;
-		  struct tui_gen_win_info *locator
-		    = tui_locator_win_info_ptr ();
-                  struct tui_source_info *src
-		    = &TUI_SRC_WIN->detail.source_info;
-		  const char *s_filename = symtab_to_filename_for_display (s);
-
-                  if (TUI_SRC_WIN->generic.title)
-                    xfree (TUI_SRC_WIN->generic.title);
-                  TUI_SRC_WIN->generic.title = xstrdup (s_filename);
-
-		  xfree (src->fullname);
-		  src->fullname = xstrdup (symtab_to_fullname (s));
-
-		  /* Determine the threshold for the length of the
-                     line and the offset to start the display.  */
-		  offset = src->horizontal_offset;
-		  threshold = (line_width - 1) + offset;
-		  gdb_file_up stream = desc.to_file (FOPEN_RT);
-		  clearerr (stream.get ());
-		  cur_line = 0;
-		  src->gdbarch = get_objfile_arch (SYMTAB_OBJFILE (s));
-		  src->start_line_or_addr.loa = LOA_LINE;
-		  cur_line_no = src->start_line_or_addr.u.line_no = line_no;
-		  if (offset > 0)
-		    src_line = (char *) xmalloc (
-					   (threshold + 1) * sizeof (char));
-		  while (cur_line < nlines)
-		    {
-		      struct tui_win_element *element
-			= TUI_SRC_WIN->generic.content[cur_line];
-
-		      /* Get the first character in the line.  */
-		      c = fgetc (stream.get ());
-
-		      if (offset == 0)
-			src_line = TUI_SRC_WIN->generic.content[cur_line]
-				     ->which_element.source.line;
-		      /* Init the line with the line number.  */
-		      sprintf (src_line, "%-6d", cur_line_no);
-		      cur_len = strlen (src_line);
-		      i = cur_len - ((cur_len / tui_tab_width)
-				     * tui_tab_width);
-		      while (i < tui_tab_width)
-			{
-			  src_line[cur_len] = ' ';
-			  i++;
-			  cur_len++;
-			}
-		      src_line[cur_len] = (char) 0;
-
-		      /* Set whether element is the execution point
-		         and whether there is a break point on it.  */
-		      element->which_element.source.line_or_addr.loa =
-			LOA_LINE;
-		      element->which_element.source.line_or_addr.u.line_no =
-			cur_line_no;
-		      element->which_element.source.is_exec_point =
-			(filename_cmp (locator->content[0]
-				         ->which_element.locator.full_name,
-				       symtab_to_fullname (s)) == 0
-				         && cur_line_no
-					      == locator->content[0]
-						   ->which_element.locator.line_no);
-		      if (c != EOF)
-			{
-			  i = strlen (src_line) - 1;
-			  do
-			    {
-			      if ((c != '\n') && (c != '\r') 
-				  && (++i < threshold))
-				{
-				  if (c < 040 && c != '\t')
-				    {
-				      src_line[i++] = '^';
-				      src_line[i] = c + 0100;
-				    }
-				  else if (c == 0177)
-				    {
-				      src_line[i++] = '^';
-				      src_line[i] = '?';
-				    }
-				  else
-				    { /* Store the charcter in the
-					 line buffer.  If it is a tab,
-					 then translate to the correct
-					 number of chars so we don't
-					 overwrite our buffer.  */
-				      if (c == '\t')
-					{
-					  int j, max_tab_len
-					    = tui_tab_width;
-
-					  for (j = i - ((i / max_tab_len)
-							* max_tab_len);
-					       j < max_tab_len
-						 && i < threshold;
-					       i++, j++)
-					    src_line[i] = ' ';
-					  i--;
-					}
-				      else
-					src_line[i] = c;
-				    }
-				  src_line[i + 1] = 0;
-				}
-			      else
-				{ /* If we have not reached EOL, then
-				     eat chars until we do.  */
-				  while (c != EOF && c != '\n' && c != '\r')
-				    c = fgetc (stream.get ());
-				  /* Handle non-'\n' end-of-line.  */
-				  if (c == '\r' 
-				      && (c = fgetc (stream.get ())) != '\n'
-				      && c != EOF)
-				    {
-				      ungetc (c, stream.get ());
-				      c = '\r';
-				    }
-				  
-				}
-			    }
-			  while (c != EOF && c != '\n' && c != '\r' 
-				 && i < threshold 
-				 && (c = fgetc (stream.get ())));
-			}
-		      /* Now copy the line taking the offset into
-			 account.  */
-		      if (offset == 0)
-			;
-		      else if (strlen (src_line) > offset)
-			strcpy (TUI_SRC_WIN->generic.content[cur_line]
-				  ->which_element.source.line,
-				&src_line[offset]);
-		      else
-			TUI_SRC_WIN->generic.content[cur_line]
-			  ->which_element.source.line[0] = (char) 0;
-		      cur_line++;
-		      cur_line_no++;
-		    }
-		  if (offset > 0)
-		    xfree (src_line);
-		  TUI_SRC_WIN->generic.content_size = nlines;
-		  ret = TUI_SUCCESS;
+		  struct tui_win_element *element
+		    = TUI_SRC_WIN->generic.content[cur_line];
+
+		  std::string text;
+		  if (*iter != '\0')
+		    text = copy_source_line (&iter, cur_line_no,
+					     src->horizontal_offset,
+					     line_width);
+
+		  /* Set whether element is the execution point
+		     and whether there is a break point on it.  */
+		  element->which_element.source.line_or_addr.loa =
+		    LOA_LINE;
+		  element->which_element.source.line_or_addr.u.line_no =
+		    cur_line_no;
+		  element->which_element.source.is_exec_point =
+		    (filename_cmp (locator->content[0]
+				   ->which_element.locator.full_name,
+				   symtab_to_fullname (s)) == 0
+		     && cur_line_no
+		     == locator->content[0]
+		     ->which_element.locator.line_no);
+
+		  xfree (TUI_SRC_WIN->generic.content[cur_line]
+			 ->which_element.source.line);
+		  int alloc_len = text.size ();
+		  if (alloc_len < line_width)
+		    alloc_len = line_width + 1;
+		  TUI_SRC_WIN->generic.content[cur_line]
+		    ->which_element.source.line
+		    = (char *) xmalloc (alloc_len);
+		  strcpy (TUI_SRC_WIN->generic.content[cur_line]
+			  ->which_element.source.line,
+			  text.c_str ());
+
+		  cur_line++;
+		  cur_line_no++;
 		}
+	      TUI_SRC_WIN->generic.content_size = nlines;
+	      ret = TUI_SUCCESS;
 	    }
 	}
     }
diff --git a/gdb/tui/tui-winsource.c b/gdb/tui/tui-winsource.c
index 0bf74383b1..00b4b9e4fa 100644
--- a/gdb/tui/tui-winsource.c
+++ b/gdb/tui/tui-winsource.c
@@ -31,6 +31,7 @@
 
 #include "tui/tui.h"
 #include "tui/tui-data.h"
+#include "tui/tui-io.h"
 #include "tui/tui-stack.h"
 #include "tui/tui-win.h"
 #include "tui/tui-wingeneral.h"
@@ -277,8 +278,9 @@ tui_show_source_line (struct tui_win_info *win_info, int lineno)
   if (line->which_element.source.is_exec_point)
     wattron (win_info->generic.handle, A_STANDOUT);
 
-  mvwaddstr (win_info->generic.handle, lineno, 1,
-	     line->which_element.source.line);
+  wmove (win_info->generic.handle, lineno, 1);
+  tui_puts (line->which_element.source.line,
+	    win_info->generic.handle);
   if (line->which_element.source.is_exec_point)
     wattroff (win_info->generic.handle, A_STANDOUT);
 
@@ -595,7 +597,6 @@ tui_update_exec_info (struct tui_win_info *win_info)
 enum tui_status
 tui_alloc_source_buffer (struct tui_win_info *win_info)
 {
-  char *src_line_buf;
   int i, line_width, max_lines;
 
   /* The window width/height includes the highlight box.  Determine actual
@@ -603,20 +604,14 @@ tui_alloc_source_buffer (struct tui_win_info *win_info)
   max_lines = win_info->generic.height - 2;
   line_width = win_info->generic.width - 2 + 1;
 
-  /*
-   * Allocate the buffer for the source lines.  Do this only once
-   * since they will be re-used for all source displays.  The only
-   * other time this will be done is when a window's size changes.
-   */
+  /* Allocate the buffer for the source lines.  */
   if (win_info->generic.content == NULL)
     {
-      src_line_buf = (char *) 
-	xmalloc ((max_lines * line_width) * sizeof (char));
       /* Allocate the content list.  */
       win_info->generic.content = tui_alloc_content (max_lines, SRC_WIN);
       for (i = 0; i < max_lines; i++)
 	win_info->generic.content[i]->which_element.source.line
-	  = src_line_buf + (line_width * i);
+	  = (char *) xmalloc (line_width);
     }
 
   return TUI_SUCCESS;
diff --git a/gdb/utils.c b/gdb/utils.c
index 85b0fb14e3..00f524c52e 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -1444,9 +1444,9 @@ emit_style_escape (const ui_file_style &style)
   wrap_buffer.append (style.to_ansi ());
 }
 
-/* Return true if ANSI escapes can be used on STREAM.  */
+/* See utils.h.  */
 
-static bool
+bool
 can_emit_style_escape (struct ui_file *stream)
 {
   if (stream != gdb_stdout
diff --git a/gdb/utils.h b/gdb/utils.h
index 1f09ec2d47..16ee9fbd33 100644
--- a/gdb/utils.h
+++ b/gdb/utils.h
@@ -443,6 +443,10 @@ extern void fputs_styled (const char *linebuffer,
 
 extern void reset_terminal_style (struct ui_file *stream);
 
+/* Return true if ANSI escapes can be used on STREAM.  */
+
+extern bool can_emit_style_escape (struct ui_file *stream);
+
 /* Display the host ADDR on STREAM formatted as ``0x%x''.  */
 extern void gdb_print_host_address_1 (const void *addr, struct ui_file *stream);
 
-- 
2.17.2

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 16/16] Document the "set style" commands
  2018-11-28  0:16 [PATCH 00/16] Add styling to the gdb CLI and TUI Tom Tromey
                   ` (12 preceding siblings ...)
  2018-11-28  0:16 ` [PATCH 13/16] Make ANSI terminal escape sequences work in TUI Tom Tromey
@ 2018-11-28  0:16 ` Tom Tromey
  2018-11-28  6:51   ` Eli Zaretskii
  2018-11-28  0:16 ` [PATCH 11/16] Style the "Reading symbols" message Tom Tromey
                   ` (3 subsequent siblings)
  17 siblings, 1 reply; 99+ messages in thread
From: Tom Tromey @ 2018-11-28  0:16 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This documents the new "set style" commands.

gdb/ChangeLog
2018-11-27  Tom Tromey  <tom@tromey.com>

	* NEWS: Mention terminal styling.

gdb/doc/ChangeLog
2018-11-27  Tom Tromey  <tom@tromey.com>

	* gdb.texinfo (Output Styling): New node.
---
 gdb/ChangeLog       |  4 +++
 gdb/NEWS            | 30 +++++++++++++++++++
 gdb/doc/ChangeLog   |  4 +++
 gdb/doc/gdb.texinfo | 72 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 110 insertions(+)

diff --git a/gdb/NEWS b/gdb/NEWS
index 9ecbb83d99..a5e677bc84 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -40,6 +40,11 @@
 
 * The RISC-V target now supports target descriptions.
 
+* Terminal styling is now available for the CLI and the TUI.  GNU
+  Source Highlight can additionally be used to provide styling of
+  source code snippets.  See the "set style" commands, below, for more
+  information.
+
 * New targets
 
   NXP S12Z		s12z-*-elf
@@ -116,6 +121,31 @@ set tui tab-width NCHARS
 show tui tab-width NCHARS
   "set tui tab-width" replaces the "tabset" command, which has been deprecated.
 
+set style enabled [on|off]
+show style enabled
+  Enable or disable terminal styling.  Styling is enabled by default
+  on most hosts.
+
+set style filename foreground COLOR
+set style filename background COLOR
+set style filename intensity VALUE
+  Control the styling of file names.
+
+set style function foreground COLOR
+set style function background COLOR
+set style function intensity VALUE
+  Control the styling of function names.
+
+set style variable foreground COLOR
+set style variable background COLOR
+set style variable intensity VALUE
+  Control the styling of variable names.
+
+set style address foreground COLOR
+set style address background COLOR
+set style address intensity VALUE
+  Control the styling of addresses.
+
 * MI changes
 
   ** The '-data-disassemble' MI command now accepts an '-a' option to
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 7350d94573..4d7b085f35 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -24196,6 +24196,7 @@ described here.
 * Editing::                     Command editing
 * Command History::             Command history
 * Screen Size::                 Screen size
+* Output Styling::              Output styling
 * Numbers::                     Numbers
 * ABI::                         Configuring the current ABI
 * Auto-loading::                Automatically loading associated files
@@ -24503,6 +24504,77 @@ Options, -batch}) also automatically disables pagination.
 Show the current pagination mode.
 @end table
 
+@node Output Styling
+@section Output Styling
+@cindex styling
+@cindex colors
+
+@value{GDBN} can style its output on a capable terminal.  This is
+enabled by default on most systems.  Various style settings are
+available; and styles can also be disabled entirely.
+
+@table @code
+@kindex set style enabled
+@item set style enabled @samp{on|off}
+Enable or disable all styling.  The default is host-dependent, with
+most hosts defaulting to @samp{on}.
+
+@kindex show style enabled
+@item show style enabled
+Show the current state of styling.
+@end table
+
+Subcommands of @code{set style} control specific forms of styling.
+These subcommands all follow the same pattern: each style-able object
+can be styled with a foreground color, a background color, and an
+intensity.
+
+For example, the style of file names can be controlled using the
+@code{set style filename} group of commands:
+
+@table @code
+@kindex set style filename background
+@item set style filename background @var{color}
+Set the background to @var{color}.  Valid colors are @samp{none}
+(meaning the terminal's default color), @samp{black}, @samp{red},
+@samp{green}, @samp{yellow}, @samp{vlue}, @samp{magenta}, @samp{cyan},
+and@samp{white}.
+
+@kindex set style filename foreground
+@item set style filename foreground @var{color}
+Set the foreground to @var{color}.  Valid colors are @samp{none}
+(meaning the terminal's default color), @samp{black}, @samp{red},
+@samp{green}, @samp{yellow}, @samp{vlue}, @samp{magenta}, @samp{cyan},
+and@samp{white}.
+
+@kindex set style filename intensity
+@item set style filename intensity @var{value}
+Set the intensity to @var{value}.  Valid intensities are @samp{normal}
+(the default), @samp{bold}, and @samp{dim}.
+@end table
+
+The style-able objects are:
+@table @code
+@kindex set style filename
+@item filename
+Control the styling of file names.
+
+@kindex set style function
+@item function
+Control the styling of function names.  These are managed with the
+@code{set style function} family of commands.
+
+@kindex set style variable
+@item variable
+Control the styling of variable names.  These are managed with the
+@code{set style variable} family of commands.
+
+@kindex set style address
+@item address
+Control the styling of addresses.  These are managed with the
+@code{set style address} family of commands.
+@end table
+
 @node Numbers
 @section Numbers
 @cindex number representation
-- 
2.17.2

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 04/16] Change gdb test suite's TERM setting
  2018-11-28  0:16 [PATCH 00/16] Add styling to the gdb CLI and TUI Tom Tromey
                   ` (8 preceding siblings ...)
  2018-11-28  0:16 ` [PATCH 08/16] Style locations when setting a breakpoint Tom Tromey
@ 2018-11-28  0:16 ` Tom Tromey
  2018-11-28  0:16 ` [PATCH 07/16] Style variable names Tom Tromey
                   ` (7 subsequent siblings)
  17 siblings, 0 replies; 99+ messages in thread
From: Tom Tromey @ 2018-11-28  0:16 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This changes the gdb test suite to set TERM to "dumb" by default.
This setting disables terminal styling, so that the existing tests do
not need to be updated.

gdb/testsuite/ChangeLog
2018-11-27  Tom Tromey  <tom@tromey.com>

	* lib/gdb.exp (gdb_init): Set the TERM environment variable to
	"dumb".
	* gdb.base/readline.exp (operate_and_get_next): Save and restore
	the TERM environment variable.
---
 gdb/testsuite/ChangeLog             |  7 +++
 gdb/testsuite/gdb.base/readline.exp | 94 +++++++++++++++--------------
 gdb/testsuite/lib/gdb.exp           |  7 +--
 3 files changed, 59 insertions(+), 49 deletions(-)

diff --git a/gdb/testsuite/gdb.base/readline.exp b/gdb/testsuite/gdb.base/readline.exp
index 49bd308197..9f0955c112 100644
--- a/gdb/testsuite/gdb.base/readline.exp
+++ b/gdb/testsuite/gdb.base/readline.exp
@@ -141,57 +141,61 @@ proc operate_and_get_next {name args} {
   return 1
 }
 
+save_vars { env(TERM) } {
+    # The arrow key test relies on the standard VT100 bindings, so
+    # make sure that an appropriate terminal is selected.  The same
+    # bug doesn't show up if we use ^P / ^N instead.
+    setenv TERM vt100
 
-gdb_start
-gdb_reinitialize_dir $srcdir/$subdir
+    gdb_start
+    gdb_reinitialize_dir $srcdir/$subdir
 
-if { ![readline_is_used] } {
-    unsupported "readline isn't used."
-    return -1
-}
+    if { ![readline_is_used] } {
+	unsupported "readline isn't used."
+	return -1
+    }
 
-save_vars { timeout env(GDBHISTSIZE) env(GDBHISTFILE) } {
-    set timeout 30
-
-    # A simple test of operate-and-get-next.
-    operate_and_get_next "Simple operate-and-get-next" \
-      "p 1" ".* = 1" \
-      "p 2" ".* = 2" \
-      "p 3" ".* = 3"
-
-    # Test operate-and-get-next with a secondary prompt.
-    operate_and_get_next "operate-and-get-next with secondary prompt" \
-      "if 1 > 0" "" \
-      "p 5" "" \
-      "end" ".* = 5"
-
-    # Verify that arrow keys work in secondary prompts.  The control
-    # sequence is a hard-coded VT100 up arrow.
-    gdb_test "print 42" "\\\$\[0-9\]* = 42"
-    set msg "arrow keys with secondary prompt"
-    gdb_test_multiple "if 1 > 0\n\033\[A\033\[A\nend" $msg {
-	-re ".*\\\$\[0-9\]* = 42\r\n$gdb_prompt $" {
-	    pass $msg
-	}
-	-re ".*Undefined command:.*$gdb_prompt $" {
-	    fail $msg
+    save_vars { timeout env(GDBHISTSIZE) env(GDBHISTFILE) } {
+	set timeout 30
+
+	# A simple test of operate-and-get-next.
+	operate_and_get_next "Simple operate-and-get-next" \
+	    "p 1" ".* = 1" \
+	    "p 2" ".* = 2" \
+	    "p 3" ".* = 3"
+
+	# Test operate-and-get-next with a secondary prompt.
+	operate_and_get_next "operate-and-get-next with secondary prompt" \
+	    "if 1 > 0" "" \
+	    "p 5" "" \
+	    "end" ".* = 5"
+
+	# Verify that arrow keys work in secondary prompts.  The control
+	# sequence is a hard-coded VT100 up arrow.
+	gdb_test "print 42" "\\\$\[0-9\]* = 42"
+	set msg "arrow keys with secondary prompt"
+	gdb_test_multiple "if 1 > 0\n\033\[A\033\[A\nend" $msg {
+	    -re ".*\\\$\[0-9\]* = 42\r\n$gdb_prompt $" {
+		pass $msg
+	    }
+	    -re ".*Undefined command:.*$gdb_prompt $" {
+		fail $msg
+	    }
 	}
-    }
 
-    # Now repeat the first test with a history file that fills the entire
-    # history list.
+	# Now repeat the first test with a history file that fills the entire
+	# history list.
 
-    set env(GDBHISTFILE) "${srcdir}/${subdir}/gdb_history"
-    set env(GDBHISTSIZE) "10"
+	set env(GDBHISTFILE) "${srcdir}/${subdir}/gdb_history"
+	set env(GDBHISTSIZE) "10"
 
-    gdb_exit
-    gdb_start
-    gdb_reinitialize_dir $srcdir/$subdir
+	gdb_exit
+	gdb_start
+	gdb_reinitialize_dir $srcdir/$subdir
 
-    operate_and_get_next "Simple operate-and-get-next" \
-      "p 7" ".* = 7" \
-      "p 8" ".* = 8" \
-      "p 9" ".* = 9"
+	operate_and_get_next "Simple operate-and-get-next" \
+	    "p 7" ".* = 7" \
+	    "p 8" ".* = 8" \
+	    "p 9" ".* = 9"
+    }
 }
-
-return 0
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index 5a5713b114..7eed7b5190 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -4719,10 +4719,9 @@ proc gdb_init { test_file_name } {
     # read from this file.
     setenv INPUTRC "/dev/null"
 
-    # The gdb.base/readline.exp arrow key test relies on the standard VT100
-    # bindings, so make sure that an appropriate terminal is selected.
-    # The same bug doesn't show up if we use ^P / ^N instead.
-    setenv TERM "vt100"
+    # This disables style output, which would interfere with many
+    # tests.
+    setenv TERM "dumb"
 
     # Some tests (for example gdb.base/maint.exp) shell out from gdb to use
     # grep.  Clear GREP_OPTIONS to make the behavior predictable,
-- 
2.17.2

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 00/16] Add styling to the gdb CLI and TUI
@ 2018-11-28  0:16 Tom Tromey
  2018-11-28  0:14 ` [PATCH 06/16] Reset terminal styles Tom Tromey
                   ` (17 more replies)
  0 siblings, 18 replies; 99+ messages in thread
From: Tom Tromey @ 2018-11-28  0:16 UTC (permalink / raw)
  To: gdb-patches

This patch series adds terminal styling (colorizing) to gdb's CLI and
TUI.  It is a refresh of an earlier RFC series, but some parts have
changed, and now there are tests and documentation.  It also includes
some TUI colorizing patches that were sent separately.

This series doesn't support the Windows console.  I don't know
anything about it.  So, it defaults to disabling styling on Windows
hosts.  This could be fixed by doing something like what the TUI does:
filter escape sequences from the output and apply them by some other
means.

More styling could be done.  It's relatively easy to add a new
style-able object.

If you want to try this out, it is the branch "submit/colorize" in my
github repository.

Regression tested on x86-64 Fedora 28.  I think it was too big for the
buildbot.

Tom


^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 01/16] Change wrap buffering to use a std::string
  2018-11-28  0:16 [PATCH 00/16] Add styling to the gdb CLI and TUI Tom Tromey
                   ` (14 preceding siblings ...)
  2018-11-28  0:16 ` [PATCH 11/16] Style the "Reading symbols" message Tom Tromey
@ 2018-11-28  0:19 ` Tom Tromey
  2018-12-23 15:26   ` Joel Brobecker
  2018-11-28  7:02 ` [PATCH 00/16] Add styling to the gdb CLI and TUI Eli Zaretskii
  2018-12-24  9:27 ` Joel Brobecker
  17 siblings, 1 reply; 99+ messages in thread
From: Tom Tromey @ 2018-11-28  0:19 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

Currently wrap buffering is implemented by allocating a string that is
the same width as the window, and then writing characters into it.
However, if gdb emits terminal escapes, then these could possibly
overflow the buffer.

To prevent this, change the wrap buffer to be a std::string and update
the various uses.

This also changes utils.c to always emit characters to the wrap
buffer.  This simplifies future patches which emit terminal escape
sequences, and also makes it possible for the "echo" and "printf"
commands to be used to emit terminal escapes and have these work in
the TUI.

gdb/ChangeLog
2018-11-27  Tom Tromey  <tom@tromey.com>

	* utils.c (filter_initalized): New global.
	(wrap_buffer): Now a std::string.
	(wrap_pointer): Remove.
	(flush_wrap_buffer): New function.
	(filtered_printing_initialized, set_width, wrap_here)
	(fputs_maybe_filtered): Update.
---
 gdb/ChangeLog |  9 ++++++++
 gdb/utils.c   | 63 +++++++++++++++++++++------------------------------
 2 files changed, 35 insertions(+), 37 deletions(-)

diff --git a/gdb/utils.c b/gdb/utils.c
index 0577e64ea8..0f1953a66d 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -1268,13 +1268,11 @@ static bool pagination_disabled_for_command;
    the end of the line, we spit out a newline, the indent, and then
    the buffered output.  */
 
-/* Malloc'd buffer with chars_per_line+2 bytes.  Contains characters which
-   are waiting to be output (they have already been counted in chars_printed).
-   When wrap_buffer[0] is null, the buffer is empty.  */
-static char *wrap_buffer;
+static bool filter_initalized = false;
 
-/* Pointer in wrap_buffer to the next character to fill.  */
-static char *wrap_pointer;
+/* Contains characters which are waiting to be output (they have
+   already been counted in chars_printed).  */
+static std::string wrap_buffer;
 
 /* String to indent by if the wrap occurs.  Must not be NULL if wrap_column
    is non-zero.  */
@@ -1347,7 +1345,7 @@ init_page_info (void)
 int
 filtered_printing_initialized (void)
 {
-  return wrap_buffer != NULL;
+  return filter_initalized;
 }
 
 set_batch_flag_and_restore_page_info::set_batch_flag_and_restore_page_info ()
@@ -1387,8 +1385,7 @@ set_screen_size (void)
   rl_set_screen_size (rows, cols);
 }
 
-/* Reinitialize WRAP_BUFFER according to the current value of
-   CHARS_PER_LINE.  */
+/* Reinitialize WRAP_BUFFER.  */
 
 static void
 set_width (void)
@@ -1396,14 +1393,8 @@ set_width (void)
   if (chars_per_line == 0)
     init_page_info ();
 
-  if (!wrap_buffer)
-    {
-      wrap_buffer = (char *) xmalloc (chars_per_line + 2);
-      wrap_buffer[0] = '\0';
-    }
-  else
-    wrap_buffer = (char *) xrealloc (wrap_buffer, chars_per_line + 2);
-  wrap_pointer = wrap_buffer;	/* Start it at the beginning.  */
+  wrap_buffer.clear ();
+  filter_initalized = true;
 }
 
 static void
@@ -1521,6 +1512,18 @@ reinitialize_more_filter (void)
   pagination_disabled_for_command = false;
 }
 
+/* Flush the wrap buffer to STREAM, if necessary.  */
+
+static void
+flush_wrap_buffer (struct ui_file *stream)
+{
+  if (!wrap_buffer.empty ())
+    {
+      fputs_unfiltered (wrap_buffer.c_str (), stream);
+      wrap_buffer.clear ();
+    }
+}
+
 /* Indicate that if the next sequence of characters overflows the line,
    a newline should be inserted here rather than when it hits the end.
    If INDENT is non-null, it is a string to be printed to indent the
@@ -1546,17 +1549,11 @@ void
 wrap_here (const char *indent)
 {
   /* This should have been allocated, but be paranoid anyway.  */
-  if (!wrap_buffer)
+  if (!filter_initalized)
     internal_error (__FILE__, __LINE__,
 		    _("failed internal consistency check"));
 
-  if (wrap_buffer[0])
-    {
-      *wrap_pointer = '\0';
-      fputs_unfiltered (wrap_buffer, gdb_stdout);
-    }
-  wrap_pointer = wrap_buffer;
-  wrap_buffer[0] = '\0';
+  flush_wrap_buffer (gdb_stdout);
   if (chars_per_line == UINT_MAX)	/* No line overflow checking.  */
     {
       wrap_column = 0;
@@ -1669,6 +1666,7 @@ fputs_maybe_filtered (const char *linebuffer, struct ui_file *stream,
       || top_level_interpreter () == NULL
       || top_level_interpreter ()->interp_ui_out ()->is_mi_like_p ())
     {
+      flush_wrap_buffer (stream);
       fputs_unfiltered (linebuffer, stream);
       return;
     }
@@ -1692,10 +1690,7 @@ fputs_maybe_filtered (const char *linebuffer, struct ui_file *stream,
 	  /* Print a single line.  */
 	  if (*lineptr == '\t')
 	    {
-	      if (wrap_column)
-		*wrap_pointer++ = '\t';
-	      else
-		fputc_unfiltered ('\t', stream);
+	      wrap_buffer.push_back ('\t');
 	      /* Shifting right by 3 produces the number of tab stops
 	         we have already passed, and then adding one and
 	         shifting left 3 advances to the next tab stop.  */
@@ -1704,10 +1699,7 @@ fputs_maybe_filtered (const char *linebuffer, struct ui_file *stream,
 	    }
 	  else
 	    {
-	      if (wrap_column)
-		*wrap_pointer++ = *lineptr;
-	      else
-		fputc_unfiltered (*lineptr, stream);
+	      wrap_buffer.push_back (*lineptr);
 	      chars_printed++;
 	      lineptr++;
 	    }
@@ -1735,8 +1727,7 @@ fputs_maybe_filtered (const char *linebuffer, struct ui_file *stream,
 	      if (wrap_column)
 		{
 		  fputs_unfiltered (wrap_indent, stream);
-		  *wrap_pointer = '\0';	/* Null-terminate saved stuff, */
-		  fputs_unfiltered (wrap_buffer, stream); /* and eject it.  */
+		  flush_wrap_buffer (stream);
 		  /* FIXME, this strlen is what prevents wrap_indent from
 		     containing tabs.  However, if we recurse to print it
 		     and count its chars, we risk trouble if wrap_indent is
@@ -1745,8 +1736,6 @@ fputs_maybe_filtered (const char *linebuffer, struct ui_file *stream,
 		     if we are printing a long string.  */
 		  chars_printed = strlen (wrap_indent)
 		    + (save_chars - wrap_column);
-		  wrap_pointer = wrap_buffer;	/* Reset buffer */
-		  wrap_buffer[0] = '\0';
 		  wrap_column = 0;	/* And disable fancy wrap */
 		}
 	    }
-- 
2.17.2

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 16/16] Document the "set style" commands
  2018-11-28  0:16 ` [PATCH 16/16] Document the "set style" commands Tom Tromey
@ 2018-11-28  6:51   ` Eli Zaretskii
  2018-12-28 19:19     ` Tom Tromey
  0 siblings, 1 reply; 99+ messages in thread
From: Eli Zaretskii @ 2018-11-28  6:51 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

> From: Tom Tromey <tom@tromey.com>
> Cc: Tom Tromey <tom@tromey.com>
> Date: Tue, 27 Nov 2018 17:14:35 -0700
> 
> +For example, the style of file names can be controlled using the
> +@code{set style filename} group of commands:
> +
> +@table @code
> +@kindex set style filename background
> +@item set style filename background @var{color}
> +Set the background to @var{color}.  Valid colors are @samp{none}
> +(meaning the terminal's default color), @samp{black}, @samp{red},
> +@samp{green}, @samp{yellow}, @samp{vlue}, @samp{magenta}, @samp{cyan},
> +and@samp{white}.
> +
> +@kindex set style filename foreground
> +@item set style filename foreground @var{color}
> +Set the foreground to @var{color}.  Valid colors are @samp{none}
> +(meaning the terminal's default color), @samp{black}, @samp{red},
> +@samp{green}, @samp{yellow}, @samp{vlue}, @samp{magenta}, @samp{cyan},
> +and@samp{white}.
> +
> +@kindex set style filename intensity
> +@item set style filename intensity @var{value}
> +Set the intensity to @var{value}.  Valid intensities are @samp{normal}
> +(the default), @samp{bold}, and @samp{dim}.
> +@end table
> +
> +The style-able objects are:
> +@table @code
> +@kindex set style filename
> +@item filename
> +Control the styling of file names.
> +
> +@kindex set style function
> +@item function
> +Control the styling of function names.  These are managed with the
> +@code{set style function} family of commands.
> +
> +@kindex set style variable
> +@item variable
> +Control the styling of variable names.  These are managed with the
> +@code{set style variable} family of commands.
> +
> +@kindex set style address
> +@item address
> +Control the styling of addresses.  These are managed with the
> +@code{set style address} family of commands.
> +@end table

The text is OK, but you have numerous "set style" index entries that
all start with the same substring and will point to almost the same
page.  This is not useful, IME.  I suggest just a single index entry
about "set style" instead.

Thanks.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2018-11-28  0:16 [PATCH 00/16] Add styling to the gdb CLI and TUI Tom Tromey
                   ` (15 preceding siblings ...)
  2018-11-28  0:19 ` [PATCH 01/16] Change wrap buffering to use a std::string Tom Tromey
@ 2018-11-28  7:02 ` Eli Zaretskii
  2018-11-29 22:44   ` Tom Tromey
  2018-12-24  9:27 ` Joel Brobecker
  17 siblings, 1 reply; 99+ messages in thread
From: Eli Zaretskii @ 2018-11-28  7:02 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

> From: Tom Tromey <tom@tromey.com>
> Date: Tue, 27 Nov 2018 17:14:19 -0700
> 
> This series doesn't support the Windows console.  I don't know
> anything about it.  So, it defaults to disabling styling on Windows
> hosts.  This could be fixed by doing something like what the TUI does:
> filter escape sequences from the output and apply them by some other
> means.

Will the Windows TUI build support styling out of the box?  It uses
ncurses.

And I don't think I understand what you mean by "filter escape
sequences from the output".  Where (on what level) would such filter
be installed, given that output is written directly to the console?

I see that you introduced the emit_style_escape function that switches
styles.  What I don't think I understand is whether it will work to
have a Windows implementation of that that calls a function which
causes the text output after that to use given colors?  It seems it
will, because the code calls emit_style_escape before and after each
string, but I cannot be sure.

Thanks.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2018-11-28  7:02 ` [PATCH 00/16] Add styling to the gdb CLI and TUI Eli Zaretskii
@ 2018-11-29 22:44   ` Tom Tromey
  2018-11-30  7:02     ` Eli Zaretskii
  2019-03-01  7:47     ` Eli Zaretskii
  0 siblings, 2 replies; 99+ messages in thread
From: Tom Tromey @ 2018-11-29 22:44 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Tom Tromey, gdb-patches

>>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes:

Eli> Will the Windows TUI build support styling out of the box?  It uses
Eli> ncurses.

I think it should work, but you'd have to "set style enabled on" first.

Eli> And I don't think I understand what you mean by "filter escape
Eli> sequences from the output".  Where (on what level) would such filter
Eli> be installed, given that output is written directly to the console?

I think either utils.c would have to be modified to change where it
sends output, or stdio_file::puts would have to be modified.  The idea
there would be to call a host-specific function; and then on Windows do
the filtering+styling if the output is going to the terminal.

Eli> I see that you introduced the emit_style_escape function that switches
Eli> styles.  What I don't think I understand is whether it will work to
Eli> have a Windows implementation of that that calls a function which
Eli> causes the text output after that to use given colors?  It seems it
Eli> will, because the code calls emit_style_escape before and after each
Eli> string, but I cannot be sure.

Doing it that way can't work due to buffering.  Also, this approach
would be undesirable anyway, because GNU Source Highlight emits escape
codes -- that's why I abandoned my earlier plan of implementing styling
as objects in the utils.c buffer.  Instead, I think filtering the escape
sequences is really the only way.

Tom

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2018-11-29 22:44   ` Tom Tromey
@ 2018-11-30  7:02     ` Eli Zaretskii
  2018-11-30 16:17       ` Tom Tromey
  2019-03-01  7:47     ` Eli Zaretskii
  1 sibling, 1 reply; 99+ messages in thread
From: Eli Zaretskii @ 2018-11-30  7:02 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

> From: Tom Tromey <tom@tromey.com>
> Cc: Tom Tromey <tom@tromey.com>,  gdb-patches@sourceware.org
> Date: Thu, 29 Nov 2018 15:43:59 -0700
> 
> >>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes:
> 
> Eli> Will the Windows TUI build support styling out of the box?  It uses
> Eli> ncurses.
> 
> I think it should work, but you'd have to "set style enabled on" first.

Maybe a TUI invocation should "set style enabled on" on all platforms?
Or at least on those that use ncurses?

> Eli> And I don't think I understand what you mean by "filter escape
> Eli> sequences from the output".  Where (on what level) would such filter
> Eli> be installed, given that output is written directly to the console?
> 
> I think either utils.c would have to be modified to change where it
> sends output, or stdio_file::puts would have to be modified.  The idea
> there would be to call a host-specific function; and then on Windows do
> the filtering+styling if the output is going to the terminal.

Ouch!  I hoped we could avoid such kludges.  Although it could, of
course, be done, I did that at some point for Gnu Grep.  One problem
with this approach is that it needs to fix the escape sequences for
the relevant attributes, whereas AFAIU your code simply uses the
terminfo that happens to be in effect, is that right?

> Eli> I see that you introduced the emit_style_escape function that switches
> Eli> styles.  What I don't think I understand is whether it will work to
> Eli> have a Windows implementation of that that calls a function which
> Eli> causes the text output after that to use given colors?  It seems it
> Eli> will, because the code calls emit_style_escape before and after each
> Eli> string, but I cannot be sure.
> 
> Doing it that way can't work due to buffering.

Not sure I understand.  Console output is generally line-buffered, and
there's fflush to force writing any buffered output before applying
text attributes.  Am I missing something?

> Also, this approach would be undesirable anyway, because GNU Source
> Highlight emits escape codes -- that's why I abandoned my earlier
> plan of implementing styling as objects in the utils.c buffer.

What is GNU Source Highlight, and what is its relevance to the issue
at hand?

> Instead, I think filtering the escape sequences is really the only
> way.

The problem with that is that it hard-codes the SGR sequences concepts
right into the design, and the escape sequences are unknown in advance
on systems where there's no terminfo.

Thanks.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2018-11-30  7:02     ` Eli Zaretskii
@ 2018-11-30 16:17       ` Tom Tromey
  2018-12-23 10:49         ` Joel Brobecker
  2019-03-01 13:10         ` Pedro Alves
  0 siblings, 2 replies; 99+ messages in thread
From: Tom Tromey @ 2018-11-30 16:17 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Tom Tromey, gdb-patches

>>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes:

Tom> I think it should work, but you'd have to "set style enabled on" first.

Eli> Maybe a TUI invocation should "set style enabled on" on all platforms?
Eli> Or at least on those that use ncurses?

That would possibly override the user's setting.  It's probably better
to simply implement the console support for Windows.  Or, change how the
disabling is done on Windows -- right now it is done by changing the
default for this setting, but perhaps it could be done some other way.

Is it possible to ssh in to a Windows machine and then use gdb?  That's
one scenario where you may want to keep the ANSI terminal escape
sequences in the output.  It also may affect how calls to the Windows
API are handled.

Eli> One problem with this approach is that it needs to fix the escape
Eli> sequences for the relevant attributes, whereas AFAIU your code
Eli> simply uses the terminfo that happens to be in effect, is that
Eli> right?

This patch series uses ANSI escape sequences for the styling; and the
TUI decodes these and turns them into curses calls.

Tom> Doing it that way can't work due to buffering.

Eli> Not sure I understand.  Console output is generally line-buffered, and
Eli> there's fflush to force writing any buffered output before applying
Eli> text attributes.  Am I missing something?

utils.c implements its own buffering.  Previous to this series this was
only done when "wrap_column > 0", but patch #1 changes this code to
always buffer.

This is a problem for other approaches because styles are emitted inline
with other text; and then flushed as a unit.

Tom> Also, this approach would be undesirable anyway, because GNU Source
Tom> Highlight emits escape codes -- that's why I abandoned my earlier
Tom> plan of implementing styling as objects in the utils.c buffer.

Eli> What is GNU Source Highlight, and what is its relevance to the issue
Eli> at hand?

GNU Source Highlight is used to style source text.

    https://www.gnu.org/software/src-highlite/

Support for using it is added to gdb in patch #15.

Tom> Instead, I think filtering the escape sequences is really the only
Tom> way.

Eli> The problem with that is that it hard-codes the SGR sequences concepts
Eli> right into the design, and the escape sequences are unknown in advance
Eli> on systems where there's no terminfo.

Only terminals using the ANSI sequences are supported by this series, at
least for the CLI.  The TUI can support more in theory, though I have no
way to test that.

Tom

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2018-11-30 16:17       ` Tom Tromey
@ 2018-12-23 10:49         ` Joel Brobecker
  2019-03-01 13:10         ` Pedro Alves
  1 sibling, 0 replies; 99+ messages in thread
From: Joel Brobecker @ 2018-12-23 10:49 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Eli Zaretskii, gdb-patches

[/me starting to look into this patch series...]

To answer one specific question:

> Is it possible to ssh in to a Windows machine and then use gdb?  That's
> one scenario where you may want to keep the ANSI terminal escape
> sequences in the output.  It also may affect how calls to the Windows
> API are handled.

Yes, it is possible to ssh into a Windows machine. The SSH server
we used is cygwin's one, and it's a bit of a special situation as stdin
is actually not viewed as a TTY, IIRC.  This has various consequences
because we actually want GDB to think it's a TTY. This is why we have
the "set interactive mode" command.

I am no longer sure whether this is related to TTY-ness or not, but
buffering was also an issue, that caused stdout/stderr to be output
in random order. That caused a lot of grief trying to run the testsuite,
so we "fixed" that internally at AdaCore by turning buffering off
entirely.

-- 
Joel

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 01/16] Change wrap buffering to use a std::string
  2018-11-28  0:19 ` [PATCH 01/16] Change wrap buffering to use a std::string Tom Tromey
@ 2018-12-23 15:26   ` Joel Brobecker
  2018-12-28 18:47     ` Tom Tromey
  0 siblings, 1 reply; 99+ messages in thread
From: Joel Brobecker @ 2018-12-23 15:26 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

Hi Tom,


> Currently wrap buffering is implemented by allocating a string that is
> the same width as the window, and then writing characters into it.
> However, if gdb emits terminal escapes, then these could possibly
> overflow the buffer.
> 
> To prevent this, change the wrap buffer to be a std::string and update
> the various uses.
> 
> This also changes utils.c to always emit characters to the wrap
> buffer.  This simplifies future patches which emit terminal escape
> sequences, and also makes it possible for the "echo" and "printf"
> commands to be used to emit terminal escapes and have these work in
> the TUI.
> 
> gdb/ChangeLog
> 2018-11-27  Tom Tromey  <tom@tromey.com>
> 
> 	* utils.c (filter_initalized): New global.
> 	(wrap_buffer): Now a std::string.
> 	(wrap_pointer): Remove.
> 	(flush_wrap_buffer): New function.
> 	(filtered_printing_initialized, set_width, wrap_here)
> 	(fputs_maybe_filtered): Update.

This patch kept me entertained for quite a bit longer than I thought!

I think just the mechanis of replacing the manually-managed buffer
with a string is a win in and of itself. The question your patch
raised as a side-effect is whether we still need the boolean indicating
whether the wrap buffer has been initialized or not (filter_initalized).
I tried to explore that question, hence the unexpected entertainment,
and the answer is still not clear to me, but I *think* that we should
be able to. It really depends what the semantics of
filtered_printing_initialized is, and it looks like it might be used for
two purposes, rather than one. Eg: one meaning is the wrap_buffer is
indeed iniatilized and therefore can be used; but it looks like the
other use is to determine whether buffering is done at all.

Anyways, this is orthogonal to your patch, so I will stop rambling now.

Overall, I think it is a good patch. I have one comment and one
question.


> ---
>  gdb/ChangeLog |  9 ++++++++
>  gdb/utils.c   | 63 +++++++++++++++++++++------------------------------
>  2 files changed, 35 insertions(+), 37 deletions(-)
> 
> diff --git a/gdb/utils.c b/gdb/utils.c
> index 0577e64ea8..0f1953a66d 100644
> --- a/gdb/utils.c
> +++ b/gdb/utils.c
> @@ -1268,13 +1268,11 @@ static bool pagination_disabled_for_command;
>     the end of the line, we spit out a newline, the indent, and then
>     the buffered output.  */
>  
> -/* Malloc'd buffer with chars_per_line+2 bytes.  Contains characters which
> -   are waiting to be output (they have already been counted in chars_printed).
> -   When wrap_buffer[0] is null, the buffer is empty.  */
> -static char *wrap_buffer;
> +static bool filter_initalized = false;

Small typo in the name of that static global "filter_initalized" ->
"filter_initialized" :-)

> @@ -1669,6 +1666,7 @@ fputs_maybe_filtered (const char *linebuffer, struct ui_file *stream,
>        || top_level_interpreter () == NULL
>        || top_level_interpreter ()->interp_ui_out ()->is_mi_like_p ())
>      {
> +      flush_wrap_buffer (stream);
>        fputs_unfiltered (linebuffer, stream);
>        return;
>      }

I understand why this is needed today; but I can't determine
whether this is needed as a consequence of your patch, or if this
was a hole in the previous code. Can you explain what made you
make this change?

Thank you,
-- 
Joel

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 03/16] Introduce ui_file_style
  2018-11-28  0:14 ` [PATCH 03/16] Introduce ui_file_style Tom Tromey
@ 2018-12-24  3:40   ` Joel Brobecker
  2018-12-28 18:54     ` Tom Tromey
  0 siblings, 1 reply; 99+ messages in thread
From: Joel Brobecker @ 2018-12-24  3:40 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On Tue, Nov 27, 2018 at 05:14:22PM -0700, Tom Tromey wrote:
> This introduces the new ui_file_style class and various helpers.  This
> class represents a terminal style and provides methods for parsing and
> emitting the corresponding ANSI terminal escape sequences.
> 
> gdb/ChangeLog
> 2018-11-27  Tom Tromey  <tom@tromey.com>
> 
> 	* unittests/style-selftests.c: New file.
> 	* ui-style.c: New file.
> 	* ui-style.h: New file.
> 	* ui-file.h: Include ui-style.h.
> 	* Makefile.in (COMMON_SFILES): Add ui-style.c.
> 	(HFILES_NO_SRCDIR): Add ui-style.h.
> 	(SUBDIR_UNITTESTS_SRCS): Add style-selftests.c.

FWIW, this looks good overall. I have one minor comment, and
a question or two...

Having the unit tests is absolutely awesome!

> +/* See ui-style.h.  */
> +
> +void
> +ui_file_style::color::get_rgb (uint8_t *rgb) const
> +{
> +  if (m_simple)
> +    {
> +      /* Can't call this for a basic color.  */

I am trying to understand this comment, as well as the corresponding
comment describing this method (in ui-style.h):

+       This may not be called for simple colors or for the "NONE"
+       color.  */

Does it look like you can, in fact, call this method on
a simple color?

> +  ui_file_style ()
> +  {
> +  }

Sorry for the obvious C++ question - Does this constructor means
that the default constructor results in an object with undefined
data? Or is that the same as...

    ui_file_style () = default;

It seems that it would be the latter case, but then I don't see
why we would want that...

> +/* Skip an ANSI escape sequence in BUF.  BUF must begin with an ESC
> +   character.  Return true if an escape sequence was successfully
> +   skipped; false otherwise.  In either case, N_READ is updated to
> +   reflect the number of chars read from BUF.  */
> +
> +extern bool skip_ansi_escape (const char *buf, int *bytes);

I think there might be a copy-pasto in the comment: N_READ -> BYTES?

-- 
Joel

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 05/16] Add output styles to gdb
  2018-11-28  0:14 ` [PATCH 05/16] Add output styles to gdb Tom Tromey
@ 2018-12-24  4:08   ` Joel Brobecker
  2018-12-28 18:55     ` Tom Tromey
  0 siblings, 1 reply; 99+ messages in thread
From: Joel Brobecker @ 2018-12-24  4:08 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

> gdb/ChangeLog
> 2018-11-27  Tom Tromey  <tom@tromey.com>
> 
> 	* utils.h (set_output_style, fprintf_styled)
> 	(fputs_styled): Declare.
> 	* utils.c (applied_style, desired_style): New globals.
> 	(emit_style_escape, set_output_style): New function.
> 	(prompt_for_continue): Emit style escapes.
> 	(fputs_maybe_filtered): Likewise.
> 	(fputs_styled, fprintf_styled): New functions.
> 	* ui-out.h (enum class ui_out_style_kind): New.
> 	(class ui_out) <field_string, field_stream, do_field_string>: Add
> 	style parameter.
> 	* ui-out.c (ui_out::field_stream, ui_out::field_string): Add style
> 	parameter.
> 	* tui/tui-out.h (class tui_ui_out) <do_field_string>: Add style
> 	parameter.
> 	* tui/tui-out.c (tui_ui_out::do_field_string): Add style
> 	parameter.
> 	(tui_ui_out::do_field_string): Update.
> 	* tracepoint.c (print_one_static_tracepoint_marker): Style
> 	output.
> 	* stack.c (print_frame_info, print_frame): Style output.
> 	* source.c (print_source_lines_base): Style output.
> 	* skip.c (info_skip_command): Style output.
> 	* record-btrace.c (btrace_call_history_src_line): Style output.
> 	(btrace_call_history): Likewise.
> 	* python/py-framefilter.c (py_print_frame): Style output.
> 	* mi/mi-out.h (class mi_ui_out) <do_field_string>: Add style
> 	parameter.
> 	* mi/mi-out.c (mi_ui_out::do_table_header)
> 	(mi_ui_out::do_field_int): Update.
> 	(mi_ui_out::do_field_string): Update.
> 	* disasm.c (gdb_pretty_print_disassembler::pretty_print_insn):
> 	Style output.
> 	* cli/cli-style.h: New file.
> 	* cli/cli-style.c: New file.
> 	* cli-out.h (class cli_ui_out) <do_field_string>: Add style
> 	parameter.
> 	* cli-out.c (cli_ui_out::do_table_header)
> 	(cli_ui_out::do_field_int, cli_ui_out::do_field_skip): Update.
> 	(cli_ui_out::do_field_string): Add style parameter.  Style the
> 	output.
> 	* breakpoint.c (print_breakpoint_location): Style output.
> 	(update_static_tracepoint): Likewise.
> 	* Makefile.in (SUBDIR_CLI_SRCS): Add cli-style.c.
> 	(HFILES_NO_SRCDIR): Add cli-style.h.
> 
> gdb/testsuite/ChangeLog
> 2018-11-27  Tom Tromey  <tom@tromey.com>
> 
> 	* gdb.base/style.exp: New file.
> 	* gdb.base/style.c: New file.

I tried to think about other ways to decide whether styling is
supported or not, but at the end of the day, Athis is just a detail,
and we can always come back to it. In the meantime, I think what
you've done should be good enough. I assume there aren't that
many terminals out there that don't support ansi colorizing.

The patch looks good to me overall. Just a few very minor nits.

> +void
> +cli_style_option::add_setshow_commands (const char *name,
> +					enum command_class theclass,
> +					const char *prefix_doc,
> +					const char *prefixname,
> +					struct cmd_list_element **set_list,
> +					struct cmd_list_element **show_list)
> +{
> +  m_show_prefix = std::string ("set ") + prefixname + " ";
> +  m_show_prefix = std::string ("show ") + prefixname + " ";
> +
> +  add_prefix_cmd (name, no_class, do_set, prefix_doc, &m_set_list, 

Small nit: Trailing space here...

> @@ -1182,7 +1185,7 @@ print_frame (struct frame_info *frame, int print_level,
>      string_file stb;
>      fprintf_symbol_filtered (&stb, funname ? funname.get () : "??",
>  			     funlang, DMGL_ANSI);
> -    uiout->field_stream ("func", stb);
> +    uiout->field_stream ("func", stb, ui_out_style_kind::FUNCTION);
>      uiout->wrap_hint ("   ");
>      annotate_frame_args ();
>        

Another one here as well.

> +++ b/gdb/testsuite/gdb.base/style.c
> @@ -0,0 +1,22 @@
> +/* Copyright 2018 Free Software Foundation, Inc.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
> +
> +#include <stdio.h>

Can we remove the #include in this case?

> +save_vars { env(TERM) } {
> +    # We need an ANSI-capable terminal to get the output.
> +    setenv TERM ansi
> +
> +    if {[prepare_for_testing "failed to prepare" $testfile $srcfile]} {
> +	return -1
> +    }
> +
> +    if {![runto_main]} {
> +	fail "style tests failed"
> +	return
> +    }
> +
> +    gdb_test_no_output "set style enabled on"
> +    

Nit: A few trailing spaces here...


-- 
Joel

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 06/16] Reset terminal styles
  2018-11-28  0:14 ` [PATCH 06/16] Reset terminal styles Tom Tromey
@ 2018-12-24  4:16   ` Joel Brobecker
  2018-12-28 19:01     ` Tom Tromey
  0 siblings, 1 reply; 99+ messages in thread
From: Joel Brobecker @ 2018-12-24  4:16 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

Hi Tom,

> This adds a function that can be used to reset terminal styles,
> regardless of what style the low-levle output routines currently think

Typo: levle -> level

> is applied.
> 
> This is used to make "echo" and "printf" work properly when emitting
> ANSI terminal escapes -- now gdb will reset the style at the end of
> the command.
> 
> gdb/ChangeLog
> 2018-11-27  Tom Tromey  <tom@tromey.com>
> 
> 	* utils.h (reset_terminal_style): Declare.
> 	* utils.c (can_emit_style_escape): New function.
> 	(set_output_style): Use it.
> 	(reset_terminal_style): New function.
> 	* printcmd.c (printf_command): Call reset_terminal_style.
> 	* cli/cli-cmds.c (echo_command): Call reset_terminal_style.

OK with me. Just one question below.

> diff --git a/gdb/printcmd.c b/gdb/printcmd.c
> index 8c999188d7..79c3d2d2ff 100644
> --- a/gdb/printcmd.c
> +++ b/gdb/printcmd.c
> @@ -2609,6 +2609,8 @@ static void
>  printf_command (const char *arg, int from_tty)
>  {
>    ui_printf (arg, gdb_stdout);
> +  reset_terminal_style (gdb_stdout);
> +  wrap_here ("");

Can you explain why you added the "wrap_here"?


-- 
Joel

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 13/16] Make ANSI terminal escape sequences work in TUI
  2018-11-28  0:16 ` [PATCH 13/16] Make ANSI terminal escape sequences work in TUI Tom Tromey
@ 2018-12-24  8:02   ` Joel Brobecker
  2018-12-28 19:42   ` Tom Tromey
  1 sibling, 0 replies; 99+ messages in thread
From: Joel Brobecker @ 2018-12-24  8:02 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

> I am very sour on the curses design now.

I would be too!

> gdb/ChangeLog
> 2018-11-27  Tom Tromey  <tom@tromey.com>
> 
> 	PR tui/14126:
> 	* tui/tui.c (tui_enable): Call start_color and
> 	use_default_colors.
> 	* tui/tui-io.c (struct color_pair): New.
> 	(color_pair_map, last_color_pair, last_style): New globals.
> 	(tui_setup_io): Clean up color map when shutting down.
> 	(curses_colors): New constant.
> 	(get_color_pair, apply_ansi_escape): New functions.
> 	(tui_write): Rewrite.
> 	(tui_puts_internal): New function, from tui_puts.  Add "height"
> 	parameter.
> 	(tui_puts): Use tui_puts_internal.
> 	(tui_redisplay_readline): Use tui_puts_internal.
> 	(_initialize_tui_io): New function.
> 	(color_map): New globals.
> 	(get_color): New function.
> 	* configure.ac: Check for use_default_colors.
> 	* config.in, configure: Rebuild.

I scan the patch. I didn't go into too much detail, but for what
it's worth, what I read made sense to me.

-- 
Joel

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 14/16] Use wclrtoeol in tui_show_source_line
  2018-11-28  0:14 ` [PATCH 14/16] Use wclrtoeol in tui_show_source_line Tom Tromey
@ 2018-12-24  8:03   ` Joel Brobecker
  0 siblings, 0 replies; 99+ messages in thread
From: Joel Brobecker @ 2018-12-24  8:03 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

> This changes tui_show_source_line to use wclrtoeol rather than
> manually emitting a sequence of spaces.
> 
> gdb/ChangeLog
> 2018-11-27  Tom Tromey  <tom@tromey.com>
> 
> 	* tui/tui-winsource.c (tui_show_source_line): Use wclrtoeol.

This one can go in on its own, I think!


-- 
Joel

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2018-11-28  0:16 [PATCH 00/16] Add styling to the gdb CLI and TUI Tom Tromey
                   ` (16 preceding siblings ...)
  2018-11-28  7:02 ` [PATCH 00/16] Add styling to the gdb CLI and TUI Eli Zaretskii
@ 2018-12-24  9:27 ` Joel Brobecker
  2018-12-28 20:57   ` Tom Tromey
  17 siblings, 1 reply; 99+ messages in thread
From: Joel Brobecker @ 2018-12-24  9:27 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

> This patch series adds terminal styling (colorizing) to gdb's CLI and
> TUI.  It is a refresh of an earlier RFC series, but some parts have
> changed, and now there are tests and documentation.  It also includes
> some TUI colorizing patches that were sent separately.
> 
> This series doesn't support the Windows console.  I don't know
> anything about it.  So, it defaults to disabling styling on Windows
> hosts.  This could be fixed by doing something like what the TUI does:
> filter escape sequences from the output and apply them by some other
> means.
> 
> More styling could be done.  It's relatively easy to add a new
> style-able object.
> 
> If you want to try this out, it is the branch "submit/colorize" in my
> github repository.
> 
> Regression tested on x86-64 Fedora 28.  I think it was too big for the
> buildbot.

I gave the whole series a look. The TUI changes were a bit alien
to me. I sent comments on the patches where I had questions;
otherwise, those I didn't comment on looked fine to me.

I really look forward to this series making it to master, it would
be a nice feature to advertise on the release that includes it.
The source highlighting is also a very nice touch!

One feature I might volunteer to work on once the series is in
is to provide two sets of defaults for the colors - one to be used
when the terminal has a dark background vs one to be used when
the terminal has a light background. I think the way ou added
colorizing should make it easy to do.

That's all I had to say as a summary. Thanks a lot for those.
I think people are going to enjoy this enchancement. At least
I know I will!

-- 
Joel

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 01/16] Change wrap buffering to use a std::string
  2018-12-23 15:26   ` Joel Brobecker
@ 2018-12-28 18:47     ` Tom Tromey
  0 siblings, 0 replies; 99+ messages in thread
From: Tom Tromey @ 2018-12-28 18:47 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: Tom Tromey, gdb-patches

>>>>> "Joel" == Joel Brobecker <brobecker@adacore.com> writes:

Joel> The question your patch
Joel> raised as a side-effect is whether we still need the boolean indicating
Joel> whether the wrap buffer has been initialized or not (filter_initalized).
Joel> I tried to explore that question, hence the unexpected entertainment,
Joel> and the answer is still not clear to me, but I *think* that we should
Joel> be able to. It really depends what the semantics of
Joel> filtered_printing_initialized is, and it looks like it might be used for
Joel> two purposes, rather than one. Eg: one meaning is the wrap_buffer is
Joel> indeed iniatilized and therefore can be used; but it looks like the
Joel> other use is to determine whether buffering is done at all.

This is a good point.  I've put a note in my to-do list to remind me to
see if it can be removed.

Joel> Small typo in the name of that static global "filter_initalized" ->
Joel> "filter_initialized" :-)

Thanks, I fixed this.

>> @@ -1669,6 +1666,7 @@ fputs_maybe_filtered (const char *linebuffer, struct ui_file *stream,
>> || top_level_interpreter () == NULL
>> || top_level_interpreter ()->interp_ui_out ()->is_mi_like_p ())
>> {
>> +      flush_wrap_buffer (stream);
>> fputs_unfiltered (linebuffer, stream);
>> return;
>> }

Joel> I understand why this is needed today; but I can't determine
Joel> whether this is needed as a consequence of your patch, or if this
Joel> was a hole in the previous code. Can you explain what made you
Joel> make this change?

It's probably not needed in this particular patch, but eventually style
changes are just written to the buffer; so to get styles to apply
properly when filtering is not in use, the buffer has to be flushed
here.

Tom

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 03/16] Introduce ui_file_style
  2018-12-24  3:40   ` Joel Brobecker
@ 2018-12-28 18:54     ` Tom Tromey
  0 siblings, 0 replies; 99+ messages in thread
From: Tom Tromey @ 2018-12-28 18:54 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: Tom Tromey, gdb-patches

>>>>> "Joel" == Joel Brobecker <brobecker@adacore.com> writes:

>> +      /* Can't call this for a basic color.  */

Joel> I am trying to understand this comment, as well as the corresponding
Joel> comment describing this method (in ui-style.h):

Joel> +       This may not be called for simple colors or for the "NONE"
Joel> +       color.  */

Joel> Does it look like you can, in fact, call this method on
Joel> a simple color?

Yeah.  The naming was confusing here, so I have cleaned it up by
renaming "enum simple_color" to "enum basic_color".  You can call this
method for any "simple" (scalar) color that isn't a basic color or NONE,
simply because we don't have RGB values for these.

>> +  ui_file_style ()
>> +  {
>> +  }

Joel> Sorry for the obvious C++ question - Does this constructor means
Joel> that the default constructor results in an object with undefined
Joel> data? Or is that the same as...

Joel>     ui_file_style () = default;

It's the same, I have changed the code to use the "= default" form.

Joel> I think there might be a copy-pasto in the comment: N_READ -> BYTES?

I fixed this.

Tom

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 05/16] Add output styles to gdb
  2018-12-24  4:08   ` Joel Brobecker
@ 2018-12-28 18:55     ` Tom Tromey
  0 siblings, 0 replies; 99+ messages in thread
From: Tom Tromey @ 2018-12-28 18:55 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: Tom Tromey, gdb-patches

>>>>> "Joel" == Joel Brobecker <brobecker@adacore.com> writes:

Joel> The patch looks good to me overall. Just a few very minor nits.
[...]

I've fixed all these.  Thanks for the review.

Tom

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 06/16] Reset terminal styles
  2018-12-24  4:16   ` Joel Brobecker
@ 2018-12-28 19:01     ` Tom Tromey
  0 siblings, 0 replies; 99+ messages in thread
From: Tom Tromey @ 2018-12-28 19:01 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: Tom Tromey, gdb-patches

>>>>> "Joel" == Joel Brobecker <brobecker@adacore.com> writes:

>> printf_command (const char *arg, int from_tty)
>> {
>> ui_printf (arg, gdb_stdout);
>> +  reset_terminal_style (gdb_stdout);
>> +  wrap_here ("");

Joel> Can you explain why you added the "wrap_here"?

gdb's pager has the unusual property that it introduces another layer of
buffering that isn't accessible to gdb_flush.  So, to properly flush
stdout and I guess stderr, one must first call wrap_here to flush this
buffer.

You can see this most clearly in exceptions.c:print_flush, which is
where this seems to have been documented.

In this particular case, reset_terminal_style might emit an escape
sequence to the wrap buffer.  So, wrap_here is needed to be sure this is
flushed.  We can't flush in reset_terminal_style because it might be
used in cases where flushing is inappropriate, for example in the middle
of a command when paging is still desired.

I think a better design would be to require nothing more than gdb_flush.
However, this requires some thought and experimentation, and seemed
orthogonal to my goal in this series.

Tom

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 16/16] Document the "set style" commands
  2018-11-28  6:51   ` Eli Zaretskii
@ 2018-12-28 19:19     ` Tom Tromey
  0 siblings, 0 replies; 99+ messages in thread
From: Tom Tromey @ 2018-12-28 19:19 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Tom Tromey, gdb-patches

>>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes:

Eli> The text is OK, but you have numerous "set style" index entries that
Eli> all start with the same substring and will point to almost the same
Eli> page.  This is not useful, IME.  I suggest just a single index entry
Eli> about "set style" instead.

I've made this change.

Tom

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 13/16] Make ANSI terminal escape sequences work in TUI
  2018-11-28  0:16 ` [PATCH 13/16] Make ANSI terminal escape sequences work in TUI Tom Tromey
  2018-12-24  8:02   ` Joel Brobecker
@ 2018-12-28 19:42   ` Tom Tromey
  1 sibling, 0 replies; 99+ messages in thread
From: Tom Tromey @ 2018-12-28 19:42 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

>>>>> "Tom" == Tom Tromey <tom@tromey.com> writes:

Tom> PR tui/14126 notes that ANSI terminal escape sequences don't affect
Tom> the colors shown in the TUI.  A simple way to see this is to try the
Tom> extended-prompt example from the gdb manual.

[...]

I found a bug in this patch:

Tom> +  if (color.is_none ())
Tom> +    *result = 1;

This should be -1, not 1.
Fixing this makes the output much less garish.

Tom

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2018-12-24  9:27 ` Joel Brobecker
@ 2018-12-28 20:57   ` Tom Tromey
  0 siblings, 0 replies; 99+ messages in thread
From: Tom Tromey @ 2018-12-28 20:57 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: Tom Tromey, gdb-patches

>>>>> "Joel" == Joel Brobecker <brobecker@adacore.com> writes:

Joel> I gave the whole series a look. The TUI changes were a bit alien
Joel> to me. I sent comments on the patches where I had questions;
Joel> otherwise, those I didn't comment on looked fine to me.

Thanks for the reviews!

Joel> One feature I might volunteer to work on once the series is in
Joel> is to provide two sets of defaults for the colors - one to be used
Joel> when the terminal has a dark background vs one to be used when
Joel> the terminal has a light background. I think the way ou added
Joel> colorizing should make it easy to do.

This sounds like a good idea, and we can certainly tinker with it as
need be.

I have a few patches to GNU Source Highlight that I am trying to get in.
I have some updates for the C and C++ support, plus Rust support.  The
project seems a bit dead so I've asked maintainers@gnu to give me
permissions to check in some patches and do a new release.

Joel> That's all I had to say as a summary. Thanks a lot for those.
Joel> I think people are going to enjoy this enchancement. At least
Joel> I know I will!

Thanks.  I am going to check in the series now.

Tom

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2018-11-29 22:44   ` Tom Tromey
  2018-11-30  7:02     ` Eli Zaretskii
@ 2019-03-01  7:47     ` Eli Zaretskii
  2019-03-01 18:42       ` Tom Tromey
  2019-03-04 16:04       ` Eli Zaretskii
  1 sibling, 2 replies; 99+ messages in thread
From: Eli Zaretskii @ 2019-03-01  7:47 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

> From: Tom Tromey <tom@tromey.com>
> Cc: Tom Tromey <tom@tromey.com>,  gdb-patches@sourceware.org
> Date: Thu, 29 Nov 2018 15:43:59 -0700
> 
> >>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes:
> 
> Eli> Will the Windows TUI build support styling out of the box?  It uses
> Eli> ncurses.
> 
> I think it should work, but you'd have to "set style enabled on" first.

For the record, it doesn't work in GDB 8.2.90, even after I disabled
the test for $TERM being defined in the environment.  I will try to
find out why at some point.

> I think either utils.c would have to be modified to change where it
> sends output, or stdio_file::puts would have to be modified.  The idea
> there would be to call a host-specific function; and then on Windows do
> the filtering+styling if the output is going to the terminal.

I'm looking into this now.  The simplest change would be to modify
stdio_file::puts that performs the filtering only on Windows, but the
fact that you mentioned calling a host-specific function confuses me a
little.  Can you elaborate on what you had in mind, and specifically
what kind of a host-specific function should be involved here, and
how?

Thanks.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2018-11-30 16:17       ` Tom Tromey
  2018-12-23 10:49         ` Joel Brobecker
@ 2019-03-01 13:10         ` Pedro Alves
  2019-03-01 13:56           ` Eli Zaretskii
  1 sibling, 1 reply; 99+ messages in thread
From: Pedro Alves @ 2019-03-01 13:10 UTC (permalink / raw)
  To: Tom Tromey, Eli Zaretskii; +Cc: gdb-patches

On 11/30/2018 04:17 PM, Tom Tromey wrote:
>>>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes:
> 
> Tom> I think it should work, but you'd have to "set style enabled on" first.
> 
> Eli> Maybe a TUI invocation should "set style enabled on" on all platforms?
> Eli> Or at least on those that use ncurses?
> 
> That would possibly override the user's setting.  It's probably better
> to simply implement the console support for Windows.  Or, change how the
> disabling is done on Windows -- right now it is done by changing the
> default for this setting, but perhaps it could be done some other way.
> 
> Is it possible to ssh in to a Windows machine and then use gdb?  That's
> one scenario where you may want to keep the ANSI terminal escape
> sequences in the output.  It also may affect how calls to the Windows
> API are handled.
> 
> Eli> One problem with this approach is that it needs to fix the escape
> Eli> sequences for the relevant attributes, whereas AFAIU your code
> Eli> simply uses the terminfo that happens to be in effect, is that
> Eli> right?
> 
> This patch series uses ANSI escape sequences for the styling; and the
> TUI decodes these and turns them into curses calls.
> 
> Tom> Doing it that way can't work due to buffering.
> 
> Eli> Not sure I understand.  Console output is generally line-buffered, and
> Eli> there's fflush to force writing any buffered output before applying
> Eli> text attributes.  Am I missing something?
> 
> utils.c implements its own buffering.  Previous to this series this was
> only done when "wrap_column > 0", but patch #1 changes this code to
> always buffer.
> 
> This is a problem for other approaches because styles are emitted inline
> with other text; and then flushed as a unit.
> 
> Tom> Also, this approach would be undesirable anyway, because GNU Source
> Tom> Highlight emits escape codes -- that's why I abandoned my earlier
> Tom> plan of implementing styling as objects in the utils.c buffer.
> 
> Eli> What is GNU Source Highlight, and what is its relevance to the issue
> Eli> at hand?
> 
> GNU Source Highlight is used to style source text.
> 
>     https://www.gnu.org/software/src-highlite/
> 
> Support for using it is added to gdb in patch #15.
> 
> Tom> Instead, I think filtering the escape sequences is really the only
> Tom> way.
> 
> Eli> The problem with that is that it hard-codes the SGR sequences concepts
> Eli> right into the design, and the escape sequences are unknown in advance
> Eli> on systems where there's no terminfo.
> 
> Only terminals using the ANSI sequences are supported by this series, at
> least for the CLI.  The TUI can support more in theory, though I have no
> way to test that.

The Windows console in Windows 10 Anniversary Update supports ANSI escape sequences:

 [1] https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
 [2] https://blogs.msdn.microsoft.com/commandline/2017/04/11/windows-10-creators-update-whats-new-in-bashwsl-windows-console/

Basically, GDB needs to call SetConsoleMode with
ENABLE_VIRTUAL_TERMINAL_PROCESSING at early startup to enable the feature.
There's an example at the bottom of page [1] above.

I have no idea whether that interacts badly with readline or curses, but
it seems like the ideal solution going forward.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-01 13:10         ` Pedro Alves
@ 2019-03-01 13:56           ` Eli Zaretskii
  2019-03-01 14:10             ` Pedro Alves
  0 siblings, 1 reply; 99+ messages in thread
From: Eli Zaretskii @ 2019-03-01 13:56 UTC (permalink / raw)
  To: Pedro Alves; +Cc: tom, gdb-patches

> Cc: gdb-patches@sourceware.org
> From: Pedro Alves <palves@redhat.com>
> Date: Fri, 1 Mar 2019 13:10:35 +0000
> 
> The Windows console in Windows 10 Anniversary Update supports ANSI escape sequences:
> 
>  [1] https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
>  [2] https://blogs.msdn.microsoft.com/commandline/2017/04/11/windows-10-creators-update-whats-new-in-bashwsl-windows-console/

Yes, I know.  I guess GDB will have to use that, at least at some
point, or maybe as an option even today.  Thanks for the pointers,
regardless.

> Basically, GDB needs to call SetConsoleMode with
> ENABLE_VIRTUAL_TERMINAL_PROCESSING at early startup to enable the feature.
> There's an example at the bottom of page [1] above.
> 
> I have no idea whether that interacts badly with readline or curses, but
> it seems like the ideal solution going forward.

We don't want to require Windows 10 for the styling support, do we?
Older versions of Windows still have quite a few years before they are
unsupported even by Microsoft, let alone GDB.

Or are you saying that you will be unwilling to accept patches that
enable styling on all versions of Windows (by converting SGR sequences
to corresponding Windows API calls)?

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-01 13:56           ` Eli Zaretskii
@ 2019-03-01 14:10             ` Pedro Alves
  2019-03-01 14:50               ` Eli Zaretskii
  0 siblings, 1 reply; 99+ messages in thread
From: Pedro Alves @ 2019-03-01 14:10 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: tom, gdb-patches

On 03/01/2019 01:56 PM, Eli Zaretskii wrote:
>> Cc: gdb-patches@sourceware.org
>> From: Pedro Alves <palves@redhat.com>

>> Basically, GDB needs to call SetConsoleMode with
>> ENABLE_VIRTUAL_TERMINAL_PROCESSING at early startup to enable the feature.
>> There's an example at the bottom of page [1] above.
>>
>> I have no idea whether that interacts badly with readline or curses, but
>> it seems like the ideal solution going forward.
> 
> We don't want to require Windows 10 for the styling support, do we?
> Older versions of Windows still have quite a few years before they are
> unsupported even by Microsoft, let alone GDB.

I'm saying that there's an easy way out that likely
gets you styling without much work.  Over time, older versions of
Windows will fade away.  I'm comparing to the current state, where
there's no styling at all.

> Or are you saying that you will be unwilling to accept patches that
> enable styling on all versions of Windows (by converting SGR sequences
> to corresponding Windows API calls)?

Of course not.  If someone's willing to implement that, it's super
fine with me.  It's not unlike what Tom did for TUI / curses.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-01 14:10             ` Pedro Alves
@ 2019-03-01 14:50               ` Eli Zaretskii
  0 siblings, 0 replies; 99+ messages in thread
From: Eli Zaretskii @ 2019-03-01 14:50 UTC (permalink / raw)
  To: Pedro Alves; +Cc: tom, gdb-patches

> Cc: tom@tromey.com, gdb-patches@sourceware.org
> From: Pedro Alves <palves@redhat.com>
> Date: Fri, 1 Mar 2019 14:10:00 +0000
> 
> I'm saying that there's an easy way out that likely
> gets you styling without much work.  Over time, older versions of
> Windows will fade away.

That's a long wait, IMO.

> I'm comparing to the current state, where there's no styling at all.

That's not yet a "state", since GDB 8.3 was not yet released ;-)

> If someone's willing to implement that, it's super fine with me.

Thank you, then I will continue working on this.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-01  7:47     ` Eli Zaretskii
@ 2019-03-01 18:42       ` Tom Tromey
  2019-03-01 19:40         ` Eli Zaretskii
  2019-03-04 16:04       ` Eli Zaretskii
  1 sibling, 1 reply; 99+ messages in thread
From: Tom Tromey @ 2019-03-01 18:42 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Tom Tromey, gdb-patches

>>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes:

>> I think either utils.c would have to be modified to change where it
>> sends output, or stdio_file::puts would have to be modified.  The idea
>> there would be to call a host-specific function; and then on Windows do
>> the filtering+styling if the output is going to the terminal.

Eli> I'm looking into this now.  The simplest change would be to modify
Eli> stdio_file::puts that performs the filtering only on Windows, but the
Eli> fact that you mentioned calling a host-specific function confuses me a
Eli> little.  Can you elaborate on what you had in mind, and specifically
Eli> what kind of a host-specific function should be involved here, and
Eli> how?

Right now styling works because, in the end, ANSI escape sequences are
emitted via stdio_file::puts, which just calls fputs.

However, my understanding is that the Windows console instead requires
styling to be done by making various API calls.

So, the idea is to replace stdio_file::puts with a function that, for
the Windows console only, parses out the ANSI escapes from the output
string and replaces those with the appropriate API calls.

This made sense to me as a host-dependent function of some kind.  But I
don't really know.

The TUI does essentially this in order to convert ANSI escapes into
curses calls.  See tui-io.c:tui_puts_internal and apply_ansi_escape.
The parsing work is done by the method ui_file_style::parse.

Tom

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-01 18:42       ` Tom Tromey
@ 2019-03-01 19:40         ` Eli Zaretskii
  2019-03-01 21:04           ` Tom Tromey
  0 siblings, 1 reply; 99+ messages in thread
From: Eli Zaretskii @ 2019-03-01 19:40 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

> From: Tom Tromey <tom@tromey.com>
> Cc: Tom Tromey <tom@tromey.com>,  gdb-patches@sourceware.org
> Date: Fri, 01 Mar 2019 11:42:39 -0700
> 
> Right now styling works because, in the end, ANSI escape sequences are
> emitted via stdio_file::puts, which just calls fputs.
> 
> However, my understanding is that the Windows console instead requires
> styling to be done by making various API calls.
> 
> So, the idea is to replace stdio_file::puts with a function that, for
> the Windows console only, parses out the ANSI escapes from the output
> string and replaces those with the appropriate API calls.

Right.  My question is about the details, or, more accurately, about
stylistic conventions and policies in such cases.

> This made sense to me as a host-dependent function of some kind.  But I
> don't really know.

I'm not sure I understand how to call that host-dependent function.
You don't mean #ifdef, do you?  My idea was to do something like

  void
  stdio_file::puts (const char *linebuffer)
  {
  #ifdef _WIN32
    w32_fputs (linebuffer, m_file);
  #else
    /* Calling error crashes when we are called from the exception framework.  */
    if (fputs (linebuffer, m_file))
      {
	/* Nothing.  */
      }
  #endif
  }

where w32_fputs will DTRT for Windows.  If this is not what you had in
mind, can you maybe point me to a place where host-dependent functions
are called?

> The TUI does essentially this in order to convert ANSI escapes into
> curses calls.  See tui-io.c:tui_puts_internal and apply_ansi_escape.
> The parsing work is done by the method ui_file_style::parse.

Right, but TUI overrides the puts method, which is not what I need to
do here.

Thanks.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-01 19:40         ` Eli Zaretskii
@ 2019-03-01 21:04           ` Tom Tromey
  2019-03-02  7:15             ` Eli Zaretskii
                               ` (2 more replies)
  0 siblings, 3 replies; 99+ messages in thread
From: Tom Tromey @ 2019-03-01 21:04 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Tom Tromey, gdb-patches

>>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes:

Eli> I'm not sure I understand how to call that host-dependent function.
Eli> You don't mean #ifdef, do you?  My idea was to do something like
[...]

Eli> where w32_fputs will DTRT for Windows.  If this is not what you had in
Eli> mind, can you maybe point me to a place where host-dependent functions
Eli> are called?

Another way would be to just make a new function and implement it
differently in mingw-hdep.c and in posix-hdep.c.

Tom

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-01 21:04           ` Tom Tromey
@ 2019-03-02  7:15             ` Eli Zaretskii
  2019-03-03 15:42             ` Eli Zaretskii
  2019-03-03 15:53             ` Eli Zaretskii
  2 siblings, 0 replies; 99+ messages in thread
From: Eli Zaretskii @ 2019-03-02  7:15 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

> From: Tom Tromey <tom@tromey.com>
> Cc: Tom Tromey <tom@tromey.com>,  gdb-patches@sourceware.org
> Date: Fri, 01 Mar 2019 14:03:58 -0700
> 
> Eli> where w32_fputs will DTRT for Windows.  If this is not what you had in
> Eli> mind, can you maybe point me to a place where host-dependent functions
> Eli> are called?
> 
> Another way would be to just make a new function and implement it
> differently in mingw-hdep.c and in posix-hdep.c.

OK, thanks, I think I see what I need to do.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-01 21:04           ` Tom Tromey
  2019-03-02  7:15             ` Eli Zaretskii
@ 2019-03-03 15:42             ` Eli Zaretskii
  2019-03-04 15:08               ` Tom Tromey
  2019-03-03 15:53             ` Eli Zaretskii
  2 siblings, 1 reply; 99+ messages in thread
From: Eli Zaretskii @ 2019-03-03 15:42 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

> From: Tom Tromey <tom@tromey.com>
> Cc: Tom Tromey <tom@tromey.com>,  gdb-patches@sourceware.org
> Date: Fri, 01 Mar 2019 14:03:58 -0700
> 
> Another way would be to just make a new function and implement it
> differently in mingw-hdep.c and in posix-hdep.c.

Here's a working prototype I'm currently testing.  If this
implementation strategy is acceptable, I will post a proper patch
soon.

Thanks for the guidance.

--- ./gdb/cli/cli-style.c~1	2019-02-27 06:51:50.000000000 +0200
+++ ./gdb/cli/cli-style.c	2019-03-03 17:26:34.122234300 +0200
@@ -24,7 +24,7 @@
 
 /* True if styling is enabled.  */
 
-#if defined(_WIN32) || defined (__CYGWIN__)
+#if defined (__MSDOS__) || defined (__CYGWIN__)
 int cli_styling = 0;
 #else
 int cli_styling = 1;
--- ./gdb/mingw-hdep.c~1	2019-02-27 06:51:50.000000000 +0200
+++ ./gdb/mingw-hdep.c	2019-03-03 17:15:24.608418300 +0200
@@ -177,3 +177,166 @@ gdb_select (int n, fd_set *readfds, fd_s
 
   return num_ready;
 }
+
+/* Zero if not yet initialized, 1 if stdout is a console device, else -1.  */
+static int mingw_console_initialized;
+
+/* Handle to stdout . */
+static HANDLE hstdout = INVALID_HANDLE_VALUE;
+
+/* Text attribute to use for normal text (the "none" pseudo-color).  */
+static SHORT  norm_attr;
+
+/* The most recently applied style.  */
+static ui_file_style last_style;
+
+/* Alternative for the libc 'fputs' which handles embedded SGR
+   sequences in support of styling.  */
+
+int
+gdb_console_fputs (const char *linebuf, FILE *fstream)
+{
+  if (!mingw_console_initialized)
+    {
+      hstdout = (HANDLE)_get_osfhandle (fileno (fstream));
+      DWORD cmode;
+      CONSOLE_SCREEN_BUFFER_INFO csbi;
+
+      if (hstdout != INVALID_HANDLE_VALUE
+	  && GetConsoleMode (hstdout, &cmode) != 0
+	  && GetConsoleScreenBufferInfo (hstdout, &csbi))
+	{
+	  norm_attr = csbi.wAttributes;
+	  mingw_console_initialized = 1;
+	}
+      else if (hstdout != INVALID_HANDLE_VALUE)
+	mingw_console_initialized = -1; /* valid, but not a console device */
+    }
+  /* If our stdout is not a console device, let the default 'fputs'
+     handle the task. */
+  if (mingw_console_initialized <= 0)
+    return 0;
+
+  /* Mapping between 8 ANSI colors and Windows console attributes.  */
+  static int fg_color[] = {
+    0,					/* black */
+    FOREGROUND_RED,			/* red */
+    FOREGROUND_GREEN,			/* green */
+    FOREGROUND_GREEN | FOREGROUND_RED,	/* yellow */
+    FOREGROUND_BLUE,			/* blue */
+    FOREGROUND_BLUE | FOREGROUND_RED,	/* magenta */
+    FOREGROUND_BLUE | FOREGROUND_GREEN, /* cyan */
+    FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE /* gray */
+  };
+  static int bg_color[] = {
+    0,					/* black */
+    BACKGROUND_RED,			/* red */
+    BACKGROUND_GREEN,			/* green */
+    BACKGROUND_GREEN | BACKGROUND_RED,	/* yellow */
+    BACKGROUND_BLUE,			/* blue */
+    BACKGROUND_BLUE | BACKGROUND_RED,	/* magenta */
+    BACKGROUND_BLUE | BACKGROUND_GREEN, /* cyan */
+    BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE /* gray */
+  };
+
+  ui_file_style style = last_style;
+  unsigned char c;
+  size_t n_read;
+
+  for ( ; (c = *linebuf) != 0; linebuf += n_read)
+    {
+      if (c == '\033')
+	{
+	  fflush (fstream);
+	  bool parsed = style.parse (linebuf, &n_read);
+	  if (n_read <= 0)	/* should never happen */
+	    n_read = 1;
+	  if (!parsed)
+	    {
+	      /* This means we silently swallow SGR sequences we
+		 cannot parse.  */
+	      continue;
+	    }
+	  /* Colors.  */
+	  const ui_file_style::color &fg = style.get_foreground ();
+	  const ui_file_style::color &bg = style.get_background ();
+	  int fgcolor, bgcolor, bright, inverse;
+	  if (fg.is_none ())
+	    fgcolor = norm_attr & 15;
+	  else
+	    fgcolor = fg_color[fg.get_value () & 15];
+	  if (bg.is_none ())
+	    bgcolor = norm_attr & (15 << 4);
+	  else
+	    bgcolor = bg_color[bg.get_value () & 15];
+
+	  /* Intensity.  */
+	  switch (style.get_intensity ())
+	    {
+	    case ui_file_style::NORMAL:
+	    case ui_file_style::DIM:
+	      bright = 0;
+	      break;
+	    case ui_file_style::BOLD:
+	      bright = 1;
+	      break;
+	    default:
+	      gdb_assert_not_reached ("invalid intensity");
+	    }
+
+	  /* Inverse video.  */
+	  if (style.is_reverse ())
+	    inverse = 1;
+	  else
+	    inverse = 0;
+
+	  /* Construct the attribute.  */
+	  if (inverse)
+	    {
+	      int t = fgcolor;
+	      fgcolor = (bgcolor >> 4);
+	      bgcolor = (t << 4);
+	    }
+	  if (bright)
+	    fgcolor |= FOREGROUND_INTENSITY;
+
+	  SHORT attr = (bgcolor & (15 << 4)) | (fgcolor & 15);
+
+	  /* Apply the attribute.  */
+	  SetConsoleTextAttribute (hstdout, attr);
+	}
+      else
+	{
+	  /* When we are about to write newline, we need to clear to
+	     EOL with the normal attribute, to avoid spilling the
+	     colors to the next screen line.  We assume here that no
+	     non-default attribute extends beyond the newline.  */
+	  if (c == '\n')
+	    {
+	      DWORD nchars;
+	      COORD start_pos;
+	      DWORD written;
+	      CONSOLE_SCREEN_BUFFER_INFO csbi;
+
+	      fflush (fstream);
+	      GetConsoleScreenBufferInfo (hstdout, &csbi);
+
+	      if (csbi.wAttributes != norm_attr)
+		{
+		  start_pos = csbi.dwCursorPosition;
+		  nchars = csbi.dwSize.X - start_pos.X;
+
+		  FillConsoleOutputAttribute (hstdout, norm_attr, nchars,
+					      start_pos, &written);
+		  FillConsoleOutputCharacter (hstdout, ' ', nchars,
+					      start_pos, &written);
+		}
+	    }
+	  fputc (c, fstream);
+	  n_read = 1;
+	}
+    }
+
+  last_style = style;
+  return 1;
+}
--- ./gdb/posix-hdep.c~1	2019-02-27 06:51:50.000000000 +0200
+++ ./gdb/posix-hdep.c	2019-03-03 17:34:32.870539500 +0200
@@ -30,3 +30,11 @@ gdb_select (int n, fd_set *readfds, fd_s
 {
   return select (n, readfds, writefds, exceptfds, timeout);
 }
+
+/* Host-dependent console fputs method.  POSIX platforms always return
+   zero, to use the default C 'fputs'.  */
+int
+gdb_console_fputs (const char *buf, FILE *f)
+{
+  return 0;
+}
--- ./gdb/ui-file.c~1	2019-02-27 06:51:50.000000000 +0200
+++ ./gdb/ui-file.c	2019-03-03 17:32:02.526701100 +0200
@@ -236,6 +236,12 @@ stdio_file::write_async_safe (const char
 void
 stdio_file::puts (const char *linebuffer)
 {
+  /* This host-dependent function (with implementations in
+     posix-hdep.c and mingw-hdep.c) is given the opportunity to
+     process the output first in host-dependent way.  If it does, it
+     should return non-zero, to avoid calling fputs below.  */
+  if (gdb_console_fputs (linebuffer, m_file))
+    return;
   /* Calling error crashes when we are called from the exception framework.  */
   if (fputs (linebuffer, m_file))
     {
--- ./gdb/ui-file.h~1	2019-02-27 06:51:50.000000000 +0200
+++ ./gdb/ui-file.h	2019-03-03 17:40:00.605222700 +0200
@@ -101,6 +101,8 @@
 
 extern long ui_file_read (struct ui_file *file, char *buf, long length_buf);
 
+extern int gdb_console_fputs (const char *, FILE *);
+
 /* A std::string-based ui_file.  Can be used as a scratch buffer for
    collecting output.  */
 
--- ./gdb/utils.c~1	2019-02-27 06:51:50.000000000 +0200
+++ ./gdb/utils.c	2019-03-03 17:39:30.222675900 +0200
@@ -1456,8 +1456,18 @@ can_emit_style_escape (struct ui_file *s
       || !ui_file_isatty (stream))
     return false;
   const char *term = getenv ("TERM");
+  /* Windows doesn't by default define $TERM, but can support styles
+     regardless.  */
+#ifndef _WIN32
   if (term == nullptr || !strcmp (term, "dumb"))
     return false;
+#else
+  /* But if they do define $TERM, let us behave the same as on Posix
+     platforms, for the benefit of programs which invoke GDB as their
+     back-end.  */
+  if (term && !strcmp (term, "dumb"))
+    return false;
+#endif
   return true;
 }
 

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-01 21:04           ` Tom Tromey
  2019-03-02  7:15             ` Eli Zaretskii
  2019-03-03 15:42             ` Eli Zaretskii
@ 2019-03-03 15:53             ` Eli Zaretskii
  2019-03-03 16:16               ` Matt Rice
  2019-03-04 15:01               ` Tom Tromey
  2 siblings, 2 replies; 99+ messages in thread
From: Eli Zaretskii @ 2019-03-03 15:53 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

A few minor comments and questions related to this feature:

 . What should be the behavior wrt styling when GDB is used as a
   back-end debugging engine?  E.g., Emacs can act as the GUI
   front-end to GDB -- should styling be turned off in that case?  On
   Windows, it will be urned off, because Emacs communicates with GDB
   via pipes, but on Posix hosts Emacs uses pty's, so GDB will think
   its stdout is a tty device, right?

 . I'm surprised there's no CLI support for requesting the
   "inverse-video" style, although the infrastructure does support the
   corresponding escape sequences.  Is that on purpose?

 . The default foreground color used for addresses, blue, is too dark
   when the terminal's background is black.  Maybe we should change to
   magenta, which should look OK on both dark and light backgrounds.

And one more issue, only tangentially related: if I put on my
~/.gdbinit settings that customize style, older versions of GDB
complain when they start up, because they don't know about styles.  Is
there any way of conditioning scripting commands on the GDB version,
or some other way of avoiding such problems?

Thanks.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-03 15:53             ` Eli Zaretskii
@ 2019-03-03 16:16               ` Matt Rice
  2019-03-03 17:13                 ` Eli Zaretskii
  2019-03-04 15:01               ` Tom Tromey
  1 sibling, 1 reply; 99+ messages in thread
From: Matt Rice @ 2019-03-03 16:16 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Tom Tromey, gdb-patches

On Sun, Mar 3, 2019 at 7:53 AM Eli Zaretskii <eliz@gnu.org> wrote:
>
> A few minor comments and questions related to this feature:
>
> And one more issue, only tangentially related: if I put on my
> ~/.gdbinit settings that customize style, older versions of GDB
> complain when they start up, because they don't know about styles.  Is
> there any way of conditioning scripting commands on the GDB version,
> or some other way of avoiding such problems?

I didn't see a easy way to get the gdb version from python,
except parsing the output of "show version", perhaps I missed it.

but I have added stuff conditional on the inferior binary name before..
py
def on_bin_echo(): gdb.execute("set arg -d")
exec_funcs = {"/bin/echo" : on_bin_echo}
map(lambda x: exec_funcs[x.filename]() if
exec_funcs.has_key(x.filename) else None, gdb.objfiles())
end

You should be able to do the same by parsing the output of 'show version',
However, given that, I think it'd be better in this case to just try
and use the gdb.parameter API from python to set the setting,
and handling any exception which should be thrown for old gdb without
the appropriate parameter.

If the gdb in question python or guile, I really have no idea, but i
hope that helps.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-03 16:16               ` Matt Rice
@ 2019-03-03 17:13                 ` Eli Zaretskii
  2019-03-03 18:04                   ` Matt Rice
  0 siblings, 1 reply; 99+ messages in thread
From: Eli Zaretskii @ 2019-03-03 17:13 UTC (permalink / raw)
  To: Matt Rice; +Cc: tom, gdb-patches

> From: Matt Rice <ratmice@gmail.com>
> Date: Sun, 3 Mar 2019 08:16:27 -0800
> Cc: Tom Tromey <tom@tromey.com>, 
> 	"gdb-patches@sourceware.org" <gdb-patches@sourceware.org>
> 
> I didn't see a easy way to get the gdb version from python,
> except parsing the output of "show version", perhaps I missed it.
> 
> but I have added stuff conditional on the inferior binary name before..
> py
> def on_bin_echo(): gdb.execute("set arg -d")
> exec_funcs = {"/bin/echo" : on_bin_echo}
> map(lambda x: exec_funcs[x.filename]() if
> exec_funcs.has_key(x.filename) else None, gdb.objfiles())
> end
> 
> You should be able to do the same by parsing the output of 'show version',
> However, given that, I think it'd be better in this case to just try
> and use the gdb.parameter API from python to set the setting,
> and handling any exception which should be thrown for old gdb without
> the appropriate parameter.

Thanks.  I hoped for a way that would avoid using Python or Guile, but
I guess you are saying there is no such way, is that right?

Maybe we should add a convenience variable $_gdb_version ?

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-03 17:13                 ` Eli Zaretskii
@ 2019-03-03 18:04                   ` Matt Rice
  0 siblings, 0 replies; 99+ messages in thread
From: Matt Rice @ 2019-03-03 18:04 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Tom Tromey, gdb-patches

On Sun, Mar 3, 2019 at 9:13 AM Eli Zaretskii <eliz@gnu.org> wrote:
>
> > From: Matt Rice <ratmice@gmail.com>
> > Date: Sun, 3 Mar 2019 08:16:27 -0800
> > Cc: Tom Tromey <tom@tromey.com>,
> >       "gdb-patches@sourceware.org" <gdb-patches@sourceware.org>
> >
> > I didn't see a easy way to get the gdb version from python,
> > except parsing the output of "show version", perhaps I missed it.
> >
> > but I have added stuff conditional on the inferior binary name before..
> > py
> > def on_bin_echo(): gdb.execute("set arg -d")
> > exec_funcs = {"/bin/echo" : on_bin_echo}
> > map(lambda x: exec_funcs[x.filename]() if
> > exec_funcs.has_key(x.filename) else None, gdb.objfiles())
> > end
> >
> > You should be able to do the same by parsing the output of 'show version',
> > However, given that, I think it'd be better in this case to just try
> > and use the gdb.parameter API from python to set the setting,
> > and handling any exception which should be thrown for old gdb without
> > the appropriate parameter.
>
> Thanks.  I hoped for a way that would avoid using Python or Guile, but
> I guess you are saying there is no such way, is that right?
>
> Maybe we should add a convenience variable $_gdb_version ?

I'm not going to say there is no way, I just don't know of one which
is robust/portable/palatable.
If you can use the gdb shell command , and get the parent PID/path to
the gdb from there, then write out a gdb script
after that source the newly generated script

So, perhaps I'm missing some obvious/nice way, but i don't really know, sorry.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-03 15:53             ` Eli Zaretskii
  2019-03-03 16:16               ` Matt Rice
@ 2019-03-04 15:01               ` Tom Tromey
  2019-03-04 17:37                 ` Eli Zaretskii
  1 sibling, 1 reply; 99+ messages in thread
From: Tom Tromey @ 2019-03-04 15:01 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Tom Tromey, gdb-patches

>>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes:

Eli>  . What should be the behavior wrt styling when GDB is used as a
Eli>    back-end debugging engine?  E.g., Emacs can act as the GUI
Eli>    front-end to GDB -- should styling be turned off in that case?  On
Eli>    Windows, it will be urned off, because Emacs communicates with GDB
Eli>    via pipes, but on Posix hosts Emacs uses pty's, so GDB will think
Eli>    its stdout is a tty device, right?

Yes, it will.  I think for cases like gud-gdb (where the ordinary CLI is
used) that it makes sense for Emacs to use gdb's styling.  For MI, I
think there is no styling, and Emacs can do what it likes.

Eli>  . I'm surprised there's no CLI support for requesting the
Eli>    "inverse-video" style, although the infrastructure does support the
Eli>    corresponding escape sequences.  Is that on purpose?

It just didn't seem super important, but I'm not opposed if you want to
add it.

It would also be possible to add support for 24 bit color, but I didn't
do that either.

Eli>  . The default foreground color used for addresses, blue, is too dark
Eli>    when the terminal's background is black.  Maybe we should change to
Eli>    magenta, which should look OK on both dark and light backgrounds.

For me magenta is even darker.  Setting the intensity to bold might be
more acceptable?

Eli> And one more issue, only tangentially related: if I put on my
Eli> ~/.gdbinit settings that customize style, older versions of GDB
Eli> complain when they start up, because they don't know about styles.  Is
Eli> there any way of conditioning scripting commands on the GDB version,
Eli> or some other way of avoiding such problems?

Nothing built in, this is a longstanding issue when adding new settings
to gdb.

Tom

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-03 15:42             ` Eli Zaretskii
@ 2019-03-04 15:08               ` Tom Tromey
  2019-03-04 15:57                 ` Eli Zaretskii
  0 siblings, 1 reply; 99+ messages in thread
From: Tom Tromey @ 2019-03-04 15:08 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Tom Tromey, gdb-patches

>>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes:

Eli> Here's a working prototype I'm currently testing.  If this
Eli> implementation strategy is acceptable, I will post a proper patch
Eli> soon.

It looks reasonable to me.

Eli> +	  if (fg.is_none ())
Eli> +	    fgcolor = norm_attr & 15;
Eli> +	  else
Eli> +	    fgcolor = fg_color[fg.get_value () & 15];

get_value is only defined for basic colors; you'll get an assertion here
if the color is not basic.  For non-basic colors, you can get the rgb
values for the color instead via the get_rgb method.

Tom

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-04 15:08               ` Tom Tromey
@ 2019-03-04 15:57                 ` Eli Zaretskii
  2019-03-04 16:16                   ` Tom Tromey
  0 siblings, 1 reply; 99+ messages in thread
From: Eli Zaretskii @ 2019-03-04 15:57 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

> From: Tom Tromey <tom@tromey.com>
> Cc: Tom Tromey <tom@tromey.com>,  gdb-patches@sourceware.org
> Date: Mon, 04 Mar 2019 08:08:47 -0700
> 
> Eli> +	  if (fg.is_none ())
> Eli> +	    fgcolor = norm_attr & 15;
> Eli> +	  else
> Eli> +	    fgcolor = fg_color[fg.get_value () & 15];
> 
> get_value is only defined for basic colors; you'll get an assertion here
> if the color is not basic.  For non-basic colors, you can get the rgb
> values for the color instead via the get_rgb method.

I've seen the assertion in the code, but it wasn't clear to me when/if
I could get non-basic colors on MS-Windows.  Could you describe a
situation where that could happen?

Thanks.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-01  7:47     ` Eli Zaretskii
  2019-03-01 18:42       ` Tom Tromey
@ 2019-03-04 16:04       ` Eli Zaretskii
  1 sibling, 0 replies; 99+ messages in thread
From: Eli Zaretskii @ 2019-03-04 16:04 UTC (permalink / raw)
  To: tom; +Cc: gdb-patches

> Date: Fri, 01 Mar 2019 09:47:23 +0200
> From: Eli Zaretskii <eliz@gnu.org>
> CC: gdb-patches@sourceware.org
> 
> > Eli> Will the Windows TUI build support styling out of the box?  It uses
> > Eli> ncurses.
> > 
> > I think it should work, but you'd have to "set style enabled on" first.
> 
> For the record, it doesn't work in GDB 8.2.90, even after I disabled
> the test for $TERM being defined in the environment.  I will try to
> find out why at some point.

OK, I now know why.  The colors do work, but only if the style
specifies both the foreground and the background colors explicitly;
specifying just one of them causes no colors at all (but other
attributes, like intensity, do still work).

I think this means that the MS-Windows console belongs to the devices
which don't support resetting to the default colors.  I even tried to
add the call to assume_default_colors, per the ncurses docs, to no
avail.

Are there any other consoles out there with such an issue?

In any case, I think we should at least tell in the manual that on
some systems the color pairs need to be specified completely, even if
only one of the two colors changes from the default.  Does anyone have
ideas how to do better than just documenting this?  Let the user
define the default fore- and back-ground colors, perhaps?

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-04 15:57                 ` Eli Zaretskii
@ 2019-03-04 16:16                   ` Tom Tromey
  2019-03-05 15:38                     ` Eli Zaretskii
  0 siblings, 1 reply; 99+ messages in thread
From: Tom Tromey @ 2019-03-04 16:16 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Tom Tromey, gdb-patches

>>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes:

Eli> I've seen the assertion in the code, but it wasn't clear to me when/if
Eli> I could get non-basic colors on MS-Windows.  Could you describe a
Eli> situation where that could happen?

The user can do it from the command line:

(gdb) printf "\e[38;2;255;100;0mTRUECOLOR\e[0m\n"

Maybe it can be done via GNU Source Highlight as well, though I am not
totally sure.

Tom

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-04 15:01               ` Tom Tromey
@ 2019-03-04 17:37                 ` Eli Zaretskii
  2019-03-04 17:40                   ` Tom Tromey
  2019-03-07  6:02                   ` Joel Brobecker
  0 siblings, 2 replies; 99+ messages in thread
From: Eli Zaretskii @ 2019-03-04 17:37 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

> From: Tom Tromey <tom@tromey.com>
> Cc: Tom Tromey <tom@tromey.com>,  gdb-patches@sourceware.org
> Date: Mon, 04 Mar 2019 08:01:49 -0700
> 
> Eli>  . The default foreground color used for addresses, blue, is too dark
> Eli>    when the terminal's background is black.  Maybe we should change to
> Eli>    magenta, which should look OK on both dark and light backgrounds.
> 
> For me magenta is even darker.  Setting the intensity to bold might be
> more acceptable?

Still too dark.  I guess we will need to leave this to personal
customizations.

> Eli> And one more issue, only tangentially related: if I put on my
> Eli> ~/.gdbinit settings that customize style, older versions of GDB
> Eli> complain when they start up, because they don't know about styles.  Is
> Eli> there any way of conditioning scripting commands on the GDB version,
> Eli> or some other way of avoiding such problems?
> 
> Nothing built in, this is a longstanding issue when adding new settings
> to gdb.

What do you think about the idea to add a convenience variable that
would provide the GDB version?

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-04 17:37                 ` Eli Zaretskii
@ 2019-03-04 17:40                   ` Tom Tromey
  2019-03-06 16:02                     ` Eli Zaretskii
  2019-03-07  6:02                   ` Joel Brobecker
  1 sibling, 1 reply; 99+ messages in thread
From: Tom Tromey @ 2019-03-04 17:40 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Tom Tromey, gdb-patches

>>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes:

>> Nothing built in, this is a longstanding issue when adding new settings
>> to gdb.

Eli> What do you think about the idea to add a convenience variable that
Eli> would provide the GDB version?

Seems reasonable to me.

Something I've done in the past is have an "ignore-errors" command in
Python so I can just "ignore-errors set some-new-thing ...".

Tom

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-04 16:16                   ` Tom Tromey
@ 2019-03-05 15:38                     ` Eli Zaretskii
  2019-03-08 14:55                       ` Eli Zaretskii
  0 siblings, 1 reply; 99+ messages in thread
From: Eli Zaretskii @ 2019-03-05 15:38 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

> From: Tom Tromey <tom@tromey.com>
> Cc: Tom Tromey <tom@tromey.com>,  gdb-patches@sourceware.org
> Date: Mon, 04 Mar 2019 09:16:25 -0700
> 
> (gdb) printf "\e[38;2;255;100;0mTRUECOLOR\e[0m\n"

Thanks, I used this example (and its variations) to extend the support
to any kind of color.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-04 17:40                   ` Tom Tromey
@ 2019-03-06 16:02                     ` Eli Zaretskii
  2019-03-20 19:35                       ` GDB version as convenience variable Eli Zaretskii
  2019-03-21  1:55                       ` [PATCH 00/16] Add styling to the gdb CLI and TUI Simon Marchi
  0 siblings, 2 replies; 99+ messages in thread
From: Eli Zaretskii @ 2019-03-06 16:02 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

> From: Tom Tromey <tom@tromey.com>
> Cc: Tom Tromey <tom@tromey.com>,  gdb-patches@sourceware.org
> Date: Mon, 04 Mar 2019 10:40:46 -0700
> 
> >>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes:
> 
> Eli> What do you think about the idea to add a convenience variable that
> Eli> would provide the GDB version?
> 
> Seems reasonable to me.

How about the patch below?  Is it okay to go in?  (Note that I took
this opportunity to clean up whitespace in top.c, I hope it's OK to do
that as part of unrelated code changes.)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index ac61e65..f2915d0 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,10 @@
+2019-03-06  Eli Zaretskii  <eliz@gnu.org>
+
+	* NEWS: Announce $_gdb_version.
+
+	* top.c (init_gdb_version_var): New function.
+	(gdb_init): Call init_gdb_version_var.
+
 2019-03-06  Tom Tromey  <tromey@adacore.com>
 
 	* remote-sim.c (gdbsim_target_open): Use result of
diff --git a/gdb/NEWS b/gdb/NEWS
index cc7c35c..260e6cc 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -3,6 +3,12 @@
 
 *** Changes since GDB 8.3
 
+* New built-in convenience variable $_gdb_version provides the GDB
+  version.  It is handy for conditionally using features available
+  only in or since specific GDB versions, in scripts that should work
+  error-free with many different versions, such as in system-wide init
+  files.
+
 *** Changes in GDB 8.3
 
 * GDB and GDBserver now support access to additional registers on
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index 0380322..313a061 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,3 +1,7 @@
+2019-03-06  Eli Zaretskii  <eliz@gnu.org>
+
+	* gdb.texinfo (Convenience Vars): Document $_gdb_version.
+
 2019-03-05  Simon Marchi  <simon.marchi@efficios.com>
 
 	* python.texi (Values From Inferior): Change synopsys of the
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index f2028f8..9d15337 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -11197,7 +11197,7 @@
 @vindex $_tlb@r{, convenience variable}
 The variable @code{$_tlb} is automatically set when debugging
 applications running on MS-Windows in native mode or connected to
-gdbserver that supports the @code{qGetTIBAddr} request. 
+gdbserver that supports the @code{qGetTIBAddr} request.
 @xref{General Query Packets}.
 This variable contains the address of the thread information block.
 
@@ -11211,6 +11211,17 @@
 @item $_gthread
 The global number of the current thread.  @xref{global thread numbers}.
 
+@item $_gdb_version
+@vindex $_gdb_version@r{, convenience variable}
+The version of the running @value{GDBN}.  The value is an integer
+number that encodes the major and minor @value{GDBN} versions as
+@w{@code{@var{major}*100 + @var{minor}}}, so, e.g., @value{GDBN}
+version 9.10 will produce the value @code{910}.  Development snapshots
+and pretest versions have their minor version incremented by one;
+thus, @value{GDBN} pretest 9.11.90 will produce the value 912.  This
+variable allows you to write scripts that work with different versions
+of @value{GDBN} without errors caused by features unavailable in some
+of those versions.
 @end table
 
 @node Convenience Funs
diff --git a/gdb/top.c b/gdb/top.c
index 22e6f7e..97b349a 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -147,22 +147,22 @@ int server_command;
 
 /* Timeout limit for response from target.  */
 
-/* The default value has been changed many times over the years.  It 
-   was originally 5 seconds.  But that was thought to be a long time 
+/* The default value has been changed many times over the years.  It
+   was originally 5 seconds.  But that was thought to be a long time
    to sit and wait, so it was changed to 2 seconds.  That was thought
-   to be plenty unless the connection was going through some terminal 
+   to be plenty unless the connection was going through some terminal
    server or multiplexer or other form of hairy serial connection.
 
-   In mid-1996, remote_timeout was moved from remote.c to top.c and 
+   In mid-1996, remote_timeout was moved from remote.c to top.c and
    it began being used in other remote-* targets.  It appears that the
    default was changed to 20 seconds at that time, perhaps because the
    Renesas E7000 ICE didn't always respond in a timely manner.
 
    But if 5 seconds is a long time to sit and wait for retransmissions,
-   20 seconds is far worse.  This demonstrates the difficulty of using 
+   20 seconds is far worse.  This demonstrates the difficulty of using
    a single variable for all protocol timeouts.
 
-   As remote.c is used much more than remote-e7000.c, it was changed 
+   As remote.c is used much more than remote-e7000.c, it was changed
    back to 2 seconds in 1999.  */
 
 int remote_timeout = 2;
@@ -188,9 +188,9 @@ int (*deprecated_ui_loop_hook) (int);
 
 /* Called from print_frame_info to list the line we stopped in.  */
 
-void (*deprecated_print_frame_info_listing_hook) (struct symtab * s, 
+void (*deprecated_print_frame_info_listing_hook) (struct symtab * s,
 						  int line,
-						  int stopline, 
+						  int stopline,
 						  int noerror);
 /* Replaces most of query.  */
 
@@ -237,7 +237,7 @@ ptid_t (*deprecated_target_wait_hook) (ptid_t ptid,
 /* Used by UI as a wrapper around command execution.  May do various
    things like enabling/disabling buttons, etc...  */
 
-void (*deprecated_call_command_hook) (struct cmd_list_element * c, 
+void (*deprecated_call_command_hook) (struct cmd_list_element * c,
 				      const char *cmd, int from_tty);
 
 /* Called when the current thread changes.  Argument is thread id.  */
@@ -1339,8 +1339,9 @@ There is NO WARRANTY, to the extent permitted by law.");
 resources online at:\n    <http://www.gnu.org/software/gdb/documentation/>."));
   fprintf_filtered (stream, "\n\n");
   fprintf_filtered (stream, _("For help, type \"help\".\n"));
-  fprintf_filtered (stream, _("Type \"apropos word\" to search for \
-commands related to \"word\"."));
+  fprintf_filtered (stream,
+		    _("Type \"apropos word\" to search for commands \
+related to \"word\"."));
 }
 
 /* Print the details of GDB build-time configuration.  */
@@ -1608,7 +1609,7 @@ quit_force (int *exit_arg, int from_tty)
 
   undo_terminal_modifications_before_exit ();
 
-  /* An optional expression may be used to cause gdb to terminate with the 
+  /* An optional expression may be used to cause gdb to terminate with the
      value of that expression.  */
   if (exit_arg)
     exit_code = *exit_arg;
@@ -1998,11 +1999,21 @@ set_history_filename (const char *args,
      directories the file written will be the same as the one
      that was read.  */
   if (!IS_ABSOLUTE_PATH (history_filename))
-    history_filename = reconcat (history_filename, current_directory, "/", 
+    history_filename = reconcat (history_filename, current_directory, "/",
 				 history_filename, (char *) NULL);
 }
 
 static void
+init_gdb_version_var (void)
+{
+  struct internalvar *version_var = create_internalvar ("_gdb_version");
+  int vmajor = 0, vminor = 0, vrevision = 0;
+  sscanf (version, "%d.%d.%d", &vmajor, &vminor, &vrevision);
+  set_internalvar_integer (version_var,
+			   vmajor * 100 + vminor + (vrevision > 0));
+}
+
+static void
 init_main (void)
 {
   struct cmd_list_element *c;
@@ -2206,4 +2217,7 @@ gdb_init (char *argv0)
      prefix to be installed.  Keep things simple and just do final
      script initialization here.  */
   finish_ext_lang_initialization ();
+
+  /* Create $_gdb_version convenience variable.  */
+  init_gdb_version_var ();
 }

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-04 17:37                 ` Eli Zaretskii
  2019-03-04 17:40                   ` Tom Tromey
@ 2019-03-07  6:02                   ` Joel Brobecker
  2019-03-07 14:53                     ` Eli Zaretskii
  1 sibling, 1 reply; 99+ messages in thread
From: Joel Brobecker @ 2019-03-07  6:02 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Tom Tromey, gdb-patches

> > Eli>  . The default foreground color used for addresses, blue, is too dark
> > Eli>    when the terminal's background is black.  Maybe we should change to
> > Eli>    magenta, which should look OK on both dark and light backgrounds.
> > 
> > For me magenta is even darker.  Setting the intensity to bold might be
> > more acceptable?
> 
> Still too dark.  I guess we will need to leave this to personal
> customizations.

My idea was to mimick what vim does: It actually has two sets of
settings, one for dark terminals, and one for bright ones. Each set
uses similar colors by default, but adapted for the brightness
of the terminal.

For more info, check out vim's help for "set background=[dark|light]".

-- 
Joel

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-07  6:02                   ` Joel Brobecker
@ 2019-03-07 14:53                     ` Eli Zaretskii
  2019-03-08  5:40                       ` Joel Brobecker
  0 siblings, 1 reply; 99+ messages in thread
From: Eli Zaretskii @ 2019-03-07 14:53 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: tom, gdb-patches

> Date: Thu, 7 Mar 2019 10:02:24 +0400
> From: Joel Brobecker <brobecker@adacore.com>
> Cc: Tom Tromey <tom@tromey.com>, gdb-patches@sourceware.org
> 
> > > For me magenta is even darker.  Setting the intensity to bold might be
> > > more acceptable?
> > 
> > Still too dark.  I guess we will need to leave this to personal
> > customizations.
> 
> My idea was to mimick what vim does: It actually has two sets of
> settings, one for dark terminals, and one for bright ones. Each set
> uses similar colors by default, but adapted for the brightness
> of the terminal.

Yes, Emacs does something similar.  But experience taught me that
automatically deducing whether the background is dark or light is a
Pandora box, so I won't suggest this for GDB, where this is after all
just a minor issue (unlike in editors).

But if you meant something like "set style background light" which
will change all the default colors, then I'm with you.  We just need
to come up with agreed-upon sets of colors.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-07 14:53                     ` Eli Zaretskii
@ 2019-03-08  5:40                       ` Joel Brobecker
  0 siblings, 0 replies; 99+ messages in thread
From: Joel Brobecker @ 2019-03-08  5:40 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: tom, gdb-patches

> Yes, Emacs does something similar.  But experience taught me that
> automatically deducing whether the background is dark or light is a
> Pandora box, so I won't suggest this for GDB, where this is after all
> just a minor issue (unlike in editors).

Agreed.

> But if you meant something like "set style background light" which
> will change all the default colors, then I'm with you.  We just need
> to come up with agreed-upon sets of colors.

Sounds like we're on the same page. I would go with the same colors
as right now, except for the few were it's hard to read; e.g. change
the dark blue for a cyan, for instance.

-- 
Joel

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-05 15:38                     ` Eli Zaretskii
@ 2019-03-08 14:55                       ` Eli Zaretskii
  2019-03-08 16:14                         ` Hannes Domani via gdb-patches
  2019-03-08 21:11                         ` Tom Tromey
  0 siblings, 2 replies; 99+ messages in thread
From: Eli Zaretskii @ 2019-03-08 14:55 UTC (permalink / raw)
  To: tom; +Cc: gdb-patches

> Date: Tue, 05 Mar 2019 17:38:32 +0200
> From: Eli Zaretskii <eliz@gnu.org>
> CC: gdb-patches@sourceware.org
> 
> > From: Tom Tromey <tom@tromey.com>
> > Cc: Tom Tromey <tom@tromey.com>,  gdb-patches@sourceware.org
> > Date: Mon, 04 Mar 2019 09:16:25 -0700
> > 
> > (gdb) printf "\e[38;2;255;100;0mTRUECOLOR\e[0m\n"
> 
> Thanks, I used this example (and its variations) to extend the support
> to any kind of color.

Here's the patch I propose to enable styling on native MS-Windows
console.

OK to commit, master and the release branch?

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index de5e74a..bb10c7d 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,21 @@
+2019-03-08  Eli Zaretskii  <eliz@gnu.org>
+
+	Support styling on native MS-Windows console
+
+	PR/24315
+	* utils.c (can_emit_style_escape) [_WIN32]: Don't disable styling
+	on MS-Windows if $TERM is not defined.
+
+	* cli/cli-style.c: Set cli_styling to 1 in the MinGW build.
+
+	* posix-hdep.c (gdb_console_fputs):
+	* mingw-hdep.c (rgb_to_16colors, gdb_console_fputs): New
+	functions.
+	* ui-file.h (gdb_console_fputs): Add prototype.
+
+	* ui-file.c (stdio_file::puts): Call gdb_console_fputs, and fall
+	back to fputs only if the former returns zero.
+
 2019-03-07  Tom Tromey  <tom@tromey.com>
 
 	* symmisc.c (print_symbol_bcache_statistics): Update.
diff --git a/gdb/cli/cli-style.c b/gdb/cli/cli-style.c
index 234cc41..ec385da 100644
--- a/gdb/cli/cli-style.c
+++ b/gdb/cli/cli-style.c
@@ -24,7 +24,7 @@
 
 /* True if styling is enabled.  */
 
-#if defined(_WIN32) || defined (__CYGWIN__)
+#if defined (__MSDOS__) || defined (__CYGWIN__)
 int cli_styling = 0;
 #else
 int cli_styling = 1;
diff --git a/gdb/mingw-hdep.c b/gdb/mingw-hdep.c
index 1a4b93b..8ed4b44 100644
--- a/gdb/mingw-hdep.c
+++ b/gdb/mingw-hdep.c
@@ -177,3 +177,195 @@ gdb_select (int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
 
   return num_ready;
 }
+
+/* Map COLOR's RGB triplet, with 8 bits per component, into 16 Windows
+   console colors, where each component has just 1 bit, plus a single
+   intensity bit which affects all 3 components.  */
+static int
+rgb_to_16colors (const ui_file_style::color &color)
+{
+  uint8_t rgb[3];
+  color.get_rgb (rgb);
+
+  int retval = 0;
+  for (int i = 0; i < 3; i++)
+    {
+      /* Subdivide 256 possible values of each RGB component into 3
+	 regions: no color, normal color, bright color.  256 / 3 = 85,
+	 but ui-style.c follows xterm and uses 92 for R and G
+	 components of the bright-blue color, so we bias the divisor a
+	 bit to have the bright colors between 9 and 15 identical to
+	 what ui-style.c expects.  */
+      int bits = rgb[i] / 93;
+      retval |= ((bits > 0) << (2 - i)) | ((bits > 1) << 3);
+    }
+
+  return retval;
+}
+
+/* Zero if not yet initialized, 1 if stdout is a console device, else -1.  */
+static int mingw_console_initialized;
+
+/* Handle to stdout . */
+static HANDLE hstdout = INVALID_HANDLE_VALUE;
+
+/* Text attribute to use for normal text (the "none" pseudo-color).  */
+static SHORT  norm_attr;
+
+/* The most recently applied style.  */
+static ui_file_style last_style;
+
+/* Alternative for the libc 'fputs' which handles embedded SGR
+   sequences in support of styling.  */
+
+int
+gdb_console_fputs (const char *linebuf, FILE *fstream)
+{
+  if (!mingw_console_initialized)
+    {
+      hstdout = (HANDLE)_get_osfhandle (fileno (fstream));
+      DWORD cmode;
+      CONSOLE_SCREEN_BUFFER_INFO csbi;
+
+      if (hstdout != INVALID_HANDLE_VALUE
+	  && GetConsoleMode (hstdout, &cmode) != 0
+	  && GetConsoleScreenBufferInfo (hstdout, &csbi))
+	{
+	  norm_attr = csbi.wAttributes;
+	  mingw_console_initialized = 1;
+	}
+      else if (hstdout != INVALID_HANDLE_VALUE)
+	mingw_console_initialized = -1; /* valid, but not a console device */
+    }
+  /* If our stdout is not a console device, let the default 'fputs'
+     handle the task. */
+  if (mingw_console_initialized <= 0)
+    return 0;
+
+  /* Mapping between 8 ANSI colors and Windows console attributes.  */
+  static int fg_color[] = {
+    0,					/* black */
+    FOREGROUND_RED,			/* red */
+    FOREGROUND_GREEN,			/* green */
+    FOREGROUND_GREEN | FOREGROUND_RED,	/* yellow */
+    FOREGROUND_BLUE,			/* blue */
+    FOREGROUND_BLUE | FOREGROUND_RED,	/* magenta */
+    FOREGROUND_BLUE | FOREGROUND_GREEN, /* cyan */
+    FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE /* gray */
+  };
+  static int bg_color[] = {
+    0,					/* black */
+    BACKGROUND_RED,			/* red */
+    BACKGROUND_GREEN,			/* green */
+    BACKGROUND_GREEN | BACKGROUND_RED,	/* yellow */
+    BACKGROUND_BLUE,			/* blue */
+    BACKGROUND_BLUE | BACKGROUND_RED,	/* magenta */
+    BACKGROUND_BLUE | BACKGROUND_GREEN, /* cyan */
+    BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE /* gray */
+  };
+
+  ui_file_style style = last_style;
+  unsigned char c;
+  size_t n_read;
+
+  for ( ; (c = *linebuf) != 0; linebuf += n_read)
+    {
+      if (c == '\033')
+	{
+	  fflush (fstream);
+	  bool parsed = style.parse (linebuf, &n_read);
+	  if (n_read <= 0)	/* should never happen */
+	    n_read = 1;
+	  if (!parsed)
+	    {
+	      /* This means we silently swallow SGR sequences we
+		 cannot parse.  */
+	      continue;
+	    }
+	  /* Colors.  */
+	  const ui_file_style::color &fg = style.get_foreground ();
+	  const ui_file_style::color &bg = style.get_background ();
+	  int fgcolor, bgcolor, bright, inverse;
+	  if (fg.is_none ())
+	    fgcolor = norm_attr & 15;
+	  else if (fg.is_basic ())
+	    fgcolor = fg_color[fg.get_value () & 15];
+	  else
+	    fgcolor = rgb_to_16colors (fg);
+	  if (bg.is_none ())
+	    bgcolor = norm_attr & (15 << 4);
+	  else if (bg.is_basic ())
+	    bgcolor = bg_color[bg.get_value () & 15];
+	  else
+	    bgcolor = rgb_to_16colors (bg) << 4;
+
+	  /* Intensity.  */
+	  switch (style.get_intensity ())
+	    {
+	    case ui_file_style::NORMAL:
+	    case ui_file_style::DIM:
+	      bright = 0;
+	      break;
+	    case ui_file_style::BOLD:
+	      bright = 1;
+	      break;
+	    default:
+	      gdb_assert_not_reached ("invalid intensity");
+	    }
+
+	  /* Inverse video.  */
+	  if (style.is_reverse ())
+	    inverse = 1;
+	  else
+	    inverse = 0;
+
+	  /* Construct the attribute.  */
+	  if (inverse)
+	    {
+	      int t = fgcolor;
+	      fgcolor = (bgcolor >> 4);
+	      bgcolor = (t << 4);
+	    }
+	  if (bright)
+	    fgcolor |= FOREGROUND_INTENSITY;
+
+	  SHORT attr = (bgcolor & (15 << 4)) | (fgcolor & 15);
+
+	  /* Apply the attribute.  */
+	  SetConsoleTextAttribute (hstdout, attr);
+	}
+      else
+	{
+	  /* When we are about to write newline, we need to clear to
+	     EOL with the normal attribute, to avoid spilling the
+	     colors to the next screen line.  We assume here that no
+	     non-default attribute extends beyond the newline.  */
+	  if (c == '\n')
+	    {
+	      DWORD nchars;
+	      COORD start_pos;
+	      DWORD written;
+	      CONSOLE_SCREEN_BUFFER_INFO csbi;
+
+	      fflush (fstream);
+	      GetConsoleScreenBufferInfo (hstdout, &csbi);
+
+	      if (csbi.wAttributes != norm_attr)
+		{
+		  start_pos = csbi.dwCursorPosition;
+		  nchars = csbi.dwSize.X - start_pos.X;
+
+		  FillConsoleOutputAttribute (hstdout, norm_attr, nchars,
+					      start_pos, &written);
+		  FillConsoleOutputCharacter (hstdout, ' ', nchars,
+					      start_pos, &written);
+		}
+	    }
+	  fputc (c, fstream);
+	  n_read = 1;
+	}
+    }
+
+  last_style = style;
+  return 1;
+}
diff --git a/gdb/posix-hdep.c b/gdb/posix-hdep.c
index 7911bc5..d0f467e 100644
--- a/gdb/posix-hdep.c
+++ b/gdb/posix-hdep.c
@@ -30,3 +30,11 @@ gdb_select (int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
 {
   return select (n, readfds, writefds, exceptfds, timeout);
 }
+
+/* Host-dependent console fputs method.  POSIX platforms always return
+   zero, to use the default C 'fputs'.  */
+int
+gdb_console_fputs (const char *buf, FILE *f)
+{
+  return 0;
+}
diff --git a/gdb/ui-file.c b/gdb/ui-file.c
index 690fc62..77f6b31 100644
--- a/gdb/ui-file.c
+++ b/gdb/ui-file.c
@@ -236,6 +236,12 @@ stdio_file::write_async_safe (const char *buf, long length_buf)
 void
 stdio_file::puts (const char *linebuffer)
 {
+  /* This host-dependent function (with implementations in
+     posix-hdep.c and mingw-hdep.c) is given the opportunity to
+     process the output first in host-dependent way.  If it does, it
+     should return non-zero, to avoid calling fputs below.  */
+  if (gdb_console_fputs (linebuffer, m_file))
+    return;
   /* Calling error crashes when we are called from the exception framework.  */
   if (fputs (linebuffer, m_file))
     {
diff --git a/gdb/ui-file.h b/gdb/ui-file.h
index 26cf2bf..6e6ca1c 100644
--- a/gdb/ui-file.h
+++ b/gdb/ui-file.h
@@ -101,6 +101,8 @@ extern void ui_file_write_async_safe (struct ui_file *file, const char *buf,
 
 extern long ui_file_read (struct ui_file *file, char *buf, long length_buf);
 
+extern int gdb_console_fputs (const char *, FILE *);
+
 /* A std::string-based ui_file.  Can be used as a scratch buffer for
    collecting output.  */
 
diff --git a/gdb/utils.c b/gdb/utils.c
index 258614a..840779a 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -1445,8 +1445,18 @@ can_emit_style_escape (struct ui_file *stream)
       || !ui_file_isatty (stream))
     return false;
   const char *term = getenv ("TERM");
+  /* Windows doesn't by default define $TERM, but can support styles
+     regardless.  */
+#ifndef _WIN32
   if (term == nullptr || !strcmp (term, "dumb"))
     return false;
+#else
+  /* But if they do define $TERM, let us behave the same as on Posix
+     platforms, for the benefit of programs which invoke GDB as their
+     back-end.  */
+  if (term && !strcmp (term, "dumb"))
+    return false;
+#endif
   return true;
 }
 

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-08 14:55                       ` Eli Zaretskii
@ 2019-03-08 16:14                         ` Hannes Domani via gdb-patches
  2019-03-08 21:08                           ` Tom Tromey
  2019-03-08 21:11                         ` Tom Tromey
  1 sibling, 1 reply; 99+ messages in thread
From: Hannes Domani via gdb-patches @ 2019-03-08 16:14 UTC (permalink / raw)
  To: GDB Patches

Am Freitag, 8. März 2019, 15:55:50 MEZ hat Eli Zaretskii <eliz@gnu.org> Folgendes geschrieben:

> > Date: Tue, 05 Mar 2019 17:38:32 +0200
> > From: Eli Zaretskii <eliz@gnu.org>
> > CC: gdb-patches@sourceware.org
> >
> > > From: Tom Tromey <tom@tromey.com>
> > > Cc: Tom Tromey <tom@tromey.com>,  gdb-patches@sourceware.org
> > > Date: Mon, 04 Mar 2019 09:16:25 -0700
> > >
> > > (gdb) printf "\e[38;2;255;100;0mTRUECOLOR\e[0m\n"
> >
> > Thanks, I used this example (and its variations) to extend the support
> > to any kind of color.
> 
> Here's the patch I propose to enable styling on native MS-Windows
> console.
> 
> OK to commit, master and the release branch?

I just tried this patch out, and it's working great for me.
I really like this new syntax highlighting.


@Tom, you mentioned some time ago that you had some patches
for source-highlight itself, are they available somewhere?


Regards
Hannes Domani

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-08 16:14                         ` Hannes Domani via gdb-patches
@ 2019-03-08 21:08                           ` Tom Tromey
  0 siblings, 0 replies; 99+ messages in thread
From: Tom Tromey @ 2019-03-08 21:08 UTC (permalink / raw)
  To: Hannes Domani via gdb-patches; +Cc: Hannes Domani

>>>>> "Hannes" == Hannes Domani via gdb-patches <gdb-patches@sourceware.org> writes:

Hannes> @Tom, you mentioned some time ago that you had some patches
Hannes> for source-highlight itself, are they available somewhere?

I sent them to the source highlight mailing list.  The main one was to
add Rust highlighting, but I also have some here (can't recall if I sent
them) that update the highlighters for C and C++ to handle newer
versions.

I have to send a follow-up email to the source highlight maintainer, so
I can get permissions to land the patches and send out a new release.
I'll try to get to that soon.

Tom

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-08 14:55                       ` Eli Zaretskii
  2019-03-08 16:14                         ` Hannes Domani via gdb-patches
@ 2019-03-08 21:11                         ` Tom Tromey
  2019-03-09  6:49                           ` Eli Zaretskii
  1 sibling, 1 reply; 99+ messages in thread
From: Tom Tromey @ 2019-03-08 21:11 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: tom, gdb-patches

>>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes:

Eli> Here's the patch I propose to enable styling on native MS-Windows
Eli> console.

Eli> OK to commit, master and the release branch?

Looks reasonable to me.
Thank you for doing this.

Tom

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-08 21:11                         ` Tom Tromey
@ 2019-03-09  6:49                           ` Eli Zaretskii
  0 siblings, 0 replies; 99+ messages in thread
From: Eli Zaretskii @ 2019-03-09  6:49 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

> From: Tom Tromey <tom@tromey.com>
> Cc: tom@tromey.com,  gdb-patches@sourceware.org
> Date: Fri, 08 Mar 2019 14:11:01 -0700
> 
> >>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes:
> 
> Eli> Here's the patch I propose to enable styling on native MS-Windows
> Eli> console.
> 
> Eli> OK to commit, master and the release branch?
> 
> Looks reasonable to me.
> Thank you for doing this.

Thanks for the review, I've pushed this now to both branches.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: GDB version as convenience variable
  2019-03-06 16:02                     ` Eli Zaretskii
@ 2019-03-20 19:35                       ` Eli Zaretskii
  2019-03-25 17:31                         ` Eli Zaretskii
  2019-03-21  1:55                       ` [PATCH 00/16] Add styling to the gdb CLI and TUI Simon Marchi
  1 sibling, 1 reply; 99+ messages in thread
From: Eli Zaretskii @ 2019-03-20 19:35 UTC (permalink / raw)
  To: tom; +Cc: gdb-patches

Ping!

> Date: Wed, 06 Mar 2019 18:02:00 +0200
> From: Eli Zaretskii <eliz@gnu.org>
> CC: gdb-patches@sourceware.org
> 
> > From: Tom Tromey <tom@tromey.com>
> > Cc: Tom Tromey <tom@tromey.com>,  gdb-patches@sourceware.org
> > Date: Mon, 04 Mar 2019 10:40:46 -0700
> > 
> > >>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes:
> > 
> > Eli> What do you think about the idea to add a convenience variable that
> > Eli> would provide the GDB version?
> > 
> > Seems reasonable to me.
> 
> How about the patch below?  Is it okay to go in?  (Note that I took
> this opportunity to clean up whitespace in top.c, I hope it's OK to do
> that as part of unrelated code changes.)
> 
> diff --git a/gdb/ChangeLog b/gdb/ChangeLog
> index ac61e65..f2915d0 100644
> --- a/gdb/ChangeLog
> +++ b/gdb/ChangeLog
> @@ -1,3 +1,10 @@
> +2019-03-06  Eli Zaretskii  <eliz@gnu.org>
> +
> +	* NEWS: Announce $_gdb_version.
> +
> +	* top.c (init_gdb_version_var): New function.
> +	(gdb_init): Call init_gdb_version_var.
> +
>  2019-03-06  Tom Tromey  <tromey@adacore.com>
>  
>  	* remote-sim.c (gdbsim_target_open): Use result of
> diff --git a/gdb/NEWS b/gdb/NEWS
> index cc7c35c..260e6cc 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -3,6 +3,12 @@
>  
>  *** Changes since GDB 8.3
>  
> +* New built-in convenience variable $_gdb_version provides the GDB
> +  version.  It is handy for conditionally using features available
> +  only in or since specific GDB versions, in scripts that should work
> +  error-free with many different versions, such as in system-wide init
> +  files.
> +
>  *** Changes in GDB 8.3
>  
>  * GDB and GDBserver now support access to additional registers on
> diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
> index 0380322..313a061 100644
> --- a/gdb/doc/ChangeLog
> +++ b/gdb/doc/ChangeLog
> @@ -1,3 +1,7 @@
> +2019-03-06  Eli Zaretskii  <eliz@gnu.org>
> +
> +	* gdb.texinfo (Convenience Vars): Document $_gdb_version.
> +
>  2019-03-05  Simon Marchi  <simon.marchi@efficios.com>
>  
>  	* python.texi (Values From Inferior): Change synopsys of the
> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> index f2028f8..9d15337 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -11197,7 +11197,7 @@
>  @vindex $_tlb@r{, convenience variable}
>  The variable @code{$_tlb} is automatically set when debugging
>  applications running on MS-Windows in native mode or connected to
> -gdbserver that supports the @code{qGetTIBAddr} request. 
> +gdbserver that supports the @code{qGetTIBAddr} request.
>  @xref{General Query Packets}.
>  This variable contains the address of the thread information block.
>  
> @@ -11211,6 +11211,17 @@
>  @item $_gthread
>  The global number of the current thread.  @xref{global thread numbers}.
>  
> +@item $_gdb_version
> +@vindex $_gdb_version@r{, convenience variable}
> +The version of the running @value{GDBN}.  The value is an integer
> +number that encodes the major and minor @value{GDBN} versions as
> +@w{@code{@var{major}*100 + @var{minor}}}, so, e.g., @value{GDBN}
> +version 9.10 will produce the value @code{910}.  Development snapshots
> +and pretest versions have their minor version incremented by one;
> +thus, @value{GDBN} pretest 9.11.90 will produce the value 912.  This
> +variable allows you to write scripts that work with different versions
> +of @value{GDBN} without errors caused by features unavailable in some
> +of those versions.
>  @end table
>  
>  @node Convenience Funs
> diff --git a/gdb/top.c b/gdb/top.c
> index 22e6f7e..97b349a 100644
> --- a/gdb/top.c
> +++ b/gdb/top.c
> @@ -147,22 +147,22 @@ int server_command;
>  
>  /* Timeout limit for response from target.  */
>  
> -/* The default value has been changed many times over the years.  It 
> -   was originally 5 seconds.  But that was thought to be a long time 
> +/* The default value has been changed many times over the years.  It
> +   was originally 5 seconds.  But that was thought to be a long time
>     to sit and wait, so it was changed to 2 seconds.  That was thought
> -   to be plenty unless the connection was going through some terminal 
> +   to be plenty unless the connection was going through some terminal
>     server or multiplexer or other form of hairy serial connection.
>  
> -   In mid-1996, remote_timeout was moved from remote.c to top.c and 
> +   In mid-1996, remote_timeout was moved from remote.c to top.c and
>     it began being used in other remote-* targets.  It appears that the
>     default was changed to 20 seconds at that time, perhaps because the
>     Renesas E7000 ICE didn't always respond in a timely manner.
>  
>     But if 5 seconds is a long time to sit and wait for retransmissions,
> -   20 seconds is far worse.  This demonstrates the difficulty of using 
> +   20 seconds is far worse.  This demonstrates the difficulty of using
>     a single variable for all protocol timeouts.
>  
> -   As remote.c is used much more than remote-e7000.c, it was changed 
> +   As remote.c is used much more than remote-e7000.c, it was changed
>     back to 2 seconds in 1999.  */
>  
>  int remote_timeout = 2;
> @@ -188,9 +188,9 @@ int (*deprecated_ui_loop_hook) (int);
>  
>  /* Called from print_frame_info to list the line we stopped in.  */
>  
> -void (*deprecated_print_frame_info_listing_hook) (struct symtab * s, 
> +void (*deprecated_print_frame_info_listing_hook) (struct symtab * s,
>  						  int line,
> -						  int stopline, 
> +						  int stopline,
>  						  int noerror);
>  /* Replaces most of query.  */
>  
> @@ -237,7 +237,7 @@ ptid_t (*deprecated_target_wait_hook) (ptid_t ptid,
>  /* Used by UI as a wrapper around command execution.  May do various
>     things like enabling/disabling buttons, etc...  */
>  
> -void (*deprecated_call_command_hook) (struct cmd_list_element * c, 
> +void (*deprecated_call_command_hook) (struct cmd_list_element * c,
>  				      const char *cmd, int from_tty);
>  
>  /* Called when the current thread changes.  Argument is thread id.  */
> @@ -1339,8 +1339,9 @@ There is NO WARRANTY, to the extent permitted by law.");
>  resources online at:\n    <http://www.gnu.org/software/gdb/documentation/>."));
>    fprintf_filtered (stream, "\n\n");
>    fprintf_filtered (stream, _("For help, type \"help\".\n"));
> -  fprintf_filtered (stream, _("Type \"apropos word\" to search for \
> -commands related to \"word\"."));
> +  fprintf_filtered (stream,
> +		    _("Type \"apropos word\" to search for commands \
> +related to \"word\"."));
>  }
>  
>  /* Print the details of GDB build-time configuration.  */
> @@ -1608,7 +1609,7 @@ quit_force (int *exit_arg, int from_tty)
>  
>    undo_terminal_modifications_before_exit ();
>  
> -  /* An optional expression may be used to cause gdb to terminate with the 
> +  /* An optional expression may be used to cause gdb to terminate with the
>       value of that expression.  */
>    if (exit_arg)
>      exit_code = *exit_arg;
> @@ -1998,11 +1999,21 @@ set_history_filename (const char *args,
>       directories the file written will be the same as the one
>       that was read.  */
>    if (!IS_ABSOLUTE_PATH (history_filename))
> -    history_filename = reconcat (history_filename, current_directory, "/", 
> +    history_filename = reconcat (history_filename, current_directory, "/",
>  				 history_filename, (char *) NULL);
>  }
>  
>  static void
> +init_gdb_version_var (void)
> +{
> +  struct internalvar *version_var = create_internalvar ("_gdb_version");
> +  int vmajor = 0, vminor = 0, vrevision = 0;
> +  sscanf (version, "%d.%d.%d", &vmajor, &vminor, &vrevision);
> +  set_internalvar_integer (version_var,
> +			   vmajor * 100 + vminor + (vrevision > 0));
> +}
> +
> +static void
>  init_main (void)
>  {
>    struct cmd_list_element *c;
> @@ -2206,4 +2217,7 @@ gdb_init (char *argv0)
>       prefix to be installed.  Keep things simple and just do final
>       script initialization here.  */
>    finish_ext_lang_initialization ();
> +
> +  /* Create $_gdb_version convenience variable.  */
> +  init_gdb_version_var ();
>  }
> 

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-06 16:02                     ` Eli Zaretskii
  2019-03-20 19:35                       ` GDB version as convenience variable Eli Zaretskii
@ 2019-03-21  1:55                       ` Simon Marchi
  2019-03-21 14:38                         ` Eli Zaretskii
  1 sibling, 1 reply; 99+ messages in thread
From: Simon Marchi @ 2019-03-21  1:55 UTC (permalink / raw)
  To: Eli Zaretskii, Tom Tromey; +Cc: gdb-patches

On 2019-03-06 11:02 a.m., Eli Zaretskii wrote:
>> From: Tom Tromey <tom@tromey.com>
>> Cc: Tom Tromey <tom@tromey.com>,  gdb-patches@sourceware.org
>> Date: Mon, 04 Mar 2019 10:40:46 -0700
>>
>>>>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes:
>>
>> Eli> What do you think about the idea to add a convenience variable that
>> Eli> would provide the GDB version?
>>
>> Seems reasonable to me.
> 
> How about the patch below?  Is it okay to go in?  (Note that I took
> this opportunity to clean up whitespace in top.c, I hope it's OK to do
> that as part of unrelated code changes.)

Ah, I noticed this because you changed the subject in your ping :).  This would
be very useful, especially that we can quite easily query this from MI as well
as Python.

> 
> diff --git a/gdb/ChangeLog b/gdb/ChangeLog
> index ac61e65..f2915d0 100644
> --- a/gdb/ChangeLog
> +++ b/gdb/ChangeLog
> @@ -1,3 +1,10 @@
> +2019-03-06  Eli Zaretskii  <eliz@gnu.org>
> +
> +	* NEWS: Announce $_gdb_version.
> +
> +	* top.c (init_gdb_version_var): New function.
> +	(gdb_init): Call init_gdb_version_var.
> +
>  2019-03-06  Tom Tromey  <tromey@adacore.com>
>  
>  	* remote-sim.c (gdbsim_target_open): Use result of
> diff --git a/gdb/NEWS b/gdb/NEWS
> index cc7c35c..260e6cc 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -3,6 +3,12 @@
>  
>  *** Changes since GDB 8.3
>  
> +* New built-in convenience variable $_gdb_version provides the GDB
> +  version.  It is handy for conditionally using features available
> +  only in or since specific GDB versions, in scripts that should work
> +  error-free with many different versions, such as in system-wide init
> +  files.
> +
>  *** Changes in GDB 8.3
>  
>  * GDB and GDBserver now support access to additional registers on
> diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
> index 0380322..313a061 100644
> --- a/gdb/doc/ChangeLog
> +++ b/gdb/doc/ChangeLog
> @@ -1,3 +1,7 @@
> +2019-03-06  Eli Zaretskii  <eliz@gnu.org>
> +
> +	* gdb.texinfo (Convenience Vars): Document $_gdb_version.
> +
>  2019-03-05  Simon Marchi  <simon.marchi@efficios.com>
>  
>  	* python.texi (Values From Inferior): Change synopsys of the
> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> index f2028f8..9d15337 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -11197,7 +11197,7 @@
>  @vindex $_tlb@r{, convenience variable}
>  The variable @code{$_tlb} is automatically set when debugging
>  applications running on MS-Windows in native mode or connected to
> -gdbserver that supports the @code{qGetTIBAddr} request. 
> +gdbserver that supports the @code{qGetTIBAddr} request.
>  @xref{General Query Packets}.
>  This variable contains the address of the thread information block.

This looks like an unintended change.

> @@ -11211,6 +11211,17 @@
>  @item $_gthread
>  The global number of the current thread.  @xref{global thread numbers}.
>  
> +@item $_gdb_version
> +@vindex $_gdb_version@r{, convenience variable}
> +The version of the running @value{GDBN}.  The value is an integer
> +number that encodes the major and minor @value{GDBN} versions as
> +@w{@code{@var{major}*100 + @var{minor}}}, so, e.g., @value{GDBN}
> +version 9.10 will produce the value @code{910}.  Development snapshots
> +and pretest versions have their minor version incremented by one;
> +thus, @value{GDBN} pretest 9.11.90 will produce the value 912.  This
> +variable allows you to write scripts that work with different versions
> +of @value{GDBN} without errors caused by features unavailable in some
> +of those versions.
>  @end table

I know we plan to move to a version scheme where we don't have a "patch"
number (a third number), but just in case, maybe we could plan for it anyway
just in case it ever changes again in the future (I don't expect it will,
but we never know.

So something like MAJOR * 10000 + MINOR * 100 + PATCH * 100

Also, it means that in your example, 9.11.90 would produce 091190.  I think
it's better if we are able to distinguish 9.11.90 from 9.12.

Also, we should consider doing like Python does, and encode different numbers
in different bytes:

  https://docs.python.org/3/c-api/apiabiversion.html

So we could say ((MAJOR << 16) | (MINOR << 8) | PATCH), for example.  The
advantage with this is that it's easy to to isolate a particular number
using bitshifts and masks.  I know it would be possible as well in decimal
to isolate a particular number, but it's just more convenient in hex.

>  
>  @node Convenience Funs
> diff --git a/gdb/top.c b/gdb/top.c
> index 22e6f7e..97b349a 100644
> --- a/gdb/top.c
> +++ b/gdb/top.c
> @@ -147,22 +147,22 @@ int server_command;
>  
>  /* Timeout limit for response from target.  */
>  
> -/* The default value has been changed many times over the years.  It 
> -   was originally 5 seconds.  But that was thought to be a long time 
> +/* The default value has been changed many times over the years.  It
> +   was originally 5 seconds.  But that was thought to be a long time
>     to sit and wait, so it was changed to 2 seconds.  That was thought
> -   to be plenty unless the connection was going through some terminal 
> +   to be plenty unless the connection was going through some terminal
>     server or multiplexer or other form of hairy serial connection.
>  
> -   In mid-1996, remote_timeout was moved from remote.c to top.c and 
> +   In mid-1996, remote_timeout was moved from remote.c to top.c and
>     it began being used in other remote-* targets.  It appears that the
>     default was changed to 20 seconds at that time, perhaps because the
>     Renesas E7000 ICE didn't always respond in a timely manner.
>  
>     But if 5 seconds is a long time to sit and wait for retransmissions,
> -   20 seconds is far worse.  This demonstrates the difficulty of using 
> +   20 seconds is far worse.  This demonstrates the difficulty of using
>     a single variable for all protocol timeouts.
>  
> -   As remote.c is used much more than remote-e7000.c, it was changed 
> +   As remote.c is used much more than remote-e7000.c, it was changed
>     back to 2 seconds in 1999.  */

Some more unintended changes?  There are more in the patch, I won't point
out all of them.

I have to go for now, I didn't look at the implementation yet.

Simon

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-21  1:55                       ` [PATCH 00/16] Add styling to the gdb CLI and TUI Simon Marchi
@ 2019-03-21 14:38                         ` Eli Zaretskii
  2019-03-21 15:02                           ` Simon Marchi
  0 siblings, 1 reply; 99+ messages in thread
From: Eli Zaretskii @ 2019-03-21 14:38 UTC (permalink / raw)
  To: Simon Marchi; +Cc: tom, gdb-patches

> Cc: gdb-patches@sourceware.org
> From: Simon Marchi <simark@simark.ca>
> Date: Wed, 20 Mar 2019 21:55:43 -0400
> 
> Ah, I noticed this because you changed the subject in your ping :).

The original one evidently failed to draw attention ;-)

> This would be very useful, especially that we can quite easily query
> this from MI as well as Python.

Thanks, I agree.

> > --- a/gdb/doc/gdb.texinfo
> > +++ b/gdb/doc/gdb.texinfo
> > @@ -11197,7 +11197,7 @@
> >  @vindex $_tlb@r{, convenience variable}
> >  The variable @code{$_tlb} is automatically set when debugging
> >  applications running on MS-Windows in native mode or connected to
> > -gdbserver that supports the @code{qGetTIBAddr} request. 
> > +gdbserver that supports the @code{qGetTIBAddr} request.
> >  @xref{General Query Packets}.
> >  This variable contains the address of the thread information block.
> 
> This looks like an unintended change.

No, it's not unintended.  I mentioned that in my preamble:

> (Note that I took this opportunity to clean up whitespace in top.c,
> I hope it's OK to do that as part of unrelated code changes.)

> I know we plan to move to a version scheme where we don't have a "patch"
> number (a third number), but just in case, maybe we could plan for it anyway
> just in case it ever changes again in the future (I don't expect it will,
> but we never know.
> 
> So something like MAJOR * 10000 + MINOR * 100 + PATCH * 100
> 
> Also, it means that in your example, 9.11.90 would produce 091190.  I think
> it's better if we are able to distinguish 9.11.90 from 9.12.

The idea was that we don't need to distinguish between them.  This
feature is intended to be used in scripts that need to know when a
certain feature became available, so IMO resolution below XX.YY is not
needed, because any XX.YY.ZZ version is just a snapshot of XX.YY+1.

> Also, we should consider doing like Python does, and encode different numbers
> in different bytes:
> 
>   https://docs.python.org/3/c-api/apiabiversion.html
> 
> So we could say ((MAJOR << 16) | (MINOR << 8) | PATCH), for example.  The
> advantage with this is that it's easy to to isolate a particular number
> using bitshifts and masks.  I know it would be possible as well in decimal
> to isolate a particular number, but it's just more convenient in hex.

I don't have a strong opinion, but I do have a weak one: the decimal
"encoding" makes it much easier for humans to construct version
numbers, they don't need to convert to hex.

> > -   As remote.c is used much more than remote-e7000.c, it was changed 
> > +   As remote.c is used much more than remote-e7000.c, it was changed
> >     back to 2 seconds in 1999.  */
> 
> Some more unintended changes?

It's intended, see above.

Thanks for the review.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-21 14:38                         ` Eli Zaretskii
@ 2019-03-21 15:02                           ` Simon Marchi
  2019-03-21 16:01                             ` Eli Zaretskii
  0 siblings, 1 reply; 99+ messages in thread
From: Simon Marchi @ 2019-03-21 15:02 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: tom, gdb-patches

> No, it's not unintended.  I mentioned that in my preamble:

Sorry about that, I see it now.  IMO, you could directly push a patch 
that does these cleanups.

>> (Note that I took this opportunity to clean up whitespace in top.c,
>> I hope it's OK to do that as part of unrelated code changes.)
> 
>> I know we plan to move to a version scheme where we don't have a 
>> "patch"
>> number (a third number), but just in case, maybe we could plan for it 
>> anyway
>> just in case it ever changes again in the future (I don't expect it 
>> will,
>> but we never know.
>> 
>> So something like MAJOR * 10000 + MINOR * 100 + PATCH * 100
>> 
>> Also, it means that in your example, 9.11.90 would produce 091190.  I 
>> think
>> it's better if we are able to distinguish 9.11.90 from 9.12.
> 
> The idea was that we don't need to distinguish between them.  This
> feature is intended to be used in scripts that need to know when a
> certain feature became available, so IMO resolution below XX.YY is not
> needed, because any XX.YY.ZZ version is just a snapshot of XX.YY+1.

Ok, fair enough.  Since the .90 is supposed to behave exactly how the 
next version will (and then never used in production again), I'm fine 
with that.

I'm just a little worried that some day we'll introduce back some 
"patch" number, and then we'll need to change how this number is 
encoded, which will cause some headaches :).

>> Also, we should consider doing like Python does, and encode different 
>> numbers
>> in different bytes:
>> 
>>   https://docs.python.org/3/c-api/apiabiversion.html
>> 
>> So we could say ((MAJOR << 16) | (MINOR << 8) | PATCH), for example.  
>> The
>> advantage with this is that it's easy to to isolate a particular 
>> number
>> using bitshifts and masks.  I know it would be possible as well in 
>> decimal
>> to isolate a particular number, but it's just more convenient in hex.
> 
> I don't have a strong opinion, but I do have a weak one: the decimal
> "encoding" makes it much easier for humans to construct version
> numbers, they don't need to convert to hex.

There's not much difference in hex, you would just write "if 
$_gdb_version >= 0x0901" for example, rather than "if $_gdb_version >= 
901".

But again, my argument for hex is weak too, it's easy enough to extract 
the GDB version components using some "% 100" and "/ 100".  If there's 
no more compelling argument for hex, I'm fine with decimal.

Simon

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-21 15:02                           ` Simon Marchi
@ 2019-03-21 16:01                             ` Eli Zaretskii
  2019-03-21 16:06                               ` Simon Marchi
  0 siblings, 1 reply; 99+ messages in thread
From: Eli Zaretskii @ 2019-03-21 16:01 UTC (permalink / raw)
  To: Simon Marchi; +Cc: tom, gdb-patches

> Date: Thu, 21 Mar 2019 11:02:00 -0400
> From: Simon Marchi <simark@simark.ca>
> Cc: tom@tromey.com, gdb-patches@sourceware.org
> 
> > I don't have a strong opinion, but I do have a weak one: the decimal
> > "encoding" makes it much easier for humans to construct version
> > numbers, they don't need to convert to hex.
> 
> There's not much difference in hex, you would just write "if 
> $_gdb_version >= 0x0901" for example, rather than "if $_gdb_version >= 
> 901".

That's true for small values of major/minor.  But imagine GDB 12.13
for a moment.

> But again, my argument for hex is weak too, it's easy enough to extract 
> the GDB version components using some "% 100" and "/ 100".  If there's 
> no more compelling argument for hex, I'm fine with decimal.

Maybe someone else have an opinion on this?

Thanks.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-21 16:01                             ` Eli Zaretskii
@ 2019-03-21 16:06                               ` Simon Marchi
  2019-03-21 16:12                                 ` Pedro Alves
  0 siblings, 1 reply; 99+ messages in thread
From: Simon Marchi @ 2019-03-21 16:06 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: tom, gdb-patches

On 2019-03-21 12:01, Eli Zaretskii wrote:
>> Date: Thu, 21 Mar 2019 11:02:00 -0400
>> From: Simon Marchi <simark@simark.ca>
>> Cc: tom@tromey.com, gdb-patches@sourceware.org
>> 
>> > I don't have a strong opinion, but I do have a weak one: the decimal
>> > "encoding" makes it much easier for humans to construct version
>> > numbers, they don't need to convert to hex.
>> 
>> There's not much difference in hex, you would just write "if
>> $_gdb_version >= 0x0901" for example, rather than "if $_gdb_version >=
>> 901".
> 
> That's true for small values of major/minor.  But imagine GDB 12.13
> for a moment.

Hmm, true :).

Simon

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-21 16:06                               ` Simon Marchi
@ 2019-03-21 16:12                                 ` Pedro Alves
  2019-03-21 16:54                                   ` John Baldwin
  2019-03-21 17:02                                   ` Eli Zaretskii
  0 siblings, 2 replies; 99+ messages in thread
From: Pedro Alves @ 2019-03-21 16:12 UTC (permalink / raw)
  To: Simon Marchi, Eli Zaretskii; +Cc: tom, gdb-patches

On 03/21/2019 04:06 PM, Simon Marchi wrote:
> On 2019-03-21 12:01, Eli Zaretskii wrote:
>>> Date: Thu, 21 Mar 2019 11:02:00 -0400
>>> From: Simon Marchi <simark@simark.ca>
>>> Cc: tom@tromey.com, gdb-patches@sourceware.org
>>>
>>> > I don't have a strong opinion, but I do have a weak one: the decimal
>>> > "encoding" makes it much easier for humans to construct version
>>> > numbers, they don't need to convert to hex.
>>>
>>> There's not much difference in hex, you would just write "if
>>> $_gdb_version >= 0x0901" for example, rather than "if $_gdb_version >=
>>> 901".

Is there an advantage of a single variable that encodes the version,
compared to separate major/minor variables?  Separate variables
would render the discussion of how to encode this moot.

GCC has these as predefined preprocessor macros:

 __GNUC__
 __GNUC_MINOR__
 __GNUC_PATCHLEVEL__

We could likewise have separate variables for these.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-21 16:12                                 ` Pedro Alves
@ 2019-03-21 16:54                                   ` John Baldwin
  2019-03-21 17:02                                   ` Eli Zaretskii
  1 sibling, 0 replies; 99+ messages in thread
From: John Baldwin @ 2019-03-21 16:54 UTC (permalink / raw)
  To: Pedro Alves, Simon Marchi, Eli Zaretskii; +Cc: tom, gdb-patches

On 3/21/19 9:12 AM, Pedro Alves wrote:
> On 03/21/2019 04:06 PM, Simon Marchi wrote:
>> On 2019-03-21 12:01, Eli Zaretskii wrote:
>>>> Date: Thu, 21 Mar 2019 11:02:00 -0400
>>>> From: Simon Marchi <simark@simark.ca>
>>>> Cc: tom@tromey.com, gdb-patches@sourceware.org
>>>>
>>>>> I don't have a strong opinion, but I do have a weak one: the decimal
>>>>> "encoding" makes it much easier for humans to construct version
>>>>> numbers, they don't need to convert to hex.
>>>>
>>>> There's not much difference in hex, you would just write "if
>>>> $_gdb_version >= 0x0901" for example, rather than "if $_gdb_version >=
>>>> 901".
> 
> Is there an advantage of a single variable that encodes the version,
> compared to separate major/minor variables?  Separate variables
> would render the discussion of how to encode this moot.
> 
> GCC has these as predefined preprocessor macros:
> 
>  __GNUC__
>  __GNUC_MINOR__
>  __GNUC_PATCHLEVEL__
> 
> We could likewise have separate variables for these.

I think splitting it out is perhaps the simplest.  FWIW, in FreeBSD we
have a single __FreeBSD_version macro that uses decimal.  We also had
some drama when we originally had a single digit field for the minor
version but had minor versions beyond 9 (4.10, 4.11).  The current
format is:

 * scheme is:  <major><two digit minor>Rxx
 *		'R' is in the range 0 to 4 if this is a release branch or
 *		X.0-CURRENT before releng/X.0 is created, otherwise 'R' is
 *		in the range 5 to 9.
 */
#undef __FreeBSD_version
#define __FreeBSD_version 1300013	/* Master, propagated to newvers */

So release 7.2 would be 702000 and each time a patch is issued to the
release due to an errata or security, the last two digits get bumped
(kind of like a patch number), e.g. 702001, 702002.  The 7.x branch
in between 7.2 and 7.3 is 702500 so it sorts between 7.2 release and
7.3 release.  FreeBSD also bumps the 'patch level' field somewhat
frequently even on 'master' as it's used to denote API (or ABI on
'master') changes.  This has mostly worked out ok, and I do think using
decimal is easier to "read" than hex for this, but split out version
numbers is probably simpler for users to work with.

-- 
John Baldwin

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-21 16:12                                 ` Pedro Alves
  2019-03-21 16:54                                   ` John Baldwin
@ 2019-03-21 17:02                                   ` Eli Zaretskii
  2019-03-21 18:08                                     ` Simon Marchi
  1 sibling, 1 reply; 99+ messages in thread
From: Eli Zaretskii @ 2019-03-21 17:02 UTC (permalink / raw)
  To: Pedro Alves; +Cc: simark, tom, gdb-patches

> Cc: tom@tromey.com, gdb-patches@sourceware.org
> From: Pedro Alves <palves@redhat.com>
> Date: Thu, 21 Mar 2019 16:12:26 +0000
> 
> Is there an advantage of a single variable that encodes the version,
> compared to separate major/minor variables?

Just that it makes comparison simpler, and IME less error-prone.  Not
a very important argument, admittedly.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-21 17:02                                   ` Eli Zaretskii
@ 2019-03-21 18:08                                     ` Simon Marchi
  2019-03-21 18:19                                       ` Pedro Alves
  0 siblings, 1 reply; 99+ messages in thread
From: Simon Marchi @ 2019-03-21 18:08 UTC (permalink / raw)
  To: Eli Zaretskii, Pedro Alves; +Cc: tom, gdb-patches

On 2019-03-21 1:02 p.m., Eli Zaretskii wrote:
>> Cc: tom@tromey.com, gdb-patches@sourceware.org
>> From: Pedro Alves <palves@redhat.com>
>> Date: Thu, 21 Mar 2019 16:12:26 +0000
>>
>> Is there an advantage of a single variable that encodes the version,
>> compared to separate major/minor variables?
> 
> Just that it makes comparison simpler, and IME less error-prone.  Not
> a very important argument, admittedly.
> 

Yeah, if you want to check if you are running 8.5 or more, you can do:

if $_gdb_version >= 805

With separate components, you have to do something like

if $_gdb_version_major >= 9 \
    || ($_gdb_version_major >= 8 && $gdb_version_minor >= 5

If you need to check for a range, it's even more complicated.

But then, if the version is provided as separate components, nothing 
prevents you to re-encode it however you want after that.  You can do 
easily enough

set $my_gdb_version = ($_gdb_version_major * 100) + $_gdb_version_minor

if you want, and use the simple comparison.  And everyone is free to 
choose their own encoding :).  So, to me separate components sounds better.

Simon

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-21 18:08                                     ` Simon Marchi
@ 2019-03-21 18:19                                       ` Pedro Alves
  2019-03-21 18:38                                         ` Eli Zaretskii
  0 siblings, 1 reply; 99+ messages in thread
From: Pedro Alves @ 2019-03-21 18:19 UTC (permalink / raw)
  To: Simon Marchi, Eli Zaretskii; +Cc: tom, gdb-patches

On 03/21/2019 06:08 PM, Simon Marchi wrote:
> On 2019-03-21 1:02 p.m., Eli Zaretskii wrote:
>>> Cc: tom@tromey.com, gdb-patches@sourceware.org
>>> From: Pedro Alves <palves@redhat.com>
>>> Date: Thu, 21 Mar 2019 16:12:26 +0000
>>>
>>> Is there an advantage of a single variable that encodes the version,
>>> compared to separate major/minor variables?
>>
>> Just that it makes comparison simpler, and IME less error-prone.  Not
>> a very important argument, admittedly.
>>
> 
> Yeah, if you want to check if you are running 8.5 or more, you can do:
> 
> if $_gdb_version >= 805
> 
> With separate components, you have to do something like
> 
> if $_gdb_version_major >= 9 \
>    || ($_gdb_version_major >= 8 && $gdb_version_minor >= 5
> 
> If you need to check for a range, it's even more complicated.
> 
> But then, if the version is provided as separate components, nothing prevents you to re-encode it however you want after that.  You can do easily enough
> 
> set $my_gdb_version = ($_gdb_version_major * 100) + $_gdb_version_minor
> 
> if you want, and use the simple comparison.  And everyone is free to choose their own encoding :).  So, to me separate components sounds better.

Exactly my thoughts.  That's what the GCC manual describes, BTW:

  https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html

Note that with the new gdb version numbering, going forward, for features,
you'll only really care about the major version number, since there won't
be new features added in minor releases.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 00/16] Add styling to the gdb CLI and TUI
  2019-03-21 18:19                                       ` Pedro Alves
@ 2019-03-21 18:38                                         ` Eli Zaretskii
  0 siblings, 0 replies; 99+ messages in thread
From: Eli Zaretskii @ 2019-03-21 18:38 UTC (permalink / raw)
  To: Pedro Alves; +Cc: simark, tom, gdb-patches

> Cc: tom@tromey.com, gdb-patches@sourceware.org
> From: Pedro Alves <palves@redhat.com>
> Date: Thu, 21 Mar 2019 18:19:04 +0000
> 
> > if $_gdb_version_major >= 9 \
> >    || ($_gdb_version_major >= 8 && $gdb_version_minor >= 5
> > 
> > If you need to check for a range, it's even more complicated.
> > 
> > But then, if the version is provided as separate components, nothing prevents you to re-encode it however you want after that.  You can do easily enough
> > 
> > set $my_gdb_version = ($_gdb_version_major * 100) + $_gdb_version_minor
> > 
> > if you want, and use the simple comparison.  And everyone is free to choose their own encoding :).  So, to me separate components sounds better.
> 
> Exactly my thoughts.  That's what the GCC manual describes, BTW:
> 
>   https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html

And I've seen my share of erroneous version checks using the GCC
macros.

But if there's a consensus to go with 2 separate numbers, I'm okay
with redoing the patch that way.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: GDB version as convenience variable
  2019-03-20 19:35                       ` GDB version as convenience variable Eli Zaretskii
@ 2019-03-25 17:31                         ` Eli Zaretskii
  2019-03-25 17:58                           ` Simon Marchi
  0 siblings, 1 reply; 99+ messages in thread
From: Eli Zaretskii @ 2019-03-25 17:31 UTC (permalink / raw)
  To: gdb-patches

Seems like there's a consensus to have 2 separate variables, so here's
a version of the patch that does that.  OK to commit?

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 2de1adc..f841e0a 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,10 @@
+2019-03-06  Eli Zaretskii  <eliz@gnu.org>
+
+	* NEWS: Announce $_gdb_major and $_gdb_minor.
+
+	* top.c (init_gdb_version_vars): New function.
+	(gdb_init): Call init_gdb_version_vars.
+
 2019-03-25  Alan Hayward  <alan.hayward@arm.com>
 
 	* s390-linux-nat.c: Add include.
diff --git a/gdb/NEWS b/gdb/NEWS
index c45b313..676f0a0 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -3,6 +3,12 @@
 
 *** Changes since GDB 8.3
 
+* New built-in convenience variables $_gdb_major and $_gdb_minor
+  provide the GDB version.  They are handy for conditionally using
+  features available only in or since specific GDB versions, in
+  scripts that should work error-free with many different versions,
+  such as in system-wide init files.
+
 *** Changes in GDB 8.3
 
 * GDB and GDBserver now support access to additional registers on
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index 1f41498..c384267 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,3 +1,7 @@
+2019-03-06  Eli Zaretskii  <eliz@gnu.org>
+
+	* gdb.texinfo (Convenience Vars): Document $_gdb_version.
+
 2019-03-22  Alan Hayward  <alan.hayward@arm.com>
 	    Jiong Wang  <jiong.wang@arm.com>
 
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 4c1d5e8..115bcf7 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -11211,6 +11211,17 @@
 @item $_gthread
 The global number of the current thread.  @xref{global thread numbers}.
 
+@item $_gdb_major
+@itemx $_gdb_minor
+@vindex $_gdb_major@{, convenience variable}
+@vindex $_gdb_minor@{, convenience variable}
+The major and minor version numbers of the running @value{GDBN}.
+Development snapshots and pretest versions have their minor version
+incremented by one; thus, @value{GDBN} pretest 9.11.90 will produce
+the value 12 for @code{$_gdb_minor}.  These variables allow you to
+write scripts that work with different versions of @value{GDBN}
+without errors caused by features unavailable in some of those
+versions.
 @end table
 
 @node Convenience Funs
diff --git a/gdb/top.c b/gdb/top.c
index b10b064..afb77c0 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -2003,6 +2004,17 @@ set_history_filename (const char *args,
 }
 
 static void
+init_gdb_version_vars (void)
+{
+  struct internalvar *major_version_var = create_internalvar ("_gdb_major");
+  struct internalvar *minor_version_var = create_internalvar ("_gdb_minor");
+  int vmajor = 0, vminor = 0, vrevision = 0;
+  sscanf (version, "%d.%d.%d", &vmajor, &vminor, &vrevision);
+  set_internalvar_integer (major_version_var, vmajor);
+  set_internalvar_integer (minor_version_var, vminor + (vrevision > 0));
+}
+
+static void
 init_main (void)
 {
   struct cmd_list_element *c;
@@ -2206,4 +2218,7 @@ gdb_init (char *argv0)
      prefix to be installed.  Keep things simple and just do final
      script initialization here.  */
   finish_ext_lang_initialization ();
+
+  /* Create $_gdb_major and $_gdb_minor convenience variables.  */
+  init_gdb_version_vars ();
 }

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: GDB version as convenience variable
  2019-03-25 17:31                         ` Eli Zaretskii
@ 2019-03-25 17:58                           ` Simon Marchi
  2019-03-25 18:10                             ` Eli Zaretskii
  0 siblings, 1 reply; 99+ messages in thread
From: Simon Marchi @ 2019-03-25 17:58 UTC (permalink / raw)
  To: Eli Zaretskii, gdb-patches, Joel Brobecker

On 2019-03-25 1:31 p.m., Eli Zaretskii wrote:
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -11211,6 +11211,17 @@
>   @item $_gthread
>   The global number of the current thread.  @xref{global thread numbers}.
>   
> +@item $_gdb_major
> +@itemx $_gdb_minor
> +@vindex $_gdb_major@{, convenience variable}
> +@vindex $_gdb_minor@{, convenience variable}
> +The major and minor version numbers of the running @value{GDBN}.
> +Development snapshots and pretest versions have their minor version
> +incremented by one; thus, @value{GDBN} pretest 9.11.90 will produce
> +the value 12 for @code{$_gdb_minor}.  These variables allow you to
> +write scripts that work with different versions of @value{GDBN}
> +without errors caused by features unavailable in some of those
> +versions.
>   @end table

I get this error when trying to "make html":

/home/smarchi/src/binutils-gdb/gdb/doc/gdb.texinfo:11216: misplaced }
/home/smarchi/src/binutils-gdb/gdb/doc/gdb.texinfo:11217: misplaced }

Is it worth having a test for that?  If we check that they have the 
expected value, it would be something to change when a new GDB branch is 
created, probably (as the master branch will now represent the next 
version).  Maybe our release manager should have a say in this :).

Otherwise, this LGTM.

Simon

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: GDB version as convenience variable
  2019-03-25 17:58                           ` Simon Marchi
@ 2019-03-25 18:10                             ` Eli Zaretskii
  2019-03-25 18:33                               ` Simon Marchi
  0 siblings, 1 reply; 99+ messages in thread
From: Eli Zaretskii @ 2019-03-25 18:10 UTC (permalink / raw)
  To: Simon Marchi; +Cc: gdb-patches, brobecker

> From: Simon Marchi <simark@simark.ca>
> Date: Mon, 25 Mar 2019 13:58:20 -0400
> 
> > +@item $_gdb_major
> > +@itemx $_gdb_minor
> > +@vindex $_gdb_major@{, convenience variable}
> > +@vindex $_gdb_minor@{, convenience variable}
> > +The major and minor version numbers of the running @value{GDBN}.
> > +Development snapshots and pretest versions have their minor version
> > +incremented by one; thus, @value{GDBN} pretest 9.11.90 will produce
> > +the value 12 for @code{$_gdb_minor}.  These variables allow you to
> > +write scripts that work with different versions of @value{GDBN}
> > +without errors caused by features unavailable in some of those
> > +versions.
> >   @end table
> 
> I get this error when trying to "make html":
> 
> /home/smarchi/src/binutils-gdb/gdb/doc/gdb.texinfo:11216: misplaced }
> /home/smarchi/src/binutils-gdb/gdb/doc/gdb.texinfo:11217: misplaced }

Thanks, fixed.  Too many r's...

> Is it worth having a test for that?

Hmm... how would you test that?

> If we check that they have the expected value, it would be something
> to change when a new GDB branch is created, probably (as the master
> branch will now represent the next version).  Maybe our release
> manager should have a say in this :).

I'm all ears.

> Otherwise, this LGTM.

Thanks for the review.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: GDB version as convenience variable
  2019-03-25 18:10                             ` Eli Zaretskii
@ 2019-03-25 18:33                               ` Simon Marchi
  2019-03-25 18:37                                 ` Simon Marchi
  2019-03-25 18:43                                 ` Eli Zaretskii
  0 siblings, 2 replies; 99+ messages in thread
From: Simon Marchi @ 2019-03-25 18:33 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches, brobecker

On 2019-03-25 14:10, Eli Zaretskii wrote:
>> Is it worth having a test for that?
> 
> Hmm... how would you test that?

Something like

gdb_test "print \$_gdb_major" " = 8"
gdb_test "print \$_gdb_minor" " = 4"

Simon

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: GDB version as convenience variable
  2019-03-25 18:33                               ` Simon Marchi
@ 2019-03-25 18:37                                 ` Simon Marchi
  2019-03-25 18:43                                 ` Eli Zaretskii
  1 sibling, 0 replies; 99+ messages in thread
From: Simon Marchi @ 2019-03-25 18:37 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches, brobecker

On 2019-03-25 14:33, Simon Marchi wrote:
> On 2019-03-25 14:10, Eli Zaretskii wrote:
>>> Is it worth having a test for that?
>> 
>> Hmm... how would you test that?
> 
> Something like
> 
> gdb_test "print \$_gdb_major" " = 8"
> gdb_test "print \$_gdb_minor" " = 4"
> 
> Simon

Or, the test could somehow automatically get the current version of GDB 
and compare $_gdb_major/$_gdb_minor against that, so that we don't need 
to modify it at every release.

Simon

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: GDB version as convenience variable
  2019-03-25 18:33                               ` Simon Marchi
  2019-03-25 18:37                                 ` Simon Marchi
@ 2019-03-25 18:43                                 ` Eli Zaretskii
  2019-03-25 18:51                                   ` Simon Marchi
  1 sibling, 1 reply; 99+ messages in thread
From: Eli Zaretskii @ 2019-03-25 18:43 UTC (permalink / raw)
  To: Simon Marchi; +Cc: gdb-patches, brobecker

> Date: Mon, 25 Mar 2019 14:33:55 -0400
> From: Simon Marchi <simark@simark.ca>
> Cc: gdb-patches@sourceware.org, brobecker@adacore.com
> 
> > Hmm... how would you test that?
> 
> Something like
> 
> gdb_test "print \$_gdb_major" " = 8"
> gdb_test "print \$_gdb_minor" " = 4"

This would require changes with each new version.  I thought you had
in mind comparison with output of "gdb --version", suitably edited.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: GDB version as convenience variable
  2019-03-25 18:43                                 ` Eli Zaretskii
@ 2019-03-25 18:51                                   ` Simon Marchi
  2019-03-25 19:19                                     ` Eli Zaretskii
  0 siblings, 1 reply; 99+ messages in thread
From: Simon Marchi @ 2019-03-25 18:51 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches, brobecker

On 2019-03-25 14:43, Eli Zaretskii wrote:
>> Date: Mon, 25 Mar 2019 14:33:55 -0400
>> From: Simon Marchi <simark@simark.ca>
>> Cc: gdb-patches@sourceware.org, brobecker@adacore.com
>> 
>> > Hmm... how would you test that?
>> 
>> Something like
>> 
>> gdb_test "print \$_gdb_major" " = 8"
>> gdb_test "print \$_gdb_minor" " = 4"
> 
> This would require changes with each new version.  I thought you had
> in mind comparison with output of "gdb --version", suitably edited.

Yes, that's why I wondered initially if it was worth adding a test like 
this, since it would impose an additional burden on the person doing the 
release.  However, comparing the output with gdb --version, or some 
other automated mean, would be perfect.

Simon

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: GDB version as convenience variable
  2019-03-25 18:51                                   ` Simon Marchi
@ 2019-03-25 19:19                                     ` Eli Zaretskii
  2019-03-26 14:47                                       ` Simon Marchi
  0 siblings, 1 reply; 99+ messages in thread
From: Eli Zaretskii @ 2019-03-25 19:19 UTC (permalink / raw)
  To: Simon Marchi; +Cc: gdb-patches, brobecker

> Date: Mon, 25 Mar 2019 14:51:36 -0400
> From: Simon Marchi <simark@simark.ca>
> Cc: gdb-patches@sourceware.org, brobecker@adacore.com
> 
> comparing the output with gdb --version, or some other automated
> mean, would be perfect.

Well, I never wrote any tests for GDB, and I'm not sure I have a
system on which to run such a test.  So I hope someone else will add
this test.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: GDB version as convenience variable
  2019-03-25 19:19                                     ` Eli Zaretskii
@ 2019-03-26 14:47                                       ` Simon Marchi
  2019-03-26 20:57                                         ` Joel Brobecker
  2019-03-30 10:01                                         ` Eli Zaretskii
  0 siblings, 2 replies; 99+ messages in thread
From: Simon Marchi @ 2019-03-26 14:47 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches, brobecker

On 2019-03-25 3:18 p.m., Eli Zaretskii wrote:
>> Date: Mon, 25 Mar 2019 14:51:36 -0400
>> From: Simon Marchi <simark@simark.ca>
>> Cc: gdb-patches@sourceware.org, brobecker@adacore.com
>>
>> comparing the output with gdb --version, or some other automated
>> mean, would be perfect.
> 
> Well, I never wrote any tests for GDB, and I'm not sure I have a
> system on which to run such a test.  So I hope someone else will add
> this test.
> 

Apparently, the test default.exp needs to be changed in any case, because
it adds new convenience variables.  Without modification, the
"show convenience" test fails because there is a new entry it doesn't know
about.

So for now, I would suggest adding the modification below to your patch to keep
the test passing.  It is not obvious to change the test to match the convenience
variable value against a variable or even against a regexp, because it uses
gdb_test_list_exact, which does straight string comparison.

Also, I am not sure if reading the output of "show version" and testing against
that would be a really good test, because the implementation and the test would
work essentially work the same way.  So if the version string erroneously becomes
0.0.0 because of some bug in some script, the test would still pass, even though
the values are wrong.

At least, the following is simple and robust.


diff --git a/gdb/testsuite/gdb.base/default.exp b/gdb/testsuite/gdb.base/default.exp
index ece1428e617e..9ff5144448d8 100644
--- a/gdb/testsuite/gdb.base/default.exp
+++ b/gdb/testsuite/gdb.base/default.exp
@@ -602,6 +602,8 @@ set show_conv_list \
        {$_probe_arg10 = <error: No frame selected>} \
        {$_probe_arg11 = <error: No frame selected>} \
        {$_isvoid = <internal function _isvoid>} \
+       {$_gdb_major = 8} \
+       {$_gdb_minor = 4} \
     }
 if ![skip_python_tests] {
     append show_conv_list \


	
Simon

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: GDB version as convenience variable
  2019-03-26 14:47                                       ` Simon Marchi
@ 2019-03-26 20:57                                         ` Joel Brobecker
  2019-03-27  3:34                                           ` Eli Zaretskii
  2019-03-30 10:01                                         ` Eli Zaretskii
  1 sibling, 1 reply; 99+ messages in thread
From: Joel Brobecker @ 2019-03-26 20:57 UTC (permalink / raw)
  To: Simon Marchi; +Cc: Eli Zaretskii, gdb-patches

> Apparently, the test default.exp needs to be changed in any case,
> because it adds new convenience variables.  Without modification, the
> "show convenience" test fails because there is a new entry it doesn't
> know about.
> 
> So for now, I would suggest adding the modification below to your
> patch to keep the test passing.  It is not obvious to change the test
> to match the convenience variable value against a variable or even
> against a regexp, because it uses gdb_test_list_exact, which does
> straight string comparison.
> 
> Also, I am not sure if reading the output of "show version" and
> testing against that would be a really good test, because the
> implementation and the test would work essentially work the same way.
> So if the version string erroneously becomes 0.0.0 because of some bug
> in some script, the test would still pass, even though the values are
> wrong.
> 
> At least, the following is simple and robust.

Hmmm, the direct string comparison thing is a bit annoying.

This is going to be one more manual test to do after each branch,
and I'm a bit concerned about that. We can start with that, as we want
the test to pass. But I'm wondering if, instead of getting the output
from "show version" to determine the expected values, we could parse
gdb/version.in instead. If needed, we could so the parsing as part of
the build process (ig do it in the makefile, and store the result in
a couple of files). Something like that.

> diff --git a/gdb/testsuite/gdb.base/default.exp b/gdb/testsuite/gdb.base/default.exp
> index ece1428e617e..9ff5144448d8 100644
> --- a/gdb/testsuite/gdb.base/default.exp
> +++ b/gdb/testsuite/gdb.base/default.exp
> @@ -602,6 +602,8 @@ set show_conv_list \
>         {$_probe_arg10 = <error: No frame selected>} \
>         {$_probe_arg11 = <error: No frame selected>} \
>         {$_isvoid = <internal function _isvoid>} \
> +       {$_gdb_major = 8} \
> +       {$_gdb_minor = 4} \
>      }
>  if ![skip_python_tests] {
>      append show_conv_list \
> 
> 
> 	
> Simon

-- 
Joel

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: GDB version as convenience variable
  2019-03-26 20:57                                         ` Joel Brobecker
@ 2019-03-27  3:34                                           ` Eli Zaretskii
  2019-03-27 12:56                                             ` Joel Brobecker
  0 siblings, 1 reply; 99+ messages in thread
From: Eli Zaretskii @ 2019-03-27  3:34 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: simark, gdb-patches

> Date: Tue, 26 Mar 2019 13:57:16 -0700
> From: Joel Brobecker <brobecker@adacore.com>
> Cc: Eli Zaretskii <eliz@gnu.org>, gdb-patches@sourceware.org
> 
> This is going to be one more manual test to do after each branch,
> and I'm a bit concerned about that. We can start with that, as we want
> the test to pass. But I'm wondering if, instead of getting the output
> from "show version" to determine the expected values, we could parse
> gdb/version.in instead. If needed, we could so the parsing as part of
> the build process (ig do it in the makefile, and store the result in
> a couple of files). Something like that.

Yes, if version.in is updated by some automated method, the same
method could update the test suite.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: GDB version as convenience variable
  2019-03-27  3:34                                           ` Eli Zaretskii
@ 2019-03-27 12:56                                             ` Joel Brobecker
  2019-03-30 17:25                                               ` Simon Marchi
  0 siblings, 1 reply; 99+ messages in thread
From: Joel Brobecker @ 2019-03-27 12:56 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: simark, gdb-patches

> > This is going to be one more manual test to do after each branch,
> > and I'm a bit concerned about that. We can start with that, as we want
> > the test to pass. But I'm wondering if, instead of getting the output
> > from "show version" to determine the expected values, we could parse
> > gdb/version.in instead. If needed, we could so the parsing as part of
> > the build process (ig do it in the makefile, and store the result in
> > a couple of files). Something like that.
> 
> Yes, if version.in is updated by some automated method, the same
> method could update the test suite.

We're actually thinking of getting rid of that daily bump, and doing
this would make it more difficult. There has to be a way to parse
version.in during the build and make that information available to
the testsuite, somehow. If not, I'd rather adjust the testing to
allow regexps, and just verify that it prints a positive number for
the major version, and a non-zero number for the minor version.

-- 
Joel

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: GDB version as convenience variable
  2019-03-26 14:47                                       ` Simon Marchi
  2019-03-26 20:57                                         ` Joel Brobecker
@ 2019-03-30 10:01                                         ` Eli Zaretskii
  1 sibling, 0 replies; 99+ messages in thread
From: Eli Zaretskii @ 2019-03-30 10:01 UTC (permalink / raw)
  To: Simon Marchi; +Cc: gdb-patches, brobecker

> From: Simon Marchi <simark@simark.ca>
> Cc: gdb-patches@sourceware.org, brobecker@adacore.com
> Date: Tue, 26 Mar 2019 10:46:56 -0400
> 
> Apparently, the test default.exp needs to be changed in any case, because
> it adds new convenience variables.  Without modification, the
> "show convenience" test fails because there is a new entry it doesn't know
> about.
> 
> So for now, I would suggest adding the modification below to your patch to keep
> the test passing.  It is not obvious to change the test to match the convenience
> variable value against a variable or even against a regexp, because it uses
> gdb_test_list_exact, which does straight string comparison.
> 
> Also, I am not sure if reading the output of "show version" and testing against
> that would be a really good test, because the implementation and the test would
> work essentially work the same way.  So if the version string erroneously becomes
> 0.0.0 because of some bug in some script, the test would still pass, even though
> the values are wrong.
> 
> At least, the following is simple and robust.

Thanks, I used that, and pushed the changes including this one.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: GDB version as convenience variable
  2019-03-27 12:56                                             ` Joel Brobecker
@ 2019-03-30 17:25                                               ` Simon Marchi
  0 siblings, 0 replies; 99+ messages in thread
From: Simon Marchi @ 2019-03-30 17:25 UTC (permalink / raw)
  To: Joel Brobecker, Eli Zaretskii; +Cc: gdb-patches

On 2019-03-27 8:56 a.m., Joel Brobecker wrote:
>>> This is going to be one more manual test to do after each branch,
>>> and I'm a bit concerned about that. We can start with that, as we want
>>> the test to pass. But I'm wondering if, instead of getting the output
>>> from "show version" to determine the expected values, we could parse
>>> gdb/version.in instead. If needed, we could so the parsing as part of
>>> the build process (ig do it in the makefile, and store the result in
>>> a couple of files). Something like that.
>>
>> Yes, if version.in is updated by some automated method, the same
>> method could update the test suite.
> 
> We're actually thinking of getting rid of that daily bump, and doing
> this would make it more difficult. There has to be a way to parse
> version.in during the build and make that information available to
> the testsuite, somehow. If not, I'd rather adjust the testing to
> allow regexps, and just verify that it prints a positive number for
> the major version, and a non-zero number for the minor version.
> 

I wrote a patch to make the test read the version number from version.in
directly, see here:

https://sourceware.org/ml/gdb-patches/2019-03/msg00762.html

Simon

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 15/16] Highlight source code using GNU Source Highlight
  2018-11-28  0:16 ` [PATCH 15/16] Highlight source code using GNU Source Highlight Tom Tromey
@ 2019-11-16  0:58   ` Andrew Pinski
  2019-11-16  8:19     ` Eli Zaretskii
  2019-11-24 17:41     ` Tom Tromey
  0 siblings, 2 replies; 99+ messages in thread
From: Andrew Pinski @ 2019-11-16  0:58 UTC (permalink / raw)
  To: Tom Tromey; +Cc: GDB Patches

On Tue, Nov 27, 2018 at 4:16 PM Tom Tromey <tom@tromey.com> wrote:
>
> This changes gdb to highlight source using GNU Source Highlight, if it
> is available.
>
> This affects the output of the "list" command and also the TUI source
> window.
>
> No new test because I didn't see a way to make it work when Source
> Highlight is not found.

I know this patch has been in for almost a year now.  But I have a
question, is there a way to build GNU Source Highlight as a static
library and have it built at the top level?  Like what is done for
GMP/MPFR for GCC?  It would reduce how I built a gdb that is for a
non-native target.
If it cannot be compiled at a top-level, does it support as a static
library?  I have not looked fully though.  The reason is I want to
support one gdb that can be run on multiple (some older) distros.

Thanks,
Andrew Pinski


>
> gdb/ChangeLog
> 2018-11-27  Tom Tromey  <tom@tromey.com>
>
>         * utils.h (can_emit_style_escape): Declare.
>         * utils.c (can_emit_style_escape): No longer static.
>         * cli/cli-style.c (set_style_enabled): New function.
>         (_initialize_cli_style): Use it.
>         * tui/tui-winsource.c (tui_show_source_line): Use tui_puts.
>         (tui_alloc_source_buffer): Change how source lines are allocated.
>         * tui/tui-source.c (copy_source_line): New function.
>         (tui_set_source_content): Use source cache.
>         * tui/tui-io.h (tui_puts): Update.
>         * tui/tui-io.c (tui_puts_internal): Add window parameter.
>         (tui_puts): Likewise.
>         (tui_redisplay_readline): Update.
>         * tui/tui-data.c (free_content_elements): Change how source window
>         contents are freed.
>         * source.c (forget_cached_source_info): Clear the source cache.
>         (print_source_lines_base): Use the source cache.
>         * source-cache.h: New file.
>         * source-cache.c: New file.
>         * configure.ac: Check for GNU Source Highlight library.
>         * configure: Update.
>         * config.in: Update.
>         * Makefile.in (SRCHIGH_LIBS, SRCHIGH_CFLAGS): New variables.
>         (INTERNAL_CFLAGS_BASE): Add SRCHIGH_CFLAGS.
>         (CLIBS): Add SRCHIGH_LIBS.
>         (COMMON_SFILES): Add source-cache.c.
>         (HFILES_NO_SRCDIR): Add source-cache.h.
> ---
>  gdb/ChangeLog           |  29 ++++
>  gdb/Makefile.in         |  12 +-
>  gdb/cli/cli-style.c     |   9 +-
>  gdb/config.in           |   3 +
>  gdb/configure           |  30 ++++
>  gdb/configure.ac        |  23 +++
>  gdb/source-cache.c      | 209 +++++++++++++++++++++++++++
>  gdb/source-cache.h      |  79 +++++++++++
>  gdb/source.c            |  38 ++---
>  gdb/tui/tui-data.c      |   5 +-
>  gdb/tui/tui-io.c        |  11 +-
>  gdb/tui/tui-io.h        |   4 +-
>  gdb/tui/tui-source.c    | 302 +++++++++++++++++++---------------------
>  gdb/tui/tui-winsource.c |  17 +--
>  gdb/utils.c             |   4 +-
>  gdb/utils.h             |   4 +
>  16 files changed, 576 insertions(+), 203 deletions(-)
>  create mode 100644 gdb/source-cache.c
>  create mode 100644 gdb/source-cache.h
>
> diff --git a/gdb/Makefile.in b/gdb/Makefile.in
> index 54baf96ea3..50d429d792 100644
> --- a/gdb/Makefile.in
> +++ b/gdb/Makefile.in
> @@ -194,6 +194,10 @@ LIBIPT = @LIBIPT@
>  # Where is libmpfr?  This will be empty if libmpfr was not available.
>  LIBMPFR = @LIBMPFR@
>
> +# GNU source highlight library.
> +SRCHIGH_LIBS = @SRCHIGH_LIBS@
> +SRCHIGH_CFLAGS = @SRCHIGH_CFLAGS@
> +
>  WARN_CFLAGS = @WARN_CFLAGS@
>  WERROR_CFLAGS = @WERROR_CFLAGS@
>  GDB_WARN_CFLAGS = $(WARN_CFLAGS)
> @@ -565,7 +569,8 @@ INTERNAL_CFLAGS_BASE = \
>         $(CXXFLAGS) $(GLOBAL_CFLAGS) $(PROFILE_CFLAGS) \
>         $(GDB_CFLAGS) $(OPCODES_CFLAGS) $(READLINE_CFLAGS) $(ZLIBINC) \
>         $(BFD_CFLAGS) $(INCLUDE_CFLAGS) $(LIBDECNUMBER_CFLAGS) \
> -       $(INTL_CFLAGS) $(INCGNU) $(ENABLE_CFLAGS) $(INTERNAL_CPPFLAGS)
> +       $(INTL_CFLAGS) $(INCGNU) $(ENABLE_CFLAGS) $(INTERNAL_CPPFLAGS) \
> +       $(SRCHIGH_CFLAGS)
>  INTERNAL_WARN_CFLAGS = $(INTERNAL_CFLAGS_BASE) $(GDB_WARN_CFLAGS)
>  INTERNAL_CFLAGS = $(INTERNAL_WARN_CFLAGS) $(GDB_WERROR_CFLAGS)
>
> @@ -591,7 +596,8 @@ CLIBS = $(SIM) $(READLINE) $(OPCODES) $(BFD) $(ZLIB) $(INTL) $(LIBIBERTY) $(LIBD
>         $(XM_CLIBS) $(GDBTKLIBS) \
>         @LIBS@ @GUILE_LIBS@ @PYTHON_LIBS@ \
>         $(LIBEXPAT) $(LIBLZMA) $(LIBBABELTRACE) $(LIBIPT) \
> -       $(LIBIBERTY) $(WIN32LIBS) $(LIBGNU) $(LIBICONV) $(LIBMPFR)
> +       $(LIBIBERTY) $(WIN32LIBS) $(LIBGNU) $(LIBICONV) $(LIBMPFR) \
> +       $(SRCHIGH_LIBS)
>  CDEPS = $(NAT_CDEPS) $(SIM) $(BFD) $(READLINE_DEPS) \
>         $(OPCODES) $(INTL_DEPS) $(LIBIBERTY) $(CONFIG_DEPS) $(LIBGNU)
>
> @@ -1101,6 +1107,7 @@ COMMON_SFILES = \
>         solib.c \
>         solib-target.c \
>         source.c \
> +       source-cache.c \
>         stabsread.c \
>         stack.c \
>         std-regs.c \
> @@ -1376,6 +1383,7 @@ HFILES_NO_SRCDIR = \
>         solib-target.h \
>         solist.h \
>         source.h \
> +       source-cache.h \
>         sparc-nat.h \
>         sparc-ravenscar-thread.h \
>         sparc-tdep.h \
> diff --git a/gdb/cli/cli-style.c b/gdb/cli/cli-style.c
> index 74e3958eb8..16415e0f88 100644
> --- a/gdb/cli/cli-style.c
> +++ b/gdb/cli/cli-style.c
> @@ -20,6 +20,7 @@
>  #include "defs.h"
>  #include "cli/cli-cmds.h"
>  #include "cli/cli-style.h"
> +#include "source-cache.h"
>
>  /* True if styling is enabled.  */
>
> @@ -216,6 +217,12 @@ show_style (const char *arg, int from_tty)
>  {
>  }
>
> +static void
> +set_style_enabled  (const char *args, int from_tty, struct cmd_list_element *c)
> +{
> +  g_source_cache.clear ();
> +}
> +
>  static void
>  show_style_enabled (struct ui_file *file, int from_tty,
>                     struct cmd_list_element *c, const char *value)
> @@ -245,7 +252,7 @@ Configure various style-related variables, such as colors"),
>  Set whether CLI styling is enabled."), _("\
>  Show whether CLI is enabled."), _("\
>  If enabled, output to the terminal is styled."),
> -                          NULL, show_style_enabled,
> +                          set_style_enabled, show_style_enabled,
>                            &style_set_list, &style_show_list);
>
>    file_name_style.add_setshow_commands ("filename", no_class,
> diff --git a/gdb/config.in b/gdb/config.in
> index 760db6b320..ea907d2b56 100644
> --- a/gdb/config.in
> +++ b/gdb/config.in
> @@ -426,6 +426,9 @@
>  /* Define to 1 if the system has the type `socklen_t'. */
>  #undef HAVE_SOCKLEN_T
>
> +/* Define to 1 if the source-highlight library is available */
> +#undef HAVE_SOURCE_HIGHLIGHT
> +
>  /* Define to 1 if you have the <stdint.h> header file. */
>  #undef HAVE_STDINT_H
>
> diff --git a/gdb/configure b/gdb/configure
> index 44df6ebcfb..811664ed40 100755
> --- a/gdb/configure
> +++ b/gdb/configure
> @@ -701,6 +701,8 @@ ALLOCA
>  LTLIBIPT
>  LIBIPT
>  HAVE_LIBIPT
> +SRCHIGH_CFLAGS
> +SRCHIGH_LIBS
>  HAVE_GUILE_FALSE
>  HAVE_GUILE_TRUE
>  GUILE_LIBS
> @@ -11469,6 +11471,34 @@ else
>  fi
>
>
> +# ---------------------------- #
> +# Check for source highlight.  #
> +# ---------------------------- #
> +
> +SRCHIGH_LIBS=
> +SRCHIGH_CFLAGS=
> +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for source highlight" >&5
> +$as_echo_n "checking for source highlight... " >&6; }
> +if test "${pkg_config_prog_path}" = "missing"; then
> +   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no - pkg-config not found" >&5
> +$as_echo "no - pkg-config not found" >&6; }
> +else
> +   if ${pkg_config_prog_path} --exists source-highlight; then
> +      SRCHIGH_CFLAGS=`${pkg_config_prog_path} --cflags source-highlight`
> +      SRCHIGH_LIBS=`${pkg_config_prog_path} --libs source-highlight`
> +
> +$as_echo "#define HAVE_SOURCE_HIGHLIGHT 1" >>confdefs.h
> +
> +      { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
> +$as_echo "yes" >&6; }
> +   else
> +      { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
> +$as_echo "no" >&6; }
> +   fi
> +fi
> +
> +
> +
>  # --------------------- #
>  # Check for libmcheck.  #
>  # --------------------- #
> diff --git a/gdb/configure.ac b/gdb/configure.ac
> index 56cd0927bb..7d2d39b710 100644
> --- a/gdb/configure.ac
> +++ b/gdb/configure.ac
> @@ -1226,6 +1226,29 @@ AC_SUBST(GUILE_CPPFLAGS)
>  AC_SUBST(GUILE_LIBS)
>  AM_CONDITIONAL(HAVE_GUILE, test "${have_libguile}" != no)
>
> +# ---------------------------- #
> +# Check for source highlight.  #
> +# ---------------------------- #
> +
> +SRCHIGH_LIBS=
> +SRCHIGH_CFLAGS=
> +AC_MSG_CHECKING([for the source-highlight library])
> +if test "${pkg_config_prog_path}" = "missing"; then
> +   AC_MSG_RESULT([no - pkg-config not found])
> +else
> +   if ${pkg_config_prog_path} --exists source-highlight; then
> +      SRCHIGH_CFLAGS=`${pkg_config_prog_path} --cflags source-highlight`
> +      SRCHIGH_LIBS=`${pkg_config_prog_path} --libs source-highlight`
> +      AC_DEFINE([HAVE_SOURCE_HIGHLIGHT], 1,
> +                [Define to 1 if the source-highlight library is available])
> +      AC_MSG_RESULT([yes])
> +   else
> +      AC_MSG_RESULT([no])
> +   fi
> +fi
> +AC_SUBST(SRCHIGH_LIBS)
> +AC_SUBST(SRCHIGH_CFLAGS)
> +
>  # --------------------- #
>  # Check for libmcheck.  #
>  # --------------------- #
> diff --git a/gdb/source-cache.c b/gdb/source-cache.c
> new file mode 100644
> index 0000000000..56851806e4
> --- /dev/null
> +++ b/gdb/source-cache.c
> @@ -0,0 +1,209 @@
> +/* Cache of styled source file text
> +   Copyright (C) 2018 Free Software Foundation, Inc.
> +
> +   This file is part of GDB.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
> +
> +#include "defs.h"
> +#include "source-cache.h"
> +#include "common/scoped_fd.h"
> +#include "source.h"
> +#include "cli/cli-style.h"
> +
> +#ifdef HAVE_SOURCE_HIGHLIGHT
> +#include <fstream>
> +#include <sstream>
> +#include <srchilite/sourcehighlight.h>
> +#include <srchilite/langmap.h>
> +#endif
> +
> +/* The number of source files we'll cache.  */
> +
> +#define MAX_ENTRIES 5
> +
> +/* See source-cache.h.  */
> +
> +source_cache g_source_cache;
> +
> +/* See source-cache.h.  */
> +
> +bool
> +source_cache::get_plain_source_lines (struct symtab *s, int first_line,
> +                                     int last_line, std::string *lines)
> +{
> +  scoped_fd desc (open_source_file (s));
> +  if (desc.get () < 0)
> +    return false;
> +
> +  if (s->line_charpos == 0)
> +    find_source_lines (s, desc.get ());
> +
> +  if (first_line < 1 || first_line > s->nlines || last_line < 1)
> +    return false;
> +
> +  if (lseek (desc.get (), s->line_charpos[first_line - 1], SEEK_SET) < 0)
> +    perror_with_name (symtab_to_filename_for_display (s));
> +
> +  int last_charpos;
> +  if (last_line >= s->nlines)
> +    {
> +      struct stat st;
> +
> +      if (fstat (desc.get (), &st) < 0)
> +       perror_with_name (symtab_to_filename_for_display (s));
> +      /* We could cache this in line_charpos... */
> +      last_charpos = st.st_size;
> +    }
> +  else
> +    last_charpos = s->line_charpos[last_line];
> +
> +  lines->resize (last_charpos - s->line_charpos[first_line - 1]);
> +  if (myread (desc.get (), &(*lines)[0], lines->size ()) < 0)
> +    perror_with_name (symtab_to_filename_for_display (s));
> +
> +  return true;
> +}
> +
> +/* See source-cache.h.  */
> +
> +bool
> +source_cache::extract_lines (const struct source_text &text, int first_line,
> +                            int last_line, std::string *lines)
> +{
> +  int lineno = 1;
> +  std::string::size_type pos = 0;
> +  std::string::size_type first_pos = std::string::npos;
> +
> +  while (pos != std::string::npos && lineno <= last_line)
> +    {
> +      std::string::size_type new_pos = text.contents.find ('\n', pos);
> +
> +      if (lineno == first_line)
> +       first_pos = pos;
> +
> +      pos = new_pos;
> +      if (lineno == last_line || pos == std::string::npos)
> +       {
> +         if (pos == std::string::npos)
> +           pos = text.contents.size ();
> +         *lines = text.contents.substr (first_pos, pos - first_pos);
> +         return true;
> +       }
> +      ++lineno;
> +      ++pos;
> +    }
> +
> +  return false;
> +}
> +
> +/* Return the Source Highlight language name, given a gdb language
> +   LANG.  Returns NULL if the language is not known.  */
> +
> +static const char *
> +get_language_name (enum language lang)
> +{
> +  switch (lang)
> +    {
> +    case language_c:
> +    case language_objc:
> +      return "c.lang";
> +
> +    case language_cplus:
> +      return "cpp.lang";
> +
> +    case language_d:
> +      return "d.lang";
> +
> +    case language_go:
> +      return "go.lang";
> +
> +    case language_fortran:
> +      return "fortran.lang";
> +
> +    case language_m2:
> +      /* Not handled by Source Highlight.  */
> +      break;
> +
> +    case language_asm:
> +      return "asm.lang";
> +
> +    case language_pascal:
> +      return "pascal.lang";
> +
> +    case language_opencl:
> +      /* Not handled by Source Highlight.  */
> +      break;
> +
> +    case language_rust:
> +      /* Not handled by Source Highlight.  */
> +      break;
> +
> +    case language_ada:
> +      return "ada.lang";
> +
> +    default:
> +      break;
> +    }
> +
> +  return nullptr;
> +}
> +
> +/* See source-cache.h.  */
> +
> +bool
> +source_cache::get_source_lines (struct symtab *s, int first_line,
> +                               int last_line, std::string *lines)
> +{
> +  if (first_line < 1 || last_line < 1 || first_line > last_line)
> +    return false;
> +
> +#ifdef HAVE_SOURCE_HIGHLIGHT
> +  if (can_emit_style_escape (gdb_stdout))
> +    {
> +      const char *fullname = symtab_to_fullname (s);
> +
> +      for (const auto &item : m_source_map)
> +       {
> +         if (item.fullname == fullname)
> +           return extract_lines (item, first_line, last_line, lines);
> +       }
> +
> +      const char *lang_name = get_language_name (SYMTAB_LANGUAGE (s));
> +      if (lang_name != nullptr)
> +       {
> +         std::ifstream input (fullname);
> +         if (input.is_open ())
> +           {
> +             srchilite::SourceHighlight highlighter ("esc.outlang");
> +             highlighter.setStyleFile("esc.style");
> +
> +             std::ostringstream output;
> +             highlighter.highlight (input, output, lang_name, fullname);
> +
> +             source_text result = { fullname, output.str () };
> +             m_source_map.push_back (std::move (result));
> +
> +             if (m_source_map.size () > MAX_ENTRIES)
> +               m_source_map.erase (m_source_map.begin ());
> +
> +             return extract_lines (m_source_map.back (), first_line,
> +                                   last_line, lines);
> +           }
> +       }
> +    }
> +#endif /* HAVE_SOURCE_HIGHLIGHT */
> +
> +  return get_plain_source_lines (s, first_line, last_line, lines);
> +}
> diff --git a/gdb/source-cache.h b/gdb/source-cache.h
> new file mode 100644
> index 0000000000..2236d38846
> --- /dev/null
> +++ b/gdb/source-cache.h
> @@ -0,0 +1,79 @@
> +/* Cache of styled source file text
> +   Copyright (C) 2018 Free Software Foundation, Inc.
> +
> +   This file is part of GDB.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
> +
> +#ifndef SOURCE_CACHE_H
> +#define SOURCE_CACHE_H
> +
> +/* This caches highlighted source text, keyed by the source file's
> +   full name.  A size-limited LRU cache is used.
> +
> +   Highlighting depends on the GNU Source Highlight library.  When not
> +   available, this cache will fall back on reading plain text from the
> +   appropriate file.  */
> +class source_cache
> +{
> +public:
> +
> +  source_cache ()
> +  {
> +  }
> +
> +  /* Get the source text for the source file in symtab S.  FIRST_LINE
> +     and LAST_LINE are the first and last lines to return; line
> +     numbers are 1-based.  If the file cannot be read, false is
> +     returned.  Otherwise, LINES is set to the desired text.  The
> +     returned text may include ANSI terminal escapes.  */
> +  bool get_source_lines (struct symtab *s, int first_line,
> +                        int last_line, std::string *lines);
> +
> +  /* Remove all the items from the source cache.  */
> +  void clear ()
> +  {
> +    m_source_map.clear ();
> +  }
> +
> +private:
> +
> +  /* One element in the cache.  */
> +  struct source_text
> +  {
> +    /* The full name of the file.  */
> +    std::string fullname;
> +    /* The contents of the file.  */
> +    std::string contents;
> +  };
> +
> +  /* A helper function for get_source_lines that is used when the
> +     source lines are not highlighted.  The arguments and return value
> +     are as for get_source_lines.  */
> +  bool get_plain_source_lines (struct symtab *s, int first_line,
> +                              int last_line, std::string *lines);
> +  /* A helper function for get_plain_source_lines that extracts the
> +     desired source lines from TEXT, putting them into LINES.  The
> +     arguments and return value are as for get_source_lines.  */
> +  bool extract_lines (const struct source_text &text, int first_line,
> +                     int last_line, std::string *lines);
> +
> +  /* The contents of the cache.  */
> +  std::vector<source_text> m_source_map;
> +};
> +
> +/* The global source cache.  */
> +extern source_cache g_source_cache;
> +
> +#endif /* SOURCE_CACHE_H */
> diff --git a/gdb/source.c b/gdb/source.c
> index 7552496f78..aa7eb8a6d4 100644
> --- a/gdb/source.c
> +++ b/gdb/source.c
> @@ -45,6 +45,7 @@
>  #include "common/scoped_fd.h"
>  #include <algorithm>
>  #include "common/pathstuff.h"
> +#include "source-cache.h"
>
>  #define OPEN_MODE (O_RDONLY | O_BINARY)
>  #define FDOPEN_MODE FOPEN_RB
> @@ -393,6 +394,7 @@ forget_cached_source_info (void)
>        forget_cached_source_info_for_objfile (objfile);
>      }
>
> +  g_source_cache.clear ();
>    last_source_visited = NULL;
>  }
>
> @@ -1344,25 +1346,18 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
>
>    last_source_error = 0;
>
> -  if (s->line_charpos == 0)
> -    find_source_lines (s, desc.get ());
> -
> -  if (line < 1 || line > s->nlines)
> +  std::string lines;
> +  if (!g_source_cache.get_source_lines (s, line, stopline - 1, &lines))
>      error (_("Line number %d out of range; %s has %d lines."),
>            line, symtab_to_filename_for_display (s), s->nlines);
>
> -  if (lseek (desc.get (), s->line_charpos[line - 1], 0) < 0)
> -    perror_with_name (symtab_to_filename_for_display (s));
> -
> -  gdb_file_up stream = desc.to_file (FDOPEN_MODE);
> -  clearerr (stream.get ());
> -
> +  const char *iter = lines.c_str ();
>    while (nlines-- > 0)
>      {
>        char buf[20];
>
> -      c = fgetc (stream.get ());
> -      if (c == EOF)
> +      c = *iter++;
> +      if (c == '\0')
>         break;
>        last_line_listed = current_source_line;
>        if (flags & PRINT_SOURCE_LINES_FILENAME)
> @@ -1374,7 +1369,7 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
>        uiout->text (buf);
>        do
>         {
> -         if (c < 040 && c != '\t' && c != '\n' && c != '\r')
> +         if (c < 040 && c != '\t' && c != '\n' && c != '\r' && c != '\033')
>             {
>               xsnprintf (buf, sizeof (buf), "^%c", c + 0100);
>               uiout->text (buf);
> @@ -1384,12 +1379,13 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
>           else if (c == '\r')
>             {
>               /* Skip a \r character, but only before a \n.  */
> -             int c1 = fgetc (stream.get ());
> -
> -             if (c1 != '\n')
> +             if (iter[1] == '\n')
> +               {
> +                 ++iter;
> +                 c = '\n';
> +               }
> +             else
>                 printf_filtered ("^%c", c + 0100);
> -             if (c1 != EOF)
> -               ungetc (c1, stream.get ());
>             }
>           else
>             {
> @@ -1397,8 +1393,12 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
>               uiout->text (buf);
>             }
>         }
> -      while (c != '\n' && (c = fgetc (stream.get ())) >= 0);
> +      while (c != '\n' && (c = *iter++) != '\0');
> +      if (c == '\0')
> +       break;
>      }
> +  if (lines.back () != '\n')
> +    uiout->text ("\n");
>  }
>
>  /* Show source lines from the file of symtab S, starting with line
> diff --git a/gdb/tui/tui-data.c b/gdb/tui/tui-data.c
> index 4391f0d100..2b95f197fd 100644
> --- a/gdb/tui/tui-data.c
> +++ b/gdb/tui/tui-data.c
> @@ -838,7 +838,7 @@ free_content_elements (tui_win_content content,
>      {
>        int i;
>
> -      if (type == SRC_WIN || type == DISASSEM_WIN)
> +      if (type == DISASSEM_WIN)
>         {
>           /* Free whole source block.  */
>           xfree (content[0]->which_element.source.line);
> @@ -854,6 +854,9 @@ free_content_elements (tui_win_content content,
>                 {
>                   switch (type)
>                     {
> +                   case SRC_WIN:
> +                     xfree (element->which_element.source.line);
> +                     break;
>                     case DATA_WIN:
>                       xfree (element);
>                       break;
> diff --git a/gdb/tui/tui-io.c b/gdb/tui/tui-io.c
> index b1099246dd..0c7b88f1c7 100644
> --- a/gdb/tui/tui-io.c
> +++ b/gdb/tui/tui-io.c
> @@ -367,9 +367,8 @@ tui_write (const char *buf, size_t length)
>  }
>
>  static void
> -tui_puts_internal (const char *string, int *height)
> +tui_puts_internal (WINDOW *w, const char *string, int *height)
>  {
> -  WINDOW *w = TUI_CMD_WIN->generic.handle;
>    char c;
>    int prev_col = 0;
>
> @@ -410,9 +409,11 @@ tui_puts_internal (const char *string, int *height)
>     necessary.  */
>
>  void
> -tui_puts (const char *string)
> +tui_puts (const char *string, WINDOW *w)
>  {
> -  tui_puts_internal (string, nullptr);
> +  if (w == nullptr)
> +    w = TUI_CMD_WIN->generic.handle;
> +  tui_puts_internal (w, string, nullptr);
>  }
>
>  /* Readline callback.
> @@ -453,7 +454,7 @@ tui_redisplay_readline (void)
>    prev_col = 0;
>    height = 1;
>    if (prompt != nullptr)
> -    tui_puts_internal (prompt, &height);
> +    tui_puts_internal (TUI_CMD_WIN->generic.handle, prompt, &height);
>
>    prev_col = getcurx (w);
>    for (in = 0; in <= rl_end; in++)
> diff --git a/gdb/tui/tui-io.h b/gdb/tui/tui-io.h
> index 11752d0845..95887639ec 100644
> --- a/gdb/tui/tui-io.h
> +++ b/gdb/tui/tui-io.h
> @@ -22,11 +22,13 @@
>  #ifndef TUI_IO_H
>  #define TUI_IO_H
>
> +#include "gdb_curses.h"
> +
>  struct ui_out;
>  class cli_ui_out;
>
>  /* Print the string in the curses command window.  */
> -extern void tui_puts (const char *);
> +extern void tui_puts (const char *, WINDOW * = nullptr);
>
>  /* Print LENGTH characters from the buffer pointed to by BUF to the
>     curses command window.  */
> diff --git a/gdb/tui/tui-source.c b/gdb/tui/tui-source.c
> index 3c4f06b01a..260b274297 100644
> --- a/gdb/tui/tui-source.c
> +++ b/gdb/tui/tui-source.c
> @@ -28,14 +28,90 @@
>  #include "symtab.h"
>  #include "objfiles.h"
>  #include "filenames.h"
> +#include "source-cache.h"
>
>  #include "tui/tui.h"
>  #include "tui/tui-data.h"
> +#include "tui/tui-io.h"
>  #include "tui/tui-stack.h"
>  #include "tui/tui-winsource.h"
>  #include "tui/tui-source.h"
>  #include "gdb_curses.h"
>
> +/* A helper function for tui_set_source_content that extracts some
> +   source text from PTR.  LINE_NO is the line number; FIRST_COL is the
> +   first column to extract, and LINE_WIDTH is the number of characters
> +   to display.  Returns a string holding the desired text.  */
> +
> +static std::string
> +copy_source_line (const char **ptr, int line_no, int first_col,
> +                 int line_width)
> +{
> +  const char *lineptr = *ptr;
> +
> +  /* Init the line with the line number.  */
> +  std::string result = string_printf ("%-6d", line_no);
> +  int len = result.size ();
> +  len = len - ((len / tui_tab_width) * tui_tab_width);
> +  result.append (len, ' ');
> +
> +  int column = 0;
> +  char c;
> +  do
> +    {
> +      int skip_bytes;
> +
> +      c = *lineptr;
> +      if (c == '\033' && skip_ansi_escape (lineptr, &skip_bytes))
> +       {
> +         /* We always have to preserve escapes.  */
> +         result.append (lineptr, lineptr + skip_bytes);
> +         lineptr += skip_bytes;
> +         continue;
> +       }
> +
> +      ++lineptr;
> +      ++column;
> +      /* We have to process all the text in order to pick up all the
> +        escapes.  */
> +      if (column < first_col || column > first_col + line_width)
> +       continue;
> +
> +      if (c == '\n' || c == '\r' || c == '\0')
> +       {
> +         /* Nothing.  */
> +       }
> +      else if (c < 040 && c != '\t')
> +       {
> +         result.push_back ('^');
> +         result.push_back (c + 0100);
> +       }
> +      else if (c == 0177)
> +       {
> +         result.push_back ('^');
> +         result.push_back ('?');
> +       }
> +      else if (c == '\t')
> +       {
> +         int j, max_tab_len = tui_tab_width;
> +
> +         for (j = column - ((column / max_tab_len) * max_tab_len);
> +              j < max_tab_len && column < first_col + line_width;
> +              column++, j++)
> +           result.push_back (' ');
> +       }
> +      else
> +       result.push_back (c);
> +    }
> +  while (c != '\0' && c != '\n' && c != '\r');
> +
> +  if (c == '\r' && *lineptr == '\n')
> +    ++lineptr;
> +  *ptr = lineptr;
> +
> +  return result;
> +}
> +
>  /* Function to display source in the source window.  */
>  enum tui_status
>  tui_set_source_content (struct symtab *s,
> @@ -46,8 +122,7 @@ tui_set_source_content (struct symtab *s,
>
>    if (s != (struct symtab *) NULL)
>      {
> -      int i, c, line_width, nlines;
> -      char *src_line = 0;
> +      int line_width, nlines;
>
>        if ((ret = tui_alloc_source_buffer (TUI_SRC_WIN)) == TUI_SUCCESS)
>         {
> @@ -55,8 +130,10 @@ tui_set_source_content (struct symtab *s,
>           /* Take hilite (window border) into account, when
>              calculating the number of lines.  */
>           nlines = (line_no + (TUI_SRC_WIN->generic.height - 2)) - line_no;
> -         scoped_fd desc = open_source_file (s);
> -         if (desc.get () < 0)
> +
> +         std::string srclines;
> +         if (!g_source_cache.get_source_lines (s, line_no, line_no + nlines,
> +                                               &srclines))
>             {
>               if (!noerror)
>                 {
> @@ -70,165 +147,68 @@ tui_set_source_content (struct symtab *s,
>             }
>           else
>             {
> -             if (s->line_charpos == 0)
> -               find_source_lines (s, desc.get ());
> -
> -             if (line_no < 1 || line_no > s->nlines)
> -               printf_unfiltered ("Line number %d out of range; "
> -                                  "%s has %d lines.\n",
> -                                  line_no,
> -                                  symtab_to_filename_for_display (s),
> -                                  s->nlines);
> -             else if (lseek (desc.get (), s->line_charpos[line_no - 1], 0)
> -                      < 0)
> -               perror_with_name (symtab_to_filename_for_display (s));
> -             else
> +             int cur_line_no, cur_line;
> +             struct tui_gen_win_info *locator
> +               = tui_locator_win_info_ptr ();
> +             struct tui_source_info *src
> +               = &TUI_SRC_WIN->detail.source_info;
> +             const char *s_filename = symtab_to_filename_for_display (s);
> +
> +             if (TUI_SRC_WIN->generic.title)
> +               xfree (TUI_SRC_WIN->generic.title);
> +             TUI_SRC_WIN->generic.title = xstrdup (s_filename);
> +
> +             xfree (src->fullname);
> +             src->fullname = xstrdup (symtab_to_fullname (s));
> +
> +             cur_line = 0;
> +             src->gdbarch = get_objfile_arch (SYMTAB_OBJFILE (s));
> +             src->start_line_or_addr.loa = LOA_LINE;
> +             cur_line_no = src->start_line_or_addr.u.line_no = line_no;
> +
> +             const char *iter = srclines.c_str ();
> +             while (cur_line < nlines)
>                 {
> -                 int offset, cur_line_no, cur_line, cur_len, threshold;
> -                 struct tui_gen_win_info *locator
> -                   = tui_locator_win_info_ptr ();
> -                  struct tui_source_info *src
> -                   = &TUI_SRC_WIN->detail.source_info;
> -                 const char *s_filename = symtab_to_filename_for_display (s);
> -
> -                  if (TUI_SRC_WIN->generic.title)
> -                    xfree (TUI_SRC_WIN->generic.title);
> -                  TUI_SRC_WIN->generic.title = xstrdup (s_filename);
> -
> -                 xfree (src->fullname);
> -                 src->fullname = xstrdup (symtab_to_fullname (s));
> -
> -                 /* Determine the threshold for the length of the
> -                     line and the offset to start the display.  */
> -                 offset = src->horizontal_offset;
> -                 threshold = (line_width - 1) + offset;
> -                 gdb_file_up stream = desc.to_file (FOPEN_RT);
> -                 clearerr (stream.get ());
> -                 cur_line = 0;
> -                 src->gdbarch = get_objfile_arch (SYMTAB_OBJFILE (s));
> -                 src->start_line_or_addr.loa = LOA_LINE;
> -                 cur_line_no = src->start_line_or_addr.u.line_no = line_no;
> -                 if (offset > 0)
> -                   src_line = (char *) xmalloc (
> -                                          (threshold + 1) * sizeof (char));
> -                 while (cur_line < nlines)
> -                   {
> -                     struct tui_win_element *element
> -                       = TUI_SRC_WIN->generic.content[cur_line];
> -
> -                     /* Get the first character in the line.  */
> -                     c = fgetc (stream.get ());
> -
> -                     if (offset == 0)
> -                       src_line = TUI_SRC_WIN->generic.content[cur_line]
> -                                    ->which_element.source.line;
> -                     /* Init the line with the line number.  */
> -                     sprintf (src_line, "%-6d", cur_line_no);
> -                     cur_len = strlen (src_line);
> -                     i = cur_len - ((cur_len / tui_tab_width)
> -                                    * tui_tab_width);
> -                     while (i < tui_tab_width)
> -                       {
> -                         src_line[cur_len] = ' ';
> -                         i++;
> -                         cur_len++;
> -                       }
> -                     src_line[cur_len] = (char) 0;
> -
> -                     /* Set whether element is the execution point
> -                        and whether there is a break point on it.  */
> -                     element->which_element.source.line_or_addr.loa =
> -                       LOA_LINE;
> -                     element->which_element.source.line_or_addr.u.line_no =
> -                       cur_line_no;
> -                     element->which_element.source.is_exec_point =
> -                       (filename_cmp (locator->content[0]
> -                                        ->which_element.locator.full_name,
> -                                      symtab_to_fullname (s)) == 0
> -                                        && cur_line_no
> -                                             == locator->content[0]
> -                                                  ->which_element.locator.line_no);
> -                     if (c != EOF)
> -                       {
> -                         i = strlen (src_line) - 1;
> -                         do
> -                           {
> -                             if ((c != '\n') && (c != '\r')
> -                                 && (++i < threshold))
> -                               {
> -                                 if (c < 040 && c != '\t')
> -                                   {
> -                                     src_line[i++] = '^';
> -                                     src_line[i] = c + 0100;
> -                                   }
> -                                 else if (c == 0177)
> -                                   {
> -                                     src_line[i++] = '^';
> -                                     src_line[i] = '?';
> -                                   }
> -                                 else
> -                                   { /* Store the charcter in the
> -                                        line buffer.  If it is a tab,
> -                                        then translate to the correct
> -                                        number of chars so we don't
> -                                        overwrite our buffer.  */
> -                                     if (c == '\t')
> -                                       {
> -                                         int j, max_tab_len
> -                                           = tui_tab_width;
> -
> -                                         for (j = i - ((i / max_tab_len)
> -                                                       * max_tab_len);
> -                                              j < max_tab_len
> -                                                && i < threshold;
> -                                              i++, j++)
> -                                           src_line[i] = ' ';
> -                                         i--;
> -                                       }
> -                                     else
> -                                       src_line[i] = c;
> -                                   }
> -                                 src_line[i + 1] = 0;
> -                               }
> -                             else
> -                               { /* If we have not reached EOL, then
> -                                    eat chars until we do.  */
> -                                 while (c != EOF && c != '\n' && c != '\r')
> -                                   c = fgetc (stream.get ());
> -                                 /* Handle non-'\n' end-of-line.  */
> -                                 if (c == '\r'
> -                                     && (c = fgetc (stream.get ())) != '\n'
> -                                     && c != EOF)
> -                                   {
> -                                     ungetc (c, stream.get ());
> -                                     c = '\r';
> -                                   }
> -
> -                               }
> -                           }
> -                         while (c != EOF && c != '\n' && c != '\r'
> -                                && i < threshold
> -                                && (c = fgetc (stream.get ())));
> -                       }
> -                     /* Now copy the line taking the offset into
> -                        account.  */
> -                     if (offset == 0)
> -                       ;
> -                     else if (strlen (src_line) > offset)
> -                       strcpy (TUI_SRC_WIN->generic.content[cur_line]
> -                                 ->which_element.source.line,
> -                               &src_line[offset]);
> -                     else
> -                       TUI_SRC_WIN->generic.content[cur_line]
> -                         ->which_element.source.line[0] = (char) 0;
> -                     cur_line++;
> -                     cur_line_no++;
> -                   }
> -                 if (offset > 0)
> -                   xfree (src_line);
> -                 TUI_SRC_WIN->generic.content_size = nlines;
> -                 ret = TUI_SUCCESS;
> +                 struct tui_win_element *element
> +                   = TUI_SRC_WIN->generic.content[cur_line];
> +
> +                 std::string text;
> +                 if (*iter != '\0')
> +                   text = copy_source_line (&iter, cur_line_no,
> +                                            src->horizontal_offset,
> +                                            line_width);
> +
> +                 /* Set whether element is the execution point
> +                    and whether there is a break point on it.  */
> +                 element->which_element.source.line_or_addr.loa =
> +                   LOA_LINE;
> +                 element->which_element.source.line_or_addr.u.line_no =
> +                   cur_line_no;
> +                 element->which_element.source.is_exec_point =
> +                   (filename_cmp (locator->content[0]
> +                                  ->which_element.locator.full_name,
> +                                  symtab_to_fullname (s)) == 0
> +                    && cur_line_no
> +                    == locator->content[0]
> +                    ->which_element.locator.line_no);
> +
> +                 xfree (TUI_SRC_WIN->generic.content[cur_line]
> +                        ->which_element.source.line);
> +                 int alloc_len = text.size ();
> +                 if (alloc_len < line_width)
> +                   alloc_len = line_width + 1;
> +                 TUI_SRC_WIN->generic.content[cur_line]
> +                   ->which_element.source.line
> +                   = (char *) xmalloc (alloc_len);
> +                 strcpy (TUI_SRC_WIN->generic.content[cur_line]
> +                         ->which_element.source.line,
> +                         text.c_str ());
> +
> +                 cur_line++;
> +                 cur_line_no++;
>                 }
> +             TUI_SRC_WIN->generic.content_size = nlines;
> +             ret = TUI_SUCCESS;
>             }
>         }
>      }
> diff --git a/gdb/tui/tui-winsource.c b/gdb/tui/tui-winsource.c
> index 0bf74383b1..00b4b9e4fa 100644
> --- a/gdb/tui/tui-winsource.c
> +++ b/gdb/tui/tui-winsource.c
> @@ -31,6 +31,7 @@
>
>  #include "tui/tui.h"
>  #include "tui/tui-data.h"
> +#include "tui/tui-io.h"
>  #include "tui/tui-stack.h"
>  #include "tui/tui-win.h"
>  #include "tui/tui-wingeneral.h"
> @@ -277,8 +278,9 @@ tui_show_source_line (struct tui_win_info *win_info, int lineno)
>    if (line->which_element.source.is_exec_point)
>      wattron (win_info->generic.handle, A_STANDOUT);
>
> -  mvwaddstr (win_info->generic.handle, lineno, 1,
> -            line->which_element.source.line);
> +  wmove (win_info->generic.handle, lineno, 1);
> +  tui_puts (line->which_element.source.line,
> +           win_info->generic.handle);
>    if (line->which_element.source.is_exec_point)
>      wattroff (win_info->generic.handle, A_STANDOUT);
>
> @@ -595,7 +597,6 @@ tui_update_exec_info (struct tui_win_info *win_info)
>  enum tui_status
>  tui_alloc_source_buffer (struct tui_win_info *win_info)
>  {
> -  char *src_line_buf;
>    int i, line_width, max_lines;
>
>    /* The window width/height includes the highlight box.  Determine actual
> @@ -603,20 +604,14 @@ tui_alloc_source_buffer (struct tui_win_info *win_info)
>    max_lines = win_info->generic.height - 2;
>    line_width = win_info->generic.width - 2 + 1;
>
> -  /*
> -   * Allocate the buffer for the source lines.  Do this only once
> -   * since they will be re-used for all source displays.  The only
> -   * other time this will be done is when a window's size changes.
> -   */
> +  /* Allocate the buffer for the source lines.  */
>    if (win_info->generic.content == NULL)
>      {
> -      src_line_buf = (char *)
> -       xmalloc ((max_lines * line_width) * sizeof (char));
>        /* Allocate the content list.  */
>        win_info->generic.content = tui_alloc_content (max_lines, SRC_WIN);
>        for (i = 0; i < max_lines; i++)
>         win_info->generic.content[i]->which_element.source.line
> -         = src_line_buf + (line_width * i);
> +         = (char *) xmalloc (line_width);
>      }
>
>    return TUI_SUCCESS;
> diff --git a/gdb/utils.c b/gdb/utils.c
> index 85b0fb14e3..00f524c52e 100644
> --- a/gdb/utils.c
> +++ b/gdb/utils.c
> @@ -1444,9 +1444,9 @@ emit_style_escape (const ui_file_style &style)
>    wrap_buffer.append (style.to_ansi ());
>  }
>
> -/* Return true if ANSI escapes can be used on STREAM.  */
> +/* See utils.h.  */
>
> -static bool
> +bool
>  can_emit_style_escape (struct ui_file *stream)
>  {
>    if (stream != gdb_stdout
> diff --git a/gdb/utils.h b/gdb/utils.h
> index 1f09ec2d47..16ee9fbd33 100644
> --- a/gdb/utils.h
> +++ b/gdb/utils.h
> @@ -443,6 +443,10 @@ extern void fputs_styled (const char *linebuffer,
>
>  extern void reset_terminal_style (struct ui_file *stream);
>
> +/* Return true if ANSI escapes can be used on STREAM.  */
> +
> +extern bool can_emit_style_escape (struct ui_file *stream);
> +
>  /* Display the host ADDR on STREAM formatted as ``0x%x''.  */
>  extern void gdb_print_host_address_1 (const void *addr, struct ui_file *stream);
>
> --
> 2.17.2
>

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 15/16] Highlight source code using GNU Source Highlight
  2019-11-16  0:58   ` Andrew Pinski
@ 2019-11-16  8:19     ` Eli Zaretskii
  2019-11-24 17:41     ` Tom Tromey
  1 sibling, 0 replies; 99+ messages in thread
From: Eli Zaretskii @ 2019-11-16  8:19 UTC (permalink / raw)
  To: Andrew Pinski; +Cc: tom, gdb-patches

> From: Andrew Pinski <pinskia@gmail.com>
> Date: Fri, 15 Nov 2019 16:57:49 -0800
> Cc: GDB Patches <gdb-patches@sourceware.org>
> 
> If it cannot be compiled at a top-level, does it support as a static
> library?

Not sure I understand what you are asking about.  If you ask whether
GDB can be linked statically with Source Highlight, then the answer is
YES.  In fact, this is how I build my GDB, because the shared library
version of Source Highlight includes (on MS-Windows) dependencies on
libstdc++ and libgcc DLLs, which makes it impossible for me to
redistribute the GDB binaries without also providing the humongous GCC
source tarballs.

Apologies if this is not the question you were asking.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 15/16] Highlight source code using GNU Source Highlight
  2019-11-16  0:58   ` Andrew Pinski
  2019-11-16  8:19     ` Eli Zaretskii
@ 2019-11-24 17:41     ` Tom Tromey
  2019-11-24 18:13       ` Christian Biesinger via gdb-patches
  1 sibling, 1 reply; 99+ messages in thread
From: Tom Tromey @ 2019-11-24 17:41 UTC (permalink / raw)
  To: Andrew Pinski; +Cc: Tom Tromey, GDB Patches

Andrew> I know this patch has been in for almost a year now.  But I have a
Andrew> question, is there a way to build GNU Source Highlight as a static
Andrew> library and have it built at the top level?  Like what is done for
Andrew> GMP/MPFR for GCC?  It would reduce how I built a gdb that is for a
Andrew> non-native target.

There's currently no support for dropping the sources into the tree.
However, I think it would be fine if you wanted to add such support.

Andrew> If it cannot be compiled at a top-level, does it support as a static
Andrew> library?

Eli answered this in the affirmative; I have never tried it myself.

I've considered also adding support for Pygments, in addition to Source
Highlight.  In some situations that might be simpler to distribute; and
also it would mean that one could just install Pygments and have it
suddenly start working.

Tom

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 15/16] Highlight source code using GNU Source Highlight
  2019-11-24 17:41     ` Tom Tromey
@ 2019-11-24 18:13       ` Christian Biesinger via gdb-patches
  2019-11-24 19:53         ` Tom Tromey
  0 siblings, 1 reply; 99+ messages in thread
From: Christian Biesinger via gdb-patches @ 2019-11-24 18:13 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Andrew Pinski, GDB Patches

On Sun, Nov 24, 2019 at 11:41 AM Tom Tromey <tom@tromey.com> wrote:
>
> Andrew> I know this patch has been in for almost a year now.  But I have a
> Andrew> question, is there a way to build GNU Source Highlight as a static
> Andrew> library and have it built at the top level?  Like what is done for
> Andrew> GMP/MPFR for GCC?  It would reduce how I built a gdb that is for a
> Andrew> non-native target.
>
> There's currently no support for dropping the sources into the tree.
> However, I think it would be fine if you wanted to add such support.

Note that the source highlight library depends on boost_regex and ICU,
according to ldd, so that might make this harder?

(I wonder why it doesn't use std::regex)

Christian

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 15/16] Highlight source code using GNU Source Highlight
  2019-11-24 18:13       ` Christian Biesinger via gdb-patches
@ 2019-11-24 19:53         ` Tom Tromey
  0 siblings, 0 replies; 99+ messages in thread
From: Tom Tromey @ 2019-11-24 19:53 UTC (permalink / raw)
  To: Christian Biesinger; +Cc: Tom Tromey, Andrew Pinski, GDB Patches

Christian> Note that the source highlight library depends on boost_regex and ICU,
Christian> according to ldd, so that might make this harder?

Yeah.  I forgot about that.

Christian> (I wonder why it doesn't use std::regex)

There's a bug open in the source highlight tracker about this (I can't
link right now since savannah seems to be down).  Basically, I think
std::regex wasn't available (maybe not implemented in libstdc++?) when
it was written.  Anyway, removing the boost dependency would be good.

Tom

^ permalink raw reply	[flat|nested] 99+ messages in thread

end of thread, other threads:[~2019-11-24 19:53 UTC | newest]

Thread overview: 99+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-28  0:16 [PATCH 00/16] Add styling to the gdb CLI and TUI Tom Tromey
2018-11-28  0:14 ` [PATCH 06/16] Reset terminal styles Tom Tromey
2018-12-24  4:16   ` Joel Brobecker
2018-12-28 19:01     ` Tom Tromey
2018-11-28  0:14 ` [PATCH 10/16] Style the gdb welcome message Tom Tromey
2018-11-28  0:14 ` [PATCH 03/16] Introduce ui_file_style Tom Tromey
2018-12-24  3:40   ` Joel Brobecker
2018-12-28 18:54     ` Tom Tromey
2018-11-28  0:14 ` [PATCH 14/16] Use wclrtoeol in tui_show_source_line Tom Tromey
2018-12-24  8:03   ` Joel Brobecker
2018-11-28  0:14 ` [PATCH 09/16] Style print_address_symbolic Tom Tromey
2018-11-28  0:14 ` [PATCH 02/16] Add a "context" argument to add_setshow_enum_cmd Tom Tromey
2018-11-28  0:14 ` [PATCH 05/16] Add output styles to gdb Tom Tromey
2018-12-24  4:08   ` Joel Brobecker
2018-12-28 18:55     ` Tom Tromey
2018-11-28  0:14 ` [PATCH 12/16] Style addresses Tom Tromey
2018-11-28  0:16 ` [PATCH 08/16] Style locations when setting a breakpoint Tom Tromey
2018-11-28  0:16 ` [PATCH 04/16] Change gdb test suite's TERM setting Tom Tromey
2018-11-28  0:16 ` [PATCH 07/16] Style variable names Tom Tromey
2018-11-28  0:16 ` [PATCH 15/16] Highlight source code using GNU Source Highlight Tom Tromey
2019-11-16  0:58   ` Andrew Pinski
2019-11-16  8:19     ` Eli Zaretskii
2019-11-24 17:41     ` Tom Tromey
2019-11-24 18:13       ` Christian Biesinger via gdb-patches
2019-11-24 19:53         ` Tom Tromey
2018-11-28  0:16 ` [PATCH 13/16] Make ANSI terminal escape sequences work in TUI Tom Tromey
2018-12-24  8:02   ` Joel Brobecker
2018-12-28 19:42   ` Tom Tromey
2018-11-28  0:16 ` [PATCH 16/16] Document the "set style" commands Tom Tromey
2018-11-28  6:51   ` Eli Zaretskii
2018-12-28 19:19     ` Tom Tromey
2018-11-28  0:16 ` [PATCH 11/16] Style the "Reading symbols" message Tom Tromey
2018-11-28  0:19 ` [PATCH 01/16] Change wrap buffering to use a std::string Tom Tromey
2018-12-23 15:26   ` Joel Brobecker
2018-12-28 18:47     ` Tom Tromey
2018-11-28  7:02 ` [PATCH 00/16] Add styling to the gdb CLI and TUI Eli Zaretskii
2018-11-29 22:44   ` Tom Tromey
2018-11-30  7:02     ` Eli Zaretskii
2018-11-30 16:17       ` Tom Tromey
2018-12-23 10:49         ` Joel Brobecker
2019-03-01 13:10         ` Pedro Alves
2019-03-01 13:56           ` Eli Zaretskii
2019-03-01 14:10             ` Pedro Alves
2019-03-01 14:50               ` Eli Zaretskii
2019-03-01  7:47     ` Eli Zaretskii
2019-03-01 18:42       ` Tom Tromey
2019-03-01 19:40         ` Eli Zaretskii
2019-03-01 21:04           ` Tom Tromey
2019-03-02  7:15             ` Eli Zaretskii
2019-03-03 15:42             ` Eli Zaretskii
2019-03-04 15:08               ` Tom Tromey
2019-03-04 15:57                 ` Eli Zaretskii
2019-03-04 16:16                   ` Tom Tromey
2019-03-05 15:38                     ` Eli Zaretskii
2019-03-08 14:55                       ` Eli Zaretskii
2019-03-08 16:14                         ` Hannes Domani via gdb-patches
2019-03-08 21:08                           ` Tom Tromey
2019-03-08 21:11                         ` Tom Tromey
2019-03-09  6:49                           ` Eli Zaretskii
2019-03-03 15:53             ` Eli Zaretskii
2019-03-03 16:16               ` Matt Rice
2019-03-03 17:13                 ` Eli Zaretskii
2019-03-03 18:04                   ` Matt Rice
2019-03-04 15:01               ` Tom Tromey
2019-03-04 17:37                 ` Eli Zaretskii
2019-03-04 17:40                   ` Tom Tromey
2019-03-06 16:02                     ` Eli Zaretskii
2019-03-20 19:35                       ` GDB version as convenience variable Eli Zaretskii
2019-03-25 17:31                         ` Eli Zaretskii
2019-03-25 17:58                           ` Simon Marchi
2019-03-25 18:10                             ` Eli Zaretskii
2019-03-25 18:33                               ` Simon Marchi
2019-03-25 18:37                                 ` Simon Marchi
2019-03-25 18:43                                 ` Eli Zaretskii
2019-03-25 18:51                                   ` Simon Marchi
2019-03-25 19:19                                     ` Eli Zaretskii
2019-03-26 14:47                                       ` Simon Marchi
2019-03-26 20:57                                         ` Joel Brobecker
2019-03-27  3:34                                           ` Eli Zaretskii
2019-03-27 12:56                                             ` Joel Brobecker
2019-03-30 17:25                                               ` Simon Marchi
2019-03-30 10:01                                         ` Eli Zaretskii
2019-03-21  1:55                       ` [PATCH 00/16] Add styling to the gdb CLI and TUI Simon Marchi
2019-03-21 14:38                         ` Eli Zaretskii
2019-03-21 15:02                           ` Simon Marchi
2019-03-21 16:01                             ` Eli Zaretskii
2019-03-21 16:06                               ` Simon Marchi
2019-03-21 16:12                                 ` Pedro Alves
2019-03-21 16:54                                   ` John Baldwin
2019-03-21 17:02                                   ` Eli Zaretskii
2019-03-21 18:08                                     ` Simon Marchi
2019-03-21 18:19                                       ` Pedro Alves
2019-03-21 18:38                                         ` Eli Zaretskii
2019-03-07  6:02                   ` Joel Brobecker
2019-03-07 14:53                     ` Eli Zaretskii
2019-03-08  5:40                       ` Joel Brobecker
2019-03-04 16:04       ` Eli Zaretskii
2018-12-24  9:27 ` Joel Brobecker
2018-12-28 20:57   ` Tom Tromey

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).