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