aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/Makefile.in3
-rw-r--r--gcc/c-family/c-pragma.cc4
-rw-r--r--gcc/diagnostic.cc7
-rw-r--r--gcc/diagnostic.h4
-rw-r--r--gcc/gcc-urlifier.cc159
-rw-r--r--gcc/gcc-urlifier.def20
-rw-r--r--gcc/gcc-urlifier.h26
-rw-r--r--gcc/gcc.cc2
-rw-r--r--gcc/pretty-print-urlifier.h33
-rw-r--r--gcc/pretty-print.cc242
-rw-r--r--gcc/pretty-print.h5
-rw-r--r--gcc/selftest-run-tests.cc1
-rw-r--r--gcc/selftest.h1
-rw-r--r--gcc/toplev.cc2
14 files changed, 498 insertions, 11 deletions
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 83f2946..29cec21 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1286,7 +1286,7 @@ FORTRAN_TARGET_OBJS=@fortran_target_objs@
RUST_TARGET_OBJS=@rust_target_objs@
# Object files for gcc many-languages driver.
-GCC_OBJS = gcc.o gcc-main.o ggc-none.o
+GCC_OBJS = gcc.o gcc-main.o ggc-none.o gcc-urlifier.o
c-family-warn = $(STRICT_WARN)
@@ -1459,6 +1459,7 @@ OBJS = \
function-tests.o \
fwprop.o \
gcc-rich-location.o \
+ gcc-urlifier.o \
gcse.o \
gcse-common.o \
ggc-common.o \
diff --git a/gcc/c-family/c-pragma.cc b/gcc/c-family/c-pragma.cc
index df3e3e6..849f8ac 100644
--- a/gcc/c-family/c-pragma.cc
+++ b/gcc/c-family/c-pragma.cc
@@ -1208,7 +1208,7 @@ handle_pragma_push_options (cpp_reader *)
token = pragma_lex (&x);
if (token != CPP_EOF)
{
- warning (OPT_Wpragmas, "junk at end of %<#pragma push_options%>");
+ warning (OPT_Wpragmas, "junk at end of %<#pragma GCC push_options%>");
return;
}
@@ -1245,7 +1245,7 @@ handle_pragma_pop_options (cpp_reader *)
token = pragma_lex (&x);
if (token != CPP_EOF)
{
- warning (OPT_Wpragmas, "junk at end of %<#pragma pop_options%>");
+ warning (OPT_Wpragmas, "junk at end of %<#pragma GCC pop_options%>");
return;
}
diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc
index 4b92f54..e917e6c 100644
--- a/gcc/diagnostic.cc
+++ b/gcc/diagnostic.cc
@@ -43,6 +43,7 @@ along with GCC; see the file COPYING3. If not see
#include "opts.h"
#include "cpplib.h"
#include "text-art/theme.h"
+#include "pretty-print-urlifier.h"
#ifdef HAVE_TERMIOS_H
# include <termios.h>
@@ -193,6 +194,7 @@ diagnostic_context::initialize (int n_opts)
m_option_state = nullptr;
m_option_name = nullptr;
m_get_option_url = nullptr;
+ m_urlifier = nullptr;
m_last_location = UNKNOWN_LOCATION;
m_last_module = nullptr;
m_client_aux_data = nullptr;
@@ -350,6 +352,9 @@ diagnostic_context::finish ()
delete m_client_data_hooks;
m_client_data_hooks = nullptr;
}
+
+ delete m_urlifier;
+ m_urlifier = nullptr;
}
void
@@ -1567,7 +1572,7 @@ diagnostic_context::report_diagnostic (diagnostic_info *diagnostic)
m_output_format->on_begin_group ();
m_diagnostic_groups.m_emission_count++;
- pp_format (this->printer, &diagnostic->message);
+ pp_format (this->printer, &diagnostic->message, m_urlifier);
m_output_format->on_begin_diagnostic (diagnostic);
pp_output_formatted_text (this->printer);
if (m_show_cwe)
diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index 2def7bd..cf21558 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -518,6 +518,10 @@ public:
particular option. */
char *(*m_get_option_url) (diagnostic_context *, int);
+ /* An optional hook for adding URLs to quoted text strings in
+ diagnostics. Only used for the main diagnostic message. */
+ urlifier *m_urlifier;
+
void (*m_print_path) (diagnostic_context *, const diagnostic_path *);
json::value *(*m_make_json_for_path) (diagnostic_context *,
const diagnostic_path *);
diff --git a/gcc/gcc-urlifier.cc b/gcc/gcc-urlifier.cc
new file mode 100644
index 0000000..269246b
--- /dev/null
+++ b/gcc/gcc-urlifier.cc
@@ -0,0 +1,159 @@
+/* Automatic generation of links into GCC's documentation.
+ Copyright (C) 2023 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/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "pretty-print.h"
+#include "pretty-print-urlifier.h"
+#include "gcc-urlifier.h"
+#include "selftest.h"
+
+namespace {
+
+/* Concrete subclass of urlifier for generating links into
+ GCC's HTML documentation. */
+
+class gcc_urlifier : public urlifier
+{
+public:
+ char *get_url_for_quoted_text (const char *p, size_t sz) const final override;
+
+ const char *get_url_suffix_for_quoted_text (const char *p, size_t sz) const;
+ const char *get_url_suffix_for_quoted_text (const char *p) const;
+
+private:
+ static char *
+ make_doc_url (const char *doc_url_suffix);
+};
+
+/* class gcc_urlifier : public urlifier. */
+
+#define DOC_URL(QUOTED_TEXT, URL_SUFFIX) \
+ { (QUOTED_TEXT), (URL_SUFFIX) }
+
+const struct
+{
+ const char *quoted_text;
+ const char *url_suffix;
+} doc_urls[] = {
+
+#include "gcc-urlifier.def"
+
+};
+
+char *
+gcc_urlifier::get_url_for_quoted_text (const char *p, size_t sz) const
+{
+ if (const char *url_suffix = get_url_suffix_for_quoted_text (p, sz))
+ return make_doc_url (url_suffix);
+ return nullptr;
+}
+
+const char *
+gcc_urlifier::get_url_suffix_for_quoted_text (const char *p, size_t sz) const
+{
+ /* Binary search. This assumes that the quoted_text fields of doc_urls
+ are in sorted order. */
+ int min = 0;
+ int max = ARRAY_SIZE (doc_urls) - 1;
+ while (true)
+ {
+ if (min > max)
+ return nullptr;
+ int midpoint = (min + max) / 2;
+ gcc_assert ((size_t)midpoint < ARRAY_SIZE (doc_urls));
+ int cmp = strncmp (p, doc_urls[midpoint].quoted_text, sz);
+ if (cmp == 0)
+ {
+ if (doc_urls[midpoint].quoted_text[sz] == '\0')
+ return doc_urls[midpoint].url_suffix;
+ else
+ max = midpoint - 1;
+ }
+ else if (cmp < 0)
+ max = midpoint - 1;
+ else
+ min = midpoint + 1;
+ }
+ return nullptr;
+}
+
+const char *
+gcc_urlifier::get_url_suffix_for_quoted_text (const char *p) const
+{
+ return get_url_suffix_for_quoted_text (p, strlen (p));
+}
+
+char *
+gcc_urlifier::make_doc_url (const char *doc_url_suffix)
+{
+ if (!doc_url_suffix)
+ return nullptr;
+
+ return concat (DOCUMENTATION_ROOT_URL, doc_url_suffix, nullptr);
+}
+
+} // anonymous namespace
+
+urlifier *
+make_gcc_urlifier ()
+{
+ return new gcc_urlifier ();
+}
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Selftests. */
+
+/* Run all of the selftests within this file. */
+
+void
+gcc_urlifier_cc_tests ()
+{
+ /* Check that doc_urls.quoted_text is sorted. */
+ for (size_t idx = 1; idx < ARRAY_SIZE (doc_urls); idx++)
+ gcc_assert (strcmp (doc_urls[idx - 1].quoted_text,
+ doc_urls[idx].quoted_text)
+ < 0);
+
+ gcc_urlifier u;
+
+ ASSERT_EQ (u.get_url_suffix_for_quoted_text (""), nullptr);
+ ASSERT_EQ (u.get_url_suffix_for_quoted_text (")"), nullptr);
+
+ ASSERT_STREQ (u.get_url_suffix_for_quoted_text ("#pragma message"),
+ "gcc/Diagnostic-Pragmas.html");
+
+ // Incomplete prefix of a quoted_text
+ ASSERT_EQ (u.get_url_suffix_for_quoted_text ("#pragma mess"), nullptr);
+
+ /* Check that every element is findable. */
+ for (size_t idx = 0; idx < ARRAY_SIZE (doc_urls); idx++)
+ ASSERT_STREQ
+ (u.get_url_suffix_for_quoted_text (doc_urls[idx].quoted_text),
+ doc_urls[idx].url_suffix);
+}
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
diff --git a/gcc/gcc-urlifier.def b/gcc/gcc-urlifier.def
new file mode 100644
index 0000000..360de93
--- /dev/null
+++ b/gcc/gcc-urlifier.def
@@ -0,0 +1,20 @@
+/* Keep this file sorted. */
+DOC_URL ("#pragma GCC diagnostic", "gcc/Diagnostic-Pragmas.html"),
+DOC_URL ("#pragma GCC diagnostic ignored_attributes", "gcc/Diagnostic-Pragmas.html"),
+DOC_URL ("#pragma GCC ivdep", "gcc/Loop-Specific-Pragmas.html#index-pragma-GCC-ivdep"),
+DOC_URL ("#pragma GCC novector", "gcc/Loop-Specific-Pragmas.html#index-pragma-GCC-novector"),
+DOC_URL ("#pragma GCC optimize", "gcc/Function-Specific-Option-Pragmas.html#index-pragma-GCC-optimize"),
+DOC_URL ("#pragma GCC pop_options", "gcc/Push_002fPop-Macro-Pragmas.html"),
+DOC_URL ("#pragma GCC push_options", "gcc/Push_002fPop-Macro-Pragmas.html"),
+DOC_URL ("#pragma GCC reset_options", "gcc/Function-Specific-Option-Pragmas.html#index-pragma-GCC-reset_005foptions"),
+DOC_URL ("#pragma GCC target", "gcc/Function-Specific-Option-Pragmas.html#index-pragma-GCC-target"),
+DOC_URL ("#pragma GCC unroll", "gcc/Loop-Specific-Pragmas.html#index-pragma-GCC-unroll-n"),
+DOC_URL ("#pragma GCC visibility", "gcc/Visibility-Pragmas.html"),
+DOC_URL ("#pragma GCC visibility pop", "gcc/Visibility-Pragmas.html"),
+DOC_URL ("#pragma message", "gcc/Diagnostic-Pragmas.html"),
+DOC_URL ("#pragma pack", "gcc/Structure-Layout-Pragmas.html"),
+DOC_URL ("#pragma redefine_extname", "gcc/Symbol-Renaming-Pragmas.html"),
+DOC_URL ("#pragma scalar_storage_order", "gcc/Structure-Layout-Pragmas.html"),
+DOC_URL ("#pragma weak", "gcc/Weak-Pragmas.html"),
+DOC_URL ("--version", "gcc/Overall-Options.html#index-version"),
+DOC_URL ("-fpack-struct", "gcc/Code-Gen-Options.html#index-fpack-struct"),
diff --git a/gcc/gcc-urlifier.h b/gcc/gcc-urlifier.h
new file mode 100644
index 0000000..614e1c6
--- /dev/null
+++ b/gcc/gcc-urlifier.h
@@ -0,0 +1,26 @@
+/* Automatic generation of links into GCC's documentation.
+ Copyright (C) 2023 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_GCC_URLIFIER_H
+#define GCC_GCC_URLIFIER_H
+
+extern urlifier *make_gcc_urlifier ();
+
+#endif /* GCC_GCC_URLIFIER_H */
diff --git a/gcc/gcc.cc b/gcc/gcc.cc
index 0b7e078..0246495 100644
--- a/gcc/gcc.cc
+++ b/gcc/gcc.cc
@@ -46,6 +46,7 @@ compilation is specified by a string called a "spec". */
#include "spellcheck.h"
#include "opts-jobserver.h"
#include "common/common-target.h"
+#include "gcc-urlifier.h"
#ifndef MATH_LIBRARY
#define MATH_LIBRARY "m"
@@ -8291,6 +8292,7 @@ driver::global_initializations ()
diagnostic_initialize (global_dc, 0);
diagnostic_color_init (global_dc);
diagnostic_urls_init (global_dc);
+ global_dc->m_urlifier = make_gcc_urlifier ();
#ifdef GCC_DRIVER_HOST_INITIALIZATION
/* Perform host dependent initialization when needed. */
diff --git a/gcc/pretty-print-urlifier.h b/gcc/pretty-print-urlifier.h
new file mode 100644
index 0000000..bdb7fca
--- /dev/null
+++ b/gcc/pretty-print-urlifier.h
@@ -0,0 +1,33 @@
+/* Copyright (C) 2023 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_PRETTY_PRINT_URLIFIER_H
+#define GCC_PRETTY_PRINT_URLIFIER_H
+
+/* Abstract base class for optional use in pp_format for adding URLs
+ to quoted text strings. */
+
+class urlifier
+{
+public:
+ virtual ~urlifier () {}
+ virtual char *get_url_for_quoted_text (const char *p, size_t sz) const = 0;
+};
+
+#endif /* GCC_PRETTY_PRINT_URLIFIER_H */
diff --git a/gcc/pretty-print.cc b/gcc/pretty-print.cc
index 80780cf..9a48276 100644
--- a/gcc/pretty-print.cc
+++ b/gcc/pretty-print.cc
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "intl.h"
#include "pretty-print.h"
+#include "pretty-print-urlifier.h"
#include "diagnostic-color.h"
#include "diagnostic-event-id.h"
#include "selftest.h"
@@ -1022,6 +1023,95 @@ pp_indent (pretty_printer *pp)
static const char *get_end_url_string (pretty_printer *);
+/* Append STR to OSTACK, without a null-terminator. */
+
+static void
+obstack_append_string (obstack *ostack, const char *str)
+{
+ obstack_grow (ostack, str, strlen (str));
+}
+
+/* Given quoted text starting at QUOTED_TEXT_START_IDX within PP's buffer,
+ potentially use URLIFIER (if non-null) to see if there's a URL for the
+ quoted text.
+
+ If so, replace the quoted part of the text in the buffer with a URLified
+ version of the text, using PP's settings.
+
+ For example, given this is the buffer:
+ "this is a test `hello world"
+ .................^~~~~~~~~~~
+ with the quoted text starting at the 'h' of "hello world", the buffer
+ becomes:
+ "this is a test `BEGIN_URL(URL)hello worldEND(URL)"
+ .................^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ .................-----------replacement-----------
+*/
+
+static void
+urlify_quoted_string (pretty_printer *pp,
+ const urlifier *urlifier,
+ size_t quoted_text_start_idx)
+{
+ if (pp->url_format == URL_FORMAT_NONE)
+ return;
+ if (!urlifier)
+ return;
+
+ output_buffer * const buffer = pp_buffer (pp);
+
+ /* Get end of quoted string. */
+ const size_t close_quote_idx
+ = obstack_object_size (&buffer->chunk_obstack);
+ gcc_assert (close_quote_idx >= quoted_text_start_idx);
+ if (close_quote_idx == quoted_text_start_idx)
+ /* Empty quoted string; do nothing. */
+ return;
+ const size_t len = close_quote_idx - quoted_text_start_idx;
+ const char *start = (buffer->chunk_obstack.object_base
+ + quoted_text_start_idx);
+ char *url = urlifier->get_url_for_quoted_text (start, len);
+ if (!url)
+ /* No URL for this quoted text; do nothing. */
+ return;
+
+ /* Stash a copy of the quoted text. */
+ char *text = xstrndup (start, len);
+
+ /* Replace quoted text... */
+ buffer->chunk_obstack.next_free -= len;
+
+ /* ...with URLified version of the text. */
+ /* Begin URL. */
+ switch (pp->url_format)
+ {
+ default:
+ case URL_FORMAT_NONE:
+ gcc_unreachable ();
+ case URL_FORMAT_ST:
+ obstack_append_string (&buffer->chunk_obstack,
+ "\33]8;;");
+ obstack_append_string (&buffer->chunk_obstack, url);
+ obstack_append_string (&buffer->chunk_obstack,
+ "\33\\");
+ break;
+ case URL_FORMAT_BEL:
+ obstack_append_string (&buffer->chunk_obstack,
+ "\33]8;;");
+ obstack_append_string (&buffer->chunk_obstack, url);
+ obstack_append_string (&buffer->chunk_obstack,
+ "\a");
+ break;
+ }
+ /* Add the text back. */
+ obstack_append_string (&buffer->chunk_obstack, text);
+ /* End URL. */
+ obstack_append_string (&buffer->chunk_obstack,
+ get_end_url_string (pp));
+ free (text);
+ free (url);
+}
+
/* The following format specifiers are recognized as being client independent:
%d, %i: (signed) integer in base ten.
%u: unsigned integer in base ten.
@@ -1064,12 +1154,25 @@ static const char *get_end_url_string (pretty_printer *);
/* Formatting phases 1 and 2: render TEXT->format_spec plus
text->m_args_ptr into a series of chunks in pp_buffer (PP)->args[].
- Phase 3 is in pp_output_formatted_text. */
+ Phase 3 is in pp_output_formatted_text.
+
+ If URLIFIER is non-NULL, then use it to add URLs for quoted
+ strings, so that e.g.
+ "before %<quoted%> after"
+ with a URLIFIER that has a URL for "quoted" might be emitted as:
+ "before `BEGIN_URL(http://example.com)quotedEND_URL' after"
+ This only works for message fragments that are:
+ - quoted entirely in phase 1 (e.g. "%<this is quoted%>"), or
+ - quoted entirely in phase 2 (e.g. "%qs"),
+ but *not* in strings that use a mixture of both phases
+ (e.g. "%<this is a mixture: %s %>"). */
void
-pp_format (pretty_printer *pp, text_info *text)
+pp_format (pretty_printer *pp,
+ text_info *text,
+ const urlifier *urlifier)
{
- output_buffer *buffer = pp_buffer (pp);
+ output_buffer * const buffer = pp_buffer (pp);
const char *p;
const char **args;
struct chunk_info *new_chunk_array;
@@ -1079,6 +1182,9 @@ pp_format (pretty_printer *pp, text_info *text)
bool any_unnumbered = false, any_numbered = false;
const char **formatters[PP_NL_ARGMAX];
+ /* Keep track of location of last "%", if any. */
+ size_t quoted_text_start_idx = 0;
+
/* Allocate a new chunk structure. */
new_chunk_array = XOBNEW (&buffer->chunk_obstack, struct chunk_info);
new_chunk_array->prev = buffer->cur_chunk_array;
@@ -1122,11 +1228,21 @@ pp_format (pretty_printer *pp, text_info *text)
= colorize_start (pp_show_color (pp), "quote");
obstack_grow (&buffer->chunk_obstack, colorstr, strlen (colorstr));
p++;
+
+ /* Stash offset of start of quoted string. */
+ quoted_text_start_idx
+ = obstack_object_size (&buffer->chunk_obstack);
+
continue;
}
case '>':
{
+ if (quoted_text_start_idx)
+ {
+ urlify_quoted_string (pp, urlifier, quoted_text_start_idx);
+ quoted_text_start_idx = 0;
+ }
const char *colorstr = colorize_stop (pp_show_color (pp));
obstack_grow (&buffer->chunk_obstack, colorstr, strlen (colorstr));
}
@@ -1168,6 +1284,12 @@ pp_format (pretty_printer *pp, text_info *text)
obstack_1grow (&buffer->chunk_obstack, '\0');
gcc_assert (chunk < PP_NL_ARGMAX * 2);
args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char *);
+ /* We can't yet handle urlifying quoted strings that use
+ a combination of phase 1 and phase 2 e.g.
+ "did you mean %<-%s%>".
+ Stop any phase 1 quoted text if there are going to be any
+ phase 2 quoted chunks. */
+ quoted_text_start_idx = 0;
break;
}
@@ -1270,6 +1392,7 @@ pp_format (pretty_printer *pp, text_info *text)
bool plus = false;
bool hash = false;
bool quote = false;
+ quoted_text_start_idx = 0;
/* We do not attempt to enforce any ordering on the modifier
characters. */
@@ -1310,7 +1433,11 @@ pp_format (pretty_printer *pp, text_info *text)
gcc_assert (!wide || precision == 0);
if (quote)
- pp_begin_quote (pp, pp_show_color (pp));
+ {
+ pp_begin_quote (pp, pp_show_color (pp));
+ quoted_text_start_idx
+ = obstack_object_size (&buffer->chunk_obstack);
+ }
switch (*p)
{
@@ -1480,7 +1607,14 @@ pp_format (pretty_printer *pp, text_info *text)
}
if (quote)
- pp_end_quote (pp, pp_show_color (pp));
+ {
+ if (quoted_text_start_idx)
+ {
+ urlify_quoted_string (pp, urlifier, quoted_text_start_idx);
+ quoted_text_start_idx = 0;
+ }
+ pp_end_quote (pp, pp_show_color (pp));
+ }
obstack_1grow (&buffer->chunk_obstack, '\0');
*formatters[argno] = XOBFINISH (&buffer->chunk_obstack, const char *);
@@ -1507,7 +1641,7 @@ void
pp_output_formatted_text (pretty_printer *pp)
{
unsigned int chunk;
- output_buffer *buffer = pp_buffer (pp);
+ output_buffer * const buffer = pp_buffer (pp);
struct chunk_info *chunk_array = buffer->cur_chunk_array;
const char **args = chunk_array->args;
@@ -2640,6 +2774,101 @@ test_null_urls ()
}
}
+/* Verify that URLification works as expected. */
+
+static void
+pp_printf_with_urlifier (pretty_printer *pp,
+ const urlifier *urlifier,
+ const char *msg, ...)
+{
+ va_list ap;
+
+ va_start (ap, msg);
+ text_info text (msg, &ap, errno);
+ pp_format (pp, &text, urlifier);
+ pp_output_formatted_text (pp);
+ va_end (ap);
+}
+
+
+void
+test_urlification ()
+{
+ class test_urlifier : public urlifier
+ {
+ public:
+ char *
+ get_url_for_quoted_text (const char *p, size_t sz) const final override
+ {
+ if (!strncmp (p, "-foption", sz))
+ return xstrdup ("http://example.com");
+ return nullptr;
+ }
+ };
+
+ auto_fix_quotes fix_quotes;
+ const test_urlifier urlifier;
+
+ /* Uses of "%<" and "%>". */
+ {
+ {
+ pretty_printer pp;
+ pp.url_format = URL_FORMAT_NONE;
+ pp_printf_with_urlifier (&pp, &urlifier,
+ "foo %<-foption%> %<unrecognized%> bar");
+ ASSERT_STREQ ("foo `-foption' `unrecognized' bar",
+ pp_formatted_text (&pp));
+ }
+ {
+ pretty_printer pp;
+ pp.url_format = URL_FORMAT_ST;
+ pp_printf_with_urlifier (&pp, &urlifier,
+ "foo %<-foption%> %<unrecognized%> bar");
+ ASSERT_STREQ
+ ("foo `\33]8;;http://example.com\33\\-foption\33]8;;\33\\'"
+ " `unrecognized' bar",
+ pp_formatted_text (&pp));
+ }
+ {
+ pretty_printer pp;
+ pp.url_format = URL_FORMAT_BEL;
+ pp_printf_with_urlifier (&pp, &urlifier,
+ "foo %<-foption%> %<unrecognized%> bar");
+ ASSERT_STREQ
+ ("foo `\33]8;;http://example.com\a-foption\33]8;;\a'"
+ " `unrecognized' bar",
+ pp_formatted_text (&pp));
+ }
+ }
+
+ /* Use of "%qs". */
+ {
+ pretty_printer pp;
+ pp.url_format = URL_FORMAT_ST;
+ pp_printf_with_urlifier (&pp, &urlifier,
+ "foo %qs %qs bar",
+ "-foption", "unrecognized");
+ ASSERT_STREQ
+ ("foo `\33]8;;http://example.com\33\\-foption\33]8;;\33\\'"
+ " `unrecognized' bar",
+ pp_formatted_text (&pp));
+ }
+
+ /* Mixed usage of %< and %s, where the quoted string is built between
+ a mixture of phase 1 and phase 2. */
+ {
+ pretty_printer pp;
+ pp.url_format = URL_FORMAT_ST;
+ pp_printf_with_urlifier (&pp, &urlifier,
+ "foo %<-f%s%> bar",
+ "option");
+ /* We don't support this, but make sure we don't crash. */
+ ASSERT_STREQ
+ ("foo `-foption' bar",
+ pp_formatted_text (&pp));
+ }
+}
+
/* Test multibyte awareness. */
static void test_utf8 ()
{
@@ -2690,6 +2919,7 @@ pretty_print_cc_tests ()
test_prefixes_and_wrapping ();
test_urls ();
test_null_urls ();
+ test_urlification ();
test_utf8 ();
}
diff --git a/gcc/pretty-print.h b/gcc/pretty-print.h
index 8759f0d..9ba2c0a 100644
--- a/gcc/pretty-print.h
+++ b/gcc/pretty-print.h
@@ -228,6 +228,8 @@ class format_postprocessor
/* True if colors should be shown. */
#define pp_show_color(PP) (PP)->show_color
+class urlifier;
+
/* The data structure that contains the bare minimum required to do
proper pretty-printing. Clients may derived from this structure
and add additional fields they need. */
@@ -404,7 +406,8 @@ extern void pp_verbatim (pretty_printer *, const char *, ...)
ATTRIBUTE_GCC_PPDIAG(2,3);
extern void pp_flush (pretty_printer *);
extern void pp_really_flush (pretty_printer *);
-extern void pp_format (pretty_printer *, text_info *);
+extern void pp_format (pretty_printer *, text_info *,
+ const urlifier * = nullptr);
extern void pp_output_formatted_text (pretty_printer *);
extern void pp_format_verbatim (pretty_printer *, text_info *);
diff --git a/gcc/selftest-run-tests.cc b/gcc/selftest-run-tests.cc
index e2fc8f8..cb53e90 100644
--- a/gcc/selftest-run-tests.cc
+++ b/gcc/selftest-run-tests.cc
@@ -120,6 +120,7 @@ selftest::run_tests ()
lang_hooks.run_lang_selftests ();
text_art_tests ();
+ gcc_urlifier_cc_tests ();
/* Run the analyzer selftests (if enabled). */
ana::selftest::run_analyzer_selftests ();
diff --git a/gcc/selftest.h b/gcc/selftest.h
index 20d522a..b0a4142 100644
--- a/gcc/selftest.h
+++ b/gcc/selftest.h
@@ -231,6 +231,7 @@ extern void et_forest_cc_tests ();
extern void fibonacci_heap_cc_tests ();
extern void fold_const_cc_tests ();
extern void function_tests_cc_tests ();
+extern void gcc_urlifier_cc_tests ();
extern void ggc_tests_cc_tests ();
extern void gimple_cc_tests ();
extern void hash_map_tests_cc_tests ();
diff --git a/gcc/toplev.cc b/gcc/toplev.cc
index d098a7c..e39162a 100644
--- a/gcc/toplev.cc
+++ b/gcc/toplev.cc
@@ -88,6 +88,7 @@ along with GCC; see the file COPYING3. If not see
#include "ipa-modref.h"
#include "ipa-param-manipulation.h"
#include "dbgcnt.h"
+#include "gcc-urlifier.h"
#include "selftest.h"
@@ -1048,6 +1049,7 @@ general_init (const char *argv0, bool init_signals)
global_dc->m_option_state = &global_options;
global_dc->m_option_name = option_name;
global_dc->m_get_option_url = get_option_url;
+ global_dc->m_urlifier = make_gcc_urlifier ();
if (init_signals)
{