From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id HL9eI2zlD2B9IgAAWB0awg (envelope-from ) for ; Tue, 26 Jan 2021 04:48:28 -0500 Received: by simark.ca (Postfix, from userid 112) id 7A30B1EF82; Tue, 26 Jan 2021 04:48:28 -0500 (EST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-0.9 required=5.0 tests=DKIM_SIGNED, MAILING_LIST_MULTI,T_DKIM_INVALID,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id F25131E945 for ; Tue, 26 Jan 2021 04:48:26 -0500 (EST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 505033AA9C1F; Tue, 26 Jan 2021 09:48:26 +0000 (GMT) Received: from mail-wr1-x430.google.com (mail-wr1-x430.google.com [IPv6:2a00:1450:4864:20::430]) by sourceware.org (Postfix) with ESMTPS id 2C2A7386F403 for ; Tue, 26 Jan 2021 09:48:22 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 2C2A7386F403 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=embecosm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=andrew.burgess@embecosm.com Received: by mail-wr1-x430.google.com with SMTP id v15so15717805wrx.4 for ; Tue, 26 Jan 2021 01:48:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=embecosm.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=BrYqG/E8xl5t5ju1eyGbT/JB7xtzUX3yAqBICaKlDdQ=; b=eiWUVdHVzLOjzetln4U/T27u76CoDWnOsicskV9dTyaK6S2+oIf/+fcAeXX7Wva5xL AQBVNWq1j7o2bxI9I7iEoLqlhf0QHpxughuWO4xu2K0us2eLh4V/VjK5FcE0a6xcU7gr wvGOaNVWe43s5lzb2Pb6YD7gxXfs/xx8RG1LHsAlthrSyKsWwlJeSxRnm2/kFp1cfyYf reOyIW6Iy4/tHk03SWA2c+cR7sCailZjeM2q+icDO1lvN5EQ5DNy5Peou4If0lMZWShC oKmwvmGlDaYKoYtD123XsWcDHDU8ewk4FmW9ToE0DsJzDt0vyEI1BaY9J40rZBl4T2XA FzOQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=BrYqG/E8xl5t5ju1eyGbT/JB7xtzUX3yAqBICaKlDdQ=; b=fHv/vqStAOjmxbneZnY3SCl5d5tEltnb9047+7NdkdQobBwZGHI5hFvTaXTjVbpxQ6 GInUctR8DItmebyrFrjnbSYsl2pu1jaE2O7IVeqfIa/Zu2UQ9mHMTR7kX0E/1z7nLUv9 jgJ50/s+31C1hjRqqaHzxt6kmFZrP/Rcaco5MXum0JO0qMbfZtNO/PPN7UgELHoXDvss 9BV4CEqqoRWC8N/MqTfQwyHxCgEWYqgdkeuhbrkdsQwb4UBNU3Idkg3iZ5kBtWxSv0Fs teeLXUrUEG/Ch/rtfkwA7x1GxuG5ZgrcZjlfxXmQ4LhjCDmrlbU/qKY1xeO2wSNjooj8 YSXA== X-Gm-Message-State: AOAM530mV2hilBzzLptVZvIN0VVudPxUk6I5M19efdS2/o79ytSisSar YQr41FXcSPQnj69U415oKwY2UhcpAlwwbA== X-Google-Smtp-Source: ABdhPJxOB661YGsSmPmeaAEPqcmJnM9Je5898k60+pbHkXiDTnQr96HceF4hCvg3GSXq18a+AhhTQQ== X-Received: by 2002:a5d:6045:: with SMTP id j5mr1174464wrt.365.1611654500940; Tue, 26 Jan 2021 01:48:20 -0800 (PST) Received: from localhost (host86-166-129-180.range86-166.btcentralplus.com. [86.166.129.180]) by smtp.gmail.com with ESMTPSA id p9sm26459508wrj.11.2021.01.26.01.48.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 Jan 2021 01:48:20 -0800 (PST) From: Andrew Burgess To: gdb-patches@sourceware.org Subject: [PATCHv2 1/3] gdb: refactor the initialization file lookup code Date: Tue, 26 Jan 2021 09:48:11 +0000 Message-Id: X-Mailer: git-send-email 2.25.4 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces@sourceware.org Sender: "Gdb-patches" In preparation for the next patch, which adds startup files, this commit refactors the code for looking up the initialization files so that the code can be more easily reused in the next commit. There should be no user visible changes after this commit. gdb/ChangeLog: * main.c (relocate_gdbinit_path_maybe_in_datadir): Rename to... (relocate_file_path_maybe_in_datadir): ...this. (class gdb_initfile_finder): New class. (get_init_files): Now uses gdb_initfile_finder. (print_gdb_help): Print 'None found' when there are no init files. --- gdb/ChangeLog | 8 +++ gdb/main.c | 190 +++++++++++++++++++++++++++++++++----------------- 2 files changed, 135 insertions(+), 63 deletions(-) diff --git a/gdb/main.c b/gdb/main.c index 331e3a50acf..2d2fded7158 100644 --- a/gdb/main.c +++ b/gdb/main.c @@ -203,8 +203,8 @@ relocate_gdb_directory (const char *initial, bool relocatable) otherwise. */ static std::string -relocate_gdbinit_path_maybe_in_datadir (const std::string &file, - bool relocatable) +relocate_file_path_maybe_in_datadir (const std::string &file, + bool relocatable) { size_t datadir_len = strlen (GDB_DATADIR); @@ -233,45 +233,52 @@ relocate_gdbinit_path_maybe_in_datadir (const std::string &file, return relocated_path; } -/* Compute the locations of init files that GDB should source and - return them in SYSTEM_GDBINIT, HOME_GDBINIT, LOCAL_GDBINIT. If - there is no system gdbinit (resp. home gdbinit and local gdbinit) - to be loaded, then SYSTEM_GDBINIT (resp. HOME_GDBINIT and - LOCAL_GDBINIT) is set to the empty string. */ -static void -get_init_files (std::vector *system_gdbinit, - std::string *home_gdbinit, - std::string *local_gdbinit) +/* A class to wrap up the logic for finding the three different types of + initialisation files GDB uses, system wide, home directory, and current + working directory. */ + +class gdb_initfile_finder { - static std::vector sysgdbinit; - static std::string homeinit; - static std::string localinit; - static int initialized = 0; +public: + /* Constructor. Finds initialisation files named FILENAME in the home + directory or local (current working) directory. System initialisation + files are found in both SYSTEM_FILENAME and SYSTEM_DIRNAME if these + are not nullptr (either or both can be). The matching *_RELOCATABLE + flag is passed through to RELOCATE_FILE_PATH_MAYBE_IN_DATADIR. + + If FILENAME starts with a '.' then when looking in the home directory + this first '.' can be ignored in some cases. */ + explicit gdb_initfile_finder (const char *filename, + const char *system_filename, + bool system_filename_relocatable, + const char *system_dirname, + bool system_dirname_relocatable, + bool lookup_local_file) + { + struct stat s; - if (!initialized) - { - struct stat homebuf, cwdbuf, s; + if (system_filename != nullptr && system_filename[0] != '\0') + { + std::string relocated_filename + = relocate_file_path_maybe_in_datadir (system_filename, + system_filename_relocatable); + if (!relocated_filename.empty () + && stat (relocated_filename.c_str (), &s) == 0) + m_system_files.push_back (relocated_filename); + } - if (SYSTEM_GDBINIT[0]) - { - std::string relocated_sysgdbinit - = relocate_gdbinit_path_maybe_in_datadir - (SYSTEM_GDBINIT, SYSTEM_GDBINIT_RELOCATABLE); - if (!relocated_sysgdbinit.empty () - && stat (relocated_sysgdbinit.c_str (), &s) == 0) - sysgdbinit.push_back (relocated_sysgdbinit); - } - if (SYSTEM_GDBINIT_DIR[0]) - { - std::string relocated_gdbinit_dir - = relocate_gdbinit_path_maybe_in_datadir - (SYSTEM_GDBINIT_DIR, SYSTEM_GDBINIT_DIR_RELOCATABLE); - if (!relocated_gdbinit_dir.empty ()) { - gdb_dir_up dir (opendir (relocated_gdbinit_dir.c_str ())); + if (system_dirname != nullptr && system_dirname[0] != '\0') + { + std::string relocated_dirname + = relocate_file_path_maybe_in_datadir (system_dirname, + system_dirname_relocatable); + if (!relocated_dirname.empty ()) + { + gdb_dir_up dir (opendir (relocated_dirname.c_str ())); if (dir != nullptr) { std::vector files; - for (;;) + while (true) { struct dirent *ent = readdir (dir.get ()); if (ent == nullptr) @@ -279,28 +286,28 @@ get_init_files (std::vector *system_gdbinit, std::string name (ent->d_name); if (name == "." || name == "..") continue; - /* ent->d_type is not available on all systems (e.g. mingw, - Solaris), so we have to call stat(). */ - std::string filename - = relocated_gdbinit_dir + SLASH_STRING + name; - if (stat (filename.c_str (), &s) != 0 + /* ent->d_type is not available on all systems + (e.g. mingw, Solaris), so we have to call stat(). */ + std::string tmp_filename + = relocated_dirname + SLASH_STRING + name; + if (stat (tmp_filename.c_str (), &s) != 0 || !S_ISREG (s.st_mode)) continue; const struct extension_language_defn *extlang - = get_ext_lang_of_file (filename.c_str ()); + = get_ext_lang_of_file (tmp_filename.c_str ()); /* We effectively don't support "set script-extension - off/soft", because we are loading system init files here, - so it does not really make sense to depend on a - setting. */ + off/soft", because we are loading system init files + here, so it does not really make sense to depend on + a setting. */ if (extlang != nullptr && ext_lang_present_p (extlang)) - files.push_back (std::move (filename)); + files.push_back (std::move (tmp_filename)); } std::sort (files.begin (), files.end ()); - sysgdbinit.insert (sysgdbinit.end (), - files.begin (), files.end ()); + m_system_files.insert (m_system_files.end (), + files.begin (), files.end ()); } } - } + } /* If the .gdbinit file in the current directory is the same as the $HOME/.gdbinit file, it should not be sourced. homebuf @@ -308,25 +315,78 @@ get_init_files (std::vector *system_gdbinit, are zero in case one of them fails (this guarantees that they won't match if either exists). */ - memset (&homebuf, 0, sizeof (struct stat)); - memset (&cwdbuf, 0, sizeof (struct stat)); + struct stat homebuf, cwdbuf; + memset (&homebuf, 0, sizeof (struct stat)); + memset (&cwdbuf, 0, sizeof (struct stat)); - homeinit = find_gdb_home_config_file (GDBINIT, &homebuf); + m_home_file = find_gdb_home_config_file (filename, &homebuf); - if (stat (GDBINIT, &cwdbuf) == 0) - { - if (homeinit.empty () - || memcmp ((char *) &homebuf, (char *) &cwdbuf, - sizeof (struct stat))) - localinit = GDBINIT; - } + if (lookup_local_file && stat (filename, &cwdbuf) == 0) + { + if (m_home_file.empty () + || memcmp ((char *) &homebuf, (char *) &cwdbuf, + sizeof (struct stat))) + m_local_file = filename; + } + } - initialized = 1; - } + DISABLE_COPY_AND_ASSIGN (gdb_initfile_finder); + + /* Return a list of system initialisation files. The list could be + empty. */ + const std::vector &system_files () const + { return m_system_files; } + + /* Return the path to the home initialisation file. The string can be + empty if there is no such file. */ + const std::string &home_file () const + { return m_home_file; } + + /* Return the path to the local initialisation file. The string can be + empty if there is no such file. */ + const std::string &local_file () const + { return m_local_file; } + +private: + + /* Vector of all system init files in the order they should be processed. + Could be empty. */ + std::vector m_system_files; + + /* Initialization file from the home directory. Could be the empty + string if there is no such file found. */ + std::string m_home_file; - *system_gdbinit = sysgdbinit; - *home_gdbinit = homeinit; - *local_gdbinit = localinit; + /* Initialization file from the current working directory. Could be the + empty string if there is no such file found. */ + std::string m_local_file; +}; + +/* Compute the locations of init files that GDB should source and return + them in SYSTEM_GDBINIT, HOME_GDBINIT, LOCAL_GDBINIT. The SYSTEM_GDBINIT + can be returned as an empty vector, and HOME_GDBINIT and LOCAL_GDBINIT + can be returned as empty strings if there is no init file of that + type. */ + +static void +get_init_files (std::vector *system_gdbinit, + std::string *home_gdbinit, + std::string *local_gdbinit) +{ + /* Cache the file lookup object so we only actually search for the files + once. */ + static std::unique_ptr init_files; + if (init_files == nullptr) + init_files = std::unique_ptr + (new gdb_initfile_finder (GDBINIT, + SYSTEM_GDBINIT, + SYSTEM_GDBINIT_RELOCATABLE, + SYSTEM_GDBINIT_DIR, + SYSTEM_GDBINIT_DIR_RELOCATABLE, true)); + + *system_gdbinit = init_files->system_files (); + *home_gdbinit = init_files->home_file (); + *local_gdbinit = init_files->local_file (); } /* Start up the event loop. This is the entry point to the event loop @@ -1375,6 +1435,10 @@ At startup, GDB reads the following init files and executes their commands:\n\ fprintf_unfiltered (stream, _("\ * local init file (see also 'set auto-load local-gdbinit'): ./%s\n\ "), local_gdbinit.c_str ()); + if (system_gdbinit.empty () && home_gdbinit.empty () + && local_gdbinit.empty ()) + fprintf_unfiltered (stream, _("\ + None found.\n")); fputs_unfiltered (_("\n\ For more information, type \"help\" from within GDB, or consult the\n\ GDB manual (available as on-line info or a printed manual).\n\ -- 2.25.4