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 150e5e5a79SGreg Clayton #include "llvm/ADT/StringRef.h" 160e5e5a79SGreg Clayton 17ebc09c36SJim Ingham // Project includes 18ebc09c36SJim Ingham #include "lldb/Core/Debugger.h" 19de164aaaSGreg Clayton #include "lldb/Core/InputReader.h" 20de164aaaSGreg Clayton #include "lldb/Interpreter/Args.h" 21ebc09c36SJim Ingham #include "lldb/Interpreter/CommandInterpreter.h" 22de164aaaSGreg Clayton #include "lldb/Interpreter/CommandObjectRegexCommand.h" 23ebc09c36SJim Ingham #include "lldb/Interpreter/CommandReturnObject.h" 24ebc09c36SJim Ingham #include "lldb/Interpreter/Options.h" 25ebc09c36SJim Ingham 26ebc09c36SJim Ingham using namespace lldb; 27ebc09c36SJim Ingham using namespace lldb_private; 28ebc09c36SJim Ingham 29ebc09c36SJim Ingham //------------------------------------------------------------------------- 30ebc09c36SJim Ingham // CommandObjectCommandsSource 31ebc09c36SJim Ingham //------------------------------------------------------------------------- 32ebc09c36SJim Ingham 33*a5a97ebeSJim Ingham class CommandObjectCommandsHistory : public CommandObject 34*a5a97ebeSJim Ingham { 35*a5a97ebeSJim Ingham private: 36*a5a97ebeSJim Ingham 37*a5a97ebeSJim Ingham class CommandOptions : public Options 38*a5a97ebeSJim Ingham { 39*a5a97ebeSJim Ingham public: 40*a5a97ebeSJim Ingham 41*a5a97ebeSJim Ingham CommandOptions (CommandInterpreter &interpreter) : 42*a5a97ebeSJim Ingham Options (interpreter) 43*a5a97ebeSJim Ingham { 44*a5a97ebeSJim Ingham } 45*a5a97ebeSJim Ingham 46*a5a97ebeSJim Ingham virtual 47*a5a97ebeSJim Ingham ~CommandOptions (){} 48*a5a97ebeSJim Ingham 49*a5a97ebeSJim Ingham virtual Error 50*a5a97ebeSJim Ingham SetOptionValue (uint32_t option_idx, const char *option_arg) 51*a5a97ebeSJim Ingham { 52*a5a97ebeSJim Ingham Error error; 53*a5a97ebeSJim Ingham char short_option = (char) m_getopt_table[option_idx].val; 54*a5a97ebeSJim Ingham bool success; 55*a5a97ebeSJim Ingham 56*a5a97ebeSJim Ingham switch (short_option) 57*a5a97ebeSJim Ingham { 58*a5a97ebeSJim Ingham case 'c': 59*a5a97ebeSJim Ingham m_end_idx = Args::StringToUInt32(option_arg, UINT_MAX, 0, &success); 60*a5a97ebeSJim Ingham if (!success) 61*a5a97ebeSJim Ingham error.SetErrorStringWithFormat("Invalid value for count: %s.\n", option_arg); 62*a5a97ebeSJim Ingham if (m_end_idx != 0) 63*a5a97ebeSJim Ingham m_end_idx--; 64*a5a97ebeSJim Ingham m_start_idx = 0; 65*a5a97ebeSJim Ingham break; 66*a5a97ebeSJim Ingham case 'e': 67*a5a97ebeSJim Ingham m_end_idx = Args::StringToUInt32(option_arg, 0, 0, &success); 68*a5a97ebeSJim Ingham if (!success) 69*a5a97ebeSJim Ingham error.SetErrorStringWithFormat("Invalid value for end index: %s.\n", option_arg); 70*a5a97ebeSJim Ingham break; 71*a5a97ebeSJim Ingham case 's': 72*a5a97ebeSJim Ingham m_start_idx = Args::StringToUInt32(option_arg, 0, 0, &success); 73*a5a97ebeSJim Ingham if (!success) 74*a5a97ebeSJim Ingham error.SetErrorStringWithFormat("Invalid value for start index: %s.\n", option_arg); 75*a5a97ebeSJim Ingham break; 76*a5a97ebeSJim Ingham default: 77*a5a97ebeSJim Ingham error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); 78*a5a97ebeSJim Ingham break; 79*a5a97ebeSJim Ingham } 80*a5a97ebeSJim Ingham 81*a5a97ebeSJim Ingham return error; 82*a5a97ebeSJim Ingham } 83*a5a97ebeSJim Ingham 84*a5a97ebeSJim Ingham void 85*a5a97ebeSJim Ingham OptionParsingStarting () 86*a5a97ebeSJim Ingham { 87*a5a97ebeSJim Ingham m_start_idx = 0; 88*a5a97ebeSJim Ingham m_end_idx = UINT_MAX; 89*a5a97ebeSJim Ingham } 90*a5a97ebeSJim Ingham 91*a5a97ebeSJim Ingham const OptionDefinition* 92*a5a97ebeSJim Ingham GetDefinitions () 93*a5a97ebeSJim Ingham { 94*a5a97ebeSJim Ingham return g_option_table; 95*a5a97ebeSJim Ingham } 96*a5a97ebeSJim Ingham 97*a5a97ebeSJim Ingham // Options table: Required for subclasses of Options. 98*a5a97ebeSJim Ingham 99*a5a97ebeSJim Ingham static OptionDefinition g_option_table[]; 100*a5a97ebeSJim Ingham 101*a5a97ebeSJim Ingham // Instance variables to hold the values for command options. 102*a5a97ebeSJim Ingham 103*a5a97ebeSJim Ingham uint32_t m_start_idx; 104*a5a97ebeSJim Ingham uint32_t m_end_idx; 105*a5a97ebeSJim Ingham }; 106*a5a97ebeSJim Ingham 107*a5a97ebeSJim Ingham CommandOptions m_options; 108*a5a97ebeSJim Ingham 109*a5a97ebeSJim Ingham virtual Options * 110*a5a97ebeSJim Ingham GetOptions () 111*a5a97ebeSJim Ingham { 112*a5a97ebeSJim Ingham return &m_options; 113*a5a97ebeSJim Ingham } 114*a5a97ebeSJim Ingham 115*a5a97ebeSJim Ingham public: 116*a5a97ebeSJim Ingham CommandObjectCommandsHistory(CommandInterpreter &interpreter) : 117*a5a97ebeSJim Ingham CommandObject (interpreter, 118*a5a97ebeSJim Ingham "command history", 119*a5a97ebeSJim Ingham "Dump the history of commands in this session.", 120*a5a97ebeSJim Ingham NULL), 121*a5a97ebeSJim Ingham m_options (interpreter) 122*a5a97ebeSJim Ingham { 123*a5a97ebeSJim Ingham } 124*a5a97ebeSJim Ingham 125*a5a97ebeSJim Ingham ~CommandObjectCommandsHistory () 126*a5a97ebeSJim Ingham { 127*a5a97ebeSJim Ingham } 128*a5a97ebeSJim Ingham 129*a5a97ebeSJim Ingham bool 130*a5a97ebeSJim Ingham Execute 131*a5a97ebeSJim Ingham ( 132*a5a97ebeSJim Ingham Args& args, 133*a5a97ebeSJim Ingham CommandReturnObject &result 134*a5a97ebeSJim Ingham ) 135*a5a97ebeSJim Ingham { 136*a5a97ebeSJim Ingham 137*a5a97ebeSJim Ingham m_interpreter.DumpHistory (result.GetOutputStream(), 138*a5a97ebeSJim Ingham m_options.m_start_idx, 139*a5a97ebeSJim Ingham m_options.m_end_idx); 140*a5a97ebeSJim Ingham return result.Succeeded(); 141*a5a97ebeSJim Ingham 142*a5a97ebeSJim Ingham } 143*a5a97ebeSJim Ingham }; 144*a5a97ebeSJim Ingham 145*a5a97ebeSJim Ingham OptionDefinition 146*a5a97ebeSJim Ingham CommandObjectCommandsHistory::CommandOptions::g_option_table[] = 147*a5a97ebeSJim Ingham { 148*a5a97ebeSJim Ingham { LLDB_OPT_SET_1, false, "count", 'c', required_argument, NULL, 0, eArgTypeUnsignedInteger, "How many history commands to print."}, 149*a5a97ebeSJim Ingham { LLDB_OPT_SET_1, false, "start-index", 's', required_argument, NULL, 0, eArgTypeUnsignedInteger, "Index at which to start printing history commands."}, 150*a5a97ebeSJim Ingham { LLDB_OPT_SET_1, false, "end-index", 'e', required_argument, NULL, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands."}, 151*a5a97ebeSJim Ingham { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 152*a5a97ebeSJim Ingham }; 153*a5a97ebeSJim Ingham 154*a5a97ebeSJim Ingham 155*a5a97ebeSJim Ingham //------------------------------------------------------------------------- 156*a5a97ebeSJim Ingham // CommandObjectCommandsSource 157*a5a97ebeSJim Ingham //------------------------------------------------------------------------- 158*a5a97ebeSJim Ingham 159ebc09c36SJim Ingham class CommandObjectCommandsSource : public CommandObject 160ebc09c36SJim Ingham { 161e16c50a1SJim Ingham private: 162e16c50a1SJim Ingham 163e16c50a1SJim Ingham class CommandOptions : public Options 164e16c50a1SJim Ingham { 165e16c50a1SJim Ingham public: 166e16c50a1SJim Ingham 167eb0103f2SGreg Clayton CommandOptions (CommandInterpreter &interpreter) : 168eb0103f2SGreg Clayton Options (interpreter) 169eb0103f2SGreg Clayton { 170eb0103f2SGreg Clayton } 171e16c50a1SJim Ingham 172e16c50a1SJim Ingham virtual 173e16c50a1SJim Ingham ~CommandOptions (){} 174e16c50a1SJim Ingham 175e16c50a1SJim Ingham virtual Error 176f6b8b581SGreg Clayton SetOptionValue (uint32_t option_idx, const char *option_arg) 177e16c50a1SJim Ingham { 178e16c50a1SJim Ingham Error error; 179e16c50a1SJim Ingham char short_option = (char) m_getopt_table[option_idx].val; 180e16c50a1SJim Ingham bool success; 181e16c50a1SJim Ingham 182e16c50a1SJim Ingham switch (short_option) 183e16c50a1SJim Ingham { 184e16c50a1SJim Ingham case 'e': 185e16c50a1SJim Ingham m_stop_on_error = Args::StringToBoolean(option_arg, true, &success); 186e16c50a1SJim Ingham if (!success) 187e16c50a1SJim Ingham error.SetErrorStringWithFormat("Invalid value for stop-on-error: %s.\n", option_arg); 188e16c50a1SJim Ingham break; 189e16c50a1SJim Ingham case 'c': 190e16c50a1SJim Ingham m_stop_on_continue = Args::StringToBoolean(option_arg, true, &success); 191e16c50a1SJim Ingham if (!success) 192e16c50a1SJim Ingham error.SetErrorStringWithFormat("Invalid value for stop-on-continue: %s.\n", option_arg); 193e16c50a1SJim Ingham break; 194e16c50a1SJim Ingham default: 195e16c50a1SJim Ingham error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); 196e16c50a1SJim Ingham break; 197e16c50a1SJim Ingham } 198e16c50a1SJim Ingham 199e16c50a1SJim Ingham return error; 200e16c50a1SJim Ingham } 201e16c50a1SJim Ingham 202e16c50a1SJim Ingham void 203f6b8b581SGreg Clayton OptionParsingStarting () 204e16c50a1SJim Ingham { 205e16c50a1SJim Ingham m_stop_on_error = true; 206e16c50a1SJim Ingham m_stop_on_continue = true; 207e16c50a1SJim Ingham } 208e16c50a1SJim Ingham 209e0d378b3SGreg Clayton const OptionDefinition* 210e16c50a1SJim Ingham GetDefinitions () 211e16c50a1SJim Ingham { 212e16c50a1SJim Ingham return g_option_table; 213e16c50a1SJim Ingham } 214e16c50a1SJim Ingham 215e16c50a1SJim Ingham // Options table: Required for subclasses of Options. 216e16c50a1SJim Ingham 217e0d378b3SGreg Clayton static OptionDefinition g_option_table[]; 218e16c50a1SJim Ingham 219e16c50a1SJim Ingham // Instance variables to hold the values for command options. 220e16c50a1SJim Ingham 221e16c50a1SJim Ingham bool m_stop_on_error; 222e16c50a1SJim Ingham bool m_stop_on_continue; 223e16c50a1SJim Ingham }; 224e16c50a1SJim Ingham 225e16c50a1SJim Ingham CommandOptions m_options; 226e16c50a1SJim Ingham 227e16c50a1SJim Ingham virtual Options * 228e16c50a1SJim Ingham GetOptions () 229e16c50a1SJim Ingham { 230e16c50a1SJim Ingham return &m_options; 231e16c50a1SJim Ingham } 232e16c50a1SJim Ingham 233ebc09c36SJim Ingham public: 234a7015092SGreg Clayton CommandObjectCommandsSource(CommandInterpreter &interpreter) : 235a7015092SGreg Clayton CommandObject (interpreter, 2360e5e5a79SGreg Clayton "command source", 237e3d26315SCaroline Tice "Read in debugger commands from the file <filename> and execute them.", 238eb0103f2SGreg Clayton NULL), 239eb0103f2SGreg Clayton m_options (interpreter) 240ebc09c36SJim Ingham { 241405fe67fSCaroline Tice CommandArgumentEntry arg; 242405fe67fSCaroline Tice CommandArgumentData file_arg; 243405fe67fSCaroline Tice 244405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 245405fe67fSCaroline Tice file_arg.arg_type = eArgTypeFilename; 246405fe67fSCaroline Tice file_arg.arg_repetition = eArgRepeatPlain; 247405fe67fSCaroline Tice 248405fe67fSCaroline Tice // There is only one variant this argument could be; put it into the argument entry. 249405fe67fSCaroline Tice arg.push_back (file_arg); 250405fe67fSCaroline Tice 251405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 252405fe67fSCaroline Tice m_arguments.push_back (arg); 253ebc09c36SJim Ingham } 254ebc09c36SJim Ingham 255ebc09c36SJim Ingham ~CommandObjectCommandsSource () 256ebc09c36SJim Ingham { 257ebc09c36SJim Ingham } 258ebc09c36SJim Ingham 259ebc09c36SJim Ingham bool 260ebc09c36SJim Ingham Execute 261ebc09c36SJim Ingham ( 262ebc09c36SJim Ingham Args& args, 263ebc09c36SJim Ingham CommandReturnObject &result 264ebc09c36SJim Ingham ) 265ebc09c36SJim Ingham { 266ebc09c36SJim Ingham const int argc = args.GetArgumentCount(); 267ebc09c36SJim Ingham if (argc == 1) 268ebc09c36SJim Ingham { 269ebc09c36SJim Ingham const char *filename = args.GetArgumentAtIndex(0); 270ebc09c36SJim Ingham 271ebc09c36SJim Ingham result.AppendMessageWithFormat ("Executing commands in '%s'.\n", filename); 272ebc09c36SJim Ingham 2731ee3853fSJohnny Chen FileSpec cmd_file (filename, true); 274e16c50a1SJim Ingham ExecutionContext *exe_ctx = NULL; // Just use the default context. 275e16c50a1SJim Ingham bool echo_commands = true; 276e16c50a1SJim Ingham bool print_results = true; 277ebc09c36SJim Ingham 278e16c50a1SJim Ingham m_interpreter.HandleCommandsFromFile (cmd_file, 279e16c50a1SJim Ingham exe_ctx, 280e16c50a1SJim Ingham m_options.m_stop_on_continue, 281e16c50a1SJim Ingham m_options.m_stop_on_error, 282e16c50a1SJim Ingham echo_commands, 283e16c50a1SJim Ingham print_results, 284e16c50a1SJim Ingham result); 285ebc09c36SJim Ingham } 286ebc09c36SJim Ingham else 287ebc09c36SJim Ingham { 288ebc09c36SJim Ingham result.AppendErrorWithFormat("'%s' takes exactly one executable filename argument.\n", GetCommandName()); 289ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 290ebc09c36SJim Ingham } 291ebc09c36SJim Ingham return result.Succeeded(); 292ebc09c36SJim Ingham 293ebc09c36SJim Ingham } 294ebc09c36SJim Ingham }; 295ebc09c36SJim Ingham 296e0d378b3SGreg Clayton OptionDefinition 297e16c50a1SJim Ingham CommandObjectCommandsSource::CommandOptions::g_option_table[] = 298e16c50a1SJim Ingham { 299e16c50a1SJim Ingham { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', required_argument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on error."}, 300e16c50a1SJim Ingham { LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', required_argument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on continue."}, 301e16c50a1SJim Ingham { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 302e16c50a1SJim Ingham }; 303e16c50a1SJim Ingham 304ebc09c36SJim Ingham #pragma mark CommandObjectCommandsAlias 305ebc09c36SJim Ingham //------------------------------------------------------------------------- 306ebc09c36SJim Ingham // CommandObjectCommandsAlias 307ebc09c36SJim Ingham //------------------------------------------------------------------------- 308ebc09c36SJim Ingham 309ebc09c36SJim Ingham class CommandObjectCommandsAlias : public CommandObject 310ebc09c36SJim Ingham { 311ebc09c36SJim Ingham public: 312a7015092SGreg Clayton CommandObjectCommandsAlias (CommandInterpreter &interpreter) : 313a7015092SGreg Clayton CommandObject (interpreter, 3140e5e5a79SGreg Clayton "command alias", 315e3d26315SCaroline Tice "Allow users to define their own debugger command abbreviations.", 316405fe67fSCaroline Tice NULL) 317ebc09c36SJim Ingham { 318ebc09c36SJim Ingham SetHelpLong( 319ebc09c36SJim Ingham "'alias' allows the user to create a short-cut or abbreviation for long \n\ 320ebc09c36SJim Ingham commands, multi-word commands, and commands that take particular options. \n\ 321ebc09c36SJim Ingham Below are some simple examples of how one might use the 'alias' command: \n\ 32209799af6SCaroline Tice \n 'commands alias sc script' // Creates the abbreviation 'sc' for the 'script' \n\ 323ebc09c36SJim Ingham // command. \n\ 32409799af6SCaroline Tice 'commands alias bp breakpoint' // Creates the abbreviation 'bp' for the 'breakpoint' \n\ 325ebc09c36SJim Ingham // command. Since breakpoint commands are two-word \n\ 326ebc09c36SJim Ingham // commands, the user will still need to enter the \n\ 327ebc09c36SJim Ingham // second word after 'bp', e.g. 'bp enable' or \n\ 328ebc09c36SJim Ingham // 'bp delete'. \n\ 32909799af6SCaroline Tice 'commands alias bpl breakpoint list' // Creates the abbreviation 'bpl' for the \n\ 330ebc09c36SJim Ingham // two-word command 'breakpoint list'. \n\ 331ebc09c36SJim Ingham \nAn alias can include some options for the command, with the values either \n\ 332ebc09c36SJim Ingham filled in at the time the alias is created, or specified as positional \n\ 333ebc09c36SJim Ingham arguments, to be filled in when the alias is invoked. The following example \n\ 334ebc09c36SJim Ingham shows how to create aliases with options: \n\ 335ebc09c36SJim Ingham \n\ 33609799af6SCaroline Tice 'commands alias bfl breakpoint set -f %1 -l %2' \n\ 337ebc09c36SJim Ingham \nThis creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \n\ 338ebc09c36SJim Ingham options already part of the alias. So if the user wants to set a breakpoint \n\ 339ebc09c36SJim Ingham by file and line without explicitly having to use the -f and -l options, the \n\ 340ebc09c36SJim Ingham user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \n\ 341ebc09c36SJim Ingham for the actual arguments that will be passed when the alias command is used. \n\ 342ebc09c36SJim Ingham The number in the placeholder refers to the position/order the actual value \n\ 343ebc09c36SJim Ingham occupies when the alias is used. So all the occurrences of '%1' in the alias \n\ 344ebc09c36SJim Ingham will be replaced with the first argument, all the occurrences of '%2' in the \n\ 345ebc09c36SJim Ingham alias will be replaced with the second argument, and so on. This also allows \n\ 346ebc09c36SJim Ingham actual arguments to be used multiple times within an alias (see 'process \n\ 347ebc09c36SJim Ingham launch' example below). So in the 'bfl' case, the actual file value will be \n\ 348ebc09c36SJim Ingham filled in with the first argument following 'bfl' and the actual line number \n\ 349ebc09c36SJim Ingham value will be filled in with the second argument. The user would use this \n\ 350ebc09c36SJim Ingham alias as follows: \n\ 35109799af6SCaroline Tice \n (lldb) commands alias bfl breakpoint set -f %1 -l %2 \n\ 352ebc09c36SJim Ingham <... some time later ...> \n\ 35309799af6SCaroline Tice (lldb) bfl my-file.c 137 \n\ 354ebc09c36SJim Ingham \nThis would be the same as if the user had entered \n\ 355ebc09c36SJim Ingham 'breakpoint set -f my-file.c -l 137'. \n\ 356ebc09c36SJim Ingham \nAnother example: \n\ 35709799af6SCaroline Tice \n (lldb) commands alias pltty process launch -s -o %1 -e %1 \n\ 35809799af6SCaroline Tice (lldb) pltty /dev/tty0 \n\ 359ebc09c36SJim Ingham // becomes 'process launch -s -o /dev/tty0 -e /dev/tty0' \n\ 360ebc09c36SJim Ingham \nIf the user always wanted to pass the same value to a particular option, the \n\ 361ebc09c36SJim Ingham alias could be defined with that value directly in the alias as a constant, \n\ 362ebc09c36SJim Ingham rather than using a positional placeholder: \n\ 3630708e2c2SSean Callanan \n commands alias bl3 breakpoint set -f %1 -l 3 // Always sets a breakpoint on line \n\ 364ebc09c36SJim Ingham // 3 of whatever file is indicated. \n"); 365ebc09c36SJim Ingham 366405fe67fSCaroline Tice CommandArgumentEntry arg1; 367405fe67fSCaroline Tice CommandArgumentEntry arg2; 368405fe67fSCaroline Tice CommandArgumentEntry arg3; 369405fe67fSCaroline Tice CommandArgumentData alias_arg; 370405fe67fSCaroline Tice CommandArgumentData cmd_arg; 371405fe67fSCaroline Tice CommandArgumentData options_arg; 372405fe67fSCaroline Tice 373405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 374405fe67fSCaroline Tice alias_arg.arg_type = eArgTypeAliasName; 375405fe67fSCaroline Tice alias_arg.arg_repetition = eArgRepeatPlain; 376405fe67fSCaroline Tice 377405fe67fSCaroline Tice // There is only one variant this argument could be; put it into the argument entry. 378405fe67fSCaroline Tice arg1.push_back (alias_arg); 379405fe67fSCaroline Tice 380405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 381405fe67fSCaroline Tice cmd_arg.arg_type = eArgTypeCommandName; 382405fe67fSCaroline Tice cmd_arg.arg_repetition = eArgRepeatPlain; 383405fe67fSCaroline Tice 384405fe67fSCaroline Tice // There is only one variant this argument could be; put it into the argument entry. 385405fe67fSCaroline Tice arg2.push_back (cmd_arg); 386405fe67fSCaroline Tice 387405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 388405fe67fSCaroline Tice options_arg.arg_type = eArgTypeAliasOptions; 389405fe67fSCaroline Tice options_arg.arg_repetition = eArgRepeatOptional; 390405fe67fSCaroline Tice 391405fe67fSCaroline Tice // There is only one variant this argument could be; put it into the argument entry. 392405fe67fSCaroline Tice arg3.push_back (options_arg); 393405fe67fSCaroline Tice 394405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 395405fe67fSCaroline Tice m_arguments.push_back (arg1); 396405fe67fSCaroline Tice m_arguments.push_back (arg2); 397405fe67fSCaroline Tice m_arguments.push_back (arg3); 398ebc09c36SJim Ingham } 399ebc09c36SJim Ingham 400ebc09c36SJim Ingham ~CommandObjectCommandsAlias () 401ebc09c36SJim Ingham { 402ebc09c36SJim Ingham } 403ebc09c36SJim Ingham 404844d2303SCaroline Tice bool 405844d2303SCaroline Tice WantsRawCommandString () 406844d2303SCaroline Tice { 407844d2303SCaroline Tice return true; 408844d2303SCaroline Tice } 409844d2303SCaroline Tice 410844d2303SCaroline Tice bool 411844d2303SCaroline Tice ExecuteRawCommandString (const char *raw_command_line, CommandReturnObject &result) 412844d2303SCaroline Tice { 413844d2303SCaroline Tice Args args (raw_command_line); 414844d2303SCaroline Tice std::string raw_command_string (raw_command_line); 415844d2303SCaroline Tice 416844d2303SCaroline Tice size_t argc = args.GetArgumentCount(); 417844d2303SCaroline Tice 418844d2303SCaroline Tice if (argc < 2) 419844d2303SCaroline Tice { 420844d2303SCaroline Tice result.AppendError ("'alias' requires at least two arguments"); 421844d2303SCaroline Tice result.SetStatus (eReturnStatusFailed); 422844d2303SCaroline Tice return false; 423844d2303SCaroline Tice } 424844d2303SCaroline Tice 425844d2303SCaroline Tice // Get the alias command. 426844d2303SCaroline Tice 427844d2303SCaroline Tice const std::string alias_command = args.GetArgumentAtIndex (0); 428844d2303SCaroline Tice 429844d2303SCaroline Tice // Strip the new alias name off 'raw_command_string' (leave it on args, which gets passed to 'Execute', which 430844d2303SCaroline Tice // does the stripping itself. 431844d2303SCaroline Tice size_t pos = raw_command_string.find (alias_command); 432844d2303SCaroline Tice if (pos == 0) 433844d2303SCaroline Tice { 434844d2303SCaroline Tice raw_command_string = raw_command_string.substr (alias_command.size()); 435844d2303SCaroline Tice pos = raw_command_string.find_first_not_of (' '); 436844d2303SCaroline Tice if ((pos != std::string::npos) && (pos > 0)) 437844d2303SCaroline Tice raw_command_string = raw_command_string.substr (pos); 438844d2303SCaroline Tice } 439844d2303SCaroline Tice else 440844d2303SCaroline Tice { 441844d2303SCaroline Tice result.AppendError ("Error parsing command string. No alias created."); 442844d2303SCaroline Tice result.SetStatus (eReturnStatusFailed); 443844d2303SCaroline Tice return false; 444844d2303SCaroline Tice } 445844d2303SCaroline Tice 446844d2303SCaroline Tice 447844d2303SCaroline Tice // Verify that the command is alias-able. 448844d2303SCaroline Tice if (m_interpreter.CommandExists (alias_command.c_str())) 449844d2303SCaroline Tice { 450844d2303SCaroline Tice result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n", 451844d2303SCaroline Tice alias_command.c_str()); 452844d2303SCaroline Tice result.SetStatus (eReturnStatusFailed); 453844d2303SCaroline Tice return false; 454844d2303SCaroline Tice } 455844d2303SCaroline Tice 456844d2303SCaroline Tice // Get CommandObject that is being aliased. The command name is read from the front of raw_command_string. 457844d2303SCaroline Tice // raw_command_string is returned with the name of the command object stripped off the front. 458844d2303SCaroline Tice CommandObject *cmd_obj = m_interpreter.GetCommandObjectForCommand (raw_command_string); 459844d2303SCaroline Tice 460844d2303SCaroline Tice if (!cmd_obj) 461844d2303SCaroline Tice { 462844d2303SCaroline Tice result.AppendErrorWithFormat ("Invalid command given to 'alias'. '%s' does not begin with a valid command." 463844d2303SCaroline Tice " No alias created.", raw_command_string.c_str()); 464844d2303SCaroline Tice result.SetStatus (eReturnStatusFailed); 465844d2303SCaroline Tice return false; 466844d2303SCaroline Tice } 467844d2303SCaroline Tice else if (!cmd_obj->WantsRawCommandString ()) 468844d2303SCaroline Tice { 469844d2303SCaroline Tice // Note that args was initialized with the original command, and has not been updated to this point. 470844d2303SCaroline Tice // Therefore can we pass it to the version of Execute that does not need/expect raw input in the alias. 471844d2303SCaroline Tice return Execute (args, result); 472844d2303SCaroline Tice } 473844d2303SCaroline Tice else 474844d2303SCaroline Tice { 475844d2303SCaroline Tice // Verify & handle any options/arguments passed to the alias command 476844d2303SCaroline Tice 477844d2303SCaroline Tice OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector); 478844d2303SCaroline Tice OptionArgVector *option_arg_vector = option_arg_vector_sp.get(); 479844d2303SCaroline Tice 480ca90c47eSCaroline Tice CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false); 481844d2303SCaroline Tice 482ca90c47eSCaroline Tice if (!m_interpreter.ProcessAliasOptionsArgs (cmd_obj_sp, raw_command_string.c_str(), option_arg_vector_sp)) 483844d2303SCaroline Tice { 484844d2303SCaroline Tice result.AppendError ("Unable to create requested alias.\n"); 485ca90c47eSCaroline Tice result.SetStatus (eReturnStatusFailed); 486844d2303SCaroline Tice return false; 487844d2303SCaroline Tice } 488844d2303SCaroline Tice 489844d2303SCaroline Tice // Create the alias 490844d2303SCaroline Tice if (m_interpreter.AliasExists (alias_command.c_str()) 491844d2303SCaroline Tice || m_interpreter.UserCommandExists (alias_command.c_str())) 492844d2303SCaroline Tice { 493844d2303SCaroline Tice OptionArgVectorSP temp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str())); 494844d2303SCaroline Tice if (temp_option_arg_sp.get()) 495844d2303SCaroline Tice { 496844d2303SCaroline Tice if (option_arg_vector->size() == 0) 497844d2303SCaroline Tice m_interpreter.RemoveAliasOptions (alias_command.c_str()); 498844d2303SCaroline Tice } 499844d2303SCaroline Tice result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n", 500844d2303SCaroline Tice alias_command.c_str()); 501844d2303SCaroline Tice } 502844d2303SCaroline Tice 503472362e6SCaroline Tice if (cmd_obj_sp) 504472362e6SCaroline Tice { 505844d2303SCaroline Tice m_interpreter.AddAlias (alias_command.c_str(), cmd_obj_sp); 506844d2303SCaroline Tice if (option_arg_vector->size() > 0) 507844d2303SCaroline Tice m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp); 508844d2303SCaroline Tice result.SetStatus (eReturnStatusSuccessFinishNoResult); 509844d2303SCaroline Tice } 510472362e6SCaroline Tice else 511472362e6SCaroline Tice { 512472362e6SCaroline Tice result.AppendError ("Unable to create requested alias.\n"); 513472362e6SCaroline Tice result.SetStatus (eReturnStatusFailed); 514472362e6SCaroline Tice } 515472362e6SCaroline Tice } 516844d2303SCaroline Tice return result.Succeeded(); 517844d2303SCaroline Tice } 518ebc09c36SJim Ingham 519ebc09c36SJim Ingham bool 520ebc09c36SJim Ingham Execute 521ebc09c36SJim Ingham ( 522ebc09c36SJim Ingham Args& args, 523ebc09c36SJim Ingham CommandReturnObject &result 524ebc09c36SJim Ingham ) 525ebc09c36SJim Ingham { 526867b185dSCaroline Tice size_t argc = args.GetArgumentCount(); 527ebc09c36SJim Ingham 528ebc09c36SJim Ingham if (argc < 2) 529ebc09c36SJim Ingham { 530ebc09c36SJim Ingham result.AppendError ("'alias' requires at least two arguments"); 531ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 532ebc09c36SJim Ingham return false; 533ebc09c36SJim Ingham } 534ebc09c36SJim Ingham 535ebc09c36SJim Ingham const std::string alias_command = args.GetArgumentAtIndex(0); 536ebc09c36SJim Ingham const std::string actual_command = args.GetArgumentAtIndex(1); 537ebc09c36SJim Ingham 538ebc09c36SJim Ingham args.Shift(); // Shift the alias command word off the argument vector. 539ebc09c36SJim Ingham args.Shift(); // Shift the old command word off the argument vector. 540ebc09c36SJim Ingham 541ebc09c36SJim Ingham // Verify that the command is alias'able, and get the appropriate command object. 542ebc09c36SJim Ingham 543a7015092SGreg Clayton if (m_interpreter.CommandExists (alias_command.c_str())) 544ebc09c36SJim Ingham { 545ebc09c36SJim Ingham result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n", 546ebc09c36SJim Ingham alias_command.c_str()); 547ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 548ebc09c36SJim Ingham } 549ebc09c36SJim Ingham else 550ebc09c36SJim Ingham { 551a7015092SGreg Clayton CommandObjectSP command_obj_sp(m_interpreter.GetCommandSPExact (actual_command.c_str(), true)); 552ebc09c36SJim Ingham CommandObjectSP subcommand_obj_sp; 553ebc09c36SJim Ingham bool use_subcommand = false; 554ebc09c36SJim Ingham if (command_obj_sp.get()) 555ebc09c36SJim Ingham { 556ebc09c36SJim Ingham CommandObject *cmd_obj = command_obj_sp.get(); 557c982c768SGreg Clayton CommandObject *sub_cmd_obj = NULL; 558ebc09c36SJim Ingham OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector); 559ebc09c36SJim Ingham OptionArgVector *option_arg_vector = option_arg_vector_sp.get(); 560ebc09c36SJim Ingham 561844d2303SCaroline Tice while (cmd_obj->IsMultiwordObject() && args.GetArgumentCount() > 0) 562ebc09c36SJim Ingham { 563ebc09c36SJim Ingham if (argc >= 3) 564ebc09c36SJim Ingham { 565ebc09c36SJim Ingham const std::string sub_command = args.GetArgumentAtIndex(0); 566ebc09c36SJim Ingham assert (sub_command.length() != 0); 567ebc09c36SJim Ingham subcommand_obj_sp = 568ebc09c36SJim Ingham (((CommandObjectMultiword *) cmd_obj)->GetSubcommandSP (sub_command.c_str())); 569ebc09c36SJim Ingham if (subcommand_obj_sp.get()) 570ebc09c36SJim Ingham { 571ebc09c36SJim Ingham sub_cmd_obj = subcommand_obj_sp.get(); 572ebc09c36SJim Ingham use_subcommand = true; 573ebc09c36SJim Ingham args.Shift(); // Shift the sub_command word off the argument vector. 574844d2303SCaroline Tice cmd_obj = sub_cmd_obj; 575ebc09c36SJim Ingham } 576ebc09c36SJim Ingham else 577ebc09c36SJim Ingham { 578f415eeb4SCaroline Tice result.AppendErrorWithFormat("'%s' is not a valid sub-command of '%s'. " 579f415eeb4SCaroline Tice "Unable to create alias.\n", 580f415eeb4SCaroline Tice sub_command.c_str(), actual_command.c_str()); 581ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 582ebc09c36SJim Ingham return false; 583ebc09c36SJim Ingham } 584ebc09c36SJim Ingham } 585ebc09c36SJim Ingham } 586ebc09c36SJim Ingham 587ebc09c36SJim Ingham // Verify & handle any options/arguments passed to the alias command 588ebc09c36SJim Ingham 589ebc09c36SJim Ingham if (args.GetArgumentCount () > 0) 590ebc09c36SJim Ingham { 591ca90c47eSCaroline Tice CommandObjectSP tmp_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false); 592ebc09c36SJim Ingham if (use_subcommand) 593ca90c47eSCaroline Tice tmp_sp = m_interpreter.GetCommandSPExact (sub_cmd_obj->GetCommandName(), false); 594ca90c47eSCaroline Tice 595ca90c47eSCaroline Tice std::string args_string; 596ca90c47eSCaroline Tice args.GetCommandString (args_string); 597ca90c47eSCaroline Tice 598ca90c47eSCaroline Tice if (!m_interpreter.ProcessAliasOptionsArgs (tmp_sp, args_string.c_str(), option_arg_vector_sp)) 599ebc09c36SJim Ingham { 600ca90c47eSCaroline Tice result.AppendError ("Unable to create requested alias.\n"); 601ca90c47eSCaroline Tice result.SetStatus (eReturnStatusFailed); 602e7941795SCaroline Tice return false; 603867b185dSCaroline Tice } 604867b185dSCaroline Tice } 605867b185dSCaroline Tice 606ebc09c36SJim Ingham // Create the alias. 607ebc09c36SJim Ingham 608a7015092SGreg Clayton if (m_interpreter.AliasExists (alias_command.c_str()) 609a7015092SGreg Clayton || m_interpreter.UserCommandExists (alias_command.c_str())) 610ebc09c36SJim Ingham { 611a7015092SGreg Clayton OptionArgVectorSP tmp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str())); 612ebc09c36SJim Ingham if (tmp_option_arg_sp.get()) 613ebc09c36SJim Ingham { 614ebc09c36SJim Ingham if (option_arg_vector->size() == 0) 615a7015092SGreg Clayton m_interpreter.RemoveAliasOptions (alias_command.c_str()); 616ebc09c36SJim Ingham } 617ebc09c36SJim Ingham result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n", 618ebc09c36SJim Ingham alias_command.c_str()); 619ebc09c36SJim Ingham } 620ebc09c36SJim Ingham 621ebc09c36SJim Ingham if (use_subcommand) 622a7015092SGreg Clayton m_interpreter.AddAlias (alias_command.c_str(), subcommand_obj_sp); 623ebc09c36SJim Ingham else 624a7015092SGreg Clayton m_interpreter.AddAlias (alias_command.c_str(), command_obj_sp); 625ebc09c36SJim Ingham if (option_arg_vector->size() > 0) 626a7015092SGreg Clayton m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp); 627ebc09c36SJim Ingham result.SetStatus (eReturnStatusSuccessFinishNoResult); 628ebc09c36SJim Ingham } 629ebc09c36SJim Ingham else 630ebc09c36SJim Ingham { 631ebc09c36SJim Ingham result.AppendErrorWithFormat ("'%s' is not an existing command.\n", actual_command.c_str()); 632ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 633e7941795SCaroline Tice return false; 634ebc09c36SJim Ingham } 635ebc09c36SJim Ingham } 636ebc09c36SJim Ingham 637ebc09c36SJim Ingham return result.Succeeded(); 638ebc09c36SJim Ingham } 639ebc09c36SJim Ingham }; 640ebc09c36SJim Ingham 641ebc09c36SJim Ingham #pragma mark CommandObjectCommandsUnalias 642ebc09c36SJim Ingham //------------------------------------------------------------------------- 643ebc09c36SJim Ingham // CommandObjectCommandsUnalias 644ebc09c36SJim Ingham //------------------------------------------------------------------------- 645ebc09c36SJim Ingham 646ebc09c36SJim Ingham class CommandObjectCommandsUnalias : public CommandObject 647ebc09c36SJim Ingham { 648ebc09c36SJim Ingham public: 649a7015092SGreg Clayton CommandObjectCommandsUnalias (CommandInterpreter &interpreter) : 650a7015092SGreg Clayton CommandObject (interpreter, 6510e5e5a79SGreg Clayton "command unalias", 65286ddae50SCaroline Tice "Allow the user to remove/delete a user-defined command abbreviation.", 653405fe67fSCaroline Tice NULL) 654ebc09c36SJim Ingham { 655405fe67fSCaroline Tice CommandArgumentEntry arg; 656405fe67fSCaroline Tice CommandArgumentData alias_arg; 657405fe67fSCaroline Tice 658405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 659405fe67fSCaroline Tice alias_arg.arg_type = eArgTypeAliasName; 660405fe67fSCaroline Tice alias_arg.arg_repetition = eArgRepeatPlain; 661405fe67fSCaroline Tice 662405fe67fSCaroline Tice // There is only one variant this argument could be; put it into the argument entry. 663405fe67fSCaroline Tice arg.push_back (alias_arg); 664405fe67fSCaroline Tice 665405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 666405fe67fSCaroline Tice m_arguments.push_back (arg); 667ebc09c36SJim Ingham } 668ebc09c36SJim Ingham 669ebc09c36SJim Ingham ~CommandObjectCommandsUnalias() 670ebc09c36SJim Ingham { 671ebc09c36SJim Ingham } 672ebc09c36SJim Ingham 673ebc09c36SJim Ingham 674ebc09c36SJim Ingham bool 675ebc09c36SJim Ingham Execute 676ebc09c36SJim Ingham ( 677ebc09c36SJim Ingham Args& args, 678ebc09c36SJim Ingham CommandReturnObject &result 679ebc09c36SJim Ingham ) 680ebc09c36SJim Ingham { 681ebc09c36SJim Ingham CommandObject::CommandMap::iterator pos; 682ebc09c36SJim Ingham CommandObject *cmd_obj; 683ebc09c36SJim Ingham 684ebc09c36SJim Ingham if (args.GetArgumentCount() != 0) 685ebc09c36SJim Ingham { 686ebc09c36SJim Ingham const char *command_name = args.GetArgumentAtIndex(0); 687a7015092SGreg Clayton cmd_obj = m_interpreter.GetCommandObject(command_name); 688ebc09c36SJim Ingham if (cmd_obj) 689ebc09c36SJim Ingham { 690a7015092SGreg Clayton if (m_interpreter.CommandExists (command_name)) 691ebc09c36SJim Ingham { 692ebc09c36SJim Ingham result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n", 693ebc09c36SJim Ingham command_name); 694ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 695ebc09c36SJim Ingham } 696ebc09c36SJim Ingham else 697ebc09c36SJim Ingham { 698ebc09c36SJim Ingham 699a7015092SGreg Clayton if (m_interpreter.RemoveAlias (command_name) == false) 700ebc09c36SJim Ingham { 701a7015092SGreg Clayton if (m_interpreter.AliasExists (command_name)) 702ebc09c36SJim Ingham result.AppendErrorWithFormat ("Error occurred while attempting to unalias '%s'.\n", 703ebc09c36SJim Ingham command_name); 704ebc09c36SJim Ingham else 705ebc09c36SJim Ingham result.AppendErrorWithFormat ("'%s' is not an existing alias.\n", command_name); 706ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 707ebc09c36SJim Ingham } 708ebc09c36SJim Ingham else 709ebc09c36SJim Ingham result.SetStatus (eReturnStatusSuccessFinishNoResult); 710ebc09c36SJim Ingham } 711ebc09c36SJim Ingham } 712ebc09c36SJim Ingham else 713ebc09c36SJim Ingham { 714ebc09c36SJim Ingham result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a " 715ebc09c36SJim Ingham "current list of commands.\n", 716ebc09c36SJim Ingham command_name); 717ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 718ebc09c36SJim Ingham } 719ebc09c36SJim Ingham } 720ebc09c36SJim Ingham else 721ebc09c36SJim Ingham { 722ebc09c36SJim Ingham result.AppendError ("must call 'unalias' with a valid alias"); 723ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 724ebc09c36SJim Ingham } 725ebc09c36SJim Ingham 726ebc09c36SJim Ingham return result.Succeeded(); 727ebc09c36SJim Ingham } 728ebc09c36SJim Ingham }; 729ebc09c36SJim Ingham 730de164aaaSGreg Clayton #pragma mark CommandObjectCommandsAddRegex 731de164aaaSGreg Clayton //------------------------------------------------------------------------- 732de164aaaSGreg Clayton // CommandObjectCommandsAddRegex 733de164aaaSGreg Clayton //------------------------------------------------------------------------- 734de164aaaSGreg Clayton 735de164aaaSGreg Clayton class CommandObjectCommandsAddRegex : public CommandObject 736de164aaaSGreg Clayton { 737de164aaaSGreg Clayton public: 738de164aaaSGreg Clayton CommandObjectCommandsAddRegex (CommandInterpreter &interpreter) : 739de164aaaSGreg Clayton CommandObject (interpreter, 7400e5e5a79SGreg Clayton "command regex", 741de164aaaSGreg Clayton "Allow the user to create a regular expression command.", 7420e5e5a79SGreg Clayton "command regex <cmd-name> [s/<regex>/<subst>/ ...]"), 743de164aaaSGreg Clayton m_options (interpreter) 744de164aaaSGreg Clayton { 7450e5e5a79SGreg Clayton SetHelpLong( 7460e5e5a79SGreg Clayton "This command allows the user to create powerful regular expression commands\n" 7470e5e5a79SGreg Clayton "with substitutions. The regular expressions and substitutions are specified\n" 7480e5e5a79SGreg Clayton "using the regular exression substitution format of:\n" 7490e5e5a79SGreg Clayton "\n" 7500e5e5a79SGreg Clayton " s/<regex>/<subst>/\n" 7510e5e5a79SGreg Clayton "\n" 7520e5e5a79SGreg Clayton "<regex> is a regular expression that can use parenthesis to capture regular\n" 7530e5e5a79SGreg Clayton "expression input and substitute the captured matches in the output using %1\n" 7540e5e5a79SGreg Clayton "for the first match, %2 for the second, and so on.\n" 7550e5e5a79SGreg Clayton "\n" 7560e5e5a79SGreg Clayton "The regular expressions can all be specified on the command line if more than\n" 7570e5e5a79SGreg Clayton "one argument is provided. If just the command name is provided on the command\n" 7580e5e5a79SGreg Clayton "line, then the regular expressions and substitutions can be entered on separate\n" 7590e5e5a79SGreg Clayton " lines, followed by an empty line to terminate the command definition.\n" 7600e5e5a79SGreg Clayton "\n" 7610e5e5a79SGreg Clayton "EXAMPLES\n" 7620e5e5a79SGreg Clayton "\n" 7630e5e5a79SGreg Clayton "The following example with define a regular expression command named 'f' that\n" 7640e5e5a79SGreg Clayton "will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if\n" 7650e5e5a79SGreg Clayton "a number follows 'f':\n" 7660e5e5a79SGreg Clayton "(lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/'\n" 7670e5e5a79SGreg Clayton ); 768de164aaaSGreg Clayton } 769de164aaaSGreg Clayton 770de164aaaSGreg Clayton ~CommandObjectCommandsAddRegex() 771de164aaaSGreg Clayton { 772de164aaaSGreg Clayton } 773de164aaaSGreg Clayton 774de164aaaSGreg Clayton 775de164aaaSGreg Clayton bool 776de164aaaSGreg Clayton Execute (Args& args, CommandReturnObject &result) 777de164aaaSGreg Clayton { 7780e5e5a79SGreg Clayton const size_t argc = args.GetArgumentCount(); 7790e5e5a79SGreg Clayton if (argc == 0) 780de164aaaSGreg Clayton { 7810e5e5a79SGreg Clayton result.AppendError ("usage: 'commands regex <command-name> [s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n"); 7820e5e5a79SGreg Clayton result.SetStatus (eReturnStatusFailed); 7830e5e5a79SGreg Clayton } 7840e5e5a79SGreg Clayton else 7850e5e5a79SGreg Clayton { 7860e5e5a79SGreg Clayton Error error; 787de164aaaSGreg Clayton const char *name = args.GetArgumentAtIndex(0); 788de164aaaSGreg Clayton m_regex_cmd_ap.reset (new CommandObjectRegexCommand (m_interpreter, 789de164aaaSGreg Clayton name, 790de164aaaSGreg Clayton m_options.GetHelp (), 791de164aaaSGreg Clayton m_options.GetSyntax (), 792de164aaaSGreg Clayton 10)); 7930e5e5a79SGreg Clayton 7940e5e5a79SGreg Clayton if (argc == 1) 7950e5e5a79SGreg Clayton { 7960e5e5a79SGreg Clayton InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger())); 797de164aaaSGreg Clayton if (reader_sp) 798de164aaaSGreg Clayton { 7990e5e5a79SGreg Clayton error =reader_sp->Initialize (CommandObjectCommandsAddRegex::InputReaderCallback, 800de164aaaSGreg Clayton this, // baton 801de164aaaSGreg Clayton eInputReaderGranularityLine, // token size, to pass to callback function 8020e5e5a79SGreg Clayton NULL, // end token 803de164aaaSGreg Clayton "> ", // prompt 8040e5e5a79SGreg Clayton true); // echo input 8050e5e5a79SGreg Clayton if (error.Success()) 806de164aaaSGreg Clayton { 807de164aaaSGreg Clayton m_interpreter.GetDebugger().PushInputReader (reader_sp); 808de164aaaSGreg Clayton result.SetStatus (eReturnStatusSuccessFinishNoResult); 8090e5e5a79SGreg Clayton return true; 810de164aaaSGreg Clayton } 811de164aaaSGreg Clayton } 812de164aaaSGreg Clayton } 813de164aaaSGreg Clayton else 814de164aaaSGreg Clayton { 8150e5e5a79SGreg Clayton for (size_t arg_idx = 1; arg_idx < argc; ++arg_idx) 8160e5e5a79SGreg Clayton { 8170e5e5a79SGreg Clayton llvm::StringRef arg_strref (args.GetArgumentAtIndex(arg_idx)); 8180e5e5a79SGreg Clayton error = AppendRegexSubstitution (arg_strref); 8190e5e5a79SGreg Clayton if (error.Fail()) 8200e5e5a79SGreg Clayton break; 8210e5e5a79SGreg Clayton } 8220e5e5a79SGreg Clayton 8230e5e5a79SGreg Clayton if (error.Success()) 8240e5e5a79SGreg Clayton { 8250e5e5a79SGreg Clayton AddRegexCommandToInterpreter(); 8260e5e5a79SGreg Clayton } 8270e5e5a79SGreg Clayton } 8280e5e5a79SGreg Clayton if (error.Fail()) 8290e5e5a79SGreg Clayton { 8300e5e5a79SGreg Clayton result.AppendError (error.AsCString()); 831de164aaaSGreg Clayton result.SetStatus (eReturnStatusFailed); 832de164aaaSGreg Clayton } 8330e5e5a79SGreg Clayton } 8340e5e5a79SGreg Clayton 835de164aaaSGreg Clayton return result.Succeeded(); 836de164aaaSGreg Clayton } 837de164aaaSGreg Clayton 8380e5e5a79SGreg Clayton Error 8390e5e5a79SGreg Clayton AppendRegexSubstitution (const llvm::StringRef ®ex_sed) 840de164aaaSGreg Clayton { 8410e5e5a79SGreg Clayton Error error; 8420e5e5a79SGreg Clayton 8430e5e5a79SGreg Clayton if (m_regex_cmd_ap.get() == NULL) 844de164aaaSGreg Clayton { 8450e5e5a79SGreg Clayton error.SetErrorStringWithFormat("invalid regular expression command object for: '%.*s'", 8460e5e5a79SGreg Clayton (int)regex_sed.size(), 8470e5e5a79SGreg Clayton regex_sed.data()); 8480e5e5a79SGreg Clayton return error; 849de164aaaSGreg Clayton } 8500e5e5a79SGreg Clayton 8510e5e5a79SGreg Clayton size_t regex_sed_size = regex_sed.size(); 8520e5e5a79SGreg Clayton 8530e5e5a79SGreg Clayton if (regex_sed_size <= 1) 8540e5e5a79SGreg Clayton { 8550e5e5a79SGreg Clayton error.SetErrorStringWithFormat("regular expression substitution string is too short: '%.*s'", 8560e5e5a79SGreg Clayton (int)regex_sed.size(), 8570e5e5a79SGreg Clayton regex_sed.data()); 8580e5e5a79SGreg Clayton return error; 8590e5e5a79SGreg Clayton } 8600e5e5a79SGreg Clayton 8610e5e5a79SGreg Clayton if (regex_sed[0] != 's') 8620e5e5a79SGreg Clayton { 8630e5e5a79SGreg Clayton error.SetErrorStringWithFormat("regular expression substitution string doesn't start with 's': '%.*s'", 8640e5e5a79SGreg Clayton (int)regex_sed.size(), 8650e5e5a79SGreg Clayton regex_sed.data()); 8660e5e5a79SGreg Clayton return error; 8670e5e5a79SGreg Clayton } 8680e5e5a79SGreg Clayton const size_t first_separator_char_pos = 1; 8690e5e5a79SGreg Clayton // use the char that follows 's' as the regex separator character 8700e5e5a79SGreg Clayton // so we can have "s/<regex>/<subst>/" or "s|<regex>|<subst>|" 8710e5e5a79SGreg Clayton const char separator_char = regex_sed[first_separator_char_pos]; 8720e5e5a79SGreg Clayton const size_t second_separator_char_pos = regex_sed.find (separator_char, first_separator_char_pos + 1); 8730e5e5a79SGreg Clayton 8740e5e5a79SGreg Clayton if (second_separator_char_pos == std::string::npos) 8750e5e5a79SGreg Clayton { 8760e5e5a79SGreg Clayton error.SetErrorStringWithFormat("missing second '%c' separator char after '%.*s'", 8770e5e5a79SGreg Clayton separator_char, 8780e5e5a79SGreg Clayton (int)(regex_sed.size() - first_separator_char_pos - 1), 8790e5e5a79SGreg Clayton regex_sed.data() + (first_separator_char_pos + 1)); 8800e5e5a79SGreg Clayton return error; 8810e5e5a79SGreg Clayton } 8820e5e5a79SGreg Clayton 8830e5e5a79SGreg Clayton const size_t third_separator_char_pos = regex_sed.find (separator_char, second_separator_char_pos + 1); 8840e5e5a79SGreg Clayton 8850e5e5a79SGreg Clayton if (third_separator_char_pos == std::string::npos) 8860e5e5a79SGreg Clayton { 8870e5e5a79SGreg Clayton error.SetErrorStringWithFormat("missing third '%c' separator char after '%.*s'", 8880e5e5a79SGreg Clayton separator_char, 8890e5e5a79SGreg Clayton (int)(regex_sed.size() - second_separator_char_pos - 1), 8900e5e5a79SGreg Clayton regex_sed.data() + (second_separator_char_pos + 1)); 8910e5e5a79SGreg Clayton return error; 8920e5e5a79SGreg Clayton } 8930e5e5a79SGreg Clayton 8940e5e5a79SGreg Clayton if (third_separator_char_pos != regex_sed_size - 1) 8950e5e5a79SGreg Clayton { 8960e5e5a79SGreg Clayton // Make sure that everything that follows the last regex 8970e5e5a79SGreg Clayton // separator char 8980e5e5a79SGreg Clayton if (regex_sed.find_first_not_of("\t\n\v\f\r ", third_separator_char_pos + 1) != std::string::npos) 8990e5e5a79SGreg Clayton { 9000e5e5a79SGreg Clayton error.SetErrorStringWithFormat("extra data found after the '%.*s' regular expression substitution string: '%.*s'", 9010e5e5a79SGreg Clayton (int)third_separator_char_pos + 1, 9020e5e5a79SGreg Clayton regex_sed.data(), 9030e5e5a79SGreg Clayton (int)(regex_sed.size() - third_separator_char_pos - 1), 9040e5e5a79SGreg Clayton regex_sed.data() + (third_separator_char_pos + 1)); 9050e5e5a79SGreg Clayton return error; 9060e5e5a79SGreg Clayton } 9070e5e5a79SGreg Clayton 9080e5e5a79SGreg Clayton } 9090e5e5a79SGreg Clayton else if (first_separator_char_pos + 1 == second_separator_char_pos) 9100e5e5a79SGreg Clayton { 9110e5e5a79SGreg Clayton error.SetErrorStringWithFormat("<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'", 9120e5e5a79SGreg Clayton separator_char, 9130e5e5a79SGreg Clayton separator_char, 9140e5e5a79SGreg Clayton separator_char, 9150e5e5a79SGreg Clayton (int)regex_sed.size(), 9160e5e5a79SGreg Clayton regex_sed.data()); 9170e5e5a79SGreg Clayton return error; 9180e5e5a79SGreg Clayton } 9190e5e5a79SGreg Clayton else if (second_separator_char_pos + 1 == third_separator_char_pos) 9200e5e5a79SGreg Clayton { 9210e5e5a79SGreg Clayton error.SetErrorStringWithFormat("<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'", 9220e5e5a79SGreg Clayton separator_char, 9230e5e5a79SGreg Clayton separator_char, 9240e5e5a79SGreg Clayton separator_char, 9250e5e5a79SGreg Clayton (int)regex_sed.size(), 9260e5e5a79SGreg Clayton regex_sed.data()); 9270e5e5a79SGreg Clayton return error; 9280e5e5a79SGreg Clayton } 9290e5e5a79SGreg Clayton std::string regex(regex_sed.substr(first_separator_char_pos + 1, second_separator_char_pos - first_separator_char_pos - 1)); 9300e5e5a79SGreg Clayton std::string subst(regex_sed.substr(second_separator_char_pos + 1, third_separator_char_pos - second_separator_char_pos - 1)); 9310e5e5a79SGreg Clayton m_regex_cmd_ap->AddRegexCommand (regex.c_str(), 9320e5e5a79SGreg Clayton subst.c_str()); 9330e5e5a79SGreg Clayton return error; 934de164aaaSGreg Clayton } 935de164aaaSGreg Clayton 936de164aaaSGreg Clayton void 9370e5e5a79SGreg Clayton AddRegexCommandToInterpreter() 938de164aaaSGreg Clayton { 939de164aaaSGreg Clayton if (m_regex_cmd_ap.get()) 940de164aaaSGreg Clayton { 941de164aaaSGreg Clayton if (m_regex_cmd_ap->HasRegexEntries()) 942de164aaaSGreg Clayton { 943de164aaaSGreg Clayton CommandObjectSP cmd_sp (m_regex_cmd_ap.release()); 944de164aaaSGreg Clayton m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true); 945de164aaaSGreg Clayton } 946de164aaaSGreg Clayton } 947de164aaaSGreg Clayton } 948de164aaaSGreg Clayton 9490e5e5a79SGreg Clayton void 9500e5e5a79SGreg Clayton InputReaderDidCancel() 9510e5e5a79SGreg Clayton { 9520e5e5a79SGreg Clayton m_regex_cmd_ap.reset(); 9530e5e5a79SGreg Clayton } 9540e5e5a79SGreg Clayton 955de164aaaSGreg Clayton static size_t 956de164aaaSGreg Clayton InputReaderCallback (void *baton, 957de164aaaSGreg Clayton InputReader &reader, 958de164aaaSGreg Clayton lldb::InputReaderAction notification, 959de164aaaSGreg Clayton const char *bytes, 960de164aaaSGreg Clayton size_t bytes_len); 961de164aaaSGreg Clayton private: 962de164aaaSGreg Clayton std::auto_ptr<CommandObjectRegexCommand> m_regex_cmd_ap; 963de164aaaSGreg Clayton 964de164aaaSGreg Clayton class CommandOptions : public Options 965de164aaaSGreg Clayton { 966de164aaaSGreg Clayton public: 967de164aaaSGreg Clayton 968de164aaaSGreg Clayton CommandOptions (CommandInterpreter &interpreter) : 969de164aaaSGreg Clayton Options (interpreter) 970de164aaaSGreg Clayton { 971de164aaaSGreg Clayton } 972de164aaaSGreg Clayton 973de164aaaSGreg Clayton virtual 974de164aaaSGreg Clayton ~CommandOptions (){} 975de164aaaSGreg Clayton 976de164aaaSGreg Clayton virtual Error 977de164aaaSGreg Clayton SetOptionValue (uint32_t option_idx, const char *option_arg) 978de164aaaSGreg Clayton { 979de164aaaSGreg Clayton Error error; 980de164aaaSGreg Clayton char short_option = (char) m_getopt_table[option_idx].val; 981de164aaaSGreg Clayton 982de164aaaSGreg Clayton switch (short_option) 983de164aaaSGreg Clayton { 984de164aaaSGreg Clayton case 'h': 985de164aaaSGreg Clayton m_help.assign (option_arg); 986de164aaaSGreg Clayton break; 987de164aaaSGreg Clayton case 's': 988de164aaaSGreg Clayton m_syntax.assign (option_arg); 989de164aaaSGreg Clayton break; 990de164aaaSGreg Clayton 991de164aaaSGreg Clayton default: 992de164aaaSGreg Clayton error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); 993de164aaaSGreg Clayton break; 994de164aaaSGreg Clayton } 995de164aaaSGreg Clayton 996de164aaaSGreg Clayton return error; 997de164aaaSGreg Clayton } 998de164aaaSGreg Clayton 999de164aaaSGreg Clayton void 1000de164aaaSGreg Clayton OptionParsingStarting () 1001de164aaaSGreg Clayton { 1002de164aaaSGreg Clayton m_help.clear(); 1003de164aaaSGreg Clayton m_syntax.clear(); 1004de164aaaSGreg Clayton } 1005de164aaaSGreg Clayton 1006de164aaaSGreg Clayton const OptionDefinition* 1007de164aaaSGreg Clayton GetDefinitions () 1008de164aaaSGreg Clayton { 1009de164aaaSGreg Clayton return g_option_table; 1010de164aaaSGreg Clayton } 1011de164aaaSGreg Clayton 1012de164aaaSGreg Clayton // Options table: Required for subclasses of Options. 1013de164aaaSGreg Clayton 1014de164aaaSGreg Clayton static OptionDefinition g_option_table[]; 1015de164aaaSGreg Clayton 1016de164aaaSGreg Clayton const char * 1017de164aaaSGreg Clayton GetHelp () 1018de164aaaSGreg Clayton { 1019de164aaaSGreg Clayton if (m_help.empty()) 1020de164aaaSGreg Clayton return NULL; 1021de164aaaSGreg Clayton return m_help.c_str(); 1022de164aaaSGreg Clayton } 1023de164aaaSGreg Clayton const char * 1024de164aaaSGreg Clayton GetSyntax () 1025de164aaaSGreg Clayton { 1026de164aaaSGreg Clayton if (m_syntax.empty()) 1027de164aaaSGreg Clayton return NULL; 1028de164aaaSGreg Clayton return m_syntax.c_str(); 1029de164aaaSGreg Clayton } 1030de164aaaSGreg Clayton // Instance variables to hold the values for command options. 1031de164aaaSGreg Clayton protected: 1032de164aaaSGreg Clayton std::string m_help; 1033de164aaaSGreg Clayton std::string m_syntax; 1034de164aaaSGreg Clayton }; 1035de164aaaSGreg Clayton 1036de164aaaSGreg Clayton CommandOptions m_options; 1037de164aaaSGreg Clayton 1038de164aaaSGreg Clayton virtual Options * 1039de164aaaSGreg Clayton GetOptions () 1040de164aaaSGreg Clayton { 1041de164aaaSGreg Clayton return &m_options; 1042de164aaaSGreg Clayton } 1043de164aaaSGreg Clayton 1044de164aaaSGreg Clayton }; 1045de164aaaSGreg Clayton 1046de164aaaSGreg Clayton size_t 1047de164aaaSGreg Clayton CommandObjectCommandsAddRegex::InputReaderCallback (void *baton, 1048de164aaaSGreg Clayton InputReader &reader, 1049de164aaaSGreg Clayton lldb::InputReaderAction notification, 1050de164aaaSGreg Clayton const char *bytes, 1051de164aaaSGreg Clayton size_t bytes_len) 1052de164aaaSGreg Clayton { 1053de164aaaSGreg Clayton CommandObjectCommandsAddRegex *add_regex_cmd = (CommandObjectCommandsAddRegex *) baton; 1054d61c10bcSCaroline Tice bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); 1055de164aaaSGreg Clayton 1056de164aaaSGreg Clayton switch (notification) 1057de164aaaSGreg Clayton { 1058de164aaaSGreg Clayton case eInputReaderActivate: 1059d61c10bcSCaroline Tice if (!batch_mode) 106015356e7fSCaroline Tice { 106115356e7fSCaroline Tice StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream (); 106215356e7fSCaroline Tice out_stream->Printf("%s\n", "Enter regular expressions in the form 's/<regex>/<subst>/' and terminate with an empty line:"); 106315356e7fSCaroline Tice out_stream->Flush(); 106415356e7fSCaroline Tice } 1065de164aaaSGreg Clayton break; 1066de164aaaSGreg Clayton case eInputReaderReactivate: 1067de164aaaSGreg Clayton break; 1068de164aaaSGreg Clayton 1069de164aaaSGreg Clayton case eInputReaderDeactivate: 1070de164aaaSGreg Clayton break; 1071de164aaaSGreg Clayton 1072969ed3d1SCaroline Tice case eInputReaderAsynchronousOutputWritten: 1073969ed3d1SCaroline Tice break; 1074969ed3d1SCaroline Tice 1075de164aaaSGreg Clayton case eInputReaderGotToken: 10760e5e5a79SGreg Clayton while (bytes_len > 0 && (bytes[bytes_len-1] == '\r' || bytes[bytes_len-1] == '\n')) 10770e5e5a79SGreg Clayton --bytes_len; 1078de164aaaSGreg Clayton if (bytes_len == 0) 1079de164aaaSGreg Clayton reader.SetIsDone(true); 1080de164aaaSGreg Clayton else if (bytes) 1081de164aaaSGreg Clayton { 10820e5e5a79SGreg Clayton llvm::StringRef bytes_strref (bytes, bytes_len); 10830e5e5a79SGreg Clayton Error error (add_regex_cmd->AppendRegexSubstitution (bytes_strref)); 10840e5e5a79SGreg Clayton if (error.Fail()) 1085de164aaaSGreg Clayton { 1086d61c10bcSCaroline Tice if (!batch_mode) 1087d61c10bcSCaroline Tice { 108815356e7fSCaroline Tice StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream(); 108915356e7fSCaroline Tice out_stream->Printf("error: %s\n", error.AsCString()); 109015356e7fSCaroline Tice out_stream->Flush(); 1091d61c10bcSCaroline Tice } 10920e5e5a79SGreg Clayton add_regex_cmd->InputReaderDidCancel (); 10930e5e5a79SGreg Clayton reader.SetIsDone (true); 1094de164aaaSGreg Clayton } 1095de164aaaSGreg Clayton } 1096de164aaaSGreg Clayton break; 1097de164aaaSGreg Clayton 1098de164aaaSGreg Clayton case eInputReaderInterrupt: 109915356e7fSCaroline Tice { 1100de164aaaSGreg Clayton reader.SetIsDone (true); 1101d61c10bcSCaroline Tice if (!batch_mode) 1102d61c10bcSCaroline Tice { 110315356e7fSCaroline Tice StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream(); 110415356e7fSCaroline Tice out_stream->PutCString("Regular expression command creations was cancelled.\n"); 110515356e7fSCaroline Tice out_stream->Flush(); 1106d61c10bcSCaroline Tice } 11070e5e5a79SGreg Clayton add_regex_cmd->InputReaderDidCancel (); 110815356e7fSCaroline Tice } 1109de164aaaSGreg Clayton break; 1110de164aaaSGreg Clayton 1111de164aaaSGreg Clayton case eInputReaderEndOfFile: 1112de164aaaSGreg Clayton reader.SetIsDone (true); 1113de164aaaSGreg Clayton break; 1114de164aaaSGreg Clayton 1115de164aaaSGreg Clayton case eInputReaderDone: 11160e5e5a79SGreg Clayton add_regex_cmd->AddRegexCommandToInterpreter(); 1117de164aaaSGreg Clayton break; 1118de164aaaSGreg Clayton } 1119de164aaaSGreg Clayton 1120de164aaaSGreg Clayton return bytes_len; 1121de164aaaSGreg Clayton } 1122de164aaaSGreg Clayton 1123de164aaaSGreg Clayton 1124de164aaaSGreg Clayton OptionDefinition 1125de164aaaSGreg Clayton CommandObjectCommandsAddRegex::CommandOptions::g_option_table[] = 1126de164aaaSGreg Clayton { 1127de164aaaSGreg Clayton { LLDB_OPT_SET_1, false, "help" , 'h', required_argument, NULL, 0, eArgTypeNone, "The help text to display for this command."}, 1128de164aaaSGreg Clayton { LLDB_OPT_SET_1, false, "syntax", 's', required_argument, NULL, 0, eArgTypeNone, "A syntax string showing the typical usage syntax."}, 1129de164aaaSGreg Clayton { 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone, NULL } 1130de164aaaSGreg Clayton }; 1131de164aaaSGreg Clayton 1132de164aaaSGreg Clayton 1133ebc09c36SJim Ingham #pragma mark CommandObjectMultiwordCommands 1134ebc09c36SJim Ingham 1135ebc09c36SJim Ingham //------------------------------------------------------------------------- 1136ebc09c36SJim Ingham // CommandObjectMultiwordCommands 1137ebc09c36SJim Ingham //------------------------------------------------------------------------- 1138ebc09c36SJim Ingham 1139ebc09c36SJim Ingham CommandObjectMultiwordCommands::CommandObjectMultiwordCommands (CommandInterpreter &interpreter) : 1140a7015092SGreg Clayton CommandObjectMultiword (interpreter, 11410e5e5a79SGreg Clayton "command", 11423f4c09c1SCaroline Tice "A set of commands for managing or customizing the debugger commands.", 11430e5e5a79SGreg Clayton "command <subcommand> [<subcommand-options>]") 1144ebc09c36SJim Ingham { 1145a7015092SGreg Clayton LoadSubCommand ("source", CommandObjectSP (new CommandObjectCommandsSource (interpreter))); 1146a7015092SGreg Clayton LoadSubCommand ("alias", CommandObjectSP (new CommandObjectCommandsAlias (interpreter))); 1147a7015092SGreg Clayton LoadSubCommand ("unalias", CommandObjectSP (new CommandObjectCommandsUnalias (interpreter))); 1148de164aaaSGreg Clayton LoadSubCommand ("regex", CommandObjectSP (new CommandObjectCommandsAddRegex (interpreter))); 1149*a5a97ebeSJim Ingham LoadSubCommand ("history", CommandObjectSP (new CommandObjectCommandsHistory (interpreter))); 1150ebc09c36SJim Ingham } 1151ebc09c36SJim Ingham 1152ebc09c36SJim Ingham CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands () 1153ebc09c36SJim Ingham { 1154ebc09c36SJim Ingham } 1155ebc09c36SJim Ingham 1156