diff options
-rw-r--r-- | gcc/Makefile.in | 3 | ||||
-rw-r--r-- | gcc/c-family/c-pragma.cc | 4 | ||||
-rw-r--r-- | gcc/diagnostic.cc | 7 | ||||
-rw-r--r-- | gcc/diagnostic.h | 4 | ||||
-rw-r--r-- | gcc/gcc-urlifier.cc | 159 | ||||
-rw-r--r-- | gcc/gcc-urlifier.def | 20 | ||||
-rw-r--r-- | gcc/gcc-urlifier.h | 26 | ||||
-rw-r--r-- | gcc/gcc.cc | 2 | ||||
-rw-r--r-- | gcc/pretty-print-urlifier.h | 33 | ||||
-rw-r--r-- | gcc/pretty-print.cc | 242 | ||||
-rw-r--r-- | gcc/pretty-print.h | 5 | ||||
-rw-r--r-- | gcc/selftest-run-tests.cc | 1 | ||||
-rw-r--r-- | gcc/selftest.h | 1 | ||||
-rw-r--r-- | gcc/toplev.cc | 2 |
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 */ @@ -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) { |