1 //===-- CommandObjectMultiword.cpp ------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "lldb/Interpreter/CommandObjectMultiword.h" 11 // C Includes 12 // C++ Includes 13 // Other libraries and framework includes 14 // Project includes 15 #include "lldb/Core/Debugger.h" 16 #include "lldb/Interpreter/CommandInterpreter.h" 17 #include "lldb/Interpreter/Options.h" 18 #include "lldb/Interpreter/CommandReturnObject.h" 19 20 using namespace lldb; 21 using namespace lldb_private; 22 23 //------------------------------------------------------------------------- 24 // CommandObjectMultiword 25 //------------------------------------------------------------------------- 26 27 CommandObjectMultiword::CommandObjectMultiword 28 ( 29 CommandInterpreter &interpreter, 30 const char *name, 31 const char *help, 32 const char *syntax, 33 uint32_t flags 34 ) : 35 CommandObject (interpreter, name, help, syntax, flags) 36 { 37 } 38 39 CommandObjectMultiword::~CommandObjectMultiword () 40 { 41 } 42 43 CommandObjectSP 44 CommandObjectMultiword::GetSubcommandSP (const char *sub_cmd, StringList *matches) 45 { 46 CommandObjectSP return_cmd_sp; 47 CommandObject::CommandMap::iterator pos; 48 49 if (!m_subcommand_dict.empty()) 50 { 51 pos = m_subcommand_dict.find (sub_cmd); 52 if (pos != m_subcommand_dict.end()) 53 return_cmd_sp = pos->second; 54 else 55 { 56 57 StringList local_matches; 58 if (matches == NULL) 59 matches = &local_matches; 60 int num_matches = CommandObject::AddNamesMatchingPartialString (m_subcommand_dict, sub_cmd, *matches); 61 62 if (num_matches == 1) 63 { 64 // Cleaner, but slightly less efficient would be to call back into this function, since I now 65 // know I have an exact match... 66 67 sub_cmd = matches->GetStringAtIndex(0); 68 pos = m_subcommand_dict.find(sub_cmd); 69 if (pos != m_subcommand_dict.end()) 70 return_cmd_sp = pos->second; 71 } 72 } 73 } 74 return return_cmd_sp; 75 } 76 77 CommandObject * 78 CommandObjectMultiword::GetSubcommandObject (const char *sub_cmd, StringList *matches) 79 { 80 return GetSubcommandSP(sub_cmd, matches).get(); 81 } 82 83 bool 84 CommandObjectMultiword::LoadSubCommand 85 ( 86 const char *name, 87 const CommandObjectSP& cmd_obj 88 ) 89 { 90 CommandMap::iterator pos; 91 bool success = true; 92 93 pos = m_subcommand_dict.find(name); 94 if (pos == m_subcommand_dict.end()) 95 { 96 m_subcommand_dict[name] = cmd_obj; 97 m_interpreter.CrossRegisterCommand (name, GetCommandName()); 98 } 99 else 100 success = false; 101 102 return success; 103 } 104 105 bool 106 CommandObjectMultiword::Execute 107 ( 108 Args& args, 109 CommandReturnObject &result 110 ) 111 { 112 const size_t argc = args.GetArgumentCount(); 113 if (argc == 0) 114 { 115 GenerateHelpText (result); 116 } 117 else 118 { 119 const char *sub_command = args.GetArgumentAtIndex (0); 120 121 if (sub_command) 122 { 123 if (::strcasecmp (sub_command, "help") == 0) 124 { 125 GenerateHelpText (result); 126 } 127 else if (!m_subcommand_dict.empty()) 128 { 129 StringList matches; 130 CommandObject *sub_cmd_obj = GetSubcommandObject(sub_command, &matches); 131 if (sub_cmd_obj != NULL) 132 { 133 // Now call CommandObject::Execute to process and options in 'rest_of_line'. From there 134 // the command-specific version of Execute will be called, with the processed arguments. 135 136 args.Shift(); 137 138 sub_cmd_obj->ExecuteWithOptions (args, result); 139 } 140 else 141 { 142 std::string error_msg; 143 int num_subcmd_matches = matches.GetSize(); 144 if (num_subcmd_matches > 0) 145 error_msg.assign ("ambiguous command "); 146 else 147 error_msg.assign ("invalid command "); 148 149 error_msg.append ("'"); 150 error_msg.append (GetCommandName()); 151 error_msg.append (" "); 152 error_msg.append (sub_command); 153 error_msg.append ("'"); 154 155 if (num_subcmd_matches > 0) 156 { 157 error_msg.append (" Possible completions:"); 158 for (int i = 0; i < num_subcmd_matches; i++) 159 { 160 error_msg.append ("\n\t"); 161 error_msg.append (matches.GetStringAtIndex (i)); 162 } 163 } 164 error_msg.append ("\n"); 165 result.AppendRawError (error_msg.c_str(), error_msg.size()); 166 result.SetStatus (eReturnStatusFailed); 167 } 168 } 169 else 170 { 171 result.AppendErrorWithFormat ("'%s' does not have any subcommands.\n", GetCommandName()); 172 result.SetStatus (eReturnStatusFailed); 173 } 174 } 175 } 176 177 return result.Succeeded(); 178 } 179 180 void 181 CommandObjectMultiword::GenerateHelpText (CommandReturnObject &result) 182 { 183 // First time through here, generate the help text for the object and 184 // push it to the return result object as well 185 186 StreamString &output_stream = result.GetOutputStream(); 187 output_stream.PutCString ("The following subcommands are supported:\n\n"); 188 189 CommandMap::iterator pos; 190 uint32_t max_len = m_interpreter.FindLongestCommandWord (m_subcommand_dict); 191 192 if (max_len) 193 max_len += 4; // Indent the output by 4 spaces. 194 195 for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos) 196 { 197 std::string indented_command (" "); 198 indented_command.append (pos->first); 199 if (pos->second->WantsRawCommandString ()) 200 { 201 std::string help_text (pos->second->GetHelp()); 202 help_text.append (" This command takes 'raw' input (no need to quote stuff)."); 203 m_interpreter.OutputFormattedHelpText (result.GetOutputStream(), 204 indented_command.c_str(), 205 "--", 206 help_text.c_str(), 207 max_len); 208 } 209 else 210 m_interpreter.OutputFormattedHelpText (result.GetOutputStream(), 211 indented_command.c_str(), 212 "--", 213 pos->second->GetHelp(), 214 max_len); 215 } 216 217 output_stream.PutCString ("\nFor more help on any particular subcommand, type 'help <command> <subcommand>'.\n"); 218 219 result.SetStatus (eReturnStatusSuccessFinishNoResult); 220 } 221 222 int 223 CommandObjectMultiword::HandleCompletion 224 ( 225 Args &input, 226 int &cursor_index, 227 int &cursor_char_position, 228 int match_start_point, 229 int max_return_elements, 230 bool &word_complete, 231 StringList &matches 232 ) 233 { 234 // Any of the command matches will provide a complete word, otherwise the individual 235 // completers will override this. 236 word_complete = true; 237 238 if (cursor_index == 0) 239 { 240 CommandObject::AddNamesMatchingPartialString (m_subcommand_dict, 241 input.GetArgumentAtIndex(0), 242 matches); 243 244 if (matches.GetSize() == 1 245 && matches.GetStringAtIndex(0) != NULL 246 && strcmp (input.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0) 247 { 248 StringList temp_matches; 249 CommandObject *cmd_obj = GetSubcommandObject (input.GetArgumentAtIndex(0), 250 &temp_matches); 251 if (cmd_obj != NULL) 252 { 253 matches.DeleteStringAtIndex (0); 254 input.Shift(); 255 cursor_char_position = 0; 256 input.AppendArgument (""); 257 return cmd_obj->HandleCompletion (input, 258 cursor_index, 259 cursor_char_position, 260 match_start_point, 261 max_return_elements, 262 word_complete, 263 matches); 264 } 265 else 266 return matches.GetSize(); 267 } 268 else 269 return matches.GetSize(); 270 } 271 else 272 { 273 CommandObject *sub_command_object = GetSubcommandObject (input.GetArgumentAtIndex(0), 274 &matches); 275 if (sub_command_object == NULL) 276 { 277 return matches.GetSize(); 278 } 279 else 280 { 281 // Remove the one match that we got from calling GetSubcommandObject. 282 matches.DeleteStringAtIndex(0); 283 input.Shift(); 284 cursor_index--; 285 return sub_command_object->HandleCompletion (input, 286 cursor_index, 287 cursor_char_position, 288 match_start_point, 289 max_return_elements, 290 word_complete, 291 matches); 292 } 293 294 } 295 } 296 297 const char * 298 CommandObjectMultiword::GetRepeatCommand (Args ¤t_command_args, uint32_t index) 299 { 300 index++; 301 if (current_command_args.GetArgumentCount() <= index) 302 return NULL; 303 CommandObject *sub_command_object = GetSubcommandObject (current_command_args.GetArgumentAtIndex(index)); 304 if (sub_command_object == NULL) 305 return NULL; 306 return sub_command_object->GetRepeatCommand(current_command_args, index); 307 } 308 309