Fix regression 'info variables' does not show minimal symbols.
[external/binutils.git] / gdb / skip.c
1 /* Skipping uninteresting files and functions while stepping.
2
3    Copyright (C) 2011-2018 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 ()); /* 4 */
417       if (e.function_is_regexp ())
418         current_uiout->field_string ("regexp", "y"); /* 5 */
419       else
420         current_uiout->field_string ("regexp", "n"); /* 5 */
421
422       current_uiout->field_string ("function",
423                                    e.function ().empty () ? "<none>"
424                                    : e.function ().c_str ()); /* 6 */
425
426       current_uiout->text ("\n");
427     }
428 }
429
430 static void
431 skip_enable_command (const char *arg, int from_tty)
432 {
433   bool found = false;
434
435   for (skiplist_entry &e : skiplist_entries)
436     if (arg == NULL || number_is_in_list (arg, e.number ()))
437       {
438         e.enable ();
439         found = true;
440       }
441
442   if (!found)
443     error (_("No skiplist entries found with number %s."), arg);
444 }
445
446 static void
447 skip_disable_command (const char *arg, int from_tty)
448 {
449   bool found = false;
450
451   for (skiplist_entry &e : skiplist_entries)
452     if (arg == NULL || number_is_in_list (arg, e.number ()))
453       {
454         e.disable ();
455         found = true;
456       }
457
458   if (!found)
459     error (_("No skiplist entries found with number %s."), arg);
460 }
461
462 static void
463 skip_delete_command (const char *arg, int from_tty)
464 {
465   bool found = false;
466
467   for (auto it = skiplist_entries.begin (),
468          end = skiplist_entries.end ();
469        it != end;)
470     {
471       const skiplist_entry &e = *it;
472
473       if (arg == NULL || number_is_in_list (arg, e.number ()))
474         {
475           it = skiplist_entries.erase (it);
476           found = true;
477         }
478       else
479         ++it;
480     }
481
482   if (!found)
483     error (_("No skiplist entries found with number %s."), arg);
484 }
485
486 bool
487 skiplist_entry::do_skip_file_p (const symtab_and_line &function_sal) const
488 {
489   if (debug_skip)
490     fprintf_unfiltered (gdb_stdlog,
491                         "skip: checking if file %s matches non-glob %s...",
492                         function_sal.symtab->filename, m_file.c_str ());
493
494   bool result;
495
496   /* Check first sole SYMTAB->FILENAME.  It may not be a substring of
497      symtab_to_fullname as it may contain "./" etc.  */
498   if (compare_filenames_for_search (function_sal.symtab->filename,
499                                     m_file.c_str ()))
500     result = true;
501
502   /* Before we invoke realpath, which can get expensive when many
503      files are involved, do a quick comparison of the basenames.  */
504   else if (!basenames_may_differ
505            && filename_cmp (lbasename (function_sal.symtab->filename),
506                             lbasename (m_file.c_str ())) != 0)
507     result = false;
508   else
509     {
510       /* Note: symtab_to_fullname caches its result, thus we don't have to.  */
511       const char *fullname = symtab_to_fullname (function_sal.symtab);
512
513       result = compare_filenames_for_search (fullname, m_file.c_str ());
514     }
515
516   if (debug_skip)
517     fprintf_unfiltered (gdb_stdlog, result ? "yes.\n" : "no.\n");
518
519   return result;
520 }
521
522 bool
523 skiplist_entry::do_skip_gfile_p (const symtab_and_line &function_sal) const
524 {
525   if (debug_skip)
526     fprintf_unfiltered (gdb_stdlog,
527                         "skip: checking if file %s matches glob %s...",
528                         function_sal.symtab->filename, m_file.c_str ());
529
530   bool result;
531
532   /* Check first sole SYMTAB->FILENAME.  It may not be a substring of
533      symtab_to_fullname as it may contain "./" etc.  */
534   if (gdb_filename_fnmatch (m_file.c_str (), function_sal.symtab->filename,
535                             FNM_FILE_NAME | FNM_NOESCAPE) == 0)
536     result = true;
537
538   /* Before we invoke symtab_to_fullname, which is expensive, do a quick
539      comparison of the basenames.
540      Note that we assume that lbasename works with glob-style patterns.
541      If the basename of the glob pattern is something like "*.c" then this
542      isn't much of a win.  Oh well.  */
543   else if (!basenames_may_differ
544       && gdb_filename_fnmatch (lbasename (m_file.c_str ()),
545                                lbasename (function_sal.symtab->filename),
546                                FNM_FILE_NAME | FNM_NOESCAPE) != 0)
547     result = false;
548   else
549     {
550       /* Note: symtab_to_fullname caches its result, thus we don't have to.  */
551       const char *fullname = symtab_to_fullname (function_sal.symtab);
552
553       result = compare_glob_filenames_for_search (fullname, m_file.c_str ());
554     }
555
556   if (debug_skip)
557     fprintf_unfiltered (gdb_stdlog, result ? "yes.\n" : "no.\n");
558
559   return result;
560 }
561
562 bool
563 skiplist_entry::skip_file_p (const symtab_and_line &function_sal) const
564 {
565   if (m_file.empty ())
566     return false;
567
568   if (function_sal.symtab == NULL)
569     return false;
570
571   if (m_file_is_glob)
572     return do_skip_gfile_p (function_sal);
573   else
574     return do_skip_file_p (function_sal);
575 }
576
577 bool
578 skiplist_entry::skip_function_p (const char *function_name) const
579 {
580   if (m_function.empty ())
581     return false;
582
583   bool result;
584
585   if (m_function_is_regexp)
586     {
587       if (debug_skip)
588         fprintf_unfiltered (gdb_stdlog,
589                             "skip: checking if function %s matches regex %s...",
590                             function_name, m_function.c_str ());
591
592       gdb_assert (m_compiled_function_regexp);
593       result
594         = (m_compiled_function_regexp->exec (function_name, 0, NULL, 0) == 0);
595     }
596   else
597     {
598       if (debug_skip)
599         fprintf_unfiltered (gdb_stdlog,
600                             ("skip: checking if function %s matches non-regex "
601                              "%s..."),
602                             function_name, m_function.c_str ());
603       result = (strcmp_iw (function_name, m_function.c_str ()) == 0);
604     }
605
606   if (debug_skip)
607     fprintf_unfiltered (gdb_stdlog, result ? "yes.\n" : "no.\n");
608
609   return result;
610 }
611
612 /* See skip.h.  */
613
614 bool
615 function_name_is_marked_for_skip (const char *function_name,
616                                   const symtab_and_line &function_sal)
617 {
618   if (function_name == NULL)
619     return false;
620
621   for (const skiplist_entry &e : skiplist_entries)
622     {
623       if (!e.enabled ())
624         continue;
625
626       bool skip_by_file = e.skip_file_p (function_sal);
627       bool skip_by_function = e.skip_function_p (function_name);
628
629       /* If both file and function must match, make sure we don't errantly
630          exit if only one of them match.  */
631       if (!e.file ().empty () && !e.function ().empty ())
632         {
633           if (skip_by_file && skip_by_function)
634             return true;
635         }
636       /* Only one of file/function is specified.  */
637       else if (skip_by_file || skip_by_function)
638         return true;
639     }
640
641   return false;
642 }
643
644 /* Completer for skip numbers.  */
645
646 static void
647 complete_skip_number (cmd_list_element *cmd,
648                       completion_tracker &completer,
649                       const char *text, const char *word)
650 {
651   size_t word_len = strlen (word);
652
653   for (const skiplist_entry &entry : skiplist_entries)
654     {
655       gdb::unique_xmalloc_ptr<char> name (xstrprintf ("%d", entry.number ()));
656       if (strncmp (word, name.get (), word_len) == 0)
657         completer.add_completion (std::move (name));
658     }
659 }
660
661 void
662 _initialize_step_skip (void)
663 {
664   static struct cmd_list_element *skiplist = NULL;
665   struct cmd_list_element *c;
666
667   add_prefix_cmd ("skip", class_breakpoint, skip_command, _("\
668 Ignore a function while stepping.\n\
669 \n\
670 Usage: skip [FUNCTION-NAME]\n\
671        skip [FILE-SPEC] [FUNCTION-SPEC]\n\
672 If no arguments are given, ignore the current function.\n\
673 \n\
674 FILE-SPEC is one of:\n\
675        -fi|-file FILE-NAME\n\
676        -gfi|-gfile GLOB-FILE-PATTERN\n\
677 FUNCTION-SPEC is one of:\n\
678        -fu|-function FUNCTION-NAME\n\
679        -rfu|-rfunction FUNCTION-NAME-REGULAR-EXPRESSION"),
680                   &skiplist, "skip ", 1, &cmdlist);
681
682   c = add_cmd ("file", class_breakpoint, skip_file_command, _("\
683 Ignore a file while stepping.\n\
684 Usage: skip file [FILE-NAME]\n\
685 If no filename is given, ignore the current file."),
686                &skiplist);
687   set_cmd_completer (c, filename_completer);
688
689   c = add_cmd ("function", class_breakpoint, skip_function_command, _("\
690 Ignore a function while stepping.\n\
691 Usage: skip function [FUNCTION-NAME]\n\
692 If no function name is given, skip the current function."),
693                &skiplist);
694   set_cmd_completer (c, location_completer);
695
696   c = add_cmd ("enable", class_breakpoint, skip_enable_command, _("\
697 Enable skip entries.  You can specify numbers (e.g. \"skip enable 1 3\"), \
698 ranges (e.g. \"skip enable 4-8\"), or both (e.g. \"skip enable 1 3 4-8\").\n\n\
699 If you don't specify any numbers or ranges, we'll enable all skip entries.\n\n\
700 Usage: skip enable [NUMBER | RANGE]..."),
701                &skiplist);
702   set_cmd_completer (c, complete_skip_number);
703
704   c = add_cmd ("disable", class_breakpoint, skip_disable_command, _("\
705 Disable skip entries.  You can specify numbers (e.g. \"skip disable 1 3\"), \
706 ranges (e.g. \"skip disable 4-8\"), or both (e.g. \"skip disable 1 3 4-8\").\n\n\
707 If you don't specify any numbers or ranges, we'll disable all skip entries.\n\n\
708 Usage: skip disable [NUMBER | RANGE]..."),
709                &skiplist);
710   set_cmd_completer (c, complete_skip_number);
711
712   c = add_cmd ("delete", class_breakpoint, skip_delete_command, _("\
713 Delete skip entries.  You can specify numbers (e.g. \"skip delete 1 3\"), \
714 ranges (e.g. \"skip delete 4-8\"), or both (e.g. \"skip delete 1 3 4-8\").\n\n\
715 If you don't specify any numbers or ranges, we'll delete all skip entries.\n\n\
716 Usage: skip delete [NUMBER | RANGES]..."),
717                &skiplist);
718   set_cmd_completer (c, complete_skip_number);
719
720   add_info ("skip", info_skip_command, _("\
721 Display the status of skips.  You can specify numbers (e.g. \"info skip 1 3\"), \
722 ranges (e.g. \"info skip 4-8\"), or both (e.g. \"info skip 1 3 4-8\").\n\n\
723 If you don't specify any numbers or ranges, we'll show all skips.\n\n\
724 Usage: info skip [NUMBER | RANGES]..."));
725   set_cmd_completer (c, complete_skip_number);
726
727   add_setshow_boolean_cmd ("skip", class_maintenance,
728                            &debug_skip, _("\
729 Set whether to print the debug output about skipping files and functions."),
730                            _("\
731 Show whether the debug output about skipping files and functions is printed"),
732                            _("\
733 When non-zero, debug output about skipping files and functions is displayed."),
734                            NULL, NULL,
735                            &setdebuglist, &showdebuglist);
736 }