| // Copyright 2018 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. |
| |
| #ifndef SRC_DEVELOPER_DEBUG_ZXDB_CONSOLE_COMMAND_H_ |
| #define SRC_DEVELOPER_DEBUG_ZXDB_CONSOLE_COMMAND_H_ |
| |
| #include <lib/syslog/cpp/macros.h> |
| |
| #include <initializer_list> |
| #include <map> |
| #include <string> |
| #include <vector> |
| |
| #include "lib/fit/function.h" |
| #include "src/developer/debug/zxdb/common/err.h" |
| #include "src/developer/debug/zxdb/console/nouns.h" |
| #include "src/developer/debug/zxdb/console/verbs.h" |
| |
| namespace zxdb { |
| |
| class Breakpoint; |
| struct CommandReport; |
| class ConsoleContext; |
| class Filter; |
| class Frame; |
| class Target; |
| class Thread; |
| class SymbolServer; |
| |
| // Command --------------------------------------------------------------------- |
| |
| class Command { |
| public: |
| // This valid indicates that there was a noun specified but no index. |
| // For example the command "process step" specifies the process noun but |
| // not an index. |
| static constexpr int kNoIndex = -1; |
| // This indicates the operation should be done for all instances of this noun. Typically, this is |
| // used to remove all filters or breakpoints, or detach from all processes. Typical use is like: |
| // filter * rm |
| static constexpr int kWildcard = -2; |
| |
| Command(); |
| ~Command(); |
| |
| // Returns true if the noun was specified by the user. |
| bool HasNoun(Noun noun) const; |
| |
| // Returns the index specified for the given noun. If the noun was not |
| // specified or the index was not specified, returns kNoIndex (use HasNoun to |
| // disambiguate). |
| int GetNounIndex(Noun noun) const; |
| |
| // Sets that the given noun was present. index may be kNoIndex. |
| void SetNoun(Noun noun, int index); |
| |
| const std::map<Noun, int>& nouns() const { return nouns_; } |
| |
| // Checks the specified nouns against the parameter listing the allowed ones. |
| // If any nouns are specified that are not in the list, generates an error and |
| // returns it. If |allow_wildcard| is false, and a wildcard specifier is |
| // present, will generate an appropriate error message. Otherwise it will |
| // return an empty error. |
| Err ValidateNouns(std::initializer_list<Noun> allowed_nouns, bool allow_wildcard = false) const; |
| |
| Verb verb() const { return verb_; } |
| void set_verb(Verb v) { verb_ = v; } |
| |
| // Returns whether a given switch was specified. |
| bool HasSwitch(int id) const; |
| |
| // Returns the value corresponding to the given switch, or the empty string |
| // if not specified. |
| std::string GetSwitchValue(int id) const; |
| |
| void SetSwitch(int id, std::string str); |
| |
| const std::map<int, std::string>& switches() const { return switches_; } |
| |
| const std::vector<std::string>& args() const { return args_; } |
| void set_args(std::vector<std::string> a) { args_ = std::move(a); } |
| |
| // The computed environment for the command. This is filled in with the |
| // objects corresponding to the indices given on the command line, and |
| // default to the current one for the current command line. |
| // |
| // If |HasNoun()| returns true, the corresponding getter here is guaranteed to |
| // be non-null or have size() > 0. Most commands are interacting with a single |
| // noun, so there are convenience getters for when only a single object is |
| // needed/expected. These will only work when there is exactly one instance of |
| // that noun associated with this command. |
| Frame* frame() const { return frames_.size() == 1 ? frames_[0] : nullptr; } |
| const std::vector<Frame*>& all_frames() const { return frames_; } |
| void add_frame(Frame* f) { frames_.push_back(f); } |
| Target* target() const { |
| // Enforce at least one target exists. |
| FX_DCHECK(!targets_.empty()); |
| return targets_[0]; |
| } |
| const std::vector<Target*>& all_targets() const { return targets_; } |
| void add_target(Target* t) { targets_.push_back(t); } |
| Thread* thread() const { return threads_.size() == 1 ? threads_[0] : nullptr; } |
| const std::vector<Thread*>& all_threads() const { return threads_; } |
| void add_thread(Thread* t) { threads_.push_back(t); } |
| Breakpoint* breakpoint() const { return breakpoints_.size() == 1 ? breakpoints_[0] : nullptr; } |
| const std::vector<Breakpoint*>& all_breakpoints() const { return breakpoints_; } |
| void add_breakpoint(Breakpoint* b) { breakpoints_.push_back(b); } |
| Filter* filter() const { return filters_.size() == 1 ? filters_[0] : nullptr; } |
| const std::vector<Filter*>& all_filters() const { return filters_; } |
| void add_filter(Filter* f) { filters_.push_back(f); } |
| SymbolServer* sym_server() const { |
| return symbol_servers_.size() == 1 ? symbol_servers_[0] : nullptr; |
| } |
| const std::vector<SymbolServer*>& all_sym_servers() const { return symbol_servers_; } |
| void add_sym_server(SymbolServer* s) { symbol_servers_.push_back(s); } |
| |
| CommandReport BuildReport() const; |
| |
| private: |
| void AddNounsToCommandReport(CommandReport& report) const; |
| void AddArgsToCommandReport(CommandReport& report) const; |
| void AddSwitchesToCommandReport(CommandReport& report) const; |
| |
| // The nouns specified for this command. If not present here, the noun was not |
| // written on the command line. If present but there was no index given for |
| // it, the mapped value will be kNoIndex. Wildcards are represented as |
| // |kWildcard|. Otherwise the mapped value will be the index specified. |
| std::map<Noun, int> nouns_; |
| |
| // The effective context for the command. The explicitly specified process(es)/ |
| // thread(s)/etc. will be reflected here, and anything that wasn't explicit |
| // will inherit the default. |
| std::vector<Target*> targets_; // Guaranteed non-empty for valid commands. |
| std::vector<Thread*> threads_; // Will be empty if not running. |
| std::vector<Frame*> frames_; // Will be empty if no valid thread stopped. |
| std::vector<Breakpoint*> breakpoints_; // May be empty. |
| std::vector<Filter*> filters_; // May be empty. |
| std::vector<SymbolServer*> symbol_servers_; // May be empty. |
| |
| Verb verb_ = Verb::kNone; |
| |
| std::map<int, std::string> switches_; |
| std::vector<std::string> args_; |
| }; |
| |
| // Command dispatch ------------------------------------------------------------ |
| |
| // Type for a callback that a CommandExecutor will receive |
| using CommandCallback = fit::callback<void(Err)>; |
| |
| // Runs the given command. |
| void DispatchCommand(const Command& cmd, fxl::RefPtr<CommandContext> cmd_context); |
| |
| } // namespace zxdb |
| |
| #endif // SRC_DEVELOPER_DEBUG_ZXDB_CONSOLE_COMMAND_H_ |