Branch data Line data Source code
1 : : /* Automatic generation of links into GCC's documentation.
2 : : Copyright (C) 2023-2024 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 "make-unique.h"
33 : : #include "target.h"
34 : :
35 : : /* class attribute_urlifier : public urlifier. */
36 : :
37 : : /* By default, use the target's documentation name. */
38 : :
39 : 1832723948 : attribute_urlifier::attribute_urlifier ()
40 : 1832723948 : : m_target_docs_name (targetm.documentation_name)
41 : : {
42 : 1832723948 : }
43 : :
44 : : /* Explicitly specify a target's documentation name, for use in selftests. */
45 : :
46 : 12 : attribute_urlifier::attribute_urlifier (const char *target_docs_name)
47 : 12 : : m_target_docs_name (target_docs_name)
48 : : {
49 : 12 : }
50 : :
51 : : struct attr_url_entry
52 : : {
53 : : const char *m_name;
54 : : const char *m_url_suffix;
55 : : const char *m_target_docs_name;
56 : : size_t m_name_len;
57 : : };
58 : :
59 : : #include "attr-urls.def"
60 : :
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. */
63 : :
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. */
68 : :
69 : :
70 : : static const attr_url_entry *
71 : 172488 : 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)
76 : : {
77 : : /* This is linear search, but TABLE_SZ ought not to be very large. */
78 : 10115296 : for (size_t i = 0; i < table_sz; i++)
79 : 9946684 : if (str_len == table[i].m_name_len)
80 : 540656 : if (0 == strncmp (str, table[i].m_name, str_len))
81 : : {
82 : 9808 : if (target_docs_name)
83 : : {
84 : : /* Reject entries with m_target_docs_name that doesn't match. */
85 : 5928 : if (strcmp (target_docs_name, table[i].m_target_docs_name))
86 : 5916 : continue;
87 : : }
88 : : else
89 : : {
90 : : /* Reject entries for which m_target_docs_name is non-empty. */
91 : 3880 : if (table[i].m_target_docs_name[0])
92 : 16 : continue;
93 : : }
94 : : return &table[i];
95 : : }
96 : :
97 : : return nullptr;
98 : : }
99 : :
100 : : /* Search for STR, LEN in all of the attribute tables, in order.
101 : : TARGET_DOCS_NAME works as above. */
102 : :
103 : : static const attr_url_entry *
104 : 30688 : find_attr_url_entry (const char *str,
105 : : size_t str_len,
106 : : const char *target_docs_name)
107 : : {
108 : 199300 : for (size_t table_idx = 0; table_idx < ARRAY_SIZE (attr_url_tables);
109 : : table_idx++)
110 : 172488 : if (const attr_url_entry *entry
111 : 172488 : = find_attr_url_entry (str, str_len, target_docs_name,
112 : 172488 : attr_url_tables[table_idx].m_table,
113 : 172488 : attr_url_tables[table_idx].m_table_sz))
114 : : return entry;
115 : :
116 : : return nullptr;
117 : : }
118 : :
119 : : char *
120 : 15302 : attribute_urlifier::get_url_for_quoted_text (const char *p,
121 : : size_t sz) const
122 : : {
123 : 15302 : label_text url_suffix = get_url_suffix_for_quoted_text (p, sz);
124 : 15302 : if (url_suffix.get ())
125 : 3836 : return make_doc_url (url_suffix.get ());
126 : : return nullptr;
127 : 15302 : }
128 : :
129 : : label_text
130 : 15350 : attribute_urlifier::get_url_suffix_for_quoted_text (const char *p,
131 : : size_t sz) const
132 : : {
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 : 130448 : for (size_t i = 0; i < sz; i++)
137 : 119228 : if (!ISIDNUM (p[i]))
138 : : {
139 : : /* Truncate to p[0..i). */
140 : : sz = i;
141 : : break;
142 : : }
143 : :
144 : 15350 : if (m_target_docs_name)
145 : 15350 : if (const attr_url_entry *entry
146 : 15350 : = find_attr_url_entry (p, sz, m_target_docs_name))
147 : 12 : return label_text::borrow (entry->m_url_suffix);
148 : :
149 : 15338 : if (const attr_url_entry *entry = find_attr_url_entry (p, sz, nullptr))
150 : 3864 : return label_text::borrow (entry->m_url_suffix);
151 : :
152 : 11474 : return label_text ();
153 : : }
154 : :
155 : : label_text
156 : 48 : attribute_urlifier::get_url_suffix_for_quoted_text (const char *p) const
157 : : {
158 : 48 : return get_url_suffix_for_quoted_text (p, strlen (p));
159 : : }
160 : :
161 : : #if CHECKING_P
162 : :
163 : : namespace selftest {
164 : :
165 : : /* Selftests. */
166 : :
167 : : static void
168 : 4 : test_attribute_urlifier ()
169 : : {
170 : 4 : attribute_urlifier u;
171 : :
172 : 4 : ASSERT_EQ (u.get_url_suffix_for_quoted_text ("").get (), nullptr);
173 : 4 : ASSERT_EQ (u.get_url_suffix_for_quoted_text (")").get (), nullptr);
174 : :
175 : : /* Examples of function attributes. */
176 : 4 : ASSERT_STREQ (u.get_url_suffix_for_quoted_text ("alias").get (),
177 : : "gcc/Common-Function-Attributes.html"
178 : : "#index-alias-function-attribute");
179 : :
180 : 4 : 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");
184 : :
185 : : /* Example of enumerator attribute. */
186 : 4 : ASSERT_STREQ (u.get_url_suffix_for_quoted_text ("deprecated").get (),
187 : : "gcc/Enumerator-Attributes.html"
188 : : "#index-deprecated-enumerator-attribute");
189 : :
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. */
193 : :
194 : : /* Example of statement attribute. */
195 : 4 : ASSERT_STREQ (u.get_url_suffix_for_quoted_text ("assume").get (),
196 : : "gcc/Statement-Attributes.html"
197 : : "#index-assume-statement-attribute");
198 : :
199 : : /* Examples of type attributes. */
200 : 4 : ASSERT_STREQ (u.get_url_suffix_for_quoted_text ("hardbool").get (),
201 : : "gcc/Common-Type-Attributes.html"
202 : : "#index-hardbool-type-attribute");
203 : 4 : ASSERT_STREQ (u.get_url_suffix_for_quoted_text
204 : : ("packed").get (),
205 : : "gcc/Common-Type-Attributes.html"
206 : : "#index-packed-type-attribute");
207 : :
208 : : /* Example of variable attribute. */
209 : 4 : ASSERT_STREQ (u.get_url_suffix_for_quoted_text ("nonstring").get (),
210 : : "gcc/Common-Variable-Attributes.html"
211 : : "#index-nonstring-variable-attribute");
212 : :
213 : : /* Example of target-specific attributes.
214 : : For example, "interrupt" has many target-specific documentation URLs. */
215 : 4 : {
216 : 4 : attribute_urlifier u_rl78 ("RL78");
217 : 4 : attribute_urlifier u_x86 ("x86");
218 : 4 : attribute_urlifier u_unrecognized ("not-a-target");
219 : :
220 : 4 : 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 : 4 : 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 : 4 : ASSERT_STREQ (u_unrecognized.get_url_suffix_for_quoted_text
227 : : ("interrupt").get (),
228 : : "gcc/Common-Function-Attributes.html"
229 : : "#index-interrupt-function-attribute");
230 : 4 : }
231 : 4 : }
232 : :
233 : : /* Run all of the selftests within this file. */
234 : :
235 : : void
236 : 4 : gcc_attribute_urlifier_cc_tests ()
237 : : {
238 : 4 : test_attribute_urlifier ();
239 : 4 : }
240 : :
241 : : } // namespace selftest
242 : :
243 : : #endif /* #if CHECKING_P */
|