/* Automatic generation of links into GCC's documentation.
   Copyright (C) 2023-2025 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 */
