1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "command.h" 18 19#include <algorithm> 20#include <map> 21#include <string> 22#include <vector> 23 24#include <android-base/logging.h> 25 26#include "utils.h" 27 28bool Command::NextArgumentOrError(const std::vector<std::string>& args, size_t* pi) { 29 if (*pi + 1 == args.size()) { 30 LOG(ERROR) << "No argument following " << args[*pi] << " option. Try `simpleperf help " << name_ 31 << "`"; 32 return false; 33 } 34 ++*pi; 35 return true; 36} 37 38void Command::ReportUnknownOption(const std::vector<std::string>& args, size_t i) { 39 LOG(ERROR) << "Unknown option for " << name_ << " command: '" << args[i] 40 << "'. Try `simpleperf help " << name_ << "`"; 41} 42 43typedef std::function<std::unique_ptr<Command>(void)> callback_t; 44 45static std::map<std::string, callback_t>& CommandMap() { 46 // commands is used in the constructor of Command. Defining it as a static 47 // variable in a function makes sure it is initialized before use. 48 static std::map<std::string, callback_t> command_map; 49 return command_map; 50} 51 52void RegisterCommand(const std::string& cmd_name, 53 const std::function<std::unique_ptr<Command>(void)>& callback) { 54 CommandMap().insert(std::make_pair(cmd_name, callback)); 55} 56 57void UnRegisterCommand(const std::string& cmd_name) { 58 CommandMap().erase(cmd_name); 59} 60 61std::unique_ptr<Command> CreateCommandInstance(const std::string& cmd_name) { 62 auto it = CommandMap().find(cmd_name); 63 return (it == CommandMap().end()) ? nullptr : (it->second)(); 64} 65 66const std::vector<std::string> GetAllCommandNames() { 67 std::vector<std::string> names; 68 for (auto pair : CommandMap()) { 69 names.push_back(pair.first); 70 } 71 return names; 72} 73 74extern void RegisterDumpRecordCommand(); 75extern void RegisterHelpCommand(); 76extern void RegisterListCommand(); 77extern void RegisterKmemCommand(); 78extern void RegisterRecordCommand(); 79extern void RegisterReportCommand(); 80extern void RegisterReportSampleCommand(); 81extern void RegisterStatCommand(); 82 83class CommandRegister { 84 public: 85 CommandRegister() { 86 RegisterDumpRecordCommand(); 87 RegisterHelpCommand(); 88 RegisterKmemCommand(); 89 RegisterReportCommand(); 90 RegisterReportSampleCommand(); 91#if defined(__linux__) 92 RegisterListCommand(); 93 RegisterRecordCommand(); 94 RegisterStatCommand(); 95#endif 96 } 97}; 98 99CommandRegister command_register; 100 101bool RunSimpleperfCmd(int argc, char** argv) { 102 android::base::InitLogging(argv, android::base::StderrLogger); 103 std::vector<std::string> args; 104 android::base::LogSeverity log_severity = android::base::INFO; 105 106 for (int i = 1; i < argc; ++i) { 107 if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) { 108 args.insert(args.begin(), "help"); 109 } else if (strcmp(argv[i], "--log") == 0) { 110 if (i + 1 < argc) { 111 ++i; 112 if (!GetLogSeverity(argv[i], &log_severity)) { 113 LOG(ERROR) << "Unknown log severity: " << argv[i]; 114 return false; 115 } 116 } else { 117 LOG(ERROR) << "Missing argument for --log option.\n"; 118 return false; 119 } 120 } else if (strcmp(argv[i], "--version") == 0) { 121 LOG(INFO) << "Simpleperf version " << GetSimpleperfVersion(); 122 return true; 123 } else { 124 args.push_back(argv[i]); 125 } 126 } 127 android::base::ScopedLogSeverity severity(log_severity); 128 129 if (args.empty()) { 130 args.push_back("help"); 131 } 132 std::unique_ptr<Command> command = CreateCommandInstance(args[0]); 133 if (command == nullptr) { 134 LOG(ERROR) << "malformed command line: unknown command " << args[0]; 135 return false; 136 } 137 std::string command_name = args[0]; 138 args.erase(args.begin()); 139 140 LOG(DEBUG) << "command '" << command_name << "' starts running"; 141 bool result = command->Run(args); 142 LOG(DEBUG) << "command '" << command_name << "' " 143 << (result ? "finished successfully" : "failed"); 144 return result; 145} 146