On Thu, 2015-10-29 at 22:49 -0600, Jeff Law wrote:
> On 10/28/2015 12:09 PM, David Malcolm wrote:
> > gcc/ChangeLog:
> >     * diagnostic-show-locus.c (struct point_state): New struct.
> >     (class colorizer): New class.
> >     (class layout_point): New class.
> >     (class layout_range): New class.
> >     (class layout): New class.
> >     (colorizer::colorizer): New ctor.
> >     (colorizer::~colorizer): New dtor.
> >     (layout::layout): New ctor.
> >     (layout::print_line): New method.
> >     (layout::get_state_at_point): New method.
> >     (layout::get_x_bound_for_row): New method.
> >     (show_ruler): New function.
> >     (diagnostic_show_locus): Reimplement in terms of class layout.
> > ---
> > +};
> > +
> > +/* A class to inject colorization codes when printing the diagnostic locus.
> > +
> > +   It has one kind of colorization for each of:
> > +     - normal text
> > +     - range 0 (the "primary location")
> > +     - range 1
> > +     - range 2
> > +
> > +   The class caches the lookup of the color codes for the above.
> > +
> > +   The class also has responsibility for tracking which of the above is
> > +   active, filtering out unnecessary changes.  This allows 
> > layout::print_line
> > +   to simply request a colorization code for *every* character it prints
> > +   through this class, and have the filtering be done for it here.  */
> Not asking you to do anything here -- hopefully this isn't a huge burden 
> on the diagnostic performance.  Normally I wouldn't even notice except 
> that we're inserting colorization on every character.  That kind of 
> model can get expensive.  Something to watch out for -- though I doubt 
> we do he massive diagnostic spews we used to which is probably the only 
> place it'd be noticeable.
> 
> 
> 
> > +
> > +/* A point within a layout_range; similar to an expanded_location,
> > +   but after filtering on file.  */
> > +
> > +class layout_point
> > +{
> > + public:
> > +  layout_point (const expanded_location &exploc)
> > +  : m_line (exploc.line),
> > +    m_column (exploc.column) {}
> > +
> > +  int m_line;
> > +  int m_column;
> > +};
> Is this even deserving of its own class?  If you pulled up 
> m_line/m_column you don't need the class, though I guess you need thee 
> of each, one for the start, one for the finish & one for the caret, 
> which in turn bloats the layout_range's constructor.  So I guess this is OK.
> 
> 
> 
> 
> 
> 
> > +/* Given a source line LINE of length LINE_WIDTH, determine the width
> > +   without any trailing whitespace.  */
> > +
> > +static int
> > +get_line_width_without_trailing_whitespace (const char *line, int 
> > line_width)
> > +{
> > +  int result = line_width;
> > +  while (result > 0)
> > +    {
> > +      char ch = line[result - 1];
> > +      if (ch == ' ' || ch == '\t')
> > +   result--;
> > +      else
> > +   break;
> > +    }
> > +  gcc_assert (result >= 0);
> > +  gcc_assert (result <= line_width);
> > +  gcc_assert (result == 0 ||
> > +         (line[result - 1] != ' '
> > +          && line[result -1] != '\t'));
> > +  return result;
> > +}
> If you use an unsigned for the line width, don't all the asserts become 
> redundant & unnecessary?  I love the sanity checking and I could see how 
> it might be useful it someone were to reimplmenent this function at a 
> later date.  So maybe keep.
> 
> > +
> > +/* Implementation of class layout.  */
> > +
> > +/* Constructor for class layout.
> > +
> > +   Filter the ranges from the rich_location to those that we can
> > +   sanely print, populating m_layout_ranges.
> > +   Determine the range of lines that we will print.
> > +   Determine m_x_offset, to ensure that the primary caret
> > +   will fit within the max_width provided by the diagnostic_context.  */
> > +
> > +layout::layout (diagnostic_context * context,
> > +           const diagnostic_info *diagnostic)
> [ ... ]
> > +  if (0)
> > +    show_ruler (context, line_width, m_x_offset);
> Debugging code?  If it's if (0) you should probably delete it at this point.
> 
> 
> > +}
> > +
> > +/* Print text describing a line of source code.
> > +   This typically prints two lines:
> > +
> > +   (1) the source code itself, potentially colorized at any ranges, and
> > +   (2) an annotation line containing any carets/underlines
> > +   describing the ranges.  */
> > +
> > +void
> > +layout::print_line (int row)
> Consider breaking this into two functions.  One to print the source line 
> and another to print caret/underlines.
> 
> 
>   +
> > +/* Return true if (ROW/COLUMN) is within a range of the layout.
> > +   If it returns true, OUT_STATE is written to, with the
> > +   range index, and whether we should draw the caret at
> > +   (ROW/COLUMN) (as opposed to an underline).  */
> > +
> > +bool
> > +layout::get_state_at_point (/* Inputs.  */
> > +                       int row, int column,
> > +                       int first_non_ws, int last_non_ws,
> > +                       /* Outputs.  */
> > +                       point_state *out_state)
> > +{
> > +  layout_range *range;
> > +  int i;
> > +  FOR_EACH_VEC_ELT (m_layout_ranges, i, range)
> > +    {
> > +      if (0)
> > +   fprintf (stderr,
> > +            "range ( (%i, %i), (%i, %i))->contains_point (%i, %i): %s\n",
> > +            range->m_start.m_line,
> > +            range->m_start.m_column,
> > +            range->m_finish.m_line,
> > +            range->m_finish.m_column,
> > +            row,
> > +            column,
> > +            range->contains_point (row, column) ? "true" : "false");
> More old debugging code that needs to be removed?
> 
> 
> 
> > +
> > +/* For debugging layout issues in diagnostic_show_locus and friends,
> > +   render a ruler giving column numbers (after the 1-column indent).  */
> > +
> > +static void
> > +show_ruler (diagnostic_context *context, int max_width, int x_offset)
> Seems like it ought to be DEBUG_FUNCTION or removed.  I believe it's 
> only caller is in if (0) code in layout's ctor.
> 
> 
> Overall this looks good.  Take the actions you deem appropriate WRT the 
> debugging bits, breaking print_line into two functions and the signed vs 
> unsigned stuff in get_line_width_without_trailing_whitespace and it's 
> good for the trunk.

Thanks.  I broke print_line into two methods, and eliminated the
debugging bits; I didn't touch the signedness within 
get_line_width_without_trailing_whitespace (since this signedness is
coming from input.c, as noted before).

I've committed the combination of 4a+4b+4c+cleanups to trunk as r229884
(having bootstrapped&regrtested).

For reference, I'm attaching the diffs (relative to 4b) for the cleanups
mentioned above.

Dave
>From 221d5daa7c88d1776a8ea1dc7bd5b4b1bb460ce5 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalc...@redhat.com>
Date: Sat, 31 Oct 2015 04:38:15 -0400
Subject: [PATCH] Split layout::print_line into two methods.

gcc/ChangeLog:
	* diagnostic-show-locus.c (class colorizer): Update comment to
	reflect split of layout::print_line into layout::print_source_line
	and layout::print_annotation_line.
	(struct line_bounds): New.
	(class layout): Update comment to reflect split of
	layout::print_line.
	(layout::print_line): Delete, in favor of...
	(layout::print_source_line): ...this new method and...
	(layout::print_annotation_line): ...this new method.
	(diagnostic_show_locus): Update for split of layout::print_line
	into layout::print_source_line and layout::print_annotation_line.
---
 gcc/diagnostic-show-locus.c | 78 ++++++++++++++++++++++++++++++---------------
 1 file changed, 52 insertions(+), 26 deletions(-)

diff --git a/gcc/diagnostic-show-locus.c b/gcc/diagnostic-show-locus.c
index 6865209..97f2853 100644
--- a/gcc/diagnostic-show-locus.c
+++ b/gcc/diagnostic-show-locus.c
@@ -67,9 +67,10 @@ struct point_state
    The class caches the lookup of the color codes for the above.
 
    The class also has responsibility for tracking which of the above is
-   active, filtering out unnecessary changes.  This allows layout::print_line
-   to simply request a colorization code for *every* character it prints
-   through this class, and have the filtering be done for it here.  */
+   active, filtering out unnecessary changes.  This allows
+   layout::print_source_line and layout::print_annotation_line
+   to simply request a colorization code for *every* character they print,
+   via this class, and have the filtering be done for them here.  */
 
 class colorizer
 {
@@ -128,12 +129,21 @@ class layout_range
   layout_point m_caret;
 };
 
+/* A struct for use by layout::print_source_line for telling
+   layout::print_annotation_line the extents of the source line that
+   it printed, so that underlines can be clipped appropriately.  */
+
+struct line_bounds
+{
+  int m_first_non_ws;
+  int m_last_non_ws;
+};
+
 /* A class to control the overall layout when printing a diagnostic.
 
    The layout is determined within the constructor.
-   It is then printed by repeatedly calling the "print_line" method.
-   Each such call can print two lines: one for the source line itself,
-   and potentially an "annotation" line, containing carets/underlines.
+   It is then printed by repeatedly calling the "print_source_line"
+   and "print_annotation_line" methods.
 
    We assume we have disjoint ranges.  */
 
@@ -146,7 +156,8 @@ class layout
   int get_first_line () const { return m_first_line; }
   int get_last_line () const { return m_last_line; }
 
-  void print_line (int row);
+  bool print_source_line (int row, line_bounds *lbounds_out);
+  void print_annotation_line (int row, const line_bounds lbounds);
 
  private:
   bool
@@ -477,32 +488,30 @@ layout::layout (diagnostic_context * context,
     show_ruler (context, line_width, m_x_offset);
 }
 
-/* Print text describing a line of source code.
-   This typically prints two lines:
+/* Attempt to print line ROW of source code, potentially colorized at any
+   ranges.
+   Return true if the line was printed, populating *LBOUNDS_OUT.
+   Return false if the source line could not be read, leaving *LBOUNDS_OUT
+   untouched.  */
 
-   (1) the source code itself, potentially colorized at any ranges, and
-   (2) an annotation line containing any carets/underlines
-   describing the ranges.  */
-
-void
-layout::print_line (int row)
+bool
+layout::print_source_line (int row, line_bounds *lbounds_out)
 {
   int line_width;
   const char *line = location_get_source_line (m_exploc.file, row,
 					       &line_width);
   if (!line)
-    return;
+    return false;
 
   line += m_x_offset;
 
   m_colorizer.set_normal_text ();
 
-  /* Step 1: print the source code line.  */
+  /* We will stop printing the source line at any trailing
+     whitespace.  */
+  line_width = get_line_width_without_trailing_whitespace (line,
+							   line_width);
 
-  /* We will stop printing at any trailing whitespace.  */
-  line_width
-    = get_line_width_without_trailing_whitespace (line,
-						  line_width);
   pp_space (m_pp);
   int first_non_ws = INT_MAX;
   int last_non_ws = 0;
@@ -547,10 +556,19 @@ layout::print_line (int row)
     }
   pp_newline (m_pp);
 
-  /* Step 2: print a line consisting of the caret/underlines for the
-     given source line.  */
+  lbounds_out->m_first_non_ws = first_non_ws;
+  lbounds_out->m_last_non_ws = last_non_ws;
+  return true;
+}
+
+/* Print a line consisting of the caret/underlines for the given
+   source line.  */
+
+void
+layout::print_annotation_line (int row, const line_bounds lbounds)
+{
   int x_bound = get_x_bound_for_row (row, m_exploc.column,
-				     last_non_ws);
+				     lbounds.m_last_non_ws);
 
   pp_space (m_pp);
   for (int column = 1 + m_x_offset; column < x_bound; column++)
@@ -558,7 +576,8 @@ layout::print_line (int row)
       bool in_range_p;
       point_state state;
       in_range_p = get_state_at_point (row, column,
-				       first_non_ws, last_non_ws,
+				       lbounds.m_first_non_ws,
+				       lbounds.m_last_non_ws,
 				       &state);
       if (in_range_p)
 	{
@@ -734,7 +753,14 @@ diagnostic_show_locus (diagnostic_context * context,
     for (int row = layout.get_first_line ();
 	 row <= last_line;
 	 row++)
-      layout.print_line (row);
+      {
+	/* Print the source line, followed by an annotation line
+	   consisting of any caret/underlines.  If the source line can't
+	   be read, print nothing.  */
+	line_bounds lbounds;
+	if (layout.print_source_line (row, &lbounds))
+	  layout.print_annotation_line (row, lbounds);
+      }
 
     /* The closing scope here leads to the dtor for layout and thus
        colorizer being called here, which affects the precise
-- 
1.8.5.3

>From 4b1113880023d404ebb52d7efab934b913ff3284 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalc...@redhat.com>
Date: Mon, 2 Nov 2015 15:35:34 -0500
Subject: [PATCH] Fix nits in diagnostic-show-locus.c

gcc/ChangeLog:
	* diagnostic-show-locus.c (layout::layout): Eliminate call to
	show_ruler.
	(layout::get_state_at_point): Eliminate debug code.
	(show_ruler): Delete.
---
 gcc/diagnostic-show-locus.c | 51 ---------------------------------------------
 1 file changed, 51 deletions(-)

diff --git a/gcc/diagnostic-show-locus.c b/gcc/diagnostic-show-locus.c
index 97f2853..22203cd 100644
--- a/gcc/diagnostic-show-locus.c
+++ b/gcc/diagnostic-show-locus.c
@@ -36,9 +36,6 @@ along with GCC; see the file COPYING3.  If not see
 # include <sys/ioctl.h>
 #endif
 
-static void
-show_ruler (diagnostic_context *context, int max_width, int x_offset);
-
 /* Classes for rendering source code and diagnostics, within an
    anonymous namespace.
    The work is done by "class layout", which embeds and uses
@@ -483,9 +480,6 @@ layout::layout (diagnostic_context * context,
 	m_x_offset = column - right_margin;
       gcc_assert (m_x_offset >= 0);
     }
-
-  if (0)
-    show_ruler (context, line_width, m_x_offset);
 }
 
 /* Attempt to print line ROW of source code, potentially colorized at any
@@ -615,17 +609,6 @@ layout::get_state_at_point (/* Inputs.  */
   int i;
   FOR_EACH_VEC_ELT (m_layout_ranges, i, range)
     {
-      if (0)
-	fprintf (stderr,
-		 "range ( (%i, %i), (%i, %i))->contains_point (%i, %i): %s\n",
-		 range->m_start.m_line,
-		 range->m_start.m_column,
-		 range->m_finish.m_line,
-		 range->m_finish.m_column,
-		 row,
-		 column,
-		 range->contains_point (row, column) ? "true" : "false");
-
       if (range->contains_point (row, column))
 	{
 	  out_state->range_idx = i;
@@ -694,40 +677,6 @@ layout::get_x_bound_for_row (int row, int caret_column,
 
 } /* End of anonymous namespace.  */
 
-/* For debugging layout issues in diagnostic_show_locus and friends,
-   render a ruler giving column numbers (after the 1-column indent).  */
-
-static void
-show_ruler (diagnostic_context *context, int max_width, int x_offset)
-{
-  /* Hundreds.  */
-  if (max_width > 99)
-    {
-      pp_space (context->printer);
-      for (int column = 1 + x_offset; column < max_width; column++)
-	if (0 == column % 10)
-	  pp_character (context->printer, '0' + (column / 100) % 10);
-	else
-	  pp_space (context->printer);
-      pp_newline (context->printer);
-    }
-
-  /* Tens.  */
-  pp_space (context->printer);
-  for (int column = 1 + x_offset; column < max_width; column++)
-    if (0 == column % 10)
-      pp_character (context->printer, '0' + (column / 10) % 10);
-    else
-      pp_space (context->printer);
-  pp_newline (context->printer);
-
-  /* Units.  */
-  pp_space (context->printer);
-  for (int column = 1 + x_offset; column < max_width; column++)
-    pp_character (context->printer, '0' + (column % 10));
-  pp_newline (context->printer);
-}
-
 /* Print the physical source code corresponding to the location of
    this diagnostic, with additional annotations.  */
 
-- 
1.8.5.3

Reply via email to