Remove struct complain

At this point, struct complain is just holds a key, a value, and a
"next" pointer to form a linked list.  It's simpler to replace this
with an unordered map.

gdb/ChangeLog
2018-05-23  Tom Tromey  <tom@tromey.com>

	* complaints.c (counters): New global.
	(struct complain): Remove.
	(struct complaints) <root>: Remove.
	(complaint_sentinel): Remove.
	(symfile_complaint_book): Update.
	(find_complaint) Remove.
	(complaint_internal, clear_complaints): Update.

gdb/testsuite/ChangeLog
2018-05-23  Tom Tromey  <tom@tromey.com>

	* gdb.gdb/complaints.exp (test_initial_complaints): Simplify.
This commit is contained in:
Tom Tromey 2018-05-16 23:22:54 -06:00
parent 7ff8817441
commit ff1cf532db
4 changed files with 23 additions and 69 deletions

View File

@ -1,3 +1,13 @@
2018-05-23 Tom Tromey <tom@tromey.com>
* complaints.c (counters): New global.
(struct complain): Remove.
(struct complaints) <root>: Remove.
(complaint_sentinel): Remove.
(symfile_complaint_book): Update.
(find_complaint) Remove.
(complaint_internal, clear_complaints): Update.
2018-05-23 Tom Tromey <tom@tromey.com> 2018-05-23 Tom Tromey <tom@tromey.com>
* complaints.c (struct complain) <file, line>: Remove. * complaints.c (struct complain) <file, line>: Remove.

View File

@ -21,6 +21,7 @@
#include "complaints.h" #include "complaints.h"
#include "command.h" #include "command.h"
#include "gdbcmd.h" #include "gdbcmd.h"
#include <unordered_map>
/* Should each complaint message be self explanatory, or should we /* Should each complaint message be self explanatory, or should we
assume that a series of complaints is being produced? */ assume that a series of complaints is being produced? */
@ -34,59 +35,19 @@ enum complaint_series {
SHORT_FIRST_MESSAGE, SHORT_FIRST_MESSAGE,
}; };
/* Structure to manage complaints about symbol file contents. */ /* Map format strings to counters. */
struct complain static std::unordered_map<const char *, int> counters;
{
const char *fmt;
int counter;
struct complain *next;
};
struct complaints struct complaints
{ {
struct complain *root;
enum complaint_series series; enum complaint_series series;
}; };
static struct complain complaint_sentinel;
static struct complaints symfile_complaint_book = { static struct complaints symfile_complaint_book = {
&complaint_sentinel,
ISOLATED_MESSAGE ISOLATED_MESSAGE
}; };
static struct complain * ATTRIBUTE_PRINTF (2, 0)
find_complaint (struct complaints *complaints, const char *fmt)
{
struct complain *complaint;
/* Find the complaint in the table. A more efficient search
algorithm (based on hash table or something) could be used. But
that can wait until someone shows evidence that this lookup is
a real bottle neck. */
for (complaint = complaints->root;
complaint != NULL;
complaint = complaint->next)
{
if (complaint->fmt == fmt)
return complaint;
}
/* Oops not seen before, fill in a new complaint. */
complaint = XNEW (struct complain);
complaint->fmt = fmt;
complaint->counter = 0;
complaint->next = NULL;
/* File it, return it. */
complaint->next = complaints->root;
complaints->root = complaint;
return complaint;
}
/* How many complaints about a particular thing should be printed /* How many complaints about a particular thing should be printed
before we stop whining about it? Default is no whining at all, before we stop whining about it? Default is no whining at all,
since so many systems have ill-constructed symbol files. */ since so many systems have ill-constructed symbol files. */
@ -99,24 +60,14 @@ void
complaint_internal (const char *fmt, ...) complaint_internal (const char *fmt, ...)
{ {
va_list args; va_list args;
struct complain *complaint = find_complaint (&symfile_complaint_book, fmt);
enum complaint_series series; enum complaint_series series;
complaint->counter++; if (counters[fmt]++ > stop_whining)
if (complaint->counter > stop_whining)
return; return;
va_start (args, fmt); va_start (args, fmt);
series = symfile_complaint_book.series; series = symfile_complaint_book.series;
/* Pass 'fmt' instead of 'complaint->fmt' to printf-like callees
from here on, to avoid "format string is not a string literal"
warnings. 'fmt' is this function's printf-format parameter, so
the compiler can assume the passed in argument is a literal
string somewhere up the call chain. */
gdb_assert (complaint->fmt == fmt);
if (deprecated_warning_hook) if (deprecated_warning_hook)
(*deprecated_warning_hook) (fmt, args); (*deprecated_warning_hook) (fmt, args);
else else
@ -150,10 +101,7 @@ clear_complaints (int less_verbose)
{ {
struct complain *p; struct complain *p;
for (p = symfile_complaint_book.root; p != NULL; p = p->next) counters.clear ();
{
p->counter = 0;
}
if (!less_verbose) if (!less_verbose)
symfile_complaint_book.series = ISOLATED_MESSAGE; symfile_complaint_book.series = ISOLATED_MESSAGE;

View File

@ -1,3 +1,7 @@
2018-05-23 Tom Tromey <tom@tromey.com>
* gdb.gdb/complaints.exp (test_initial_complaints): Simplify.
2018-05-23 Tom Tromey <tom@tromey.com> 2018-05-23 Tom Tromey <tom@tromey.com>
* gdb.gdb/complaints.exp (test_initial_complaints): Don't mention * gdb.gdb/complaints.exp (test_initial_complaints): Don't mention

View File

@ -57,26 +57,18 @@ proc test_initial_complaints { } {
# Unsupress complaints # Unsupress complaints
gdb_test "set stop_whining = 2" gdb_test "set stop_whining = 2"
gdb_test_no_output "set var \$cstr = \"Register a complaint\""
# Prime the system # Prime the system
gdb_test_stdio \ gdb_test_stdio \
"call complaint_internal (\"Register a complaint\")" \ "call complaint_internal (\$cstr)" \
"During symbol reading, Register a complaint." "During symbol reading, Register a complaint."
# Check that the complaint was inserted and where
gdb_test "print symfile_complaint_book.root->fmt" \
".\[0-9\]+ =.*\"Register a complaint\""
# Re-issue the first message #1 # Re-issue the first message #1
gdb_test_stdio \ gdb_test_stdio \
"call complaint_internal (symfile_complaint_book.root->fmt)" \ "call complaint_internal (\$cstr)" \
"During symbol reading, Register a complaint." "During symbol reading, Register a complaint."
# Check that there is only one thing in the list. How the boolean
# result is output depends on whether GDB is built as a C or C++
# program.
gdb_test "print symfile_complaint_book.root->next == &complaint_sentinel" \
".\[0-9\]+ = \(1|true\)" "list has one entry"
# Add a second complaint, expect it # Add a second complaint, expect it
gdb_test_stdio \ gdb_test_stdio \
"call complaint_internal (\"Testing! Testing! Testing!\")" \ "call complaint_internal (\"Testing! Testing! Testing!\")" \