mirror of
https://forge.sourceware.org/marek/gcc.git
synced 2026-02-21 19:35:36 -05:00
284 lines
7.6 KiB
C++
284 lines
7.6 KiB
C++
/* Automatic generation of links into GCC's documentation.
|
|
Copyright (C) 2023-2026 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 "opts.h"
|
|
#include "options.h"
|
|
#include "diagnostic.h"
|
|
#include "selftest.h"
|
|
|
|
char *
|
|
make_doc_url (const char *doc_url_suffix)
|
|
{
|
|
if (!doc_url_suffix)
|
|
return nullptr;
|
|
|
|
return concat (DOCUMENTATION_ROOT_URL, doc_url_suffix, nullptr);
|
|
}
|
|
|
|
namespace {
|
|
|
|
/* Concrete subclass of urlifier for generating links into
|
|
GCC's HTML documentation. */
|
|
|
|
class gcc_urlifier : public urlifier
|
|
{
|
|
public:
|
|
gcc_urlifier (unsigned int lang_mask)
|
|
: m_lang_mask (lang_mask)
|
|
{}
|
|
|
|
char *get_url_for_quoted_text (const char *p, size_t sz) const final override;
|
|
|
|
label_text get_url_suffix_for_quoted_text (const char *p, size_t sz) const;
|
|
/* We use ATTRIBUTE_UNUSED as this helper is called only from ASSERTs. */
|
|
label_text get_url_suffix_for_quoted_text (const char *p) const ATTRIBUTE_UNUSED;
|
|
|
|
private:
|
|
label_text get_url_suffix_for_option (const char *p, size_t sz) const;
|
|
|
|
unsigned int m_lang_mask;
|
|
};
|
|
|
|
/* class gcc_urlifier : public urlifier. */
|
|
|
|
/* Manage a hard-coded mapping from quoted string to URL suffixes
|
|
in gcc-urlifier.def */
|
|
|
|
#define DOC_URL(QUOTED_TEXT, URL_SUFFIX) \
|
|
{ (QUOTED_TEXT), (URL_SUFFIX) }
|
|
|
|
static const struct
|
|
{
|
|
const char *quoted_text;
|
|
const char *url_suffix;
|
|
} doc_urls[] = {
|
|
|
|
#include "gcc-urlifier.def"
|
|
|
|
};
|
|
|
|
/* Implementation of urlifier::get_url_for_quoted_text vfunc for GCC
|
|
diagnostics. */
|
|
|
|
char *
|
|
gcc_urlifier::get_url_for_quoted_text (const char *p, size_t sz) const
|
|
{
|
|
label_text url_suffix = get_url_suffix_for_quoted_text (p, sz);
|
|
if (url_suffix.get ())
|
|
return make_doc_url (url_suffix.get ());
|
|
return nullptr;
|
|
}
|
|
|
|
/* Look for a URL for the quoted string (P, SZ).
|
|
Return the url suffix if found, or nullptr otherwise. */
|
|
|
|
label_text
|
|
gcc_urlifier::get_url_suffix_for_quoted_text (const char *p, size_t sz) const
|
|
{
|
|
if (sz == 0)
|
|
return label_text ();
|
|
|
|
/* If this is an option, look up the option and see if we have
|
|
a URL for it. */
|
|
if (p[0] == '-')
|
|
{
|
|
label_text suffix = get_url_suffix_for_option (p, sz);
|
|
if (suffix.get ())
|
|
return suffix;
|
|
}
|
|
|
|
/* Otherwise, look within the hard-coded data table in gcc-urlifier.def.
|
|
|
|
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 label_text ();
|
|
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 label_text::borrow (doc_urls[midpoint].url_suffix);
|
|
else
|
|
max = midpoint - 1;
|
|
}
|
|
else if (cmp < 0)
|
|
max = midpoint - 1;
|
|
else
|
|
min = midpoint + 1;
|
|
}
|
|
|
|
/* Not found. */
|
|
return label_text ();
|
|
}
|
|
|
|
/* For use in selftests. */
|
|
|
|
label_text
|
|
gcc_urlifier::get_url_suffix_for_quoted_text (const char *p) const
|
|
{
|
|
return get_url_suffix_for_quoted_text (p, strlen (p));
|
|
}
|
|
|
|
/* Look for a URL for the quoted string (P, SZ) that appears to be
|
|
an option.
|
|
Return the url suffix if found, or nullptr otherwise. */
|
|
|
|
label_text
|
|
gcc_urlifier::get_url_suffix_for_option (const char *p, size_t sz) const
|
|
{
|
|
/* Look up this option
|
|
|
|
find_opt does a binary search, taking a 0-terminated string,
|
|
and skipping the leading '-'.
|
|
|
|
We have a (pointer,size) pair that doesn't necessarily have a
|
|
terminator.
|
|
Additionally, we could have one of the e.g. "-Wno-" variants of
|
|
the option, which find_opt doesn't handle.
|
|
|
|
Hence we need to create input for find_opt in a temporary buffer. */
|
|
char *option_buffer;
|
|
|
|
const char *new_prefix;
|
|
if (const char *old_prefix = get_option_prefix_remapping (p, sz, &new_prefix))
|
|
{
|
|
/* We have one of the variants; generate a buffer containing a copy
|
|
that maps from the old prefix to the new prefix
|
|
e.g. given "-Wno-suffix", generate "-Wsuffix". */
|
|
gcc_assert (old_prefix[0] == '-');
|
|
gcc_assert (new_prefix);
|
|
gcc_assert (new_prefix[0] == '-');
|
|
|
|
const size_t old_prefix_len = strlen (old_prefix);
|
|
gcc_assert (old_prefix_len <= sz);
|
|
const size_t suffix_len = sz - old_prefix_len;
|
|
const size_t new_prefix_len = strlen (new_prefix);
|
|
const size_t new_sz = new_prefix_len + suffix_len + 1;
|
|
|
|
option_buffer = (char *)xmalloc (new_sz);
|
|
memcpy (option_buffer, new_prefix, new_prefix_len);
|
|
/* Copy suffix. */
|
|
memcpy (option_buffer + new_prefix_len, p + old_prefix_len, suffix_len);
|
|
/* Terminate. */
|
|
option_buffer[new_prefix_len + suffix_len] = '\0';
|
|
}
|
|
else
|
|
{
|
|
/* Otherwise we can simply create a 0-terminated clone of the string. */
|
|
gcc_assert (sz > 0);
|
|
gcc_assert (p[0] == '-');
|
|
option_buffer = xstrndup (p, sz);
|
|
}
|
|
|
|
size_t opt = find_opt (option_buffer + 1, m_lang_mask);
|
|
free (option_buffer);
|
|
|
|
if (opt >= N_OPTS)
|
|
/* Option not recognized. */
|
|
return label_text ();
|
|
|
|
return get_option_url_suffix (opt, m_lang_mask);
|
|
}
|
|
|
|
} // anonymous namespace
|
|
|
|
std::unique_ptr<urlifier>
|
|
make_gcc_urlifier (unsigned int lang_mask)
|
|
{
|
|
return std::make_unique<gcc_urlifier> (lang_mask);
|
|
}
|
|
|
|
/* class auto_override_urlifier. */
|
|
|
|
auto_override_urlifier::auto_override_urlifier (const urlifier &new_urlifier)
|
|
{
|
|
global_dc->push_borrowed_urlifier (new_urlifier);
|
|
}
|
|
|
|
auto_override_urlifier::~auto_override_urlifier ()
|
|
{
|
|
global_dc->pop_urlifier ();
|
|
}
|
|
|
|
#if CHECKING_P
|
|
|
|
namespace selftest {
|
|
|
|
/* Selftests. */
|
|
|
|
static void
|
|
test_gcc_urlifier ()
|
|
{
|
|
/* 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 (0);
|
|
|
|
ASSERT_EQ (u.get_url_suffix_for_quoted_text ("").get (), nullptr);
|
|
ASSERT_EQ (u.get_url_suffix_for_quoted_text (")").get (), nullptr);
|
|
|
|
ASSERT_STREQ (u.get_url_suffix_for_quoted_text ("#pragma message").get (),
|
|
"gcc/Diagnostic-Pragmas.html");
|
|
|
|
// Incomplete prefix of a quoted_text
|
|
ASSERT_EQ (u.get_url_suffix_for_quoted_text ("#pragma mess").get (), 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).get (),
|
|
doc_urls[idx].url_suffix);
|
|
|
|
/* Check an option. */
|
|
ASSERT_STREQ (u.get_url_suffix_for_quoted_text ("-fpack-struct").get (),
|
|
"gcc/Code-Gen-Options.html#index-fpack-struct");
|
|
|
|
/* Check a "-fno-" variant of an option. */
|
|
ASSERT_STREQ (u.get_url_suffix_for_quoted_text ("-fno-inline").get (),
|
|
"gcc/Optimize-Options.html#index-finline");
|
|
}
|
|
|
|
/* Run all of the selftests within this file. */
|
|
|
|
void
|
|
gcc_urlifier_cc_tests ()
|
|
{
|
|
test_gcc_urlifier ();
|
|
}
|
|
|
|
} // namespace selftest
|
|
|
|
#endif /* #if CHECKING_P */
|