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 // C Includes 11ebc09c36SJim Ingham // C++ Includes 12ebc09c36SJim Ingham // Other libraries and framework includes 130e5e5a79SGreg Clayton #include "llvm/ADT/StringRef.h" 140e5e5a79SGreg Clayton 15ebc09c36SJim Ingham // Project includes 166e3d8e7fSEugene Zelenko #include "CommandObjectCommands.h" 1746d4aa21SEnrico Granata #include "CommandObjectHelp.h" 18ebc09c36SJim Ingham #include "lldb/Core/Debugger.h" 1944d93782SGreg Clayton #include "lldb/Core/IOHandler.h" 20be93a35aSEnrico Granata #include "lldb/Core/StringList.h" 21de164aaaSGreg Clayton #include "lldb/Interpreter/Args.h" 227594f14fSEnrico Granata #include "lldb/Interpreter/CommandHistory.h" 23ebc09c36SJim Ingham #include "lldb/Interpreter/CommandInterpreter.h" 24de164aaaSGreg Clayton #include "lldb/Interpreter/CommandObjectRegexCommand.h" 25ebc09c36SJim Ingham #include "lldb/Interpreter/CommandReturnObject.h" 26012d4fcaSEnrico Granata #include "lldb/Interpreter/OptionValueBoolean.h" 2745d0e238SEnrico Granata #include "lldb/Interpreter/OptionValueString.h" 287594f14fSEnrico Granata #include "lldb/Interpreter/OptionValueUInt64.h" 29ebc09c36SJim Ingham #include "lldb/Interpreter/Options.h" 3099f0b8f9SEnrico Granata #include "lldb/Interpreter/ScriptInterpreter.h" 31ebc09c36SJim Ingham 32ebc09c36SJim Ingham using namespace lldb; 33ebc09c36SJim Ingham using namespace lldb_private; 34ebc09c36SJim Ingham 35ebc09c36SJim Ingham //------------------------------------------------------------------------- 36ebc09c36SJim Ingham // CommandObjectCommandsSource 37ebc09c36SJim Ingham //------------------------------------------------------------------------- 38ebc09c36SJim Ingham 395a988416SJim Ingham class CommandObjectCommandsHistory : public CommandObjectParsed 40a5a97ebeSJim Ingham { 415a988416SJim Ingham public: 425a988416SJim Ingham CommandObjectCommandsHistory(CommandInterpreter &interpreter) : 435a988416SJim Ingham CommandObjectParsed(interpreter, 445a988416SJim Ingham "command history", 455a988416SJim Ingham "Dump the history of commands in this session.", 466e3d8e7fSEugene Zelenko nullptr), 475a988416SJim Ingham m_options (interpreter) 485a988416SJim Ingham { 495a988416SJim Ingham } 505a988416SJim Ingham 516e3d8e7fSEugene Zelenko ~CommandObjectCommandsHistory() override = default; 525a988416SJim Ingham 5313d21e9aSBruce Mitchener Options * 5413d21e9aSBruce Mitchener GetOptions () override 555a988416SJim Ingham { 565a988416SJim Ingham return &m_options; 575a988416SJim Ingham } 585a988416SJim Ingham 595a988416SJim Ingham protected: 60a5a97ebeSJim Ingham class CommandOptions : public Options 61a5a97ebeSJim Ingham { 62a5a97ebeSJim Ingham public: 63a5a97ebeSJim Ingham CommandOptions (CommandInterpreter &interpreter) : 647594f14fSEnrico Granata Options (interpreter), 657594f14fSEnrico Granata m_start_idx(0), 667594f14fSEnrico Granata m_stop_idx(0), 677594f14fSEnrico Granata m_count(0), 6863123b64SEnrico Granata m_clear(false) 69a5a97ebeSJim Ingham { 70a5a97ebeSJim Ingham } 71a5a97ebeSJim Ingham 726e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 73a5a97ebeSJim Ingham 7413d21e9aSBruce Mitchener Error 7513d21e9aSBruce Mitchener SetOptionValue (uint32_t option_idx, const char *option_arg) override 76a5a97ebeSJim Ingham { 77a5a97ebeSJim Ingham Error error; 783bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 79a5a97ebeSJim Ingham 80a5a97ebeSJim Ingham switch (short_option) 81a5a97ebeSJim Ingham { 82a5a97ebeSJim Ingham case 'c': 83c95f7e2aSPavel Labath error = m_count.SetValueFromString(option_arg,eVarSetOperationAssign); 84a5a97ebeSJim Ingham break; 85a5a97ebeSJim Ingham case 's': 867594f14fSEnrico Granata if (option_arg && strcmp("end", option_arg) == 0) 877594f14fSEnrico Granata { 887594f14fSEnrico Granata m_start_idx.SetCurrentValue(UINT64_MAX); 897594f14fSEnrico Granata m_start_idx.SetOptionWasSet(); 907594f14fSEnrico Granata } 917594f14fSEnrico Granata else 92c95f7e2aSPavel Labath error = m_start_idx.SetValueFromString(option_arg,eVarSetOperationAssign); 937594f14fSEnrico Granata break; 947594f14fSEnrico Granata case 'e': 95c95f7e2aSPavel Labath error = m_stop_idx.SetValueFromString(option_arg,eVarSetOperationAssign); 967594f14fSEnrico Granata break; 9763123b64SEnrico Granata case 'C': 9863123b64SEnrico Granata m_clear.SetCurrentValue(true); 9963123b64SEnrico Granata m_clear.SetOptionWasSet(); 100a5a97ebeSJim Ingham break; 101a5a97ebeSJim Ingham default: 10286edbf41SGreg Clayton error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 103a5a97ebeSJim Ingham break; 104a5a97ebeSJim Ingham } 105a5a97ebeSJim Ingham 106a5a97ebeSJim Ingham return error; 107a5a97ebeSJim Ingham } 108a5a97ebeSJim Ingham 109a5a97ebeSJim Ingham void 11013d21e9aSBruce Mitchener OptionParsingStarting () override 111a5a97ebeSJim Ingham { 1127594f14fSEnrico Granata m_start_idx.Clear(); 1137594f14fSEnrico Granata m_stop_idx.Clear(); 1147594f14fSEnrico Granata m_count.Clear(); 11563123b64SEnrico Granata m_clear.Clear(); 116a5a97ebeSJim Ingham } 117a5a97ebeSJim Ingham 118a5a97ebeSJim Ingham const OptionDefinition* 11913d21e9aSBruce Mitchener GetDefinitions () override 120a5a97ebeSJim Ingham { 121a5a97ebeSJim Ingham return g_option_table; 122a5a97ebeSJim Ingham } 123a5a97ebeSJim Ingham 124a5a97ebeSJim Ingham // Options table: Required for subclasses of Options. 125a5a97ebeSJim Ingham 126a5a97ebeSJim Ingham static OptionDefinition g_option_table[]; 127a5a97ebeSJim Ingham 128a5a97ebeSJim Ingham // Instance variables to hold the values for command options. 129a5a97ebeSJim Ingham 1307594f14fSEnrico Granata OptionValueUInt64 m_start_idx; 1317594f14fSEnrico Granata OptionValueUInt64 m_stop_idx; 1327594f14fSEnrico Granata OptionValueUInt64 m_count; 13363123b64SEnrico Granata OptionValueBoolean m_clear; 134a5a97ebeSJim Ingham }; 135a5a97ebeSJim Ingham 136a5a97ebeSJim Ingham bool 13713d21e9aSBruce Mitchener DoExecute (Args& command, CommandReturnObject &result) override 138a5a97ebeSJim Ingham { 13963123b64SEnrico Granata if (m_options.m_clear.GetCurrentValue() && m_options.m_clear.OptionWasSet()) 1407594f14fSEnrico Granata { 1417594f14fSEnrico Granata m_interpreter.GetCommandHistory().Clear(); 1427594f14fSEnrico Granata result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); 1437594f14fSEnrico Granata } 1447594f14fSEnrico Granata else 1457594f14fSEnrico Granata { 1467594f14fSEnrico Granata if (m_options.m_start_idx.OptionWasSet() && m_options.m_stop_idx.OptionWasSet() && m_options.m_count.OptionWasSet()) 1477594f14fSEnrico Granata { 1487594f14fSEnrico Granata result.AppendError("--count, --start-index and --end-index cannot be all specified in the same invocation"); 1497594f14fSEnrico Granata result.SetStatus(lldb::eReturnStatusFailed); 1507594f14fSEnrico Granata } 1517594f14fSEnrico Granata else 1527594f14fSEnrico Granata { 15384400ec7SVirgile Bello std::pair<bool,uint64_t> start_idx(m_options.m_start_idx.OptionWasSet(),m_options.m_start_idx.GetCurrentValue()); 15484400ec7SVirgile Bello std::pair<bool,uint64_t> stop_idx(m_options.m_stop_idx.OptionWasSet(),m_options.m_stop_idx.GetCurrentValue()); 15584400ec7SVirgile Bello std::pair<bool,uint64_t> count(m_options.m_count.OptionWasSet(),m_options.m_count.GetCurrentValue()); 156a5a97ebeSJim Ingham 1577594f14fSEnrico Granata const CommandHistory& history(m_interpreter.GetCommandHistory()); 1587594f14fSEnrico Granata 1597594f14fSEnrico Granata if (start_idx.first && start_idx.second == UINT64_MAX) 1607594f14fSEnrico Granata { 1617594f14fSEnrico Granata if (count.first) 1627594f14fSEnrico Granata { 1637594f14fSEnrico Granata start_idx.second = history.GetSize() - count.second; 1647594f14fSEnrico Granata stop_idx.second = history.GetSize() - 1; 1657594f14fSEnrico Granata } 1667594f14fSEnrico Granata else if (stop_idx.first) 1677594f14fSEnrico Granata { 1687594f14fSEnrico Granata start_idx.second = stop_idx.second; 1697594f14fSEnrico Granata stop_idx.second = history.GetSize() - 1; 1707594f14fSEnrico Granata } 1717594f14fSEnrico Granata else 1727594f14fSEnrico Granata { 1737594f14fSEnrico Granata start_idx.second = 0; 1747594f14fSEnrico Granata stop_idx.second = history.GetSize() - 1; 1757594f14fSEnrico Granata } 1767594f14fSEnrico Granata } 1777594f14fSEnrico Granata else 1787594f14fSEnrico Granata { 1797594f14fSEnrico Granata if (!start_idx.first && !stop_idx.first && !count.first) 1807594f14fSEnrico Granata { 1817594f14fSEnrico Granata start_idx.second = 0; 1827594f14fSEnrico Granata stop_idx.second = history.GetSize() - 1; 1837594f14fSEnrico Granata } 1847594f14fSEnrico Granata else if (start_idx.first) 1857594f14fSEnrico Granata { 1867594f14fSEnrico Granata if (count.first) 1877594f14fSEnrico Granata { 1887594f14fSEnrico Granata stop_idx.second = start_idx.second + count.second - 1; 1897594f14fSEnrico Granata } 1907594f14fSEnrico Granata else if (!stop_idx.first) 1917594f14fSEnrico Granata { 1927594f14fSEnrico Granata stop_idx.second = history.GetSize() - 1; 1937594f14fSEnrico Granata } 1947594f14fSEnrico Granata } 1957594f14fSEnrico Granata else if (stop_idx.first) 1967594f14fSEnrico Granata { 1977594f14fSEnrico Granata if (count.first) 1987594f14fSEnrico Granata { 1997594f14fSEnrico Granata if (stop_idx.second >= count.second) 2007594f14fSEnrico Granata start_idx.second = stop_idx.second - count.second + 1; 2017594f14fSEnrico Granata else 2027594f14fSEnrico Granata start_idx.second = 0; 2037594f14fSEnrico Granata } 2047594f14fSEnrico Granata } 2057594f14fSEnrico Granata else /* if (count.first) */ 2067594f14fSEnrico Granata { 2077594f14fSEnrico Granata start_idx.second = 0; 2087594f14fSEnrico Granata stop_idx.second = count.second - 1; 2097594f14fSEnrico Granata } 2107594f14fSEnrico Granata } 2117594f14fSEnrico Granata history.Dump(result.GetOutputStream(), start_idx.second, stop_idx.second); 2127594f14fSEnrico Granata } 2137594f14fSEnrico Granata } 214a5a97ebeSJim Ingham return result.Succeeded(); 215a5a97ebeSJim Ingham 216a5a97ebeSJim Ingham } 2175a988416SJim Ingham 2185a988416SJim Ingham CommandOptions m_options; 219a5a97ebeSJim Ingham }; 220a5a97ebeSJim Ingham 221a5a97ebeSJim Ingham OptionDefinition 222a5a97ebeSJim Ingham CommandObjectCommandsHistory::CommandOptions::g_option_table[] = 223a5a97ebeSJim Ingham { 2246e3d8e7fSEugene Zelenko { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "How many history commands to print."}, 2256e3d8e7fSEugene Zelenko { LLDB_OPT_SET_1, false, "start-index", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Index at which to start printing history commands (or end to mean tail mode)."}, 2266e3d8e7fSEugene Zelenko { LLDB_OPT_SET_1, false, "end-index", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands."}, 2276e3d8e7fSEugene Zelenko { LLDB_OPT_SET_2, false, "clear", 'C', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Clears the current command history."}, 2286e3d8e7fSEugene Zelenko { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 229a5a97ebeSJim Ingham }; 230a5a97ebeSJim Ingham 231a5a97ebeSJim Ingham //------------------------------------------------------------------------- 232a5a97ebeSJim Ingham // CommandObjectCommandsSource 233a5a97ebeSJim Ingham //------------------------------------------------------------------------- 234a5a97ebeSJim Ingham 2355a988416SJim Ingham class CommandObjectCommandsSource : public CommandObjectParsed 236ebc09c36SJim Ingham { 2375a988416SJim Ingham public: 238*7428a18cSKate Stone CommandObjectCommandsSource(CommandInterpreter &interpreter) 239*7428a18cSKate Stone : CommandObjectParsed(interpreter, "command source", "Read and execute LLDB commands from the file <filename>.", 2406e3d8e7fSEugene Zelenko nullptr), 2415a988416SJim Ingham m_options(interpreter) 2425a988416SJim Ingham { 2435a988416SJim Ingham CommandArgumentEntry arg; 2445a988416SJim Ingham CommandArgumentData file_arg; 2455a988416SJim Ingham 2465a988416SJim Ingham // Define the first (and only) variant of this arg. 2475a988416SJim Ingham file_arg.arg_type = eArgTypeFilename; 2485a988416SJim Ingham file_arg.arg_repetition = eArgRepeatPlain; 2495a988416SJim Ingham 2505a988416SJim Ingham // There is only one variant this argument could be; put it into the argument entry. 2515a988416SJim Ingham arg.push_back (file_arg); 2525a988416SJim Ingham 2535a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 2545a988416SJim Ingham m_arguments.push_back (arg); 2555a988416SJim Ingham } 2565a988416SJim Ingham 2576e3d8e7fSEugene Zelenko ~CommandObjectCommandsSource() override = default; 2585a988416SJim Ingham 25913d21e9aSBruce Mitchener const char* 26013d21e9aSBruce Mitchener GetRepeatCommand (Args ¤t_command_args, uint32_t index) override 2615a988416SJim Ingham { 2625a988416SJim Ingham return ""; 2635a988416SJim Ingham } 2645a988416SJim Ingham 26513d21e9aSBruce Mitchener int 2665a988416SJim Ingham HandleArgumentCompletion (Args &input, 2675a988416SJim Ingham int &cursor_index, 2685a988416SJim Ingham int &cursor_char_position, 2695a988416SJim Ingham OptionElementVector &opt_element_vector, 2705a988416SJim Ingham int match_start_point, 2715a988416SJim Ingham int max_return_elements, 2725a988416SJim Ingham bool &word_complete, 27313d21e9aSBruce Mitchener StringList &matches) override 2745a988416SJim Ingham { 2755a988416SJim Ingham std::string completion_str (input.GetArgumentAtIndex(cursor_index)); 2765a988416SJim Ingham completion_str.erase (cursor_char_position); 2775a988416SJim Ingham 2785a988416SJim Ingham CommandCompletions::InvokeCommonCompletionCallbacks(m_interpreter, 2795a988416SJim Ingham CommandCompletions::eDiskFileCompletion, 2805a988416SJim Ingham completion_str.c_str(), 2815a988416SJim Ingham match_start_point, 2825a988416SJim Ingham max_return_elements, 2836e3d8e7fSEugene Zelenko nullptr, 2845a988416SJim Ingham word_complete, 2855a988416SJim Ingham matches); 2865a988416SJim Ingham return matches.GetSize(); 2875a988416SJim Ingham } 2885a988416SJim Ingham 28913d21e9aSBruce Mitchener Options * 29013d21e9aSBruce Mitchener GetOptions () override 2915a988416SJim Ingham { 2925a988416SJim Ingham return &m_options; 2935a988416SJim Ingham } 2945a988416SJim Ingham 2955a988416SJim Ingham protected: 296e16c50a1SJim Ingham class CommandOptions : public Options 297e16c50a1SJim Ingham { 298e16c50a1SJim Ingham public: 299eb0103f2SGreg Clayton CommandOptions (CommandInterpreter &interpreter) : 300012d4fcaSEnrico Granata Options (interpreter), 301340b0309SGreg Clayton m_stop_on_error (true), 302340b0309SGreg Clayton m_silent_run (false), 303340b0309SGreg Clayton m_stop_on_continue (true) 304eb0103f2SGreg Clayton { 305eb0103f2SGreg Clayton } 306e16c50a1SJim Ingham 3076e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 308e16c50a1SJim Ingham 30913d21e9aSBruce Mitchener Error 31013d21e9aSBruce Mitchener SetOptionValue (uint32_t option_idx, const char *option_arg) override 311e16c50a1SJim Ingham { 312e16c50a1SJim Ingham Error error; 3133bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 314e16c50a1SJim Ingham 315e16c50a1SJim Ingham switch (short_option) 316e16c50a1SJim Ingham { 317e16c50a1SJim Ingham case 'e': 318c95f7e2aSPavel Labath error = m_stop_on_error.SetValueFromString(option_arg); 319e16c50a1SJim Ingham break; 320340b0309SGreg Clayton 321e16c50a1SJim Ingham case 'c': 322c95f7e2aSPavel Labath error = m_stop_on_continue.SetValueFromString(option_arg); 323e16c50a1SJim Ingham break; 324340b0309SGreg Clayton 32560986174SMichael Sartain case 's': 326c95f7e2aSPavel Labath error = m_silent_run.SetValueFromString(option_arg); 32760986174SMichael Sartain break; 328340b0309SGreg Clayton 329e16c50a1SJim Ingham default: 33086edbf41SGreg Clayton error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 331e16c50a1SJim Ingham break; 332e16c50a1SJim Ingham } 333e16c50a1SJim Ingham 334e16c50a1SJim Ingham return error; 335e16c50a1SJim Ingham } 336e16c50a1SJim Ingham 337e16c50a1SJim Ingham void 33813d21e9aSBruce Mitchener OptionParsingStarting () override 339e16c50a1SJim Ingham { 340012d4fcaSEnrico Granata m_stop_on_error.Clear(); 341340b0309SGreg Clayton m_silent_run.Clear(); 342340b0309SGreg Clayton m_stop_on_continue.Clear(); 343e16c50a1SJim Ingham } 344e16c50a1SJim Ingham 345e0d378b3SGreg Clayton const OptionDefinition* 34613d21e9aSBruce Mitchener GetDefinitions () override 347e16c50a1SJim Ingham { 348e16c50a1SJim Ingham return g_option_table; 349e16c50a1SJim Ingham } 350e16c50a1SJim Ingham 351e16c50a1SJim Ingham // Options table: Required for subclasses of Options. 352e16c50a1SJim Ingham 353e0d378b3SGreg Clayton static OptionDefinition g_option_table[]; 354e16c50a1SJim Ingham 355e16c50a1SJim Ingham // Instance variables to hold the values for command options. 356e16c50a1SJim Ingham 357012d4fcaSEnrico Granata OptionValueBoolean m_stop_on_error; 358340b0309SGreg Clayton OptionValueBoolean m_silent_run; 359340b0309SGreg Clayton OptionValueBoolean m_stop_on_continue; 360e16c50a1SJim Ingham }; 361e16c50a1SJim Ingham 362ebc09c36SJim Ingham bool 36313d21e9aSBruce Mitchener DoExecute(Args& command, CommandReturnObject &result) override 364ebc09c36SJim Ingham { 365c7bece56SGreg Clayton const size_t argc = command.GetArgumentCount(); 366ebc09c36SJim Ingham if (argc == 1) 367ebc09c36SJim Ingham { 3685a988416SJim Ingham const char *filename = command.GetArgumentAtIndex(0); 369ebc09c36SJim Ingham 3701ee3853fSJohnny Chen FileSpec cmd_file (filename, true); 3716e3d8e7fSEugene Zelenko ExecutionContext *exe_ctx = nullptr; // Just use the default context. 372ebc09c36SJim Ingham 373340b0309SGreg Clayton // If any options were set, then use them 374340b0309SGreg Clayton if (m_options.m_stop_on_error.OptionWasSet() || 375340b0309SGreg Clayton m_options.m_silent_run.OptionWasSet() || 376340b0309SGreg Clayton m_options.m_stop_on_continue.OptionWasSet()) 377340b0309SGreg Clayton { 378340b0309SGreg Clayton // Use user set settings 37926c7bf93SJim Ingham CommandInterpreterRunOptions options; 38026c7bf93SJim Ingham options.SetStopOnContinue(m_options.m_stop_on_continue.GetCurrentValue()); 38126c7bf93SJim Ingham options.SetStopOnError (m_options.m_stop_on_error.GetCurrentValue()); 3827d8555c4SJim Ingham options.SetEchoCommands (!m_options.m_silent_run.GetCurrentValue()); 3837d8555c4SJim Ingham options.SetPrintResults (!m_options.m_silent_run.GetCurrentValue()); 38426c7bf93SJim Ingham 385e16c50a1SJim Ingham m_interpreter.HandleCommandsFromFile (cmd_file, 386e16c50a1SJim Ingham exe_ctx, 38726c7bf93SJim Ingham options, 388e16c50a1SJim Ingham result); 389340b0309SGreg Clayton } 390340b0309SGreg Clayton else 391340b0309SGreg Clayton { 392340b0309SGreg Clayton // No options were set, inherit any settings from nested "command source" commands, 393340b0309SGreg Clayton // or set to sane default settings... 39426c7bf93SJim Ingham CommandInterpreterRunOptions options; 395340b0309SGreg Clayton m_interpreter.HandleCommandsFromFile (cmd_file, 396340b0309SGreg Clayton exe_ctx, 39726c7bf93SJim Ingham options, 398340b0309SGreg Clayton result); 399340b0309SGreg Clayton } 400ebc09c36SJim Ingham } 401ebc09c36SJim Ingham else 402ebc09c36SJim Ingham { 403ebc09c36SJim Ingham result.AppendErrorWithFormat("'%s' takes exactly one executable filename argument.\n", GetCommandName()); 404ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 405ebc09c36SJim Ingham } 406ebc09c36SJim Ingham return result.Succeeded(); 407ebc09c36SJim Ingham } 4086e3d8e7fSEugene Zelenko 4095a988416SJim Ingham CommandOptions m_options; 410ebc09c36SJim Ingham }; 411ebc09c36SJim Ingham 412e0d378b3SGreg Clayton OptionDefinition 413e16c50a1SJim Ingham CommandObjectCommandsSource::CommandOptions::g_option_table[] = 414e16c50a1SJim Ingham { 4156e3d8e7fSEugene Zelenko { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on error."}, 4166e3d8e7fSEugene Zelenko { LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on continue."}, 4176e3d8e7fSEugene Zelenko { LLDB_OPT_SET_ALL, false, "silent-run", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true don't echo commands while executing."}, 4186e3d8e7fSEugene Zelenko { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 419e16c50a1SJim Ingham }; 420e16c50a1SJim Ingham 421ebc09c36SJim Ingham #pragma mark CommandObjectCommandsAlias 422ebc09c36SJim Ingham //------------------------------------------------------------------------- 423ebc09c36SJim Ingham // CommandObjectCommandsAlias 424ebc09c36SJim Ingham //------------------------------------------------------------------------- 425ebc09c36SJim Ingham 426be93a35aSEnrico Granata static const char *g_python_command_instructions = "Enter your Python command(s). Type 'DONE' to end.\n" 427be93a35aSEnrico Granata "You must define a Python function with this signature:\n" 42844d93782SGreg Clayton "def my_command_impl(debugger, args, result, internal_dict):\n"; 429be93a35aSEnrico Granata 4305a988416SJim Ingham class CommandObjectCommandsAlias : public CommandObjectRaw 431ebc09c36SJim Ingham { 43245d0e238SEnrico Granata protected: 43345d0e238SEnrico Granata class CommandOptions : public OptionGroup 43445d0e238SEnrico Granata { 435ebc09c36SJim Ingham public: 43645d0e238SEnrico Granata CommandOptions () : 43745d0e238SEnrico Granata OptionGroup(), 43845d0e238SEnrico Granata m_help(), 43945d0e238SEnrico Granata m_long_help() 44045d0e238SEnrico Granata {} 44145d0e238SEnrico Granata 44245d0e238SEnrico Granata ~CommandOptions() override = default; 44345d0e238SEnrico Granata 44445d0e238SEnrico Granata uint32_t 44545d0e238SEnrico Granata GetNumDefinitions () override 44645d0e238SEnrico Granata { 44745d0e238SEnrico Granata return 3; 44845d0e238SEnrico Granata } 44945d0e238SEnrico Granata 45045d0e238SEnrico Granata const OptionDefinition* 45145d0e238SEnrico Granata GetDefinitions () override 45245d0e238SEnrico Granata { 45345d0e238SEnrico Granata return g_option_table; 45445d0e238SEnrico Granata } 45545d0e238SEnrico Granata 45645d0e238SEnrico Granata Error 45745d0e238SEnrico Granata SetOptionValue (CommandInterpreter &interpreter, 45845d0e238SEnrico Granata uint32_t option_idx, 45945d0e238SEnrico Granata const char *option_value) override 46045d0e238SEnrico Granata { 46145d0e238SEnrico Granata Error error; 46245d0e238SEnrico Granata 46345d0e238SEnrico Granata const int short_option = g_option_table[option_idx].short_option; 46445d0e238SEnrico Granata 46545d0e238SEnrico Granata switch (short_option) 46645d0e238SEnrico Granata { 46745d0e238SEnrico Granata case 'h': 46845d0e238SEnrico Granata m_help.SetCurrentValue(option_value); 46945d0e238SEnrico Granata m_help.SetOptionWasSet(); 47045d0e238SEnrico Granata break; 47145d0e238SEnrico Granata 47245d0e238SEnrico Granata case 'H': 47345d0e238SEnrico Granata m_long_help.SetCurrentValue(option_value); 47445d0e238SEnrico Granata m_long_help.SetOptionWasSet(); 47545d0e238SEnrico Granata break; 47645d0e238SEnrico Granata 47745d0e238SEnrico Granata default: 47845d0e238SEnrico Granata error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 47945d0e238SEnrico Granata break; 48045d0e238SEnrico Granata } 48145d0e238SEnrico Granata 48245d0e238SEnrico Granata return error; 48345d0e238SEnrico Granata } 48445d0e238SEnrico Granata 48545d0e238SEnrico Granata void 48645d0e238SEnrico Granata OptionParsingStarting (CommandInterpreter &interpreter) override 48745d0e238SEnrico Granata { 48845d0e238SEnrico Granata m_help.Clear(); 48945d0e238SEnrico Granata m_long_help.Clear(); 49045d0e238SEnrico Granata } 49145d0e238SEnrico Granata 49245d0e238SEnrico Granata // Options table: Required for subclasses of Options. 49345d0e238SEnrico Granata 49445d0e238SEnrico Granata static OptionDefinition g_option_table[]; 49545d0e238SEnrico Granata OptionValueString m_help; 49645d0e238SEnrico Granata OptionValueString m_long_help; 49745d0e238SEnrico Granata }; 49845d0e238SEnrico Granata 49945d0e238SEnrico Granata OptionGroupOptions m_option_group; 50045d0e238SEnrico Granata CommandOptions m_command_options; 50145d0e238SEnrico Granata 50245d0e238SEnrico Granata public: 50345d0e238SEnrico Granata Options * 50445d0e238SEnrico Granata GetOptions () override 50545d0e238SEnrico Granata { 50645d0e238SEnrico Granata return &m_option_group; 50745d0e238SEnrico Granata } 50845d0e238SEnrico Granata 509*7428a18cSKate Stone CommandObjectCommandsAlias(CommandInterpreter &interpreter) 510*7428a18cSKate Stone : CommandObjectRaw(interpreter, "command alias", "Define a custom command in terms of an existing command.", 51145d0e238SEnrico Granata nullptr), 51245d0e238SEnrico Granata m_option_group(interpreter), 51345d0e238SEnrico Granata m_command_options() 514ebc09c36SJim Ingham { 51545d0e238SEnrico Granata m_option_group.Append(&m_command_options); 51645d0e238SEnrico Granata m_option_group.Finalize(); 51745d0e238SEnrico Granata 518ebc09c36SJim Ingham SetHelpLong( 519ea671fbdSKate Stone "'alias' allows the user to create a short-cut or abbreviation for long \ 520ea671fbdSKate Stone commands, multi-word commands, and commands that take particular options. \ 521ea671fbdSKate Stone Below are some simple examples of how one might use the 'alias' command:" R"( 522ea671fbdSKate Stone 523ea671fbdSKate Stone (lldb) command alias sc script 524ea671fbdSKate Stone 525ea671fbdSKate Stone Creates the abbreviation 'sc' for the 'script' command. 526ea671fbdSKate Stone 527ea671fbdSKate Stone (lldb) command alias bp breakpoint 528ea671fbdSKate Stone 529ea671fbdSKate Stone )" " Creates the abbreviation 'bp' for the 'breakpoint' command. Since \ 530ea671fbdSKate Stone breakpoint commands are two-word commands, the user would still need to \ 531ea671fbdSKate Stone enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'." R"( 532ea671fbdSKate Stone 533ea671fbdSKate Stone (lldb) command alias bpl breakpoint list 534ea671fbdSKate Stone 535ea671fbdSKate Stone Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'. 536ea671fbdSKate Stone 537ea671fbdSKate Stone )" "An alias can include some options for the command, with the values either \ 538ea671fbdSKate Stone filled in at the time the alias is created, or specified as positional \ 539ea671fbdSKate Stone arguments, to be filled in when the alias is invoked. The following example \ 540ea671fbdSKate Stone shows how to create aliases with options:" R"( 541ea671fbdSKate Stone 542ea671fbdSKate Stone (lldb) command alias bfl breakpoint set -f %1 -l %2 543ea671fbdSKate Stone 544ea671fbdSKate Stone )" " Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \ 545ea671fbdSKate Stone options already part of the alias. So if the user wants to set a breakpoint \ 546ea671fbdSKate Stone by file and line without explicitly having to use the -f and -l options, the \ 547ea671fbdSKate Stone user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \ 548ea671fbdSKate Stone for the actual arguments that will be passed when the alias command is used. \ 549ea671fbdSKate Stone The number in the placeholder refers to the position/order the actual value \ 550ea671fbdSKate Stone occupies when the alias is used. All the occurrences of '%1' in the alias \ 551ea671fbdSKate Stone will be replaced with the first argument, all the occurrences of '%2' in the \ 552ea671fbdSKate Stone alias will be replaced with the second argument, and so on. This also allows \ 553ea671fbdSKate Stone actual arguments to be used multiple times within an alias (see 'process \ 554ea671fbdSKate Stone launch' example below)." R"( 555ea671fbdSKate Stone 556ea671fbdSKate Stone )" "Note: the positional arguments must substitute as whole words in the resultant \ 557ea671fbdSKate Stone command, so you can't at present do something like this to append the file extension \ 558ea671fbdSKate Stone \".cpp\":" R"( 559ea671fbdSKate Stone 560ea671fbdSKate Stone (lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2 561ea671fbdSKate Stone 562ea671fbdSKate Stone )" "For more complex aliasing, use the \"command regex\" command instead. In the \ 563ea671fbdSKate Stone 'bfl' case above, the actual file value will be filled in with the first argument \ 564ea671fbdSKate Stone following 'bfl' and the actual line number value will be filled in with the second \ 565ea671fbdSKate Stone argument. The user would use this alias as follows:" R"( 566ea671fbdSKate Stone 567ea671fbdSKate Stone (lldb) command alias bfl breakpoint set -f %1 -l %2 568ea671fbdSKate Stone (lldb) bfl my-file.c 137 569ea671fbdSKate Stone 570ea671fbdSKate Stone This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'. 571ea671fbdSKate Stone 572ea671fbdSKate Stone Another example: 573ea671fbdSKate Stone 574ea671fbdSKate Stone (lldb) command alias pltty process launch -s -o %1 -e %1 575ea671fbdSKate Stone (lldb) pltty /dev/tty0 576ea671fbdSKate Stone 577ea671fbdSKate Stone Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0' 578ea671fbdSKate Stone 579ea671fbdSKate Stone )" "If the user always wanted to pass the same value to a particular option, the \ 580ea671fbdSKate Stone alias could be defined with that value directly in the alias as a constant, \ 581ea671fbdSKate Stone rather than using a positional placeholder:" R"( 582ea671fbdSKate Stone 583ea671fbdSKate Stone (lldb) command alias bl3 breakpoint set -f %1 -l 3 584ea671fbdSKate Stone 585ea671fbdSKate Stone Always sets a breakpoint on line 3 of whatever file is indicated.)" 586ea671fbdSKate Stone ); 587ebc09c36SJim Ingham 588405fe67fSCaroline Tice CommandArgumentEntry arg1; 589405fe67fSCaroline Tice CommandArgumentEntry arg2; 590405fe67fSCaroline Tice CommandArgumentEntry arg3; 591405fe67fSCaroline Tice CommandArgumentData alias_arg; 592405fe67fSCaroline Tice CommandArgumentData cmd_arg; 593405fe67fSCaroline Tice CommandArgumentData options_arg; 594405fe67fSCaroline Tice 595405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 596405fe67fSCaroline Tice alias_arg.arg_type = eArgTypeAliasName; 597405fe67fSCaroline Tice alias_arg.arg_repetition = eArgRepeatPlain; 598405fe67fSCaroline Tice 599405fe67fSCaroline Tice // There is only one variant this argument could be; put it into the argument entry. 600405fe67fSCaroline Tice arg1.push_back (alias_arg); 601405fe67fSCaroline Tice 602405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 603405fe67fSCaroline Tice cmd_arg.arg_type = eArgTypeCommandName; 604405fe67fSCaroline Tice cmd_arg.arg_repetition = eArgRepeatPlain; 605405fe67fSCaroline Tice 606405fe67fSCaroline Tice // There is only one variant this argument could be; put it into the argument entry. 607405fe67fSCaroline Tice arg2.push_back (cmd_arg); 608405fe67fSCaroline Tice 609405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 610405fe67fSCaroline Tice options_arg.arg_type = eArgTypeAliasOptions; 611405fe67fSCaroline Tice options_arg.arg_repetition = eArgRepeatOptional; 612405fe67fSCaroline Tice 613405fe67fSCaroline Tice // There is only one variant this argument could be; put it into the argument entry. 614405fe67fSCaroline Tice arg3.push_back (options_arg); 615405fe67fSCaroline Tice 616405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 617405fe67fSCaroline Tice m_arguments.push_back (arg1); 618405fe67fSCaroline Tice m_arguments.push_back (arg2); 619405fe67fSCaroline Tice m_arguments.push_back (arg3); 620ebc09c36SJim Ingham } 621ebc09c36SJim Ingham 6226e3d8e7fSEugene Zelenko ~CommandObjectCommandsAlias() override = default; 623ebc09c36SJim Ingham 6245a988416SJim Ingham protected: 62513d21e9aSBruce Mitchener bool 62613d21e9aSBruce Mitchener DoExecute (const char *raw_command_line, CommandReturnObject &result) override 627844d2303SCaroline Tice { 62845d0e238SEnrico Granata if (!raw_command_line || !raw_command_line[0]) 62945d0e238SEnrico Granata { 630d72e412fSEnrico Granata result.AppendError ("'command alias' requires at least two arguments"); 63145d0e238SEnrico Granata return false; 63245d0e238SEnrico Granata } 63345d0e238SEnrico Granata 63445d0e238SEnrico Granata m_option_group.NotifyOptionParsingStarting(); 63545d0e238SEnrico Granata 63645d0e238SEnrico Granata const char * remainder = nullptr; 63745d0e238SEnrico Granata 63845d0e238SEnrico Granata if (raw_command_line[0] == '-') 63945d0e238SEnrico Granata { 64045d0e238SEnrico Granata // We have some options and these options MUST end with --. 64145d0e238SEnrico Granata const char *end_options = nullptr; 64245d0e238SEnrico Granata const char *s = raw_command_line; 64345d0e238SEnrico Granata while (s && s[0]) 64445d0e238SEnrico Granata { 64545d0e238SEnrico Granata end_options = ::strstr (s, "--"); 64645d0e238SEnrico Granata if (end_options) 64745d0e238SEnrico Granata { 64845d0e238SEnrico Granata end_options += 2; // Get past the "--" 64945d0e238SEnrico Granata if (::isspace (end_options[0])) 65045d0e238SEnrico Granata { 65145d0e238SEnrico Granata remainder = end_options; 65245d0e238SEnrico Granata while (::isspace (*remainder)) 65345d0e238SEnrico Granata ++remainder; 65445d0e238SEnrico Granata break; 65545d0e238SEnrico Granata } 65645d0e238SEnrico Granata } 65745d0e238SEnrico Granata s = end_options; 65845d0e238SEnrico Granata } 65945d0e238SEnrico Granata 66045d0e238SEnrico Granata if (end_options) 66145d0e238SEnrico Granata { 66245d0e238SEnrico Granata Args args (llvm::StringRef(raw_command_line, end_options - raw_command_line)); 66345d0e238SEnrico Granata if (!ParseOptions (args, result)) 66445d0e238SEnrico Granata return false; 66545d0e238SEnrico Granata 66645d0e238SEnrico Granata Error error (m_option_group.NotifyOptionParsingFinished()); 66745d0e238SEnrico Granata if (error.Fail()) 66845d0e238SEnrico Granata { 66945d0e238SEnrico Granata result.AppendError (error.AsCString()); 67045d0e238SEnrico Granata result.SetStatus (eReturnStatusFailed); 67145d0e238SEnrico Granata return false; 67245d0e238SEnrico Granata } 67345d0e238SEnrico Granata } 67445d0e238SEnrico Granata } 67545d0e238SEnrico Granata if (nullptr == remainder) 67645d0e238SEnrico Granata remainder = raw_command_line; 67745d0e238SEnrico Granata 67845d0e238SEnrico Granata std::string raw_command_string (remainder); 67945d0e238SEnrico Granata Args args (raw_command_string.c_str()); 680844d2303SCaroline Tice 681844d2303SCaroline Tice size_t argc = args.GetArgumentCount(); 682844d2303SCaroline Tice 683844d2303SCaroline Tice if (argc < 2) 684844d2303SCaroline Tice { 685d72e412fSEnrico Granata result.AppendError ("'command alias' requires at least two arguments"); 686844d2303SCaroline Tice result.SetStatus (eReturnStatusFailed); 687844d2303SCaroline Tice return false; 688844d2303SCaroline Tice } 689844d2303SCaroline Tice 690844d2303SCaroline Tice // Get the alias command. 691844d2303SCaroline Tice 692844d2303SCaroline Tice const std::string alias_command = args.GetArgumentAtIndex (0); 693d72e412fSEnrico Granata if (alias_command.size() > 1 && 694d72e412fSEnrico Granata alias_command[0] == '-') 695d72e412fSEnrico Granata { 696d72e412fSEnrico Granata result.AppendError("aliases starting with a dash are not supported"); 697d72e412fSEnrico Granata if (alias_command == "--help" || alias_command == "--long-help") 698d72e412fSEnrico Granata { 699d72e412fSEnrico Granata result.AppendWarning("if trying to pass options to 'command alias' add a -- at the end of the options"); 700d72e412fSEnrico Granata } 701d72e412fSEnrico Granata result.SetStatus (eReturnStatusFailed); 702d72e412fSEnrico Granata return false; 703d72e412fSEnrico Granata } 704844d2303SCaroline Tice 705844d2303SCaroline Tice // Strip the new alias name off 'raw_command_string' (leave it on args, which gets passed to 'Execute', which 706844d2303SCaroline Tice // does the stripping itself. 707844d2303SCaroline Tice size_t pos = raw_command_string.find (alias_command); 708844d2303SCaroline Tice if (pos == 0) 709844d2303SCaroline Tice { 710844d2303SCaroline Tice raw_command_string = raw_command_string.substr (alias_command.size()); 711844d2303SCaroline Tice pos = raw_command_string.find_first_not_of (' '); 712844d2303SCaroline Tice if ((pos != std::string::npos) && (pos > 0)) 713844d2303SCaroline Tice raw_command_string = raw_command_string.substr (pos); 714844d2303SCaroline Tice } 715844d2303SCaroline Tice else 716844d2303SCaroline Tice { 717844d2303SCaroline Tice result.AppendError ("Error parsing command string. No alias created."); 718844d2303SCaroline Tice result.SetStatus (eReturnStatusFailed); 719844d2303SCaroline Tice return false; 720844d2303SCaroline Tice } 721844d2303SCaroline Tice 722844d2303SCaroline Tice 723844d2303SCaroline Tice // Verify that the command is alias-able. 724844d2303SCaroline Tice if (m_interpreter.CommandExists (alias_command.c_str())) 725844d2303SCaroline Tice { 726844d2303SCaroline Tice result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n", 727844d2303SCaroline Tice alias_command.c_str()); 728844d2303SCaroline Tice result.SetStatus (eReturnStatusFailed); 729844d2303SCaroline Tice return false; 730844d2303SCaroline Tice } 731844d2303SCaroline Tice 732844d2303SCaroline Tice // Get CommandObject that is being aliased. The command name is read from the front of raw_command_string. 733844d2303SCaroline Tice // raw_command_string is returned with the name of the command object stripped off the front. 734d72e412fSEnrico Granata std::string original_raw_command_string(raw_command_string); 735844d2303SCaroline Tice CommandObject *cmd_obj = m_interpreter.GetCommandObjectForCommand (raw_command_string); 736844d2303SCaroline Tice 737844d2303SCaroline Tice if (!cmd_obj) 738844d2303SCaroline Tice { 739d72e412fSEnrico Granata result.AppendErrorWithFormat ("invalid command given to 'command alias'. '%s' does not begin with a valid command." 740d72e412fSEnrico Granata " No alias created.", original_raw_command_string.c_str()); 741844d2303SCaroline Tice result.SetStatus (eReturnStatusFailed); 742844d2303SCaroline Tice return false; 743844d2303SCaroline Tice } 744844d2303SCaroline Tice else if (!cmd_obj->WantsRawCommandString ()) 745844d2303SCaroline Tice { 746844d2303SCaroline Tice // Note that args was initialized with the original command, and has not been updated to this point. 747844d2303SCaroline Tice // Therefore can we pass it to the version of Execute that does not need/expect raw input in the alias. 7485a988416SJim Ingham return HandleAliasingNormalCommand (args, result); 749844d2303SCaroline Tice } 750844d2303SCaroline Tice else 751844d2303SCaroline Tice { 7525a988416SJim Ingham return HandleAliasingRawCommand (alias_command, raw_command_string, *cmd_obj, result); 7535a988416SJim Ingham } 7545a988416SJim Ingham return result.Succeeded(); 7555a988416SJim Ingham } 7565a988416SJim Ingham 7575a988416SJim Ingham bool 7585a988416SJim Ingham HandleAliasingRawCommand (const std::string &alias_command, std::string &raw_command_string, CommandObject &cmd_obj, CommandReturnObject &result) 7595a988416SJim Ingham { 760844d2303SCaroline Tice // Verify & handle any options/arguments passed to the alias command 761844d2303SCaroline Tice 762844d2303SCaroline Tice OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector); 763844d2303SCaroline Tice 764212130acSEnrico Granata if (CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact (cmd_obj.GetCommandName(), false)) 765844d2303SCaroline Tice { 766844d2303SCaroline Tice if (m_interpreter.AliasExists (alias_command.c_str()) 767844d2303SCaroline Tice || m_interpreter.UserCommandExists (alias_command.c_str())) 768844d2303SCaroline Tice { 769844d2303SCaroline Tice result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n", 770844d2303SCaroline Tice alias_command.c_str()); 771844d2303SCaroline Tice } 77245d0e238SEnrico Granata if (CommandAlias *alias = m_interpreter.AddAlias (alias_command.c_str(), cmd_obj_sp, raw_command_string.c_str())) 773472362e6SCaroline Tice { 77445d0e238SEnrico Granata if (m_command_options.m_help.OptionWasSet()) 77545d0e238SEnrico Granata alias->SetHelp(m_command_options.m_help.GetCurrentValue()); 77645d0e238SEnrico Granata if (m_command_options.m_long_help.OptionWasSet()) 77745d0e238SEnrico Granata alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue()); 778844d2303SCaroline Tice result.SetStatus (eReturnStatusSuccessFinishNoResult); 779844d2303SCaroline Tice } 780472362e6SCaroline Tice else 781472362e6SCaroline Tice { 782472362e6SCaroline Tice result.AppendError ("Unable to create requested alias.\n"); 783472362e6SCaroline Tice result.SetStatus (eReturnStatusFailed); 784472362e6SCaroline Tice } 785212130acSEnrico Granata 786212130acSEnrico Granata } 787212130acSEnrico Granata else 788212130acSEnrico Granata { 789212130acSEnrico Granata result.AppendError ("Unable to create requested alias.\n"); 790212130acSEnrico Granata result.SetStatus (eReturnStatusFailed); 791212130acSEnrico Granata } 792212130acSEnrico Granata 793844d2303SCaroline Tice return result.Succeeded (); 794844d2303SCaroline Tice } 795ebc09c36SJim Ingham 796ebc09c36SJim Ingham bool 7975a988416SJim Ingham HandleAliasingNormalCommand (Args& args, CommandReturnObject &result) 798ebc09c36SJim Ingham { 799867b185dSCaroline Tice size_t argc = args.GetArgumentCount(); 800ebc09c36SJim Ingham 801ebc09c36SJim Ingham if (argc < 2) 802ebc09c36SJim Ingham { 803d72e412fSEnrico Granata result.AppendError ("'command alias' requires at least two arguments"); 804ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 805ebc09c36SJim Ingham return false; 806ebc09c36SJim Ingham } 807ebc09c36SJim Ingham 808ebc09c36SJim Ingham const std::string alias_command = args.GetArgumentAtIndex(0); 809ebc09c36SJim Ingham const std::string actual_command = args.GetArgumentAtIndex(1); 810ebc09c36SJim Ingham 811ebc09c36SJim Ingham args.Shift(); // Shift the alias command word off the argument vector. 812ebc09c36SJim Ingham args.Shift(); // Shift the old command word off the argument vector. 813ebc09c36SJim Ingham 814ebc09c36SJim Ingham // Verify that the command is alias'able, and get the appropriate command object. 815ebc09c36SJim Ingham 816a7015092SGreg Clayton if (m_interpreter.CommandExists (alias_command.c_str())) 817ebc09c36SJim Ingham { 818ebc09c36SJim Ingham result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n", 819ebc09c36SJim Ingham alias_command.c_str()); 820ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 821ebc09c36SJim Ingham } 822ebc09c36SJim Ingham else 823ebc09c36SJim Ingham { 824a7015092SGreg Clayton CommandObjectSP command_obj_sp(m_interpreter.GetCommandSPExact (actual_command.c_str(), true)); 825ebc09c36SJim Ingham CommandObjectSP subcommand_obj_sp; 826ebc09c36SJim Ingham bool use_subcommand = false; 8276e3d8e7fSEugene Zelenko if (command_obj_sp) 828ebc09c36SJim Ingham { 829ebc09c36SJim Ingham CommandObject *cmd_obj = command_obj_sp.get(); 8306e3d8e7fSEugene Zelenko CommandObject *sub_cmd_obj = nullptr; 831ebc09c36SJim Ingham OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector); 832ebc09c36SJim Ingham 833844d2303SCaroline Tice while (cmd_obj->IsMultiwordObject() && args.GetArgumentCount() > 0) 834ebc09c36SJim Ingham { 835ebc09c36SJim Ingham if (argc >= 3) 836ebc09c36SJim Ingham { 837ebc09c36SJim Ingham const std::string sub_command = args.GetArgumentAtIndex(0); 838ebc09c36SJim Ingham assert (sub_command.length() != 0); 839998255bfSGreg Clayton subcommand_obj_sp = cmd_obj->GetSubcommandSP (sub_command.c_str()); 8406e3d8e7fSEugene Zelenko if (subcommand_obj_sp) 841ebc09c36SJim Ingham { 842ebc09c36SJim Ingham sub_cmd_obj = subcommand_obj_sp.get(); 843ebc09c36SJim Ingham use_subcommand = true; 844ebc09c36SJim Ingham args.Shift(); // Shift the sub_command word off the argument vector. 845844d2303SCaroline Tice cmd_obj = sub_cmd_obj; 846ebc09c36SJim Ingham } 847ebc09c36SJim Ingham else 848ebc09c36SJim Ingham { 849f415eeb4SCaroline Tice result.AppendErrorWithFormat("'%s' is not a valid sub-command of '%s'. " 850f415eeb4SCaroline Tice "Unable to create alias.\n", 851f415eeb4SCaroline Tice sub_command.c_str(), actual_command.c_str()); 852ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 853ebc09c36SJim Ingham return false; 854ebc09c36SJim Ingham } 855ebc09c36SJim Ingham } 856ebc09c36SJim Ingham } 857ebc09c36SJim Ingham 858ebc09c36SJim Ingham // Verify & handle any options/arguments passed to the alias command 859ebc09c36SJim Ingham 860212130acSEnrico Granata std::string args_string; 861212130acSEnrico Granata 862ebc09c36SJim Ingham if (args.GetArgumentCount () > 0) 863ebc09c36SJim Ingham { 864ca90c47eSCaroline Tice CommandObjectSP tmp_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false); 865ebc09c36SJim Ingham if (use_subcommand) 866ca90c47eSCaroline Tice tmp_sp = m_interpreter.GetCommandSPExact (sub_cmd_obj->GetCommandName(), false); 867ca90c47eSCaroline Tice 868ca90c47eSCaroline Tice args.GetCommandString (args_string); 869867b185dSCaroline Tice } 870ebc09c36SJim Ingham 871a7015092SGreg Clayton if (m_interpreter.AliasExists (alias_command.c_str()) 872a7015092SGreg Clayton || m_interpreter.UserCommandExists (alias_command.c_str())) 873ebc09c36SJim Ingham { 874ebc09c36SJim Ingham result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n", 875ebc09c36SJim Ingham alias_command.c_str()); 876ebc09c36SJim Ingham } 877ebc09c36SJim Ingham 87845d0e238SEnrico Granata if (CommandAlias *alias = m_interpreter.AddAlias(alias_command.c_str(), 879212130acSEnrico Granata use_subcommand ? subcommand_obj_sp : command_obj_sp, 880212130acSEnrico Granata args_string.c_str())) 881212130acSEnrico Granata { 88245d0e238SEnrico Granata if (m_command_options.m_help.OptionWasSet()) 88345d0e238SEnrico Granata alias->SetHelp(m_command_options.m_help.GetCurrentValue()); 88445d0e238SEnrico Granata if (m_command_options.m_long_help.OptionWasSet()) 88545d0e238SEnrico Granata alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue()); 886ebc09c36SJim Ingham result.SetStatus (eReturnStatusSuccessFinishNoResult); 887ebc09c36SJim Ingham } 888ebc09c36SJim Ingham else 889ebc09c36SJim Ingham { 890212130acSEnrico Granata result.AppendError ("Unable to create requested alias.\n"); 891212130acSEnrico Granata result.SetStatus (eReturnStatusFailed); 892212130acSEnrico Granata return false; 893212130acSEnrico Granata } 894212130acSEnrico Granata } 895212130acSEnrico Granata else 896212130acSEnrico Granata { 897ebc09c36SJim Ingham result.AppendErrorWithFormat ("'%s' is not an existing command.\n", actual_command.c_str()); 898ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 899e7941795SCaroline Tice return false; 900ebc09c36SJim Ingham } 901ebc09c36SJim Ingham } 902ebc09c36SJim Ingham 903ebc09c36SJim Ingham return result.Succeeded(); 904ebc09c36SJim Ingham } 905ebc09c36SJim Ingham }; 906ebc09c36SJim Ingham 90745d0e238SEnrico Granata OptionDefinition 90845d0e238SEnrico Granata CommandObjectCommandsAlias::CommandOptions::g_option_table[] = 90945d0e238SEnrico Granata { 91045d0e238SEnrico Granata { LLDB_OPT_SET_ALL, false, "help", 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Help text for this command"}, 91145d0e238SEnrico Granata { LLDB_OPT_SET_ALL, false, "long-help", 'H', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Long help text for this command"}, 91245d0e238SEnrico Granata { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 91345d0e238SEnrico Granata }; 91445d0e238SEnrico Granata 915ebc09c36SJim Ingham #pragma mark CommandObjectCommandsUnalias 916ebc09c36SJim Ingham //------------------------------------------------------------------------- 917ebc09c36SJim Ingham // CommandObjectCommandsUnalias 918ebc09c36SJim Ingham //------------------------------------------------------------------------- 919ebc09c36SJim Ingham 9205a988416SJim Ingham class CommandObjectCommandsUnalias : public CommandObjectParsed 921ebc09c36SJim Ingham { 922ebc09c36SJim Ingham public: 923*7428a18cSKate Stone CommandObjectCommandsUnalias(CommandInterpreter &interpreter) 924*7428a18cSKate Stone : CommandObjectParsed(interpreter, "command unalias", 925*7428a18cSKate Stone "Delete one or more custom commands defined by 'command alias'.", nullptr) 926ebc09c36SJim Ingham { 927405fe67fSCaroline Tice CommandArgumentEntry arg; 928405fe67fSCaroline Tice CommandArgumentData alias_arg; 929405fe67fSCaroline Tice 930405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 931405fe67fSCaroline Tice alias_arg.arg_type = eArgTypeAliasName; 932405fe67fSCaroline Tice alias_arg.arg_repetition = eArgRepeatPlain; 933405fe67fSCaroline Tice 934405fe67fSCaroline Tice // There is only one variant this argument could be; put it into the argument entry. 935405fe67fSCaroline Tice arg.push_back (alias_arg); 936405fe67fSCaroline Tice 937405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 938405fe67fSCaroline Tice m_arguments.push_back (arg); 939ebc09c36SJim Ingham } 940ebc09c36SJim Ingham 9416e3d8e7fSEugene Zelenko ~CommandObjectCommandsUnalias() override = default; 942ebc09c36SJim Ingham 9435a988416SJim Ingham protected: 944ebc09c36SJim Ingham bool 94513d21e9aSBruce Mitchener DoExecute (Args& args, CommandReturnObject &result) override 946ebc09c36SJim Ingham { 947ebc09c36SJim Ingham CommandObject::CommandMap::iterator pos; 948ebc09c36SJim Ingham CommandObject *cmd_obj; 949ebc09c36SJim Ingham 950ebc09c36SJim Ingham if (args.GetArgumentCount() != 0) 951ebc09c36SJim Ingham { 952ebc09c36SJim Ingham const char *command_name = args.GetArgumentAtIndex(0); 953a7015092SGreg Clayton cmd_obj = m_interpreter.GetCommandObject(command_name); 954ebc09c36SJim Ingham if (cmd_obj) 955ebc09c36SJim Ingham { 956a7015092SGreg Clayton if (m_interpreter.CommandExists (command_name)) 957ebc09c36SJim Ingham { 958b547278cSGreg Clayton if (cmd_obj->IsRemovable()) 959b547278cSGreg Clayton { 960b547278cSGreg Clayton result.AppendErrorWithFormat ("'%s' is not an alias, it is a debugger command which can be removed using the 'command delete' command.\n", 961b547278cSGreg Clayton command_name); 962b547278cSGreg Clayton } 963b547278cSGreg Clayton else 964b547278cSGreg Clayton { 965ebc09c36SJim Ingham result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n", 966ebc09c36SJim Ingham command_name); 967b547278cSGreg Clayton } 968ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 969ebc09c36SJim Ingham } 970ebc09c36SJim Ingham else 971ebc09c36SJim Ingham { 9726e3d8e7fSEugene Zelenko if (!m_interpreter.RemoveAlias(command_name)) 973ebc09c36SJim Ingham { 974a7015092SGreg Clayton if (m_interpreter.AliasExists (command_name)) 975ebc09c36SJim Ingham result.AppendErrorWithFormat ("Error occurred while attempting to unalias '%s'.\n", 976ebc09c36SJim Ingham command_name); 977ebc09c36SJim Ingham else 978ebc09c36SJim Ingham result.AppendErrorWithFormat ("'%s' is not an existing alias.\n", command_name); 979ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 980ebc09c36SJim Ingham } 981ebc09c36SJim Ingham else 982ebc09c36SJim Ingham result.SetStatus (eReturnStatusSuccessFinishNoResult); 983ebc09c36SJim Ingham } 984ebc09c36SJim Ingham } 985ebc09c36SJim Ingham else 986ebc09c36SJim Ingham { 987ebc09c36SJim Ingham result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a " 988ebc09c36SJim Ingham "current list of commands.\n", 989ebc09c36SJim Ingham command_name); 990ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 991ebc09c36SJim Ingham } 992ebc09c36SJim Ingham } 993ebc09c36SJim Ingham else 994ebc09c36SJim Ingham { 995ebc09c36SJim Ingham result.AppendError ("must call 'unalias' with a valid alias"); 996ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 997ebc09c36SJim Ingham } 998ebc09c36SJim Ingham 999ebc09c36SJim Ingham return result.Succeeded(); 1000ebc09c36SJim Ingham } 1001ebc09c36SJim Ingham }; 1002ebc09c36SJim Ingham 1003b547278cSGreg Clayton #pragma mark CommandObjectCommandsDelete 1004b547278cSGreg Clayton //------------------------------------------------------------------------- 1005b547278cSGreg Clayton // CommandObjectCommandsDelete 1006b547278cSGreg Clayton //------------------------------------------------------------------------- 1007b547278cSGreg Clayton 1008b547278cSGreg Clayton class CommandObjectCommandsDelete : public CommandObjectParsed 1009b547278cSGreg Clayton { 1010b547278cSGreg Clayton public: 1011*7428a18cSKate Stone CommandObjectCommandsDelete(CommandInterpreter &interpreter) 1012*7428a18cSKate Stone : CommandObjectParsed(interpreter, "command delete", 1013*7428a18cSKate Stone "Delete one or more custom commands defined by 'command regex'.", nullptr) 1014b547278cSGreg Clayton { 1015b547278cSGreg Clayton CommandArgumentEntry arg; 1016b547278cSGreg Clayton CommandArgumentData alias_arg; 1017b547278cSGreg Clayton 1018b547278cSGreg Clayton // Define the first (and only) variant of this arg. 1019b547278cSGreg Clayton alias_arg.arg_type = eArgTypeCommandName; 1020b547278cSGreg Clayton alias_arg.arg_repetition = eArgRepeatPlain; 1021b547278cSGreg Clayton 1022b547278cSGreg Clayton // There is only one variant this argument could be; put it into the argument entry. 1023b547278cSGreg Clayton arg.push_back (alias_arg); 1024b547278cSGreg Clayton 1025b547278cSGreg Clayton // Push the data for the first argument into the m_arguments vector. 1026b547278cSGreg Clayton m_arguments.push_back (arg); 1027b547278cSGreg Clayton } 1028b547278cSGreg Clayton 10296e3d8e7fSEugene Zelenko ~CommandObjectCommandsDelete() override = default; 1030b547278cSGreg Clayton 1031b547278cSGreg Clayton protected: 1032b547278cSGreg Clayton bool 103313d21e9aSBruce Mitchener DoExecute (Args& args, CommandReturnObject &result) override 1034b547278cSGreg Clayton { 1035b547278cSGreg Clayton CommandObject::CommandMap::iterator pos; 1036b547278cSGreg Clayton 1037b547278cSGreg Clayton if (args.GetArgumentCount() != 0) 1038b547278cSGreg Clayton { 1039b547278cSGreg Clayton const char *command_name = args.GetArgumentAtIndex(0); 1040b547278cSGreg Clayton if (m_interpreter.CommandExists (command_name)) 1041b547278cSGreg Clayton { 1042b547278cSGreg Clayton if (m_interpreter.RemoveCommand (command_name)) 1043b547278cSGreg Clayton { 1044b547278cSGreg Clayton result.SetStatus (eReturnStatusSuccessFinishNoResult); 1045b547278cSGreg Clayton } 1046b547278cSGreg Clayton else 1047b547278cSGreg Clayton { 1048b547278cSGreg Clayton result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n", 1049b547278cSGreg Clayton command_name); 1050b547278cSGreg Clayton result.SetStatus (eReturnStatusFailed); 1051b547278cSGreg Clayton } 1052b547278cSGreg Clayton } 1053b547278cSGreg Clayton else 1054b547278cSGreg Clayton { 105546d4aa21SEnrico Granata StreamString error_msg_stream; 105646d4aa21SEnrico Granata const bool generate_apropos = true; 105746d4aa21SEnrico Granata const bool generate_type_lookup = false; 105846d4aa21SEnrico Granata CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(&error_msg_stream, 105946d4aa21SEnrico Granata command_name, 106046d4aa21SEnrico Granata nullptr, 106146d4aa21SEnrico Granata nullptr, 106246d4aa21SEnrico Granata generate_apropos, 106346d4aa21SEnrico Granata generate_type_lookup); 106446d4aa21SEnrico Granata result.AppendErrorWithFormat ("%s", error_msg_stream.GetData()); 1065b547278cSGreg Clayton result.SetStatus (eReturnStatusFailed); 1066b547278cSGreg Clayton } 1067b547278cSGreg Clayton } 1068b547278cSGreg Clayton else 1069b547278cSGreg Clayton { 1070*7428a18cSKate Stone result.AppendErrorWithFormat( 1071*7428a18cSKate Stone "must call '%s' with one or more valid user defined regular expression command names", 1072*7428a18cSKate Stone GetCommandName()); 1073b547278cSGreg Clayton result.SetStatus (eReturnStatusFailed); 1074b547278cSGreg Clayton } 1075b547278cSGreg Clayton 1076b547278cSGreg Clayton return result.Succeeded(); 1077b547278cSGreg Clayton } 1078b547278cSGreg Clayton }; 1079b547278cSGreg Clayton 1080de164aaaSGreg Clayton //------------------------------------------------------------------------- 1081de164aaaSGreg Clayton // CommandObjectCommandsAddRegex 1082de164aaaSGreg Clayton //------------------------------------------------------------------------- 10835a988416SJim Ingham #pragma mark CommandObjectCommandsAddRegex 1084de164aaaSGreg Clayton 108544d93782SGreg Clayton class CommandObjectCommandsAddRegex : 108644d93782SGreg Clayton public CommandObjectParsed, 1087ea508635SGreg Clayton public IOHandlerDelegateMultiline 1088de164aaaSGreg Clayton { 1089de164aaaSGreg Clayton public: 1090*7428a18cSKate Stone CommandObjectCommandsAddRegex(CommandInterpreter &interpreter) 1091*7428a18cSKate Stone : CommandObjectParsed(interpreter, "command regex", 1092*7428a18cSKate Stone "Define a custom command in terms of existing commands by matching regular expressions.", 10930e5e5a79SGreg Clayton "command regex <cmd-name> [s/<regex>/<subst>/ ...]"), 1094ea508635SGreg Clayton IOHandlerDelegateMultiline("", IOHandlerDelegate::Completion::LLDBCommand), 1095de164aaaSGreg Clayton m_options(interpreter) 1096de164aaaSGreg Clayton { 1097ea671fbdSKate Stone SetHelpLong(R"( 1098ea671fbdSKate Stone )" "This command allows the user to create powerful regular expression commands \ 1099ea671fbdSKate Stone with substitutions. The regular expressions and substitutions are specified \ 1100ea671fbdSKate Stone using the regular expression substitution format of:" R"( 1101ea671fbdSKate Stone 1102ea671fbdSKate Stone s/<regex>/<subst>/ 1103ea671fbdSKate Stone 1104ea671fbdSKate Stone )" "<regex> is a regular expression that can use parenthesis to capture regular \ 1105ea671fbdSKate Stone expression input and substitute the captured matches in the output using %1 \ 1106ea671fbdSKate Stone for the first match, %2 for the second, and so on." R"( 1107ea671fbdSKate Stone 1108ea671fbdSKate Stone )" "The regular expressions can all be specified on the command line if more than \ 1109ea671fbdSKate Stone one argument is provided. If just the command name is provided on the command \ 1110ea671fbdSKate Stone line, then the regular expressions and substitutions can be entered on separate \ 1111ea671fbdSKate Stone lines, followed by an empty line to terminate the command definition." R"( 1112ea671fbdSKate Stone 1113ea671fbdSKate Stone EXAMPLES 1114ea671fbdSKate Stone 1115ea671fbdSKate Stone )" "The following example will define a regular expression command named 'f' that \ 1116ea671fbdSKate Stone will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \ 1117ea671fbdSKate Stone a number follows 'f':" R"( 1118ea671fbdSKate Stone 1119ea671fbdSKate Stone (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')" 11200e5e5a79SGreg Clayton ); 1121de164aaaSGreg Clayton } 1122de164aaaSGreg Clayton 11236e3d8e7fSEugene Zelenko ~CommandObjectCommandsAddRegex() override = default; 1124de164aaaSGreg Clayton 11255a988416SJim Ingham protected: 1126ea508635SGreg Clayton void 1127ea508635SGreg Clayton IOHandlerActivated (IOHandler &io_handler) override 112844d93782SGreg Clayton { 112944d93782SGreg Clayton StreamFileSP output_sp(io_handler.GetOutputStreamFile()); 113044d93782SGreg Clayton if (output_sp) 113144d93782SGreg Clayton { 113244d93782SGreg Clayton output_sp->PutCString("Enter one of more sed substitution commands in the form: 's/<regex>/<subst>/'.\nTerminate the substitution list with an empty line.\n"); 113344d93782SGreg Clayton output_sp->Flush(); 113444d93782SGreg Clayton } 113544d93782SGreg Clayton } 113644d93782SGreg Clayton 1137ea508635SGreg Clayton void 1138ea508635SGreg Clayton IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override 113944d93782SGreg Clayton { 114044d93782SGreg Clayton io_handler.SetIsDone(true); 11416e3d8e7fSEugene Zelenko if (m_regex_cmd_ap) 114244d93782SGreg Clayton { 114344d93782SGreg Clayton StringList lines; 114444d93782SGreg Clayton if (lines.SplitIntoLines (data)) 114544d93782SGreg Clayton { 114644d93782SGreg Clayton const size_t num_lines = lines.GetSize(); 114744d93782SGreg Clayton bool check_only = false; 114844d93782SGreg Clayton for (size_t i=0; i<num_lines; ++i) 114944d93782SGreg Clayton { 115044d93782SGreg Clayton llvm::StringRef bytes_strref (lines[i]); 115144d93782SGreg Clayton Error error = AppendRegexSubstitution (bytes_strref, check_only); 115244d93782SGreg Clayton if (error.Fail()) 115344d93782SGreg Clayton { 115444d93782SGreg Clayton if (!m_interpreter.GetDebugger().GetCommandInterpreter().GetBatchCommandMode()) 115544d93782SGreg Clayton { 115644d93782SGreg Clayton StreamSP out_stream = m_interpreter.GetDebugger().GetAsyncOutputStream(); 115744d93782SGreg Clayton out_stream->Printf("error: %s\n", error.AsCString()); 115844d93782SGreg Clayton } 115944d93782SGreg Clayton } 116044d93782SGreg Clayton } 116144d93782SGreg Clayton } 116244d93782SGreg Clayton if (m_regex_cmd_ap->HasRegexEntries()) 116344d93782SGreg Clayton { 116444d93782SGreg Clayton CommandObjectSP cmd_sp (m_regex_cmd_ap.release()); 116544d93782SGreg Clayton m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true); 116644d93782SGreg Clayton } 116744d93782SGreg Clayton } 116844d93782SGreg Clayton } 116944d93782SGreg Clayton 1170de164aaaSGreg Clayton bool 1171b0a1814fSEric Christopher DoExecute (Args& command, CommandReturnObject &result) override 1172de164aaaSGreg Clayton { 11735a988416SJim Ingham const size_t argc = command.GetArgumentCount(); 11740e5e5a79SGreg Clayton if (argc == 0) 1175de164aaaSGreg Clayton { 117669c12ccbSJason Molenda result.AppendError ("usage: 'command regex <command-name> [s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n"); 11770e5e5a79SGreg Clayton result.SetStatus (eReturnStatusFailed); 11780e5e5a79SGreg Clayton } 11790e5e5a79SGreg Clayton else 11800e5e5a79SGreg Clayton { 11810e5e5a79SGreg Clayton Error error; 11825a988416SJim Ingham const char *name = command.GetArgumentAtIndex(0); 1183de164aaaSGreg Clayton m_regex_cmd_ap.reset (new CommandObjectRegexCommand (m_interpreter, 1184de164aaaSGreg Clayton name, 1185de164aaaSGreg Clayton m_options.GetHelp (), 1186de164aaaSGreg Clayton m_options.GetSyntax (), 1187b547278cSGreg Clayton 10, 1188b547278cSGreg Clayton 0, 1189b547278cSGreg Clayton true)); 11900e5e5a79SGreg Clayton 11910e5e5a79SGreg Clayton if (argc == 1) 11920e5e5a79SGreg Clayton { 119344d93782SGreg Clayton Debugger &debugger = m_interpreter.GetDebugger(); 1194e30f11d9SKate Stone bool color_prompt = debugger.GetUseColor(); 119544d93782SGreg Clayton const bool multiple_lines = true; // Get multiple lines 119644d93782SGreg Clayton IOHandlerSP io_handler_sp(new IOHandlerEditline(debugger, 1197e30f11d9SKate Stone IOHandler::Type::Other, 119873d80faaSGreg Clayton "lldb-regex", // Name of input reader for history 1199ea508635SGreg Clayton "> ", // Prompt 12006e3d8e7fSEugene Zelenko nullptr, // Continuation prompt 120144d93782SGreg Clayton multiple_lines, 1202e30f11d9SKate Stone color_prompt, 1203f6913cd7SGreg Clayton 0, // Don't show line numbers 120444d93782SGreg Clayton *this)); 120544d93782SGreg Clayton 120644d93782SGreg Clayton if (io_handler_sp) 1207de164aaaSGreg Clayton { 120844d93782SGreg Clayton debugger.PushIOHandler(io_handler_sp); 1209de164aaaSGreg Clayton result.SetStatus (eReturnStatusSuccessFinishNoResult); 1210de164aaaSGreg Clayton } 1211de164aaaSGreg Clayton } 1212de164aaaSGreg Clayton else 1213de164aaaSGreg Clayton { 12140e5e5a79SGreg Clayton for (size_t arg_idx = 1; arg_idx < argc; ++arg_idx) 12150e5e5a79SGreg Clayton { 12165a988416SJim Ingham llvm::StringRef arg_strref (command.GetArgumentAtIndex(arg_idx)); 121744d93782SGreg Clayton bool check_only = false; 121844d93782SGreg Clayton error = AppendRegexSubstitution (arg_strref, check_only); 12190e5e5a79SGreg Clayton if (error.Fail()) 12200e5e5a79SGreg Clayton break; 12210e5e5a79SGreg Clayton } 12220e5e5a79SGreg Clayton 12230e5e5a79SGreg Clayton if (error.Success()) 12240e5e5a79SGreg Clayton { 12250e5e5a79SGreg Clayton AddRegexCommandToInterpreter(); 12260e5e5a79SGreg Clayton } 12270e5e5a79SGreg Clayton } 12280e5e5a79SGreg Clayton if (error.Fail()) 12290e5e5a79SGreg Clayton { 12300e5e5a79SGreg Clayton result.AppendError (error.AsCString()); 1231de164aaaSGreg Clayton result.SetStatus (eReturnStatusFailed); 1232de164aaaSGreg Clayton } 12330e5e5a79SGreg Clayton } 12340e5e5a79SGreg Clayton 1235de164aaaSGreg Clayton return result.Succeeded(); 1236de164aaaSGreg Clayton } 1237de164aaaSGreg Clayton 12380e5e5a79SGreg Clayton Error 123944d93782SGreg Clayton AppendRegexSubstitution (const llvm::StringRef ®ex_sed, bool check_only) 1240de164aaaSGreg Clayton { 12410e5e5a79SGreg Clayton Error error; 12420e5e5a79SGreg Clayton 12436e3d8e7fSEugene Zelenko if (!m_regex_cmd_ap) 1244de164aaaSGreg Clayton { 12450e5e5a79SGreg Clayton error.SetErrorStringWithFormat("invalid regular expression command object for: '%.*s'", 12460e5e5a79SGreg Clayton (int)regex_sed.size(), 12470e5e5a79SGreg Clayton regex_sed.data()); 12480e5e5a79SGreg Clayton return error; 1249de164aaaSGreg Clayton } 12500e5e5a79SGreg Clayton 12510e5e5a79SGreg Clayton size_t regex_sed_size = regex_sed.size(); 12520e5e5a79SGreg Clayton 12530e5e5a79SGreg Clayton if (regex_sed_size <= 1) 12540e5e5a79SGreg Clayton { 12550e5e5a79SGreg Clayton error.SetErrorStringWithFormat("regular expression substitution string is too short: '%.*s'", 12560e5e5a79SGreg Clayton (int)regex_sed.size(), 12570e5e5a79SGreg Clayton regex_sed.data()); 12580e5e5a79SGreg Clayton return error; 12590e5e5a79SGreg Clayton } 12600e5e5a79SGreg Clayton 12610e5e5a79SGreg Clayton if (regex_sed[0] != 's') 12620e5e5a79SGreg Clayton { 12630e5e5a79SGreg Clayton error.SetErrorStringWithFormat("regular expression substitution string doesn't start with 's': '%.*s'", 12640e5e5a79SGreg Clayton (int)regex_sed.size(), 12650e5e5a79SGreg Clayton regex_sed.data()); 12660e5e5a79SGreg Clayton return error; 12670e5e5a79SGreg Clayton } 12680e5e5a79SGreg Clayton const size_t first_separator_char_pos = 1; 12690e5e5a79SGreg Clayton // use the char that follows 's' as the regex separator character 12700e5e5a79SGreg Clayton // so we can have "s/<regex>/<subst>/" or "s|<regex>|<subst>|" 12710e5e5a79SGreg Clayton const char separator_char = regex_sed[first_separator_char_pos]; 12720e5e5a79SGreg Clayton const size_t second_separator_char_pos = regex_sed.find (separator_char, first_separator_char_pos + 1); 12730e5e5a79SGreg Clayton 12740e5e5a79SGreg Clayton if (second_separator_char_pos == std::string::npos) 12750e5e5a79SGreg Clayton { 1276ea508635SGreg Clayton error.SetErrorStringWithFormat("missing second '%c' separator char after '%.*s' in '%.*s'", 12770e5e5a79SGreg Clayton separator_char, 12780e5e5a79SGreg Clayton (int)(regex_sed.size() - first_separator_char_pos - 1), 1279ea508635SGreg Clayton regex_sed.data() + (first_separator_char_pos + 1), 1280ea508635SGreg Clayton (int)regex_sed.size(), 1281ea508635SGreg Clayton regex_sed.data()); 12820e5e5a79SGreg Clayton return error; 12830e5e5a79SGreg Clayton } 12840e5e5a79SGreg Clayton 12850e5e5a79SGreg Clayton const size_t third_separator_char_pos = regex_sed.find (separator_char, second_separator_char_pos + 1); 12860e5e5a79SGreg Clayton 12870e5e5a79SGreg Clayton if (third_separator_char_pos == std::string::npos) 12880e5e5a79SGreg Clayton { 1289ea508635SGreg Clayton error.SetErrorStringWithFormat("missing third '%c' separator char after '%.*s' in '%.*s'", 12900e5e5a79SGreg Clayton separator_char, 12910e5e5a79SGreg Clayton (int)(regex_sed.size() - second_separator_char_pos - 1), 1292ea508635SGreg Clayton regex_sed.data() + (second_separator_char_pos + 1), 1293ea508635SGreg Clayton (int)regex_sed.size(), 1294ea508635SGreg Clayton regex_sed.data()); 12950e5e5a79SGreg Clayton return error; 12960e5e5a79SGreg Clayton } 12970e5e5a79SGreg Clayton 12980e5e5a79SGreg Clayton if (third_separator_char_pos != regex_sed_size - 1) 12990e5e5a79SGreg Clayton { 13000e5e5a79SGreg Clayton // Make sure that everything that follows the last regex 13010e5e5a79SGreg Clayton // separator char 13020e5e5a79SGreg Clayton if (regex_sed.find_first_not_of("\t\n\v\f\r ", third_separator_char_pos + 1) != std::string::npos) 13030e5e5a79SGreg Clayton { 13040e5e5a79SGreg Clayton error.SetErrorStringWithFormat("extra data found after the '%.*s' regular expression substitution string: '%.*s'", 13050e5e5a79SGreg Clayton (int)third_separator_char_pos + 1, 13060e5e5a79SGreg Clayton regex_sed.data(), 13070e5e5a79SGreg Clayton (int)(regex_sed.size() - third_separator_char_pos - 1), 13080e5e5a79SGreg Clayton regex_sed.data() + (third_separator_char_pos + 1)); 13090e5e5a79SGreg Clayton return error; 13100e5e5a79SGreg Clayton } 13110e5e5a79SGreg Clayton } 13120e5e5a79SGreg Clayton else if (first_separator_char_pos + 1 == second_separator_char_pos) 13130e5e5a79SGreg Clayton { 13140e5e5a79SGreg Clayton error.SetErrorStringWithFormat("<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'", 13150e5e5a79SGreg Clayton separator_char, 13160e5e5a79SGreg Clayton separator_char, 13170e5e5a79SGreg Clayton separator_char, 13180e5e5a79SGreg Clayton (int)regex_sed.size(), 13190e5e5a79SGreg Clayton regex_sed.data()); 13200e5e5a79SGreg Clayton return error; 13210e5e5a79SGreg Clayton } 13220e5e5a79SGreg Clayton else if (second_separator_char_pos + 1 == third_separator_char_pos) 13230e5e5a79SGreg Clayton { 13240e5e5a79SGreg Clayton error.SetErrorStringWithFormat("<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'", 13250e5e5a79SGreg Clayton separator_char, 13260e5e5a79SGreg Clayton separator_char, 13270e5e5a79SGreg Clayton separator_char, 13280e5e5a79SGreg Clayton (int)regex_sed.size(), 13290e5e5a79SGreg Clayton regex_sed.data()); 13300e5e5a79SGreg Clayton return error; 13310e5e5a79SGreg Clayton } 133244d93782SGreg Clayton 13336e3d8e7fSEugene Zelenko if (!check_only) 133444d93782SGreg Clayton { 13350e5e5a79SGreg Clayton std::string regex(regex_sed.substr(first_separator_char_pos + 1, second_separator_char_pos - first_separator_char_pos - 1)); 13360e5e5a79SGreg Clayton std::string subst(regex_sed.substr(second_separator_char_pos + 1, third_separator_char_pos - second_separator_char_pos - 1)); 13370e5e5a79SGreg Clayton m_regex_cmd_ap->AddRegexCommand (regex.c_str(), 13380e5e5a79SGreg Clayton subst.c_str()); 133944d93782SGreg Clayton } 13400e5e5a79SGreg Clayton return error; 1341de164aaaSGreg Clayton } 1342de164aaaSGreg Clayton 1343de164aaaSGreg Clayton void 13440e5e5a79SGreg Clayton AddRegexCommandToInterpreter() 1345de164aaaSGreg Clayton { 13466e3d8e7fSEugene Zelenko if (m_regex_cmd_ap) 1347de164aaaSGreg Clayton { 1348de164aaaSGreg Clayton if (m_regex_cmd_ap->HasRegexEntries()) 1349de164aaaSGreg Clayton { 1350de164aaaSGreg Clayton CommandObjectSP cmd_sp (m_regex_cmd_ap.release()); 1351de164aaaSGreg Clayton m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true); 1352de164aaaSGreg Clayton } 1353de164aaaSGreg Clayton } 1354de164aaaSGreg Clayton } 1355de164aaaSGreg Clayton 1356de164aaaSGreg Clayton private: 13577b0992d9SGreg Clayton std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_ap; 1358de164aaaSGreg Clayton 1359de164aaaSGreg Clayton class CommandOptions : public Options 1360de164aaaSGreg Clayton { 1361de164aaaSGreg Clayton public: 1362de164aaaSGreg Clayton CommandOptions (CommandInterpreter &interpreter) : 1363de164aaaSGreg Clayton Options (interpreter) 1364de164aaaSGreg Clayton { 1365de164aaaSGreg Clayton } 1366de164aaaSGreg Clayton 13676e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 1368de164aaaSGreg Clayton 136913d21e9aSBruce Mitchener Error 137013d21e9aSBruce Mitchener SetOptionValue (uint32_t option_idx, const char *option_arg) override 1371de164aaaSGreg Clayton { 1372de164aaaSGreg Clayton Error error; 13733bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 1374de164aaaSGreg Clayton 1375de164aaaSGreg Clayton switch (short_option) 1376de164aaaSGreg Clayton { 1377de164aaaSGreg Clayton case 'h': 1378de164aaaSGreg Clayton m_help.assign (option_arg); 1379de164aaaSGreg Clayton break; 1380de164aaaSGreg Clayton case 's': 1381de164aaaSGreg Clayton m_syntax.assign (option_arg); 1382de164aaaSGreg Clayton break; 1383de164aaaSGreg Clayton default: 138486edbf41SGreg Clayton error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1385de164aaaSGreg Clayton break; 1386de164aaaSGreg Clayton } 1387de164aaaSGreg Clayton 1388de164aaaSGreg Clayton return error; 1389de164aaaSGreg Clayton } 1390de164aaaSGreg Clayton 1391de164aaaSGreg Clayton void 139213d21e9aSBruce Mitchener OptionParsingStarting () override 1393de164aaaSGreg Clayton { 1394de164aaaSGreg Clayton m_help.clear(); 1395de164aaaSGreg Clayton m_syntax.clear(); 1396de164aaaSGreg Clayton } 1397de164aaaSGreg Clayton 1398de164aaaSGreg Clayton const OptionDefinition* 139913d21e9aSBruce Mitchener GetDefinitions () override 1400de164aaaSGreg Clayton { 1401de164aaaSGreg Clayton return g_option_table; 1402de164aaaSGreg Clayton } 1403de164aaaSGreg Clayton 1404de164aaaSGreg Clayton // Options table: Required for subclasses of Options. 1405de164aaaSGreg Clayton 1406de164aaaSGreg Clayton static OptionDefinition g_option_table[]; 1407de164aaaSGreg Clayton 1408de164aaaSGreg Clayton const char * 1409de164aaaSGreg Clayton GetHelp() 1410de164aaaSGreg Clayton { 14116e3d8e7fSEugene Zelenko return (m_help.empty() ? nullptr : m_help.c_str()); 1412de164aaaSGreg Clayton } 14136e3d8e7fSEugene Zelenko 1414de164aaaSGreg Clayton const char * 1415de164aaaSGreg Clayton GetSyntax () 1416de164aaaSGreg Clayton { 14176e3d8e7fSEugene Zelenko return (m_syntax.empty() ? nullptr : m_syntax.c_str()); 1418de164aaaSGreg Clayton } 14196e3d8e7fSEugene Zelenko 1420de164aaaSGreg Clayton protected: 14216e3d8e7fSEugene Zelenko // Instance variables to hold the values for command options. 14226e3d8e7fSEugene Zelenko 1423de164aaaSGreg Clayton std::string m_help; 1424de164aaaSGreg Clayton std::string m_syntax; 1425de164aaaSGreg Clayton }; 1426de164aaaSGreg Clayton 1427b0a1814fSEric Christopher Options * 1428b0a1814fSEric Christopher GetOptions () override 1429de164aaaSGreg Clayton { 1430de164aaaSGreg Clayton return &m_options; 1431de164aaaSGreg Clayton } 1432de164aaaSGreg Clayton 14335a988416SJim Ingham CommandOptions m_options; 1434de164aaaSGreg Clayton }; 1435de164aaaSGreg Clayton 1436de164aaaSGreg Clayton OptionDefinition 1437de164aaaSGreg Clayton CommandObjectCommandsAddRegex::CommandOptions::g_option_table[] = 1438de164aaaSGreg Clayton { 14396e3d8e7fSEugene Zelenko { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "The help text to display for this command."}, 14406e3d8e7fSEugene Zelenko { LLDB_OPT_SET_1, false, "syntax", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "A syntax string showing the typical usage syntax."}, 14416e3d8e7fSEugene Zelenko { 0 , false, nullptr , 0 , 0 , nullptr, nullptr, 0, eArgTypeNone, nullptr } 1442de164aaaSGreg Clayton }; 1443de164aaaSGreg Clayton 14445a988416SJim Ingham class CommandObjectPythonFunction : public CommandObjectRaw 1445223383edSEnrico Granata { 1446223383edSEnrico Granata public: 1447223383edSEnrico Granata CommandObjectPythonFunction (CommandInterpreter &interpreter, 1448223383edSEnrico Granata std::string name, 14490a305db7SEnrico Granata std::string funct, 1450735152e3SEnrico Granata std::string help, 14510a305db7SEnrico Granata ScriptedCommandSynchronicity synch) : 14525a988416SJim Ingham CommandObjectRaw(interpreter, 1453223383edSEnrico Granata name.c_str(), 14546e3d8e7fSEugene Zelenko nullptr, 14556e3d8e7fSEugene Zelenko nullptr), 14560a305db7SEnrico Granata m_function_name(funct), 1457fac939e9SEnrico Granata m_synchro(synch), 1458fac939e9SEnrico Granata m_fetched_help_long(false) 1459223383edSEnrico Granata { 1460735152e3SEnrico Granata if (!help.empty()) 1461735152e3SEnrico Granata SetHelp(help.c_str()); 1462735152e3SEnrico Granata else 1463735152e3SEnrico Granata { 1464735152e3SEnrico Granata StreamString stream; 1465735152e3SEnrico Granata stream.Printf("For more information run 'help %s'",name.c_str()); 1466735152e3SEnrico Granata SetHelp(stream.GetData()); 1467735152e3SEnrico Granata } 1468223383edSEnrico Granata } 1469223383edSEnrico Granata 14706e3d8e7fSEugene Zelenko ~CommandObjectPythonFunction() override = default; 1471223383edSEnrico Granata 147213d21e9aSBruce Mitchener bool 147313d21e9aSBruce Mitchener IsRemovable () const override 14745a988416SJim Ingham { 14755a988416SJim Ingham return true; 14765a988416SJim Ingham } 14775a988416SJim Ingham 14785a988416SJim Ingham const std::string& 14795a988416SJim Ingham GetFunctionName () 14805a988416SJim Ingham { 14815a988416SJim Ingham return m_function_name; 14825a988416SJim Ingham } 14835a988416SJim Ingham 14845a988416SJim Ingham ScriptedCommandSynchronicity 14855a988416SJim Ingham GetSynchronicity () 14865a988416SJim Ingham { 14875a988416SJim Ingham return m_synchro; 14885a988416SJim Ingham } 14895a988416SJim Ingham 149013d21e9aSBruce Mitchener const char * 149113d21e9aSBruce Mitchener GetHelpLong () override 1492fac939e9SEnrico Granata { 1493fac939e9SEnrico Granata if (!m_fetched_help_long) 1494fac939e9SEnrico Granata { 1495fac939e9SEnrico Granata ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter(); 1496fac939e9SEnrico Granata if (scripter) 1497fac939e9SEnrico Granata { 1498fac939e9SEnrico Granata std::string docstring; 1499fac939e9SEnrico Granata m_fetched_help_long = scripter->GetDocumentationForItem(m_function_name.c_str(),docstring); 1500fac939e9SEnrico Granata if (!docstring.empty()) 1501bfb75e9bSEnrico Granata SetHelpLong(docstring.c_str()); 1502fac939e9SEnrico Granata } 1503fac939e9SEnrico Granata } 1504fac939e9SEnrico Granata return CommandObjectRaw::GetHelpLong(); 1505fac939e9SEnrico Granata } 1506fac939e9SEnrico Granata 15075a988416SJim Ingham protected: 150813d21e9aSBruce Mitchener bool 150913d21e9aSBruce Mitchener DoExecute (const char *raw_command_line, CommandReturnObject &result) override 1510223383edSEnrico Granata { 1511223383edSEnrico Granata ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter(); 1512223383edSEnrico Granata 1513223383edSEnrico Granata Error error; 1514223383edSEnrico Granata 151570f11f88SJim Ingham result.SetStatus(eReturnStatusInvalid); 151670f11f88SJim Ingham 15176e3d8e7fSEugene Zelenko if (!scripter || !scripter->RunScriptBasedCommand(m_function_name.c_str(), 1518223383edSEnrico Granata raw_command_line, 15190a305db7SEnrico Granata m_synchro, 1520223383edSEnrico Granata result, 152106be059aSEnrico Granata error, 15226e3d8e7fSEugene Zelenko m_exe_ctx)) 1523223383edSEnrico Granata { 1524223383edSEnrico Granata result.AppendError(error.AsCString()); 1525223383edSEnrico Granata result.SetStatus(eReturnStatusFailed); 1526223383edSEnrico Granata } 1527223383edSEnrico Granata else 152870f11f88SJim Ingham { 152970f11f88SJim Ingham // Don't change the status if the command already set it... 153070f11f88SJim Ingham if (result.GetStatus() == eReturnStatusInvalid) 153170f11f88SJim Ingham { 15326e3d8e7fSEugene Zelenko if (result.GetOutputData() == nullptr || result.GetOutputData()[0] == '\0') 1533223383edSEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 153470f11f88SJim Ingham else 153570f11f88SJim Ingham result.SetStatus(eReturnStatusSuccessFinishResult); 153670f11f88SJim Ingham } 153770f11f88SJim Ingham } 1538223383edSEnrico Granata 1539223383edSEnrico Granata return result.Succeeded(); 1540223383edSEnrico Granata } 1541223383edSEnrico Granata 15426e3d8e7fSEugene Zelenko private: 15436e3d8e7fSEugene Zelenko std::string m_function_name; 15446e3d8e7fSEugene Zelenko ScriptedCommandSynchronicity m_synchro; 15456e3d8e7fSEugene Zelenko bool m_fetched_help_long; 1546223383edSEnrico Granata }; 1547223383edSEnrico Granata 15489fe00e52SEnrico Granata class CommandObjectScriptingObject : public CommandObjectRaw 15499fe00e52SEnrico Granata { 15509fe00e52SEnrico Granata public: 15519fe00e52SEnrico Granata CommandObjectScriptingObject (CommandInterpreter &interpreter, 15529fe00e52SEnrico Granata std::string name, 15530641ca1aSZachary Turner StructuredData::GenericSP cmd_obj_sp, 15549fe00e52SEnrico Granata ScriptedCommandSynchronicity synch) : 15559fe00e52SEnrico Granata CommandObjectRaw(interpreter, 15569fe00e52SEnrico Granata name.c_str(), 15576e3d8e7fSEugene Zelenko nullptr, 15586e3d8e7fSEugene Zelenko nullptr), 15599fe00e52SEnrico Granata m_cmd_obj_sp(cmd_obj_sp), 15606f79bb2dSEnrico Granata m_synchro(synch), 15616f79bb2dSEnrico Granata m_fetched_help_short(false), 15626f79bb2dSEnrico Granata m_fetched_help_long(false) 15639fe00e52SEnrico Granata { 15649fe00e52SEnrico Granata StreamString stream; 15659fe00e52SEnrico Granata stream.Printf("For more information run 'help %s'",name.c_str()); 15669fe00e52SEnrico Granata SetHelp(stream.GetData()); 1567e87764f2SEnrico Granata if (ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter()) 1568e87764f2SEnrico Granata GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp)); 15699fe00e52SEnrico Granata } 15709fe00e52SEnrico Granata 15716e3d8e7fSEugene Zelenko ~CommandObjectScriptingObject() override = default; 15729fe00e52SEnrico Granata 157313d21e9aSBruce Mitchener bool 157413d21e9aSBruce Mitchener IsRemovable () const override 15759fe00e52SEnrico Granata { 15769fe00e52SEnrico Granata return true; 15779fe00e52SEnrico Granata } 15789fe00e52SEnrico Granata 15790641ca1aSZachary Turner StructuredData::GenericSP 15809fe00e52SEnrico Granata GetImplementingObject () 15819fe00e52SEnrico Granata { 15829fe00e52SEnrico Granata return m_cmd_obj_sp; 15839fe00e52SEnrico Granata } 15849fe00e52SEnrico Granata 15859fe00e52SEnrico Granata ScriptedCommandSynchronicity 15869fe00e52SEnrico Granata GetSynchronicity () 15879fe00e52SEnrico Granata { 15889fe00e52SEnrico Granata return m_synchro; 15899fe00e52SEnrico Granata } 15909fe00e52SEnrico Granata 159113d21e9aSBruce Mitchener const char * 159213d21e9aSBruce Mitchener GetHelp () override 15936f79bb2dSEnrico Granata { 15946f79bb2dSEnrico Granata if (!m_fetched_help_short) 15956f79bb2dSEnrico Granata { 15966f79bb2dSEnrico Granata ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter(); 15976f79bb2dSEnrico Granata if (scripter) 15986f79bb2dSEnrico Granata { 15996f79bb2dSEnrico Granata std::string docstring; 16006f79bb2dSEnrico Granata m_fetched_help_short = scripter->GetShortHelpForCommandObject(m_cmd_obj_sp,docstring); 16016f79bb2dSEnrico Granata if (!docstring.empty()) 1602bfb75e9bSEnrico Granata SetHelp(docstring.c_str()); 16036f79bb2dSEnrico Granata } 16046f79bb2dSEnrico Granata } 16056f79bb2dSEnrico Granata return CommandObjectRaw::GetHelp(); 16066f79bb2dSEnrico Granata } 16076f79bb2dSEnrico Granata 160813d21e9aSBruce Mitchener const char * 160913d21e9aSBruce Mitchener GetHelpLong () override 16109fe00e52SEnrico Granata { 16116f79bb2dSEnrico Granata if (!m_fetched_help_long) 16126f79bb2dSEnrico Granata { 16136f79bb2dSEnrico Granata ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter(); 16146f79bb2dSEnrico Granata if (scripter) 16156f79bb2dSEnrico Granata { 16166f79bb2dSEnrico Granata std::string docstring; 16176f79bb2dSEnrico Granata m_fetched_help_long = scripter->GetLongHelpForCommandObject(m_cmd_obj_sp,docstring); 16186f79bb2dSEnrico Granata if (!docstring.empty()) 1619bfb75e9bSEnrico Granata SetHelpLong(docstring.c_str()); 16206f79bb2dSEnrico Granata } 16216f79bb2dSEnrico Granata } 16229fe00e52SEnrico Granata return CommandObjectRaw::GetHelpLong(); 16239fe00e52SEnrico Granata } 16249fe00e52SEnrico Granata 16259fe00e52SEnrico Granata protected: 162613d21e9aSBruce Mitchener bool 162713d21e9aSBruce Mitchener DoExecute (const char *raw_command_line, CommandReturnObject &result) override 16289fe00e52SEnrico Granata { 16299fe00e52SEnrico Granata ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter(); 16309fe00e52SEnrico Granata 16319fe00e52SEnrico Granata Error error; 16329fe00e52SEnrico Granata 16339fe00e52SEnrico Granata result.SetStatus(eReturnStatusInvalid); 16349fe00e52SEnrico Granata 16356e3d8e7fSEugene Zelenko if (!scripter || !scripter->RunScriptBasedCommand(m_cmd_obj_sp, 16369fe00e52SEnrico Granata raw_command_line, 16379fe00e52SEnrico Granata m_synchro, 16389fe00e52SEnrico Granata result, 16399fe00e52SEnrico Granata error, 16406e3d8e7fSEugene Zelenko m_exe_ctx)) 16419fe00e52SEnrico Granata { 16429fe00e52SEnrico Granata result.AppendError(error.AsCString()); 16439fe00e52SEnrico Granata result.SetStatus(eReturnStatusFailed); 16449fe00e52SEnrico Granata } 16459fe00e52SEnrico Granata else 16469fe00e52SEnrico Granata { 16479fe00e52SEnrico Granata // Don't change the status if the command already set it... 16489fe00e52SEnrico Granata if (result.GetStatus() == eReturnStatusInvalid) 16499fe00e52SEnrico Granata { 16506e3d8e7fSEugene Zelenko if (result.GetOutputData() == nullptr || result.GetOutputData()[0] == '\0') 16519fe00e52SEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 16529fe00e52SEnrico Granata else 16539fe00e52SEnrico Granata result.SetStatus(eReturnStatusSuccessFinishResult); 16549fe00e52SEnrico Granata } 16559fe00e52SEnrico Granata } 16569fe00e52SEnrico Granata 16579fe00e52SEnrico Granata return result.Succeeded(); 16589fe00e52SEnrico Granata } 16599fe00e52SEnrico Granata 16606e3d8e7fSEugene Zelenko private: 16616e3d8e7fSEugene Zelenko StructuredData::GenericSP m_cmd_obj_sp; 16626e3d8e7fSEugene Zelenko ScriptedCommandSynchronicity m_synchro; 16636e3d8e7fSEugene Zelenko bool m_fetched_help_short: 1; 16646e3d8e7fSEugene Zelenko bool m_fetched_help_long: 1; 16659fe00e52SEnrico Granata }; 16669fe00e52SEnrico Granata 1667a9dbf432SEnrico Granata //------------------------------------------------------------------------- 1668a9dbf432SEnrico Granata // CommandObjectCommandsScriptImport 1669a9dbf432SEnrico Granata //------------------------------------------------------------------------- 1670a9dbf432SEnrico Granata 16715a988416SJim Ingham class CommandObjectCommandsScriptImport : public CommandObjectParsed 1672a9dbf432SEnrico Granata { 16735a988416SJim Ingham public: 16745a988416SJim Ingham CommandObjectCommandsScriptImport (CommandInterpreter &interpreter) : 16755a988416SJim Ingham CommandObjectParsed(interpreter, 16765a988416SJim Ingham "command script import", 16775a988416SJim Ingham "Import a scripting module in LLDB.", 16786e3d8e7fSEugene Zelenko nullptr), 16795a988416SJim Ingham m_options(interpreter) 16805a988416SJim Ingham { 16815a988416SJim Ingham CommandArgumentEntry arg1; 16825a988416SJim Ingham CommandArgumentData cmd_arg; 16835a988416SJim Ingham 16845a988416SJim Ingham // Define the first (and only) variant of this arg. 16855a988416SJim Ingham cmd_arg.arg_type = eArgTypeFilename; 16863b00e35bSEnrico Granata cmd_arg.arg_repetition = eArgRepeatPlus; 16875a988416SJim Ingham 16885a988416SJim Ingham // There is only one variant this argument could be; put it into the argument entry. 16895a988416SJim Ingham arg1.push_back (cmd_arg); 16905a988416SJim Ingham 16915a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 16925a988416SJim Ingham m_arguments.push_back (arg1); 16935a988416SJim Ingham } 16945a988416SJim Ingham 16956e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptImport() override = default; 16965a988416SJim Ingham 169713d21e9aSBruce Mitchener int 16985a988416SJim Ingham HandleArgumentCompletion (Args &input, 16995a988416SJim Ingham int &cursor_index, 17005a988416SJim Ingham int &cursor_char_position, 17015a988416SJim Ingham OptionElementVector &opt_element_vector, 17025a988416SJim Ingham int match_start_point, 17035a988416SJim Ingham int max_return_elements, 17045a988416SJim Ingham bool &word_complete, 170513d21e9aSBruce Mitchener StringList &matches) override 17065a988416SJim Ingham { 17075a988416SJim Ingham std::string completion_str (input.GetArgumentAtIndex(cursor_index)); 17085a988416SJim Ingham completion_str.erase (cursor_char_position); 17095a988416SJim Ingham 17105a988416SJim Ingham CommandCompletions::InvokeCommonCompletionCallbacks(m_interpreter, 17115a988416SJim Ingham CommandCompletions::eDiskFileCompletion, 17125a988416SJim Ingham completion_str.c_str(), 17135a988416SJim Ingham match_start_point, 17145a988416SJim Ingham max_return_elements, 17156e3d8e7fSEugene Zelenko nullptr, 17165a988416SJim Ingham word_complete, 17175a988416SJim Ingham matches); 17185a988416SJim Ingham return matches.GetSize(); 17195a988416SJim Ingham } 17205a988416SJim Ingham 172113d21e9aSBruce Mitchener Options * 172213d21e9aSBruce Mitchener GetOptions () override 17235a988416SJim Ingham { 17245a988416SJim Ingham return &m_options; 17255a988416SJim Ingham } 17265a988416SJim Ingham 17275a988416SJim Ingham protected: 17280a305db7SEnrico Granata class CommandOptions : public Options 17290a305db7SEnrico Granata { 17300a305db7SEnrico Granata public: 17310a305db7SEnrico Granata CommandOptions (CommandInterpreter &interpreter) : 17320a305db7SEnrico Granata Options (interpreter) 17330a305db7SEnrico Granata { 17340a305db7SEnrico Granata } 17350a305db7SEnrico Granata 17366e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 17370a305db7SEnrico Granata 173813d21e9aSBruce Mitchener Error 173913d21e9aSBruce Mitchener SetOptionValue (uint32_t option_idx, const char *option_arg) override 17400a305db7SEnrico Granata { 17410a305db7SEnrico Granata Error error; 17423bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 17430a305db7SEnrico Granata 17440a305db7SEnrico Granata switch (short_option) 17450a305db7SEnrico Granata { 17460a305db7SEnrico Granata case 'r': 17470a305db7SEnrico Granata m_allow_reload = true; 17480a305db7SEnrico Granata break; 17490a305db7SEnrico Granata default: 17500a305db7SEnrico Granata error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 17510a305db7SEnrico Granata break; 17520a305db7SEnrico Granata } 17530a305db7SEnrico Granata 17540a305db7SEnrico Granata return error; 17550a305db7SEnrico Granata } 17560a305db7SEnrico Granata 17570a305db7SEnrico Granata void 175813d21e9aSBruce Mitchener OptionParsingStarting () override 17590a305db7SEnrico Granata { 1760e0c70f1bSEnrico Granata m_allow_reload = true; 17610a305db7SEnrico Granata } 17620a305db7SEnrico Granata 17630a305db7SEnrico Granata const OptionDefinition* 176413d21e9aSBruce Mitchener GetDefinitions () override 17650a305db7SEnrico Granata { 17660a305db7SEnrico Granata return g_option_table; 17670a305db7SEnrico Granata } 17680a305db7SEnrico Granata 17690a305db7SEnrico Granata // Options table: Required for subclasses of Options. 17700a305db7SEnrico Granata 17710a305db7SEnrico Granata static OptionDefinition g_option_table[]; 17720a305db7SEnrico Granata 17730a305db7SEnrico Granata // Instance variables to hold the values for command options. 17740a305db7SEnrico Granata 17750a305db7SEnrico Granata bool m_allow_reload; 17760a305db7SEnrico Granata }; 17770a305db7SEnrico Granata 1778a9dbf432SEnrico Granata bool 177913d21e9aSBruce Mitchener DoExecute (Args& command, CommandReturnObject &result) override 1780a9dbf432SEnrico Granata { 1781a9dbf432SEnrico Granata if (m_interpreter.GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) 1782a9dbf432SEnrico Granata { 1783a9dbf432SEnrico Granata result.AppendError ("only scripting language supported for module importing is currently Python"); 1784a9dbf432SEnrico Granata result.SetStatus (eReturnStatusFailed); 1785a9dbf432SEnrico Granata return false; 1786a9dbf432SEnrico Granata } 1787a9dbf432SEnrico Granata 17885a988416SJim Ingham size_t argc = command.GetArgumentCount(); 17893b00e35bSEnrico Granata if (0 == argc) 1790a9dbf432SEnrico Granata { 17913b00e35bSEnrico Granata result.AppendError("command script import needs one or more arguments"); 1792a9dbf432SEnrico Granata result.SetStatus (eReturnStatusFailed); 1793a9dbf432SEnrico Granata return false; 1794a9dbf432SEnrico Granata } 1795a9dbf432SEnrico Granata 17960e978481SEd Maste for (size_t i = 0; 17973b00e35bSEnrico Granata i < argc; 17983b00e35bSEnrico Granata i++) 17993b00e35bSEnrico Granata { 18003b00e35bSEnrico Granata std::string path = command.GetArgumentAtIndex(i); 1801a9dbf432SEnrico Granata Error error; 1802a9dbf432SEnrico Granata 1803c9d645d3SGreg Clayton const bool init_session = true; 1804078551c7SEnrico Granata // FIXME: this is necessary because CommandObject::CheckRequirements() assumes that 1805078551c7SEnrico Granata // commands won't ever be recursively invoked, but it's actually possible to craft 1806078551c7SEnrico Granata // a Python script that does other "command script imports" in __lldb_init_module 1807078551c7SEnrico Granata // the real fix is to have recursive commands possible with a CommandInvocation object 1808078551c7SEnrico Granata // separate from the CommandObject itself, so that recursive command invocations 1809078551c7SEnrico Granata // won't stomp on each other (wrt to execution contents, options, and more) 1810078551c7SEnrico Granata m_exe_ctx.Clear(); 1811a9dbf432SEnrico Granata if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule(path.c_str(), 18120a305db7SEnrico Granata m_options.m_allow_reload, 1813c9d645d3SGreg Clayton init_session, 1814a9dbf432SEnrico Granata error)) 1815a9dbf432SEnrico Granata { 1816a9dbf432SEnrico Granata result.SetStatus (eReturnStatusSuccessFinishNoResult); 1817a9dbf432SEnrico Granata } 1818a9dbf432SEnrico Granata else 1819a9dbf432SEnrico Granata { 1820a9dbf432SEnrico Granata result.AppendErrorWithFormat("module importing failed: %s", error.AsCString()); 1821a9dbf432SEnrico Granata result.SetStatus (eReturnStatusFailed); 1822a9dbf432SEnrico Granata } 18233b00e35bSEnrico Granata } 1824a9dbf432SEnrico Granata 1825a9dbf432SEnrico Granata return result.Succeeded(); 1826a9dbf432SEnrico Granata } 18270a305db7SEnrico Granata 18285a988416SJim Ingham CommandOptions m_options; 1829a9dbf432SEnrico Granata }; 1830223383edSEnrico Granata 18310a305db7SEnrico Granata OptionDefinition 18320a305db7SEnrico Granata CommandObjectCommandsScriptImport::CommandOptions::g_option_table[] = 18330a305db7SEnrico Granata { 18346e3d8e7fSEugene Zelenko { LLDB_OPT_SET_1, false, "allow-reload", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow the script to be loaded even if it was already loaded before. This argument exists for backwards compatibility, but reloading is always allowed, whether you specify it or not."}, 18356e3d8e7fSEugene Zelenko { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 18360a305db7SEnrico Granata }; 18370a305db7SEnrico Granata 1838223383edSEnrico Granata //------------------------------------------------------------------------- 1839223383edSEnrico Granata // CommandObjectCommandsScriptAdd 1840223383edSEnrico Granata //------------------------------------------------------------------------- 1841223383edSEnrico Granata 184244d93782SGreg Clayton class CommandObjectCommandsScriptAdd : 184344d93782SGreg Clayton public CommandObjectParsed, 184444d93782SGreg Clayton public IOHandlerDelegateMultiline 1845223383edSEnrico Granata { 18465a988416SJim Ingham public: 18475a988416SJim Ingham CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter) : 18485a988416SJim Ingham CommandObjectParsed(interpreter, 18495a988416SJim Ingham "command script add", 18505a988416SJim Ingham "Add a scripted function as an LLDB command.", 18516e3d8e7fSEugene Zelenko nullptr), 1852c3d874a5SGreg Clayton IOHandlerDelegateMultiline ("DONE"), 18535a988416SJim Ingham m_options (interpreter) 18545a988416SJim Ingham { 18555a988416SJim Ingham CommandArgumentEntry arg1; 18565a988416SJim Ingham CommandArgumentData cmd_arg; 18575a988416SJim Ingham 18585a988416SJim Ingham // Define the first (and only) variant of this arg. 18595a988416SJim Ingham cmd_arg.arg_type = eArgTypeCommandName; 18605a988416SJim Ingham cmd_arg.arg_repetition = eArgRepeatPlain; 18615a988416SJim Ingham 18625a988416SJim Ingham // There is only one variant this argument could be; put it into the argument entry. 18635a988416SJim Ingham arg1.push_back (cmd_arg); 18645a988416SJim Ingham 18655a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 18665a988416SJim Ingham m_arguments.push_back (arg1); 18675a988416SJim Ingham } 18685a988416SJim Ingham 18696e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptAdd() override = default; 18705a988416SJim Ingham 187113d21e9aSBruce Mitchener Options * 187213d21e9aSBruce Mitchener GetOptions () override 18735a988416SJim Ingham { 18745a988416SJim Ingham return &m_options; 18755a988416SJim Ingham } 18765a988416SJim Ingham 18775a988416SJim Ingham protected: 1878223383edSEnrico Granata class CommandOptions : public Options 1879223383edSEnrico Granata { 1880223383edSEnrico Granata public: 1881223383edSEnrico Granata CommandOptions (CommandInterpreter &interpreter) : 18829fe00e52SEnrico Granata Options (interpreter), 18839fe00e52SEnrico Granata m_class_name(), 18849fe00e52SEnrico Granata m_funct_name(), 18859fe00e52SEnrico Granata m_short_help(), 18869fe00e52SEnrico Granata m_synchronicity(eScriptedCommandSynchronicitySynchronous) 1887223383edSEnrico Granata { 1888223383edSEnrico Granata } 1889223383edSEnrico Granata 18906e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 1891223383edSEnrico Granata 189213d21e9aSBruce Mitchener Error 189313d21e9aSBruce Mitchener SetOptionValue (uint32_t option_idx, const char *option_arg) override 1894223383edSEnrico Granata { 1895223383edSEnrico Granata Error error; 18963bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 1897223383edSEnrico Granata 1898223383edSEnrico Granata switch (short_option) 1899223383edSEnrico Granata { 1900223383edSEnrico Granata case 'f': 1901735152e3SEnrico Granata if (option_arg) 1902735152e3SEnrico Granata m_funct_name.assign(option_arg); 1903735152e3SEnrico Granata break; 19049fe00e52SEnrico Granata case 'c': 19059fe00e52SEnrico Granata if (option_arg) 19069fe00e52SEnrico Granata m_class_name.assign(option_arg); 19079fe00e52SEnrico Granata break; 1908735152e3SEnrico Granata case 'h': 1909735152e3SEnrico Granata if (option_arg) 1910735152e3SEnrico Granata m_short_help.assign(option_arg); 1911223383edSEnrico Granata break; 19120a305db7SEnrico Granata case 's': 191344d93782SGreg Clayton m_synchronicity = (ScriptedCommandSynchronicity) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error); 19140a305db7SEnrico Granata if (!error.Success()) 19150a305db7SEnrico Granata error.SetErrorStringWithFormat ("unrecognized value for synchronicity '%s'", option_arg); 19160a305db7SEnrico Granata break; 1917223383edSEnrico Granata default: 191886edbf41SGreg Clayton error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1919223383edSEnrico Granata break; 1920223383edSEnrico Granata } 1921223383edSEnrico Granata 1922223383edSEnrico Granata return error; 1923223383edSEnrico Granata } 1924223383edSEnrico Granata 1925223383edSEnrico Granata void 192613d21e9aSBruce Mitchener OptionParsingStarting () override 1927223383edSEnrico Granata { 19289fe00e52SEnrico Granata m_class_name.clear(); 1929735152e3SEnrico Granata m_funct_name.clear(); 1930735152e3SEnrico Granata m_short_help.clear(); 193144d93782SGreg Clayton m_synchronicity = eScriptedCommandSynchronicitySynchronous; 1932223383edSEnrico Granata } 1933223383edSEnrico Granata 1934223383edSEnrico Granata const OptionDefinition* 193513d21e9aSBruce Mitchener GetDefinitions () override 1936223383edSEnrico Granata { 1937223383edSEnrico Granata return g_option_table; 1938223383edSEnrico Granata } 1939223383edSEnrico Granata 1940223383edSEnrico Granata // Options table: Required for subclasses of Options. 1941223383edSEnrico Granata 1942223383edSEnrico Granata static OptionDefinition g_option_table[]; 1943223383edSEnrico Granata 1944223383edSEnrico Granata // Instance variables to hold the values for command options. 1945223383edSEnrico Granata 19469fe00e52SEnrico Granata std::string m_class_name; 1947223383edSEnrico Granata std::string m_funct_name; 1948735152e3SEnrico Granata std::string m_short_help; 194944d93782SGreg Clayton ScriptedCommandSynchronicity m_synchronicity; 1950223383edSEnrico Granata }; 1951223383edSEnrico Granata 195213d21e9aSBruce Mitchener void 195313d21e9aSBruce Mitchener IOHandlerActivated (IOHandler &io_handler) override 1954223383edSEnrico Granata { 195544d93782SGreg Clayton StreamFileSP output_sp(io_handler.GetOutputStreamFile()); 195644d93782SGreg Clayton if (output_sp) 1957223383edSEnrico Granata { 195844d93782SGreg Clayton output_sp->PutCString(g_python_command_instructions); 195944d93782SGreg Clayton output_sp->Flush(); 1960223383edSEnrico Granata } 1961223383edSEnrico Granata } 1962223383edSEnrico Granata 1963223383edSEnrico Granata 196413d21e9aSBruce Mitchener void 196513d21e9aSBruce Mitchener IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override 1966223383edSEnrico Granata { 196744d93782SGreg Clayton StreamFileSP error_sp = io_handler.GetErrorStreamFile(); 196844d93782SGreg Clayton 196944d93782SGreg Clayton ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); 197044d93782SGreg Clayton if (interpreter) 197144d93782SGreg Clayton { 197244d93782SGreg Clayton 197344d93782SGreg Clayton StringList lines; 197444d93782SGreg Clayton lines.SplitIntoLines(data); 197544d93782SGreg Clayton if (lines.GetSize() > 0) 197644d93782SGreg Clayton { 1977a73b7df7SEnrico Granata std::string funct_name_str; 197844d93782SGreg Clayton if (interpreter->GenerateScriptAliasFunction (lines, funct_name_str)) 1979223383edSEnrico Granata { 1980a73b7df7SEnrico Granata if (funct_name_str.empty()) 1981223383edSEnrico Granata { 198244d93782SGreg Clayton error_sp->Printf ("error: unable to obtain a function name, didn't add python command.\n"); 198344d93782SGreg Clayton error_sp->Flush(); 1984223383edSEnrico Granata } 198544d93782SGreg Clayton else 198644d93782SGreg Clayton { 1987223383edSEnrico Granata // everything should be fine now, let's add this alias 1988223383edSEnrico Granata 1989223383edSEnrico Granata CommandObjectSP command_obj_sp(new CommandObjectPythonFunction (m_interpreter, 1990223383edSEnrico Granata m_cmd_name, 1991a73b7df7SEnrico Granata funct_name_str.c_str(), 1992735152e3SEnrico Granata m_short_help, 199344d93782SGreg Clayton m_synchronicity)); 1994223383edSEnrico Granata 19950a305db7SEnrico Granata if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp, true)) 1996223383edSEnrico Granata { 199744d93782SGreg Clayton error_sp->Printf ("error: unable to add selected command, didn't add python command.\n"); 199844d93782SGreg Clayton error_sp->Flush(); 1999223383edSEnrico Granata } 2000223383edSEnrico Granata } 200144d93782SGreg Clayton } 200244d93782SGreg Clayton else 200344d93782SGreg Clayton { 200444d93782SGreg Clayton error_sp->Printf ("error: unable to create function, didn't add python command.\n"); 200544d93782SGreg Clayton error_sp->Flush(); 200644d93782SGreg Clayton } 200744d93782SGreg Clayton } 200844d93782SGreg Clayton else 200944d93782SGreg Clayton { 201044d93782SGreg Clayton error_sp->Printf ("error: empty function, didn't add python command.\n"); 201144d93782SGreg Clayton error_sp->Flush(); 201244d93782SGreg Clayton } 201344d93782SGreg Clayton } 201444d93782SGreg Clayton else 201544d93782SGreg Clayton { 201644d93782SGreg Clayton error_sp->Printf ("error: script interpreter missing, didn't add python command.\n"); 201744d93782SGreg Clayton error_sp->Flush(); 201844d93782SGreg Clayton } 201944d93782SGreg Clayton 202044d93782SGreg Clayton io_handler.SetIsDone(true); 202144d93782SGreg Clayton } 2022223383edSEnrico Granata 20235a988416SJim Ingham protected: 2024223383edSEnrico Granata bool 202513d21e9aSBruce Mitchener DoExecute (Args& command, CommandReturnObject &result) override 2026223383edSEnrico Granata { 202799f0b8f9SEnrico Granata if (m_interpreter.GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) 202899f0b8f9SEnrico Granata { 202999f0b8f9SEnrico Granata result.AppendError ("only scripting language supported for scripted commands is currently Python"); 203099f0b8f9SEnrico Granata result.SetStatus (eReturnStatusFailed); 203199f0b8f9SEnrico Granata return false; 203299f0b8f9SEnrico Granata } 203399f0b8f9SEnrico Granata 20345a988416SJim Ingham size_t argc = command.GetArgumentCount(); 2035223383edSEnrico Granata 2036223383edSEnrico Granata if (argc != 1) 2037223383edSEnrico Granata { 2038223383edSEnrico Granata result.AppendError ("'command script add' requires one argument"); 2039223383edSEnrico Granata result.SetStatus (eReturnStatusFailed); 2040223383edSEnrico Granata return false; 2041223383edSEnrico Granata } 2042223383edSEnrico Granata 2043735152e3SEnrico Granata // Store the options in case we get multi-line input 204444d93782SGreg Clayton m_cmd_name = command.GetArgumentAtIndex(0); 2045735152e3SEnrico Granata m_short_help.assign(m_options.m_short_help); 204644d93782SGreg Clayton m_synchronicity = m_options.m_synchronicity; 2047223383edSEnrico Granata 20489fe00e52SEnrico Granata if (m_options.m_class_name.empty()) 20499fe00e52SEnrico Granata { 2050223383edSEnrico Granata if (m_options.m_funct_name.empty()) 2051223383edSEnrico Granata { 205244d93782SGreg Clayton m_interpreter.GetPythonCommandsFromIOHandler(" ", // Prompt 205344d93782SGreg Clayton *this, // IOHandlerDelegate 205444d93782SGreg Clayton true, // Run IOHandler in async mode 20556e3d8e7fSEugene Zelenko nullptr); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions 2056223383edSEnrico Granata } 2057223383edSEnrico Granata else 2058223383edSEnrico Granata { 20590a305db7SEnrico Granata CommandObjectSP new_cmd(new CommandObjectPythonFunction(m_interpreter, 206044d93782SGreg Clayton m_cmd_name, 20610a305db7SEnrico Granata m_options.m_funct_name, 2062735152e3SEnrico Granata m_options.m_short_help, 206344d93782SGreg Clayton m_synchronicity)); 206444d93782SGreg Clayton if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) 2065223383edSEnrico Granata { 2066223383edSEnrico Granata result.SetStatus (eReturnStatusSuccessFinishNoResult); 2067223383edSEnrico Granata } 2068223383edSEnrico Granata else 2069223383edSEnrico Granata { 2070223383edSEnrico Granata result.AppendError("cannot add command"); 2071223383edSEnrico Granata result.SetStatus (eReturnStatusFailed); 2072223383edSEnrico Granata } 2073223383edSEnrico Granata } 20749fe00e52SEnrico Granata } 20759fe00e52SEnrico Granata else 20769fe00e52SEnrico Granata { 20779fe00e52SEnrico Granata ScriptInterpreter *interpreter = GetCommandInterpreter().GetScriptInterpreter(); 20789fe00e52SEnrico Granata if (!interpreter) 20799fe00e52SEnrico Granata { 20809fe00e52SEnrico Granata result.AppendError("cannot find ScriptInterpreter"); 20819fe00e52SEnrico Granata result.SetStatus(eReturnStatusFailed); 20829fe00e52SEnrico Granata return false; 20839fe00e52SEnrico Granata } 20849fe00e52SEnrico Granata 20859fe00e52SEnrico Granata auto cmd_obj_sp = interpreter->CreateScriptCommandObject(m_options.m_class_name.c_str()); 20869fe00e52SEnrico Granata if (!cmd_obj_sp) 20879fe00e52SEnrico Granata { 20889fe00e52SEnrico Granata result.AppendError("cannot create helper object"); 20899fe00e52SEnrico Granata result.SetStatus(eReturnStatusFailed); 20909fe00e52SEnrico Granata return false; 20919fe00e52SEnrico Granata } 20929fe00e52SEnrico Granata 20939fe00e52SEnrico Granata CommandObjectSP new_cmd(new CommandObjectScriptingObject(m_interpreter, 20949fe00e52SEnrico Granata m_cmd_name, 20959fe00e52SEnrico Granata cmd_obj_sp, 20969fe00e52SEnrico Granata m_synchronicity)); 20979fe00e52SEnrico Granata if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) 20989fe00e52SEnrico Granata { 20999fe00e52SEnrico Granata result.SetStatus (eReturnStatusSuccessFinishNoResult); 21009fe00e52SEnrico Granata } 21019fe00e52SEnrico Granata else 21029fe00e52SEnrico Granata { 21039fe00e52SEnrico Granata result.AppendError("cannot add command"); 21049fe00e52SEnrico Granata result.SetStatus (eReturnStatusFailed); 21059fe00e52SEnrico Granata } 21069fe00e52SEnrico Granata } 2107223383edSEnrico Granata 2108223383edSEnrico Granata return result.Succeeded(); 2109223383edSEnrico Granata } 21105a988416SJim Ingham 21115a988416SJim Ingham CommandOptions m_options; 211244d93782SGreg Clayton std::string m_cmd_name; 2113735152e3SEnrico Granata std::string m_short_help; 211444d93782SGreg Clayton ScriptedCommandSynchronicity m_synchronicity; 2115223383edSEnrico Granata }; 2116223383edSEnrico Granata 21170a305db7SEnrico Granata static OptionEnumValueElement g_script_synchro_type[] = 21180a305db7SEnrico Granata { 21190a305db7SEnrico Granata { eScriptedCommandSynchronicitySynchronous, "synchronous", "Run synchronous"}, 21200a305db7SEnrico Granata { eScriptedCommandSynchronicityAsynchronous, "asynchronous", "Run asynchronous"}, 21210a305db7SEnrico Granata { eScriptedCommandSynchronicityCurrentValue, "current", "Do not alter current setting"}, 21226e3d8e7fSEugene Zelenko { 0, nullptr, nullptr } 21230a305db7SEnrico Granata }; 21240a305db7SEnrico Granata 2125223383edSEnrico Granata OptionDefinition 2126223383edSEnrico Granata CommandObjectCommandsScriptAdd::CommandOptions::g_option_table[] = 2127223383edSEnrico Granata { 21286e3d8e7fSEugene Zelenko { LLDB_OPT_SET_1, false, "function", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name."}, 21296e3d8e7fSEugene Zelenko { LLDB_OPT_SET_2, false, "class", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonClass, "Name of the Python class to bind to this command name."}, 21306e3d8e7fSEugene Zelenko { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "The help text to display for this command."}, 21316e3d8e7fSEugene Zelenko { LLDB_OPT_SET_ALL, false, "synchronicity", 's', OptionParser::eRequiredArgument, nullptr, g_script_synchro_type, 0, eArgTypeScriptedCommandSynchronicity, "Set the synchronicity of this command's executions with regard to LLDB event system."}, 21326e3d8e7fSEugene Zelenko { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 2133223383edSEnrico Granata }; 2134223383edSEnrico Granata 2135223383edSEnrico Granata //------------------------------------------------------------------------- 2136223383edSEnrico Granata // CommandObjectCommandsScriptList 2137223383edSEnrico Granata //------------------------------------------------------------------------- 2138223383edSEnrico Granata 21395a988416SJim Ingham class CommandObjectCommandsScriptList : public CommandObjectParsed 2140223383edSEnrico Granata { 2141223383edSEnrico Granata public: 2142223383edSEnrico Granata CommandObjectCommandsScriptList(CommandInterpreter &interpreter) : 21435a988416SJim Ingham CommandObjectParsed(interpreter, 2144223383edSEnrico Granata "command script list", 2145223383edSEnrico Granata "List defined scripted commands.", 21466e3d8e7fSEugene Zelenko nullptr) 2147223383edSEnrico Granata { 2148223383edSEnrico Granata } 2149223383edSEnrico Granata 21506e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptList() override = default; 2151223383edSEnrico Granata 2152223383edSEnrico Granata bool 215313d21e9aSBruce Mitchener DoExecute (Args& command, CommandReturnObject &result) override 2154223383edSEnrico Granata { 2155223383edSEnrico Granata m_interpreter.GetHelp(result, 2156223383edSEnrico Granata CommandInterpreter::eCommandTypesUserDef); 2157223383edSEnrico Granata 2158223383edSEnrico Granata result.SetStatus (eReturnStatusSuccessFinishResult); 2159223383edSEnrico Granata 2160223383edSEnrico Granata return true; 2161223383edSEnrico Granata } 2162223383edSEnrico Granata }; 2163223383edSEnrico Granata 2164223383edSEnrico Granata //------------------------------------------------------------------------- 2165223383edSEnrico Granata // CommandObjectCommandsScriptClear 2166223383edSEnrico Granata //------------------------------------------------------------------------- 2167223383edSEnrico Granata 21685a988416SJim Ingham class CommandObjectCommandsScriptClear : public CommandObjectParsed 2169223383edSEnrico Granata { 2170223383edSEnrico Granata public: 2171223383edSEnrico Granata CommandObjectCommandsScriptClear(CommandInterpreter &interpreter) : 21725a988416SJim Ingham CommandObjectParsed(interpreter, 2173223383edSEnrico Granata "command script clear", 2174223383edSEnrico Granata "Delete all scripted commands.", 21756e3d8e7fSEugene Zelenko nullptr) 2176223383edSEnrico Granata { 2177223383edSEnrico Granata } 2178223383edSEnrico Granata 21796e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptClear() override = default; 2180223383edSEnrico Granata 21815a988416SJim Ingham protected: 2182223383edSEnrico Granata bool 218313d21e9aSBruce Mitchener DoExecute (Args& command, CommandReturnObject &result) override 2184223383edSEnrico Granata { 2185223383edSEnrico Granata m_interpreter.RemoveAllUser(); 2186223383edSEnrico Granata 2187223383edSEnrico Granata result.SetStatus (eReturnStatusSuccessFinishResult); 2188223383edSEnrico Granata 2189223383edSEnrico Granata return true; 2190223383edSEnrico Granata } 2191223383edSEnrico Granata }; 2192223383edSEnrico Granata 2193223383edSEnrico Granata //------------------------------------------------------------------------- 2194223383edSEnrico Granata // CommandObjectCommandsScriptDelete 2195223383edSEnrico Granata //------------------------------------------------------------------------- 2196223383edSEnrico Granata 21975a988416SJim Ingham class CommandObjectCommandsScriptDelete : public CommandObjectParsed 2198223383edSEnrico Granata { 2199223383edSEnrico Granata public: 2200223383edSEnrico Granata CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter) : 22015a988416SJim Ingham CommandObjectParsed(interpreter, 2202223383edSEnrico Granata "command script delete", 2203223383edSEnrico Granata "Delete a scripted command.", 22046e3d8e7fSEugene Zelenko nullptr) 2205223383edSEnrico Granata { 2206223383edSEnrico Granata CommandArgumentEntry arg1; 2207223383edSEnrico Granata CommandArgumentData cmd_arg; 2208223383edSEnrico Granata 2209223383edSEnrico Granata // Define the first (and only) variant of this arg. 2210223383edSEnrico Granata cmd_arg.arg_type = eArgTypeCommandName; 2211223383edSEnrico Granata cmd_arg.arg_repetition = eArgRepeatPlain; 2212223383edSEnrico Granata 2213223383edSEnrico Granata // There is only one variant this argument could be; put it into the argument entry. 2214223383edSEnrico Granata arg1.push_back (cmd_arg); 2215223383edSEnrico Granata 2216223383edSEnrico Granata // Push the data for the first argument into the m_arguments vector. 2217223383edSEnrico Granata m_arguments.push_back (arg1); 2218223383edSEnrico Granata } 2219223383edSEnrico Granata 22206e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptDelete() override = default; 2221223383edSEnrico Granata 22225a988416SJim Ingham protected: 2223223383edSEnrico Granata bool 222413d21e9aSBruce Mitchener DoExecute (Args& command, CommandReturnObject &result) override 2225223383edSEnrico Granata { 2226223383edSEnrico Granata 22275a988416SJim Ingham size_t argc = command.GetArgumentCount(); 2228223383edSEnrico Granata 2229223383edSEnrico Granata if (argc != 1) 2230223383edSEnrico Granata { 2231223383edSEnrico Granata result.AppendError ("'command script delete' requires one argument"); 2232223383edSEnrico Granata result.SetStatus (eReturnStatusFailed); 2233223383edSEnrico Granata return false; 2234223383edSEnrico Granata } 2235223383edSEnrico Granata 22365a988416SJim Ingham const char* cmd_name = command.GetArgumentAtIndex(0); 2237223383edSEnrico Granata 2238223383edSEnrico Granata if (cmd_name && *cmd_name && m_interpreter.HasUserCommands() && m_interpreter.UserCommandExists(cmd_name)) 2239223383edSEnrico Granata { 2240223383edSEnrico Granata m_interpreter.RemoveUser(cmd_name); 2241223383edSEnrico Granata result.SetStatus (eReturnStatusSuccessFinishResult); 2242223383edSEnrico Granata } 2243223383edSEnrico Granata else 2244223383edSEnrico Granata { 2245223383edSEnrico Granata result.AppendErrorWithFormat ("command %s not found", cmd_name); 2246223383edSEnrico Granata result.SetStatus (eReturnStatusFailed); 2247223383edSEnrico Granata } 2248223383edSEnrico Granata 2249223383edSEnrico Granata return result.Succeeded(); 2250223383edSEnrico Granata } 2251223383edSEnrico Granata }; 2252223383edSEnrico Granata 2253223383edSEnrico Granata #pragma mark CommandObjectMultiwordCommandsScript 2254223383edSEnrico Granata 2255223383edSEnrico Granata //------------------------------------------------------------------------- 2256223383edSEnrico Granata // CommandObjectMultiwordCommandsScript 2257223383edSEnrico Granata //------------------------------------------------------------------------- 2258223383edSEnrico Granata 2259223383edSEnrico Granata class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword 2260223383edSEnrico Granata { 2261223383edSEnrico Granata public: 2262*7428a18cSKate Stone CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter) 2263*7428a18cSKate Stone : CommandObjectMultiword(interpreter, "command script", 2264*7428a18cSKate Stone "Commands for managing custom commands implemented by interpreter scripts.", 2265223383edSEnrico Granata "command script <subcommand> [<subcommand-options>]") 2266223383edSEnrico Granata { 2267223383edSEnrico Granata LoadSubCommand ("add", CommandObjectSP (new CommandObjectCommandsScriptAdd (interpreter))); 2268223383edSEnrico Granata LoadSubCommand ("delete", CommandObjectSP (new CommandObjectCommandsScriptDelete (interpreter))); 2269223383edSEnrico Granata LoadSubCommand ("clear", CommandObjectSP (new CommandObjectCommandsScriptClear (interpreter))); 2270223383edSEnrico Granata LoadSubCommand ("list", CommandObjectSP (new CommandObjectCommandsScriptList (interpreter))); 2271a9dbf432SEnrico Granata LoadSubCommand ("import", CommandObjectSP (new CommandObjectCommandsScriptImport (interpreter))); 2272223383edSEnrico Granata } 2273223383edSEnrico Granata 22746e3d8e7fSEugene Zelenko ~CommandObjectMultiwordCommandsScript() override = default; 2275223383edSEnrico Granata }; 2276223383edSEnrico Granata 2277ebc09c36SJim Ingham #pragma mark CommandObjectMultiwordCommands 2278ebc09c36SJim Ingham 2279ebc09c36SJim Ingham //------------------------------------------------------------------------- 2280ebc09c36SJim Ingham // CommandObjectMultiwordCommands 2281ebc09c36SJim Ingham //------------------------------------------------------------------------- 2282ebc09c36SJim Ingham 2283*7428a18cSKate Stone CommandObjectMultiwordCommands::CommandObjectMultiwordCommands(CommandInterpreter &interpreter) 2284*7428a18cSKate Stone : CommandObjectMultiword(interpreter, "command", "Commands for managing custom LLDB commands.", 22850e5e5a79SGreg Clayton "command <subcommand> [<subcommand-options>]") 2286ebc09c36SJim Ingham { 2287a7015092SGreg Clayton LoadSubCommand ("source", CommandObjectSP (new CommandObjectCommandsSource (interpreter))); 2288a7015092SGreg Clayton LoadSubCommand ("alias", CommandObjectSP (new CommandObjectCommandsAlias (interpreter))); 2289a7015092SGreg Clayton LoadSubCommand ("unalias", CommandObjectSP (new CommandObjectCommandsUnalias (interpreter))); 2290b547278cSGreg Clayton LoadSubCommand ("delete", CommandObjectSP (new CommandObjectCommandsDelete (interpreter))); 2291de164aaaSGreg Clayton LoadSubCommand ("regex", CommandObjectSP (new CommandObjectCommandsAddRegex (interpreter))); 2292a5a97ebeSJim Ingham LoadSubCommand ("history", CommandObjectSP (new CommandObjectCommandsHistory (interpreter))); 2293223383edSEnrico Granata LoadSubCommand ("script", CommandObjectSP (new CommandObjectMultiwordCommandsScript (interpreter))); 2294ebc09c36SJim Ingham } 2295ebc09c36SJim Ingham 22966e3d8e7fSEugene Zelenko CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default; 2297