gdb/complaints.c - gdb

Global variables defined

Data types defined

Functions defined

Source code

  1. /* Support for complaint handling during symbol reading in GDB.

  2.    Copyright (C) 1990-2015 Free Software Foundation, Inc.

  3.    This file is part of GDB.

  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 3 of the License, or
  7.    (at your option) any later version.

  8.    This program is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.    GNU General Public License for more details.

  12.    You should have received a copy of the GNU General Public License
  13.    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

  14. #include "defs.h"
  15. #include "complaints.h"
  16. #include "command.h"
  17. #include "gdbcmd.h"

  18. extern void _initialize_complaints (void);

  19. /* Should each complaint message be self explanatory, or should we
  20.    assume that a series of complaints is being produced?  */

  21. /* case 1: First message of a series that must
  22.    start off with explanation.  case 2: Subsequent message of a series
  23.    that needs no explanation (the user already knows we have a problem
  24.    so we can just state our piece).  */
  25. enum complaint_series {
  26.   /* Isolated self explanatory message.  */
  27.   ISOLATED_MESSAGE,
  28.   /* First message of a series, includes an explanation.  */
  29.   FIRST_MESSAGE,
  30.   /* First message of a series, but does not need to include any sort
  31.      of explanation.  */
  32.   SHORT_FIRST_MESSAGE,
  33.   /* Subsequent message of a series that needs no explanation (the
  34.      user already knows we have a problem so we can just state our
  35.      piece).  */
  36.   SUBSEQUENT_MESSAGE
  37. };

  38. /* Structure to manage complaints about symbol file contents.  */

  39. struct complain
  40. {
  41.   const char *file;
  42.   int line;
  43.   const char *fmt;
  44.   int counter;
  45.   struct complain *next;
  46. };

  47. /* The explanatory message that should accompany the complaint.  The
  48.    message is in two parts - pre and post - that are printed around
  49.    the complaint text.  */
  50. struct explanation
  51. {
  52.   const char *prefix;
  53.   const char *postfix;
  54. };

  55. struct complaints
  56. {
  57.   struct complain *root;

  58.   /* Should each complaint be self explanatory, or should we assume
  59.      that a series of complaints is being produced?  case 0: Isolated
  60.      self explanatory message.  case 1: First message of a series that
  61.      must start off with explanation.  case 2: Subsequent message of a
  62.      series that needs no explanation (the user already knows we have
  63.      a problem so we can just state our piece).  */
  64.   int series;

  65.   /* The explanatory messages that should accompany the complaint.
  66.      NOTE: cagney/2002-08-14: In a desperate attempt at being vaguely
  67.      i18n friendly, this is an array of two messages.  When present,
  68.      the PRE and POST EXPLANATION[SERIES] are used to wrap the
  69.      message.  */
  70.   const struct explanation *explanation;
  71. };

  72. static struct complain complaint_sentinel;

  73. /* The symbol table complaint table.  */

  74. static struct explanation symfile_explanations[] = {
  75.   { "During symbol reading, ", "." },
  76.   { "During symbol reading...", "..."},
  77.   { "", "..."},
  78.   { "", "..."},
  79.   { NULL, NULL }
  80. };

  81. static struct complaints symfile_complaint_book = {
  82.   &complaint_sentinel,
  83.   0,
  84.   symfile_explanations
  85. };
  86. struct complaints *symfile_complaints = &symfile_complaint_book;

  87. /* Wrapper function to, on-demand, fill in a complaints object.  */

  88. static struct complaints *
  89. get_complaints (struct complaints **c)
  90. {
  91.   if ((*c) != NULL)
  92.     return (*c);
  93.   (*c) = XNEW (struct complaints);
  94.   (*c)->root = &complaint_sentinel;
  95.   (*c)->series = ISOLATED_MESSAGE;
  96.   (*c)->explanation = NULL;
  97.   return (*c);
  98. }

  99. static struct complain * ATTRIBUTE_PRINTF (4, 0)
  100. find_complaint (struct complaints *complaints, const char *file,
  101.                 int line, const char *fmt)
  102. {
  103.   struct complain *complaint;

  104.   /* Find the complaint in the table.  A more efficient search
  105.      algorithm (based on hash table or something) could be used.  But
  106.      that can wait until someone shows evidence that this lookup is
  107.      a real bottle neck.  */
  108.   for (complaint = complaints->root;
  109.        complaint != NULL;
  110.        complaint = complaint->next)
  111.     {
  112.       if (complaint->fmt == fmt
  113.           && complaint->file == file
  114.           && complaint->line == line)
  115.         return complaint;
  116.     }

  117.   /* Oops not seen before, fill in a new complaint.  */
  118.   complaint = XNEW (struct complain);
  119.   complaint->fmt = fmt;
  120.   complaint->file = file;
  121.   complaint->line = line;
  122.   complaint->counter = 0;
  123.   complaint->next = NULL;

  124.   /* File it, return it.  */
  125.   complaint->next = complaints->root;
  126.   complaints->root = complaint;
  127.   return complaint;
  128. }


  129. /* How many complaints about a particular thing should be printed
  130.    before we stop whining about it?  Default is no whining at all,
  131.    since so many systems have ill-constructed symbol files.  */

  132. static int stop_whining = 0;

  133. /* Print a complaint, and link the complaint block into a chain for
  134.    later handling.  */

  135. static void ATTRIBUTE_PRINTF (4, 0)
  136. vcomplaint (struct complaints **c, const char *file,
  137.             int line, const char *fmt,
  138.             va_list args)
  139. {
  140.   struct complaints *complaints = get_complaints (c);
  141.   struct complain *complaint = find_complaint (complaints, file,
  142.                                                line, fmt);
  143.   enum complaint_series series;

  144.   gdb_assert (complaints != NULL);

  145.   complaint->counter++;
  146.   if (complaint->counter > stop_whining)
  147.     return;

  148.   if (info_verbose)
  149.     series = SUBSEQUENT_MESSAGE;
  150.   else
  151.     series = complaints->series;

  152.   if (complaint->file != NULL)
  153.     internal_vwarning (complaint->file, complaint->line,
  154.                        complaint->fmt, args);
  155.   else if (deprecated_warning_hook)
  156.     (*deprecated_warning_hook) (complaint->fmt, args);
  157.   else
  158.     {
  159.       if (complaints->explanation == NULL)
  160.         /* A [v]warning() call always appends a newline.  */
  161.         vwarning (complaint->fmt, args);
  162.       else
  163.         {
  164.           char *msg;
  165.           struct cleanup *cleanups;
  166.           msg = xstrvprintf (complaint->fmt, args);
  167.           cleanups = make_cleanup (xfree, msg);
  168.           wrap_here ("");
  169.           if (series != SUBSEQUENT_MESSAGE)
  170.             begin_line ();
  171.           /* XXX: i18n */
  172.           fprintf_filtered (gdb_stderr, "%s%s%s",
  173.                             complaints->explanation[series].prefix, msg,
  174.                             complaints->explanation[series].postfix);
  175.           /* Force a line-break after any isolated message.  For the
  176.              other cases, clear_complaints() takes care of any missing
  177.              trailing newline, the wrap_here() is just a hint.  */
  178.           if (series == ISOLATED_MESSAGE)
  179.             /* It would be really nice to use begin_line() here.
  180.                Unfortunately that function doesn't track GDB_STDERR and
  181.                consequently will sometimes supress a line when it
  182.                shouldn't.  */
  183.             fputs_filtered ("\n", gdb_stderr);
  184.           else
  185.             wrap_here ("");
  186.           do_cleanups (cleanups);
  187.         }
  188.     }

  189.   switch (series)
  190.     {
  191.     case ISOLATED_MESSAGE:
  192.       break;
  193.     case FIRST_MESSAGE:
  194.       complaints->series = SUBSEQUENT_MESSAGE;
  195.       break;
  196.     case SUBSEQUENT_MESSAGE:
  197.     case SHORT_FIRST_MESSAGE:
  198.       complaints->series = SUBSEQUENT_MESSAGE;
  199.       break;
  200.     }

  201.   /* If GDB dumps core, we'd like to see the complaints first.
  202.      Presumably GDB will not be sending so many complaints that this
  203.      becomes a performance hog.  */

  204.   gdb_flush (gdb_stderr);
  205. }

  206. void
  207. complaint (struct complaints **complaints, const char *fmt, ...)
  208. {
  209.   va_list args;

  210.   va_start (args, fmt);
  211.   vcomplaint (complaints, NULL/*file*/, 0/*line*/, fmt, args);
  212.   va_end (args);
  213. }

  214. void
  215. internal_complaint (struct complaints **complaints, const char *file,
  216.                     int line, const char *fmt, ...)
  217. {
  218.   va_list args;
  219.   va_start (args, fmt);
  220.   vcomplaint (complaints, file, line, fmt, args);
  221.   va_end (args);
  222. }

  223. /* Clear out / initialize all complaint counters that have ever been
  224.    incremented.  If LESS_VERBOSE is 1, be less verbose about
  225.    successive complaints, since the messages are appearing all
  226.    together during a command that is reporting a contiguous block of
  227.    complaints (rather than being interleaved with other messages).  If
  228.    noisy is 1, we are in a noisy command, and our caller will print
  229.    enough context for the user to figure it out.  */

  230. void
  231. clear_complaints (struct complaints **c, int less_verbose, int noisy)
  232. {
  233.   struct complaints *complaints = get_complaints (c);
  234.   struct complain *p;

  235.   for (p = complaints->root; p != NULL; p = p->next)
  236.     {
  237.       p->counter = 0;
  238.     }

  239.   switch (complaints->series)
  240.     {
  241.     case FIRST_MESSAGE:
  242.       /* Haven't yet printed anything.  */
  243.       break;
  244.     case SHORT_FIRST_MESSAGE:
  245.       /* Haven't yet printed anything.  */
  246.       break;
  247.     case ISOLATED_MESSAGE:
  248.       /* The code above, always forces a line-break.  No need to do it
  249.          here.  */
  250.       break;
  251.     case SUBSEQUENT_MESSAGE:
  252.       /* It would be really nice to use begin_line() here.
  253.          Unfortunately that function doesn't track GDB_STDERR and
  254.          consequently will sometimes supress a line when it
  255.          shouldn't.  */
  256.       fputs_unfiltered ("\n", gdb_stderr);
  257.       break;
  258.     default:
  259.       internal_error (__FILE__, __LINE__, _("bad switch"));
  260.     }

  261.   if (!less_verbose)
  262.     complaints->series = ISOLATED_MESSAGE;
  263.   else if (!noisy)
  264.     complaints->series = FIRST_MESSAGE;
  265.   else
  266.     complaints->series = SHORT_FIRST_MESSAGE;
  267. }

  268. static void
  269. complaints_show_value (struct ui_file *file, int from_tty,
  270.                        struct cmd_list_element *cmd, const char *value)
  271. {
  272.   fprintf_filtered (file, _("Max number of complaints about incorrect"
  273.                             " symbols is %s.\n"),
  274.                     value);
  275. }

  276. void
  277. _initialize_complaints (void)
  278. {
  279.   add_setshow_zinteger_cmd ("complaints", class_support,
  280.                             &stop_whining, _("\
  281. Set max number of complaints about incorrect symbols."), _("\
  282. Show max number of complaints about incorrect symbols."), NULL,
  283.                             NULL, complaints_show_value,
  284.                             &setlist, &showlist);
  285. }