* gdb/fileio.h: New file.
[deliverable/binutils-gdb.git] / gdb / complaints.c
CommitLineData
c906108c 1/* Support for complaint handling during symbol reading in GDB.
b9caf505
AC
2
3 Copyright 1990, 1991, 1992, 1993, 1995, 1998, 1999, 2000, 2002 Free
4 Software Foundation, Inc.
c906108c 5
c5aa993b 6 This file is part of GDB.
c906108c 7
c5aa993b
JM
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
c906108c 12
c5aa993b
JM
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
c906108c 17
c5aa993b
JM
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
c906108c
SS
22
23#include "defs.h"
24#include "complaints.h"
b9caf505
AC
25#include "gdb_assert.h"
26#include "command.h"
c906108c
SS
27#include "gdbcmd.h"
28
a14ed312 29extern void _initialize_complaints (void);
392a587b 30
b9caf505
AC
31/* Should each complaint message be self explanatory, or should we assume that
32 a series of complaints is being produced? */
33
34/* case 1: First message of a series that must
35 start off with explanation. case 2: Subsequent message of a series
36 that needs no explanation (the user already knows we have a problem
37 so we can just state our piece). */
38enum complaint_series {
39 /* Isolated self explanatory message. */
40 ISOLATED_MESSAGE,
41 /* First message of a series, includes an explanation. */
42 FIRST_MESSAGE,
43 /* First message of a series, but does not need to include any sort
44 of explanation. */
45 SHORT_FIRST_MESSAGE,
46 /* Subsequent message of a series that needs no explanation (the
47 user already knows we have a problem so we can just state our
48 piece). */
49 SUBSEQUENT_MESSAGE
50};
51
c906108c
SS
52/* Structure to manage complaints about symbol file contents. */
53
b9caf505 54struct complain
c5aa993b 55{
b9caf505
AC
56 const char *file;
57 int line;
58 const char *fmt;
59 int counter;
60 struct complain *next;
c906108c
SS
61};
62
b9caf505
AC
63struct complaints
64{
65 struct complain *root;
c906108c 66
b9caf505
AC
67 /* Should each complaint be self explanatory, or should we assume
68 that a series of complaints is being produced? case 0: Isolated
69 self explanatory message. case 1: First message of a series that
70 must start off with explanation. case 2: Subsequent message of a
71 series that needs no explanation (the user already knows we have
72 a problem so we can just state our piece). */
73 int series;
c906108c 74
b9caf505
AC
75 /* The explanatory messages that should accompany the complaint.
76 NOTE: cagney/2002-08-14: In a desperate attempt at being vaguely
77 i18n friendly, this is an array of two messages. When present,
78 EXPLANATION[SERIES] is used to wrap the message. */
79 const char **explanation;
80};
c906108c 81
b9caf505 82static struct complain complaint_sentinel;
c906108c 83
b9caf505 84/* The symbol table complaint table. */
c5aa993b 85
b9caf505 86static const char *symfile_explanations[] = {
cc3b68a5 87 "During symbol reading, %s.",
b9caf505
AC
88 "During symbol reading...%s...",
89 "%s...",
90 "%s...",
91 NULL
92};
c906108c 93
b9caf505
AC
94static struct complaints symfile_complaint_book = {
95 &complaint_sentinel,
96 0,
97 symfile_explanations
98};
99struct complaints *symfile_complaints = &symfile_complaint_book;
c906108c 100
b9caf505
AC
101/* Wrapper function to, on-demand, fill in a complaints object. */
102
103static struct complaints *
104get_complaints (struct complaints **c)
c906108c 105{
b9caf505
AC
106 if ((*c) != NULL)
107 return (*c);
108 (*c) = XMALLOC (struct complaints);
109 (*c)->root = &complaint_sentinel;
110 (*c)->series = ISOLATED_MESSAGE;
111 (*c)->explanation = NULL;
112 return (*c);
113}
c906108c 114
b9caf505
AC
115static struct complain *
116find_complaint (struct complaints *complaints, const char *file,
117 int line, const char *fmt)
118{
119 struct complain *complaint;
120
121 /* Find the complaint in the table. A more efficient search
122 algorithm (based on hash table or something) could be used. But
123 that can wait until someone shows evidence that this lookup is
124 a real bottle neck. */
125 for (complaint = complaints->root;
126 complaint != NULL;
127 complaint = complaint->next)
c906108c 128 {
b9caf505
AC
129 if (complaint->fmt == fmt
130 && complaint->file == file
131 && complaint->line == line)
132 return complaint;
c906108c 133 }
b9caf505
AC
134
135 /* Oops not seen before, fill in a new complaint. */
136 complaint = XMALLOC (struct complain);
137 complaint->fmt = fmt;
138 complaint->file = file;
139 complaint->line = line;
140 complaint->counter = 0;
141 complaint->next = NULL;
142
143 /* File it, return it. */
144 complaint->next = complaints->root;
145 complaints->root = complaint;
146 return complaint;
147}
148
149
150/* How many complaints about a particular thing should be printed
151 before we stop whining about it? Default is no whining at all,
152 since so many systems have ill-constructed symbol files. */
153
154static unsigned int stop_whining = 0;
155
156/* Print a complaint, and link the complaint block into a chain for
157 later handling. */
158
159static void
160vcomplaint (struct complaints **c, const char *file, int line, const char *fmt,
161 va_list args)
162{
163 struct complaints *complaints = get_complaints (c);
164 struct complain *complaint = find_complaint (complaints, file, line, fmt);
165 enum complaint_series series;
166 gdb_assert (complaints != NULL);
167
168 complaint->counter++;
c5aa993b 169 if (complaint->counter > stop_whining)
b9caf505
AC
170 return;
171
172 if (info_verbose)
173 series = SUBSEQUENT_MESSAGE;
174 else
175 series = complaints->series;
176
177 if (complaint->file != NULL)
178 internal_vwarning (complaint->file, complaint->line, complaint->fmt, args);
179 else if (warning_hook)
180 (*warning_hook) (complaint->fmt, args);
181 else
c906108c 182 {
b9caf505 183 if (complaints->explanation == NULL)
cc3b68a5 184 /* A [v]warning() call always appends a newline. */
b9caf505
AC
185 vwarning (complaint->fmt, args);
186 else
187 {
188 char *msg;
189 struct cleanup *cleanups;
190 xvasprintf (&msg, complaint->fmt, args);
191 cleanups = make_cleanup (xfree, msg);
192 wrap_here ("");
193 if (series != SUBSEQUENT_MESSAGE)
194 begin_line ();
195 fprintf_filtered (gdb_stderr,
196 complaints->explanation[series],
197 msg);
cc3b68a5
AC
198 /* Force a line-break after any isolated message. For the
199 other cases, clear_complaints() takes care of any missing
200 trailing newline, the wrap_here() is just a hint. */
201 if (series == ISOLATED_MESSAGE)
202 /* It would be really nice to use begin_line() here.
203 Unfortunatly that function doesn't track GDB_STDERR and
204 consequently will sometimes supress a line when it
205 shouldn't. */
206 fputs_filtered ("\n", gdb_stderr);
207 else
208 wrap_here ("");
b9caf505
AC
209 do_cleanups (cleanups);
210 }
c906108c 211 }
c906108c 212
b9caf505 213 switch (series)
c906108c 214 {
b9caf505 215 case ISOLATED_MESSAGE:
c5aa993b 216 break;
b9caf505
AC
217 case FIRST_MESSAGE:
218 complaints->series = SUBSEQUENT_MESSAGE;
219 break;
220 case SUBSEQUENT_MESSAGE:
221 case SHORT_FIRST_MESSAGE:
222 complaints->series = SUBSEQUENT_MESSAGE;
c5aa993b 223 break;
c906108c 224 }
b9caf505
AC
225
226 /* If GDB dumps core, we'd like to see the complaints first.
227 Presumably GDB will not be sending so many complaints that this
228 becomes a performance hog. */
229
6426a772 230 gdb_flush (gdb_stderr);
b9caf505
AC
231}
232
233void
234complaint (struct complaints **complaints, const char *fmt, ...)
235{
236 va_list args;
237 va_start (args, fmt);
238 vcomplaint (complaints, NULL/*file*/, 0/*line*/, fmt, args);
239 va_end (args);
240}
241
242void
243internal_complaint (struct complaints **complaints, const char *file,
244 int line, const char *fmt, ...)
245{
246 va_list args;
247 va_start (args, fmt);
248 vcomplaint (complaints, file, line, fmt, args);
249 va_end (args);
250}
251
b9caf505
AC
252/* Clear out / initialize all complaint counters that have ever been
253 incremented. If LESS_VERBOSE is 1, be less verbose about
254 successive complaints, since the messages are appearing all
255 together during a command that is reporting a contiguous block of
256 complaints (rather than being interleaved with other messages). If
257 noisy is 1, we are in a noisy command, and our caller will print
258 enough context for the user to figure it out. */
c906108c
SS
259
260void
b9caf505 261clear_complaints (struct complaints **c, int less_verbose, int noisy)
c906108c 262{
b9caf505
AC
263 struct complaints *complaints = get_complaints (c);
264 struct complain *p;
c906108c 265
b9caf505 266 for (p = complaints->root; p != NULL; p = p->next)
c906108c 267 {
c5aa993b 268 p->counter = 0;
c906108c
SS
269 }
270
cc3b68a5 271 switch (complaints->series)
c906108c 272 {
cc3b68a5
AC
273 case FIRST_MESSAGE:
274 /* Haven't yet printed anything. */
275 break;
276 case SHORT_FIRST_MESSAGE:
277 /* Haven't yet printed anything. */
278 break;
279 case ISOLATED_MESSAGE:
280 /* The code above, always forces a line-break. No need to do it
281 here. */
282 break;
283 case SUBSEQUENT_MESSAGE:
284 /* It would be really nice to use begin_line() here.
285 Unfortunatly that function doesn't track GDB_STDERR and
286 consequently will sometimes supress a line when it shouldn't. */
287 fputs_unfiltered ("\n", gdb_stderr);
288 break;
289 default:
290 internal_error (__FILE__, __LINE__, "bad switch");
c906108c
SS
291 }
292
b9caf505
AC
293 if (!less_verbose)
294 complaints->series = ISOLATED_MESSAGE;
295 else if (!noisy)
296 complaints->series = FIRST_MESSAGE;
297 else
298 complaints->series = SHORT_FIRST_MESSAGE;
c906108c
SS
299}
300
301void
fba45db2 302_initialize_complaints (void)
c906108c 303{
b9caf505
AC
304 add_setshow_cmd ("complaints", class_support, var_zinteger,
305 &stop_whining,
306 "Set max number of complaints about incorrect symbols.",
307 "Show max number of complaints about incorrect symbols.",
308 NULL, NULL,
309 &setlist, &showlist);
c906108c
SS
310
311}
This page took 0.238025 seconds and 4 git commands to generate.