1ebc09c36SJim Ingham //===-- CommandObjectSource.cpp ---------------------------------*- C++ -*-===// 2ebc09c36SJim Ingham // 3ebc09c36SJim Ingham // The LLVM Compiler Infrastructure 4ebc09c36SJim Ingham // 5ebc09c36SJim Ingham // This file is distributed under the University of Illinois Open Source 6ebc09c36SJim Ingham // License. See LICENSE.TXT for details. 7ebc09c36SJim Ingham // 8ebc09c36SJim Ingham //===----------------------------------------------------------------------===// 9ebc09c36SJim Ingham 10ebc09c36SJim Ingham #include "CommandObjectCommands.h" 11ebc09c36SJim Ingham 12ebc09c36SJim Ingham // C Includes 13ebc09c36SJim Ingham // C++ Includes 14ebc09c36SJim Ingham // Other libraries and framework includes 15ebc09c36SJim Ingham // Project includes 16ebc09c36SJim Ingham #include "lldb/Interpreter/Args.h" 17ebc09c36SJim Ingham #include "lldb/Core/Debugger.h" 18ebc09c36SJim Ingham #include "lldb/Interpreter/CommandInterpreter.h" 19ebc09c36SJim Ingham #include "lldb/Interpreter/CommandReturnObject.h" 20ebc09c36SJim Ingham #include "lldb/Interpreter/Options.h" 21ebc09c36SJim Ingham 22ebc09c36SJim Ingham using namespace lldb; 23ebc09c36SJim Ingham using namespace lldb_private; 24ebc09c36SJim Ingham 25ebc09c36SJim Ingham const char *k_space_characters = "\t\n\v\f\r "; 26ebc09c36SJim Ingham 27ebc09c36SJim Ingham //------------------------------------------------------------------------- 28ebc09c36SJim Ingham // CommandObjectCommandsSource 29ebc09c36SJim Ingham //------------------------------------------------------------------------- 30ebc09c36SJim Ingham 31ebc09c36SJim Ingham class CommandObjectCommandsSource : public CommandObject 32ebc09c36SJim Ingham { 33ebc09c36SJim Ingham public: 34a7015092SGreg Clayton CommandObjectCommandsSource(CommandInterpreter &interpreter) : 35a7015092SGreg Clayton CommandObject (interpreter, 36a7015092SGreg Clayton "commands source", 37e3d26315SCaroline Tice "Read in debugger commands from the file <filename> and execute them.", 38405fe67fSCaroline Tice NULL) 39ebc09c36SJim Ingham { 40405fe67fSCaroline Tice CommandArgumentEntry arg; 41405fe67fSCaroline Tice CommandArgumentData file_arg; 42405fe67fSCaroline Tice 43405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 44405fe67fSCaroline Tice file_arg.arg_type = eArgTypeFilename; 45405fe67fSCaroline Tice file_arg.arg_repetition = eArgRepeatPlain; 46405fe67fSCaroline Tice 47405fe67fSCaroline Tice // There is only one variant this argument could be; put it into the argument entry. 48405fe67fSCaroline Tice arg.push_back (file_arg); 49405fe67fSCaroline Tice 50405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 51405fe67fSCaroline Tice m_arguments.push_back (arg); 52ebc09c36SJim Ingham } 53ebc09c36SJim Ingham 54ebc09c36SJim Ingham ~CommandObjectCommandsSource () 55ebc09c36SJim Ingham { 56ebc09c36SJim Ingham } 57ebc09c36SJim Ingham 58ebc09c36SJim Ingham bool 59ebc09c36SJim Ingham Execute 60ebc09c36SJim Ingham ( 61ebc09c36SJim Ingham Args& args, 62ebc09c36SJim Ingham CommandReturnObject &result 63ebc09c36SJim Ingham ) 64ebc09c36SJim Ingham { 65ebc09c36SJim Ingham const int argc = args.GetArgumentCount(); 66ebc09c36SJim Ingham if (argc == 1) 67ebc09c36SJim Ingham { 68ebc09c36SJim Ingham const char *filename = args.GetArgumentAtIndex(0); 69ebc09c36SJim Ingham bool success = true; 70ebc09c36SJim Ingham 71ebc09c36SJim Ingham result.AppendMessageWithFormat ("Executing commands in '%s'.\n", filename); 72ebc09c36SJim Ingham 731ee3853fSJohnny Chen FileSpec cmd_file (filename, true); 74ebc09c36SJim Ingham if (cmd_file.Exists()) 75ebc09c36SJim Ingham { 76ebc09c36SJim Ingham STLStringArray commands; 77ebc09c36SJim Ingham success = cmd_file.ReadFileLines (commands); 78ebc09c36SJim Ingham 79ebc09c36SJim Ingham STLStringArray::iterator pos = commands.begin(); 80ebc09c36SJim Ingham 81ebc09c36SJim Ingham // Trim out any empty lines or lines that start with the comment 82ebc09c36SJim Ingham // char '#' 83ebc09c36SJim Ingham while (pos != commands.end()) 84ebc09c36SJim Ingham { 85ebc09c36SJim Ingham size_t non_space = pos->find_first_not_of (k_space_characters); 860603aa9dSGreg Clayton // Check for empty line or comment line (lines whose first 870603aa9dSGreg Clayton // non-space character is a '#') 880603aa9dSGreg Clayton if (non_space == std::string::npos || (*pos)[non_space] == '#') 89ebc09c36SJim Ingham pos = commands.erase(pos); 90ebc09c36SJim Ingham else 91ebc09c36SJim Ingham ++pos; 92ebc09c36SJim Ingham } 93ebc09c36SJim Ingham 94ebc09c36SJim Ingham if (commands.size() > 0) 95ebc09c36SJim Ingham { 96ebc09c36SJim Ingham const size_t num_commands = commands.size(); 97ebc09c36SJim Ingham size_t i; 98ebc09c36SJim Ingham for (i = 0; i<num_commands; ++i) 99ebc09c36SJim Ingham { 100a7015092SGreg Clayton result.GetOutputStream().Printf ("%s %s\n", 101a7015092SGreg Clayton m_interpreter.GetPrompt(), 102a7015092SGreg Clayton commands[i].c_str()); 103a7015092SGreg Clayton if (!m_interpreter.HandleCommand(commands[i].c_str(), false, result)) 104ebc09c36SJim Ingham break; 105ebc09c36SJim Ingham } 106ebc09c36SJim Ingham 107ebc09c36SJim Ingham if (i < num_commands) 108ebc09c36SJim Ingham { 109ebc09c36SJim Ingham result.AppendErrorWithFormat("Aborting source of '%s' after command '%s' failed.\n", 110ebc09c36SJim Ingham filename, commands[i].c_str()); 111ebc09c36SJim Ingham result.SetStatus (eReturnStatusSuccessFinishResult); 112ebc09c36SJim Ingham } 113ebc09c36SJim Ingham else 114ebc09c36SJim Ingham { 115ebc09c36SJim Ingham success = true; 116ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 117ebc09c36SJim Ingham } 118ebc09c36SJim Ingham } 119ebc09c36SJim Ingham } 120ebc09c36SJim Ingham else 121ebc09c36SJim Ingham { 122ebc09c36SJim Ingham result.AppendErrorWithFormat ("File '%s' does not exist.\n", filename); 123ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 124ebc09c36SJim Ingham success = false; 125ebc09c36SJim Ingham } 126ebc09c36SJim Ingham 127ebc09c36SJim Ingham if (success) 128ebc09c36SJim Ingham { 129ebc09c36SJim Ingham result.SetStatus (eReturnStatusSuccessFinishNoResult); 130ebc09c36SJim Ingham } 131ebc09c36SJim Ingham } 132ebc09c36SJim Ingham else 133ebc09c36SJim Ingham { 134ebc09c36SJim Ingham result.AppendErrorWithFormat("'%s' takes exactly one executable filename argument.\n", GetCommandName()); 135ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 136ebc09c36SJim Ingham } 137ebc09c36SJim Ingham return result.Succeeded(); 138ebc09c36SJim Ingham 139ebc09c36SJim Ingham } 140ebc09c36SJim Ingham }; 141ebc09c36SJim Ingham 142ebc09c36SJim Ingham #pragma mark CommandObjectCommandsAlias 143ebc09c36SJim Ingham //------------------------------------------------------------------------- 144ebc09c36SJim Ingham // CommandObjectCommandsAlias 145ebc09c36SJim Ingham //------------------------------------------------------------------------- 146ebc09c36SJim Ingham 147ebc09c36SJim Ingham class CommandObjectCommandsAlias : public CommandObject 148ebc09c36SJim Ingham { 149ebc09c36SJim Ingham public: 150a7015092SGreg Clayton CommandObjectCommandsAlias (CommandInterpreter &interpreter) : 151a7015092SGreg Clayton CommandObject (interpreter, 152a7015092SGreg Clayton "commands alias", 153e3d26315SCaroline Tice "Allow users to define their own debugger command abbreviations.", 154405fe67fSCaroline Tice NULL) 155ebc09c36SJim Ingham { 156ebc09c36SJim Ingham SetHelpLong( 157ebc09c36SJim Ingham "'alias' allows the user to create a short-cut or abbreviation for long \n\ 158ebc09c36SJim Ingham commands, multi-word commands, and commands that take particular options. \n\ 159ebc09c36SJim Ingham Below are some simple examples of how one might use the 'alias' command: \n\ 16009799af6SCaroline Tice \n 'commands alias sc script' // Creates the abbreviation 'sc' for the 'script' \n\ 161ebc09c36SJim Ingham // command. \n\ 16209799af6SCaroline Tice 'commands alias bp breakpoint' // Creates the abbreviation 'bp' for the 'breakpoint' \n\ 163ebc09c36SJim Ingham // command. Since breakpoint commands are two-word \n\ 164ebc09c36SJim Ingham // commands, the user will still need to enter the \n\ 165ebc09c36SJim Ingham // second word after 'bp', e.g. 'bp enable' or \n\ 166ebc09c36SJim Ingham // 'bp delete'. \n\ 16709799af6SCaroline Tice 'commands alias bpl breakpoint list' // Creates the abbreviation 'bpl' for the \n\ 168ebc09c36SJim Ingham // two-word command 'breakpoint list'. \n\ 169ebc09c36SJim Ingham \nAn alias can include some options for the command, with the values either \n\ 170ebc09c36SJim Ingham filled in at the time the alias is created, or specified as positional \n\ 171ebc09c36SJim Ingham arguments, to be filled in when the alias is invoked. The following example \n\ 172ebc09c36SJim Ingham shows how to create aliases with options: \n\ 173ebc09c36SJim Ingham \n\ 17409799af6SCaroline Tice 'commands alias bfl breakpoint set -f %1 -l %2' \n\ 175ebc09c36SJim Ingham \nThis creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \n\ 176ebc09c36SJim Ingham options already part of the alias. So if the user wants to set a breakpoint \n\ 177ebc09c36SJim Ingham by file and line without explicitly having to use the -f and -l options, the \n\ 178ebc09c36SJim Ingham user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \n\ 179ebc09c36SJim Ingham for the actual arguments that will be passed when the alias command is used. \n\ 180ebc09c36SJim Ingham The number in the placeholder refers to the position/order the actual value \n\ 181ebc09c36SJim Ingham occupies when the alias is used. So all the occurrences of '%1' in the alias \n\ 182ebc09c36SJim Ingham will be replaced with the first argument, all the occurrences of '%2' in the \n\ 183ebc09c36SJim Ingham alias will be replaced with the second argument, and so on. This also allows \n\ 184ebc09c36SJim Ingham actual arguments to be used multiple times within an alias (see 'process \n\ 185ebc09c36SJim Ingham launch' example below). So in the 'bfl' case, the actual file value will be \n\ 186ebc09c36SJim Ingham filled in with the first argument following 'bfl' and the actual line number \n\ 187ebc09c36SJim Ingham value will be filled in with the second argument. The user would use this \n\ 188ebc09c36SJim Ingham alias as follows: \n\ 18909799af6SCaroline Tice \n (lldb) commands alias bfl breakpoint set -f %1 -l %2 \n\ 190ebc09c36SJim Ingham <... some time later ...> \n\ 19109799af6SCaroline Tice (lldb) bfl my-file.c 137 \n\ 192ebc09c36SJim Ingham \nThis would be the same as if the user had entered \n\ 193ebc09c36SJim Ingham 'breakpoint set -f my-file.c -l 137'. \n\ 194ebc09c36SJim Ingham \nAnother example: \n\ 19509799af6SCaroline Tice \n (lldb) commands alias pltty process launch -s -o %1 -e %1 \n\ 19609799af6SCaroline Tice (lldb) pltty /dev/tty0 \n\ 197ebc09c36SJim Ingham // becomes 'process launch -s -o /dev/tty0 -e /dev/tty0' \n\ 198ebc09c36SJim Ingham \nIf the user always wanted to pass the same value to a particular option, the \n\ 199ebc09c36SJim Ingham alias could be defined with that value directly in the alias as a constant, \n\ 200ebc09c36SJim Ingham rather than using a positional placeholder: \n\ 2010708e2c2SSean Callanan \n commands alias bl3 breakpoint set -f %1 -l 3 // Always sets a breakpoint on line \n\ 202ebc09c36SJim Ingham // 3 of whatever file is indicated. \n"); 203ebc09c36SJim Ingham 204405fe67fSCaroline Tice CommandArgumentEntry arg1; 205405fe67fSCaroline Tice CommandArgumentEntry arg2; 206405fe67fSCaroline Tice CommandArgumentEntry arg3; 207405fe67fSCaroline Tice CommandArgumentData alias_arg; 208405fe67fSCaroline Tice CommandArgumentData cmd_arg; 209405fe67fSCaroline Tice CommandArgumentData options_arg; 210405fe67fSCaroline Tice 211405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 212405fe67fSCaroline Tice alias_arg.arg_type = eArgTypeAliasName; 213405fe67fSCaroline Tice alias_arg.arg_repetition = eArgRepeatPlain; 214405fe67fSCaroline Tice 215405fe67fSCaroline Tice // There is only one variant this argument could be; put it into the argument entry. 216405fe67fSCaroline Tice arg1.push_back (alias_arg); 217405fe67fSCaroline Tice 218405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 219405fe67fSCaroline Tice cmd_arg.arg_type = eArgTypeCommandName; 220405fe67fSCaroline Tice cmd_arg.arg_repetition = eArgRepeatPlain; 221405fe67fSCaroline Tice 222405fe67fSCaroline Tice // There is only one variant this argument could be; put it into the argument entry. 223405fe67fSCaroline Tice arg2.push_back (cmd_arg); 224405fe67fSCaroline Tice 225405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 226405fe67fSCaroline Tice options_arg.arg_type = eArgTypeAliasOptions; 227405fe67fSCaroline Tice options_arg.arg_repetition = eArgRepeatOptional; 228405fe67fSCaroline Tice 229405fe67fSCaroline Tice // There is only one variant this argument could be; put it into the argument entry. 230405fe67fSCaroline Tice arg3.push_back (options_arg); 231405fe67fSCaroline Tice 232405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 233405fe67fSCaroline Tice m_arguments.push_back (arg1); 234405fe67fSCaroline Tice m_arguments.push_back (arg2); 235405fe67fSCaroline Tice m_arguments.push_back (arg3); 236ebc09c36SJim Ingham } 237ebc09c36SJim Ingham 238ebc09c36SJim Ingham ~CommandObjectCommandsAlias () 239ebc09c36SJim Ingham { 240ebc09c36SJim Ingham } 241ebc09c36SJim Ingham 242844d2303SCaroline Tice bool 243844d2303SCaroline Tice WantsRawCommandString () 244844d2303SCaroline Tice { 245844d2303SCaroline Tice return true; 246844d2303SCaroline Tice } 247844d2303SCaroline Tice 248844d2303SCaroline Tice bool 249844d2303SCaroline Tice ExecuteRawCommandString (const char *raw_command_line, CommandReturnObject &result) 250844d2303SCaroline Tice { 251844d2303SCaroline Tice Args args (raw_command_line); 252844d2303SCaroline Tice std::string raw_command_string (raw_command_line); 253844d2303SCaroline Tice 254844d2303SCaroline Tice size_t argc = args.GetArgumentCount(); 255844d2303SCaroline Tice 256844d2303SCaroline Tice if (argc < 2) 257844d2303SCaroline Tice { 258844d2303SCaroline Tice result.AppendError ("'alias' requires at least two arguments"); 259844d2303SCaroline Tice result.SetStatus (eReturnStatusFailed); 260844d2303SCaroline Tice return false; 261844d2303SCaroline Tice } 262844d2303SCaroline Tice 263844d2303SCaroline Tice // Get the alias command. 264844d2303SCaroline Tice 265844d2303SCaroline Tice const std::string alias_command = args.GetArgumentAtIndex (0); 266844d2303SCaroline Tice 267844d2303SCaroline Tice // Strip the new alias name off 'raw_command_string' (leave it on args, which gets passed to 'Execute', which 268844d2303SCaroline Tice // does the stripping itself. 269844d2303SCaroline Tice size_t pos = raw_command_string.find (alias_command); 270844d2303SCaroline Tice if (pos == 0) 271844d2303SCaroline Tice { 272844d2303SCaroline Tice raw_command_string = raw_command_string.substr (alias_command.size()); 273844d2303SCaroline Tice pos = raw_command_string.find_first_not_of (' '); 274844d2303SCaroline Tice if ((pos != std::string::npos) && (pos > 0)) 275844d2303SCaroline Tice raw_command_string = raw_command_string.substr (pos); 276844d2303SCaroline Tice } 277844d2303SCaroline Tice else 278844d2303SCaroline Tice { 279844d2303SCaroline Tice result.AppendError ("Error parsing command string. No alias created."); 280844d2303SCaroline Tice result.SetStatus (eReturnStatusFailed); 281844d2303SCaroline Tice return false; 282844d2303SCaroline Tice } 283844d2303SCaroline Tice 284844d2303SCaroline Tice 285844d2303SCaroline Tice // Verify that the command is alias-able. 286844d2303SCaroline Tice if (m_interpreter.CommandExists (alias_command.c_str())) 287844d2303SCaroline Tice { 288844d2303SCaroline Tice result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n", 289844d2303SCaroline Tice alias_command.c_str()); 290844d2303SCaroline Tice result.SetStatus (eReturnStatusFailed); 291844d2303SCaroline Tice return false; 292844d2303SCaroline Tice } 293844d2303SCaroline Tice 294844d2303SCaroline Tice // Get CommandObject that is being aliased. The command name is read from the front of raw_command_string. 295844d2303SCaroline Tice // raw_command_string is returned with the name of the command object stripped off the front. 296844d2303SCaroline Tice CommandObject *cmd_obj = m_interpreter.GetCommandObjectForCommand (raw_command_string); 297844d2303SCaroline Tice 298844d2303SCaroline Tice if (!cmd_obj) 299844d2303SCaroline Tice { 300844d2303SCaroline Tice result.AppendErrorWithFormat ("Invalid command given to 'alias'. '%s' does not begin with a valid command." 301844d2303SCaroline Tice " No alias created.", raw_command_string.c_str()); 302844d2303SCaroline Tice result.SetStatus (eReturnStatusFailed); 303844d2303SCaroline Tice return false; 304844d2303SCaroline Tice } 305844d2303SCaroline Tice else if (!cmd_obj->WantsRawCommandString ()) 306844d2303SCaroline Tice { 307844d2303SCaroline Tice // Note that args was initialized with the original command, and has not been updated to this point. 308844d2303SCaroline Tice // Therefore can we pass it to the version of Execute that does not need/expect raw input in the alias. 309844d2303SCaroline Tice return Execute (args, result); 310844d2303SCaroline Tice } 311844d2303SCaroline Tice else 312844d2303SCaroline Tice { 313844d2303SCaroline Tice // Verify & handle any options/arguments passed to the alias command 314844d2303SCaroline Tice 315844d2303SCaroline Tice OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector); 316844d2303SCaroline Tice OptionArgVector *option_arg_vector = option_arg_vector_sp.get(); 317844d2303SCaroline Tice 318844d2303SCaroline Tice // Check to see if there's anything left in the input command string. 319844d2303SCaroline Tice if (raw_command_string.size() > 0) 320844d2303SCaroline Tice { 321844d2303SCaroline Tice 322844d2303SCaroline Tice // Check to see if the command being aliased can take any command options. 323844d2303SCaroline Tice Options *options = cmd_obj->GetOptions(); 324844d2303SCaroline Tice if (options) 325844d2303SCaroline Tice { 326844d2303SCaroline Tice // See if any options were specified as part of the alias; if so, handle them appropriately 327844d2303SCaroline Tice options->ResetOptionValues (); 328844d2303SCaroline Tice Args tmp_args (raw_command_string.c_str()); 329844d2303SCaroline Tice args.Unshift ("dummy_arg"); 330844d2303SCaroline Tice args.ParseAliasOptions (*options, result, option_arg_vector, raw_command_string); 331844d2303SCaroline Tice args.Shift (); 332844d2303SCaroline Tice if (result.Succeeded()) 333844d2303SCaroline Tice options->VerifyPartialOptions (result); 334844d2303SCaroline Tice if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted) 335844d2303SCaroline Tice { 336844d2303SCaroline Tice result.AppendError ("Unable to create requested alias.\n"); 337844d2303SCaroline Tice return false; 338844d2303SCaroline Tice } 339844d2303SCaroline Tice } 340844d2303SCaroline Tice // Anything remaining must be plain raw input. Push it in as a single raw input argument. 341844d2303SCaroline Tice if (raw_command_string.size() > 0) 342844d2303SCaroline Tice option_arg_vector->push_back (OptionArgPair ("<argument>", 343844d2303SCaroline Tice OptionArgValue (-1, 344844d2303SCaroline Tice raw_command_string))); 345844d2303SCaroline Tice } 346844d2303SCaroline Tice 347844d2303SCaroline Tice // Create the alias 348844d2303SCaroline Tice if (m_interpreter.AliasExists (alias_command.c_str()) 349844d2303SCaroline Tice || m_interpreter.UserCommandExists (alias_command.c_str())) 350844d2303SCaroline Tice { 351844d2303SCaroline Tice OptionArgVectorSP temp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str())); 352844d2303SCaroline Tice if (temp_option_arg_sp.get()) 353844d2303SCaroline Tice { 354844d2303SCaroline Tice if (option_arg_vector->size() == 0) 355844d2303SCaroline Tice m_interpreter.RemoveAliasOptions (alias_command.c_str()); 356844d2303SCaroline Tice } 357844d2303SCaroline Tice result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n", 358844d2303SCaroline Tice alias_command.c_str()); 359844d2303SCaroline Tice } 360844d2303SCaroline Tice 361844d2303SCaroline Tice CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false); 362*472362e6SCaroline Tice if (cmd_obj_sp) 363*472362e6SCaroline Tice { 364844d2303SCaroline Tice m_interpreter.AddAlias (alias_command.c_str(), cmd_obj_sp); 365844d2303SCaroline Tice if (option_arg_vector->size() > 0) 366844d2303SCaroline Tice m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp); 367844d2303SCaroline Tice result.SetStatus (eReturnStatusSuccessFinishNoResult); 368844d2303SCaroline Tice } 369*472362e6SCaroline Tice else 370*472362e6SCaroline Tice { 371*472362e6SCaroline Tice result.AppendError ("Unable to create requested alias.\n"); 372*472362e6SCaroline Tice result.SetStatus (eReturnStatusFailed); 373*472362e6SCaroline Tice } 374*472362e6SCaroline Tice } 375844d2303SCaroline Tice return result.Succeeded(); 376844d2303SCaroline Tice } 377ebc09c36SJim Ingham 378ebc09c36SJim Ingham bool 379ebc09c36SJim Ingham Execute 380ebc09c36SJim Ingham ( 381ebc09c36SJim Ingham Args& args, 382ebc09c36SJim Ingham CommandReturnObject &result 383ebc09c36SJim Ingham ) 384ebc09c36SJim Ingham { 385867b185dSCaroline Tice size_t argc = args.GetArgumentCount(); 386ebc09c36SJim Ingham 387ebc09c36SJim Ingham if (argc < 2) 388ebc09c36SJim Ingham { 389ebc09c36SJim Ingham result.AppendError ("'alias' requires at least two arguments"); 390ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 391ebc09c36SJim Ingham return false; 392ebc09c36SJim Ingham } 393ebc09c36SJim Ingham 394ebc09c36SJim Ingham const std::string alias_command = args.GetArgumentAtIndex(0); 395ebc09c36SJim Ingham const std::string actual_command = args.GetArgumentAtIndex(1); 396ebc09c36SJim Ingham 397ebc09c36SJim Ingham args.Shift(); // Shift the alias command word off the argument vector. 398ebc09c36SJim Ingham args.Shift(); // Shift the old command word off the argument vector. 399ebc09c36SJim Ingham 400ebc09c36SJim Ingham // Verify that the command is alias'able, and get the appropriate command object. 401ebc09c36SJim Ingham 402a7015092SGreg Clayton if (m_interpreter.CommandExists (alias_command.c_str())) 403ebc09c36SJim Ingham { 404ebc09c36SJim Ingham result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n", 405ebc09c36SJim Ingham alias_command.c_str()); 406ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 407ebc09c36SJim Ingham } 408ebc09c36SJim Ingham else 409ebc09c36SJim Ingham { 410a7015092SGreg Clayton CommandObjectSP command_obj_sp(m_interpreter.GetCommandSPExact (actual_command.c_str(), true)); 411ebc09c36SJim Ingham CommandObjectSP subcommand_obj_sp; 412ebc09c36SJim Ingham bool use_subcommand = false; 413ebc09c36SJim Ingham if (command_obj_sp.get()) 414ebc09c36SJim Ingham { 415ebc09c36SJim Ingham CommandObject *cmd_obj = command_obj_sp.get(); 416c982c768SGreg Clayton CommandObject *sub_cmd_obj = NULL; 417ebc09c36SJim Ingham OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector); 418ebc09c36SJim Ingham OptionArgVector *option_arg_vector = option_arg_vector_sp.get(); 419ebc09c36SJim Ingham 420844d2303SCaroline Tice while (cmd_obj->IsMultiwordObject() && args.GetArgumentCount() > 0) 421ebc09c36SJim Ingham { 422ebc09c36SJim Ingham if (argc >= 3) 423ebc09c36SJim Ingham { 424ebc09c36SJim Ingham const std::string sub_command = args.GetArgumentAtIndex(0); 425ebc09c36SJim Ingham assert (sub_command.length() != 0); 426ebc09c36SJim Ingham subcommand_obj_sp = 427ebc09c36SJim Ingham (((CommandObjectMultiword *) cmd_obj)->GetSubcommandSP (sub_command.c_str())); 428ebc09c36SJim Ingham if (subcommand_obj_sp.get()) 429ebc09c36SJim Ingham { 430ebc09c36SJim Ingham sub_cmd_obj = subcommand_obj_sp.get(); 431ebc09c36SJim Ingham use_subcommand = true; 432ebc09c36SJim Ingham args.Shift(); // Shift the sub_command word off the argument vector. 433844d2303SCaroline Tice cmd_obj = sub_cmd_obj; 434ebc09c36SJim Ingham } 435ebc09c36SJim Ingham else 436ebc09c36SJim Ingham { 437f415eeb4SCaroline Tice result.AppendErrorWithFormat("'%s' is not a valid sub-command of '%s'. " 438f415eeb4SCaroline Tice "Unable to create alias.\n", 439f415eeb4SCaroline Tice sub_command.c_str(), actual_command.c_str()); 440ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 441ebc09c36SJim Ingham return false; 442ebc09c36SJim Ingham } 443ebc09c36SJim Ingham } 444ebc09c36SJim Ingham } 445ebc09c36SJim Ingham 446ebc09c36SJim Ingham // Verify & handle any options/arguments passed to the alias command 447ebc09c36SJim Ingham 448ebc09c36SJim Ingham if (args.GetArgumentCount () > 0) 449ebc09c36SJim Ingham { 450ebc09c36SJim Ingham if ((!use_subcommand && (cmd_obj->GetOptions() != NULL)) 451ebc09c36SJim Ingham || (use_subcommand && (sub_cmd_obj->GetOptions() != NULL))) 452ebc09c36SJim Ingham { 453ebc09c36SJim Ingham Options *options; 454ebc09c36SJim Ingham if (use_subcommand) 455ebc09c36SJim Ingham options = sub_cmd_obj->GetOptions(); 456ebc09c36SJim Ingham else 457ebc09c36SJim Ingham options = cmd_obj->GetOptions(); 458ebc09c36SJim Ingham options->ResetOptionValues (); 459844d2303SCaroline Tice std::string empty_string; 460ebc09c36SJim Ingham args.Unshift ("dummy_arg"); 461844d2303SCaroline Tice args.ParseAliasOptions (*options, result, option_arg_vector, empty_string); 462ebc09c36SJim Ingham args.Shift (); 463ebc09c36SJim Ingham if (result.Succeeded()) 464ebc09c36SJim Ingham options->VerifyPartialOptions (result); 465867b185dSCaroline Tice if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted) 466ebc09c36SJim Ingham { 467867b185dSCaroline Tice result.AppendError ("Unable to create requested command alias.\n"); 468e7941795SCaroline Tice return false; 469867b185dSCaroline Tice } 470867b185dSCaroline Tice } 471867b185dSCaroline Tice 472867b185dSCaroline Tice // Anything remaining in args must be a plain argument. 473867b185dSCaroline Tice 474867b185dSCaroline Tice argc = args.GetArgumentCount(); 475c982c768SGreg Clayton for (size_t i = 0; i < argc; ++i) 476636d6ed0SCaroline Tice if (strcmp (args.GetArgumentAtIndex (i), "") != 0) 477d9d63369SCaroline Tice option_arg_vector->push_back 478d9d63369SCaroline Tice (OptionArgPair ("<argument>", 479d9d63369SCaroline Tice OptionArgValue (-1, 480d9d63369SCaroline Tice std::string (args.GetArgumentAtIndex (i))))); 481ebc09c36SJim Ingham } 482ebc09c36SJim Ingham 483ebc09c36SJim Ingham // Create the alias. 484ebc09c36SJim Ingham 485a7015092SGreg Clayton if (m_interpreter.AliasExists (alias_command.c_str()) 486a7015092SGreg Clayton || m_interpreter.UserCommandExists (alias_command.c_str())) 487ebc09c36SJim Ingham { 488a7015092SGreg Clayton OptionArgVectorSP tmp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str())); 489ebc09c36SJim Ingham if (tmp_option_arg_sp.get()) 490ebc09c36SJim Ingham { 491ebc09c36SJim Ingham if (option_arg_vector->size() == 0) 492a7015092SGreg Clayton m_interpreter.RemoveAliasOptions (alias_command.c_str()); 493ebc09c36SJim Ingham } 494ebc09c36SJim Ingham result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n", 495ebc09c36SJim Ingham alias_command.c_str()); 496ebc09c36SJim Ingham } 497ebc09c36SJim Ingham 498ebc09c36SJim Ingham if (use_subcommand) 499a7015092SGreg Clayton m_interpreter.AddAlias (alias_command.c_str(), subcommand_obj_sp); 500ebc09c36SJim Ingham else 501a7015092SGreg Clayton m_interpreter.AddAlias (alias_command.c_str(), command_obj_sp); 502ebc09c36SJim Ingham if (option_arg_vector->size() > 0) 503a7015092SGreg Clayton m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp); 504ebc09c36SJim Ingham result.SetStatus (eReturnStatusSuccessFinishNoResult); 505ebc09c36SJim Ingham } 506ebc09c36SJim Ingham else 507ebc09c36SJim Ingham { 508ebc09c36SJim Ingham result.AppendErrorWithFormat ("'%s' is not an existing command.\n", actual_command.c_str()); 509ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 510e7941795SCaroline Tice return false; 511ebc09c36SJim Ingham } 512ebc09c36SJim Ingham } 513ebc09c36SJim Ingham 514ebc09c36SJim Ingham return result.Succeeded(); 515ebc09c36SJim Ingham } 516ebc09c36SJim Ingham }; 517ebc09c36SJim Ingham 518ebc09c36SJim Ingham #pragma mark CommandObjectCommandsUnalias 519ebc09c36SJim Ingham //------------------------------------------------------------------------- 520ebc09c36SJim Ingham // CommandObjectCommandsUnalias 521ebc09c36SJim Ingham //------------------------------------------------------------------------- 522ebc09c36SJim Ingham 523ebc09c36SJim Ingham class CommandObjectCommandsUnalias : public CommandObject 524ebc09c36SJim Ingham { 525ebc09c36SJim Ingham public: 526a7015092SGreg Clayton CommandObjectCommandsUnalias (CommandInterpreter &interpreter) : 527a7015092SGreg Clayton CommandObject (interpreter, 528a7015092SGreg Clayton "commands unalias", 52986ddae50SCaroline Tice "Allow the user to remove/delete a user-defined command abbreviation.", 530405fe67fSCaroline Tice NULL) 531ebc09c36SJim Ingham { 532405fe67fSCaroline Tice CommandArgumentEntry arg; 533405fe67fSCaroline Tice CommandArgumentData alias_arg; 534405fe67fSCaroline Tice 535405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 536405fe67fSCaroline Tice alias_arg.arg_type = eArgTypeAliasName; 537405fe67fSCaroline Tice alias_arg.arg_repetition = eArgRepeatPlain; 538405fe67fSCaroline Tice 539405fe67fSCaroline Tice // There is only one variant this argument could be; put it into the argument entry. 540405fe67fSCaroline Tice arg.push_back (alias_arg); 541405fe67fSCaroline Tice 542405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 543405fe67fSCaroline Tice m_arguments.push_back (arg); 544ebc09c36SJim Ingham } 545ebc09c36SJim Ingham 546ebc09c36SJim Ingham ~CommandObjectCommandsUnalias() 547ebc09c36SJim Ingham { 548ebc09c36SJim Ingham } 549ebc09c36SJim Ingham 550ebc09c36SJim Ingham 551ebc09c36SJim Ingham bool 552ebc09c36SJim Ingham Execute 553ebc09c36SJim Ingham ( 554ebc09c36SJim Ingham Args& args, 555ebc09c36SJim Ingham CommandReturnObject &result 556ebc09c36SJim Ingham ) 557ebc09c36SJim Ingham { 558ebc09c36SJim Ingham CommandObject::CommandMap::iterator pos; 559ebc09c36SJim Ingham CommandObject *cmd_obj; 560ebc09c36SJim Ingham 561ebc09c36SJim Ingham if (args.GetArgumentCount() != 0) 562ebc09c36SJim Ingham { 563ebc09c36SJim Ingham const char *command_name = args.GetArgumentAtIndex(0); 564a7015092SGreg Clayton cmd_obj = m_interpreter.GetCommandObject(command_name); 565ebc09c36SJim Ingham if (cmd_obj) 566ebc09c36SJim Ingham { 567a7015092SGreg Clayton if (m_interpreter.CommandExists (command_name)) 568ebc09c36SJim Ingham { 569ebc09c36SJim Ingham result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n", 570ebc09c36SJim Ingham command_name); 571ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 572ebc09c36SJim Ingham } 573ebc09c36SJim Ingham else 574ebc09c36SJim Ingham { 575ebc09c36SJim Ingham 576a7015092SGreg Clayton if (m_interpreter.RemoveAlias (command_name) == false) 577ebc09c36SJim Ingham { 578a7015092SGreg Clayton if (m_interpreter.AliasExists (command_name)) 579ebc09c36SJim Ingham result.AppendErrorWithFormat ("Error occurred while attempting to unalias '%s'.\n", 580ebc09c36SJim Ingham command_name); 581ebc09c36SJim Ingham else 582ebc09c36SJim Ingham result.AppendErrorWithFormat ("'%s' is not an existing alias.\n", command_name); 583ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 584ebc09c36SJim Ingham } 585ebc09c36SJim Ingham else 586ebc09c36SJim Ingham result.SetStatus (eReturnStatusSuccessFinishNoResult); 587ebc09c36SJim Ingham } 588ebc09c36SJim Ingham } 589ebc09c36SJim Ingham else 590ebc09c36SJim Ingham { 591ebc09c36SJim Ingham result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a " 592ebc09c36SJim Ingham "current list of commands.\n", 593ebc09c36SJim Ingham command_name); 594ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 595ebc09c36SJim Ingham } 596ebc09c36SJim Ingham } 597ebc09c36SJim Ingham else 598ebc09c36SJim Ingham { 599ebc09c36SJim Ingham result.AppendError ("must call 'unalias' with a valid alias"); 600ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 601ebc09c36SJim Ingham } 602ebc09c36SJim Ingham 603ebc09c36SJim Ingham return result.Succeeded(); 604ebc09c36SJim Ingham } 605ebc09c36SJim Ingham }; 606ebc09c36SJim Ingham 607ebc09c36SJim Ingham #pragma mark CommandObjectMultiwordCommands 608ebc09c36SJim Ingham 609ebc09c36SJim Ingham //------------------------------------------------------------------------- 610ebc09c36SJim Ingham // CommandObjectMultiwordCommands 611ebc09c36SJim Ingham //------------------------------------------------------------------------- 612ebc09c36SJim Ingham 613ebc09c36SJim Ingham CommandObjectMultiwordCommands::CommandObjectMultiwordCommands (CommandInterpreter &interpreter) : 614a7015092SGreg Clayton CommandObjectMultiword (interpreter, 615a7015092SGreg Clayton "commands", 6163f4c09c1SCaroline Tice "A set of commands for managing or customizing the debugger commands.", 617ebc09c36SJim Ingham "commands <subcommand> [<subcommand-options>]") 618ebc09c36SJim Ingham { 619a7015092SGreg Clayton LoadSubCommand ("source", CommandObjectSP (new CommandObjectCommandsSource (interpreter))); 620a7015092SGreg Clayton LoadSubCommand ("alias", CommandObjectSP (new CommandObjectCommandsAlias (interpreter))); 621a7015092SGreg Clayton LoadSubCommand ("unalias", CommandObjectSP (new CommandObjectCommandsUnalias (interpreter))); 622ebc09c36SJim Ingham } 623ebc09c36SJim Ingham 624ebc09c36SJim Ingham CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands () 625ebc09c36SJim Ingham { 626ebc09c36SJim Ingham } 627ebc09c36SJim Ingham 628