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), 47e1cfbc79STodd Fiala m_options() 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: 63e1cfbc79STodd Fiala CommandOptions() : 64e1cfbc79STodd Fiala Options(), 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 75e1cfbc79STodd Fiala SetOptionValue (uint32_t option_idx, const char *option_arg, 76e1cfbc79STodd Fiala ExecutionContext *execution_context) override 77a5a97ebeSJim Ingham { 78a5a97ebeSJim Ingham Error error; 793bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 80a5a97ebeSJim Ingham 81a5a97ebeSJim Ingham switch (short_option) 82a5a97ebeSJim Ingham { 83a5a97ebeSJim Ingham case 'c': 84c95f7e2aSPavel Labath error = m_count.SetValueFromString(option_arg,eVarSetOperationAssign); 85a5a97ebeSJim Ingham break; 86a5a97ebeSJim Ingham case 's': 877594f14fSEnrico Granata if (option_arg && strcmp("end", option_arg) == 0) 887594f14fSEnrico Granata { 897594f14fSEnrico Granata m_start_idx.SetCurrentValue(UINT64_MAX); 907594f14fSEnrico Granata m_start_idx.SetOptionWasSet(); 917594f14fSEnrico Granata } 927594f14fSEnrico Granata else 93c95f7e2aSPavel Labath error = m_start_idx.SetValueFromString(option_arg,eVarSetOperationAssign); 947594f14fSEnrico Granata break; 957594f14fSEnrico Granata case 'e': 96c95f7e2aSPavel Labath error = m_stop_idx.SetValueFromString(option_arg,eVarSetOperationAssign); 977594f14fSEnrico Granata break; 9863123b64SEnrico Granata case 'C': 9963123b64SEnrico Granata m_clear.SetCurrentValue(true); 10063123b64SEnrico Granata m_clear.SetOptionWasSet(); 101a5a97ebeSJim Ingham break; 102a5a97ebeSJim Ingham default: 10386edbf41SGreg Clayton error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 104a5a97ebeSJim Ingham break; 105a5a97ebeSJim Ingham } 106a5a97ebeSJim Ingham 107a5a97ebeSJim Ingham return error; 108a5a97ebeSJim Ingham } 109a5a97ebeSJim Ingham 110a5a97ebeSJim Ingham void 111e1cfbc79STodd Fiala OptionParsingStarting (ExecutionContext *execution_context) override 112a5a97ebeSJim Ingham { 1137594f14fSEnrico Granata m_start_idx.Clear(); 1147594f14fSEnrico Granata m_stop_idx.Clear(); 1157594f14fSEnrico Granata m_count.Clear(); 11663123b64SEnrico Granata m_clear.Clear(); 117a5a97ebeSJim Ingham } 118a5a97ebeSJim Ingham 119a5a97ebeSJim Ingham const OptionDefinition* 12013d21e9aSBruce Mitchener GetDefinitions () override 121a5a97ebeSJim Ingham { 122a5a97ebeSJim Ingham return g_option_table; 123a5a97ebeSJim Ingham } 124a5a97ebeSJim Ingham 125a5a97ebeSJim Ingham // Options table: Required for subclasses of Options. 126a5a97ebeSJim Ingham 127a5a97ebeSJim Ingham static OptionDefinition g_option_table[]; 128a5a97ebeSJim Ingham 129a5a97ebeSJim Ingham // Instance variables to hold the values for command options. 130a5a97ebeSJim Ingham 1317594f14fSEnrico Granata OptionValueUInt64 m_start_idx; 1327594f14fSEnrico Granata OptionValueUInt64 m_stop_idx; 1337594f14fSEnrico Granata OptionValueUInt64 m_count; 13463123b64SEnrico Granata OptionValueBoolean m_clear; 135a5a97ebeSJim Ingham }; 136a5a97ebeSJim Ingham 137a5a97ebeSJim Ingham bool 13813d21e9aSBruce Mitchener DoExecute (Args& command, CommandReturnObject &result) override 139a5a97ebeSJim Ingham { 14063123b64SEnrico Granata if (m_options.m_clear.GetCurrentValue() && m_options.m_clear.OptionWasSet()) 1417594f14fSEnrico Granata { 1427594f14fSEnrico Granata m_interpreter.GetCommandHistory().Clear(); 1437594f14fSEnrico Granata result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); 1447594f14fSEnrico Granata } 1457594f14fSEnrico Granata else 1467594f14fSEnrico Granata { 1477594f14fSEnrico Granata if (m_options.m_start_idx.OptionWasSet() && m_options.m_stop_idx.OptionWasSet() && m_options.m_count.OptionWasSet()) 1487594f14fSEnrico Granata { 1497594f14fSEnrico Granata result.AppendError("--count, --start-index and --end-index cannot be all specified in the same invocation"); 1507594f14fSEnrico Granata result.SetStatus(lldb::eReturnStatusFailed); 1517594f14fSEnrico Granata } 1527594f14fSEnrico Granata else 1537594f14fSEnrico Granata { 15484400ec7SVirgile Bello std::pair<bool,uint64_t> start_idx(m_options.m_start_idx.OptionWasSet(),m_options.m_start_idx.GetCurrentValue()); 15584400ec7SVirgile Bello std::pair<bool,uint64_t> stop_idx(m_options.m_stop_idx.OptionWasSet(),m_options.m_stop_idx.GetCurrentValue()); 15684400ec7SVirgile Bello std::pair<bool,uint64_t> count(m_options.m_count.OptionWasSet(),m_options.m_count.GetCurrentValue()); 157a5a97ebeSJim Ingham 1587594f14fSEnrico Granata const CommandHistory& history(m_interpreter.GetCommandHistory()); 1597594f14fSEnrico Granata 1607594f14fSEnrico Granata if (start_idx.first && start_idx.second == UINT64_MAX) 1617594f14fSEnrico Granata { 1627594f14fSEnrico Granata if (count.first) 1637594f14fSEnrico Granata { 1647594f14fSEnrico Granata start_idx.second = history.GetSize() - count.second; 1657594f14fSEnrico Granata stop_idx.second = history.GetSize() - 1; 1667594f14fSEnrico Granata } 1677594f14fSEnrico Granata else if (stop_idx.first) 1687594f14fSEnrico Granata { 1697594f14fSEnrico Granata start_idx.second = stop_idx.second; 1707594f14fSEnrico Granata stop_idx.second = history.GetSize() - 1; 1717594f14fSEnrico Granata } 1727594f14fSEnrico Granata else 1737594f14fSEnrico Granata { 1747594f14fSEnrico Granata start_idx.second = 0; 1757594f14fSEnrico Granata stop_idx.second = history.GetSize() - 1; 1767594f14fSEnrico Granata } 1777594f14fSEnrico Granata } 1787594f14fSEnrico Granata else 1797594f14fSEnrico Granata { 1807594f14fSEnrico Granata if (!start_idx.first && !stop_idx.first && !count.first) 1817594f14fSEnrico Granata { 1827594f14fSEnrico Granata start_idx.second = 0; 1837594f14fSEnrico Granata stop_idx.second = history.GetSize() - 1; 1847594f14fSEnrico Granata } 1857594f14fSEnrico Granata else if (start_idx.first) 1867594f14fSEnrico Granata { 1877594f14fSEnrico Granata if (count.first) 1887594f14fSEnrico Granata { 1897594f14fSEnrico Granata stop_idx.second = start_idx.second + count.second - 1; 1907594f14fSEnrico Granata } 1917594f14fSEnrico Granata else if (!stop_idx.first) 1927594f14fSEnrico Granata { 1937594f14fSEnrico Granata stop_idx.second = history.GetSize() - 1; 1947594f14fSEnrico Granata } 1957594f14fSEnrico Granata } 1967594f14fSEnrico Granata else if (stop_idx.first) 1977594f14fSEnrico Granata { 1987594f14fSEnrico Granata if (count.first) 1997594f14fSEnrico Granata { 2007594f14fSEnrico Granata if (stop_idx.second >= count.second) 2017594f14fSEnrico Granata start_idx.second = stop_idx.second - count.second + 1; 2027594f14fSEnrico Granata else 2037594f14fSEnrico Granata start_idx.second = 0; 2047594f14fSEnrico Granata } 2057594f14fSEnrico Granata } 2067594f14fSEnrico Granata else /* if (count.first) */ 2077594f14fSEnrico Granata { 2087594f14fSEnrico Granata start_idx.second = 0; 2097594f14fSEnrico Granata stop_idx.second = count.second - 1; 2107594f14fSEnrico Granata } 2117594f14fSEnrico Granata } 2127594f14fSEnrico Granata history.Dump(result.GetOutputStream(), start_idx.second, stop_idx.second); 2137594f14fSEnrico Granata } 2147594f14fSEnrico Granata } 215a5a97ebeSJim Ingham return result.Succeeded(); 216a5a97ebeSJim Ingham 217a5a97ebeSJim Ingham } 2185a988416SJim Ingham 2195a988416SJim Ingham CommandOptions m_options; 220a5a97ebeSJim Ingham }; 221a5a97ebeSJim Ingham 222a5a97ebeSJim Ingham OptionDefinition 223a5a97ebeSJim Ingham CommandObjectCommandsHistory::CommandOptions::g_option_table[] = 224a5a97ebeSJim Ingham { 225*ac9c3a62SKate Stone // clang-format off 2266e3d8e7fSEugene Zelenko {LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "How many history commands to print."}, 2276e3d8e7fSEugene 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)."}, 2286e3d8e7fSEugene Zelenko {LLDB_OPT_SET_1, false, "end-index", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands."}, 2296e3d8e7fSEugene Zelenko {LLDB_OPT_SET_2, false, "clear", 'C', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Clears the current command history."}, 2306e3d8e7fSEugene Zelenko {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} 231*ac9c3a62SKate Stone // clang-format on 232a5a97ebeSJim Ingham }; 233a5a97ebeSJim Ingham 234a5a97ebeSJim Ingham //------------------------------------------------------------------------- 235a5a97ebeSJim Ingham // CommandObjectCommandsSource 236a5a97ebeSJim Ingham //------------------------------------------------------------------------- 237a5a97ebeSJim Ingham 2385a988416SJim Ingham class CommandObjectCommandsSource : public CommandObjectParsed 239ebc09c36SJim Ingham { 2405a988416SJim Ingham public: 2417428a18cSKate Stone CommandObjectCommandsSource(CommandInterpreter &interpreter) 2427428a18cSKate Stone : CommandObjectParsed(interpreter, "command source", "Read and execute LLDB commands from the file <filename>.", 2436e3d8e7fSEugene Zelenko nullptr), 244e1cfbc79STodd Fiala m_options() 2455a988416SJim Ingham { 2465a988416SJim Ingham CommandArgumentEntry arg; 2475a988416SJim Ingham CommandArgumentData file_arg; 2485a988416SJim Ingham 2495a988416SJim Ingham // Define the first (and only) variant of this arg. 2505a988416SJim Ingham file_arg.arg_type = eArgTypeFilename; 2515a988416SJim Ingham file_arg.arg_repetition = eArgRepeatPlain; 2525a988416SJim Ingham 2535a988416SJim Ingham // There is only one variant this argument could be; put it into the argument entry. 2545a988416SJim Ingham arg.push_back (file_arg); 2555a988416SJim Ingham 2565a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 2575a988416SJim Ingham m_arguments.push_back (arg); 2585a988416SJim Ingham } 2595a988416SJim Ingham 2606e3d8e7fSEugene Zelenko ~CommandObjectCommandsSource() override = default; 2615a988416SJim Ingham 26213d21e9aSBruce Mitchener const char* 26313d21e9aSBruce Mitchener GetRepeatCommand (Args ¤t_command_args, uint32_t index) override 2645a988416SJim Ingham { 2655a988416SJim Ingham return ""; 2665a988416SJim Ingham } 2675a988416SJim Ingham 26813d21e9aSBruce Mitchener int 2695a988416SJim Ingham HandleArgumentCompletion (Args &input, 2705a988416SJim Ingham int &cursor_index, 2715a988416SJim Ingham int &cursor_char_position, 2725a988416SJim Ingham OptionElementVector &opt_element_vector, 2735a988416SJim Ingham int match_start_point, 2745a988416SJim Ingham int max_return_elements, 2755a988416SJim Ingham bool &word_complete, 27613d21e9aSBruce Mitchener StringList &matches) override 2775a988416SJim Ingham { 2785a988416SJim Ingham std::string completion_str (input.GetArgumentAtIndex(cursor_index)); 2795a988416SJim Ingham completion_str.erase (cursor_char_position); 2805a988416SJim Ingham 281e1cfbc79STodd Fiala CommandCompletions::InvokeCommonCompletionCallbacks(GetCommandInterpreter(), 2825a988416SJim Ingham CommandCompletions::eDiskFileCompletion, 2835a988416SJim Ingham completion_str.c_str(), 2845a988416SJim Ingham match_start_point, 2855a988416SJim Ingham max_return_elements, 2866e3d8e7fSEugene Zelenko nullptr, 2875a988416SJim Ingham word_complete, 2885a988416SJim Ingham matches); 2895a988416SJim Ingham return matches.GetSize(); 2905a988416SJim Ingham } 2915a988416SJim Ingham 29213d21e9aSBruce Mitchener Options * 29313d21e9aSBruce Mitchener GetOptions () override 2945a988416SJim Ingham { 2955a988416SJim Ingham return &m_options; 2965a988416SJim Ingham } 2975a988416SJim Ingham 2985a988416SJim Ingham protected: 299e16c50a1SJim Ingham class CommandOptions : public Options 300e16c50a1SJim Ingham { 301e16c50a1SJim Ingham public: 302e1cfbc79STodd Fiala CommandOptions() : 303e1cfbc79STodd Fiala Options(), 304340b0309SGreg Clayton m_stop_on_error (true), 305340b0309SGreg Clayton m_silent_run (false), 306340b0309SGreg Clayton m_stop_on_continue (true) 307eb0103f2SGreg Clayton { 308eb0103f2SGreg Clayton } 309e16c50a1SJim Ingham 3106e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 311e16c50a1SJim Ingham 31213d21e9aSBruce Mitchener Error 313e1cfbc79STodd Fiala SetOptionValue (uint32_t option_idx, const char *option_arg, 314e1cfbc79STodd Fiala ExecutionContext *execution_context) override 315e16c50a1SJim Ingham { 316e16c50a1SJim Ingham Error error; 3173bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 318e16c50a1SJim Ingham 319e16c50a1SJim Ingham switch (short_option) 320e16c50a1SJim Ingham { 321e16c50a1SJim Ingham case 'e': 322c95f7e2aSPavel Labath error = m_stop_on_error.SetValueFromString(option_arg); 323e16c50a1SJim Ingham break; 324340b0309SGreg Clayton 325e16c50a1SJim Ingham case 'c': 326c95f7e2aSPavel Labath error = m_stop_on_continue.SetValueFromString(option_arg); 327e16c50a1SJim Ingham break; 328340b0309SGreg Clayton 32960986174SMichael Sartain case 's': 330c95f7e2aSPavel Labath error = m_silent_run.SetValueFromString(option_arg); 33160986174SMichael Sartain break; 332340b0309SGreg Clayton 333e16c50a1SJim Ingham default: 33486edbf41SGreg Clayton error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 335e16c50a1SJim Ingham break; 336e16c50a1SJim Ingham } 337e16c50a1SJim Ingham 338e16c50a1SJim Ingham return error; 339e16c50a1SJim Ingham } 340e16c50a1SJim Ingham 341e16c50a1SJim Ingham void 342e1cfbc79STodd Fiala OptionParsingStarting (ExecutionContext *execution_context) override 343e16c50a1SJim Ingham { 344012d4fcaSEnrico Granata m_stop_on_error.Clear(); 345340b0309SGreg Clayton m_silent_run.Clear(); 346340b0309SGreg Clayton m_stop_on_continue.Clear(); 347e16c50a1SJim Ingham } 348e16c50a1SJim Ingham 349e0d378b3SGreg Clayton const OptionDefinition* 35013d21e9aSBruce Mitchener GetDefinitions () override 351e16c50a1SJim Ingham { 352e16c50a1SJim Ingham return g_option_table; 353e16c50a1SJim Ingham } 354e16c50a1SJim Ingham 355e16c50a1SJim Ingham // Options table: Required for subclasses of Options. 356e16c50a1SJim Ingham 357e0d378b3SGreg Clayton static OptionDefinition g_option_table[]; 358e16c50a1SJim Ingham 359e16c50a1SJim Ingham // Instance variables to hold the values for command options. 360e16c50a1SJim Ingham 361012d4fcaSEnrico Granata OptionValueBoolean m_stop_on_error; 362340b0309SGreg Clayton OptionValueBoolean m_silent_run; 363340b0309SGreg Clayton OptionValueBoolean m_stop_on_continue; 364e16c50a1SJim Ingham }; 365e16c50a1SJim Ingham 366ebc09c36SJim Ingham bool 36713d21e9aSBruce Mitchener DoExecute(Args& command, CommandReturnObject &result) override 368ebc09c36SJim Ingham { 369c7bece56SGreg Clayton const size_t argc = command.GetArgumentCount(); 370ebc09c36SJim Ingham if (argc == 1) 371ebc09c36SJim Ingham { 3725a988416SJim Ingham const char *filename = command.GetArgumentAtIndex(0); 373ebc09c36SJim Ingham 3741ee3853fSJohnny Chen FileSpec cmd_file (filename, true); 3756e3d8e7fSEugene Zelenko ExecutionContext *exe_ctx = nullptr; // Just use the default context. 376ebc09c36SJim Ingham 377340b0309SGreg Clayton // If any options were set, then use them 378340b0309SGreg Clayton if (m_options.m_stop_on_error.OptionWasSet() || 379340b0309SGreg Clayton m_options.m_silent_run.OptionWasSet() || 380340b0309SGreg Clayton m_options.m_stop_on_continue.OptionWasSet()) 381340b0309SGreg Clayton { 382340b0309SGreg Clayton // Use user set settings 38326c7bf93SJim Ingham CommandInterpreterRunOptions options; 38426c7bf93SJim Ingham options.SetStopOnContinue(m_options.m_stop_on_continue.GetCurrentValue()); 38526c7bf93SJim Ingham options.SetStopOnError (m_options.m_stop_on_error.GetCurrentValue()); 3867d8555c4SJim Ingham options.SetEchoCommands (!m_options.m_silent_run.GetCurrentValue()); 3877d8555c4SJim Ingham options.SetPrintResults (!m_options.m_silent_run.GetCurrentValue()); 38826c7bf93SJim Ingham 389e16c50a1SJim Ingham m_interpreter.HandleCommandsFromFile (cmd_file, 390e16c50a1SJim Ingham exe_ctx, 39126c7bf93SJim Ingham options, 392e16c50a1SJim Ingham result); 393340b0309SGreg Clayton } 394340b0309SGreg Clayton else 395340b0309SGreg Clayton { 396340b0309SGreg Clayton // No options were set, inherit any settings from nested "command source" commands, 397340b0309SGreg Clayton // or set to sane default settings... 39826c7bf93SJim Ingham CommandInterpreterRunOptions options; 399340b0309SGreg Clayton m_interpreter.HandleCommandsFromFile (cmd_file, 400340b0309SGreg Clayton exe_ctx, 40126c7bf93SJim Ingham options, 402340b0309SGreg Clayton result); 403340b0309SGreg Clayton } 404ebc09c36SJim Ingham } 405ebc09c36SJim Ingham else 406ebc09c36SJim Ingham { 407ebc09c36SJim Ingham result.AppendErrorWithFormat("'%s' takes exactly one executable filename argument.\n", GetCommandName()); 408ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 409ebc09c36SJim Ingham } 410ebc09c36SJim Ingham return result.Succeeded(); 411ebc09c36SJim Ingham } 4126e3d8e7fSEugene Zelenko 4135a988416SJim Ingham CommandOptions m_options; 414ebc09c36SJim Ingham }; 415ebc09c36SJim Ingham 416e0d378b3SGreg Clayton OptionDefinition 417e16c50a1SJim Ingham CommandObjectCommandsSource::CommandOptions::g_option_table[] = 418e16c50a1SJim Ingham { 419*ac9c3a62SKate Stone // clang-format off 4206e3d8e7fSEugene Zelenko {LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on error."}, 4216e3d8e7fSEugene Zelenko {LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on continue."}, 4226e3d8e7fSEugene Zelenko {LLDB_OPT_SET_ALL, false, "silent-run", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true don't echo commands while executing."}, 4236e3d8e7fSEugene Zelenko {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} 424*ac9c3a62SKate Stone // clang-format on 425e16c50a1SJim Ingham }; 426e16c50a1SJim Ingham 427ebc09c36SJim Ingham #pragma mark CommandObjectCommandsAlias 428ebc09c36SJim Ingham //------------------------------------------------------------------------- 429ebc09c36SJim Ingham // CommandObjectCommandsAlias 430ebc09c36SJim Ingham //------------------------------------------------------------------------- 431ebc09c36SJim Ingham 432be93a35aSEnrico Granata static const char *g_python_command_instructions = "Enter your Python command(s). Type 'DONE' to end.\n" 433be93a35aSEnrico Granata "You must define a Python function with this signature:\n" 43444d93782SGreg Clayton "def my_command_impl(debugger, args, result, internal_dict):\n"; 435be93a35aSEnrico Granata 4365a988416SJim Ingham class CommandObjectCommandsAlias : public CommandObjectRaw 437ebc09c36SJim Ingham { 43845d0e238SEnrico Granata protected: 43945d0e238SEnrico Granata class CommandOptions : public OptionGroup 44045d0e238SEnrico Granata { 441ebc09c36SJim Ingham public: 44245d0e238SEnrico Granata CommandOptions () : 44345d0e238SEnrico Granata OptionGroup(), 44445d0e238SEnrico Granata m_help(), 44545d0e238SEnrico Granata m_long_help() 44645d0e238SEnrico Granata {} 44745d0e238SEnrico Granata 44845d0e238SEnrico Granata ~CommandOptions() override = default; 44945d0e238SEnrico Granata 45045d0e238SEnrico Granata uint32_t 45145d0e238SEnrico Granata GetNumDefinitions () override 45245d0e238SEnrico Granata { 45345d0e238SEnrico Granata return 3; 45445d0e238SEnrico Granata } 45545d0e238SEnrico Granata 45645d0e238SEnrico Granata const OptionDefinition* 45745d0e238SEnrico Granata GetDefinitions () override 45845d0e238SEnrico Granata { 45945d0e238SEnrico Granata return g_option_table; 46045d0e238SEnrico Granata } 46145d0e238SEnrico Granata 46245d0e238SEnrico Granata Error 463e1cfbc79STodd Fiala SetOptionValue (uint32_t option_idx, 464e1cfbc79STodd Fiala const char *option_value, 465e1cfbc79STodd Fiala ExecutionContext *execution_context) override 46645d0e238SEnrico Granata { 46745d0e238SEnrico Granata Error error; 46845d0e238SEnrico Granata 46945d0e238SEnrico Granata const int short_option = g_option_table[option_idx].short_option; 47045d0e238SEnrico Granata 47145d0e238SEnrico Granata switch (short_option) 47245d0e238SEnrico Granata { 47345d0e238SEnrico Granata case 'h': 47445d0e238SEnrico Granata m_help.SetCurrentValue(option_value); 47545d0e238SEnrico Granata m_help.SetOptionWasSet(); 47645d0e238SEnrico Granata break; 47745d0e238SEnrico Granata 47845d0e238SEnrico Granata case 'H': 47945d0e238SEnrico Granata m_long_help.SetCurrentValue(option_value); 48045d0e238SEnrico Granata m_long_help.SetOptionWasSet(); 48145d0e238SEnrico Granata break; 48245d0e238SEnrico Granata 48345d0e238SEnrico Granata default: 48445d0e238SEnrico Granata error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 48545d0e238SEnrico Granata break; 48645d0e238SEnrico Granata } 48745d0e238SEnrico Granata 48845d0e238SEnrico Granata return error; 48945d0e238SEnrico Granata } 49045d0e238SEnrico Granata 49145d0e238SEnrico Granata void 492e1cfbc79STodd Fiala OptionParsingStarting (ExecutionContext *execution_context) override 49345d0e238SEnrico Granata { 49445d0e238SEnrico Granata m_help.Clear(); 49545d0e238SEnrico Granata m_long_help.Clear(); 49645d0e238SEnrico Granata } 49745d0e238SEnrico Granata 49845d0e238SEnrico Granata // Options table: Required for subclasses of Options. 49945d0e238SEnrico Granata 50045d0e238SEnrico Granata static OptionDefinition g_option_table[]; 50145d0e238SEnrico Granata OptionValueString m_help; 50245d0e238SEnrico Granata OptionValueString m_long_help; 50345d0e238SEnrico Granata }; 50445d0e238SEnrico Granata 50545d0e238SEnrico Granata OptionGroupOptions m_option_group; 50645d0e238SEnrico Granata CommandOptions m_command_options; 50745d0e238SEnrico Granata 50845d0e238SEnrico Granata public: 50945d0e238SEnrico Granata Options * 51045d0e238SEnrico Granata GetOptions () override 51145d0e238SEnrico Granata { 51245d0e238SEnrico Granata return &m_option_group; 51345d0e238SEnrico Granata } 51445d0e238SEnrico Granata 5157428a18cSKate Stone CommandObjectCommandsAlias(CommandInterpreter &interpreter) 5167428a18cSKate Stone : CommandObjectRaw(interpreter, "command alias", "Define a custom command in terms of an existing command.", 51745d0e238SEnrico Granata nullptr), 518e1cfbc79STodd Fiala m_option_group(), 51945d0e238SEnrico Granata m_command_options() 520ebc09c36SJim Ingham { 52145d0e238SEnrico Granata m_option_group.Append(&m_command_options); 52245d0e238SEnrico Granata m_option_group.Finalize(); 52345d0e238SEnrico Granata 524ebc09c36SJim Ingham SetHelpLong( 525ea671fbdSKate Stone "'alias' allows the user to create a short-cut or abbreviation for long \ 526ea671fbdSKate Stone commands, multi-word commands, and commands that take particular options. \ 527ea671fbdSKate Stone Below are some simple examples of how one might use the 'alias' command:" R"( 528ea671fbdSKate Stone 529ea671fbdSKate Stone (lldb) command alias sc script 530ea671fbdSKate Stone 531ea671fbdSKate Stone Creates the abbreviation 'sc' for the 'script' command. 532ea671fbdSKate Stone 533ea671fbdSKate Stone (lldb) command alias bp breakpoint 534ea671fbdSKate Stone 535ea671fbdSKate Stone )" " Creates the abbreviation 'bp' for the 'breakpoint' command. Since \ 536ea671fbdSKate Stone breakpoint commands are two-word commands, the user would still need to \ 537ea671fbdSKate Stone enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'." R"( 538ea671fbdSKate Stone 539ea671fbdSKate Stone (lldb) command alias bpl breakpoint list 540ea671fbdSKate Stone 541ea671fbdSKate Stone Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'. 542ea671fbdSKate Stone 543ea671fbdSKate Stone )" "An alias can include some options for the command, with the values either \ 544ea671fbdSKate Stone filled in at the time the alias is created, or specified as positional \ 545ea671fbdSKate Stone arguments, to be filled in when the alias is invoked. The following example \ 546ea671fbdSKate Stone shows how to create aliases with options:" R"( 547ea671fbdSKate Stone 548ea671fbdSKate Stone (lldb) command alias bfl breakpoint set -f %1 -l %2 549ea671fbdSKate Stone 550ea671fbdSKate Stone )" " Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \ 551ea671fbdSKate Stone options already part of the alias. So if the user wants to set a breakpoint \ 552ea671fbdSKate Stone by file and line without explicitly having to use the -f and -l options, the \ 553ea671fbdSKate Stone user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \ 554ea671fbdSKate Stone for the actual arguments that will be passed when the alias command is used. \ 555ea671fbdSKate Stone The number in the placeholder refers to the position/order the actual value \ 556ea671fbdSKate Stone occupies when the alias is used. All the occurrences of '%1' in the alias \ 557ea671fbdSKate Stone will be replaced with the first argument, all the occurrences of '%2' in the \ 558ea671fbdSKate Stone alias will be replaced with the second argument, and so on. This also allows \ 559ea671fbdSKate Stone actual arguments to be used multiple times within an alias (see 'process \ 560ea671fbdSKate Stone launch' example below)." R"( 561ea671fbdSKate Stone 562ea671fbdSKate Stone )" "Note: the positional arguments must substitute as whole words in the resultant \ 563ea671fbdSKate Stone command, so you can't at present do something like this to append the file extension \ 564ea671fbdSKate Stone \".cpp\":" R"( 565ea671fbdSKate Stone 566ea671fbdSKate Stone (lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2 567ea671fbdSKate Stone 568ea671fbdSKate Stone )" "For more complex aliasing, use the \"command regex\" command instead. In the \ 569ea671fbdSKate Stone 'bfl' case above, the actual file value will be filled in with the first argument \ 570ea671fbdSKate Stone following 'bfl' and the actual line number value will be filled in with the second \ 571ea671fbdSKate Stone argument. The user would use this alias as follows:" R"( 572ea671fbdSKate Stone 573ea671fbdSKate Stone (lldb) command alias bfl breakpoint set -f %1 -l %2 574ea671fbdSKate Stone (lldb) bfl my-file.c 137 575ea671fbdSKate Stone 576ea671fbdSKate Stone This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'. 577ea671fbdSKate Stone 578ea671fbdSKate Stone Another example: 579ea671fbdSKate Stone 580ea671fbdSKate Stone (lldb) command alias pltty process launch -s -o %1 -e %1 581ea671fbdSKate Stone (lldb) pltty /dev/tty0 582ea671fbdSKate Stone 583ea671fbdSKate Stone Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0' 584ea671fbdSKate Stone 585ea671fbdSKate Stone )" "If the user always wanted to pass the same value to a particular option, the \ 586ea671fbdSKate Stone alias could be defined with that value directly in the alias as a constant, \ 587ea671fbdSKate Stone rather than using a positional placeholder:" R"( 588ea671fbdSKate Stone 589ea671fbdSKate Stone (lldb) command alias bl3 breakpoint set -f %1 -l 3 590ea671fbdSKate Stone 591ea671fbdSKate Stone Always sets a breakpoint on line 3 of whatever file is indicated.)" 592ea671fbdSKate Stone ); 593ebc09c36SJim Ingham 594405fe67fSCaroline Tice CommandArgumentEntry arg1; 595405fe67fSCaroline Tice CommandArgumentEntry arg2; 596405fe67fSCaroline Tice CommandArgumentEntry arg3; 597405fe67fSCaroline Tice CommandArgumentData alias_arg; 598405fe67fSCaroline Tice CommandArgumentData cmd_arg; 599405fe67fSCaroline Tice CommandArgumentData options_arg; 600405fe67fSCaroline Tice 601405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 602405fe67fSCaroline Tice alias_arg.arg_type = eArgTypeAliasName; 603405fe67fSCaroline Tice alias_arg.arg_repetition = eArgRepeatPlain; 604405fe67fSCaroline Tice 605405fe67fSCaroline Tice // There is only one variant this argument could be; put it into the argument entry. 606405fe67fSCaroline Tice arg1.push_back (alias_arg); 607405fe67fSCaroline Tice 608405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 609405fe67fSCaroline Tice cmd_arg.arg_type = eArgTypeCommandName; 610405fe67fSCaroline Tice cmd_arg.arg_repetition = eArgRepeatPlain; 611405fe67fSCaroline Tice 612405fe67fSCaroline Tice // There is only one variant this argument could be; put it into the argument entry. 613405fe67fSCaroline Tice arg2.push_back (cmd_arg); 614405fe67fSCaroline Tice 615405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 616405fe67fSCaroline Tice options_arg.arg_type = eArgTypeAliasOptions; 617405fe67fSCaroline Tice options_arg.arg_repetition = eArgRepeatOptional; 618405fe67fSCaroline Tice 619405fe67fSCaroline Tice // There is only one variant this argument could be; put it into the argument entry. 620405fe67fSCaroline Tice arg3.push_back (options_arg); 621405fe67fSCaroline Tice 622405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 623405fe67fSCaroline Tice m_arguments.push_back (arg1); 624405fe67fSCaroline Tice m_arguments.push_back (arg2); 625405fe67fSCaroline Tice m_arguments.push_back (arg3); 626ebc09c36SJim Ingham } 627ebc09c36SJim Ingham 6286e3d8e7fSEugene Zelenko ~CommandObjectCommandsAlias() override = default; 629ebc09c36SJim Ingham 6305a988416SJim Ingham protected: 63113d21e9aSBruce Mitchener bool 63213d21e9aSBruce Mitchener DoExecute (const char *raw_command_line, CommandReturnObject &result) override 633844d2303SCaroline Tice { 63445d0e238SEnrico Granata if (!raw_command_line || !raw_command_line[0]) 63545d0e238SEnrico Granata { 636d72e412fSEnrico Granata result.AppendError ("'command alias' requires at least two arguments"); 63745d0e238SEnrico Granata return false; 63845d0e238SEnrico Granata } 63945d0e238SEnrico Granata 640e1cfbc79STodd Fiala ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext(); 641e1cfbc79STodd Fiala m_option_group.NotifyOptionParsingStarting(&exe_ctx); 64245d0e238SEnrico Granata 64345d0e238SEnrico Granata const char * remainder = nullptr; 64445d0e238SEnrico Granata 64545d0e238SEnrico Granata if (raw_command_line[0] == '-') 64645d0e238SEnrico Granata { 64745d0e238SEnrico Granata // We have some options and these options MUST end with --. 64845d0e238SEnrico Granata const char *end_options = nullptr; 64945d0e238SEnrico Granata const char *s = raw_command_line; 65045d0e238SEnrico Granata while (s && s[0]) 65145d0e238SEnrico Granata { 65245d0e238SEnrico Granata end_options = ::strstr (s, "--"); 65345d0e238SEnrico Granata if (end_options) 65445d0e238SEnrico Granata { 65545d0e238SEnrico Granata end_options += 2; // Get past the "--" 65645d0e238SEnrico Granata if (::isspace (end_options[0])) 65745d0e238SEnrico Granata { 65845d0e238SEnrico Granata remainder = end_options; 65945d0e238SEnrico Granata while (::isspace (*remainder)) 66045d0e238SEnrico Granata ++remainder; 66145d0e238SEnrico Granata break; 66245d0e238SEnrico Granata } 66345d0e238SEnrico Granata } 66445d0e238SEnrico Granata s = end_options; 66545d0e238SEnrico Granata } 66645d0e238SEnrico Granata 66745d0e238SEnrico Granata if (end_options) 66845d0e238SEnrico Granata { 66945d0e238SEnrico Granata Args args (llvm::StringRef(raw_command_line, end_options - raw_command_line)); 67045d0e238SEnrico Granata if (!ParseOptions (args, result)) 67145d0e238SEnrico Granata return false; 67245d0e238SEnrico Granata 673e1cfbc79STodd Fiala Error error (m_option_group.NotifyOptionParsingFinished(&exe_ctx)); 67445d0e238SEnrico Granata if (error.Fail()) 67545d0e238SEnrico Granata { 67645d0e238SEnrico Granata result.AppendError (error.AsCString()); 67745d0e238SEnrico Granata result.SetStatus (eReturnStatusFailed); 67845d0e238SEnrico Granata return false; 67945d0e238SEnrico Granata } 68045d0e238SEnrico Granata } 68145d0e238SEnrico Granata } 68245d0e238SEnrico Granata if (nullptr == remainder) 68345d0e238SEnrico Granata remainder = raw_command_line; 68445d0e238SEnrico Granata 68545d0e238SEnrico Granata std::string raw_command_string (remainder); 68645d0e238SEnrico Granata Args args (raw_command_string.c_str()); 687844d2303SCaroline Tice 688844d2303SCaroline Tice size_t argc = args.GetArgumentCount(); 689844d2303SCaroline Tice 690844d2303SCaroline Tice if (argc < 2) 691844d2303SCaroline Tice { 692d72e412fSEnrico Granata result.AppendError ("'command alias' requires at least two arguments"); 693844d2303SCaroline Tice result.SetStatus (eReturnStatusFailed); 694844d2303SCaroline Tice return false; 695844d2303SCaroline Tice } 696844d2303SCaroline Tice 697844d2303SCaroline Tice // Get the alias command. 698844d2303SCaroline Tice 699844d2303SCaroline Tice const std::string alias_command = args.GetArgumentAtIndex (0); 700d72e412fSEnrico Granata if (alias_command.size() > 1 && 701d72e412fSEnrico Granata alias_command[0] == '-') 702d72e412fSEnrico Granata { 703d72e412fSEnrico Granata result.AppendError("aliases starting with a dash are not supported"); 704d72e412fSEnrico Granata if (alias_command == "--help" || alias_command == "--long-help") 705d72e412fSEnrico Granata { 706d72e412fSEnrico Granata result.AppendWarning("if trying to pass options to 'command alias' add a -- at the end of the options"); 707d72e412fSEnrico Granata } 708d72e412fSEnrico Granata result.SetStatus (eReturnStatusFailed); 709d72e412fSEnrico Granata return false; 710d72e412fSEnrico Granata } 711844d2303SCaroline Tice 712844d2303SCaroline Tice // Strip the new alias name off 'raw_command_string' (leave it on args, which gets passed to 'Execute', which 713844d2303SCaroline Tice // does the stripping itself. 714844d2303SCaroline Tice size_t pos = raw_command_string.find (alias_command); 715844d2303SCaroline Tice if (pos == 0) 716844d2303SCaroline Tice { 717844d2303SCaroline Tice raw_command_string = raw_command_string.substr (alias_command.size()); 718844d2303SCaroline Tice pos = raw_command_string.find_first_not_of (' '); 719844d2303SCaroline Tice if ((pos != std::string::npos) && (pos > 0)) 720844d2303SCaroline Tice raw_command_string = raw_command_string.substr (pos); 721844d2303SCaroline Tice } 722844d2303SCaroline Tice else 723844d2303SCaroline Tice { 724844d2303SCaroline Tice result.AppendError ("Error parsing command string. No alias created."); 725844d2303SCaroline Tice result.SetStatus (eReturnStatusFailed); 726844d2303SCaroline Tice return false; 727844d2303SCaroline Tice } 728844d2303SCaroline Tice 729844d2303SCaroline Tice 730844d2303SCaroline Tice // Verify that the command is alias-able. 731844d2303SCaroline Tice if (m_interpreter.CommandExists (alias_command.c_str())) 732844d2303SCaroline Tice { 733844d2303SCaroline Tice result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n", 734844d2303SCaroline Tice alias_command.c_str()); 735844d2303SCaroline Tice result.SetStatus (eReturnStatusFailed); 736844d2303SCaroline Tice return false; 737844d2303SCaroline Tice } 738844d2303SCaroline Tice 739844d2303SCaroline Tice // Get CommandObject that is being aliased. The command name is read from the front of raw_command_string. 740844d2303SCaroline Tice // raw_command_string is returned with the name of the command object stripped off the front. 741d72e412fSEnrico Granata std::string original_raw_command_string(raw_command_string); 742844d2303SCaroline Tice CommandObject *cmd_obj = m_interpreter.GetCommandObjectForCommand (raw_command_string); 743844d2303SCaroline Tice 744844d2303SCaroline Tice if (!cmd_obj) 745844d2303SCaroline Tice { 746d72e412fSEnrico Granata result.AppendErrorWithFormat ("invalid command given to 'command alias'. '%s' does not begin with a valid command." 747d72e412fSEnrico Granata " No alias created.", original_raw_command_string.c_str()); 748844d2303SCaroline Tice result.SetStatus (eReturnStatusFailed); 749844d2303SCaroline Tice return false; 750844d2303SCaroline Tice } 751844d2303SCaroline Tice else if (!cmd_obj->WantsRawCommandString ()) 752844d2303SCaroline Tice { 753844d2303SCaroline Tice // Note that args was initialized with the original command, and has not been updated to this point. 754844d2303SCaroline Tice // Therefore can we pass it to the version of Execute that does not need/expect raw input in the alias. 7555a988416SJim Ingham return HandleAliasingNormalCommand (args, result); 756844d2303SCaroline Tice } 757844d2303SCaroline Tice else 758844d2303SCaroline Tice { 7595a988416SJim Ingham return HandleAliasingRawCommand (alias_command, raw_command_string, *cmd_obj, result); 7605a988416SJim Ingham } 7615a988416SJim Ingham return result.Succeeded(); 7625a988416SJim Ingham } 7635a988416SJim Ingham 7645a988416SJim Ingham bool 7655a988416SJim Ingham HandleAliasingRawCommand (const std::string &alias_command, std::string &raw_command_string, CommandObject &cmd_obj, CommandReturnObject &result) 7665a988416SJim Ingham { 767844d2303SCaroline Tice // Verify & handle any options/arguments passed to the alias command 768844d2303SCaroline Tice 769844d2303SCaroline Tice OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector); 770844d2303SCaroline Tice 771212130acSEnrico Granata if (CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact (cmd_obj.GetCommandName(), false)) 772844d2303SCaroline Tice { 773844d2303SCaroline Tice if (m_interpreter.AliasExists (alias_command.c_str()) 774844d2303SCaroline Tice || m_interpreter.UserCommandExists (alias_command.c_str())) 775844d2303SCaroline Tice { 776844d2303SCaroline Tice result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n", 777844d2303SCaroline Tice alias_command.c_str()); 778844d2303SCaroline Tice } 77945d0e238SEnrico Granata if (CommandAlias *alias = m_interpreter.AddAlias (alias_command.c_str(), cmd_obj_sp, raw_command_string.c_str())) 780472362e6SCaroline Tice { 78145d0e238SEnrico Granata if (m_command_options.m_help.OptionWasSet()) 78245d0e238SEnrico Granata alias->SetHelp(m_command_options.m_help.GetCurrentValue()); 78345d0e238SEnrico Granata if (m_command_options.m_long_help.OptionWasSet()) 78445d0e238SEnrico Granata alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue()); 785844d2303SCaroline Tice result.SetStatus (eReturnStatusSuccessFinishNoResult); 786844d2303SCaroline Tice } 787472362e6SCaroline Tice else 788472362e6SCaroline Tice { 789472362e6SCaroline Tice result.AppendError ("Unable to create requested alias.\n"); 790472362e6SCaroline Tice result.SetStatus (eReturnStatusFailed); 791472362e6SCaroline Tice } 792212130acSEnrico Granata 793212130acSEnrico Granata } 794212130acSEnrico Granata else 795212130acSEnrico Granata { 796212130acSEnrico Granata result.AppendError ("Unable to create requested alias.\n"); 797212130acSEnrico Granata result.SetStatus (eReturnStatusFailed); 798212130acSEnrico Granata } 799212130acSEnrico Granata 800844d2303SCaroline Tice return result.Succeeded (); 801844d2303SCaroline Tice } 802ebc09c36SJim Ingham 803ebc09c36SJim Ingham bool 8045a988416SJim Ingham HandleAliasingNormalCommand (Args& args, CommandReturnObject &result) 805ebc09c36SJim Ingham { 806867b185dSCaroline Tice size_t argc = args.GetArgumentCount(); 807ebc09c36SJim Ingham 808ebc09c36SJim Ingham if (argc < 2) 809ebc09c36SJim Ingham { 810d72e412fSEnrico Granata result.AppendError ("'command alias' requires at least two arguments"); 811ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 812ebc09c36SJim Ingham return false; 813ebc09c36SJim Ingham } 814ebc09c36SJim Ingham 815ebc09c36SJim Ingham const std::string alias_command = args.GetArgumentAtIndex(0); 816ebc09c36SJim Ingham const std::string actual_command = args.GetArgumentAtIndex(1); 817ebc09c36SJim Ingham 818ebc09c36SJim Ingham args.Shift(); // Shift the alias command word off the argument vector. 819ebc09c36SJim Ingham args.Shift(); // Shift the old command word off the argument vector. 820ebc09c36SJim Ingham 821ebc09c36SJim Ingham // Verify that the command is alias'able, and get the appropriate command object. 822ebc09c36SJim Ingham 823a7015092SGreg Clayton if (m_interpreter.CommandExists (alias_command.c_str())) 824ebc09c36SJim Ingham { 825ebc09c36SJim Ingham result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n", 826ebc09c36SJim Ingham alias_command.c_str()); 827ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 828ebc09c36SJim Ingham } 829ebc09c36SJim Ingham else 830ebc09c36SJim Ingham { 831a7015092SGreg Clayton CommandObjectSP command_obj_sp(m_interpreter.GetCommandSPExact (actual_command.c_str(), true)); 832ebc09c36SJim Ingham CommandObjectSP subcommand_obj_sp; 833ebc09c36SJim Ingham bool use_subcommand = false; 8346e3d8e7fSEugene Zelenko if (command_obj_sp) 835ebc09c36SJim Ingham { 836ebc09c36SJim Ingham CommandObject *cmd_obj = command_obj_sp.get(); 8376e3d8e7fSEugene Zelenko CommandObject *sub_cmd_obj = nullptr; 838ebc09c36SJim Ingham OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector); 839ebc09c36SJim Ingham 840844d2303SCaroline Tice while (cmd_obj->IsMultiwordObject() && args.GetArgumentCount() > 0) 841ebc09c36SJim Ingham { 842ebc09c36SJim Ingham if (argc >= 3) 843ebc09c36SJim Ingham { 844ebc09c36SJim Ingham const std::string sub_command = args.GetArgumentAtIndex(0); 845ebc09c36SJim Ingham assert (sub_command.length() != 0); 846998255bfSGreg Clayton subcommand_obj_sp = cmd_obj->GetSubcommandSP (sub_command.c_str()); 8476e3d8e7fSEugene Zelenko if (subcommand_obj_sp) 848ebc09c36SJim Ingham { 849ebc09c36SJim Ingham sub_cmd_obj = subcommand_obj_sp.get(); 850ebc09c36SJim Ingham use_subcommand = true; 851ebc09c36SJim Ingham args.Shift(); // Shift the sub_command word off the argument vector. 852844d2303SCaroline Tice cmd_obj = sub_cmd_obj; 853ebc09c36SJim Ingham } 854ebc09c36SJim Ingham else 855ebc09c36SJim Ingham { 856f415eeb4SCaroline Tice result.AppendErrorWithFormat("'%s' is not a valid sub-command of '%s'. " 857f415eeb4SCaroline Tice "Unable to create alias.\n", 858f415eeb4SCaroline Tice sub_command.c_str(), actual_command.c_str()); 859ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 860ebc09c36SJim Ingham return false; 861ebc09c36SJim Ingham } 862ebc09c36SJim Ingham } 863ebc09c36SJim Ingham } 864ebc09c36SJim Ingham 865ebc09c36SJim Ingham // Verify & handle any options/arguments passed to the alias command 866ebc09c36SJim Ingham 867212130acSEnrico Granata std::string args_string; 868212130acSEnrico Granata 869ebc09c36SJim Ingham if (args.GetArgumentCount () > 0) 870ebc09c36SJim Ingham { 871ca90c47eSCaroline Tice CommandObjectSP tmp_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false); 872ebc09c36SJim Ingham if (use_subcommand) 873ca90c47eSCaroline Tice tmp_sp = m_interpreter.GetCommandSPExact (sub_cmd_obj->GetCommandName(), false); 874ca90c47eSCaroline Tice 875ca90c47eSCaroline Tice args.GetCommandString (args_string); 876867b185dSCaroline Tice } 877ebc09c36SJim Ingham 878a7015092SGreg Clayton if (m_interpreter.AliasExists (alias_command.c_str()) 879a7015092SGreg Clayton || m_interpreter.UserCommandExists (alias_command.c_str())) 880ebc09c36SJim Ingham { 881ebc09c36SJim Ingham result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n", 882ebc09c36SJim Ingham alias_command.c_str()); 883ebc09c36SJim Ingham } 884ebc09c36SJim Ingham 88545d0e238SEnrico Granata if (CommandAlias *alias = m_interpreter.AddAlias(alias_command.c_str(), 886212130acSEnrico Granata use_subcommand ? subcommand_obj_sp : command_obj_sp, 887212130acSEnrico Granata args_string.c_str())) 888212130acSEnrico Granata { 88945d0e238SEnrico Granata if (m_command_options.m_help.OptionWasSet()) 89045d0e238SEnrico Granata alias->SetHelp(m_command_options.m_help.GetCurrentValue()); 89145d0e238SEnrico Granata if (m_command_options.m_long_help.OptionWasSet()) 89245d0e238SEnrico Granata alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue()); 893ebc09c36SJim Ingham result.SetStatus (eReturnStatusSuccessFinishNoResult); 894ebc09c36SJim Ingham } 895ebc09c36SJim Ingham else 896ebc09c36SJim Ingham { 897212130acSEnrico Granata result.AppendError ("Unable to create requested alias.\n"); 898212130acSEnrico Granata result.SetStatus (eReturnStatusFailed); 899212130acSEnrico Granata return false; 900212130acSEnrico Granata } 901212130acSEnrico Granata } 902212130acSEnrico Granata else 903212130acSEnrico Granata { 904ebc09c36SJim Ingham result.AppendErrorWithFormat ("'%s' is not an existing command.\n", actual_command.c_str()); 905ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 906e7941795SCaroline Tice return false; 907ebc09c36SJim Ingham } 908ebc09c36SJim Ingham } 909ebc09c36SJim Ingham 910ebc09c36SJim Ingham return result.Succeeded(); 911ebc09c36SJim Ingham } 912ebc09c36SJim Ingham }; 913ebc09c36SJim Ingham 91445d0e238SEnrico Granata OptionDefinition 91545d0e238SEnrico Granata CommandObjectCommandsAlias::CommandOptions::g_option_table[] = 91645d0e238SEnrico Granata { 917*ac9c3a62SKate Stone // clang-format off 91845d0e238SEnrico Granata {LLDB_OPT_SET_ALL, false, "help", 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Help text for this command"}, 91945d0e238SEnrico Granata {LLDB_OPT_SET_ALL, false, "long-help", 'H', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Long help text for this command"}, 92045d0e238SEnrico Granata {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} 921*ac9c3a62SKate Stone // clang-format on 92245d0e238SEnrico Granata }; 92345d0e238SEnrico Granata 924ebc09c36SJim Ingham #pragma mark CommandObjectCommandsUnalias 925ebc09c36SJim Ingham //------------------------------------------------------------------------- 926ebc09c36SJim Ingham // CommandObjectCommandsUnalias 927ebc09c36SJim Ingham //------------------------------------------------------------------------- 928ebc09c36SJim Ingham 9295a988416SJim Ingham class CommandObjectCommandsUnalias : public CommandObjectParsed 930ebc09c36SJim Ingham { 931ebc09c36SJim Ingham public: 9327428a18cSKate Stone CommandObjectCommandsUnalias(CommandInterpreter &interpreter) 9337428a18cSKate Stone : CommandObjectParsed(interpreter, "command unalias", 9347428a18cSKate Stone "Delete one or more custom commands defined by 'command alias'.", nullptr) 935ebc09c36SJim Ingham { 936405fe67fSCaroline Tice CommandArgumentEntry arg; 937405fe67fSCaroline Tice CommandArgumentData alias_arg; 938405fe67fSCaroline Tice 939405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 940405fe67fSCaroline Tice alias_arg.arg_type = eArgTypeAliasName; 941405fe67fSCaroline Tice alias_arg.arg_repetition = eArgRepeatPlain; 942405fe67fSCaroline Tice 943405fe67fSCaroline Tice // There is only one variant this argument could be; put it into the argument entry. 944405fe67fSCaroline Tice arg.push_back (alias_arg); 945405fe67fSCaroline Tice 946405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 947405fe67fSCaroline Tice m_arguments.push_back (arg); 948ebc09c36SJim Ingham } 949ebc09c36SJim Ingham 9506e3d8e7fSEugene Zelenko ~CommandObjectCommandsUnalias() override = default; 951ebc09c36SJim Ingham 9525a988416SJim Ingham protected: 953ebc09c36SJim Ingham bool 95413d21e9aSBruce Mitchener DoExecute (Args& args, CommandReturnObject &result) override 955ebc09c36SJim Ingham { 956ebc09c36SJim Ingham CommandObject::CommandMap::iterator pos; 957ebc09c36SJim Ingham CommandObject *cmd_obj; 958ebc09c36SJim Ingham 959ebc09c36SJim Ingham if (args.GetArgumentCount() != 0) 960ebc09c36SJim Ingham { 961ebc09c36SJim Ingham const char *command_name = args.GetArgumentAtIndex(0); 962a7015092SGreg Clayton cmd_obj = m_interpreter.GetCommandObject(command_name); 963ebc09c36SJim Ingham if (cmd_obj) 964ebc09c36SJim Ingham { 965a7015092SGreg Clayton if (m_interpreter.CommandExists (command_name)) 966ebc09c36SJim Ingham { 967b547278cSGreg Clayton if (cmd_obj->IsRemovable()) 968b547278cSGreg Clayton { 969b547278cSGreg Clayton result.AppendErrorWithFormat ("'%s' is not an alias, it is a debugger command which can be removed using the 'command delete' command.\n", 970b547278cSGreg Clayton command_name); 971b547278cSGreg Clayton } 972b547278cSGreg Clayton else 973b547278cSGreg Clayton { 974ebc09c36SJim Ingham result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n", 975ebc09c36SJim Ingham command_name); 976b547278cSGreg Clayton } 977ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 978ebc09c36SJim Ingham } 979ebc09c36SJim Ingham else 980ebc09c36SJim Ingham { 9816e3d8e7fSEugene Zelenko if (!m_interpreter.RemoveAlias(command_name)) 982ebc09c36SJim Ingham { 983a7015092SGreg Clayton if (m_interpreter.AliasExists (command_name)) 984ebc09c36SJim Ingham result.AppendErrorWithFormat ("Error occurred while attempting to unalias '%s'.\n", 985ebc09c36SJim Ingham command_name); 986ebc09c36SJim Ingham else 987ebc09c36SJim Ingham result.AppendErrorWithFormat ("'%s' is not an existing alias.\n", command_name); 988ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 989ebc09c36SJim Ingham } 990ebc09c36SJim Ingham else 991ebc09c36SJim Ingham result.SetStatus (eReturnStatusSuccessFinishNoResult); 992ebc09c36SJim Ingham } 993ebc09c36SJim Ingham } 994ebc09c36SJim Ingham else 995ebc09c36SJim Ingham { 996ebc09c36SJim Ingham result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a " 997ebc09c36SJim Ingham "current list of commands.\n", 998ebc09c36SJim Ingham command_name); 999ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 1000ebc09c36SJim Ingham } 1001ebc09c36SJim Ingham } 1002ebc09c36SJim Ingham else 1003ebc09c36SJim Ingham { 1004ebc09c36SJim Ingham result.AppendError ("must call 'unalias' with a valid alias"); 1005ebc09c36SJim Ingham result.SetStatus (eReturnStatusFailed); 1006ebc09c36SJim Ingham } 1007ebc09c36SJim Ingham 1008ebc09c36SJim Ingham return result.Succeeded(); 1009ebc09c36SJim Ingham } 1010ebc09c36SJim Ingham }; 1011ebc09c36SJim Ingham 1012b547278cSGreg Clayton #pragma mark CommandObjectCommandsDelete 1013b547278cSGreg Clayton //------------------------------------------------------------------------- 1014b547278cSGreg Clayton // CommandObjectCommandsDelete 1015b547278cSGreg Clayton //------------------------------------------------------------------------- 1016b547278cSGreg Clayton 1017b547278cSGreg Clayton class CommandObjectCommandsDelete : public CommandObjectParsed 1018b547278cSGreg Clayton { 1019b547278cSGreg Clayton public: 10207428a18cSKate Stone CommandObjectCommandsDelete(CommandInterpreter &interpreter) 10217428a18cSKate Stone : CommandObjectParsed(interpreter, "command delete", 10227428a18cSKate Stone "Delete one or more custom commands defined by 'command regex'.", nullptr) 1023b547278cSGreg Clayton { 1024b547278cSGreg Clayton CommandArgumentEntry arg; 1025b547278cSGreg Clayton CommandArgumentData alias_arg; 1026b547278cSGreg Clayton 1027b547278cSGreg Clayton // Define the first (and only) variant of this arg. 1028b547278cSGreg Clayton alias_arg.arg_type = eArgTypeCommandName; 1029b547278cSGreg Clayton alias_arg.arg_repetition = eArgRepeatPlain; 1030b547278cSGreg Clayton 1031b547278cSGreg Clayton // There is only one variant this argument could be; put it into the argument entry. 1032b547278cSGreg Clayton arg.push_back (alias_arg); 1033b547278cSGreg Clayton 1034b547278cSGreg Clayton // Push the data for the first argument into the m_arguments vector. 1035b547278cSGreg Clayton m_arguments.push_back (arg); 1036b547278cSGreg Clayton } 1037b547278cSGreg Clayton 10386e3d8e7fSEugene Zelenko ~CommandObjectCommandsDelete() override = default; 1039b547278cSGreg Clayton 1040b547278cSGreg Clayton protected: 1041b547278cSGreg Clayton bool 104213d21e9aSBruce Mitchener DoExecute (Args& args, CommandReturnObject &result) override 1043b547278cSGreg Clayton { 1044b547278cSGreg Clayton CommandObject::CommandMap::iterator pos; 1045b547278cSGreg Clayton 1046b547278cSGreg Clayton if (args.GetArgumentCount() != 0) 1047b547278cSGreg Clayton { 1048b547278cSGreg Clayton const char *command_name = args.GetArgumentAtIndex(0); 1049b547278cSGreg Clayton if (m_interpreter.CommandExists (command_name)) 1050b547278cSGreg Clayton { 1051b547278cSGreg Clayton if (m_interpreter.RemoveCommand (command_name)) 1052b547278cSGreg Clayton { 1053b547278cSGreg Clayton result.SetStatus (eReturnStatusSuccessFinishNoResult); 1054b547278cSGreg Clayton } 1055b547278cSGreg Clayton else 1056b547278cSGreg Clayton { 1057b547278cSGreg Clayton result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n", 1058b547278cSGreg Clayton command_name); 1059b547278cSGreg Clayton result.SetStatus (eReturnStatusFailed); 1060b547278cSGreg Clayton } 1061b547278cSGreg Clayton } 1062b547278cSGreg Clayton else 1063b547278cSGreg Clayton { 106446d4aa21SEnrico Granata StreamString error_msg_stream; 106546d4aa21SEnrico Granata const bool generate_apropos = true; 106646d4aa21SEnrico Granata const bool generate_type_lookup = false; 106746d4aa21SEnrico Granata CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(&error_msg_stream, 106846d4aa21SEnrico Granata command_name, 106946d4aa21SEnrico Granata nullptr, 107046d4aa21SEnrico Granata nullptr, 107146d4aa21SEnrico Granata generate_apropos, 107246d4aa21SEnrico Granata generate_type_lookup); 107346d4aa21SEnrico Granata result.AppendErrorWithFormat ("%s", error_msg_stream.GetData()); 1074b547278cSGreg Clayton result.SetStatus (eReturnStatusFailed); 1075b547278cSGreg Clayton } 1076b547278cSGreg Clayton } 1077b547278cSGreg Clayton else 1078b547278cSGreg Clayton { 10797428a18cSKate Stone result.AppendErrorWithFormat( 10807428a18cSKate Stone "must call '%s' with one or more valid user defined regular expression command names", 10817428a18cSKate Stone GetCommandName()); 1082b547278cSGreg Clayton result.SetStatus (eReturnStatusFailed); 1083b547278cSGreg Clayton } 1084b547278cSGreg Clayton 1085b547278cSGreg Clayton return result.Succeeded(); 1086b547278cSGreg Clayton } 1087b547278cSGreg Clayton }; 1088b547278cSGreg Clayton 1089de164aaaSGreg Clayton //------------------------------------------------------------------------- 1090de164aaaSGreg Clayton // CommandObjectCommandsAddRegex 1091de164aaaSGreg Clayton //------------------------------------------------------------------------- 10925a988416SJim Ingham #pragma mark CommandObjectCommandsAddRegex 1093de164aaaSGreg Clayton 109444d93782SGreg Clayton class CommandObjectCommandsAddRegex : 109544d93782SGreg Clayton public CommandObjectParsed, 1096ea508635SGreg Clayton public IOHandlerDelegateMultiline 1097de164aaaSGreg Clayton { 1098de164aaaSGreg Clayton public: 10997428a18cSKate Stone CommandObjectCommandsAddRegex(CommandInterpreter &interpreter) 11007428a18cSKate Stone : CommandObjectParsed(interpreter, "command regex", 11017428a18cSKate Stone "Define a custom command in terms of existing commands by matching regular expressions.", 11020e5e5a79SGreg Clayton "command regex <cmd-name> [s/<regex>/<subst>/ ...]"), 1103ea508635SGreg Clayton IOHandlerDelegateMultiline("", IOHandlerDelegate::Completion::LLDBCommand), 1104e1cfbc79STodd Fiala m_options() 1105de164aaaSGreg Clayton { 1106ea671fbdSKate Stone SetHelpLong(R"( 1107ea671fbdSKate Stone )" "This command allows the user to create powerful regular expression commands \ 1108ea671fbdSKate Stone with substitutions. The regular expressions and substitutions are specified \ 1109ea671fbdSKate Stone using the regular expression substitution format of:" R"( 1110ea671fbdSKate Stone 1111ea671fbdSKate Stone s/<regex>/<subst>/ 1112ea671fbdSKate Stone 1113ea671fbdSKate Stone )" "<regex> is a regular expression that can use parenthesis to capture regular \ 1114ea671fbdSKate Stone expression input and substitute the captured matches in the output using %1 \ 1115ea671fbdSKate Stone for the first match, %2 for the second, and so on." R"( 1116ea671fbdSKate Stone 1117ea671fbdSKate Stone )" "The regular expressions can all be specified on the command line if more than \ 1118ea671fbdSKate Stone one argument is provided. If just the command name is provided on the command \ 1119ea671fbdSKate Stone line, then the regular expressions and substitutions can be entered on separate \ 1120ea671fbdSKate Stone lines, followed by an empty line to terminate the command definition." R"( 1121ea671fbdSKate Stone 1122ea671fbdSKate Stone EXAMPLES 1123ea671fbdSKate Stone 1124ea671fbdSKate Stone )" "The following example will define a regular expression command named 'f' that \ 1125ea671fbdSKate Stone will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \ 1126ea671fbdSKate Stone a number follows 'f':" R"( 1127ea671fbdSKate Stone 1128ea671fbdSKate Stone (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')" 11290e5e5a79SGreg Clayton ); 1130de164aaaSGreg Clayton } 1131de164aaaSGreg Clayton 11326e3d8e7fSEugene Zelenko ~CommandObjectCommandsAddRegex() override = default; 1133de164aaaSGreg Clayton 11345a988416SJim Ingham protected: 1135ea508635SGreg Clayton void 1136ea508635SGreg Clayton IOHandlerActivated (IOHandler &io_handler) override 113744d93782SGreg Clayton { 113844d93782SGreg Clayton StreamFileSP output_sp(io_handler.GetOutputStreamFile()); 113944d93782SGreg Clayton if (output_sp) 114044d93782SGreg Clayton { 114144d93782SGreg 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"); 114244d93782SGreg Clayton output_sp->Flush(); 114344d93782SGreg Clayton } 114444d93782SGreg Clayton } 114544d93782SGreg Clayton 1146ea508635SGreg Clayton void 1147ea508635SGreg Clayton IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override 114844d93782SGreg Clayton { 114944d93782SGreg Clayton io_handler.SetIsDone(true); 11506e3d8e7fSEugene Zelenko if (m_regex_cmd_ap) 115144d93782SGreg Clayton { 115244d93782SGreg Clayton StringList lines; 115344d93782SGreg Clayton if (lines.SplitIntoLines (data)) 115444d93782SGreg Clayton { 115544d93782SGreg Clayton const size_t num_lines = lines.GetSize(); 115644d93782SGreg Clayton bool check_only = false; 115744d93782SGreg Clayton for (size_t i=0; i<num_lines; ++i) 115844d93782SGreg Clayton { 115944d93782SGreg Clayton llvm::StringRef bytes_strref (lines[i]); 116044d93782SGreg Clayton Error error = AppendRegexSubstitution (bytes_strref, check_only); 116144d93782SGreg Clayton if (error.Fail()) 116244d93782SGreg Clayton { 116344d93782SGreg Clayton if (!m_interpreter.GetDebugger().GetCommandInterpreter().GetBatchCommandMode()) 116444d93782SGreg Clayton { 116544d93782SGreg Clayton StreamSP out_stream = m_interpreter.GetDebugger().GetAsyncOutputStream(); 116644d93782SGreg Clayton out_stream->Printf("error: %s\n", error.AsCString()); 116744d93782SGreg Clayton } 116844d93782SGreg Clayton } 116944d93782SGreg Clayton } 117044d93782SGreg Clayton } 117144d93782SGreg Clayton if (m_regex_cmd_ap->HasRegexEntries()) 117244d93782SGreg Clayton { 117344d93782SGreg Clayton CommandObjectSP cmd_sp (m_regex_cmd_ap.release()); 117444d93782SGreg Clayton m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true); 117544d93782SGreg Clayton } 117644d93782SGreg Clayton } 117744d93782SGreg Clayton } 117844d93782SGreg Clayton 1179de164aaaSGreg Clayton bool 1180b0a1814fSEric Christopher DoExecute (Args& command, CommandReturnObject &result) override 1181de164aaaSGreg Clayton { 11825a988416SJim Ingham const size_t argc = command.GetArgumentCount(); 11830e5e5a79SGreg Clayton if (argc == 0) 1184de164aaaSGreg Clayton { 118569c12ccbSJason Molenda result.AppendError ("usage: 'command regex <command-name> [s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n"); 11860e5e5a79SGreg Clayton result.SetStatus (eReturnStatusFailed); 11870e5e5a79SGreg Clayton } 11880e5e5a79SGreg Clayton else 11890e5e5a79SGreg Clayton { 11900e5e5a79SGreg Clayton Error error; 11915a988416SJim Ingham const char *name = command.GetArgumentAtIndex(0); 1192de164aaaSGreg Clayton m_regex_cmd_ap.reset (new CommandObjectRegexCommand (m_interpreter, 1193de164aaaSGreg Clayton name, 1194de164aaaSGreg Clayton m_options.GetHelp (), 1195de164aaaSGreg Clayton m_options.GetSyntax (), 1196b547278cSGreg Clayton 10, 1197b547278cSGreg Clayton 0, 1198b547278cSGreg Clayton true)); 11990e5e5a79SGreg Clayton 12000e5e5a79SGreg Clayton if (argc == 1) 12010e5e5a79SGreg Clayton { 120244d93782SGreg Clayton Debugger &debugger = m_interpreter.GetDebugger(); 1203e30f11d9SKate Stone bool color_prompt = debugger.GetUseColor(); 120444d93782SGreg Clayton const bool multiple_lines = true; // Get multiple lines 120544d93782SGreg Clayton IOHandlerSP io_handler_sp(new IOHandlerEditline(debugger, 1206e30f11d9SKate Stone IOHandler::Type::Other, 120773d80faaSGreg Clayton "lldb-regex", // Name of input reader for history 1208ea508635SGreg Clayton "> ", // Prompt 12096e3d8e7fSEugene Zelenko nullptr, // Continuation prompt 121044d93782SGreg Clayton multiple_lines, 1211e30f11d9SKate Stone color_prompt, 1212f6913cd7SGreg Clayton 0, // Don't show line numbers 121344d93782SGreg Clayton *this)); 121444d93782SGreg Clayton 121544d93782SGreg Clayton if (io_handler_sp) 1216de164aaaSGreg Clayton { 121744d93782SGreg Clayton debugger.PushIOHandler(io_handler_sp); 1218de164aaaSGreg Clayton result.SetStatus (eReturnStatusSuccessFinishNoResult); 1219de164aaaSGreg Clayton } 1220de164aaaSGreg Clayton } 1221de164aaaSGreg Clayton else 1222de164aaaSGreg Clayton { 12230e5e5a79SGreg Clayton for (size_t arg_idx = 1; arg_idx < argc; ++arg_idx) 12240e5e5a79SGreg Clayton { 12255a988416SJim Ingham llvm::StringRef arg_strref (command.GetArgumentAtIndex(arg_idx)); 122644d93782SGreg Clayton bool check_only = false; 122744d93782SGreg Clayton error = AppendRegexSubstitution (arg_strref, check_only); 12280e5e5a79SGreg Clayton if (error.Fail()) 12290e5e5a79SGreg Clayton break; 12300e5e5a79SGreg Clayton } 12310e5e5a79SGreg Clayton 12320e5e5a79SGreg Clayton if (error.Success()) 12330e5e5a79SGreg Clayton { 12340e5e5a79SGreg Clayton AddRegexCommandToInterpreter(); 12350e5e5a79SGreg Clayton } 12360e5e5a79SGreg Clayton } 12370e5e5a79SGreg Clayton if (error.Fail()) 12380e5e5a79SGreg Clayton { 12390e5e5a79SGreg Clayton result.AppendError (error.AsCString()); 1240de164aaaSGreg Clayton result.SetStatus (eReturnStatusFailed); 1241de164aaaSGreg Clayton } 12420e5e5a79SGreg Clayton } 12430e5e5a79SGreg Clayton 1244de164aaaSGreg Clayton return result.Succeeded(); 1245de164aaaSGreg Clayton } 1246de164aaaSGreg Clayton 12470e5e5a79SGreg Clayton Error 124844d93782SGreg Clayton AppendRegexSubstitution (const llvm::StringRef ®ex_sed, bool check_only) 1249de164aaaSGreg Clayton { 12500e5e5a79SGreg Clayton Error error; 12510e5e5a79SGreg Clayton 12526e3d8e7fSEugene Zelenko if (!m_regex_cmd_ap) 1253de164aaaSGreg Clayton { 12540e5e5a79SGreg Clayton error.SetErrorStringWithFormat("invalid regular expression command object for: '%.*s'", 12550e5e5a79SGreg Clayton (int)regex_sed.size(), 12560e5e5a79SGreg Clayton regex_sed.data()); 12570e5e5a79SGreg Clayton return error; 1258de164aaaSGreg Clayton } 12590e5e5a79SGreg Clayton 12600e5e5a79SGreg Clayton size_t regex_sed_size = regex_sed.size(); 12610e5e5a79SGreg Clayton 12620e5e5a79SGreg Clayton if (regex_sed_size <= 1) 12630e5e5a79SGreg Clayton { 12640e5e5a79SGreg Clayton error.SetErrorStringWithFormat("regular expression substitution string is too short: '%.*s'", 12650e5e5a79SGreg Clayton (int)regex_sed.size(), 12660e5e5a79SGreg Clayton regex_sed.data()); 12670e5e5a79SGreg Clayton return error; 12680e5e5a79SGreg Clayton } 12690e5e5a79SGreg Clayton 12700e5e5a79SGreg Clayton if (regex_sed[0] != 's') 12710e5e5a79SGreg Clayton { 12720e5e5a79SGreg Clayton error.SetErrorStringWithFormat("regular expression substitution string doesn't start with 's': '%.*s'", 12730e5e5a79SGreg Clayton (int)regex_sed.size(), 12740e5e5a79SGreg Clayton regex_sed.data()); 12750e5e5a79SGreg Clayton return error; 12760e5e5a79SGreg Clayton } 12770e5e5a79SGreg Clayton const size_t first_separator_char_pos = 1; 12780e5e5a79SGreg Clayton // use the char that follows 's' as the regex separator character 12790e5e5a79SGreg Clayton // so we can have "s/<regex>/<subst>/" or "s|<regex>|<subst>|" 12800e5e5a79SGreg Clayton const char separator_char = regex_sed[first_separator_char_pos]; 12810e5e5a79SGreg Clayton const size_t second_separator_char_pos = regex_sed.find (separator_char, first_separator_char_pos + 1); 12820e5e5a79SGreg Clayton 12830e5e5a79SGreg Clayton if (second_separator_char_pos == std::string::npos) 12840e5e5a79SGreg Clayton { 1285ea508635SGreg Clayton error.SetErrorStringWithFormat("missing second '%c' separator char after '%.*s' in '%.*s'", 12860e5e5a79SGreg Clayton separator_char, 12870e5e5a79SGreg Clayton (int)(regex_sed.size() - first_separator_char_pos - 1), 1288ea508635SGreg Clayton regex_sed.data() + (first_separator_char_pos + 1), 1289ea508635SGreg Clayton (int)regex_sed.size(), 1290ea508635SGreg Clayton regex_sed.data()); 12910e5e5a79SGreg Clayton return error; 12920e5e5a79SGreg Clayton } 12930e5e5a79SGreg Clayton 12940e5e5a79SGreg Clayton const size_t third_separator_char_pos = regex_sed.find (separator_char, second_separator_char_pos + 1); 12950e5e5a79SGreg Clayton 12960e5e5a79SGreg Clayton if (third_separator_char_pos == std::string::npos) 12970e5e5a79SGreg Clayton { 1298ea508635SGreg Clayton error.SetErrorStringWithFormat("missing third '%c' separator char after '%.*s' in '%.*s'", 12990e5e5a79SGreg Clayton separator_char, 13000e5e5a79SGreg Clayton (int)(regex_sed.size() - second_separator_char_pos - 1), 1301ea508635SGreg Clayton regex_sed.data() + (second_separator_char_pos + 1), 1302ea508635SGreg Clayton (int)regex_sed.size(), 1303ea508635SGreg Clayton regex_sed.data()); 13040e5e5a79SGreg Clayton return error; 13050e5e5a79SGreg Clayton } 13060e5e5a79SGreg Clayton 13070e5e5a79SGreg Clayton if (third_separator_char_pos != regex_sed_size - 1) 13080e5e5a79SGreg Clayton { 13090e5e5a79SGreg Clayton // Make sure that everything that follows the last regex 13100e5e5a79SGreg Clayton // separator char 13110e5e5a79SGreg Clayton if (regex_sed.find_first_not_of("\t\n\v\f\r ", third_separator_char_pos + 1) != std::string::npos) 13120e5e5a79SGreg Clayton { 13130e5e5a79SGreg Clayton error.SetErrorStringWithFormat("extra data found after the '%.*s' regular expression substitution string: '%.*s'", 13140e5e5a79SGreg Clayton (int)third_separator_char_pos + 1, 13150e5e5a79SGreg Clayton regex_sed.data(), 13160e5e5a79SGreg Clayton (int)(regex_sed.size() - third_separator_char_pos - 1), 13170e5e5a79SGreg Clayton regex_sed.data() + (third_separator_char_pos + 1)); 13180e5e5a79SGreg Clayton return error; 13190e5e5a79SGreg Clayton } 13200e5e5a79SGreg Clayton } 13210e5e5a79SGreg Clayton else if (first_separator_char_pos + 1 == second_separator_char_pos) 13220e5e5a79SGreg Clayton { 13230e5e5a79SGreg Clayton error.SetErrorStringWithFormat("<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'", 13240e5e5a79SGreg Clayton separator_char, 13250e5e5a79SGreg Clayton separator_char, 13260e5e5a79SGreg Clayton separator_char, 13270e5e5a79SGreg Clayton (int)regex_sed.size(), 13280e5e5a79SGreg Clayton regex_sed.data()); 13290e5e5a79SGreg Clayton return error; 13300e5e5a79SGreg Clayton } 13310e5e5a79SGreg Clayton else if (second_separator_char_pos + 1 == third_separator_char_pos) 13320e5e5a79SGreg Clayton { 13330e5e5a79SGreg Clayton error.SetErrorStringWithFormat("<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'", 13340e5e5a79SGreg Clayton separator_char, 13350e5e5a79SGreg Clayton separator_char, 13360e5e5a79SGreg Clayton separator_char, 13370e5e5a79SGreg Clayton (int)regex_sed.size(), 13380e5e5a79SGreg Clayton regex_sed.data()); 13390e5e5a79SGreg Clayton return error; 13400e5e5a79SGreg Clayton } 134144d93782SGreg Clayton 13426e3d8e7fSEugene Zelenko if (!check_only) 134344d93782SGreg Clayton { 13440e5e5a79SGreg Clayton std::string regex(regex_sed.substr(first_separator_char_pos + 1, second_separator_char_pos - first_separator_char_pos - 1)); 13450e5e5a79SGreg Clayton std::string subst(regex_sed.substr(second_separator_char_pos + 1, third_separator_char_pos - second_separator_char_pos - 1)); 13460e5e5a79SGreg Clayton m_regex_cmd_ap->AddRegexCommand (regex.c_str(), 13470e5e5a79SGreg Clayton subst.c_str()); 134844d93782SGreg Clayton } 13490e5e5a79SGreg Clayton return error; 1350de164aaaSGreg Clayton } 1351de164aaaSGreg Clayton 1352de164aaaSGreg Clayton void 13530e5e5a79SGreg Clayton AddRegexCommandToInterpreter() 1354de164aaaSGreg Clayton { 13556e3d8e7fSEugene Zelenko if (m_regex_cmd_ap) 1356de164aaaSGreg Clayton { 1357de164aaaSGreg Clayton if (m_regex_cmd_ap->HasRegexEntries()) 1358de164aaaSGreg Clayton { 1359de164aaaSGreg Clayton CommandObjectSP cmd_sp (m_regex_cmd_ap.release()); 1360de164aaaSGreg Clayton m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true); 1361de164aaaSGreg Clayton } 1362de164aaaSGreg Clayton } 1363de164aaaSGreg Clayton } 1364de164aaaSGreg Clayton 1365de164aaaSGreg Clayton private: 13667b0992d9SGreg Clayton std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_ap; 1367de164aaaSGreg Clayton 1368de164aaaSGreg Clayton class CommandOptions : public Options 1369de164aaaSGreg Clayton { 1370de164aaaSGreg Clayton public: 1371e1cfbc79STodd Fiala CommandOptions() : 1372e1cfbc79STodd Fiala Options() 1373de164aaaSGreg Clayton { 1374de164aaaSGreg Clayton } 1375de164aaaSGreg Clayton 13766e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 1377de164aaaSGreg Clayton 137813d21e9aSBruce Mitchener Error 1379e1cfbc79STodd Fiala SetOptionValue (uint32_t option_idx, const char *option_arg, 1380e1cfbc79STodd Fiala ExecutionContext *execution_context) override 1381de164aaaSGreg Clayton { 1382de164aaaSGreg Clayton Error error; 13833bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 1384de164aaaSGreg Clayton 1385de164aaaSGreg Clayton switch (short_option) 1386de164aaaSGreg Clayton { 1387de164aaaSGreg Clayton case 'h': 1388de164aaaSGreg Clayton m_help.assign (option_arg); 1389de164aaaSGreg Clayton break; 1390de164aaaSGreg Clayton case 's': 1391de164aaaSGreg Clayton m_syntax.assign (option_arg); 1392de164aaaSGreg Clayton break; 1393de164aaaSGreg Clayton default: 139486edbf41SGreg Clayton error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1395de164aaaSGreg Clayton break; 1396de164aaaSGreg Clayton } 1397de164aaaSGreg Clayton 1398de164aaaSGreg Clayton return error; 1399de164aaaSGreg Clayton } 1400de164aaaSGreg Clayton 1401de164aaaSGreg Clayton void 1402e1cfbc79STodd Fiala OptionParsingStarting (ExecutionContext *execution_context) override 1403de164aaaSGreg Clayton { 1404de164aaaSGreg Clayton m_help.clear(); 1405de164aaaSGreg Clayton m_syntax.clear(); 1406de164aaaSGreg Clayton } 1407de164aaaSGreg Clayton 1408de164aaaSGreg Clayton const OptionDefinition* 140913d21e9aSBruce Mitchener GetDefinitions () override 1410de164aaaSGreg Clayton { 1411de164aaaSGreg Clayton return g_option_table; 1412de164aaaSGreg Clayton } 1413de164aaaSGreg Clayton 1414de164aaaSGreg Clayton // Options table: Required for subclasses of Options. 1415de164aaaSGreg Clayton 1416de164aaaSGreg Clayton static OptionDefinition g_option_table[]; 1417de164aaaSGreg Clayton 1418de164aaaSGreg Clayton const char * 1419de164aaaSGreg Clayton GetHelp() 1420de164aaaSGreg Clayton { 14216e3d8e7fSEugene Zelenko return (m_help.empty() ? nullptr : m_help.c_str()); 1422de164aaaSGreg Clayton } 14236e3d8e7fSEugene Zelenko 1424de164aaaSGreg Clayton const char * 1425de164aaaSGreg Clayton GetSyntax () 1426de164aaaSGreg Clayton { 14276e3d8e7fSEugene Zelenko return (m_syntax.empty() ? nullptr : m_syntax.c_str()); 1428de164aaaSGreg Clayton } 14296e3d8e7fSEugene Zelenko 1430de164aaaSGreg Clayton protected: 14316e3d8e7fSEugene Zelenko // Instance variables to hold the values for command options. 14326e3d8e7fSEugene Zelenko 1433de164aaaSGreg Clayton std::string m_help; 1434de164aaaSGreg Clayton std::string m_syntax; 1435de164aaaSGreg Clayton }; 1436de164aaaSGreg Clayton 1437b0a1814fSEric Christopher Options * 1438b0a1814fSEric Christopher GetOptions () override 1439de164aaaSGreg Clayton { 1440de164aaaSGreg Clayton return &m_options; 1441de164aaaSGreg Clayton } 1442de164aaaSGreg Clayton 14435a988416SJim Ingham CommandOptions m_options; 1444de164aaaSGreg Clayton }; 1445de164aaaSGreg Clayton 1446de164aaaSGreg Clayton OptionDefinition 1447de164aaaSGreg Clayton CommandObjectCommandsAddRegex::CommandOptions::g_option_table[] = 1448de164aaaSGreg Clayton { 1449*ac9c3a62SKate Stone // clang-format off 14506e3d8e7fSEugene Zelenko {LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "The help text to display for this command."}, 14516e3d8e7fSEugene Zelenko {LLDB_OPT_SET_1, false, "syntax", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "A syntax string showing the typical usage syntax."}, 14526e3d8e7fSEugene Zelenko {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} 1453*ac9c3a62SKate Stone // clang-format on 1454de164aaaSGreg Clayton }; 1455de164aaaSGreg Clayton 14565a988416SJim Ingham class CommandObjectPythonFunction : public CommandObjectRaw 1457223383edSEnrico Granata { 1458223383edSEnrico Granata public: 1459223383edSEnrico Granata CommandObjectPythonFunction (CommandInterpreter &interpreter, 1460223383edSEnrico Granata std::string name, 14610a305db7SEnrico Granata std::string funct, 1462735152e3SEnrico Granata std::string help, 14630a305db7SEnrico Granata ScriptedCommandSynchronicity synch) : 14645a988416SJim Ingham CommandObjectRaw(interpreter, 1465223383edSEnrico Granata name.c_str(), 14666e3d8e7fSEugene Zelenko nullptr, 14676e3d8e7fSEugene Zelenko nullptr), 14680a305db7SEnrico Granata m_function_name(funct), 1469fac939e9SEnrico Granata m_synchro(synch), 1470fac939e9SEnrico Granata m_fetched_help_long(false) 1471223383edSEnrico Granata { 1472735152e3SEnrico Granata if (!help.empty()) 1473735152e3SEnrico Granata SetHelp(help.c_str()); 1474735152e3SEnrico Granata else 1475735152e3SEnrico Granata { 1476735152e3SEnrico Granata StreamString stream; 1477735152e3SEnrico Granata stream.Printf("For more information run 'help %s'",name.c_str()); 1478735152e3SEnrico Granata SetHelp(stream.GetData()); 1479735152e3SEnrico Granata } 1480223383edSEnrico Granata } 1481223383edSEnrico Granata 14826e3d8e7fSEugene Zelenko ~CommandObjectPythonFunction() override = default; 1483223383edSEnrico Granata 148413d21e9aSBruce Mitchener bool 148513d21e9aSBruce Mitchener IsRemovable () const override 14865a988416SJim Ingham { 14875a988416SJim Ingham return true; 14885a988416SJim Ingham } 14895a988416SJim Ingham 14905a988416SJim Ingham const std::string& 14915a988416SJim Ingham GetFunctionName () 14925a988416SJim Ingham { 14935a988416SJim Ingham return m_function_name; 14945a988416SJim Ingham } 14955a988416SJim Ingham 14965a988416SJim Ingham ScriptedCommandSynchronicity 14975a988416SJim Ingham GetSynchronicity () 14985a988416SJim Ingham { 14995a988416SJim Ingham return m_synchro; 15005a988416SJim Ingham } 15015a988416SJim Ingham 150213d21e9aSBruce Mitchener const char * 150313d21e9aSBruce Mitchener GetHelpLong () override 1504fac939e9SEnrico Granata { 1505fac939e9SEnrico Granata if (!m_fetched_help_long) 1506fac939e9SEnrico Granata { 1507fac939e9SEnrico Granata ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter(); 1508fac939e9SEnrico Granata if (scripter) 1509fac939e9SEnrico Granata { 1510fac939e9SEnrico Granata std::string docstring; 1511fac939e9SEnrico Granata m_fetched_help_long = scripter->GetDocumentationForItem(m_function_name.c_str(),docstring); 1512fac939e9SEnrico Granata if (!docstring.empty()) 1513bfb75e9bSEnrico Granata SetHelpLong(docstring.c_str()); 1514fac939e9SEnrico Granata } 1515fac939e9SEnrico Granata } 1516fac939e9SEnrico Granata return CommandObjectRaw::GetHelpLong(); 1517fac939e9SEnrico Granata } 1518fac939e9SEnrico Granata 15195a988416SJim Ingham protected: 152013d21e9aSBruce Mitchener bool 152113d21e9aSBruce Mitchener DoExecute (const char *raw_command_line, CommandReturnObject &result) override 1522223383edSEnrico Granata { 1523223383edSEnrico Granata ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter(); 1524223383edSEnrico Granata 1525223383edSEnrico Granata Error error; 1526223383edSEnrico Granata 152770f11f88SJim Ingham result.SetStatus(eReturnStatusInvalid); 152870f11f88SJim Ingham 15296e3d8e7fSEugene Zelenko if (!scripter || !scripter->RunScriptBasedCommand(m_function_name.c_str(), 1530223383edSEnrico Granata raw_command_line, 15310a305db7SEnrico Granata m_synchro, 1532223383edSEnrico Granata result, 153306be059aSEnrico Granata error, 15346e3d8e7fSEugene Zelenko m_exe_ctx)) 1535223383edSEnrico Granata { 1536223383edSEnrico Granata result.AppendError(error.AsCString()); 1537223383edSEnrico Granata result.SetStatus(eReturnStatusFailed); 1538223383edSEnrico Granata } 1539223383edSEnrico Granata else 154070f11f88SJim Ingham { 154170f11f88SJim Ingham // Don't change the status if the command already set it... 154270f11f88SJim Ingham if (result.GetStatus() == eReturnStatusInvalid) 154370f11f88SJim Ingham { 15446e3d8e7fSEugene Zelenko if (result.GetOutputData() == nullptr || result.GetOutputData()[0] == '\0') 1545223383edSEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 154670f11f88SJim Ingham else 154770f11f88SJim Ingham result.SetStatus(eReturnStatusSuccessFinishResult); 154870f11f88SJim Ingham } 154970f11f88SJim Ingham } 1550223383edSEnrico Granata 1551223383edSEnrico Granata return result.Succeeded(); 1552223383edSEnrico Granata } 1553223383edSEnrico Granata 15546e3d8e7fSEugene Zelenko private: 15556e3d8e7fSEugene Zelenko std::string m_function_name; 15566e3d8e7fSEugene Zelenko ScriptedCommandSynchronicity m_synchro; 15576e3d8e7fSEugene Zelenko bool m_fetched_help_long; 1558223383edSEnrico Granata }; 1559223383edSEnrico Granata 15609fe00e52SEnrico Granata class CommandObjectScriptingObject : public CommandObjectRaw 15619fe00e52SEnrico Granata { 15629fe00e52SEnrico Granata public: 15639fe00e52SEnrico Granata CommandObjectScriptingObject (CommandInterpreter &interpreter, 15649fe00e52SEnrico Granata std::string name, 15650641ca1aSZachary Turner StructuredData::GenericSP cmd_obj_sp, 15669fe00e52SEnrico Granata ScriptedCommandSynchronicity synch) : 15679fe00e52SEnrico Granata CommandObjectRaw(interpreter, 15689fe00e52SEnrico Granata name.c_str(), 15696e3d8e7fSEugene Zelenko nullptr, 15706e3d8e7fSEugene Zelenko nullptr), 15719fe00e52SEnrico Granata m_cmd_obj_sp(cmd_obj_sp), 15726f79bb2dSEnrico Granata m_synchro(synch), 15736f79bb2dSEnrico Granata m_fetched_help_short(false), 15746f79bb2dSEnrico Granata m_fetched_help_long(false) 15759fe00e52SEnrico Granata { 15769fe00e52SEnrico Granata StreamString stream; 15779fe00e52SEnrico Granata stream.Printf("For more information run 'help %s'",name.c_str()); 15789fe00e52SEnrico Granata SetHelp(stream.GetData()); 1579e87764f2SEnrico Granata if (ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter()) 1580e87764f2SEnrico Granata GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp)); 15819fe00e52SEnrico Granata } 15829fe00e52SEnrico Granata 15836e3d8e7fSEugene Zelenko ~CommandObjectScriptingObject() override = default; 15849fe00e52SEnrico Granata 158513d21e9aSBruce Mitchener bool 158613d21e9aSBruce Mitchener IsRemovable () const override 15879fe00e52SEnrico Granata { 15889fe00e52SEnrico Granata return true; 15899fe00e52SEnrico Granata } 15909fe00e52SEnrico Granata 15910641ca1aSZachary Turner StructuredData::GenericSP 15929fe00e52SEnrico Granata GetImplementingObject () 15939fe00e52SEnrico Granata { 15949fe00e52SEnrico Granata return m_cmd_obj_sp; 15959fe00e52SEnrico Granata } 15969fe00e52SEnrico Granata 15979fe00e52SEnrico Granata ScriptedCommandSynchronicity 15989fe00e52SEnrico Granata GetSynchronicity () 15999fe00e52SEnrico Granata { 16009fe00e52SEnrico Granata return m_synchro; 16019fe00e52SEnrico Granata } 16029fe00e52SEnrico Granata 160313d21e9aSBruce Mitchener const char * 160413d21e9aSBruce Mitchener GetHelp () override 16056f79bb2dSEnrico Granata { 16066f79bb2dSEnrico Granata if (!m_fetched_help_short) 16076f79bb2dSEnrico Granata { 16086f79bb2dSEnrico Granata ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter(); 16096f79bb2dSEnrico Granata if (scripter) 16106f79bb2dSEnrico Granata { 16116f79bb2dSEnrico Granata std::string docstring; 16126f79bb2dSEnrico Granata m_fetched_help_short = scripter->GetShortHelpForCommandObject(m_cmd_obj_sp,docstring); 16136f79bb2dSEnrico Granata if (!docstring.empty()) 1614bfb75e9bSEnrico Granata SetHelp(docstring.c_str()); 16156f79bb2dSEnrico Granata } 16166f79bb2dSEnrico Granata } 16176f79bb2dSEnrico Granata return CommandObjectRaw::GetHelp(); 16186f79bb2dSEnrico Granata } 16196f79bb2dSEnrico Granata 162013d21e9aSBruce Mitchener const char * 162113d21e9aSBruce Mitchener GetHelpLong () override 16229fe00e52SEnrico Granata { 16236f79bb2dSEnrico Granata if (!m_fetched_help_long) 16246f79bb2dSEnrico Granata { 16256f79bb2dSEnrico Granata ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter(); 16266f79bb2dSEnrico Granata if (scripter) 16276f79bb2dSEnrico Granata { 16286f79bb2dSEnrico Granata std::string docstring; 16296f79bb2dSEnrico Granata m_fetched_help_long = scripter->GetLongHelpForCommandObject(m_cmd_obj_sp,docstring); 16306f79bb2dSEnrico Granata if (!docstring.empty()) 1631bfb75e9bSEnrico Granata SetHelpLong(docstring.c_str()); 16326f79bb2dSEnrico Granata } 16336f79bb2dSEnrico Granata } 16349fe00e52SEnrico Granata return CommandObjectRaw::GetHelpLong(); 16359fe00e52SEnrico Granata } 16369fe00e52SEnrico Granata 16379fe00e52SEnrico Granata protected: 163813d21e9aSBruce Mitchener bool 163913d21e9aSBruce Mitchener DoExecute (const char *raw_command_line, CommandReturnObject &result) override 16409fe00e52SEnrico Granata { 16419fe00e52SEnrico Granata ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter(); 16429fe00e52SEnrico Granata 16439fe00e52SEnrico Granata Error error; 16449fe00e52SEnrico Granata 16459fe00e52SEnrico Granata result.SetStatus(eReturnStatusInvalid); 16469fe00e52SEnrico Granata 16476e3d8e7fSEugene Zelenko if (!scripter || !scripter->RunScriptBasedCommand(m_cmd_obj_sp, 16489fe00e52SEnrico Granata raw_command_line, 16499fe00e52SEnrico Granata m_synchro, 16509fe00e52SEnrico Granata result, 16519fe00e52SEnrico Granata error, 16526e3d8e7fSEugene Zelenko m_exe_ctx)) 16539fe00e52SEnrico Granata { 16549fe00e52SEnrico Granata result.AppendError(error.AsCString()); 16559fe00e52SEnrico Granata result.SetStatus(eReturnStatusFailed); 16569fe00e52SEnrico Granata } 16579fe00e52SEnrico Granata else 16589fe00e52SEnrico Granata { 16599fe00e52SEnrico Granata // Don't change the status if the command already set it... 16609fe00e52SEnrico Granata if (result.GetStatus() == eReturnStatusInvalid) 16619fe00e52SEnrico Granata { 16626e3d8e7fSEugene Zelenko if (result.GetOutputData() == nullptr || result.GetOutputData()[0] == '\0') 16639fe00e52SEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 16649fe00e52SEnrico Granata else 16659fe00e52SEnrico Granata result.SetStatus(eReturnStatusSuccessFinishResult); 16669fe00e52SEnrico Granata } 16679fe00e52SEnrico Granata } 16689fe00e52SEnrico Granata 16699fe00e52SEnrico Granata return result.Succeeded(); 16709fe00e52SEnrico Granata } 16719fe00e52SEnrico Granata 16726e3d8e7fSEugene Zelenko private: 16736e3d8e7fSEugene Zelenko StructuredData::GenericSP m_cmd_obj_sp; 16746e3d8e7fSEugene Zelenko ScriptedCommandSynchronicity m_synchro; 16756e3d8e7fSEugene Zelenko bool m_fetched_help_short: 1; 16766e3d8e7fSEugene Zelenko bool m_fetched_help_long: 1; 16779fe00e52SEnrico Granata }; 16789fe00e52SEnrico Granata 1679a9dbf432SEnrico Granata //------------------------------------------------------------------------- 1680a9dbf432SEnrico Granata // CommandObjectCommandsScriptImport 1681a9dbf432SEnrico Granata //------------------------------------------------------------------------- 1682a9dbf432SEnrico Granata 16835a988416SJim Ingham class CommandObjectCommandsScriptImport : public CommandObjectParsed 1684a9dbf432SEnrico Granata { 16855a988416SJim Ingham public: 16865a988416SJim Ingham CommandObjectCommandsScriptImport (CommandInterpreter &interpreter) : 16875a988416SJim Ingham CommandObjectParsed(interpreter, 16885a988416SJim Ingham "command script import", 16895a988416SJim Ingham "Import a scripting module in LLDB.", 16906e3d8e7fSEugene Zelenko nullptr), 1691e1cfbc79STodd Fiala m_options() 16925a988416SJim Ingham { 16935a988416SJim Ingham CommandArgumentEntry arg1; 16945a988416SJim Ingham CommandArgumentData cmd_arg; 16955a988416SJim Ingham 16965a988416SJim Ingham // Define the first (and only) variant of this arg. 16975a988416SJim Ingham cmd_arg.arg_type = eArgTypeFilename; 16983b00e35bSEnrico Granata cmd_arg.arg_repetition = eArgRepeatPlus; 16995a988416SJim Ingham 17005a988416SJim Ingham // There is only one variant this argument could be; put it into the argument entry. 17015a988416SJim Ingham arg1.push_back (cmd_arg); 17025a988416SJim Ingham 17035a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 17045a988416SJim Ingham m_arguments.push_back (arg1); 17055a988416SJim Ingham } 17065a988416SJim Ingham 17076e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptImport() override = default; 17085a988416SJim Ingham 170913d21e9aSBruce Mitchener int 17105a988416SJim Ingham HandleArgumentCompletion (Args &input, 17115a988416SJim Ingham int &cursor_index, 17125a988416SJim Ingham int &cursor_char_position, 17135a988416SJim Ingham OptionElementVector &opt_element_vector, 17145a988416SJim Ingham int match_start_point, 17155a988416SJim Ingham int max_return_elements, 17165a988416SJim Ingham bool &word_complete, 171713d21e9aSBruce Mitchener StringList &matches) override 17185a988416SJim Ingham { 17195a988416SJim Ingham std::string completion_str (input.GetArgumentAtIndex(cursor_index)); 17205a988416SJim Ingham completion_str.erase (cursor_char_position); 17215a988416SJim Ingham 1722e1cfbc79STodd Fiala CommandCompletions::InvokeCommonCompletionCallbacks(GetCommandInterpreter(), 17235a988416SJim Ingham CommandCompletions::eDiskFileCompletion, 17245a988416SJim Ingham completion_str.c_str(), 17255a988416SJim Ingham match_start_point, 17265a988416SJim Ingham max_return_elements, 17276e3d8e7fSEugene Zelenko nullptr, 17285a988416SJim Ingham word_complete, 17295a988416SJim Ingham matches); 17305a988416SJim Ingham return matches.GetSize(); 17315a988416SJim Ingham } 17325a988416SJim Ingham 173313d21e9aSBruce Mitchener Options * 173413d21e9aSBruce Mitchener GetOptions () override 17355a988416SJim Ingham { 17365a988416SJim Ingham return &m_options; 17375a988416SJim Ingham } 17385a988416SJim Ingham 17395a988416SJim Ingham protected: 17400a305db7SEnrico Granata class CommandOptions : public Options 17410a305db7SEnrico Granata { 17420a305db7SEnrico Granata public: 1743e1cfbc79STodd Fiala CommandOptions() : 1744e1cfbc79STodd Fiala Options() 17450a305db7SEnrico Granata { 17460a305db7SEnrico Granata } 17470a305db7SEnrico Granata 17486e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 17490a305db7SEnrico Granata 175013d21e9aSBruce Mitchener Error 1751e1cfbc79STodd Fiala SetOptionValue (uint32_t option_idx, const char *option_arg, 1752e1cfbc79STodd Fiala ExecutionContext *execution_context) override 17530a305db7SEnrico Granata { 17540a305db7SEnrico Granata Error error; 17553bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 17560a305db7SEnrico Granata 17570a305db7SEnrico Granata switch (short_option) 17580a305db7SEnrico Granata { 17590a305db7SEnrico Granata case 'r': 17600a305db7SEnrico Granata m_allow_reload = true; 17610a305db7SEnrico Granata break; 17620a305db7SEnrico Granata default: 17630a305db7SEnrico Granata error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 17640a305db7SEnrico Granata break; 17650a305db7SEnrico Granata } 17660a305db7SEnrico Granata 17670a305db7SEnrico Granata return error; 17680a305db7SEnrico Granata } 17690a305db7SEnrico Granata 17700a305db7SEnrico Granata void 1771e1cfbc79STodd Fiala OptionParsingStarting(ExecutionContext *execution_context) override 17720a305db7SEnrico Granata { 1773e0c70f1bSEnrico Granata m_allow_reload = true; 17740a305db7SEnrico Granata } 17750a305db7SEnrico Granata 17760a305db7SEnrico Granata const OptionDefinition* 177713d21e9aSBruce Mitchener GetDefinitions () override 17780a305db7SEnrico Granata { 17790a305db7SEnrico Granata return g_option_table; 17800a305db7SEnrico Granata } 17810a305db7SEnrico Granata 17820a305db7SEnrico Granata // Options table: Required for subclasses of Options. 17830a305db7SEnrico Granata 17840a305db7SEnrico Granata static OptionDefinition g_option_table[]; 17850a305db7SEnrico Granata 17860a305db7SEnrico Granata // Instance variables to hold the values for command options. 17870a305db7SEnrico Granata 17880a305db7SEnrico Granata bool m_allow_reload; 17890a305db7SEnrico Granata }; 17900a305db7SEnrico Granata 1791a9dbf432SEnrico Granata bool 179213d21e9aSBruce Mitchener DoExecute (Args& command, CommandReturnObject &result) override 1793a9dbf432SEnrico Granata { 1794a9dbf432SEnrico Granata if (m_interpreter.GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) 1795a9dbf432SEnrico Granata { 1796a9dbf432SEnrico Granata result.AppendError ("only scripting language supported for module importing is currently Python"); 1797a9dbf432SEnrico Granata result.SetStatus (eReturnStatusFailed); 1798a9dbf432SEnrico Granata return false; 1799a9dbf432SEnrico Granata } 1800a9dbf432SEnrico Granata 18015a988416SJim Ingham size_t argc = command.GetArgumentCount(); 18023b00e35bSEnrico Granata if (0 == argc) 1803a9dbf432SEnrico Granata { 18043b00e35bSEnrico Granata result.AppendError("command script import needs one or more arguments"); 1805a9dbf432SEnrico Granata result.SetStatus (eReturnStatusFailed); 1806a9dbf432SEnrico Granata return false; 1807a9dbf432SEnrico Granata } 1808a9dbf432SEnrico Granata 18090e978481SEd Maste for (size_t i = 0; 18103b00e35bSEnrico Granata i < argc; 18113b00e35bSEnrico Granata i++) 18123b00e35bSEnrico Granata { 18133b00e35bSEnrico Granata std::string path = command.GetArgumentAtIndex(i); 1814a9dbf432SEnrico Granata Error error; 1815a9dbf432SEnrico Granata 1816c9d645d3SGreg Clayton const bool init_session = true; 1817078551c7SEnrico Granata // FIXME: this is necessary because CommandObject::CheckRequirements() assumes that 1818078551c7SEnrico Granata // commands won't ever be recursively invoked, but it's actually possible to craft 1819078551c7SEnrico Granata // a Python script that does other "command script imports" in __lldb_init_module 1820078551c7SEnrico Granata // the real fix is to have recursive commands possible with a CommandInvocation object 1821078551c7SEnrico Granata // separate from the CommandObject itself, so that recursive command invocations 1822078551c7SEnrico Granata // won't stomp on each other (wrt to execution contents, options, and more) 1823078551c7SEnrico Granata m_exe_ctx.Clear(); 1824a9dbf432SEnrico Granata if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule(path.c_str(), 18250a305db7SEnrico Granata m_options.m_allow_reload, 1826c9d645d3SGreg Clayton init_session, 1827a9dbf432SEnrico Granata error)) 1828a9dbf432SEnrico Granata { 1829a9dbf432SEnrico Granata result.SetStatus (eReturnStatusSuccessFinishNoResult); 1830a9dbf432SEnrico Granata } 1831a9dbf432SEnrico Granata else 1832a9dbf432SEnrico Granata { 1833a9dbf432SEnrico Granata result.AppendErrorWithFormat("module importing failed: %s", error.AsCString()); 1834a9dbf432SEnrico Granata result.SetStatus (eReturnStatusFailed); 1835a9dbf432SEnrico Granata } 18363b00e35bSEnrico Granata } 1837a9dbf432SEnrico Granata 1838a9dbf432SEnrico Granata return result.Succeeded(); 1839a9dbf432SEnrico Granata } 18400a305db7SEnrico Granata 18415a988416SJim Ingham CommandOptions m_options; 1842a9dbf432SEnrico Granata }; 1843223383edSEnrico Granata 18440a305db7SEnrico Granata OptionDefinition 18450a305db7SEnrico Granata CommandObjectCommandsScriptImport::CommandOptions::g_option_table[] = 18460a305db7SEnrico Granata { 1847*ac9c3a62SKate Stone // clang-format off 18486e3d8e7fSEugene 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."}, 18496e3d8e7fSEugene Zelenko {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 1850*ac9c3a62SKate Stone // clang-format on 18510a305db7SEnrico Granata }; 18520a305db7SEnrico Granata 1853223383edSEnrico Granata //------------------------------------------------------------------------- 1854223383edSEnrico Granata // CommandObjectCommandsScriptAdd 1855223383edSEnrico Granata //------------------------------------------------------------------------- 1856223383edSEnrico Granata 185744d93782SGreg Clayton class CommandObjectCommandsScriptAdd : 185844d93782SGreg Clayton public CommandObjectParsed, 185944d93782SGreg Clayton public IOHandlerDelegateMultiline 1860223383edSEnrico Granata { 18615a988416SJim Ingham public: 18625a988416SJim Ingham CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter) : 18635a988416SJim Ingham CommandObjectParsed(interpreter, 18645a988416SJim Ingham "command script add", 18655a988416SJim Ingham "Add a scripted function as an LLDB command.", 18666e3d8e7fSEugene Zelenko nullptr), 1867c3d874a5SGreg Clayton IOHandlerDelegateMultiline ("DONE"), 1868e1cfbc79STodd Fiala m_options() 18695a988416SJim Ingham { 18705a988416SJim Ingham CommandArgumentEntry arg1; 18715a988416SJim Ingham CommandArgumentData cmd_arg; 18725a988416SJim Ingham 18735a988416SJim Ingham // Define the first (and only) variant of this arg. 18745a988416SJim Ingham cmd_arg.arg_type = eArgTypeCommandName; 18755a988416SJim Ingham cmd_arg.arg_repetition = eArgRepeatPlain; 18765a988416SJim Ingham 18775a988416SJim Ingham // There is only one variant this argument could be; put it into the argument entry. 18785a988416SJim Ingham arg1.push_back (cmd_arg); 18795a988416SJim Ingham 18805a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 18815a988416SJim Ingham m_arguments.push_back (arg1); 18825a988416SJim Ingham } 18835a988416SJim Ingham 18846e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptAdd() override = default; 18855a988416SJim Ingham 188613d21e9aSBruce Mitchener Options * 188713d21e9aSBruce Mitchener GetOptions () override 18885a988416SJim Ingham { 18895a988416SJim Ingham return &m_options; 18905a988416SJim Ingham } 18915a988416SJim Ingham 18925a988416SJim Ingham protected: 1893223383edSEnrico Granata class CommandOptions : public Options 1894223383edSEnrico Granata { 1895223383edSEnrico Granata public: 1896e1cfbc79STodd Fiala CommandOptions() : 1897e1cfbc79STodd Fiala Options(), 18989fe00e52SEnrico Granata m_class_name(), 18999fe00e52SEnrico Granata m_funct_name(), 19009fe00e52SEnrico Granata m_short_help(), 19019fe00e52SEnrico Granata m_synchronicity(eScriptedCommandSynchronicitySynchronous) 1902223383edSEnrico Granata { 1903223383edSEnrico Granata } 1904223383edSEnrico Granata 19056e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 1906223383edSEnrico Granata 190713d21e9aSBruce Mitchener Error 1908e1cfbc79STodd Fiala SetOptionValue (uint32_t option_idx, const char *option_arg, 1909e1cfbc79STodd Fiala ExecutionContext *execution_context) override 1910223383edSEnrico Granata { 1911223383edSEnrico Granata Error error; 19123bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 1913223383edSEnrico Granata 1914223383edSEnrico Granata switch (short_option) 1915223383edSEnrico Granata { 1916223383edSEnrico Granata case 'f': 1917735152e3SEnrico Granata if (option_arg) 1918735152e3SEnrico Granata m_funct_name.assign(option_arg); 1919735152e3SEnrico Granata break; 19209fe00e52SEnrico Granata case 'c': 19219fe00e52SEnrico Granata if (option_arg) 19229fe00e52SEnrico Granata m_class_name.assign(option_arg); 19239fe00e52SEnrico Granata break; 1924735152e3SEnrico Granata case 'h': 1925735152e3SEnrico Granata if (option_arg) 1926735152e3SEnrico Granata m_short_help.assign(option_arg); 1927223383edSEnrico Granata break; 19280a305db7SEnrico Granata case 's': 192944d93782SGreg Clayton m_synchronicity = (ScriptedCommandSynchronicity) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error); 19300a305db7SEnrico Granata if (!error.Success()) 19310a305db7SEnrico Granata error.SetErrorStringWithFormat ("unrecognized value for synchronicity '%s'", option_arg); 19320a305db7SEnrico Granata break; 1933223383edSEnrico Granata default: 193486edbf41SGreg Clayton error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1935223383edSEnrico Granata break; 1936223383edSEnrico Granata } 1937223383edSEnrico Granata 1938223383edSEnrico Granata return error; 1939223383edSEnrico Granata } 1940223383edSEnrico Granata 1941223383edSEnrico Granata void 1942e1cfbc79STodd Fiala OptionParsingStarting(ExecutionContext *execution_context) override 1943223383edSEnrico Granata { 19449fe00e52SEnrico Granata m_class_name.clear(); 1945735152e3SEnrico Granata m_funct_name.clear(); 1946735152e3SEnrico Granata m_short_help.clear(); 194744d93782SGreg Clayton m_synchronicity = eScriptedCommandSynchronicitySynchronous; 1948223383edSEnrico Granata } 1949223383edSEnrico Granata 1950223383edSEnrico Granata const OptionDefinition* 195113d21e9aSBruce Mitchener GetDefinitions () override 1952223383edSEnrico Granata { 1953223383edSEnrico Granata return g_option_table; 1954223383edSEnrico Granata } 1955223383edSEnrico Granata 1956223383edSEnrico Granata // Options table: Required for subclasses of Options. 1957223383edSEnrico Granata 1958223383edSEnrico Granata static OptionDefinition g_option_table[]; 1959223383edSEnrico Granata 1960223383edSEnrico Granata // Instance variables to hold the values for command options. 1961223383edSEnrico Granata 19629fe00e52SEnrico Granata std::string m_class_name; 1963223383edSEnrico Granata std::string m_funct_name; 1964735152e3SEnrico Granata std::string m_short_help; 196544d93782SGreg Clayton ScriptedCommandSynchronicity m_synchronicity; 1966223383edSEnrico Granata }; 1967223383edSEnrico Granata 196813d21e9aSBruce Mitchener void 196913d21e9aSBruce Mitchener IOHandlerActivated (IOHandler &io_handler) override 1970223383edSEnrico Granata { 197144d93782SGreg Clayton StreamFileSP output_sp(io_handler.GetOutputStreamFile()); 197244d93782SGreg Clayton if (output_sp) 1973223383edSEnrico Granata { 197444d93782SGreg Clayton output_sp->PutCString(g_python_command_instructions); 197544d93782SGreg Clayton output_sp->Flush(); 1976223383edSEnrico Granata } 1977223383edSEnrico Granata } 1978223383edSEnrico Granata 1979223383edSEnrico Granata 198013d21e9aSBruce Mitchener void 198113d21e9aSBruce Mitchener IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override 1982223383edSEnrico Granata { 198344d93782SGreg Clayton StreamFileSP error_sp = io_handler.GetErrorStreamFile(); 198444d93782SGreg Clayton 198544d93782SGreg Clayton ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); 198644d93782SGreg Clayton if (interpreter) 198744d93782SGreg Clayton { 198844d93782SGreg Clayton 198944d93782SGreg Clayton StringList lines; 199044d93782SGreg Clayton lines.SplitIntoLines(data); 199144d93782SGreg Clayton if (lines.GetSize() > 0) 199244d93782SGreg Clayton { 1993a73b7df7SEnrico Granata std::string funct_name_str; 199444d93782SGreg Clayton if (interpreter->GenerateScriptAliasFunction (lines, funct_name_str)) 1995223383edSEnrico Granata { 1996a73b7df7SEnrico Granata if (funct_name_str.empty()) 1997223383edSEnrico Granata { 199844d93782SGreg Clayton error_sp->Printf ("error: unable to obtain a function name, didn't add python command.\n"); 199944d93782SGreg Clayton error_sp->Flush(); 2000223383edSEnrico Granata } 200144d93782SGreg Clayton else 200244d93782SGreg Clayton { 2003223383edSEnrico Granata // everything should be fine now, let's add this alias 2004223383edSEnrico Granata 2005223383edSEnrico Granata CommandObjectSP command_obj_sp(new CommandObjectPythonFunction (m_interpreter, 2006223383edSEnrico Granata m_cmd_name, 2007a73b7df7SEnrico Granata funct_name_str.c_str(), 2008735152e3SEnrico Granata m_short_help, 200944d93782SGreg Clayton m_synchronicity)); 2010223383edSEnrico Granata 20110a305db7SEnrico Granata if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp, true)) 2012223383edSEnrico Granata { 201344d93782SGreg Clayton error_sp->Printf ("error: unable to add selected command, didn't add python command.\n"); 201444d93782SGreg Clayton error_sp->Flush(); 2015223383edSEnrico Granata } 2016223383edSEnrico Granata } 201744d93782SGreg Clayton } 201844d93782SGreg Clayton else 201944d93782SGreg Clayton { 202044d93782SGreg Clayton error_sp->Printf ("error: unable to create function, didn't add python command.\n"); 202144d93782SGreg Clayton error_sp->Flush(); 202244d93782SGreg Clayton } 202344d93782SGreg Clayton } 202444d93782SGreg Clayton else 202544d93782SGreg Clayton { 202644d93782SGreg Clayton error_sp->Printf ("error: empty function, didn't add python command.\n"); 202744d93782SGreg Clayton error_sp->Flush(); 202844d93782SGreg Clayton } 202944d93782SGreg Clayton } 203044d93782SGreg Clayton else 203144d93782SGreg Clayton { 203244d93782SGreg Clayton error_sp->Printf ("error: script interpreter missing, didn't add python command.\n"); 203344d93782SGreg Clayton error_sp->Flush(); 203444d93782SGreg Clayton } 203544d93782SGreg Clayton 203644d93782SGreg Clayton io_handler.SetIsDone(true); 203744d93782SGreg Clayton } 2038223383edSEnrico Granata 20395a988416SJim Ingham protected: 2040223383edSEnrico Granata bool 204113d21e9aSBruce Mitchener DoExecute (Args& command, CommandReturnObject &result) override 2042223383edSEnrico Granata { 204399f0b8f9SEnrico Granata if (m_interpreter.GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) 204499f0b8f9SEnrico Granata { 204599f0b8f9SEnrico Granata result.AppendError ("only scripting language supported for scripted commands is currently Python"); 204699f0b8f9SEnrico Granata result.SetStatus (eReturnStatusFailed); 204799f0b8f9SEnrico Granata return false; 204899f0b8f9SEnrico Granata } 204999f0b8f9SEnrico Granata 20505a988416SJim Ingham size_t argc = command.GetArgumentCount(); 2051223383edSEnrico Granata 2052223383edSEnrico Granata if (argc != 1) 2053223383edSEnrico Granata { 2054223383edSEnrico Granata result.AppendError ("'command script add' requires one argument"); 2055223383edSEnrico Granata result.SetStatus (eReturnStatusFailed); 2056223383edSEnrico Granata return false; 2057223383edSEnrico Granata } 2058223383edSEnrico Granata 2059735152e3SEnrico Granata // Store the options in case we get multi-line input 206044d93782SGreg Clayton m_cmd_name = command.GetArgumentAtIndex(0); 2061735152e3SEnrico Granata m_short_help.assign(m_options.m_short_help); 206244d93782SGreg Clayton m_synchronicity = m_options.m_synchronicity; 2063223383edSEnrico Granata 20649fe00e52SEnrico Granata if (m_options.m_class_name.empty()) 20659fe00e52SEnrico Granata { 2066223383edSEnrico Granata if (m_options.m_funct_name.empty()) 2067223383edSEnrico Granata { 206844d93782SGreg Clayton m_interpreter.GetPythonCommandsFromIOHandler(" ", // Prompt 206944d93782SGreg Clayton *this, // IOHandlerDelegate 207044d93782SGreg Clayton true, // Run IOHandler in async mode 20716e3d8e7fSEugene Zelenko nullptr); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions 2072223383edSEnrico Granata } 2073223383edSEnrico Granata else 2074223383edSEnrico Granata { 20750a305db7SEnrico Granata CommandObjectSP new_cmd(new CommandObjectPythonFunction(m_interpreter, 207644d93782SGreg Clayton m_cmd_name, 20770a305db7SEnrico Granata m_options.m_funct_name, 2078735152e3SEnrico Granata m_options.m_short_help, 207944d93782SGreg Clayton m_synchronicity)); 208044d93782SGreg Clayton if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) 2081223383edSEnrico Granata { 2082223383edSEnrico Granata result.SetStatus (eReturnStatusSuccessFinishNoResult); 2083223383edSEnrico Granata } 2084223383edSEnrico Granata else 2085223383edSEnrico Granata { 2086223383edSEnrico Granata result.AppendError("cannot add command"); 2087223383edSEnrico Granata result.SetStatus (eReturnStatusFailed); 2088223383edSEnrico Granata } 2089223383edSEnrico Granata } 20909fe00e52SEnrico Granata } 20919fe00e52SEnrico Granata else 20929fe00e52SEnrico Granata { 20939fe00e52SEnrico Granata ScriptInterpreter *interpreter = GetCommandInterpreter().GetScriptInterpreter(); 20949fe00e52SEnrico Granata if (!interpreter) 20959fe00e52SEnrico Granata { 20969fe00e52SEnrico Granata result.AppendError("cannot find ScriptInterpreter"); 20979fe00e52SEnrico Granata result.SetStatus(eReturnStatusFailed); 20989fe00e52SEnrico Granata return false; 20999fe00e52SEnrico Granata } 21009fe00e52SEnrico Granata 21019fe00e52SEnrico Granata auto cmd_obj_sp = interpreter->CreateScriptCommandObject(m_options.m_class_name.c_str()); 21029fe00e52SEnrico Granata if (!cmd_obj_sp) 21039fe00e52SEnrico Granata { 21049fe00e52SEnrico Granata result.AppendError("cannot create helper object"); 21059fe00e52SEnrico Granata result.SetStatus(eReturnStatusFailed); 21069fe00e52SEnrico Granata return false; 21079fe00e52SEnrico Granata } 21089fe00e52SEnrico Granata 21099fe00e52SEnrico Granata CommandObjectSP new_cmd(new CommandObjectScriptingObject(m_interpreter, 21109fe00e52SEnrico Granata m_cmd_name, 21119fe00e52SEnrico Granata cmd_obj_sp, 21129fe00e52SEnrico Granata m_synchronicity)); 21139fe00e52SEnrico Granata if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) 21149fe00e52SEnrico Granata { 21159fe00e52SEnrico Granata result.SetStatus (eReturnStatusSuccessFinishNoResult); 21169fe00e52SEnrico Granata } 21179fe00e52SEnrico Granata else 21189fe00e52SEnrico Granata { 21199fe00e52SEnrico Granata result.AppendError("cannot add command"); 21209fe00e52SEnrico Granata result.SetStatus (eReturnStatusFailed); 21219fe00e52SEnrico Granata } 21229fe00e52SEnrico Granata } 2123223383edSEnrico Granata 2124223383edSEnrico Granata return result.Succeeded(); 2125223383edSEnrico Granata } 21265a988416SJim Ingham 21275a988416SJim Ingham CommandOptions m_options; 212844d93782SGreg Clayton std::string m_cmd_name; 2129735152e3SEnrico Granata std::string m_short_help; 213044d93782SGreg Clayton ScriptedCommandSynchronicity m_synchronicity; 2131223383edSEnrico Granata }; 2132223383edSEnrico Granata 21330a305db7SEnrico Granata static OptionEnumValueElement g_script_synchro_type[] = 21340a305db7SEnrico Granata { 21350a305db7SEnrico Granata { eScriptedCommandSynchronicitySynchronous, "synchronous", "Run synchronous"}, 21360a305db7SEnrico Granata { eScriptedCommandSynchronicityAsynchronous, "asynchronous", "Run asynchronous"}, 21370a305db7SEnrico Granata { eScriptedCommandSynchronicityCurrentValue, "current", "Do not alter current setting"}, 21386e3d8e7fSEugene Zelenko { 0, nullptr, nullptr } 21390a305db7SEnrico Granata }; 21400a305db7SEnrico Granata 2141223383edSEnrico Granata OptionDefinition 2142223383edSEnrico Granata CommandObjectCommandsScriptAdd::CommandOptions::g_option_table[] = 2143223383edSEnrico Granata { 2144*ac9c3a62SKate Stone // clang-format off 21456e3d8e7fSEugene 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."}, 21466e3d8e7fSEugene 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."}, 21476e3d8e7fSEugene Zelenko {LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "The help text to display for this command."}, 21486e3d8e7fSEugene 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."}, 21496e3d8e7fSEugene Zelenko {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} 2150*ac9c3a62SKate Stone // clang-format on 2151223383edSEnrico Granata }; 2152223383edSEnrico Granata 2153223383edSEnrico Granata //------------------------------------------------------------------------- 2154223383edSEnrico Granata // CommandObjectCommandsScriptList 2155223383edSEnrico Granata //------------------------------------------------------------------------- 2156223383edSEnrico Granata 21575a988416SJim Ingham class CommandObjectCommandsScriptList : public CommandObjectParsed 2158223383edSEnrico Granata { 2159223383edSEnrico Granata public: 2160223383edSEnrico Granata CommandObjectCommandsScriptList(CommandInterpreter &interpreter) : 21615a988416SJim Ingham CommandObjectParsed(interpreter, 2162223383edSEnrico Granata "command script list", 2163223383edSEnrico Granata "List defined scripted commands.", 21646e3d8e7fSEugene Zelenko nullptr) 2165223383edSEnrico Granata { 2166223383edSEnrico Granata } 2167223383edSEnrico Granata 21686e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptList() override = default; 2169223383edSEnrico Granata 2170223383edSEnrico Granata bool 217113d21e9aSBruce Mitchener DoExecute (Args& command, CommandReturnObject &result) override 2172223383edSEnrico Granata { 2173223383edSEnrico Granata m_interpreter.GetHelp(result, 2174223383edSEnrico Granata CommandInterpreter::eCommandTypesUserDef); 2175223383edSEnrico Granata 2176223383edSEnrico Granata result.SetStatus (eReturnStatusSuccessFinishResult); 2177223383edSEnrico Granata 2178223383edSEnrico Granata return true; 2179223383edSEnrico Granata } 2180223383edSEnrico Granata }; 2181223383edSEnrico Granata 2182223383edSEnrico Granata //------------------------------------------------------------------------- 2183223383edSEnrico Granata // CommandObjectCommandsScriptClear 2184223383edSEnrico Granata //------------------------------------------------------------------------- 2185223383edSEnrico Granata 21865a988416SJim Ingham class CommandObjectCommandsScriptClear : public CommandObjectParsed 2187223383edSEnrico Granata { 2188223383edSEnrico Granata public: 2189223383edSEnrico Granata CommandObjectCommandsScriptClear(CommandInterpreter &interpreter) : 21905a988416SJim Ingham CommandObjectParsed(interpreter, 2191223383edSEnrico Granata "command script clear", 2192223383edSEnrico Granata "Delete all scripted commands.", 21936e3d8e7fSEugene Zelenko nullptr) 2194223383edSEnrico Granata { 2195223383edSEnrico Granata } 2196223383edSEnrico Granata 21976e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptClear() override = default; 2198223383edSEnrico Granata 21995a988416SJim Ingham protected: 2200223383edSEnrico Granata bool 220113d21e9aSBruce Mitchener DoExecute (Args& command, CommandReturnObject &result) override 2202223383edSEnrico Granata { 2203223383edSEnrico Granata m_interpreter.RemoveAllUser(); 2204223383edSEnrico Granata 2205223383edSEnrico Granata result.SetStatus (eReturnStatusSuccessFinishResult); 2206223383edSEnrico Granata 2207223383edSEnrico Granata return true; 2208223383edSEnrico Granata } 2209223383edSEnrico Granata }; 2210223383edSEnrico Granata 2211223383edSEnrico Granata //------------------------------------------------------------------------- 2212223383edSEnrico Granata // CommandObjectCommandsScriptDelete 2213223383edSEnrico Granata //------------------------------------------------------------------------- 2214223383edSEnrico Granata 22155a988416SJim Ingham class CommandObjectCommandsScriptDelete : public CommandObjectParsed 2216223383edSEnrico Granata { 2217223383edSEnrico Granata public: 2218223383edSEnrico Granata CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter) : 22195a988416SJim Ingham CommandObjectParsed(interpreter, 2220223383edSEnrico Granata "command script delete", 2221223383edSEnrico Granata "Delete a scripted command.", 22226e3d8e7fSEugene Zelenko nullptr) 2223223383edSEnrico Granata { 2224223383edSEnrico Granata CommandArgumentEntry arg1; 2225223383edSEnrico Granata CommandArgumentData cmd_arg; 2226223383edSEnrico Granata 2227223383edSEnrico Granata // Define the first (and only) variant of this arg. 2228223383edSEnrico Granata cmd_arg.arg_type = eArgTypeCommandName; 2229223383edSEnrico Granata cmd_arg.arg_repetition = eArgRepeatPlain; 2230223383edSEnrico Granata 2231223383edSEnrico Granata // There is only one variant this argument could be; put it into the argument entry. 2232223383edSEnrico Granata arg1.push_back (cmd_arg); 2233223383edSEnrico Granata 2234223383edSEnrico Granata // Push the data for the first argument into the m_arguments vector. 2235223383edSEnrico Granata m_arguments.push_back (arg1); 2236223383edSEnrico Granata } 2237223383edSEnrico Granata 22386e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptDelete() override = default; 2239223383edSEnrico Granata 22405a988416SJim Ingham protected: 2241223383edSEnrico Granata bool 224213d21e9aSBruce Mitchener DoExecute (Args& command, CommandReturnObject &result) override 2243223383edSEnrico Granata { 2244223383edSEnrico Granata 22455a988416SJim Ingham size_t argc = command.GetArgumentCount(); 2246223383edSEnrico Granata 2247223383edSEnrico Granata if (argc != 1) 2248223383edSEnrico Granata { 2249223383edSEnrico Granata result.AppendError ("'command script delete' requires one argument"); 2250223383edSEnrico Granata result.SetStatus (eReturnStatusFailed); 2251223383edSEnrico Granata return false; 2252223383edSEnrico Granata } 2253223383edSEnrico Granata 22545a988416SJim Ingham const char* cmd_name = command.GetArgumentAtIndex(0); 2255223383edSEnrico Granata 2256223383edSEnrico Granata if (cmd_name && *cmd_name && m_interpreter.HasUserCommands() && m_interpreter.UserCommandExists(cmd_name)) 2257223383edSEnrico Granata { 2258223383edSEnrico Granata m_interpreter.RemoveUser(cmd_name); 2259223383edSEnrico Granata result.SetStatus (eReturnStatusSuccessFinishResult); 2260223383edSEnrico Granata } 2261223383edSEnrico Granata else 2262223383edSEnrico Granata { 2263223383edSEnrico Granata result.AppendErrorWithFormat ("command %s not found", cmd_name); 2264223383edSEnrico Granata result.SetStatus (eReturnStatusFailed); 2265223383edSEnrico Granata } 2266223383edSEnrico Granata 2267223383edSEnrico Granata return result.Succeeded(); 2268223383edSEnrico Granata } 2269223383edSEnrico Granata }; 2270223383edSEnrico Granata 2271223383edSEnrico Granata #pragma mark CommandObjectMultiwordCommandsScript 2272223383edSEnrico Granata 2273223383edSEnrico Granata //------------------------------------------------------------------------- 2274223383edSEnrico Granata // CommandObjectMultiwordCommandsScript 2275223383edSEnrico Granata //------------------------------------------------------------------------- 2276223383edSEnrico Granata 2277223383edSEnrico Granata class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword 2278223383edSEnrico Granata { 2279223383edSEnrico Granata public: 22807428a18cSKate Stone CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter) 22817428a18cSKate Stone : CommandObjectMultiword(interpreter, "command script", 22827428a18cSKate Stone "Commands for managing custom commands implemented by interpreter scripts.", 2283223383edSEnrico Granata "command script <subcommand> [<subcommand-options>]") 2284223383edSEnrico Granata { 2285223383edSEnrico Granata LoadSubCommand ("add", CommandObjectSP (new CommandObjectCommandsScriptAdd (interpreter))); 2286223383edSEnrico Granata LoadSubCommand ("delete", CommandObjectSP (new CommandObjectCommandsScriptDelete (interpreter))); 2287223383edSEnrico Granata LoadSubCommand ("clear", CommandObjectSP (new CommandObjectCommandsScriptClear (interpreter))); 2288223383edSEnrico Granata LoadSubCommand ("list", CommandObjectSP (new CommandObjectCommandsScriptList (interpreter))); 2289a9dbf432SEnrico Granata LoadSubCommand ("import", CommandObjectSP (new CommandObjectCommandsScriptImport (interpreter))); 2290223383edSEnrico Granata } 2291223383edSEnrico Granata 22926e3d8e7fSEugene Zelenko ~CommandObjectMultiwordCommandsScript() override = default; 2293223383edSEnrico Granata }; 2294223383edSEnrico Granata 2295ebc09c36SJim Ingham #pragma mark CommandObjectMultiwordCommands 2296ebc09c36SJim Ingham 2297ebc09c36SJim Ingham //------------------------------------------------------------------------- 2298ebc09c36SJim Ingham // CommandObjectMultiwordCommands 2299ebc09c36SJim Ingham //------------------------------------------------------------------------- 2300ebc09c36SJim Ingham 23017428a18cSKate Stone CommandObjectMultiwordCommands::CommandObjectMultiwordCommands(CommandInterpreter &interpreter) 23027428a18cSKate Stone : CommandObjectMultiword(interpreter, "command", "Commands for managing custom LLDB commands.", 23030e5e5a79SGreg Clayton "command <subcommand> [<subcommand-options>]") 2304ebc09c36SJim Ingham { 2305a7015092SGreg Clayton LoadSubCommand ("source", CommandObjectSP (new CommandObjectCommandsSource (interpreter))); 2306a7015092SGreg Clayton LoadSubCommand ("alias", CommandObjectSP (new CommandObjectCommandsAlias (interpreter))); 2307a7015092SGreg Clayton LoadSubCommand ("unalias", CommandObjectSP (new CommandObjectCommandsUnalias (interpreter))); 2308b547278cSGreg Clayton LoadSubCommand ("delete", CommandObjectSP (new CommandObjectCommandsDelete (interpreter))); 2309de164aaaSGreg Clayton LoadSubCommand ("regex", CommandObjectSP (new CommandObjectCommandsAddRegex (interpreter))); 2310a5a97ebeSJim Ingham LoadSubCommand ("history", CommandObjectSP (new CommandObjectCommandsHistory (interpreter))); 2311223383edSEnrico Granata LoadSubCommand ("script", CommandObjectSP (new CommandObjectMultiwordCommandsScript (interpreter))); 2312ebc09c36SJim Ingham } 2313ebc09c36SJim Ingham 23146e3d8e7fSEugene Zelenko CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default; 2315