From patchwork Sun Jun 16 20:38:02 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Philippe Waroquiers X-Patchwork-Id: 33155 Received: (qmail 21248 invoked by alias); 16 Jun 2019 20:38:18 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 21184 invoked by uid 89); 16 Jun 2019 20:38:17 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-22.3 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.1 spammy=Does, UD:first X-HELO: mailsec115.isp.belgacom.be Received: from mailsec115.isp.belgacom.be (HELO mailsec115.isp.belgacom.be) (195.238.20.111) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sun, 16 Jun 2019 20:38:15 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=skynet.be; i=@skynet.be; q=dns/txt; s=securemail; t=1560717495; x=1592253495; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=yhSX9FsZyoRVX/1xLLBdmW/6E2pZv0FyIv4Fdk0vrLw=; b=dD3oSlRSp5oIwIabZl62Fd/HxaJZRaLwfCklbkfZFo/STxCpNbIv7Ij4 KRYxl9I8GBWCdysA9Qi8jAA7XpiEaw==; Received: from 161.32-242-81.adsl-dyn.isp.belgacom.be (HELO md.home) ([81.242.32.161]) by relay.skynet.be with ESMTP/TLS/DHE-RSA-AES128-GCM-SHA256; 16 Jun 2019 22:38:11 +0200 From: Philippe Waroquiers To: gdb-patches@sourceware.org Cc: Philippe Waroquiers Subject: [RFAv2 1/3] New "info sources" args [-dirname | -basename] [--] [REGEXP] Date: Sun, 16 Jun 2019 22:38:02 +0200 Message-Id: <20190616203804.26938-2-philippe.waroquiers@skynet.be> In-Reply-To: <20190616203804.26938-1-philippe.waroquiers@skynet.be> References: <20190616203804.26938-1-philippe.waroquiers@skynet.be> MIME-Version: 1.0 X-IsSubscribed: yes gdb/ChangeLog 2019-06-16 Philippe Waroquiers * symtab.c (filename_partial_match_opts): New struct type. (struct output_source_filename_data): New members regexp, c_regexp, partial_match. (output_source_filename): Use new members to decide to print file. (info_sources_option_defs): New variable. (make_info_sources_options_def_group, print_info_sources_header, info_sources_command_completer): New functions. (info_sources_command): Read new optional arguments. (_initialize_symtab): Update info sources help. --- gdb/symtab.c | 158 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 150 insertions(+), 8 deletions(-) diff --git a/gdb/symtab.c b/gdb/symtab.c index 4920d94a24..854af63651 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -4114,10 +4114,28 @@ operator_chars (const char *p, const char **end) } +/* What part to match in a file name. */ + +struct filename_partial_match_opts +{ + /* Only match the directory name part. */ + int dirname = false; + + /* Only match the basename part. */ + int basename = false; +}; + /* Data structure to maintain printing state for output_source_filename. */ struct output_source_filename_data { + /* Output only filenames matching REGEXP. */ + std::string regexp; + gdb::optional c_regexp; + /* Possibly only match a part of the filename. */ + filename_partial_match_opts partial_match; + + /* Cache of what we've seen so far. */ struct filename_seen_cache *filename_seen_cache; @@ -4149,7 +4167,27 @@ output_source_filename (const char *name, return; } - /* No; print it and reset *FIRST. */ + /* Does it match data->regexp? */ + if (data->c_regexp.has_value ()) + { + const char *to_match; + std::string dirname; + + if (data->partial_match.dirname) + { + dirname = ldirname (name); + to_match = dirname.c_str (); + } + else if (data->partial_match.basename) + to_match = lbasename (name); + else + to_match = name; + + if (data->c_regexp->exec (to_match, 0, NULL, 0) != 0) + return; + } + + /* Print it and reset *FIRST. */ if (! data->first) printf_filtered (", "); data->first = 0; @@ -4168,8 +4206,73 @@ output_partial_symbol_filename (const char *filename, const char *fullname, (struct output_source_filename_data *) data); } +using isrc_flag_option_def + = gdb::option::flag_option_def; + +static const gdb::option::option_def info_sources_option_defs[] = { + + isrc_flag_option_def { + "dirname", + [] (filename_partial_match_opts *opts) { return &opts->dirname; }, + N_("Show only the files having a dirname matching REGEXP."), + }, + + isrc_flag_option_def { + "basename", + [] (filename_partial_match_opts *opts) { return &opts->basename; }, + N_("Show only the files having a basename matching REGEXP."), + }, + +}; + +/* Create an option_def_group for the "info sources" options, with + ISRC_OPTS as context. */ + +static inline gdb::option::option_def_group +make_info_sources_options_def_group (filename_partial_match_opts *isrc_opts) +{ + return {{info_sources_option_defs}, isrc_opts}; +} + +/* Prints the header message for the source files that will be printed + with the matching info present in DATA. SYMBOL_MSG is a message + that tells what will or has been done with the symbols of the + matching source files. */ + +static void +print_info_sources_header (const char *symbol_msg, + const struct output_source_filename_data *data) +{ + printf_filtered ("Source files "); + if (!data->regexp.empty ()) + { + if (data->partial_match.dirname) + printf_filtered ("(dirname "); + else if (data->partial_match.basename) + printf_filtered ("(basename "); + else + printf_filtered ("(filename "); + printf_filtered ("matching regular expression \"%s\") ", + data->regexp.c_str ()); + } + printf_filtered ("for which symbols %s:\n\n", symbol_msg); +} + +/* Completer for "info sources". */ + +static void +info_sources_command_completer (cmd_list_element *ignore, + completion_tracker &tracker, + const char *text, const char *word) +{ + const auto group = make_info_sources_options_def_group (nullptr); + if (gdb::option::complete_options + (tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, group)) + return; +} + static void -info_sources_command (const char *ignore, int from_tty) +info_sources_command (const char *args, int from_tty) { struct output_source_filename_data data; @@ -4180,11 +4283,37 @@ info_sources_command (const char *ignore, int from_tty) filename_seen_cache filenames_seen; - data.filename_seen_cache = &filenames_seen; + auto group = make_info_sources_options_def_group (&data.partial_match); + + gdb::option::process_options + (&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, group); - printf_filtered ("Source files for which symbols have been read in:\n\n"); + if (args != NULL && *args != '\000') + data.regexp = args; + data.filename_seen_cache = &filenames_seen; data.first = 1; + + if (data.partial_match.dirname && data.partial_match.basename) + error (_("You cannot give both -basename and -dirname to 'info sources'.")); + if ((data.partial_match.dirname || data.partial_match.basename) + && data.regexp.empty ()) + error (_("Missing REGEXP for 'info sources'.")); + + if (data.regexp.empty ()) + data.c_regexp.reset (); + else + { + int cflags = REG_NOSUB; +#ifdef HAVE_CASE_INSENSITIVE_FILE_SYSTEM + cflags |= REG_ICASE; +#endif + data.c_regexp.emplace (data.regexp.c_str (), cflags, + _("Invalid regexp")); + } + + print_info_sources_header ("have been read in", &data); + for (objfile *objfile : current_program_space->objfiles ()) { for (compunit_symtab *cu : objfile->compunits ()) @@ -4199,8 +4328,7 @@ info_sources_command (const char *ignore, int from_tty) } printf_filtered ("\n\n"); - printf_filtered ("Source files for which symbols " - "will be read in on demand:\n\n"); + print_info_sources_header ("will be read in on demand", &data); filenames_seen.clear (); data.first = 1; @@ -6008,6 +6136,8 @@ symbol_set_symtab (struct symbol *symbol, struct symtab *symtab) void _initialize_symtab (void) { + struct cmd_list_element *c; + initialize_ordinary_address_classes (); add_info ("variables", info_variables_command, @@ -6042,8 +6172,20 @@ Prints the functions.\n"), add_info ("types", info_types_command, _("All type names, or those matching REGEXP.")); - add_info ("sources", info_sources_command, - _("Source files in the program.")); + const auto info_sources_opts = make_info_sources_options_def_group (nullptr); + + static std::string info_sources_help + = gdb::option::build_help (_("\ +All source files in the program or those matching REGEXP.\n\ +Usage: info sources [OPTION]... [REGEXP]\n\ +By default, REGEXP is used to match anywhere in the filename.\n\ +\n\ +Options:\n\ +%OPTIONS%"), + info_sources_opts); + + c = add_info ("sources", info_sources_command, info_sources_help.c_str ()); + set_cmd_completer_handle_brkchars (c, info_sources_command_completer); add_com ("rbreak", class_breakpoint, rbreak_command, _("Set a breakpoint for all functions matching REGEXP."));