GDB (API)
|
00001 /* Support for complaint handling during symbol reading in GDB. 00002 00003 Copyright (C) 1990-2013 Free Software Foundation, Inc. 00004 00005 This file is part of GDB. 00006 00007 This program is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 3 of the License, or 00010 (at your option) any later version. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00019 00020 #include "defs.h" 00021 #include "complaints.h" 00022 #include "gdb_assert.h" 00023 #include "command.h" 00024 #include "gdbcmd.h" 00025 00026 extern void _initialize_complaints (void); 00027 00028 /* Should each complaint message be self explanatory, or should we 00029 assume that a series of complaints is being produced? */ 00030 00031 /* case 1: First message of a series that must 00032 start off with explanation. case 2: Subsequent message of a series 00033 that needs no explanation (the user already knows we have a problem 00034 so we can just state our piece). */ 00035 enum complaint_series { 00036 /* Isolated self explanatory message. */ 00037 ISOLATED_MESSAGE, 00038 /* First message of a series, includes an explanation. */ 00039 FIRST_MESSAGE, 00040 /* First message of a series, but does not need to include any sort 00041 of explanation. */ 00042 SHORT_FIRST_MESSAGE, 00043 /* Subsequent message of a series that needs no explanation (the 00044 user already knows we have a problem so we can just state our 00045 piece). */ 00046 SUBSEQUENT_MESSAGE 00047 }; 00048 00049 /* Structure to manage complaints about symbol file contents. */ 00050 00051 struct complain 00052 { 00053 const char *file; 00054 int line; 00055 const char *fmt; 00056 int counter; 00057 struct complain *next; 00058 }; 00059 00060 /* The explanatory message that should accompany the complaint. The 00061 message is in two parts - pre and post - that are printed around 00062 the complaint text. */ 00063 struct explanation 00064 { 00065 const char *prefix; 00066 const char *postfix; 00067 }; 00068 00069 struct complaints 00070 { 00071 struct complain *root; 00072 00073 /* Should each complaint be self explanatory, or should we assume 00074 that a series of complaints is being produced? case 0: Isolated 00075 self explanatory message. case 1: First message of a series that 00076 must start off with explanation. case 2: Subsequent message of a 00077 series that needs no explanation (the user already knows we have 00078 a problem so we can just state our piece). */ 00079 int series; 00080 00081 /* The explanatory messages that should accompany the complaint. 00082 NOTE: cagney/2002-08-14: In a desperate attempt at being vaguely 00083 i18n friendly, this is an array of two messages. When present, 00084 the PRE and POST EXPLANATION[SERIES] are used to wrap the 00085 message. */ 00086 const struct explanation *explanation; 00087 }; 00088 00089 static struct complain complaint_sentinel; 00090 00091 /* The symbol table complaint table. */ 00092 00093 static struct explanation symfile_explanations[] = { 00094 { "During symbol reading, ", "." }, 00095 { "During symbol reading...", "..."}, 00096 { "", "..."}, 00097 { "", "..."}, 00098 { NULL, NULL } 00099 }; 00100 00101 static struct complaints symfile_complaint_book = { 00102 &complaint_sentinel, 00103 0, 00104 symfile_explanations 00105 }; 00106 struct complaints *symfile_complaints = &symfile_complaint_book; 00107 00108 /* Wrapper function to, on-demand, fill in a complaints object. */ 00109 00110 static struct complaints * 00111 get_complaints (struct complaints **c) 00112 { 00113 if ((*c) != NULL) 00114 return (*c); 00115 (*c) = XMALLOC (struct complaints); 00116 (*c)->root = &complaint_sentinel; 00117 (*c)->series = ISOLATED_MESSAGE; 00118 (*c)->explanation = NULL; 00119 return (*c); 00120 } 00121 00122 static struct complain * ATTRIBUTE_PRINTF (4, 0) 00123 find_complaint (struct complaints *complaints, const char *file, 00124 int line, const char *fmt) 00125 { 00126 struct complain *complaint; 00127 00128 /* Find the complaint in the table. A more efficient search 00129 algorithm (based on hash table or something) could be used. But 00130 that can wait until someone shows evidence that this lookup is 00131 a real bottle neck. */ 00132 for (complaint = complaints->root; 00133 complaint != NULL; 00134 complaint = complaint->next) 00135 { 00136 if (complaint->fmt == fmt 00137 && complaint->file == file 00138 && complaint->line == line) 00139 return complaint; 00140 } 00141 00142 /* Oops not seen before, fill in a new complaint. */ 00143 complaint = XMALLOC (struct complain); 00144 complaint->fmt = fmt; 00145 complaint->file = file; 00146 complaint->line = line; 00147 complaint->counter = 0; 00148 complaint->next = NULL; 00149 00150 /* File it, return it. */ 00151 complaint->next = complaints->root; 00152 complaints->root = complaint; 00153 return complaint; 00154 } 00155 00156 00157 /* How many complaints about a particular thing should be printed 00158 before we stop whining about it? Default is no whining at all, 00159 since so many systems have ill-constructed symbol files. */ 00160 00161 static int stop_whining = 0; 00162 00163 /* Print a complaint, and link the complaint block into a chain for 00164 later handling. */ 00165 00166 static void ATTRIBUTE_PRINTF (4, 0) 00167 vcomplaint (struct complaints **c, const char *file, 00168 int line, const char *fmt, 00169 va_list args) 00170 { 00171 struct complaints *complaints = get_complaints (c); 00172 struct complain *complaint = find_complaint (complaints, file, 00173 line, fmt); 00174 enum complaint_series series; 00175 00176 gdb_assert (complaints != NULL); 00177 00178 complaint->counter++; 00179 if (complaint->counter > stop_whining) 00180 return; 00181 00182 if (info_verbose) 00183 series = SUBSEQUENT_MESSAGE; 00184 else 00185 series = complaints->series; 00186 00187 if (complaint->file != NULL) 00188 internal_vwarning (complaint->file, complaint->line, 00189 complaint->fmt, args); 00190 else if (deprecated_warning_hook) 00191 (*deprecated_warning_hook) (complaint->fmt, args); 00192 else 00193 { 00194 if (complaints->explanation == NULL) 00195 /* A [v]warning() call always appends a newline. */ 00196 vwarning (complaint->fmt, args); 00197 else 00198 { 00199 char *msg; 00200 struct cleanup *cleanups; 00201 msg = xstrvprintf (complaint->fmt, args); 00202 cleanups = make_cleanup (xfree, msg); 00203 wrap_here (""); 00204 if (series != SUBSEQUENT_MESSAGE) 00205 begin_line (); 00206 /* XXX: i18n */ 00207 fprintf_filtered (gdb_stderr, "%s%s%s", 00208 complaints->explanation[series].prefix, msg, 00209 complaints->explanation[series].postfix); 00210 /* Force a line-break after any isolated message. For the 00211 other cases, clear_complaints() takes care of any missing 00212 trailing newline, the wrap_here() is just a hint. */ 00213 if (series == ISOLATED_MESSAGE) 00214 /* It would be really nice to use begin_line() here. 00215 Unfortunately that function doesn't track GDB_STDERR and 00216 consequently will sometimes supress a line when it 00217 shouldn't. */ 00218 fputs_filtered ("\n", gdb_stderr); 00219 else 00220 wrap_here (""); 00221 do_cleanups (cleanups); 00222 } 00223 } 00224 00225 switch (series) 00226 { 00227 case ISOLATED_MESSAGE: 00228 break; 00229 case FIRST_MESSAGE: 00230 complaints->series = SUBSEQUENT_MESSAGE; 00231 break; 00232 case SUBSEQUENT_MESSAGE: 00233 case SHORT_FIRST_MESSAGE: 00234 complaints->series = SUBSEQUENT_MESSAGE; 00235 break; 00236 } 00237 00238 /* If GDB dumps core, we'd like to see the complaints first. 00239 Presumably GDB will not be sending so many complaints that this 00240 becomes a performance hog. */ 00241 00242 gdb_flush (gdb_stderr); 00243 } 00244 00245 void 00246 complaint (struct complaints **complaints, const char *fmt, ...) 00247 { 00248 va_list args; 00249 00250 va_start (args, fmt); 00251 vcomplaint (complaints, NULL/*file*/, 0/*line*/, fmt, args); 00252 va_end (args); 00253 } 00254 00255 void 00256 internal_complaint (struct complaints **complaints, const char *file, 00257 int line, const char *fmt, ...) 00258 { 00259 va_list args; 00260 va_start (args, fmt); 00261 vcomplaint (complaints, file, line, fmt, args); 00262 va_end (args); 00263 } 00264 00265 /* Clear out / initialize all complaint counters that have ever been 00266 incremented. If LESS_VERBOSE is 1, be less verbose about 00267 successive complaints, since the messages are appearing all 00268 together during a command that is reporting a contiguous block of 00269 complaints (rather than being interleaved with other messages). If 00270 noisy is 1, we are in a noisy command, and our caller will print 00271 enough context for the user to figure it out. */ 00272 00273 void 00274 clear_complaints (struct complaints **c, int less_verbose, int noisy) 00275 { 00276 struct complaints *complaints = get_complaints (c); 00277 struct complain *p; 00278 00279 for (p = complaints->root; p != NULL; p = p->next) 00280 { 00281 p->counter = 0; 00282 } 00283 00284 switch (complaints->series) 00285 { 00286 case FIRST_MESSAGE: 00287 /* Haven't yet printed anything. */ 00288 break; 00289 case SHORT_FIRST_MESSAGE: 00290 /* Haven't yet printed anything. */ 00291 break; 00292 case ISOLATED_MESSAGE: 00293 /* The code above, always forces a line-break. No need to do it 00294 here. */ 00295 break; 00296 case SUBSEQUENT_MESSAGE: 00297 /* It would be really nice to use begin_line() here. 00298 Unfortunately that function doesn't track GDB_STDERR and 00299 consequently will sometimes supress a line when it 00300 shouldn't. */ 00301 fputs_unfiltered ("\n", gdb_stderr); 00302 break; 00303 default: 00304 internal_error (__FILE__, __LINE__, _("bad switch")); 00305 } 00306 00307 if (!less_verbose) 00308 complaints->series = ISOLATED_MESSAGE; 00309 else if (!noisy) 00310 complaints->series = FIRST_MESSAGE; 00311 else 00312 complaints->series = SHORT_FIRST_MESSAGE; 00313 } 00314 00315 static void 00316 complaints_show_value (struct ui_file *file, int from_tty, 00317 struct cmd_list_element *cmd, const char *value) 00318 { 00319 fprintf_filtered (file, _("Max number of complaints about incorrect" 00320 " symbols is %s.\n"), 00321 value); 00322 } 00323 00324 void 00325 _initialize_complaints (void) 00326 { 00327 add_setshow_zinteger_cmd ("complaints", class_support, 00328 &stop_whining, _("\ 00329 Set max number of complaints about incorrect symbols."), _("\ 00330 Show max number of complaints about incorrect symbols."), NULL, 00331 NULL, complaints_show_value, 00332 &setlist, &showlist); 00333 }