aboutsummaryrefslogtreecommitdiff
path: root/gcc/gcc-urlifier.cc
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2023-11-03 21:46:53 -0400
committerDavid Malcolm <dmalcolm@redhat.com>2023-11-03 21:46:53 -0400
commitc5db4d8ba5f3dea7b05ba55a65b41e4a6d5432b0 (patch)
treec1f01326ca9da21feefb5366a5e9e1757de5d546 /gcc/gcc-urlifier.cc
parent8200cd97c9c57de582e81a68a6cb2046fa8decb2 (diff)
downloadgcc-c5db4d8ba5f3dea7b05ba55a65b41e4a6d5432b0.zip
gcc-c5db4d8ba5f3dea7b05ba55a65b41e4a6d5432b0.tar.gz
gcc-c5db4d8ba5f3dea7b05ba55a65b41e4a6d5432b0.tar.bz2
diagnostics: add automatic URL-ification within messages
In r10-3781-gd26082357676a3 GCC's pretty-print framework gained the ability to emit embedding URLs via escape sequences for marking up text output.. In r10-3783-gb4c7ca2ef3915a GCC started using this for the [-Wname-of-option] emitted at the end of each diagnostic so that it becomes a hyperlink to the documentation for that option on the GCC website. This makes it much more convenient for the user to locate pertinent documentation when a diagnostic is emitted. The above involved special-casing in one specific place, but there is plenty of quoted text throughout GCC's diagnostic messages that could usefully have a documentation URL: references to options, pragmas, etc This patch adds a new optional "urlifier" parameter to pp_format. The idea is that a urlifier object has responsibility for mapping from quoted strings in diagnostic messages to URLs, and pp_format has the ability to automatically add URL escapes for strings that the urlifier gives it URLs for. For example, given the format string: "%<#pragma pack%> has no effect with %<-fpack-struct%>" with this patch GCC is able to automatically linkify the "#pragma pack" text to https://gcc.gnu.org/onlinedocs/gcc/Structure-Layout-Pragmas.html and the "-fpack-struct" text to: https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#index-fpack-struct and we don't have to modify the format string itself. This is only done for the pp_format within diagnostic_context::report_diagnostic i.e. just for the primary message in each diagnostics, and not for other places within GCC that use pp format internally. "urlifier" is an abstract base class, with a GCC-specific subclass implementing the logic for generating URLs into GCC's HTML documentation via binary search in a data table. This patch implements the gcc_urlifier with a small table generated by hand; the data table in this patch only covers various pragmas and the option referenced by the above pragma message. I have a followup patch that scripts the creation of this data by directly scraping the output of "make html", thus automating all this, and (I hope) minimizing the work of ensuring that documentation URLs emitted by GCC match the generated documentation. gcc/ChangeLog: * Makefile.in (GCC_OBJS): Add gcc-urlifier.o. (OBJS): Likewise. gcc/c-family/ChangeLog: * c-pragma.cc:: (handle_pragma_push_options): Fix missing "GCC" in name of pragma in "junk" message. (handle_pragma_pop_options): Likewise. gcc/ChangeLog: * diagnostic.cc: Include "pretty-print-urlifier.h". (diagnostic_context::initialize): Initialize m_urlifier. (diagnostic_context::finish): Clean up m_urlifier (diagnostic_report::diagnostic): m_urlifier to pp_format. * diagnostic.h (diagnostic_context::m_urlifier): New field. * gcc-urlifier.cc: New file. * gcc-urlifier.def: New file. * gcc-urlifier.h: New file. * gcc.cc: Include "gcc-urlifier.h". (driver::global_initializations): Initialize global_dc->m_urlifier. * pretty-print-urlifier.h: New file. * pretty-print.cc: Include "pretty-print-urlifier.h". (obstack_append_string): New. (urlify_quoted_string): New. (pp_format): Add "urlifier" param and use it to implement optional urlification of quoted text strings. (pp_output_formatted_text): Make buffer a const pointer. (selftest::pp_printf_with_urlifier): New. (selftest::test_urlification): New. (selftest::pretty_print_cc_tests): Call it. * pretty-print.h (class urlifier): New forward declaration. (pp_format): Add optional urlifier param. * selftest-run-tests.cc (selftest::run_tests): Call selftest::gcc_urlifier_cc_tests . * selftest.h (selftest::gcc_urlifier_cc_tests): New decl. * toplev.cc: Include "gcc-urlifier.h". (general_init): Initialize global_dc->m_urlifier. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
Diffstat (limited to 'gcc/gcc-urlifier.cc')
-rw-r--r--gcc/gcc-urlifier.cc159
1 files changed, 159 insertions, 0 deletions
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 */