]> git.saurik.com Git - bison.git/blame - src/complain.c
version 3.0
[bison.git] / src / complain.c
CommitLineData
a0f6b076 1/* Declaration for error-reporting function for Bison.
2cec9080 2
7d6bad19 3 Copyright (C) 2000-2002, 2004-2006, 2009-2013 Free Software
575619af 4 Foundation, Inc.
a0f6b076 5
f16b0819
PE
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
a0f6b076
AD
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
f16b0819 17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
a0f6b076
AD
18
19/* Based on error.c and error.h,
20 written by David MacKenzie <djm@gnu.ai.mit.edu>. */
21
2cec9080 22#include <config.h>
342b8b6e 23#include "system.h"
a0f6b076 24
12bc1c9e 25#include <argmatch.h>
21184140 26#include <stdarg.h>
4d699f44 27#include <progname.h>
a0f6b076 28
a0f6b076 29#include "complain.h"
4b68955b 30#include "files.h"
89eb3c76 31#include "getargs.h"
1dc927a7 32#include "quote.h"
a0f6b076 33
808e523d 34err_status complaint_status = status_none;
d0f11c1b 35
808e523d 36bool warnings_are_errors = false;
12bc1c9e
AD
37
38/** Diagnostics severity. */
39typedef enum
40 {
41 severity_disabled = 0,
42 severity_unset = 1,
43 severity_warning = 2,
44 severity_error = 3,
45 severity_fatal = 4
46 } severity;
47
48
49/** For each warning type, its severity. */
50static severity warnings_flag[warnings_size];
9503b0a4 51
66381412 52static unsigned *indent_ptr = 0;
12bc1c9e
AD
53
54/*------------------------.
55| --warnings's handling. |
56`------------------------*/
57
58static const char * const warnings_args[] =
59{
60 "none",
61 "midrule-values",
62 "yacc",
63 "conflicts-sr",
64 "conflicts-rr",
65 "deprecated",
f68a49ed 66 "empty-rule",
12bc1c9e
AD
67 "precedence",
68 "other",
69 "all",
70 "error",
f24695ef 71 "everything",
12bc1c9e
AD
72 0
73};
74
75static const int warnings_types[] =
76{
77 Wnone,
78 Wmidrule_values,
79 Wyacc,
80 Wconflicts_sr,
81 Wconflicts_rr,
82 Wdeprecated,
f68a49ed 83 Wempty_rule,
12bc1c9e
AD
84 Wprecedence,
85 Wother,
86 Wall,
f24695ef
AD
87 Werror,
88 Weverything
12bc1c9e
AD
89};
90
91ARGMATCH_VERIFY (warnings_args, warnings_types);
92
93void
94warning_argmatch (char const *arg, size_t no, size_t err)
95{
96 int value = XARGMATCH ("--warning", arg + no + err,
97 warnings_args, warnings_types);
98
f24695ef 99 /* -Wnone == -Wno-everything, and -Wno-none == -Weverything. */
12bc1c9e
AD
100 if (!value)
101 {
f24695ef 102 value = Weverything;
12bc1c9e
AD
103 no = !no;
104 }
105
106 if (no)
107 {
108 size_t b;
109 for (b = 0; b < warnings_size; ++b)
110 if (value & 1 << b)
111 {
112 if (err)
113 {
114 /* -Wno-error=foo: if foo enabled as an error,
115 make it a warning. */
116 if (warnings_flag[b] == severity_error)
117 warnings_flag[b] = severity_warning;
118 }
119 else
120 /* -Wno-foo. */
121 warnings_flag[b] = severity_disabled;
122 }
123 }
124 else
125 {
126 size_t b;
127 for (b = 0; b < warnings_size; ++b)
128 if (value & 1 << b)
129 /* -Wfoo and -Werror=foo. */
130 warnings_flag[b] = err ? severity_error : severity_warning;
131 }
132}
133
134/** Decode a comma-separated list of arguments from -W.
135 *
136 * \param args comma separated list of effective subarguments to decode.
137 * If 0, then activate all the flags.
138 */
139
140void
141warnings_argmatch (char *args)
142{
143 if (args)
144 for (args = strtok (args, ","); args; args = strtok (NULL, ","))
145 if (STREQ (args, "error"))
146 warnings_are_errors = true;
147 else if (STREQ (args, "no-error"))
148 {
149 warnings_are_errors = false;
f24695ef 150 warning_argmatch ("no-error=everything", 3, 6);
12bc1c9e
AD
151 }
152 else
153 {
154 size_t no = STRPREFIX_LIT ("no-", args) ? 3 : 0;
155 size_t err = STRPREFIX_LIT ("error=", args + no) ? 6 : 0;
156
157 warning_argmatch (args, no, err);
158 }
159 else
160 warning_argmatch ("all", 0, 0);
161}
162
163
164/*-----------.
165| complain. |
166`-----------*/
a0f6b076 167
808e523d
AD
168void
169complain_init (void)
170{
171 warnings warnings_default =
172 Wconflicts_sr | Wconflicts_rr | Wdeprecated | Wother;
173
174 size_t b;
175 for (b = 0; b < warnings_size; ++b)
176 warnings_flag[b] = (1 << b & warnings_default
177 ? severity_warning
178 : severity_unset);
179}
180
181static severity
182warning_severity (warnings flags)
183{
184 if (flags & fatal)
185 return severity_fatal;
186 else if (flags & complaint)
187 return severity_error;
188 else
189 {
190 severity res = severity_disabled;
191 size_t b;
192 for (b = 0; b < warnings_size; ++b)
193 if (flags & 1 << b)
194 res = res < warnings_flag[b] ? warnings_flag[b] : res;
195 if (res == severity_warning && warnings_are_errors)
196 res = severity_error;
197 return res;
198 }
199}
200
42d101da
AD
201bool
202warning_is_unset (warnings flags)
203{
204 size_t b;
205 for (b = 0; b < warnings_size; ++b)
206 if (flags & 1 << b && warnings_flag[b] != severity_unset)
207 return false;
208 return true;
209}
808e523d 210
219458e2
AD
211/** Display a "[-Wyacc]" like message on \a f. */
212
213static void
214warnings_print_categories (warnings warn_flags, FILE *f)
b6403170 215{
219458e2 216 /* Display only the first match, the second is "-Wall". */
808e523d 217 size_t i;
219458e2
AD
218 for (i = 0; warnings_args[i]; ++i)
219 if (warn_flags & warnings_types[i])
220 {
808e523d
AD
221 severity s = warning_severity (warnings_types[i]);
222 fprintf (f, " [-W%s%s]",
223 s == severity_error ? "error=" : "",
224 warnings_args[i]);
225 return;
219458e2 226 }
b6403170 227}
a0f6b076 228
23eb2a69
AD
229/** Report an error message.
230 *
231 * \param loc the location, defaulting to the current file,
232 * or the program name.
6fb8b256 233 * \param flags the category for this message.
23eb2a69 234 * \param prefix put before the message (e.g., "warning").
2bfcac9a
JD
235 * \param message the error message, a printf format string. Iff it
236 * ends with ": ", then no trailing newline is printed,
237 * and the caller should print the remaining
238 * newline-terminated message to stderr.
23eb2a69
AD
239 * \param args the arguments of the format string.
240 */
241static
e9955c83 242void
6fb8b256 243error_message (const location *loc, warnings flags, const char *prefix,
e9690142 244 const char *message, va_list args)
e9955c83 245{
66381412
AR
246 unsigned pos = 0;
247
23eb2a69 248 if (loc)
b805eca7 249 pos += location_print (*loc, stderr);
23eb2a69 250 else
46b7d74c
TR
251 pos += fprintf (stderr, "%s", current_file ? current_file : program_name);
252 pos += fprintf (stderr, ": ");
66381412
AR
253
254 if (indent_ptr)
255 {
a686f6cd
TR
256 if (*indent_ptr)
257 prefix = NULL;
66381412
AR
258 if (!*indent_ptr)
259 *indent_ptr = pos;
260 else if (*indent_ptr > pos)
261 fprintf (stderr, "%*s", *indent_ptr - pos, "");
262 indent_ptr = 0;
263 }
e9955c83 264
23eb2a69
AD
265 if (prefix)
266 fprintf (stderr, "%s: ", prefix);
267
52489d44 268 vfprintf (stderr, message, args);
219458e2
AD
269 if (! (flags & silent))
270 warnings_print_categories (flags, stderr);
2bfcac9a
JD
271 {
272 size_t l = strlen (message);
3f5d1b2c 273 if (l < 2 || message[l - 2] != ':' || message[l - 1] != ' ')
aed41cf9
AD
274 {
275 putc ('\n', stderr);
276 fflush (stderr);
ea9e670d 277 if (loc && feature_flag & feature_caret && !(flags & no_caret))
b805eca7 278 location_caret (*loc, stderr);
aed41cf9 279 }
2bfcac9a 280 }
3f5d1b2c 281 fflush (stderr);
23eb2a69
AD
282}
283
808e523d 284/** Raise a complaint. That can be a fatal error, an error or just a
6fb8b256 285 warning. */
808e523d
AD
286
287static void
6fb8b256
VS
288complains (const location *loc, warnings flags, const char *message,
289 va_list args)
89eb3c76 290{
808e523d 291 severity s = warning_severity (flags);
697a8022
TR
292 if ((flags & complaint) && complaint_status < status_complaint)
293 complaint_status = status_complaint;
808e523d
AD
294
295 if (severity_warning <= s)
296 {
297 const char* prefix =
298 s == severity_fatal ? _("fatal error")
299 : s == severity_error ? _("error")
300 : _("warning");
301 if (severity_error <= s && ! complaint_status)
302 complaint_status = status_warning_as_error;
303 error_message (loc, flags, prefix, message, args);
304 }
305
1048a1c9 306 if (flags & fatal)
a686f6cd 307 exit (EXIT_FAILURE);
66381412
AR
308}
309
52489d44 310void
b999409e 311complain (location const *loc, warnings flags, const char *message, ...)
52489d44 312{
6fb8b256
VS
313 va_list args;
314 va_start (args, message);
bb8e56ff 315 complains (loc, flags, message, args);
6fb8b256 316 va_end (args);
23eb2a69 317}
52489d44 318
e9955c83 319void
b999409e
TR
320complain_indent (location const *loc, warnings flags, unsigned *indent,
321 const char *message, ...)
e9955c83 322{
6fb8b256 323 va_list args;
66381412 324 indent_ptr = indent;
6fb8b256 325 va_start (args, message);
b999409e 326 complains (loc, flags, message, args);
6fb8b256 327 va_end (args);
e9955c83 328}
782e8187
TR
329
330void
c6c8de16
TR
331complain_args (location const *loc, warnings w, unsigned *indent,
332 int argc, char *argv[])
782e8187
TR
333{
334 switch (argc)
335 {
f60321dc
TR
336 case 1:
337 complain_indent (loc, w, indent, "%s", _(argv[0]));
338 break;
782e8187 339 case 2:
f60321dc 340 complain_indent (loc, w, indent, _(argv[0]), argv[1]);
782e8187
TR
341 break;
342 case 3:
f60321dc 343 complain_indent (loc, w, indent, _(argv[0]), argv[1], argv[2]);
782e8187
TR
344 break;
345 case 4:
f60321dc 346 complain_indent (loc, w, indent, _(argv[0]), argv[1], argv[2], argv[3]);
782e8187
TR
347 break;
348 case 5:
f60321dc
TR
349 complain_indent (loc, w, indent, _(argv[0]), argv[1], argv[2], argv[3],
350 argv[4]);
782e8187
TR
351 break;
352 default:
353 complain (loc, fatal, "too many arguments for complains");
354 break;
355 }
1dc927a7
AD
356}
357
358void
359deprecated_directive (location const *loc, char const *old, char const *upd)
360{
361 if (feature_flag & feature_caret)
362 complain (loc, Wdeprecated,
363 _("deprecated directive, use %s"),
364 quote_n (1, upd));
365 else
366 complain (loc, Wdeprecated,
367 _("deprecated directive: %s, use %s"),
368 quote (old), quote_n (1, upd));
782e8187 369}
0fe5a72a
AD
370
371void
372duplicate_directive (char const *directive,
373 location first, location second)
374{
375 unsigned i = 0;
376 complain (&second, complaint, _("only one %s allowed per rule"), directive);
377 i += SUB_INDENT;
378 complain_indent (&first, complaint, &i, _("previous declaration"));
379}