2002-09-18 Andrew Cagney <ac131313@redhat.com>
[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
AC
86static const char *symfile_explanations[] = {
87 "During symbol reading, %s.\n",
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
AC
183 if (complaints->explanation == NULL)
184 vwarning (complaint->fmt, args);
185 else
186 {
187 char *msg;
188 struct cleanup *cleanups;
189 xvasprintf (&msg, complaint->fmt, args);
190 cleanups = make_cleanup (xfree, msg);
191 wrap_here ("");
192 if (series != SUBSEQUENT_MESSAGE)
193 begin_line ();
194 fprintf_filtered (gdb_stderr,
195 complaints->explanation[series],
196 msg);
197 wrap_here ("");
198 do_cleanups (cleanups);
199 }
c906108c 200 }
c906108c 201
b9caf505 202 switch (series)
c906108c 203 {
b9caf505 204 case ISOLATED_MESSAGE:
c5aa993b 205 break;
b9caf505
AC
206 case FIRST_MESSAGE:
207 complaints->series = SUBSEQUENT_MESSAGE;
208 break;
209 case SUBSEQUENT_MESSAGE:
210 case SHORT_FIRST_MESSAGE:
211 complaints->series = SUBSEQUENT_MESSAGE;
c5aa993b 212 break;
c906108c 213 }
b9caf505
AC
214
215 /* If GDB dumps core, we'd like to see the complaints first.
216 Presumably GDB will not be sending so many complaints that this
217 becomes a performance hog. */
218
6426a772 219 gdb_flush (gdb_stderr);
b9caf505
AC
220}
221
222void
223complaint (struct complaints **complaints, const char *fmt, ...)
224{
225 va_list args;
226 va_start (args, fmt);
227 vcomplaint (complaints, NULL/*file*/, 0/*line*/, fmt, args);
228 va_end (args);
229}
230
231void
232internal_complaint (struct complaints **complaints, const char *file,
233 int line, const char *fmt, ...)
234{
235 va_list args;
236 va_start (args, fmt);
237 vcomplaint (complaints, file, line, fmt, args);
238 va_end (args);
239}
240
241void
242complain (struct complaint *complaint, ...)
243{
244 va_list args;
245 va_start (args, complaint);
246 vcomplaint (&symfile_complaints, NULL/*file*/, 0/*line*/,
247 complaint->message, args);
c906108c
SS
248 va_end (args);
249}
250
b9caf505
AC
251/* Clear out / initialize all complaint counters that have ever been
252 incremented. If LESS_VERBOSE is 1, be less verbose about
253 successive complaints, since the messages are appearing all
254 together during a command that is reporting a contiguous block of
255 complaints (rather than being interleaved with other messages). If
256 noisy is 1, we are in a noisy command, and our caller will print
257 enough context for the user to figure it out. */
c906108c
SS
258
259void
b9caf505 260clear_complaints (struct complaints **c, int less_verbose, int noisy)
c906108c 261{
b9caf505
AC
262 struct complaints *complaints = get_complaints (c);
263 struct complain *p;
c906108c 264
b9caf505 265 for (p = complaints->root; p != NULL; p = p->next)
c906108c 266 {
c5aa993b 267 p->counter = 0;
c906108c
SS
268 }
269
b9caf505 270 if (complaints->series > 1 && !warning_hook)
c906108c
SS
271 {
272 /* Terminate previous series, since caller won't. */
273 puts_filtered ("\n");
274 }
275
b9caf505
AC
276 if (!less_verbose)
277 complaints->series = ISOLATED_MESSAGE;
278 else if (!noisy)
279 complaints->series = FIRST_MESSAGE;
280 else
281 complaints->series = SHORT_FIRST_MESSAGE;
c906108c
SS
282}
283
284void
fba45db2 285_initialize_complaints (void)
c906108c 286{
b9caf505
AC
287 add_setshow_cmd ("complaints", class_support, var_zinteger,
288 &stop_whining,
289 "Set max number of complaints about incorrect symbols.",
290 "Show max number of complaints about incorrect symbols.",
291 NULL, NULL,
292 &setlist, &showlist);
c906108c
SS
293
294}
This page took 0.230495 seconds and 4 git commands to generate.