xref: /dflybsd-src/contrib/gdb-7/gdb/complaints.c (revision de8e141f24382815c10a4012d209bbbf7abf1112)
15796c8dcSSimon Schubert /* Support for complaint handling during symbol reading in GDB.
25796c8dcSSimon Schubert 
3*ef5ccd6cSJohn Marino    Copyright (C) 1990-2013 Free Software Foundation, Inc.
45796c8dcSSimon Schubert 
55796c8dcSSimon Schubert    This file is part of GDB.
65796c8dcSSimon Schubert 
75796c8dcSSimon Schubert    This program is free software; you can redistribute it and/or modify
85796c8dcSSimon Schubert    it under the terms of the GNU General Public License as published by
95796c8dcSSimon Schubert    the Free Software Foundation; either version 3 of the License, or
105796c8dcSSimon Schubert    (at your option) any later version.
115796c8dcSSimon Schubert 
125796c8dcSSimon Schubert    This program is distributed in the hope that it will be useful,
135796c8dcSSimon Schubert    but WITHOUT ANY WARRANTY; without even the implied warranty of
145796c8dcSSimon Schubert    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
155796c8dcSSimon Schubert    GNU General Public License for more details.
165796c8dcSSimon Schubert 
175796c8dcSSimon Schubert    You should have received a copy of the GNU General Public License
185796c8dcSSimon Schubert    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
195796c8dcSSimon Schubert 
205796c8dcSSimon Schubert #include "defs.h"
215796c8dcSSimon Schubert #include "complaints.h"
225796c8dcSSimon Schubert #include "gdb_assert.h"
235796c8dcSSimon Schubert #include "command.h"
245796c8dcSSimon Schubert #include "gdbcmd.h"
255796c8dcSSimon Schubert 
265796c8dcSSimon Schubert extern void _initialize_complaints (void);
275796c8dcSSimon Schubert 
28c50c785cSJohn Marino /* Should each complaint message be self explanatory, or should we
29c50c785cSJohn Marino    assume that a series of complaints is being produced?  */
305796c8dcSSimon Schubert 
315796c8dcSSimon Schubert /* case 1: First message of a series that must
325796c8dcSSimon Schubert    start off with explanation.  case 2: Subsequent message of a series
335796c8dcSSimon Schubert    that needs no explanation (the user already knows we have a problem
345796c8dcSSimon Schubert    so we can just state our piece).  */
355796c8dcSSimon Schubert enum complaint_series {
365796c8dcSSimon Schubert   /* Isolated self explanatory message.  */
375796c8dcSSimon Schubert   ISOLATED_MESSAGE,
385796c8dcSSimon Schubert   /* First message of a series, includes an explanation.  */
395796c8dcSSimon Schubert   FIRST_MESSAGE,
405796c8dcSSimon Schubert   /* First message of a series, but does not need to include any sort
415796c8dcSSimon Schubert      of explanation.  */
425796c8dcSSimon Schubert   SHORT_FIRST_MESSAGE,
435796c8dcSSimon Schubert   /* Subsequent message of a series that needs no explanation (the
445796c8dcSSimon Schubert      user already knows we have a problem so we can just state our
455796c8dcSSimon Schubert      piece).  */
465796c8dcSSimon Schubert   SUBSEQUENT_MESSAGE
475796c8dcSSimon Schubert };
485796c8dcSSimon Schubert 
495796c8dcSSimon Schubert /* Structure to manage complaints about symbol file contents.  */
505796c8dcSSimon Schubert 
515796c8dcSSimon Schubert struct complain
525796c8dcSSimon Schubert {
535796c8dcSSimon Schubert   const char *file;
545796c8dcSSimon Schubert   int line;
555796c8dcSSimon Schubert   const char *fmt;
565796c8dcSSimon Schubert   int counter;
575796c8dcSSimon Schubert   struct complain *next;
585796c8dcSSimon Schubert };
595796c8dcSSimon Schubert 
605796c8dcSSimon Schubert /* The explanatory message that should accompany the complaint.  The
615796c8dcSSimon Schubert    message is in two parts - pre and post - that are printed around
625796c8dcSSimon Schubert    the complaint text.  */
635796c8dcSSimon Schubert struct explanation
645796c8dcSSimon Schubert {
655796c8dcSSimon Schubert   const char *prefix;
665796c8dcSSimon Schubert   const char *postfix;
675796c8dcSSimon Schubert };
685796c8dcSSimon Schubert 
695796c8dcSSimon Schubert struct complaints
705796c8dcSSimon Schubert {
715796c8dcSSimon Schubert   struct complain *root;
725796c8dcSSimon Schubert 
735796c8dcSSimon Schubert   /* Should each complaint be self explanatory, or should we assume
745796c8dcSSimon Schubert      that a series of complaints is being produced?  case 0: Isolated
755796c8dcSSimon Schubert      self explanatory message.  case 1: First message of a series that
765796c8dcSSimon Schubert      must start off with explanation.  case 2: Subsequent message of a
775796c8dcSSimon Schubert      series that needs no explanation (the user already knows we have
785796c8dcSSimon Schubert      a problem so we can just state our piece).  */
795796c8dcSSimon Schubert   int series;
805796c8dcSSimon Schubert 
815796c8dcSSimon Schubert   /* The explanatory messages that should accompany the complaint.
825796c8dcSSimon Schubert      NOTE: cagney/2002-08-14: In a desperate attempt at being vaguely
835796c8dcSSimon Schubert      i18n friendly, this is an array of two messages.  When present,
845796c8dcSSimon Schubert      the PRE and POST EXPLANATION[SERIES] are used to wrap the
855796c8dcSSimon Schubert      message.  */
865796c8dcSSimon Schubert   const struct explanation *explanation;
875796c8dcSSimon Schubert };
885796c8dcSSimon Schubert 
895796c8dcSSimon Schubert static struct complain complaint_sentinel;
905796c8dcSSimon Schubert 
915796c8dcSSimon Schubert /* The symbol table complaint table.  */
925796c8dcSSimon Schubert 
935796c8dcSSimon Schubert static struct explanation symfile_explanations[] = {
945796c8dcSSimon Schubert   { "During symbol reading, ", "." },
955796c8dcSSimon Schubert   { "During symbol reading...", "..."},
965796c8dcSSimon Schubert   { "", "..."},
975796c8dcSSimon Schubert   { "", "..."},
985796c8dcSSimon Schubert   { NULL, NULL }
995796c8dcSSimon Schubert };
1005796c8dcSSimon Schubert 
1015796c8dcSSimon Schubert static struct complaints symfile_complaint_book = {
1025796c8dcSSimon Schubert   &complaint_sentinel,
1035796c8dcSSimon Schubert   0,
1045796c8dcSSimon Schubert   symfile_explanations
1055796c8dcSSimon Schubert };
1065796c8dcSSimon Schubert struct complaints *symfile_complaints = &symfile_complaint_book;
1075796c8dcSSimon Schubert 
1085796c8dcSSimon Schubert /* Wrapper function to, on-demand, fill in a complaints object.  */
1095796c8dcSSimon Schubert 
1105796c8dcSSimon Schubert static struct complaints *
get_complaints(struct complaints ** c)1115796c8dcSSimon Schubert get_complaints (struct complaints **c)
1125796c8dcSSimon Schubert {
1135796c8dcSSimon Schubert   if ((*c) != NULL)
1145796c8dcSSimon Schubert     return (*c);
1155796c8dcSSimon Schubert   (*c) = XMALLOC (struct complaints);
1165796c8dcSSimon Schubert   (*c)->root = &complaint_sentinel;
1175796c8dcSSimon Schubert   (*c)->series = ISOLATED_MESSAGE;
1185796c8dcSSimon Schubert   (*c)->explanation = NULL;
1195796c8dcSSimon Schubert   return (*c);
1205796c8dcSSimon Schubert }
1215796c8dcSSimon Schubert 
122cf7f2e2dSJohn Marino static struct complain * ATTRIBUTE_PRINTF (4, 0)
find_complaint(struct complaints * complaints,const char * file,int line,const char * fmt)1235796c8dcSSimon Schubert find_complaint (struct complaints *complaints, const char *file,
1245796c8dcSSimon Schubert 		int line, const char *fmt)
1255796c8dcSSimon Schubert {
1265796c8dcSSimon Schubert   struct complain *complaint;
1275796c8dcSSimon Schubert 
1285796c8dcSSimon Schubert   /* Find the complaint in the table.  A more efficient search
1295796c8dcSSimon Schubert      algorithm (based on hash table or something) could be used.  But
1305796c8dcSSimon Schubert      that can wait until someone shows evidence that this lookup is
1315796c8dcSSimon Schubert      a real bottle neck.  */
1325796c8dcSSimon Schubert   for (complaint = complaints->root;
1335796c8dcSSimon Schubert        complaint != NULL;
1345796c8dcSSimon Schubert        complaint = complaint->next)
1355796c8dcSSimon Schubert     {
1365796c8dcSSimon Schubert       if (complaint->fmt == fmt
1375796c8dcSSimon Schubert 	  && complaint->file == file
1385796c8dcSSimon Schubert 	  && complaint->line == line)
1395796c8dcSSimon Schubert 	return complaint;
1405796c8dcSSimon Schubert     }
1415796c8dcSSimon Schubert 
1425796c8dcSSimon Schubert   /* Oops not seen before, fill in a new complaint.  */
1435796c8dcSSimon Schubert   complaint = XMALLOC (struct complain);
1445796c8dcSSimon Schubert   complaint->fmt = fmt;
1455796c8dcSSimon Schubert   complaint->file = file;
1465796c8dcSSimon Schubert   complaint->line = line;
1475796c8dcSSimon Schubert   complaint->counter = 0;
1485796c8dcSSimon Schubert   complaint->next = NULL;
1495796c8dcSSimon Schubert 
1505796c8dcSSimon Schubert   /* File it, return it.  */
1515796c8dcSSimon Schubert   complaint->next = complaints->root;
1525796c8dcSSimon Schubert   complaints->root = complaint;
1535796c8dcSSimon Schubert   return complaint;
1545796c8dcSSimon Schubert }
1555796c8dcSSimon Schubert 
1565796c8dcSSimon Schubert 
1575796c8dcSSimon Schubert /* How many complaints about a particular thing should be printed
1585796c8dcSSimon Schubert    before we stop whining about it?  Default is no whining at all,
1595796c8dcSSimon Schubert    since so many systems have ill-constructed symbol files.  */
1605796c8dcSSimon Schubert 
1615796c8dcSSimon Schubert static int stop_whining = 0;
1625796c8dcSSimon Schubert 
1635796c8dcSSimon Schubert /* Print a complaint, and link the complaint block into a chain for
1645796c8dcSSimon Schubert    later handling.  */
1655796c8dcSSimon Schubert 
166cf7f2e2dSJohn Marino static void ATTRIBUTE_PRINTF (4, 0)
vcomplaint(struct complaints ** c,const char * file,int line,const char * fmt,va_list args)167c50c785cSJohn Marino vcomplaint (struct complaints **c, const char *file,
168c50c785cSJohn Marino 	    int line, const char *fmt,
1695796c8dcSSimon Schubert 	    va_list args)
1705796c8dcSSimon Schubert {
1715796c8dcSSimon Schubert   struct complaints *complaints = get_complaints (c);
172c50c785cSJohn Marino   struct complain *complaint = find_complaint (complaints, file,
173c50c785cSJohn Marino 					       line, fmt);
1745796c8dcSSimon Schubert   enum complaint_series series;
175cf7f2e2dSJohn Marino 
1765796c8dcSSimon Schubert   gdb_assert (complaints != NULL);
1775796c8dcSSimon Schubert 
1785796c8dcSSimon Schubert   complaint->counter++;
1795796c8dcSSimon Schubert   if (complaint->counter > stop_whining)
1805796c8dcSSimon Schubert     return;
1815796c8dcSSimon Schubert 
1825796c8dcSSimon Schubert   if (info_verbose)
1835796c8dcSSimon Schubert     series = SUBSEQUENT_MESSAGE;
1845796c8dcSSimon Schubert   else
1855796c8dcSSimon Schubert     series = complaints->series;
1865796c8dcSSimon Schubert 
1875796c8dcSSimon Schubert   if (complaint->file != NULL)
188c50c785cSJohn Marino     internal_vwarning (complaint->file, complaint->line,
189c50c785cSJohn Marino 		       complaint->fmt, args);
1905796c8dcSSimon Schubert   else if (deprecated_warning_hook)
1915796c8dcSSimon Schubert     (*deprecated_warning_hook) (complaint->fmt, args);
1925796c8dcSSimon Schubert   else
1935796c8dcSSimon Schubert     {
1945796c8dcSSimon Schubert       if (complaints->explanation == NULL)
1955796c8dcSSimon Schubert 	/* A [v]warning() call always appends a newline.  */
1965796c8dcSSimon Schubert 	vwarning (complaint->fmt, args);
1975796c8dcSSimon Schubert       else
1985796c8dcSSimon Schubert 	{
1995796c8dcSSimon Schubert 	  char *msg;
2005796c8dcSSimon Schubert 	  struct cleanup *cleanups;
2015796c8dcSSimon Schubert 	  msg = xstrvprintf (complaint->fmt, args);
2025796c8dcSSimon Schubert 	  cleanups = make_cleanup (xfree, msg);
2035796c8dcSSimon Schubert 	  wrap_here ("");
2045796c8dcSSimon Schubert 	  if (series != SUBSEQUENT_MESSAGE)
2055796c8dcSSimon Schubert 	    begin_line ();
2065796c8dcSSimon Schubert 	  /* XXX: i18n */
2075796c8dcSSimon Schubert 	  fprintf_filtered (gdb_stderr, "%s%s%s",
2085796c8dcSSimon Schubert 			    complaints->explanation[series].prefix, msg,
2095796c8dcSSimon Schubert 			    complaints->explanation[series].postfix);
2105796c8dcSSimon Schubert 	  /* Force a line-break after any isolated message.  For the
2115796c8dcSSimon Schubert              other cases, clear_complaints() takes care of any missing
2125796c8dcSSimon Schubert              trailing newline, the wrap_here() is just a hint.  */
2135796c8dcSSimon Schubert 	  if (series == ISOLATED_MESSAGE)
2145796c8dcSSimon Schubert 	    /* It would be really nice to use begin_line() here.
2155796c8dcSSimon Schubert 	       Unfortunately that function doesn't track GDB_STDERR and
2165796c8dcSSimon Schubert 	       consequently will sometimes supress a line when it
2175796c8dcSSimon Schubert 	       shouldn't.  */
2185796c8dcSSimon Schubert 	    fputs_filtered ("\n", gdb_stderr);
2195796c8dcSSimon Schubert 	  else
2205796c8dcSSimon Schubert 	    wrap_here ("");
2215796c8dcSSimon Schubert 	  do_cleanups (cleanups);
2225796c8dcSSimon Schubert 	}
2235796c8dcSSimon Schubert     }
2245796c8dcSSimon Schubert 
2255796c8dcSSimon Schubert   switch (series)
2265796c8dcSSimon Schubert     {
2275796c8dcSSimon Schubert     case ISOLATED_MESSAGE:
2285796c8dcSSimon Schubert       break;
2295796c8dcSSimon Schubert     case FIRST_MESSAGE:
2305796c8dcSSimon Schubert       complaints->series = SUBSEQUENT_MESSAGE;
2315796c8dcSSimon Schubert       break;
2325796c8dcSSimon Schubert     case SUBSEQUENT_MESSAGE:
2335796c8dcSSimon Schubert     case SHORT_FIRST_MESSAGE:
2345796c8dcSSimon Schubert       complaints->series = SUBSEQUENT_MESSAGE;
2355796c8dcSSimon Schubert       break;
2365796c8dcSSimon Schubert     }
2375796c8dcSSimon Schubert 
2385796c8dcSSimon Schubert   /* If GDB dumps core, we'd like to see the complaints first.
2395796c8dcSSimon Schubert      Presumably GDB will not be sending so many complaints that this
2405796c8dcSSimon Schubert      becomes a performance hog.  */
2415796c8dcSSimon Schubert 
2425796c8dcSSimon Schubert   gdb_flush (gdb_stderr);
2435796c8dcSSimon Schubert }
2445796c8dcSSimon Schubert 
2455796c8dcSSimon Schubert void
complaint(struct complaints ** complaints,const char * fmt,...)2465796c8dcSSimon Schubert complaint (struct complaints **complaints, const char *fmt, ...)
2475796c8dcSSimon Schubert {
2485796c8dcSSimon Schubert   va_list args;
249cf7f2e2dSJohn Marino 
2505796c8dcSSimon Schubert   va_start (args, fmt);
2515796c8dcSSimon Schubert   vcomplaint (complaints, NULL/*file*/, 0/*line*/, fmt, args);
2525796c8dcSSimon Schubert   va_end (args);
2535796c8dcSSimon Schubert }
2545796c8dcSSimon Schubert 
2555796c8dcSSimon Schubert void
internal_complaint(struct complaints ** complaints,const char * file,int line,const char * fmt,...)2565796c8dcSSimon Schubert internal_complaint (struct complaints **complaints, const char *file,
2575796c8dcSSimon Schubert 		    int line, const char *fmt, ...)
2585796c8dcSSimon Schubert {
2595796c8dcSSimon Schubert   va_list args;
2605796c8dcSSimon Schubert   va_start (args, fmt);
2615796c8dcSSimon Schubert   vcomplaint (complaints, file, line, fmt, args);
2625796c8dcSSimon Schubert   va_end (args);
2635796c8dcSSimon Schubert }
2645796c8dcSSimon Schubert 
2655796c8dcSSimon Schubert /* Clear out / initialize all complaint counters that have ever been
2665796c8dcSSimon Schubert    incremented.  If LESS_VERBOSE is 1, be less verbose about
2675796c8dcSSimon Schubert    successive complaints, since the messages are appearing all
2685796c8dcSSimon Schubert    together during a command that is reporting a contiguous block of
2695796c8dcSSimon Schubert    complaints (rather than being interleaved with other messages).  If
2705796c8dcSSimon Schubert    noisy is 1, we are in a noisy command, and our caller will print
2715796c8dcSSimon Schubert    enough context for the user to figure it out.  */
2725796c8dcSSimon Schubert 
2735796c8dcSSimon Schubert void
clear_complaints(struct complaints ** c,int less_verbose,int noisy)2745796c8dcSSimon Schubert clear_complaints (struct complaints **c, int less_verbose, int noisy)
2755796c8dcSSimon Schubert {
2765796c8dcSSimon Schubert   struct complaints *complaints = get_complaints (c);
2775796c8dcSSimon Schubert   struct complain *p;
2785796c8dcSSimon Schubert 
2795796c8dcSSimon Schubert   for (p = complaints->root; p != NULL; p = p->next)
2805796c8dcSSimon Schubert     {
2815796c8dcSSimon Schubert       p->counter = 0;
2825796c8dcSSimon Schubert     }
2835796c8dcSSimon Schubert 
2845796c8dcSSimon Schubert   switch (complaints->series)
2855796c8dcSSimon Schubert     {
2865796c8dcSSimon Schubert     case FIRST_MESSAGE:
2875796c8dcSSimon Schubert       /* Haven't yet printed anything.  */
2885796c8dcSSimon Schubert       break;
2895796c8dcSSimon Schubert     case SHORT_FIRST_MESSAGE:
2905796c8dcSSimon Schubert       /* Haven't yet printed anything.  */
2915796c8dcSSimon Schubert       break;
2925796c8dcSSimon Schubert     case ISOLATED_MESSAGE:
2935796c8dcSSimon Schubert       /* The code above, always forces a line-break.  No need to do it
2945796c8dcSSimon Schubert          here.  */
2955796c8dcSSimon Schubert       break;
2965796c8dcSSimon Schubert     case SUBSEQUENT_MESSAGE:
2975796c8dcSSimon Schubert       /* It would be really nice to use begin_line() here.
2985796c8dcSSimon Schubert          Unfortunately that function doesn't track GDB_STDERR and
299c50c785cSJohn Marino          consequently will sometimes supress a line when it
300c50c785cSJohn Marino          shouldn't.  */
3015796c8dcSSimon Schubert       fputs_unfiltered ("\n", gdb_stderr);
3025796c8dcSSimon Schubert       break;
3035796c8dcSSimon Schubert     default:
3045796c8dcSSimon Schubert       internal_error (__FILE__, __LINE__, _("bad switch"));
3055796c8dcSSimon Schubert     }
3065796c8dcSSimon Schubert 
3075796c8dcSSimon Schubert   if (!less_verbose)
3085796c8dcSSimon Schubert     complaints->series = ISOLATED_MESSAGE;
3095796c8dcSSimon Schubert   else if (!noisy)
3105796c8dcSSimon Schubert     complaints->series = FIRST_MESSAGE;
3115796c8dcSSimon Schubert   else
3125796c8dcSSimon Schubert     complaints->series = SHORT_FIRST_MESSAGE;
3135796c8dcSSimon Schubert }
3145796c8dcSSimon Schubert 
3155796c8dcSSimon Schubert static void
complaints_show_value(struct ui_file * file,int from_tty,struct cmd_list_element * cmd,const char * value)3165796c8dcSSimon Schubert complaints_show_value (struct ui_file *file, int from_tty,
3175796c8dcSSimon Schubert 		       struct cmd_list_element *cmd, const char *value)
3185796c8dcSSimon Schubert {
3195796c8dcSSimon Schubert   fprintf_filtered (file, _("Max number of complaints about incorrect"
3205796c8dcSSimon Schubert 			    " symbols is %s.\n"),
3215796c8dcSSimon Schubert 		    value);
3225796c8dcSSimon Schubert }
3235796c8dcSSimon Schubert 
3245796c8dcSSimon Schubert void
_initialize_complaints(void)3255796c8dcSSimon Schubert _initialize_complaints (void)
3265796c8dcSSimon Schubert {
327c50c785cSJohn Marino   add_setshow_zinteger_cmd ("complaints", class_support,
328c50c785cSJohn Marino 			    &stop_whining, _("\
3295796c8dcSSimon Schubert Set max number of complaints about incorrect symbols."), _("\
3305796c8dcSSimon Schubert Show max number of complaints about incorrect symbols."), NULL,
3315796c8dcSSimon Schubert 			    NULL, complaints_show_value,
3325796c8dcSSimon Schubert 			    &setlist, &showlist);
3335796c8dcSSimon Schubert }
334