| // Copyright 2020 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "tools/symbol-index/command_line_options.h" |
| |
| #include <lib/cmdline/args_parser.h> |
| |
| #include "src/lib/fxl/strings/string_printf.h" |
| |
| namespace symbol_index { |
| |
| namespace { |
| |
| const char kHelpIntro[] = R"(symbol-index [ <options> ] <verb> [ <arguments> ... ] |
| |
| Manipulates a symbol-index file. |
| |
| Available verbs: |
| |
| list |
| Lists all paths in symbol-index. |
| |
| add <symbol path> [ <build directory> ] |
| Adds a new symbol path to symbol-index. A symbol path could be either a |
| a text file in "ids.txt" format, or a directory in ".build-id" structure. |
| An optional build directory could be supplemented, which is used by zxdb |
| to locate the source code. If the symbol path is already in symbol-index, |
| no changes will be made regardless of the optional build directory. |
| |
| add-all [ <input file> ] |
| Reads the input and adds all symbol paths with optional build directories. |
| The input file can contain multiple lines, each describing a symbol path. |
| An optional build directory could be supplemented and separated from the |
| symbol path with whitespaces. Relative paths will be resolved based on |
| the input file. Empty lines and lines starting with "#" will be ignored. |
| If the input file is not specified, the input will be read from the stdin. |
| |
| remove <symbol path> |
| Removes a symbol path from symbol-index. |
| |
| purge |
| Removes all non-existent paths from symbol-index. |
| |
| Options |
| |
| )"; |
| |
| const char kConfigHelp[] = R"( --config=<path> |
| -c <path> |
| Path to the symbol-index config file, default to |
| ~/.fuchsia/debug/symbol-index.)"; |
| |
| const char kHelpHelp[] = R"( --help |
| -h |
| Prints this help.)"; |
| |
| const char kVersionHelp[] = R"( --version |
| -v |
| Prints the version.)"; |
| |
| using ::analytics::core_dev_tools::kAnalyticsHelp; |
| using ::analytics::core_dev_tools::kAnalyticsShowHelp; |
| |
| } // namespace |
| |
| Error CommandLineOptions::SetVerb(const std::string& str) { |
| if (str == "list") |
| verb = Verb::kList; |
| else if (str == "add") |
| verb = Verb::kAdd; |
| else if (str == "add-all") |
| verb = Verb::kAddAll; |
| else if (str == "remove") |
| verb = Verb::kRemove; |
| else if (str == "purge") |
| verb = Verb::kPurge; |
| else |
| return fxl::StringPrintf("Unsupported verb: %s", str.c_str()); |
| return ""; |
| } |
| |
| Error CommandLineOptions::Validate() { |
| size_t params_size = params.size(); |
| switch (verb) { |
| case Verb::kList: |
| if (params_size != 0) |
| return fxl::StringPrintf("Verb list requires 0 arguments, but %lu is given.", params_size); |
| break; |
| case Verb::kAdd: |
| if (params_size < 1 || params_size > 2) { |
| return fxl::StringPrintf("Verb add requires 1 or 2 arguments, but %lu is given.", |
| params_size); |
| } |
| break; |
| case Verb::kAddAll: |
| if (params_size > 1) { |
| return fxl::StringPrintf("Verb add-all requires 0 or 1 arguments, but %lu is given.", |
| params_size); |
| } |
| break; |
| case Verb::kRemove: |
| if (params_size != 1) |
| return fxl::StringPrintf("Verb remove requires 1 argument, but %lu is given.", params_size); |
| break; |
| case Verb::kPurge: |
| if (params_size != 0) |
| return fxl::StringPrintf("Verb purge requires 0 arguments, but %lu is given.", params_size); |
| break; |
| } |
| return ""; |
| } |
| |
| Error ParseCommandLine(int argc, const char* argv[], CommandLineOptions* options) { |
| using analytics::core_dev_tools::AnalyticsOption; |
| using analytics::core_dev_tools::ParseAnalyticsOption; |
| |
| std::vector<std::string> params; |
| cmdline::ArgsParser<CommandLineOptions> parser; |
| |
| parser.AddSwitch("config", 'c', kConfigHelp, &CommandLineOptions::symbol_index_file); |
| parser.AddSwitch("version", 'v', kVersionHelp, &CommandLineOptions::requested_version); |
| parser.AddSwitch("analytics", 0, kAnalyticsHelp, &CommandLineOptions::analytics); |
| parser.AddSwitch("analytics-show", 0, kAnalyticsShowHelp, &CommandLineOptions::analytics_show); |
| |
| // Special --help switch which doesn't exist in the options structure. |
| bool requested_help = false; |
| parser.AddGeneralSwitch("help", 'h', kHelpHelp, [&requested_help]() { requested_help = true; }); |
| |
| auto s = parser.Parse(argc, argv, options, ¶ms); |
| if (s.has_error()) { |
| return s.error_message(); |
| } |
| |
| if (options->requested_version) { |
| return ""; |
| } |
| |
| if (options->analytics_show || options->analytics == AnalyticsOption::kEnable || |
| options->analytics == AnalyticsOption::kDisable) { |
| return ""; |
| } |
| |
| if (requested_help || params.empty()) { |
| return kHelpIntro + parser.GetHelp(); |
| } |
| |
| if (Error err = options->SetVerb(params[0]); !err.empty()) { |
| return err; |
| } |
| |
| options->params.resize(params.size() - 1); |
| std::copy(params.begin() + 1, params.end(), options->params.begin()); |
| |
| if (Error err = options->Validate(); !err.empty()) { |
| return err; |
| } |
| |
| return ""; |
| } |
| |
| } // namespace symbol_index |