OpenMP: Update documentation of metadirective implementation status.
[gcc.git] / gcc / gcc-attribute-urlifier.cc
blobd066624c33b3d7e74b548c7917cdf81da91e8f46
1 /* Automatic generation of links into GCC's documentation.
2 Copyright (C) 2023-2025 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #define INCLUDE_MEMORY
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "pretty-print.h"
26 #include "pretty-print-urlifier.h"
27 #include "gcc-urlifier.h"
28 #include "opts.h"
29 #include "options.h"
30 #include "diagnostic.h"
31 #include "selftest.h"
32 #include "make-unique.h"
33 #include "target.h"
35 /* class attribute_urlifier : public urlifier. */
37 /* By default, use the target's documentation name. */
39 attribute_urlifier::attribute_urlifier ()
40 : m_target_docs_name (targetm.documentation_name)
44 /* Explicitly specify a target's documentation name, for use in selftests. */
46 attribute_urlifier::attribute_urlifier (const char *target_docs_name)
47 : m_target_docs_name (target_docs_name)
51 struct attr_url_entry
53 const char *m_name;
54 const char *m_url_suffix;
55 const char *m_target_docs_name;
56 size_t m_name_len;
59 #include "attr-urls.def"
61 /* We look in two passes: first for an exact match on target name (if any).
62 Otherwise, we look for one with an empty target name. */
64 /* Search for STR, LEN in the given TABLE.
65 If TARGET_DOCS_NAME is non-null, then look for an exact match on target name.
66 If TARGET_DOCS_NAME is null, then look for an empty string for the
67 target name. */
70 static const attr_url_entry *
71 find_attr_url_entry (const char *str,
72 size_t str_len,
73 const char *target_docs_name,
74 const attr_url_entry *table,
75 size_t table_sz)
77 /* This is linear search, but TABLE_SZ ought not to be very large. */
78 for (size_t i = 0; i < table_sz; i++)
79 if (str_len == table[i].m_name_len)
80 if (0 == strncmp (str, table[i].m_name, str_len))
82 if (target_docs_name)
84 /* Reject entries with m_target_docs_name that doesn't match. */
85 if (strcmp (target_docs_name, table[i].m_target_docs_name))
86 continue;
88 else
90 /* Reject entries for which m_target_docs_name is non-empty. */
91 if (table[i].m_target_docs_name[0])
92 continue;
94 return &table[i];
97 return nullptr;
100 /* Search for STR, LEN in all of the attribute tables, in order.
101 TARGET_DOCS_NAME works as above. */
103 static const attr_url_entry *
104 find_attr_url_entry (const char *str,
105 size_t str_len,
106 const char *target_docs_name)
108 for (size_t table_idx = 0; table_idx < ARRAY_SIZE (attr_url_tables);
109 table_idx++)
110 if (const attr_url_entry *entry
111 = find_attr_url_entry (str, str_len, target_docs_name,
112 attr_url_tables[table_idx].m_table,
113 attr_url_tables[table_idx].m_table_sz))
114 return entry;
116 return nullptr;
119 char *
120 attribute_urlifier::get_url_for_quoted_text (const char *p,
121 size_t sz) const
123 label_text url_suffix = get_url_suffix_for_quoted_text (p, sz);
124 if (url_suffix.get ())
125 return make_doc_url (url_suffix.get ());
126 return nullptr;
129 label_text
130 attribute_urlifier::get_url_suffix_for_quoted_text (const char *p,
131 size_t sz) const
133 /* Skip any text after a non-identifier character, so that
134 e.g. given "access(read_write, 2, 3)" we only compare
135 against "access". */
136 for (size_t i = 0; i < sz; i++)
137 if (!ISIDNUM (p[i]))
139 /* Truncate to p[0..i). */
140 sz = i;
141 break;
144 if (m_target_docs_name)
145 if (const attr_url_entry *entry
146 = find_attr_url_entry (p, sz, m_target_docs_name))
147 return label_text::borrow (entry->m_url_suffix);
149 if (const attr_url_entry *entry = find_attr_url_entry (p, sz, nullptr))
150 return label_text::borrow (entry->m_url_suffix);
152 return label_text ();
155 label_text
156 attribute_urlifier::get_url_suffix_for_quoted_text (const char *p) const
158 return get_url_suffix_for_quoted_text (p, strlen (p));
161 #if CHECKING_P
163 namespace selftest {
165 /* Selftests. */
167 static void
168 test_attribute_urlifier ()
170 attribute_urlifier u;
172 ASSERT_EQ (u.get_url_suffix_for_quoted_text ("").get (), nullptr);
173 ASSERT_EQ (u.get_url_suffix_for_quoted_text (")").get (), nullptr);
175 /* Examples of function attributes. */
176 ASSERT_STREQ (u.get_url_suffix_for_quoted_text ("alias").get (),
177 "gcc/Common-Function-Attributes.html"
178 "#index-alias-function-attribute");
180 ASSERT_STREQ (u.get_url_suffix_for_quoted_text
181 ("access(read_write, 2, 3)").get (),
182 "gcc/Common-Function-Attributes.html"
183 "#index-access-function-attribute");
185 /* Example of enumerator attribute. */
186 ASSERT_STREQ (u.get_url_suffix_for_quoted_text ("deprecated").get (),
187 "gcc/Enumerator-Attributes.html"
188 "#index-deprecated-enumerator-attribute");
190 /* We don't yet have an example of a label attribute, since all
191 label attributes have a matching function attribute of the same
192 name, which is found first. */
194 /* Example of statement attribute. */
195 ASSERT_STREQ (u.get_url_suffix_for_quoted_text ("assume").get (),
196 "gcc/Statement-Attributes.html"
197 "#index-assume-statement-attribute");
199 /* Examples of type attributes. */
200 ASSERT_STREQ (u.get_url_suffix_for_quoted_text ("hardbool").get (),
201 "gcc/Common-Type-Attributes.html"
202 "#index-hardbool-type-attribute");
203 ASSERT_STREQ (u.get_url_suffix_for_quoted_text
204 ("packed").get (),
205 "gcc/Common-Type-Attributes.html"
206 "#index-packed-type-attribute");
208 /* Example of variable attribute. */
209 ASSERT_STREQ (u.get_url_suffix_for_quoted_text ("nonstring").get (),
210 "gcc/Common-Variable-Attributes.html"
211 "#index-nonstring-variable-attribute");
213 /* Example of target-specific attributes.
214 For example, "interrupt" has many target-specific documentation URLs. */
216 attribute_urlifier u_rl78 ("RL78");
217 attribute_urlifier u_x86 ("x86");
218 attribute_urlifier u_unrecognized ("not-a-target");
220 ASSERT_STREQ (u_rl78.get_url_suffix_for_quoted_text ("interrupt").get (),
221 "gcc/RL78-Function-Attributes.html"
222 "#index-interrupt-function-attribute_002c-RL78");
223 ASSERT_STREQ (u_x86.get_url_suffix_for_quoted_text ("interrupt").get (),
224 "gcc/x86-Function-Attributes.html"
225 "#index-interrupt-function-attribute_002c-x86");
226 ASSERT_STREQ (u_unrecognized.get_url_suffix_for_quoted_text
227 ("interrupt").get (),
228 "gcc/Common-Function-Attributes.html"
229 "#index-interrupt-function-attribute");
233 /* Run all of the selftests within this file. */
235 void
236 gcc_attribute_urlifier_cc_tests ()
238 test_attribute_urlifier ();
241 } // namespace selftest
243 #endif /* #if CHECKING_P */