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