| /* Support for complaint handling during symbol reading in GDB. | 
 |  | 
 |    Copyright (C) 1990-2021 Free Software Foundation, Inc. | 
 |  | 
 |    This file is part of GDB. | 
 |  | 
 |    This program is free software; you can redistribute it and/or modify | 
 |    it under the terms of the GNU General Public License as published by | 
 |    the Free Software Foundation; either version 3 of the License, or | 
 |    (at your option) any later version. | 
 |  | 
 |    This program is distributed in the hope that it will be useful, | 
 |    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
 |    GNU General Public License for more details. | 
 |  | 
 |    You should have received a copy of the GNU General Public License | 
 |    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */ | 
 |  | 
 | #include "defs.h" | 
 | #include "complaints.h" | 
 | #include "command.h" | 
 | #include "gdbcmd.h" | 
 | #include "gdbsupport/selftest.h" | 
 | #include <unordered_map> | 
 |  | 
 | /* Map format strings to counters.  */ | 
 |  | 
 | static std::unordered_map<const char *, int> counters; | 
 |  | 
 | /* How many complaints about a particular thing should be printed | 
 |    before we stop whining about it?  Default is no whining at all, | 
 |    since so many systems have ill-constructed symbol files.  */ | 
 |  | 
 | int stop_whining = 0; | 
 |  | 
 | /* See complaints.h.  */ | 
 |  | 
 | void | 
 | complaint_internal (const char *fmt, ...) | 
 | { | 
 |   va_list args; | 
 |  | 
 |   if (++counters[fmt] > stop_whining) | 
 |     return; | 
 |  | 
 |   va_start (args, fmt); | 
 |  | 
 |   if (deprecated_warning_hook) | 
 |     (*deprecated_warning_hook) (fmt, args); | 
 |   else | 
 |     { | 
 |       fputs_filtered (_("During symbol reading: "), gdb_stderr); | 
 |       vfprintf_filtered (gdb_stderr, fmt, args); | 
 |       fputs_filtered ("\n", gdb_stderr); | 
 |     } | 
 |  | 
 |   va_end (args); | 
 | } | 
 |  | 
 | /* See complaints.h.  */ | 
 |  | 
 | void | 
 | clear_complaints () | 
 | { | 
 |   counters.clear (); | 
 | } | 
 |  | 
 | static void | 
 | complaints_show_value (struct ui_file *file, int from_tty, | 
 | 		       struct cmd_list_element *cmd, const char *value) | 
 | { | 
 |   fprintf_filtered (file, _("Max number of complaints about incorrect" | 
 | 			    " symbols is %s.\n"), | 
 | 		    value); | 
 | } | 
 |  | 
 | #if GDB_SELF_TEST | 
 | namespace selftests { | 
 |  | 
 | /* Entry point for complaints unit tests.  */ | 
 |  | 
 | static void | 
 | test_complaints () | 
 | { | 
 |   std::unordered_map<const char *, int> tmp; | 
 |   scoped_restore reset_counters = make_scoped_restore (&counters, tmp); | 
 |   scoped_restore reset_stop_whining = make_scoped_restore (&stop_whining, 2); | 
 |  | 
 | #define CHECK_COMPLAINT(STR, CNT)					\ | 
 |   do									\ | 
 |     {									\ | 
 |       std::string output;						\ | 
 |       execute_fn_to_string (output, []() { complaint (STR); }, false);	\ | 
 |       std::string expected						\ | 
 | 	= _("During symbol reading: ") + std::string (STR "\n");	\ | 
 |       SELF_CHECK (output == expected);					\ | 
 |       SELF_CHECK (counters[STR] == CNT);				\ | 
 |     } while (0) | 
 |  | 
 | #define CHECK_COMPLAINT_SILENT(STR, CNT)				\ | 
 |   do									\ | 
 |     {									\ | 
 |       std::string output;						\ | 
 |       execute_fn_to_string (output, []() { complaint (STR); }, false);	\ | 
 |       SELF_CHECK (output.empty ());					\ | 
 |       SELF_CHECK (counters[STR] == CNT);				\ | 
 |     } while (0) | 
 |  | 
 |   CHECK_COMPLAINT ("maintenance complaint 0", 1); | 
 |   CHECK_COMPLAINT ("maintenance complaint 0", 2); | 
 |   CHECK_COMPLAINT_SILENT ("maintenance complaint 0", 3); | 
 |   CHECK_COMPLAINT ("maintenance complaint 1", 1); | 
 |   clear_complaints (); | 
 |   CHECK_COMPLAINT ("maintenance complaint 0", 1); | 
 |  | 
 | #undef CHECK_COMPLAINT | 
 | #undef CHECK_COMPLAINT_SILENT | 
 | } | 
 |  | 
 |  | 
 | } // namespace selftests | 
 | #endif /* GDB_SELF_TEST */ | 
 |  | 
 | void _initialize_complaints (); | 
 | void | 
 | _initialize_complaints () | 
 | { | 
 |   add_setshow_zinteger_cmd ("complaints", class_support,  | 
 | 			    &stop_whining, _("\ | 
 | Set max number of complaints about incorrect symbols."), _("\ | 
 | Show max number of complaints about incorrect symbols."), NULL, | 
 | 			    NULL, complaints_show_value, | 
 | 			    &setlist, &showlist); | 
 |  | 
 | #if GDB_SELF_TEST | 
 |   selftests::register_test ("complaints", selftests::test_complaints); | 
 | #endif /* GDB_SELF_TEST */ | 
 | } |