1 | /* Default error handlers for CPP Library. |
2 | Copyright (C) 1986-2024 Free Software Foundation, Inc. |
3 | Written by Per Bothner, 1994. |
4 | Based on CCCP program by Paul Rubin, June 1986 |
5 | Adapted to ANSI C, Richard Stallman, Jan 1987 |
6 | |
7 | This program is free software; you can redistribute it and/or modify it |
8 | under the terms of the GNU General Public License as published by the |
9 | Free Software Foundation; either version 3, or (at your option) any |
10 | later version. |
11 | |
12 | This program is distributed in the hope that it will be useful, |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | GNU General Public License for more details. |
16 | |
17 | You should have received a copy of the GNU General Public License |
18 | along with this program; see the file COPYING3. If not see |
19 | <http://www.gnu.org/licenses/>. |
20 | |
21 | In other words, you are welcome to use, share and improve this program. |
22 | You are forbidden to forbid anyone else to use, share and improve |
23 | what you give them. Help stamp out software-hoarding! */ |
24 | |
25 | #include "config.h" |
26 | #include "system.h" |
27 | #include "cpplib.h" |
28 | #include "internal.h" |
29 | |
30 | /* Get a location_t for the current location in PFILE, |
31 | generally that of the previously lexed token. */ |
32 | |
33 | location_t |
34 | cpp_diagnostic_get_current_location (cpp_reader *pfile) |
35 | { |
36 | if (CPP_OPTION (pfile, traditional)) |
37 | { |
38 | if (pfile->state.in_directive) |
39 | return pfile->directive_line; |
40 | else |
41 | return pfile->line_table->highest_line; |
42 | } |
43 | /* We don't want to refer to a token before the beginning of the |
44 | current run -- that is invalid. */ |
45 | else if (pfile->cur_token == pfile->cur_run->base) |
46 | { |
47 | return 0; |
48 | } |
49 | else |
50 | { |
51 | return pfile->cur_token[-1].src_loc; |
52 | } |
53 | } |
54 | |
55 | /* Print a diagnostic at the given location. */ |
56 | |
57 | ATTRIBUTE_FPTR_PRINTF(5,0) |
58 | static bool |
59 | cpp_diagnostic_at (cpp_reader * pfile, enum cpp_diagnostic_level level, |
60 | enum cpp_warning_reason reason, rich_location *richloc, |
61 | const char *msgid, va_list *ap) |
62 | { |
63 | bool ret; |
64 | |
65 | if (!pfile->cb.diagnostic) |
66 | abort (); |
67 | ret = pfile->cb.diagnostic (pfile, level, reason, richloc, _(msgid), ap); |
68 | |
69 | return ret; |
70 | } |
71 | |
72 | /* Print a diagnostic at the location of the previously lexed token. */ |
73 | |
74 | ATTRIBUTE_FPTR_PRINTF(4,0) |
75 | static bool |
76 | cpp_diagnostic (cpp_reader * pfile, enum cpp_diagnostic_level level, |
77 | enum cpp_warning_reason reason, |
78 | const char *msgid, va_list *ap) |
79 | { |
80 | location_t src_loc = cpp_diagnostic_get_current_location (pfile); |
81 | rich_location richloc (pfile->line_table, src_loc); |
82 | return cpp_diagnostic_at (pfile, level, reason, richloc: &richloc, msgid, ap); |
83 | } |
84 | |
85 | /* Print a warning or error, depending on the value of LEVEL. */ |
86 | |
87 | bool |
88 | cpp_error (cpp_reader * pfile, enum cpp_diagnostic_level level, |
89 | const char *msgid, ...) |
90 | { |
91 | va_list ap; |
92 | bool ret; |
93 | |
94 | va_start (ap, msgid); |
95 | |
96 | ret = cpp_diagnostic (pfile, level, reason: CPP_W_NONE, msgid, ap: &ap); |
97 | |
98 | va_end (ap); |
99 | return ret; |
100 | } |
101 | |
102 | /* Print a warning. The warning reason may be given in REASON. */ |
103 | |
104 | bool |
105 | cpp_warning (cpp_reader * pfile, enum cpp_warning_reason reason, |
106 | const char *msgid, ...) |
107 | { |
108 | va_list ap; |
109 | bool ret; |
110 | |
111 | va_start (ap, msgid); |
112 | |
113 | ret = cpp_diagnostic (pfile, level: CPP_DL_WARNING, reason, msgid, ap: &ap); |
114 | |
115 | va_end (ap); |
116 | return ret; |
117 | } |
118 | |
119 | /* Print a pedantic warning. The warning reason may be given in REASON. */ |
120 | |
121 | bool |
122 | cpp_pedwarning (cpp_reader * pfile, enum cpp_warning_reason reason, |
123 | const char *msgid, ...) |
124 | { |
125 | va_list ap; |
126 | bool ret; |
127 | |
128 | va_start (ap, msgid); |
129 | |
130 | ret = cpp_diagnostic (pfile, level: CPP_DL_PEDWARN, reason, msgid, ap: &ap); |
131 | |
132 | va_end (ap); |
133 | return ret; |
134 | } |
135 | |
136 | /* Print a warning, including system headers. The warning reason may be |
137 | given in REASON. */ |
138 | |
139 | bool |
140 | cpp_warning_syshdr (cpp_reader * pfile, enum cpp_warning_reason reason, |
141 | const char *msgid, ...) |
142 | { |
143 | va_list ap; |
144 | bool ret; |
145 | |
146 | va_start (ap, msgid); |
147 | |
148 | ret = cpp_diagnostic (pfile, level: CPP_DL_WARNING_SYSHDR, reason, msgid, ap: &ap); |
149 | |
150 | va_end (ap); |
151 | return ret; |
152 | } |
153 | |
154 | /* As cpp_warning above, but use RICHLOC as the location of the diagnostic. */ |
155 | |
156 | bool cpp_warning_at (cpp_reader *pfile, enum cpp_warning_reason reason, |
157 | rich_location *richloc, const char *msgid, ...) |
158 | { |
159 | va_list ap; |
160 | bool ret; |
161 | |
162 | va_start (ap, msgid); |
163 | |
164 | ret = cpp_diagnostic_at (pfile, level: CPP_DL_WARNING, reason, richloc, |
165 | msgid, ap: &ap); |
166 | |
167 | va_end (ap); |
168 | return ret; |
169 | |
170 | } |
171 | |
172 | /* As cpp_pedwarning above, but use RICHLOC as the location of the |
173 | diagnostic. */ |
174 | |
175 | bool |
176 | cpp_pedwarning_at (cpp_reader * pfile, enum cpp_warning_reason reason, |
177 | rich_location *richloc, const char *msgid, ...) |
178 | { |
179 | va_list ap; |
180 | bool ret; |
181 | |
182 | va_start (ap, msgid); |
183 | |
184 | ret = cpp_diagnostic_at (pfile, level: CPP_DL_PEDWARN, reason, richloc, |
185 | msgid, ap: &ap); |
186 | |
187 | va_end (ap); |
188 | return ret; |
189 | } |
190 | |
191 | /* Print a diagnostic at a specific location. */ |
192 | |
193 | ATTRIBUTE_FPTR_PRINTF(6,0) |
194 | static bool |
195 | cpp_diagnostic_with_line (cpp_reader * pfile, enum cpp_diagnostic_level level, |
196 | enum cpp_warning_reason reason, |
197 | location_t src_loc, unsigned int column, |
198 | const char *msgid, va_list *ap) |
199 | { |
200 | bool ret; |
201 | |
202 | if (!pfile->cb.diagnostic) |
203 | abort (); |
204 | rich_location richloc (pfile->line_table, src_loc); |
205 | if (column) |
206 | richloc.override_column (column); |
207 | ret = pfile->cb.diagnostic (pfile, level, reason, &richloc, _(msgid), ap); |
208 | |
209 | return ret; |
210 | } |
211 | |
212 | /* Print a warning or error, depending on the value of LEVEL. */ |
213 | |
214 | bool |
215 | cpp_error_with_line (cpp_reader *pfile, enum cpp_diagnostic_level level, |
216 | location_t src_loc, unsigned int column, |
217 | const char *msgid, ...) |
218 | { |
219 | va_list ap; |
220 | bool ret; |
221 | |
222 | va_start (ap, msgid); |
223 | |
224 | ret = cpp_diagnostic_with_line (pfile, level, reason: CPP_W_NONE, src_loc, |
225 | column, msgid, ap: &ap); |
226 | |
227 | va_end (ap); |
228 | return ret; |
229 | } |
230 | |
231 | /* Print a warning. The warning reason may be given in REASON. */ |
232 | |
233 | bool |
234 | cpp_warning_with_line (cpp_reader *pfile, enum cpp_warning_reason reason, |
235 | location_t src_loc, unsigned int column, |
236 | const char *msgid, ...) |
237 | { |
238 | va_list ap; |
239 | bool ret; |
240 | |
241 | va_start (ap, msgid); |
242 | |
243 | ret = cpp_diagnostic_with_line (pfile, level: CPP_DL_WARNING, reason, src_loc, |
244 | column, msgid, ap: &ap); |
245 | |
246 | va_end (ap); |
247 | return ret; |
248 | } |
249 | |
250 | /* Print a pedantic warning. The warning reason may be given in REASON. */ |
251 | |
252 | bool |
253 | cpp_pedwarning_with_line (cpp_reader *pfile, enum cpp_warning_reason reason, |
254 | location_t src_loc, unsigned int column, |
255 | const char *msgid, ...) |
256 | { |
257 | va_list ap; |
258 | bool ret; |
259 | |
260 | va_start (ap, msgid); |
261 | |
262 | ret = cpp_diagnostic_with_line (pfile, level: CPP_DL_PEDWARN, reason, src_loc, |
263 | column, msgid, ap: &ap); |
264 | |
265 | va_end (ap); |
266 | return ret; |
267 | } |
268 | |
269 | /* Print a warning, including system headers. The warning reason may be |
270 | given in REASON. */ |
271 | |
272 | bool |
273 | cpp_warning_with_line_syshdr (cpp_reader *pfile, enum cpp_warning_reason reason, |
274 | location_t src_loc, unsigned int column, |
275 | const char *msgid, ...) |
276 | { |
277 | va_list ap; |
278 | bool ret; |
279 | |
280 | va_start (ap, msgid); |
281 | |
282 | ret = cpp_diagnostic_with_line (pfile, level: CPP_DL_WARNING_SYSHDR, reason, src_loc, |
283 | column, msgid, ap: &ap); |
284 | |
285 | va_end (ap); |
286 | return ret; |
287 | } |
288 | |
289 | /* As cpp_error, but use SRC_LOC as the location of the error, without |
290 | a column override. */ |
291 | |
292 | bool |
293 | cpp_error_at (cpp_reader * pfile, enum cpp_diagnostic_level level, |
294 | location_t src_loc, const char *msgid, ...) |
295 | { |
296 | va_list ap; |
297 | bool ret; |
298 | |
299 | va_start (ap, msgid); |
300 | |
301 | rich_location richloc (pfile->line_table, src_loc); |
302 | ret = cpp_diagnostic_at (pfile, level, reason: CPP_W_NONE, richloc: &richloc, |
303 | msgid, ap: &ap); |
304 | |
305 | va_end (ap); |
306 | return ret; |
307 | } |
308 | |
309 | /* As cpp_error, but use RICHLOC as the location of the error, without |
310 | a column override. */ |
311 | |
312 | bool |
313 | cpp_error_at (cpp_reader * pfile, enum cpp_diagnostic_level level, |
314 | rich_location *richloc, const char *msgid, ...) |
315 | { |
316 | va_list ap; |
317 | bool ret; |
318 | |
319 | va_start (ap, msgid); |
320 | |
321 | ret = cpp_diagnostic_at (pfile, level, reason: CPP_W_NONE, richloc, |
322 | msgid, ap: &ap); |
323 | |
324 | va_end (ap); |
325 | return ret; |
326 | } |
327 | |
328 | /* Print a warning or error, depending on the value of LEVEL. Include |
329 | information from errno. */ |
330 | |
331 | bool |
332 | cpp_errno (cpp_reader *pfile, enum cpp_diagnostic_level level, |
333 | const char *msgid) |
334 | { |
335 | return cpp_error (pfile, level, msgid: "%s: %s" , _(msgid), xstrerror (errno)); |
336 | } |
337 | |
338 | /* Print a warning or error, depending on the value of LEVEL. Include |
339 | information from errno. Unlike cpp_errno, the argument is a filename |
340 | that is not localized, but "" is replaced with localized "stdout". */ |
341 | |
342 | bool |
343 | cpp_errno_filename (cpp_reader *pfile, enum cpp_diagnostic_level level, |
344 | const char *filename, |
345 | location_t loc) |
346 | { |
347 | if (filename[0] == '\0') |
348 | filename = _("stdout" ); |
349 | |
350 | return cpp_error_at (pfile, level, src_loc: loc, msgid: "%s: %s" , filename, |
351 | xstrerror (errno)); |
352 | } |
353 | |