Clean up some comments in minsyms.c
[external/binutils.git] / gdb / skip.c
1 /* Skipping uninteresting files and functions while stepping.
2
3    Copyright (C) 2011-2019 Free Software Foundation, Inc.
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18 #include "defs.h"
19 #include "skip.h"
20 #include "value.h"
21 #include "valprint.h"
22 #include "ui-out.h"
23 #include "symtab.h"
24 #include "gdbcmd.h"
25 #include "command.h"
26 #include "completer.h"
27 #include "stack.h"
28 #include "cli/cli-utils.h"
29 #include "arch-utils.h"
30 #include "linespec.h"
31 #include "objfiles.h"
32 #include "breakpoint.h" /* for get_sal_arch () */
33 #include "source.h"
34 #include "filenames.h"
35 #include "fnmatch.h"
36 #include "gdb_regex.h"
37 #include "common/gdb_optional.h"
38 #include <list>
39
40 /* True if we want to print debug printouts related to file/function
41    skipping. */
42 static int debug_skip = 0;
43
44 class skiplist_entry
45 {
46 public:
47   /* Create a skiplist_entry object and add it to the chain.  */
48   static void add_entry (bool file_is_glob,
49                          std::string &&file,
50                          bool function_is_regexp,
51                          std::string &&function);
52
53   /* Return true if the skip entry has a file or glob-style file
54      pattern that matches FUNCTION_SAL.  */
55   bool skip_file_p (const symtab_and_line &function_sal) const;
56
57   /* Return true if the skip entry has a function or function regexp
58      that matches FUNCTION_NAME.  */
59   bool skip_function_p (const char *function_name) const;
60
61   /* Getters.  */
62   int number () const { return m_number; };
63   bool enabled () const { return m_enabled; };
64   bool file_is_glob () const { return m_file_is_glob; }
65   const std::string &file () const { return m_file; }
66   const std::string &function () const { return m_function; }
67   bool function_is_regexp () const { return m_function_is_regexp; }
68
69   /* Setters.  */
70   void enable () { m_enabled = true; };
71   void disable () { m_enabled = false; };
72
73   /* Disable copy.  */
74   skiplist_entry (const skiplist_entry &) = delete;
75   void operator= (const skiplist_entry &) = delete;
76
77 private:
78   /* Key that grants access to the constructor.  */
79   struct private_key {};
80 public:
81   /* Public so we can construct with container::emplace_back.  Since
82      it requires a private class key, it can't be called from outside.
83      Use the add_entry static factory method to construct instead.  */
84   skiplist_entry (bool file_is_glob, std::string &&file,
85                   bool function_is_regexp, std::string &&function,
86                   private_key);
87
88 private:
89   /* Return true if we're stopped at a file to be skipped.  */
90   bool do_skip_file_p (const symtab_and_line &function_sal) const;
91
92   /* Return true if we're stopped at a globbed file to be skipped.  */
93   bool do_skip_gfile_p (const symtab_and_line &function_sal) const;
94
95 private: /* data */
96   int m_number = -1;
97
98   /* True if FILE is a glob-style pattern.
99      Otherwise it is the plain file name (possibly with directories).  */
100   bool m_file_is_glob;
101
102   /* The name of the file or empty if no name.  */
103   std::string m_file;
104
105   /* True if FUNCTION is a regexp.
106      Otherwise it is a plain function name (possibly with arguments,
107      for C++).  */
108   bool m_function_is_regexp;
109
110   /* The name of the function or empty if no name.  */
111   std::string m_function;
112
113   /* If this is a function regexp, the compiled form.  */
114   gdb::optional<compiled_regex> m_compiled_function_regexp;
115
116   /* Enabled/disabled state.  */
117   bool m_enabled = true;
118 };
119
120 static std::list<skiplist_entry> skiplist_entries;
121 static int highest_skiplist_entry_num = 0;
122
123 skiplist_entry::skiplist_entry (bool file_is_glob,
124                                 std::string &&file,
125                                 bool function_is_regexp,
126                                 std::string &&function,
127                                 private_key)
128   : m_file_is_glob (file_is_glob),
129     m_file (std::move (file)),
130     m_function_is_regexp (function_is_regexp),
131     m_function (std::move (function))
132 {
133   gdb_assert (!m_file.empty () || !m_function.empty ());
134
135   if (m_file_is_glob)
136     gdb_assert (!m_file.empty ());
137
138   if (m_function_is_regexp)
139     {
140       gdb_assert (!m_function.empty ());
141
142       int flags = REG_NOSUB;
143 #ifdef REG_EXTENDED
144       flags |= REG_EXTENDED;
145 #endif
146
147       gdb_assert (!m_function.empty ());
148       m_compiled_function_regexp.emplace (m_function.c_str (), flags,
149                                           _("regexp"));
150     }
151 }
152
153 void
154 skiplist_entry::add_entry (bool file_is_glob, std::string &&file,
155                            bool function_is_regexp, std::string &&function)
156 {
157   skiplist_entries.emplace_back (file_is_glob,
158                                  std::move (file),
159                                  function_is_regexp,
160                                  std::move (function),
161                                  private_key {});
162
163   /* Incremented after push_back, in case push_back throws.  */
164   skiplist_entries.back ().m_number = ++highest_skiplist_entry_num;
165 }
166
167 static void
168 skip_file_command (const char *arg, int from_tty)
169 {
170   struct symtab *symtab;
171   const char *filename = NULL;
172
173   /* If no argument was given, try to default to the last
174      displayed codepoint.  */
175   if (arg == NULL)
176     {
177       symtab = get_last_displayed_symtab ();
178       if (symtab == NULL)
179         error (_("No default file now."));
180
181       /* It is not a typo, symtab_to_filename_for_display woule be needlessly
182          ambiguous.  */
183       filename = symtab_to_fullname (symtab);
184     }
185   else
186     filename = arg;
187
188   skiplist_entry::add_entry (false, std::string (filename),
189                              false, std::string ());
190
191   printf_filtered (_("File %s will be skipped when stepping.\n"), filename);
192 }
193
194 /* Create a skiplist entry for the given function NAME and add it to the
195    list.  */
196
197 static void
198 skip_function (const char *name)
199 {
200   skiplist_entry::add_entry (false, std::string (), false, std::string (name));
201
202   printf_filtered (_("Function %s will be skipped when stepping.\n"), name);
203 }
204
205 static void
206 skip_function_command (const char *arg, int from_tty)
207 {
208   /* Default to the current function if no argument is given.  */
209   if (arg == NULL)
210     {
211       const char *name = NULL;
212       CORE_ADDR pc;
213
214       if (!last_displayed_sal_is_valid ())
215         error (_("No default function now."));
216
217       pc = get_last_displayed_addr ();
218       if (!find_pc_partial_function (pc, &name, NULL, NULL))
219         {
220           error (_("No function found containing current program point %s."),
221                   paddress (get_current_arch (), pc));
222         }
223       skip_function (name);
224       return;
225     }
226
227   skip_function (arg);
228 }
229
230 /* Process "skip ..." that does not match "skip file" or "skip function".  */
231
232 static void
233 skip_command (const char *arg, int from_tty)
234 {
235   const char *file = NULL;
236   const char *gfile = NULL;
237   const char *function = NULL;
238   const char *rfunction = NULL;
239   int i;
240
241   if (arg == NULL)
242     {
243       skip_function_command (arg, from_tty);
244       return;
245     }
246
247   gdb_argv argv (arg);
248
249   for (i = 0; argv[i] != NULL; ++i)
250     {
251       const char *p = argv[i];
252       const char *value = argv[i + 1];
253
254       if (strcmp (p, "-fi") == 0
255           || strcmp (p, "-file") == 0)
256         {
257           if (value == NULL)
258             error (_("Missing value for %s option."), p);
259           file = value;
260           ++i;
261         }
262       else if (strcmp (p, "-gfi") == 0
263                || strcmp (p, "-gfile") == 0)
264         {
265           if (value == NULL)
266             error (_("Missing value for %s option."), p);
267           gfile = value;
268           ++i;
269         }
270       else if (strcmp (p, "-fu") == 0
271                || strcmp (p, "-function") == 0)
272         {
273           if (value == NULL)
274             error (_("Missing value for %s option."), p);
275           function = value;
276           ++i;
277         }
278       else if (strcmp (p, "-rfu") == 0
279                || strcmp (p, "-rfunction") == 0)
280         {
281           if (value == NULL)
282             error (_("Missing value for %s option."), p);
283           rfunction = value;
284           ++i;
285         }
286       else if (*p == '-')
287         error (_("Invalid skip option: %s"), p);
288       else if (i == 0)
289         {
290           /* Assume the user entered "skip FUNCTION-NAME".
291              FUNCTION-NAME may be `foo (int)', and therefore we pass the
292              complete original arg to skip_function command as if the user
293              typed "skip function arg".  */
294           skip_function_command (arg, from_tty);
295           return;
296         }
297       else
298         error (_("Invalid argument: %s"), p);
299     }
300
301   if (file != NULL && gfile != NULL)
302     error (_("Cannot specify both -file and -gfile."));
303
304   if (function != NULL && rfunction != NULL)
305     error (_("Cannot specify both -function and -rfunction."));
306
307   /* This shouldn't happen as "skip" by itself gets punted to
308      skip_function_command.  */
309   gdb_assert (file != NULL || gfile != NULL
310               || function != NULL || rfunction != NULL);
311
312   std::string entry_file;
313   if (file != NULL)
314     entry_file = file;
315   else if (gfile != NULL)
316     entry_file = gfile;
317
318   std::string entry_function;
319   if (function != NULL)
320     entry_function = function;
321   else if (rfunction != NULL)
322     entry_function = rfunction;
323
324   skiplist_entry::add_entry (gfile != NULL, std::move (entry_file),
325                              rfunction != NULL, std::move (entry_function));
326
327   /* I18N concerns drive some of the choices here (we can't piece together
328      the output too much).  OTOH we want to keep this simple.  Therefore the
329      only polish we add to the output is to append "(s)" to "File" or
330      "Function" if they're a glob/regexp.  */
331   {
332     const char *file_to_print = file != NULL ? file : gfile;
333     const char *function_to_print = function != NULL ? function : rfunction;
334     const char *file_text = gfile != NULL ? _("File(s)") : _("File");
335     const char *lower_file_text = gfile != NULL ? _("file(s)") : _("file");
336     const char *function_text
337       = rfunction != NULL ? _("Function(s)") : _("Function");
338
339     if (function_to_print == NULL)
340       {
341         printf_filtered (_("%s %s will be skipped when stepping.\n"),
342                          file_text, file_to_print);
343       }
344     else if (file_to_print == NULL)
345       {
346         printf_filtered (_("%s %s will be skipped when stepping.\n"),
347                          function_text, function_to_print);
348       }
349     else
350       {
351         printf_filtered (_("%s %s in %s %s will be skipped"
352                            " when stepping.\n"),
353                          function_text, function_to_print,
354                          lower_file_text, file_to_print);
355       }
356   }
357 }
358
359 static void
360 info_skip_command (const char *arg, int from_tty)
361 {
362   int num_printable_entries = 0;
363   struct value_print_options opts;
364
365   get_user_print_options (&opts);
366
367   /* Count the number of rows in the table and see if we need space for a
368      64-bit address anywhere.  */
369   for (const skiplist_entry &e : skiplist_entries)
370     if (arg == NULL || number_is_in_list (arg, e.number ()))
371       num_printable_entries++;
372
373   if (num_printable_entries == 0)
374     {
375       if (arg == NULL)
376         current_uiout->message (_("Not skipping any files or functions.\n"));
377       else
378         current_uiout->message (
379           _("No skiplist entries found with number %s.\n"), arg);
380
381       return;
382     }
383
384   ui_out_emit_table table_emitter (current_uiout, 6, num_printable_entries,
385                                    "SkiplistTable");
386
387   current_uiout->table_header (5, ui_left, "number", "Num");   /* 1 */
388   current_uiout->table_header (3, ui_left, "enabled", "Enb");  /* 2 */
389   current_uiout->table_header (4, ui_right, "regexp", "Glob"); /* 3 */
390   current_uiout->table_header (20, ui_left, "file", "File");   /* 4 */
391   current_uiout->table_header (2, ui_right, "regexp", "RE");   /* 5 */
392   current_uiout->table_header (40, ui_noalign, "function", "Function"); /* 6 */
393   current_uiout->table_body ();
394
395   for (const skiplist_entry &e : skiplist_entries)
396     {
397       QUIT;
398       if (arg != NULL && !number_is_in_list (arg, e.number ()))
399         continue;
400
401       ui_out_emit_tuple tuple_emitter (current_uiout, "blklst-entry");
402       current_uiout->field_int ("number", e.number ()); /* 1 */
403
404       if (e.enabled ())
405         current_uiout->field_string ("enabled", "y"); /* 2 */
406       else
407         current_uiout->field_string ("enabled", "n"); /* 2 */
408
409       if (e.file_is_glob ())
410         current_uiout->field_string ("regexp", "y"); /* 3 */
411       else
412         current_uiout->field_string ("regexp", "n"); /* 3 */
413
414       current_uiout->field_string ("file",
415                                    e.file ().empty () ? "<none>"
416                                    : e.file ().c_str (),
417                                    ui_out_style_kind::FILE); /* 4 */
418       if (e.function_is_regexp ())
419         current_uiout->field_string ("regexp", "y"); /* 5 */
420       else
421         current_uiout->field_string ("regexp", "n"); /* 5 */
422
423       current_uiout->field_string ("function",
424                                    e.function ().empty () ? "<none>"
425                                    : e.function ().c_str (),
426                                    ui_out_style_kind::FUNCTION); /* 6 */
427
428       current_uiout->text ("\n");
429     }
430 }
431
432 static void
433 skip_enable_command (const char *arg, int from_tty)
434 {
435   bool found = false;
436
437   for (skiplist_entry &e : skiplist_entries)
438     if (arg == NULL || number_is_in_list (arg, e.number ()))
439       {
440         e.enable ();
441         found = true;
442       }
443
444   if (!found)
445     error (_("No skiplist entries found with number %s."), arg);
446 }
447
448 static void
449 skip_disable_command (const char *arg, int from_tty)
450 {
451   bool found = false;
452
453   for (skiplist_entry &e : skiplist_entries)
454     if (arg == NULL || number_is_in_list (arg, e.number ()))
455       {
456         e.disable ();
457         found = true;
458       }
459
460   if (!found)
461     error (_("No skiplist entries found with number %s."), arg);
462 }
463
464 static void
465 skip_delete_command (const char *arg, int from_tty)
466 {
467   bool found = false;
468
469   for (auto it = skiplist_entries.begin (),
470          end = skiplist_entries.end ();
471        it != end;)
472     {
473       const skiplist_entry &e = *it;
474
475       if (arg == NULL || number_is_in_list (arg, e.number ()))
476         {
477           it = skiplist_entries.erase (it);
478           found = true;
479         }
480       else
481         ++it;
482     }
483
484   if (!found)
485     error (_("No skiplist entries found with number %s."), arg);
486 }
487
488 bool
489 skiplist_entry::do_skip_file_p (const symtab_and_line &function_sal) const
490 {
491   if (debug_skip)
492     fprintf_unfiltered (gdb_stdlog,
493                         "skip: checking if file %s matches non-glob %s...",
494                         function_sal.symtab->filename, m_file.c_str ());
495
496   bool result;
497
498   /* Check first sole SYMTAB->FILENAME.  It may not be a substring of
499      symtab_to_fullname as it may contain "./" etc.  */
500   if (compare_filenames_for_search (function_sal.symtab->filename,
501                                     m_file.c_str ()))
502     result = true;
503
504   /* Before we invoke realpath, which can get expensive when many
505      files are involved, do a quick comparison of the basenames.  */
506   else if (!basenames_may_differ
507            && filename_cmp (lbasename (function_sal.symtab->filename),
508                             lbasename (m_file.c_str ())) != 0)
509     result = false;
510   else
511     {
512       /* Note: symtab_to_fullname caches its result, thus we don't have to.  */
513       const char *fullname = symtab_to_fullname (function_sal.symtab);
514
515       result = compare_filenames_for_search (fullname, m_file.c_str ());
516     }
517
518   if (debug_skip)
519     fprintf_unfiltered (gdb_stdlog, result ? "yes.\n" : "no.\n");
520
521   return result;
522 }
523
524 bool
525 skiplist_entry::do_skip_gfile_p (const symtab_and_line &function_sal) const
526 {
527   if (debug_skip)
528     fprintf_unfiltered (gdb_stdlog,
529                         "skip: checking if file %s matches glob %s...",
530                         function_sal.symtab->filename, m_file.c_str ());
531
532   bool result;
533
534   /* Check first sole SYMTAB->FILENAME.  It may not be a substring of
535      symtab_to_fullname as it may contain "./" etc.  */
536   if (gdb_filename_fnmatch (m_file.c_str (), function_sal.symtab->filename,
537                             FNM_FILE_NAME | FNM_NOESCAPE) == 0)
538     result = true;
539
540   /* Before we invoke symtab_to_fullname, which is expensive, do a quick
541      comparison of the basenames.
542      Note that we assume that lbasename works with glob-style patterns.
543      If the basename of the glob pattern is something like "*.c" then this
544      isn't much of a win.  Oh well.  */
545   else if (!basenames_may_differ
546       && gdb_filename_fnmatch (lbasename (m_file.c_str ()),
547                                lbasename (function_sal.symtab->filename),
548                                FNM_FILE_NAME | FNM_NOESCAPE) != 0)
549     result = false;
550   else
551     {
552       /* Note: symtab_to_fullname caches its result, thus we don't have to.  */
553       const char *fullname = symtab_to_fullname (function_sal.symtab);
554
555       result = compare_glob_filenames_for_search (fullname, m_file.c_str ());
556     }
557
558   if (debug_skip)
559     fprintf_unfiltered (gdb_stdlog, result ? "yes.\n" : "no.\n");
560
561   return result;
562 }
563
564 bool
565 skiplist_entry::skip_file_p (const symtab_and_line &function_sal) const
566 {
567   if (m_file.empty ())
568     return false;
569
570   if (function_sal.symtab == NULL)
571     return false;
572
573   if (m_file_is_glob)
574     return do_skip_gfile_p (function_sal);
575   else
576     return do_skip_file_p (function_sal);
577 }
578
579 bool
580 skiplist_entry::skip_function_p (const char *function_name) const
581 {
582   if (m_function.empty ())
583     return false;
584
585   bool result;
586
587   if (m_function_is_regexp)
588     {
589       if (debug_skip)
590         fprintf_unfiltered (gdb_stdlog,
591                             "skip: checking if function %s matches regex %s...",
592                             function_name, m_function.c_str ());
593
594       gdb_assert (m_compiled_function_regexp);
595       result
596         = (m_compiled_function_regexp->exec (function_name, 0, NULL, 0) == 0);
597     }
598   else
599     {
600       if (debug_skip)
601         fprintf_unfiltered (gdb_stdlog,
602                             ("skip: checking if function %s matches non-regex "
603                              "%s..."),
604                             function_name, m_function.c_str ());
605       result = (strcmp_iw (function_name, m_function.c_str ()) == 0);
606     }
607
608   if (debug_skip)
609     fprintf_unfiltered (gdb_stdlog, result ? "yes.\n" : "no.\n");
610
611   return result;
612 }
613
614 /* See skip.h.  */
615
616 bool
617 function_name_is_marked_for_skip (const char *function_name,
618                                   const symtab_and_line &function_sal)
619 {
620   if (function_name == NULL)
621     return false;
622
623   for (const skiplist_entry &e : skiplist_entries)
624     {
625       if (!e.enabled ())
626         continue;
627
628       bool skip_by_file = e.skip_file_p (function_sal);
629       bool skip_by_function = e.skip_function_p (function_name);
630
631       /* If both file and function must match, make sure we don't errantly
632          exit if only one of them match.  */
633       if (!e.file ().empty () && !e.function ().empty ())
634         {
635           if (skip_by_file && skip_by_function)
636             return true;
637         }
638       /* Only one of file/function is specified.  */
639       else if (skip_by_file || skip_by_function)
640         return true;
641     }
642
643   return false;
644 }
645
646 /* Completer for skip numbers.  */
647
648 static void
649 complete_skip_number (cmd_list_element *cmd,
650                       completion_tracker &completer,
651                       const char *text, const char *word)
652 {
653   size_t word_len = strlen (word);
654
655   for (const skiplist_entry &entry : skiplist_entries)
656     {
657       gdb::unique_xmalloc_ptr<char> name (xstrprintf ("%d", entry.number ()));
658       if (strncmp (word, name.get (), word_len) == 0)
659         completer.add_completion (std::move (name));
660     }
661 }
662
663 void
664 _initialize_step_skip (void)
665 {
666   static struct cmd_list_element *skiplist = NULL;
667   struct cmd_list_element *c;
668
669   add_prefix_cmd ("skip", class_breakpoint, skip_command, _("\
670 Ignore a function while stepping.\n\
671 \n\
672 Usage: skip [FUNCTION-NAME]\n\
673        skip [FILE-SPEC] [FUNCTION-SPEC]\n\
674 If no arguments are given, ignore the current function.\n\
675 \n\
676 FILE-SPEC is one of:\n\
677        -fi|-file FILE-NAME\n\
678        -gfi|-gfile GLOB-FILE-PATTERN\n\
679 FUNCTION-SPEC is one of:\n\
680        -fu|-function FUNCTION-NAME\n\
681        -rfu|-rfunction FUNCTION-NAME-REGULAR-EXPRESSION"),
682                   &skiplist, "skip ", 1, &cmdlist);
683
684   c = add_cmd ("file", class_breakpoint, skip_file_command, _("\
685 Ignore a file while stepping.\n\
686 Usage: skip file [FILE-NAME]\n\
687 If no filename is given, ignore the current file."),
688                &skiplist);
689   set_cmd_completer (c, filename_completer);
690
691   c = add_cmd ("function", class_breakpoint, skip_function_command, _("\
692 Ignore a function while stepping.\n\
693 Usage: skip function [FUNCTION-NAME]\n\
694 If no function name is given, skip the current function."),
695                &skiplist);
696   set_cmd_completer (c, location_completer);
697
698   c = add_cmd ("enable", class_breakpoint, skip_enable_command, _("\
699 Enable skip entries.  You can specify numbers (e.g. \"skip enable 1 3\"), \
700 ranges (e.g. \"skip enable 4-8\"), or both (e.g. \"skip enable 1 3 4-8\").\n\n\
701 If you don't specify any numbers or ranges, we'll enable all skip entries.\n\n\
702 Usage: skip enable [NUMBER | RANGE]..."),
703                &skiplist);
704   set_cmd_completer (c, complete_skip_number);
705
706   c = add_cmd ("disable", class_breakpoint, skip_disable_command, _("\
707 Disable skip entries.  You can specify numbers (e.g. \"skip disable 1 3\"), \
708 ranges (e.g. \"skip disable 4-8\"), or both (e.g. \"skip disable 1 3 4-8\").\n\n\
709 If you don't specify any numbers or ranges, we'll disable all skip entries.\n\n\
710 Usage: skip disable [NUMBER | RANGE]..."),
711                &skiplist);
712   set_cmd_completer (c, complete_skip_number);
713
714   c = add_cmd ("delete", class_breakpoint, skip_delete_command, _("\
715 Delete skip entries.  You can specify numbers (e.g. \"skip delete 1 3\"), \
716 ranges (e.g. \"skip delete 4-8\"), or both (e.g. \"skip delete 1 3 4-8\").\n\n\
717 If you don't specify any numbers or ranges, we'll delete all skip entries.\n\n\
718 Usage: skip delete [NUMBER | RANGES]..."),
719                &skiplist);
720   set_cmd_completer (c, complete_skip_number);
721
722   add_info ("skip", info_skip_command, _("\
723 Display the status of skips.  You can specify numbers (e.g. \"info skip 1 3\"), \
724 ranges (e.g. \"info skip 4-8\"), or both (e.g. \"info skip 1 3 4-8\").\n\n\
725 If you don't specify any numbers or ranges, we'll show all skips.\n\n\
726 Usage: info skip [NUMBER | RANGES]..."));
727   set_cmd_completer (c, complete_skip_number);
728
729   add_setshow_boolean_cmd ("skip", class_maintenance,
730                            &debug_skip, _("\
731 Set whether to print the debug output about skipping files and functions."),
732                            _("\
733 Show whether the debug output about skipping files and functions is printed"),
734                            _("\
735 When non-zero, debug output about skipping files and functions is displayed."),
736                            NULL, NULL,
737                            &setdebuglist, &showdebuglist);
738 }