Branch data Line data Source code
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>.
4 : :
5 : : This file is part of GCC.
6 : :
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.
11 : :
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.
16 : :
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/>. */
20 : :
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 "target.h"
33 : :
34 : : /* class attribute_urlifier : public urlifier. */
35 : :
36 : : /* By default, use the target's documentation name. */
37 : :
38 : 1876795064 : attribute_urlifier::attribute_urlifier ()
39 : 1876795064 : : m_target_docs_name (targetm.documentation_name)
40 : : {
41 : 1876795064 : }
42 : :
43 : : /* Explicitly specify a target's documentation name, for use in selftests. */
44 : :
45 : 12 : attribute_urlifier::attribute_urlifier (const char *target_docs_name)
46 : 12 : : m_target_docs_name (target_docs_name)
47 : : {
48 : 12 : }
49 : :
50 : : struct attr_url_entry
51 : : {
52 : : const char *m_name;
53 : : const char *m_url_suffix;
54 : : const char *m_target_docs_name;
55 : : size_t m_name_len;
56 : : };
57 : :
58 : : #include "attr-urls.def"
59 : :
60 : : /* We look in two passes: first for an exact match on target name (if any).
61 : : Otherwise, we look for one with an empty target name. */
62 : :
63 : : /* Search for STR, LEN in the given TABLE.
64 : : If TARGET_DOCS_NAME is non-null, then look for an exact match on target name.
65 : : If TARGET_DOCS_NAME is null, then look for an empty string for the
66 : : target name. */
67 : :
68 : :
69 : : static const attr_url_entry *
70 : 194006 : find_attr_url_entry (const char *str,
71 : : size_t str_len,
72 : : const char *target_docs_name,
73 : : const attr_url_entry *table,
74 : : size_t table_sz)
75 : : {
76 : : /* This is linear search, but TABLE_SZ ought not to be very large. */
77 : 11576131 : for (size_t i = 0; i < table_sz; i++)
78 : 11386594 : if (str_len == table[i].m_name_len)
79 : 653325 : if (0 == strncmp (str, table[i].m_name, str_len))
80 : : {
81 : 10994 : if (target_docs_name)
82 : : {
83 : : /* Reject entries with m_target_docs_name that doesn't match. */
84 : 6521 : if (strcmp (target_docs_name, table[i].m_target_docs_name))
85 : 6509 : continue;
86 : : }
87 : : else
88 : : {
89 : : /* Reject entries for which m_target_docs_name is non-empty. */
90 : 4473 : if (table[i].m_target_docs_name[0])
91 : 16 : continue;
92 : : }
93 : : return &table[i];
94 : : }
95 : :
96 : : return nullptr;
97 : : }
98 : :
99 : : /* Search for STR, LEN in all of the attribute tables, in order.
100 : : TARGET_DOCS_NAME works as above. */
101 : :
102 : : static const attr_url_entry *
103 : 34382 : find_attr_url_entry (const char *str,
104 : : size_t str_len,
105 : : const char *target_docs_name)
106 : : {
107 : 223919 : for (size_t table_idx = 0; table_idx < ARRAY_SIZE (attr_url_tables);
108 : : table_idx++)
109 : 194006 : if (const attr_url_entry *entry
110 : 194006 : = find_attr_url_entry (str, str_len, target_docs_name,
111 : 194006 : attr_url_tables[table_idx].m_table,
112 : 194006 : attr_url_tables[table_idx].m_table_sz))
113 : : return entry;
114 : :
115 : : return nullptr;
116 : : }
117 : :
118 : : char *
119 : 17149 : attribute_urlifier::get_url_for_quoted_text (const char *p,
120 : : size_t sz) const
121 : : {
122 : 17149 : label_text url_suffix = get_url_suffix_for_quoted_text (p, sz);
123 : 17149 : if (url_suffix.get ())
124 : 4429 : return make_doc_url (url_suffix.get ());
125 : : return nullptr;
126 : 17149 : }
127 : :
128 : : label_text
129 : 17197 : attribute_urlifier::get_url_suffix_for_quoted_text (const char *p,
130 : : size_t sz) const
131 : : {
132 : : /* Skip any text after a non-identifier character, so that
133 : : e.g. given "access(read_write, 2, 3)" we only compare
134 : : against "access". */
135 : 145822 : for (size_t i = 0; i < sz; i++)
136 : 133150 : if (!ISIDNUM (p[i]))
137 : : {
138 : : /* Truncate to p[0..i). */
139 : : sz = i;
140 : : break;
141 : : }
142 : :
143 : 17197 : if (m_target_docs_name)
144 : 17197 : if (const attr_url_entry *entry
145 : 17197 : = find_attr_url_entry (p, sz, m_target_docs_name))
146 : 12 : return label_text::borrow (entry->m_url_suffix);
147 : :
148 : 17185 : if (const attr_url_entry *entry = find_attr_url_entry (p, sz, nullptr))
149 : 4457 : return label_text::borrow (entry->m_url_suffix);
150 : :
151 : 12728 : return label_text ();
152 : : }
153 : :
154 : : label_text
155 : 48 : attribute_urlifier::get_url_suffix_for_quoted_text (const char *p) const
156 : : {
157 : 48 : return get_url_suffix_for_quoted_text (p, strlen (p));
158 : : }
159 : :
160 : : #if CHECKING_P
161 : :
162 : : namespace selftest {
163 : :
164 : : /* Selftests. */
165 : :
166 : : static void
167 : 4 : test_attribute_urlifier ()
168 : : {
169 : 4 : attribute_urlifier u;
170 : :
171 : 4 : ASSERT_EQ (u.get_url_suffix_for_quoted_text ("").get (), nullptr);
172 : 4 : ASSERT_EQ (u.get_url_suffix_for_quoted_text (")").get (), nullptr);
173 : :
174 : : /* Examples of function attributes. */
175 : 4 : ASSERT_STREQ (u.get_url_suffix_for_quoted_text ("alias").get (),
176 : : "gcc/Common-Function-Attributes.html"
177 : : "#index-alias-function-attribute");
178 : :
179 : 4 : ASSERT_STREQ (u.get_url_suffix_for_quoted_text
180 : : ("access(read_write, 2, 3)").get (),
181 : : "gcc/Common-Function-Attributes.html"
182 : : "#index-access-function-attribute");
183 : :
184 : : /* Example of enumerator attribute. */
185 : 4 : ASSERT_STREQ (u.get_url_suffix_for_quoted_text ("deprecated").get (),
186 : : "gcc/Enumerator-Attributes.html"
187 : : "#index-deprecated-enumerator-attribute");
188 : :
189 : : /* We don't yet have an example of a label attribute, since all
190 : : label attributes have a matching function attribute of the same
191 : : name, which is found first. */
192 : :
193 : : /* Example of statement attribute. */
194 : 4 : ASSERT_STREQ (u.get_url_suffix_for_quoted_text ("assume").get (),
195 : : "gcc/Statement-Attributes.html"
196 : : "#index-assume-statement-attribute");
197 : :
198 : : /* Examples of type attributes. */
199 : 4 : ASSERT_STREQ (u.get_url_suffix_for_quoted_text ("hardbool").get (),
200 : : "gcc/Common-Type-Attributes.html"
201 : : "#index-hardbool-type-attribute");
202 : 4 : ASSERT_STREQ (u.get_url_suffix_for_quoted_text
203 : : ("packed").get (),
204 : : "gcc/Common-Type-Attributes.html"
205 : : "#index-packed-type-attribute");
206 : :
207 : : /* Example of variable attribute. */
208 : 4 : ASSERT_STREQ (u.get_url_suffix_for_quoted_text ("nonstring").get (),
209 : : "gcc/Common-Variable-Attributes.html"
210 : : "#index-nonstring-variable-attribute");
211 : :
212 : : /* Example of target-specific attributes.
213 : : For example, "interrupt" has many target-specific documentation URLs. */
214 : 4 : {
215 : 4 : attribute_urlifier u_rl78 ("RL78");
216 : 4 : attribute_urlifier u_x86 ("x86");
217 : 4 : attribute_urlifier u_unrecognized ("not-a-target");
218 : :
219 : 4 : ASSERT_STREQ (u_rl78.get_url_suffix_for_quoted_text ("interrupt").get (),
220 : : "gcc/RL78-Function-Attributes.html"
221 : : "#index-interrupt-function-attribute_002c-RL78");
222 : 4 : ASSERT_STREQ (u_x86.get_url_suffix_for_quoted_text ("interrupt").get (),
223 : : "gcc/x86-Function-Attributes.html"
224 : : "#index-interrupt-function-attribute_002c-x86");
225 : 4 : ASSERT_STREQ (u_unrecognized.get_url_suffix_for_quoted_text
226 : : ("interrupt").get (),
227 : : "gcc/Common-Function-Attributes.html"
228 : : "#index-interrupt-function-attribute");
229 : 4 : }
230 : 4 : }
231 : :
232 : : /* Run all of the selftests within this file. */
233 : :
234 : : void
235 : 4 : gcc_attribute_urlifier_cc_tests ()
236 : : {
237 : 4 : test_attribute_urlifier ();
238 : 4 : }
239 : :
240 : : } // namespace selftest
241 : :
242 : : #endif /* #if CHECKING_P */
|