1/* Declaration for error-reporting function for Bison.
2
3   Copyright (C) 2000-2002, 2004-2006, 2009-2012 Free Software
4   Foundation, Inc.
5
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.
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
17   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18
19/* Based on error.c and error.h,
20   written by David MacKenzie <djm@gnu.ai.mit.edu>.  */
21
22#include <config.h>
23#include "system.h"
24
25#include <stdarg.h>
26#include <progname.h>
27
28#include "complain.h"
29#include "files.h"
30#include "getargs.h"
31
32bool complaint_issued;
33static unsigned *indent_ptr = 0;
34
35
36
37/** Report an error message.
38 *
39 * \param loc     the location, defaulting to the current file,
40 *                or the program name.
41 * \param prefix  put before the message (e.g., "warning").
42 * \param message the error message, a printf format string.  Iff it
43 *                ends with ": ", then no trailing newline is printed,
44 *                and the caller should print the remaining
45 *                newline-terminated message to stderr.
46 * \param args    the arguments of the format string.
47 */
48static
49void
50error_message (location *loc,
51	       const char *prefix,
52	       const char *message, va_list args)
53{
54  unsigned pos = 0;
55
56  if (loc)
57    pos += location_print (stderr, *loc);
58  else
59    pos += fprintf(stderr, "%s", current_file ? current_file : program_name);
60  pos += fprintf(stderr, ": ");
61
62  if (indent_ptr)
63    {
64      if (!*indent_ptr)
65        *indent_ptr = pos;
66      else if (*indent_ptr > pos)
67        fprintf (stderr, "%*s", *indent_ptr - pos, "");
68      indent_ptr = 0;
69    }
70
71  if (prefix)
72    fprintf (stderr, "%s: ", prefix);
73
74  vfprintf (stderr, message, args);
75  {
76    size_t l = strlen (message);
77    if (l < 2 || message[l - 2] != ':' || message[l - 1] != ' ')
78      {
79        putc ('\n', stderr);
80        fflush (stderr);
81        if (loc && feature_flag & feature_caret)
82          location_caret (stderr, *loc);
83      }
84  }
85  fflush (stderr);
86}
87
88/** Wrap error_message() with varargs handling. */
89#define ERROR_MESSAGE(Loc, Prefix, Message)	\
90{						\
91  va_list args;					\
92  va_start (args, Message);			\
93  error_message (Loc, Prefix, Message, args);	\
94  va_end (args);				\
95}
96
97
98/*--------------------------------.
99| Report a warning, and proceed.  |
100`--------------------------------*/
101
102void
103set_warning_issued (void)
104{
105  static bool warning_issued = false;
106  if (!warning_issued && (warnings_flag & warnings_error))
107    {
108      fprintf (stderr, "%s: warnings being treated as errors\n", program_name);
109      complaint_issued = true;
110    }
111  warning_issued = true;
112}
113
114void
115warn_at (location loc, const char *message, ...)
116{
117  if (!(warnings_flag & warnings_other))
118    return;
119  set_warning_issued ();
120  ERROR_MESSAGE (&loc, _("warning"), message);
121}
122
123void
124warn_at_indent (location loc, unsigned *indent,
125                const char *message, ...)
126{
127  if (!(warnings_flag & warnings_other))
128    return;
129  set_warning_issued ();
130  indent_ptr = indent;
131  ERROR_MESSAGE (&loc, *indent ? NULL : _("warning"), message);
132}
133
134void
135warn (const char *message, ...)
136{
137  if (!(warnings_flag & warnings_other))
138    return;
139  set_warning_issued ();
140  ERROR_MESSAGE (NULL, _("warning"), message);
141}
142
143
144/*-----------------------------------------------------------.
145| An error has occurred, but we can proceed, and die later.  |
146`-----------------------------------------------------------*/
147
148void
149complain_at (location loc, const char *message, ...)
150{
151  ERROR_MESSAGE (&loc, _("error"), message);
152  complaint_issued = true;
153}
154
155void
156complain_at_indent (location loc, unsigned *indent,
157                    const char *message, ...)
158{
159  indent_ptr = indent;
160  ERROR_MESSAGE (&loc, *indent ? NULL : _("error"), message);
161  complaint_issued = true;
162}
163
164void
165complain (const char *message, ...)
166{
167  ERROR_MESSAGE (NULL, _("error"), message);
168  complaint_issued = true;
169}
170
171
172/*--------------------------------------------------------------.
173| An incompatibility with POSIX Yacc: mapped either to warn* or |
174| complain* depending on yacc_flag.                             |
175`--------------------------------------------------------------*/
176
177void
178yacc_at (location loc, const char *message, ...)
179{
180  if (yacc_flag)
181    {
182      ERROR_MESSAGE (&loc, NULL, message);
183      complaint_issued = true;
184    }
185  else if (warnings_flag & warnings_yacc)
186    {
187      set_warning_issued ();
188      ERROR_MESSAGE (&loc, _("warning"), message);
189    }
190}
191
192void
193midrule_value_at (location loc, const char *message, ...)
194{
195  if (!(warnings_flag & warnings_midrule_values))
196    return;
197  set_warning_issued ();
198  ERROR_MESSAGE (&loc, _("warning"), message);
199}
200
201/*-------------------------------------------------.
202| A severe error has occurred, we cannot proceed.  |
203`-------------------------------------------------*/
204
205void
206fatal_at (location loc, const char *message, ...)
207{
208  ERROR_MESSAGE (&loc, _("fatal error"), message);
209  exit (EXIT_FAILURE);
210}
211
212void
213fatal (const char *message, ...)
214{
215  ERROR_MESSAGE (NULL, _("fatal error"), message);
216  exit (EXIT_FAILURE);
217}
218