GDB (xrefs)
/tmp/gdb-7.10/gdb/complaints.c
Go to the documentation of this file.
1 /* Support for complaint handling during symbol reading in GDB.
2 
3  Copyright (C) 1990-2015 Free Software Foundation, Inc.
4 
5  This file is part of GDB.
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 3 of the License, or
10  (at your option) any 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. If not, see <http://www.gnu.org/licenses/>. */
19 
20 #include "defs.h"
21 #include "complaints.h"
22 #include "command.h"
23 #include "gdbcmd.h"
24 
25 extern void _initialize_complaints (void);
26 
27 /* Should each complaint message be self explanatory, or should we
28  assume that a series of complaints is being produced? */
29 
30 /* case 1: First message of a series that must
31  start off with explanation. case 2: Subsequent message of a series
32  that needs no explanation (the user already knows we have a problem
33  so we can just state our piece). */
35  /* Isolated self explanatory message. */
37  /* First message of a series, includes an explanation. */
39  /* First message of a series, but does not need to include any sort
40  of explanation. */
42  /* Subsequent message of a series that needs no explanation (the
43  user already knows we have a problem so we can just state our
44  piece). */
46 };
47 
48 /* Structure to manage complaints about symbol file contents. */
49 
50 struct complain
51 {
52  const char *file;
53  int line;
54  const char *fmt;
55  int counter;
56  struct complain *next;
57 };
58 
59 /* The explanatory message that should accompany the complaint. The
60  message is in two parts - pre and post - that are printed around
61  the complaint text. */
63 {
64  const char *prefix;
65  const char *postfix;
66 };
67 
68 struct complaints
69 {
70  struct complain *root;
71 
72  /* Should each complaint be self explanatory, or should we assume
73  that a series of complaints is being produced? case 0: Isolated
74  self explanatory message. case 1: First message of a series that
75  must start off with explanation. case 2: Subsequent message of a
76  series that needs no explanation (the user already knows we have
77  a problem so we can just state our piece). */
78  int series;
79 
80  /* The explanatory messages that should accompany the complaint.
81  NOTE: cagney/2002-08-14: In a desperate attempt at being vaguely
82  i18n friendly, this is an array of two messages. When present,
83  the PRE and POST EXPLANATION[SERIES] are used to wrap the
84  message. */
85  const struct explanation *explanation;
86 };
87 
89 
90 /* The symbol table complaint table. */
91 
92 static struct explanation symfile_explanations[] = {
93  { "During symbol reading, ", "." },
94  { "During symbol reading...", "..."},
95  { "", "..."},
96  { "", "..."},
97  { NULL, NULL }
98 };
99 
100 static struct complaints symfile_complaint_book = {
102  0,
103  symfile_explanations
104 };
105 struct complaints *symfile_complaints = &symfile_complaint_book;
106 
107 /* Wrapper function to, on-demand, fill in a complaints object. */
108 
109 static struct complaints *
111 {
112  if ((*c) != NULL)
113  return (*c);
114  (*c) = XNEW (struct complaints);
115  (*c)->root = &complaint_sentinel;
116  (*c)->series = ISOLATED_MESSAGE;
117  (*c)->explanation = NULL;
118  return (*c);
119 }
120 
121 static struct complain * ATTRIBUTE_PRINTF (4, 0)
122 find_complaint (struct complaints *complaints, const char *file,
123  int line, const char *fmt)
124 {
125  struct complain *complaint;
126 
127  /* Find the complaint in the table. A more efficient search
128  algorithm (based on hash table or something) could be used. But
129  that can wait until someone shows evidence that this lookup is
130  a real bottle neck. */
131  for (complaint = complaints->root;
132  complaint != NULL;
133  complaint = complaint->next)
134  {
135  if (complaint->fmt == fmt
136  && complaint->file == file
137  && complaint->line == line)
138  return complaint;
139  }
140 
141  /* Oops not seen before, fill in a new complaint. */
142  complaint = XNEW (struct complain);
143  complaint->fmt = fmt;
144  complaint->file = file;
145  complaint->line = line;
146  complaint->counter = 0;
147  complaint->next = NULL;
148 
149  /* File it, return it. */
150  complaint->next = complaints->root;
151  complaints->root = complaint;
152  return complaint;
153 }
154 
155 
156 /* How many complaints about a particular thing should be printed
157  before we stop whining about it? Default is no whining at all,
158  since so many systems have ill-constructed symbol files. */
159 
160 static int stop_whining = 0;
161 
162 /* Print a complaint, and link the complaint block into a chain for
163  later handling. */
164 
165 static void ATTRIBUTE_PRINTF (4, 0)
166 vcomplaint (struct complaints **c, const char *file,
167  int line, const char *fmt,
168  va_list args)
169 {
170  struct complaints *complaints = get_complaints (c);
171  struct complain *complaint = find_complaint (complaints, file,
172  line, fmt);
173  enum complaint_series series;
174 
175  gdb_assert (complaints != NULL);
176 
177  complaint->counter++;
178  if (complaint->counter > stop_whining)
179  return;
180 
181  if (info_verbose)
182  series = SUBSEQUENT_MESSAGE;
183  else
184  series = complaints->series;
185 
186  /* Pass 'fmt' instead of 'complaint->fmt' to printf-like callees
187  from here on, to avoid "format string is not a string literal"
188  warnings. 'fmt' is this function's printf-format parameter, so
189  the compiler can assume the passed in argument is a literal
190  string somewhere up the call chain. */
191  gdb_assert (complaint->fmt == fmt);
192 
193  if (complaint->file != NULL)
194  internal_vwarning (complaint->file, complaint->line, fmt, args);
195  else if (deprecated_warning_hook)
196  (*deprecated_warning_hook) (fmt, args);
197  else
198  {
199  if (complaints->explanation == NULL)
200  /* A [v]warning() call always appends a newline. */
201  vwarning (fmt, args);
202  else
203  {
204  char *msg;
205  struct cleanup *cleanups;
206  msg = xstrvprintf (fmt, args);
207  cleanups = make_cleanup (xfree, msg);
208  wrap_here ("");
209  if (series != SUBSEQUENT_MESSAGE)
210  begin_line ();
211  /* XXX: i18n */
212  fprintf_filtered (gdb_stderr, "%s%s%s",
213  complaints->explanation[series].prefix, msg,
214  complaints->explanation[series].postfix);
215  /* Force a line-break after any isolated message. For the
216  other cases, clear_complaints() takes care of any missing
217  trailing newline, the wrap_here() is just a hint. */
218  if (series == ISOLATED_MESSAGE)
219  /* It would be really nice to use begin_line() here.
220  Unfortunately that function doesn't track GDB_STDERR and
221  consequently will sometimes supress a line when it
222  shouldn't. */
223  fputs_filtered ("\n", gdb_stderr);
224  else
225  wrap_here ("");
226  do_cleanups (cleanups);
227  }
228  }
229 
230  switch (series)
231  {
232  case ISOLATED_MESSAGE:
233  break;
234  case FIRST_MESSAGE:
235  complaints->series = SUBSEQUENT_MESSAGE;
236  break;
237  case SUBSEQUENT_MESSAGE:
238  case SHORT_FIRST_MESSAGE:
239  complaints->series = SUBSEQUENT_MESSAGE;
240  break;
241  }
242 
243  /* If GDB dumps core, we'd like to see the complaints first.
244  Presumably GDB will not be sending so many complaints that this
245  becomes a performance hog. */
246 
248 }
249 
250 void
251 complaint (struct complaints **complaints, const char *fmt, ...)
252 {
253  va_list args;
254 
255  va_start (args, fmt);
256  vcomplaint (complaints, NULL/*file*/, 0/*line*/, fmt, args);
257  va_end (args);
258 }
259 
260 void
261 internal_complaint (struct complaints **complaints, const char *file,
262  int line, const char *fmt, ...)
263 {
264  va_list args;
265  va_start (args, fmt);
266  vcomplaint (complaints, file, line, fmt, args);
267  va_end (args);
268 }
269 
270 /* Clear out / initialize all complaint counters that have ever been
271  incremented. If LESS_VERBOSE is 1, be less verbose about
272  successive complaints, since the messages are appearing all
273  together during a command that is reporting a contiguous block of
274  complaints (rather than being interleaved with other messages). If
275  noisy is 1, we are in a noisy command, and our caller will print
276  enough context for the user to figure it out. */
277 
278 void
279 clear_complaints (struct complaints **c, int less_verbose, int noisy)
280 {
281  struct complaints *complaints = get_complaints (c);
282  struct complain *p;
283 
284  for (p = complaints->root; p != NULL; p = p->next)
285  {
286  p->counter = 0;
287  }
288 
289  switch (complaints->series)
290  {
291  case FIRST_MESSAGE:
292  /* Haven't yet printed anything. */
293  break;
294  case SHORT_FIRST_MESSAGE:
295  /* Haven't yet printed anything. */
296  break;
297  case ISOLATED_MESSAGE:
298  /* The code above, always forces a line-break. No need to do it
299  here. */
300  break;
301  case SUBSEQUENT_MESSAGE:
302  /* It would be really nice to use begin_line() here.
303  Unfortunately that function doesn't track GDB_STDERR and
304  consequently will sometimes supress a line when it
305  shouldn't. */
307  break;
308  default:
309  internal_error (__FILE__, __LINE__, _("bad switch"));
310  }
311 
312  if (!less_verbose)
313  complaints->series = ISOLATED_MESSAGE;
314  else if (!noisy)
315  complaints->series = FIRST_MESSAGE;
316  else
317  complaints->series = SHORT_FIRST_MESSAGE;
318 }
319 
320 static void
321 complaints_show_value (struct ui_file *file, int from_tty,
322  struct cmd_list_element *cmd, const char *value)
323 {
324  fprintf_filtered (file, _("Max number of complaints about incorrect"
325  " symbols is %s.\n"),
326  value);
327 }
328 
329 void
331 {
332  add_setshow_zinteger_cmd ("complaints", class_support,
333  &stop_whining, _("\
334 Set max number of complaints about incorrect symbols."), _("\
335 Show max number of complaints about incorrect symbols."), NULL,
336  NULL, complaints_show_value,
337  &setlist, &showlist);
338 }
void add_setshow_zinteger_cmd(const char *name, enum command_class theclass, int *var, const char *set_doc, const char *show_doc, const char *help_doc, cmd_sfunc_ftype *set_func, show_value_ftype *show_func, struct cmd_list_element **set_list, struct cmd_list_element **show_list)
Definition: cli-decode.c:719
void fputs_unfiltered(const char *buf, struct ui_file *file)
Definition: ui-file.c:252
void xfree(void *)
Definition: common-utils.c:97
static struct complaints symfile_complaint_book
Definition: complaints.c:100
char * xstrvprintf(const char *format, va_list ap)
Definition: common-utils.c:119
static struct complain complaint_sentinel
Definition: complaints.c:88
struct type ** const(pascal_builtin_types[])
void clear_complaints(struct complaints **c, int less_verbose, int noisy)
Definition: complaints.c:279
void internal_error(const char *file, int line, const char *fmt,...)
Definition: errors.c:50
int info_verbose
Definition: top.c:1699
void void void void void void void void internal_vwarning(const char *file, int line, const char *fmt, va_list args) ATTRIBUTE_PRINTF(3
#define _(String)
Definition: gdb_locale.h:40
static void complaints_show_value(struct ui_file *file, int from_tty, struct cmd_list_element *cmd, const char *value)
Definition: complaints.c:321
struct cmd_list_element * setlist
Definition: cli-cmds.c:135
void _initialize_complaints(void)
Definition: complaints.c:330
static int stop_whining
Definition: complaints.c:160
void internal_complaint(struct complaints **complaints, const char *file, int line, const char *fmt,...)
Definition: complaints.c:261
void fprintf_filtered(struct ui_file *stream, const char *format,...)
Definition: utils.c:2351
int(*) void(* deprecated_warning_hook)(const char *, va_list) ATTRIBUTE_FPTR_PRINTF(1
Definition: top.c:195
complaint_series
Definition: complaints.c:34
struct cmd_list_element * showlist
Definition: cli-cmds.c:143
void fputs_filtered(const char *linebuffer, struct ui_file *stream)
Definition: utils.c:2145
void complaint(struct complaints **complaints, const char *fmt,...)
Definition: complaints.c:251
struct cleanup * make_cleanup(make_cleanup_ftype *function, void *arg)
Definition: cleanups.c:117
#define gdb_assert(expr)
Definition: gdb_assert.h:33
void wrap_here(char *indent)
Definition: utils.c:1930
int line
Definition: complaints.c:53
const char * postfix
Definition: complaints.c:65
Definition: value.c:172
static struct complaints * get_complaints(struct complaints **c)
Definition: complaints.c:110
static struct complain * ATTRIBUTE_PRINTF(4, 0)
Definition: complaints.c:121
int counter
Definition: complaints.c:55
struct ui_file * gdb_stderr
Definition: main.c:72
const char * file
Definition: complaints.c:52
int line
Definition: symtab.h:1570
const char * fmt
Definition: complaints.c:54
struct complain * next
Definition: complaints.c:56
int series
Definition: complaints.c:78
struct complain * root
Definition: complaints.c:70
const char * prefix
Definition: complaints.c:64
void gdb_flush(struct ui_file *file)
Definition: ui-file.c:192
void void vwarning(const char *fmt, va_list args) ATTRIBUTE_PRINTF(1
const struct explanation * explanation
Definition: complaints.c:85
void do_cleanups(struct cleanup *old_chain)
Definition: cleanups.c:175
void begin_line(void)
Definition: utils.c:2016