pretty-print: support URL escape sequences (PR 87488)
authorDavid Malcolm <dmalcolm@redhat.com>
Thu, 10 Oct 2019 16:57:30 +0000 (16:57 +0000)
committerDavid Malcolm <dmalcolm@gcc.gnu.org>
Thu, 10 Oct 2019 16:57:30 +0000 (16:57 +0000)
https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda
describes an emerging standard for embedding URLs in escape sequences
for marking up text output.  This is supported e.g. by recent releases
of GNOME Terminal.

This patch adds support to our pretty-printing framework for emitting
URLs.

A followup patch uses this to add URLs to the pertinent documentation
for the output of -fdiagnostics-show-option.

gcc/ChangeLog:
PR 87488
* common.opt (fdiagnostics-urls=): New option.
(diagnostic-url.h): Add SourceInclude.
(diagnostic_url_rule): New enum.
* diagnostic-color.c: Include "diagnostic-url.h".
(diagnostic_urls_enabled_p): New function.
* diagnostic-url.h: New file.
* diagnostic.c: Include "diagnostic-url.h".
(diagnostic_urls_init): New function.
* diagnostic.h (diagnostic_urls_init): New decl.
* doc/invoke.texi (Diagnostic Message Formatting Options): Add
-fdiagnostics-urls to the list.
(-fdiagnostics-urls): New option.
* gcc.c (driver_handle_option): Handle OPT_fdiagnostics_urls_.
(driver::global_initializations): Call diagnostic_urls_init.
* opts-global.c (init_options_once): Likewise.
* opts.c (common_handle_option): Handle OPT_fdiagnostics_urls_.
* pretty-print.c (pretty_printer::pretty_printer): Initialize
show_urls.
(pp_begin_url): New function.
(pp_end_url): New function.
(selftest::test_urls): New selftest.
(selftest::pretty_print_c_tests): Call it.
* pretty-print.h (pretty_printer::show_urls): New field.
(pp_begin_url): New decl.
(pp_end_url): New decl.

gcc/testsuite/ChangeLog:
PR 87488
* lib/prune.exp (TEST_ALWAYS_FLAGS): Add -fdiagnostics-urls=never.

From-SVN: r276841

14 files changed:
gcc/ChangeLog
gcc/common.opt
gcc/diagnostic-color.c
gcc/diagnostic-url.h [new file with mode: 0644]
gcc/diagnostic.c
gcc/diagnostic.h
gcc/doc/invoke.texi
gcc/gcc.c
gcc/opts-global.c
gcc/opts.c
gcc/pretty-print.c
gcc/pretty-print.h
gcc/testsuite/ChangeLog
gcc/testsuite/lib/prune.exp

index ce7b389304f7c0e0e4ad1de7dcc76f6a0a689ec2..e3c1a4f0717c149ee2008eba686e254c8138745e 100644 (file)
@@ -1,3 +1,32 @@
+2019-10-10  David Malcolm  <dmalcolm@redhat.com>
+
+       PR 87488
+       * common.opt (fdiagnostics-urls=): New option.
+       (diagnostic-url.h): Add SourceInclude.
+       (diagnostic_url_rule): New enum.
+       * diagnostic-color.c: Include "diagnostic-url.h".
+       (diagnostic_urls_enabled_p): New function.
+       * diagnostic-url.h: New file.
+       * diagnostic.c: Include "diagnostic-url.h".
+       (diagnostic_urls_init): New function.
+       * diagnostic.h (diagnostic_urls_init): New decl.
+       * doc/invoke.texi (Diagnostic Message Formatting Options): Add
+       -fdiagnostics-urls to the list.
+       (-fdiagnostics-urls): New option.
+       * gcc.c (driver_handle_option): Handle OPT_fdiagnostics_urls_.
+       (driver::global_initializations): Call diagnostic_urls_init.
+       * opts-global.c (init_options_once): Likewise.
+       * opts.c (common_handle_option): Handle OPT_fdiagnostics_urls_.
+       * pretty-print.c (pretty_printer::pretty_printer): Initialize
+       show_urls.
+       (pp_begin_url): New function.
+       (pp_end_url): New function.
+       (selftest::test_urls): New selftest.
+       (selftest::pretty_print_c_tests): Call it.
+       * pretty-print.h (pretty_printer::show_urls): New field.
+       (pp_begin_url): New decl.
+       (pp_end_url): New decl.
+
 2019-10-10  Uroš Bizjak  <ubizjak@gmail.com>
 
        PR target/92022
index 1b9e0f3c8025a3b439f766edcd81db462973037b..124e8cf3ebe8aec4379bb980a0de6d4ed4969da6 100644 (file)
@@ -1281,6 +1281,26 @@ Enum(diagnostic_color_rule) String(always) Value(DIAGNOSTICS_COLOR_YES)
 EnumValue
 Enum(diagnostic_color_rule) String(auto) Value(DIAGNOSTICS_COLOR_AUTO)
 
+fdiagnostics-urls=
+Driver Common Joined RejectNegative Var(flag_diagnostics_show_urls) Enum(diagnostic_url_rule) Init(DIAGNOSTICS_URL_AUTO)
+-fdiagnostics-urls=[never|always|auto] Embed URLs in diagnostics.
+
+; Required for these enum values.
+SourceInclude
+diagnostic-url.h
+
+Enum
+Name(diagnostic_url_rule) Type(int)
+
+EnumValue
+Enum(diagnostic_url_rule) String(never) Value(DIAGNOSTICS_URL_NO)
+
+EnumValue
+Enum(diagnostic_url_rule) String(always) Value(DIAGNOSTICS_URL_YES)
+
+EnumValue
+Enum(diagnostic_url_rule) String(auto) Value(DIAGNOSTICS_URL_AUTO)
+
 fdiagnostics-format=
 Common Joined RejectNegative Enum(diagnostics_output_format)
 -fdiagnostics-format=[text|json] Select output format.
index 69e759ff6e84daa51b3a54f6ed5152f7722cb570..abc919f6383f098689a5e96763e9dac5a4bfc507 100644 (file)
@@ -19,6 +19,7 @@
 #include "config.h"
 #include "system.h"
 #include "diagnostic-color.h"
+#include "diagnostic-url.h"
 
 #ifdef __MINGW32__
 #  include <windows.h>
@@ -236,3 +237,22 @@ colorize_init (diagnostic_color_rule_t rule)
       gcc_unreachable ();
     }
 }
+
+/* Determine if URLs should be enabled, based on RULE.
+   This reuses the logic for colorization.  */
+
+bool
+diagnostic_urls_enabled_p (diagnostic_url_rule_t rule)
+{
+  switch (rule)
+    {
+    case DIAGNOSTICS_URL_NO:
+      return false;
+    case DIAGNOSTICS_URL_YES:
+      return true;
+    case DIAGNOSTICS_URL_AUTO:
+      return should_colorize ();
+    default:
+      gcc_unreachable ();
+    }
+}
diff --git a/gcc/diagnostic-url.h b/gcc/diagnostic-url.h
new file mode 100644 (file)
index 0000000..ce0de45
--- /dev/null
@@ -0,0 +1,36 @@
+/* Copyright (C) 2019 Free Software Foundation, Inc.
+   Contributed by David Malcolm <dmalcolm@redhat.com>.
+
+This file is part of GCC.
+
+GCC 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, or (at your option) any later
+version.
+
+GCC 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 GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_DIAGNOSTIC_URL_H
+#define GCC_DIAGNOSTIC_URL_H
+
+/* Whether to add URLs to diagnostics:
+   - DIAGNOSTICS_URL_NO: never
+   - DIAGNOSTICS_URL_YES: always
+   - DIAGNOSTICS_URL_AUTO: depending on the output stream.  */
+typedef enum
+{
+  DIAGNOSTICS_URL_NO       = 0,
+  DIAGNOSTICS_URL_YES      = 1,
+  DIAGNOSTICS_URL_AUTO     = 2
+} diagnostic_url_rule_t;
+
+extern bool diagnostic_urls_enabled_p (diagnostic_url_rule_t);
+
+#endif /* ! GCC_DIAGNOSTIC_URL_H */
index 1b3306cd73e6dbd7e053934926dfde6ddb168bfe..467cc3963e60e6fa40805972014e3a57b4dfa5bf 100644 (file)
@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "backtrace.h"
 #include "diagnostic.h"
 #include "diagnostic-color.h"
+#include "diagnostic-url.h"
 #include "edit-context.h"
 #include "selftest.h"
 #include "selftest-diagnostic.h"
@@ -246,6 +247,18 @@ diagnostic_color_init (diagnostic_context *context, int value /*= -1 */)
     = colorize_init ((diagnostic_color_rule_t) value);
 }
 
+/* Initialize URL support within CONTEXT based on VALUE, handling "auto".  */
+
+void
+diagnostic_urls_init (diagnostic_context *context, int value /*= -1 */)
+{
+  if (value < 0)
+    value = DIAGNOSTICS_COLOR_DEFAULT;
+
+  context->printer->show_urls
+    = diagnostic_urls_enabled_p ((diagnostic_url_rule_t) value);
+}
+
 /* Do any cleaning up required after the last diagnostic is emitted.  */
 
 void
index 530acb45b386e880990d60c843d98ae42b3ca148..f0ea8e8bd4cc86f4eb9f96d3e1565dc16c93d0e0 100644 (file)
@@ -331,6 +331,7 @@ diagnostic_override_option_index (diagnostic_info *info, int optidx)
 /* Diagnostic related functions.  */
 extern void diagnostic_initialize (diagnostic_context *, int);
 extern void diagnostic_color_init (diagnostic_context *, int value = -1);
+extern void diagnostic_urls_init (diagnostic_context *, int value = -1);
 extern void diagnostic_finish (diagnostic_context *);
 extern void diagnostic_report_current_module (diagnostic_context *, location_t);
 extern void diagnostic_show_locus (diagnostic_context *,
index 92476031a3fa4b112ce3a23b247bd1f3eeb00356..bdbcd95d55979771f2d514c67896d955e843172e 100644 (file)
@@ -273,6 +273,7 @@ Objective-C and Objective-C++ Dialects}.
 @gccoptlist{-fmessage-length=@var{n}  @gol
 -fdiagnostics-show-location=@r{[}once@r{|}every-line@r{]}  @gol
 -fdiagnostics-color=@r{[}auto@r{|}never@r{|}always@r{]}  @gol
+-fdiagnostics-urls=@r{[}auto@r{|}never@r{|}always@r{]}  @gol
 -fdiagnostics-format=@r{[}text@r{|}json@r{]}  @gol
 -fno-diagnostics-show-option  -fno-diagnostics-show-caret @gol
 -fno-diagnostics-show-labels  -fno-diagnostics-show-line-numbers @gol
@@ -3908,6 +3909,18 @@ SGR substring for highlighting mismatching types within template
 arguments in the C++ frontend.
 @end table
 
+@item -fdiagnostics-urls[=@var{WHEN}]
+@opindex fdiagnostics-urls
+@cindex urls
+Use escape sequences to embed URLs in diagnostics.  For example, when
+@option{-fdiagnostics-show-option} emits text showing the command-line
+option controlling a diagnostic, embed a URL for documentation of that
+option.
+
+@var{WHEN} is @samp{never}, @samp{always}, or @samp{auto}.
+The default is @samp{auto}, which means to use URL escape sequences only
+when the standard error is a terminal.
+
 @item -fno-diagnostics-show-option
 @opindex fno-diagnostics-show-option
 @opindex fdiagnostics-show-option
index 1216cdd505a18152dc1d3eee5f37755a396761f1..c45a1df656b2b8122f457edeb55db5f44c57b5bf 100644 (file)
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -4041,6 +4041,10 @@ driver_handle_option (struct gcc_options *opts,
       diagnostic_color_init (dc, value);
       break;
 
+    case OPT_fdiagnostics_urls_:
+      diagnostic_urls_init (dc, value);
+      break;
+
     case OPT_fdiagnostics_format_:
       diagnostic_output_format_init (dc,
                                     (enum diagnostics_output_format)value);
@@ -7443,6 +7447,7 @@ driver::global_initializations ()
 
   diagnostic_initialize (global_dc, 0);
   diagnostic_color_init (global_dc);
+  diagnostic_urls_init (global_dc);
 
 #ifdef GCC_DRIVER_HOST_INITIALIZATION
   /* Perform host dependent initialization when needed.  */
index 7c5bd16c7ea68cb022360fc4594f6ce8f028825e..b51c2fbc21cb8f9c812ec64c68930052286ba89a 100644 (file)
@@ -255,6 +255,7 @@ init_options_once (void)
      construct their pretty-printers means that all previous settings
      are overriden.  */
   diagnostic_color_init (global_dc);
+  diagnostic_urls_init (global_dc);
 }
 
 /* Decode command-line options to an array, like
index 83d8a87034823f97c55c8b94411c7013ff8b9a95..1070b9de955430e8b224017e15715873421f59ea 100644 (file)
@@ -2474,6 +2474,10 @@ common_handle_option (struct gcc_options *opts,
       diagnostic_color_init (dc, value);
       break;
 
+    case OPT_fdiagnostics_urls_:
+      diagnostic_urls_init (dc, value);
+      break;
+
     case OPT_fdiagnostics_format_:
       diagnostic_output_format_init (dc,
                                     (enum diagnostics_output_format)value);
index 2b6c58532b3def24d6b755ce70afa9a5e99576bb..c57a3dbd887cf79102e8ed5654921b6f9029a9fc 100644 (file)
@@ -1579,7 +1579,8 @@ pretty_printer::pretty_printer (int maximum_length)
     emitted_prefix (),
     need_newline (),
     translate_identifiers (true),
-    show_color ()
+    show_color (),
+    show_urls (false)
 {
   pp_line_cutoff (this) = maximum_length;
   /* By default, we emit prefixes once per message.  */
@@ -2028,6 +2029,41 @@ identifier_to_locale (const char *ident)
   }
 }
 
+/* Support for encoding URLs.
+   See egmontkob/Hyperlinks_in_Terminal_Emulators.md
+   ( https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda ).
+
+   > A hyperlink is opened upon encountering an OSC 8 escape sequence with
+   > the target URI. The syntax is
+   >
+   >  OSC 8 ; params ; URI ST
+   >
+   > A hyperlink is closed with the same escape sequence, omitting the
+   > parameters and the URI but keeping the separators:
+   >
+   > OSC 8 ; ; ST
+   >
+   > OSC (operating system command) is typically ESC ].  */
+
+/* If URL-printing is enabled, write an "open URL" escape sequence to PP
+   for the given URL.  */
+
+void
+pp_begin_url (pretty_printer *pp, const char *url)
+{
+  if (pp->show_urls)
+    pp_printf (pp, "\33]8;;%s\33\\", url);
+}
+
+/* If URL-printing is enabled, write a "close URL" escape sequence to PP.  */
+
+void
+pp_end_url (pretty_printer *pp)
+{
+  if (pp->show_urls)
+    pp_string (pp, "\33]8;;\33\\");
+}
+
 #if CHECKING_P
 
 namespace selftest {
@@ -2312,6 +2348,32 @@ test_prefixes_and_wrapping ()
 
 }
 
+/* Verify that URL-printing works as expected.  */
+
+void
+test_urls ()
+{
+  {
+    pretty_printer pp;
+    pp.show_urls = false;
+    pp_begin_url (&pp, "http://example.com");
+    pp_string (&pp, "This is a link");
+    pp_end_url (&pp);
+    ASSERT_STREQ ("This is a link",
+                 pp_formatted_text (&pp));
+  }
+
+  {
+    pretty_printer pp;
+    pp.show_urls = true;
+    pp_begin_url (&pp, "http://example.com");
+    pp_string (&pp, "This is a link");
+    pp_end_url (&pp);
+    ASSERT_STREQ ("\33]8;;http://example.com\33\\This is a link\33]8;;\33\\",
+                 pp_formatted_text (&pp));
+  }
+}
+
 /* Run all of the selftests within this file.  */
 
 void
@@ -2320,6 +2382,7 @@ pretty_print_c_tests ()
   test_basic_printing ();
   test_pp_format ();
   test_prefixes_and_wrapping ();
+  test_urls ();
 }
 
 } // namespace selftest
index 2d03b3f9e8def388cce022ecb375738359bdd2fe..c73fc308d509fc375208a59f785b47ec162e7d00 100644 (file)
@@ -273,6 +273,9 @@ public:
 
   /* Nonzero means that text should be colorized.  */
   bool show_color;
+
+  /* Nonzero means that URLs should be emitted.  */
+  bool show_urls;
 };
 
 static inline const char *
@@ -393,6 +396,9 @@ extern void pp_maybe_space (pretty_printer *);
 extern void pp_begin_quote (pretty_printer *, bool);
 extern void pp_end_quote (pretty_printer *, bool);
 
+extern void pp_begin_url (pretty_printer *pp, const char *url);
+extern void pp_end_url (pretty_printer *pp);
+
 /* Switch into verbatim mode and return the old mode.  */
 static inline pp_wrapping_mode_t
 pp_set_verbatim_wrapping_ (pretty_printer *pp)
index 3b1e63bd3ae3ce714e241a2eca8208a092ac109a..b6e9d88aa40c19f7aa7a6e61e0270763da4b61f2 100644 (file)
@@ -1,3 +1,8 @@
+2019-10-10  David Malcolm  <dmalcolm@redhat.com>
+
+       PR 87488
+       * lib/prune.exp (TEST_ALWAYS_FLAGS): Add -fdiagnostics-urls=never.
+
 2019-10-10  Uroš Bizjak  <ubizjak@gmail.com>
 
        PR target/92022
index 812c59e6fee10cdec7610543e0452ff26898bc95..a9beef48ecbbf2d7e19e8eddacc3e847c06ebc32 100644 (file)
@@ -21,7 +21,7 @@ load_lib multiline.exp
 if ![info exists TEST_ALWAYS_FLAGS] {
     set TEST_ALWAYS_FLAGS ""
 }
-set TEST_ALWAYS_FLAGS "-fno-diagnostics-show-caret -fno-diagnostics-show-line-numbers -fdiagnostics-color=never $TEST_ALWAYS_FLAGS"
+set TEST_ALWAYS_FLAGS "-fno-diagnostics-show-caret -fno-diagnostics-show-line-numbers -fdiagnostics-color=never  -fdiagnostics-urls=never $TEST_ALWAYS_FLAGS"
 
 proc prune_gcc_output { text } {
     global srcdir