1254721Semaste//===-- CommandInterpreter.cpp ----------------------------------*- C++ -*-===// 2254721Semaste// 3254721Semaste// The LLVM Compiler Infrastructure 4254721Semaste// 5254721Semaste// This file is distributed under the University of Illinois Open Source 6254721Semaste// License. See LICENSE.TXT for details. 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste 10254721Semaste#include "lldb/lldb-python.h" 11254721Semaste 12254721Semaste#include <string> 13254721Semaste#include <vector> 14254721Semaste#include <stdlib.h> 15254721Semaste 16254721Semaste#include "CommandObjectScript.h" 17254721Semaste#include "lldb/Interpreter/CommandObjectRegexCommand.h" 18254721Semaste 19254721Semaste#include "../Commands/CommandObjectApropos.h" 20254721Semaste#include "../Commands/CommandObjectArgs.h" 21254721Semaste#include "../Commands/CommandObjectBreakpoint.h" 22254721Semaste#include "../Commands/CommandObjectDisassemble.h" 23254721Semaste#include "../Commands/CommandObjectExpression.h" 24254721Semaste#include "../Commands/CommandObjectFrame.h" 25269024Semaste#include "../Commands/CommandObjectGUI.h" 26254721Semaste#include "../Commands/CommandObjectHelp.h" 27254721Semaste#include "../Commands/CommandObjectLog.h" 28254721Semaste#include "../Commands/CommandObjectMemory.h" 29254721Semaste#include "../Commands/CommandObjectPlatform.h" 30254721Semaste#include "../Commands/CommandObjectPlugin.h" 31254721Semaste#include "../Commands/CommandObjectProcess.h" 32254721Semaste#include "../Commands/CommandObjectQuit.h" 33254721Semaste#include "../Commands/CommandObjectRegister.h" 34254721Semaste#include "../Commands/CommandObjectSettings.h" 35254721Semaste#include "../Commands/CommandObjectSource.h" 36254721Semaste#include "../Commands/CommandObjectCommands.h" 37254721Semaste#include "../Commands/CommandObjectSyntax.h" 38254721Semaste#include "../Commands/CommandObjectTarget.h" 39254721Semaste#include "../Commands/CommandObjectThread.h" 40254721Semaste#include "../Commands/CommandObjectType.h" 41254721Semaste#include "../Commands/CommandObjectVersion.h" 42254721Semaste#include "../Commands/CommandObjectWatchpoint.h" 43254721Semaste 44254721Semaste 45254721Semaste#include "lldb/Core/Debugger.h" 46254721Semaste#include "lldb/Core/Log.h" 47254721Semaste#include "lldb/Core/Stream.h" 48269024Semaste#include "lldb/Core/StreamFile.h" 49254721Semaste#include "lldb/Core/Timer.h" 50254721Semaste 51269024Semaste#include "lldb/Host/Editline.h" 52254721Semaste#include "lldb/Host/Host.h" 53254721Semaste 54254721Semaste#include "lldb/Interpreter/Args.h" 55254721Semaste#include "lldb/Interpreter/CommandCompletions.h" 56254721Semaste#include "lldb/Interpreter/CommandInterpreter.h" 57254721Semaste#include "lldb/Interpreter/CommandReturnObject.h" 58254721Semaste#include "lldb/Interpreter/Options.h" 59254721Semaste#include "lldb/Interpreter/ScriptInterpreterNone.h" 60254721Semaste#include "lldb/Interpreter/ScriptInterpreterPython.h" 61254721Semaste 62254721Semaste 63254721Semaste#include "lldb/Target/Process.h" 64254721Semaste#include "lldb/Target/Thread.h" 65254721Semaste#include "lldb/Target/TargetList.h" 66254721Semaste 67254721Semaste#include "lldb/Utility/CleanUp.h" 68254721Semaste 69254721Semasteusing namespace lldb; 70254721Semasteusing namespace lldb_private; 71254721Semaste 72254721Semaste 73254721Semastestatic PropertyDefinition 74254721Semasteg_properties[] = 75254721Semaste{ 76254721Semaste { "expand-regex-aliases", OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true, regular expression alias commands will show the expanded command that will be executed. This can be used to debug new regular expression alias commands." }, 77254721Semaste { "prompt-on-quit", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, LLDB will prompt you before quitting if there are any live processes being debugged. If false, LLDB will quit without asking in any case." }, 78254721Semaste { "stop-command-source-on-error", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, LLDB will stop running a 'command source' script upon encountering an error." }, 79254721Semaste { NULL , OptionValue::eTypeInvalid, true, 0 , NULL, NULL, NULL } 80254721Semaste}; 81254721Semaste 82254721Semasteenum 83254721Semaste{ 84254721Semaste ePropertyExpandRegexAliases = 0, 85254721Semaste ePropertyPromptOnQuit = 1, 86254721Semaste ePropertyStopCmdSourceOnError = 2 87254721Semaste}; 88254721Semaste 89254721SemasteConstString & 90254721SemasteCommandInterpreter::GetStaticBroadcasterClass () 91254721Semaste{ 92254721Semaste static ConstString class_name ("lldb.commandInterpreter"); 93254721Semaste return class_name; 94254721Semaste} 95254721Semaste 96254721SemasteCommandInterpreter::CommandInterpreter 97254721Semaste( 98254721Semaste Debugger &debugger, 99254721Semaste ScriptLanguage script_language, 100254721Semaste bool synchronous_execution 101254721Semaste) : 102254721Semaste Broadcaster (&debugger, "lldb.command-interpreter"), 103254721Semaste Properties(OptionValuePropertiesSP(new OptionValueProperties(ConstString("interpreter")))), 104269024Semaste IOHandlerDelegate (IOHandlerDelegate::Completion::LLDBCommand), 105254721Semaste m_debugger (debugger), 106254721Semaste m_synchronous_execution (synchronous_execution), 107254721Semaste m_skip_lldbinit_files (false), 108254721Semaste m_skip_app_init_files (false), 109254721Semaste m_script_interpreter_ap (), 110269024Semaste m_command_io_handler_sp (), 111254721Semaste m_comment_char ('#'), 112254721Semaste m_batch_command_mode (false), 113254721Semaste m_truncation_warning(eNoTruncation), 114254721Semaste m_command_source_depth (0) 115254721Semaste{ 116254721Semaste debugger.SetScriptLanguage (script_language); 117254721Semaste SetEventName (eBroadcastBitThreadShouldExit, "thread-should-exit"); 118254721Semaste SetEventName (eBroadcastBitResetPrompt, "reset-prompt"); 119254721Semaste SetEventName (eBroadcastBitQuitCommandReceived, "quit"); 120254721Semaste CheckInWithManager (); 121254721Semaste m_collection_sp->Initialize (g_properties); 122254721Semaste} 123254721Semaste 124254721Semastebool 125254721SemasteCommandInterpreter::GetExpandRegexAliases () const 126254721Semaste{ 127254721Semaste const uint32_t idx = ePropertyExpandRegexAliases; 128254721Semaste return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); 129254721Semaste} 130254721Semaste 131254721Semastebool 132254721SemasteCommandInterpreter::GetPromptOnQuit () const 133254721Semaste{ 134254721Semaste const uint32_t idx = ePropertyPromptOnQuit; 135254721Semaste return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); 136254721Semaste} 137254721Semaste 138254721Semastebool 139254721SemasteCommandInterpreter::GetStopCmdSourceOnError () const 140254721Semaste{ 141254721Semaste const uint32_t idx = ePropertyStopCmdSourceOnError; 142254721Semaste return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); 143254721Semaste} 144254721Semaste 145254721Semastevoid 146254721SemasteCommandInterpreter::Initialize () 147254721Semaste{ 148254721Semaste Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); 149254721Semaste 150254721Semaste CommandReturnObject result; 151254721Semaste 152254721Semaste LoadCommandDictionary (); 153254721Semaste 154254721Semaste // Set up some initial aliases. 155254721Semaste CommandObjectSP cmd_obj_sp = GetCommandSPExact ("quit", false); 156254721Semaste if (cmd_obj_sp) 157254721Semaste { 158254721Semaste AddAlias ("q", cmd_obj_sp); 159254721Semaste AddAlias ("exit", cmd_obj_sp); 160254721Semaste } 161254721Semaste 162254721Semaste cmd_obj_sp = GetCommandSPExact ("_regexp-attach",false); 163254721Semaste if (cmd_obj_sp) 164254721Semaste { 165254721Semaste AddAlias ("attach", cmd_obj_sp); 166254721Semaste } 167254721Semaste 168254721Semaste cmd_obj_sp = GetCommandSPExact ("process detach",false); 169254721Semaste if (cmd_obj_sp) 170254721Semaste { 171254721Semaste AddAlias ("detach", cmd_obj_sp); 172254721Semaste } 173254721Semaste 174254721Semaste cmd_obj_sp = GetCommandSPExact ("process continue", false); 175254721Semaste if (cmd_obj_sp) 176254721Semaste { 177254721Semaste AddAlias ("c", cmd_obj_sp); 178254721Semaste AddAlias ("continue", cmd_obj_sp); 179254721Semaste } 180254721Semaste 181254721Semaste cmd_obj_sp = GetCommandSPExact ("_regexp-break",false); 182254721Semaste if (cmd_obj_sp) 183254721Semaste AddAlias ("b", cmd_obj_sp); 184254721Semaste 185254721Semaste cmd_obj_sp = GetCommandSPExact ("_regexp-tbreak",false); 186254721Semaste if (cmd_obj_sp) 187254721Semaste AddAlias ("tbreak", cmd_obj_sp); 188254721Semaste 189254721Semaste cmd_obj_sp = GetCommandSPExact ("thread step-inst", false); 190254721Semaste if (cmd_obj_sp) 191254721Semaste { 192254721Semaste AddAlias ("stepi", cmd_obj_sp); 193254721Semaste AddAlias ("si", cmd_obj_sp); 194254721Semaste } 195254721Semaste 196254721Semaste cmd_obj_sp = GetCommandSPExact ("thread step-inst-over", false); 197254721Semaste if (cmd_obj_sp) 198254721Semaste { 199254721Semaste AddAlias ("nexti", cmd_obj_sp); 200254721Semaste AddAlias ("ni", cmd_obj_sp); 201254721Semaste } 202254721Semaste 203254721Semaste cmd_obj_sp = GetCommandSPExact ("thread step-in", false); 204254721Semaste if (cmd_obj_sp) 205254721Semaste { 206254721Semaste AddAlias ("s", cmd_obj_sp); 207254721Semaste AddAlias ("step", cmd_obj_sp); 208254721Semaste } 209254721Semaste 210254721Semaste cmd_obj_sp = GetCommandSPExact ("thread step-over", false); 211254721Semaste if (cmd_obj_sp) 212254721Semaste { 213254721Semaste AddAlias ("n", cmd_obj_sp); 214254721Semaste AddAlias ("next", cmd_obj_sp); 215254721Semaste } 216254721Semaste 217254721Semaste cmd_obj_sp = GetCommandSPExact ("thread step-out", false); 218254721Semaste if (cmd_obj_sp) 219254721Semaste { 220254721Semaste AddAlias ("finish", cmd_obj_sp); 221254721Semaste } 222254721Semaste 223254721Semaste cmd_obj_sp = GetCommandSPExact ("frame select", false); 224254721Semaste if (cmd_obj_sp) 225254721Semaste { 226254721Semaste AddAlias ("f", cmd_obj_sp); 227254721Semaste } 228254721Semaste 229254721Semaste cmd_obj_sp = GetCommandSPExact ("thread select", false); 230254721Semaste if (cmd_obj_sp) 231254721Semaste { 232254721Semaste AddAlias ("t", cmd_obj_sp); 233254721Semaste } 234254721Semaste 235263363Semaste cmd_obj_sp = GetCommandSPExact ("_regexp-jump",false); 236263363Semaste if (cmd_obj_sp) 237263363Semaste { 238263363Semaste AddAlias ("j", cmd_obj_sp); 239263363Semaste AddAlias ("jump", cmd_obj_sp); 240263363Semaste } 241263363Semaste 242254721Semaste cmd_obj_sp = GetCommandSPExact ("_regexp-list", false); 243254721Semaste if (cmd_obj_sp) 244254721Semaste { 245254721Semaste AddAlias ("l", cmd_obj_sp); 246254721Semaste AddAlias ("list", cmd_obj_sp); 247254721Semaste } 248254721Semaste 249254721Semaste cmd_obj_sp = GetCommandSPExact ("_regexp-env", false); 250254721Semaste if (cmd_obj_sp) 251254721Semaste { 252254721Semaste AddAlias ("env", cmd_obj_sp); 253254721Semaste } 254254721Semaste 255254721Semaste cmd_obj_sp = GetCommandSPExact ("memory read", false); 256254721Semaste if (cmd_obj_sp) 257254721Semaste AddAlias ("x", cmd_obj_sp); 258254721Semaste 259254721Semaste cmd_obj_sp = GetCommandSPExact ("_regexp-up", false); 260254721Semaste if (cmd_obj_sp) 261254721Semaste AddAlias ("up", cmd_obj_sp); 262254721Semaste 263254721Semaste cmd_obj_sp = GetCommandSPExact ("_regexp-down", false); 264254721Semaste if (cmd_obj_sp) 265254721Semaste AddAlias ("down", cmd_obj_sp); 266254721Semaste 267254721Semaste cmd_obj_sp = GetCommandSPExact ("_regexp-display", false); 268254721Semaste if (cmd_obj_sp) 269254721Semaste AddAlias ("display", cmd_obj_sp); 270254721Semaste 271254721Semaste cmd_obj_sp = GetCommandSPExact ("disassemble", false); 272254721Semaste if (cmd_obj_sp) 273254721Semaste AddAlias ("dis", cmd_obj_sp); 274254721Semaste 275254721Semaste cmd_obj_sp = GetCommandSPExact ("disassemble", false); 276254721Semaste if (cmd_obj_sp) 277254721Semaste AddAlias ("di", cmd_obj_sp); 278254721Semaste 279254721Semaste 280254721Semaste 281254721Semaste cmd_obj_sp = GetCommandSPExact ("_regexp-undisplay", false); 282254721Semaste if (cmd_obj_sp) 283254721Semaste AddAlias ("undisplay", cmd_obj_sp); 284254721Semaste 285254721Semaste cmd_obj_sp = GetCommandSPExact ("_regexp-bt", false); 286254721Semaste if (cmd_obj_sp) 287254721Semaste AddAlias ("bt", cmd_obj_sp); 288254721Semaste 289254721Semaste cmd_obj_sp = GetCommandSPExact ("target create", false); 290254721Semaste if (cmd_obj_sp) 291254721Semaste AddAlias ("file", cmd_obj_sp); 292254721Semaste 293254721Semaste cmd_obj_sp = GetCommandSPExact ("target modules", false); 294254721Semaste if (cmd_obj_sp) 295254721Semaste AddAlias ("image", cmd_obj_sp); 296254721Semaste 297254721Semaste 298254721Semaste OptionArgVectorSP alias_arguments_vector_sp (new OptionArgVector); 299254721Semaste 300254721Semaste cmd_obj_sp = GetCommandSPExact ("expression", false); 301254721Semaste if (cmd_obj_sp) 302254721Semaste { 303254721Semaste ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp); 304254721Semaste AddAlias ("p", cmd_obj_sp); 305254721Semaste AddAlias ("print", cmd_obj_sp); 306254721Semaste AddAlias ("call", cmd_obj_sp); 307254721Semaste AddOrReplaceAliasOptions ("p", alias_arguments_vector_sp); 308254721Semaste AddOrReplaceAliasOptions ("print", alias_arguments_vector_sp); 309254721Semaste AddOrReplaceAliasOptions ("call", alias_arguments_vector_sp); 310254721Semaste 311254721Semaste alias_arguments_vector_sp.reset (new OptionArgVector); 312254721Semaste ProcessAliasOptionsArgs (cmd_obj_sp, "-O -- ", alias_arguments_vector_sp); 313254721Semaste AddAlias ("po", cmd_obj_sp); 314254721Semaste AddOrReplaceAliasOptions ("po", alias_arguments_vector_sp); 315254721Semaste } 316254721Semaste 317254721Semaste cmd_obj_sp = GetCommandSPExact ("process kill", false); 318254721Semaste if (cmd_obj_sp) 319254721Semaste { 320254721Semaste AddAlias ("kill", cmd_obj_sp); 321254721Semaste } 322254721Semaste 323254721Semaste cmd_obj_sp = GetCommandSPExact ("process launch", false); 324254721Semaste if (cmd_obj_sp) 325254721Semaste { 326254721Semaste alias_arguments_vector_sp.reset (new OptionArgVector); 327254721Semaste#if defined (__arm__) 328254721Semaste ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp); 329254721Semaste#else 330263363Semaste ProcessAliasOptionsArgs (cmd_obj_sp, "--shell=" LLDB_DEFAULT_SHELL " --", alias_arguments_vector_sp); 331254721Semaste#endif 332254721Semaste AddAlias ("r", cmd_obj_sp); 333254721Semaste AddAlias ("run", cmd_obj_sp); 334254721Semaste AddOrReplaceAliasOptions ("r", alias_arguments_vector_sp); 335254721Semaste AddOrReplaceAliasOptions ("run", alias_arguments_vector_sp); 336254721Semaste } 337254721Semaste 338254721Semaste cmd_obj_sp = GetCommandSPExact ("target symbols add", false); 339254721Semaste if (cmd_obj_sp) 340254721Semaste { 341254721Semaste AddAlias ("add-dsym", cmd_obj_sp); 342254721Semaste } 343254721Semaste 344254721Semaste cmd_obj_sp = GetCommandSPExact ("breakpoint set", false); 345254721Semaste if (cmd_obj_sp) 346254721Semaste { 347254721Semaste alias_arguments_vector_sp.reset (new OptionArgVector); 348254721Semaste ProcessAliasOptionsArgs (cmd_obj_sp, "--func-regex %1", alias_arguments_vector_sp); 349254721Semaste AddAlias ("rbreak", cmd_obj_sp); 350254721Semaste AddOrReplaceAliasOptions("rbreak", alias_arguments_vector_sp); 351254721Semaste } 352254721Semaste} 353254721Semaste 354254721Semasteconst char * 355254721SemasteCommandInterpreter::ProcessEmbeddedScriptCommands (const char *arg) 356254721Semaste{ 357254721Semaste // This function has not yet been implemented. 358254721Semaste 359254721Semaste // Look for any embedded script command 360254721Semaste // If found, 361254721Semaste // get interpreter object from the command dictionary, 362254721Semaste // call execute_one_command on it, 363254721Semaste // get the results as a string, 364254721Semaste // substitute that string for current stuff. 365254721Semaste 366254721Semaste return arg; 367254721Semaste} 368254721Semaste 369254721Semaste 370254721Semastevoid 371254721SemasteCommandInterpreter::LoadCommandDictionary () 372254721Semaste{ 373254721Semaste Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); 374254721Semaste 375254721Semaste lldb::ScriptLanguage script_language = m_debugger.GetScriptLanguage(); 376254721Semaste 377254721Semaste m_command_dict["apropos"] = CommandObjectSP (new CommandObjectApropos (*this)); 378254721Semaste m_command_dict["breakpoint"]= CommandObjectSP (new CommandObjectMultiwordBreakpoint (*this)); 379254721Semaste m_command_dict["command"] = CommandObjectSP (new CommandObjectMultiwordCommands (*this)); 380254721Semaste m_command_dict["disassemble"] = CommandObjectSP (new CommandObjectDisassemble (*this)); 381254721Semaste m_command_dict["expression"]= CommandObjectSP (new CommandObjectExpression (*this)); 382254721Semaste m_command_dict["frame"] = CommandObjectSP (new CommandObjectMultiwordFrame (*this)); 383269024Semaste m_command_dict["gui"] = CommandObjectSP (new CommandObjectGUI (*this)); 384254721Semaste m_command_dict["help"] = CommandObjectSP (new CommandObjectHelp (*this)); 385254721Semaste m_command_dict["log"] = CommandObjectSP (new CommandObjectLog (*this)); 386254721Semaste m_command_dict["memory"] = CommandObjectSP (new CommandObjectMemory (*this)); 387254721Semaste m_command_dict["platform"] = CommandObjectSP (new CommandObjectPlatform (*this)); 388254721Semaste m_command_dict["plugin"] = CommandObjectSP (new CommandObjectPlugin (*this)); 389254721Semaste m_command_dict["process"] = CommandObjectSP (new CommandObjectMultiwordProcess (*this)); 390254721Semaste m_command_dict["quit"] = CommandObjectSP (new CommandObjectQuit (*this)); 391254721Semaste m_command_dict["register"] = CommandObjectSP (new CommandObjectRegister (*this)); 392254721Semaste m_command_dict["script"] = CommandObjectSP (new CommandObjectScript (*this, script_language)); 393254721Semaste m_command_dict["settings"] = CommandObjectSP (new CommandObjectMultiwordSettings (*this)); 394254721Semaste m_command_dict["source"] = CommandObjectSP (new CommandObjectMultiwordSource (*this)); 395254721Semaste m_command_dict["target"] = CommandObjectSP (new CommandObjectMultiwordTarget (*this)); 396254721Semaste m_command_dict["thread"] = CommandObjectSP (new CommandObjectMultiwordThread (*this)); 397254721Semaste m_command_dict["type"] = CommandObjectSP (new CommandObjectType (*this)); 398254721Semaste m_command_dict["version"] = CommandObjectSP (new CommandObjectVersion (*this)); 399254721Semaste m_command_dict["watchpoint"]= CommandObjectSP (new CommandObjectMultiwordWatchpoint (*this)); 400254721Semaste 401254721Semaste const char *break_regexes[][2] = {{"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "breakpoint set --file '%1' --line %2"}, 402254721Semaste {"^([[:digit:]]+)[[:space:]]*$", "breakpoint set --line %1"}, 403254721Semaste {"^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1"}, 404254721Semaste {"^[\"']?([-+]?\\[.*\\])[\"']?[[:space:]]*$", "breakpoint set --name '%1'"}, 405254721Semaste {"^(-.*)$", "breakpoint set %1"}, 406254721Semaste {"^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%2' --shlib '%1'"}, 407254721Semaste {"^\\&(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1' --skip-prologue=0"}, 408254721Semaste {"^(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1'"}}; 409254721Semaste 410254721Semaste size_t num_regexes = sizeof break_regexes/sizeof(char *[2]); 411254721Semaste 412254721Semaste std::unique_ptr<CommandObjectRegexCommand> 413254721Semaste break_regex_cmd_ap(new CommandObjectRegexCommand (*this, 414254721Semaste "_regexp-break", 415254721Semaste "Set a breakpoint using a regular expression to specify the location, where <linenum> is in decimal and <address> is in hex.", 416254721Semaste "_regexp-break [<filename>:<linenum>]\n_regexp-break [<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>", 417254721Semaste 2, 418254721Semaste CommandCompletions::eSymbolCompletion | 419254721Semaste CommandCompletions::eSourceFileCompletion)); 420254721Semaste 421254721Semaste if (break_regex_cmd_ap.get()) 422254721Semaste { 423254721Semaste bool success = true; 424254721Semaste for (size_t i = 0; i < num_regexes; i++) 425254721Semaste { 426254721Semaste success = break_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], break_regexes[i][1]); 427254721Semaste if (!success) 428254721Semaste break; 429254721Semaste } 430254721Semaste success = break_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full"); 431254721Semaste 432254721Semaste if (success) 433254721Semaste { 434254721Semaste CommandObjectSP break_regex_cmd_sp(break_regex_cmd_ap.release()); 435254721Semaste m_command_dict[break_regex_cmd_sp->GetCommandName ()] = break_regex_cmd_sp; 436254721Semaste } 437254721Semaste } 438254721Semaste 439254721Semaste std::unique_ptr<CommandObjectRegexCommand> 440254721Semaste tbreak_regex_cmd_ap(new CommandObjectRegexCommand (*this, 441254721Semaste "_regexp-tbreak", 442254721Semaste "Set a one shot breakpoint using a regular expression to specify the location, where <linenum> is in decimal and <address> is in hex.", 443254721Semaste "_regexp-tbreak [<filename>:<linenum>]\n_regexp-break [<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>", 444254721Semaste 2, 445254721Semaste CommandCompletions::eSymbolCompletion | 446254721Semaste CommandCompletions::eSourceFileCompletion)); 447254721Semaste 448254721Semaste if (tbreak_regex_cmd_ap.get()) 449254721Semaste { 450254721Semaste bool success = true; 451254721Semaste for (size_t i = 0; i < num_regexes; i++) 452254721Semaste { 453254721Semaste // If you add a resultant command string longer than 1024 characters be sure to increase the size of this buffer. 454254721Semaste char buffer[1024]; 455254721Semaste int num_printed = snprintf(buffer, 1024, "%s %s", break_regexes[i][1], "-o"); 456254721Semaste assert (num_printed < 1024); 457254721Semaste success = tbreak_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], buffer); 458254721Semaste if (!success) 459254721Semaste break; 460254721Semaste } 461254721Semaste success = tbreak_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full"); 462254721Semaste 463254721Semaste if (success) 464254721Semaste { 465254721Semaste CommandObjectSP tbreak_regex_cmd_sp(tbreak_regex_cmd_ap.release()); 466254721Semaste m_command_dict[tbreak_regex_cmd_sp->GetCommandName ()] = tbreak_regex_cmd_sp; 467254721Semaste } 468254721Semaste } 469254721Semaste 470254721Semaste std::unique_ptr<CommandObjectRegexCommand> 471254721Semaste attach_regex_cmd_ap(new CommandObjectRegexCommand (*this, 472254721Semaste "_regexp-attach", 473254721Semaste "Attach to a process id if in decimal, otherwise treat the argument as a process name to attach to.", 474254721Semaste "_regexp-attach [<pid>]\n_regexp-attach [<process-name>]", 475254721Semaste 2)); 476254721Semaste if (attach_regex_cmd_ap.get()) 477254721Semaste { 478254721Semaste if (attach_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "process attach --pid %1") && 479254721Semaste attach_regex_cmd_ap->AddRegexCommand("^(-.*|.* -.*)$", "process attach %1") && // Any options that are specified get passed to 'process attach' 480254721Semaste attach_regex_cmd_ap->AddRegexCommand("^(.+)$", "process attach --name '%1'") && 481254721Semaste attach_regex_cmd_ap->AddRegexCommand("^$", "process attach")) 482254721Semaste { 483254721Semaste CommandObjectSP attach_regex_cmd_sp(attach_regex_cmd_ap.release()); 484254721Semaste m_command_dict[attach_regex_cmd_sp->GetCommandName ()] = attach_regex_cmd_sp; 485254721Semaste } 486254721Semaste } 487254721Semaste 488254721Semaste std::unique_ptr<CommandObjectRegexCommand> 489254721Semaste down_regex_cmd_ap(new CommandObjectRegexCommand (*this, 490254721Semaste "_regexp-down", 491254721Semaste "Go down \"n\" frames in the stack (1 frame by default).", 492254721Semaste "_regexp-down [n]", 2)); 493254721Semaste if (down_regex_cmd_ap.get()) 494254721Semaste { 495254721Semaste if (down_regex_cmd_ap->AddRegexCommand("^$", "frame select -r -1") && 496254721Semaste down_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r -%1")) 497254721Semaste { 498254721Semaste CommandObjectSP down_regex_cmd_sp(down_regex_cmd_ap.release()); 499254721Semaste m_command_dict[down_regex_cmd_sp->GetCommandName ()] = down_regex_cmd_sp; 500254721Semaste } 501254721Semaste } 502254721Semaste 503254721Semaste std::unique_ptr<CommandObjectRegexCommand> 504254721Semaste up_regex_cmd_ap(new CommandObjectRegexCommand (*this, 505254721Semaste "_regexp-up", 506254721Semaste "Go up \"n\" frames in the stack (1 frame by default).", 507254721Semaste "_regexp-up [n]", 2)); 508254721Semaste if (up_regex_cmd_ap.get()) 509254721Semaste { 510254721Semaste if (up_regex_cmd_ap->AddRegexCommand("^$", "frame select -r 1") && 511254721Semaste up_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r %1")) 512254721Semaste { 513254721Semaste CommandObjectSP up_regex_cmd_sp(up_regex_cmd_ap.release()); 514254721Semaste m_command_dict[up_regex_cmd_sp->GetCommandName ()] = up_regex_cmd_sp; 515254721Semaste } 516254721Semaste } 517254721Semaste 518254721Semaste std::unique_ptr<CommandObjectRegexCommand> 519254721Semaste display_regex_cmd_ap(new CommandObjectRegexCommand (*this, 520254721Semaste "_regexp-display", 521254721Semaste "Add an expression evaluation stop-hook.", 522254721Semaste "_regexp-display expression", 2)); 523254721Semaste if (display_regex_cmd_ap.get()) 524254721Semaste { 525254721Semaste if (display_regex_cmd_ap->AddRegexCommand("^(.+)$", "target stop-hook add -o \"expr -- %1\"")) 526254721Semaste { 527254721Semaste CommandObjectSP display_regex_cmd_sp(display_regex_cmd_ap.release()); 528254721Semaste m_command_dict[display_regex_cmd_sp->GetCommandName ()] = display_regex_cmd_sp; 529254721Semaste } 530254721Semaste } 531254721Semaste 532254721Semaste std::unique_ptr<CommandObjectRegexCommand> 533254721Semaste undisplay_regex_cmd_ap(new CommandObjectRegexCommand (*this, 534254721Semaste "_regexp-undisplay", 535254721Semaste "Remove an expression evaluation stop-hook.", 536254721Semaste "_regexp-undisplay stop-hook-number", 2)); 537254721Semaste if (undisplay_regex_cmd_ap.get()) 538254721Semaste { 539254721Semaste if (undisplay_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "target stop-hook delete %1")) 540254721Semaste { 541254721Semaste CommandObjectSP undisplay_regex_cmd_sp(undisplay_regex_cmd_ap.release()); 542254721Semaste m_command_dict[undisplay_regex_cmd_sp->GetCommandName ()] = undisplay_regex_cmd_sp; 543254721Semaste } 544254721Semaste } 545254721Semaste 546254721Semaste std::unique_ptr<CommandObjectRegexCommand> 547254721Semaste connect_gdb_remote_cmd_ap(new CommandObjectRegexCommand (*this, 548254721Semaste "gdb-remote", 549254721Semaste "Connect to a remote GDB server. If no hostname is provided, localhost is assumed.", 550254721Semaste "gdb-remote [<hostname>:]<portnum>", 2)); 551254721Semaste if (connect_gdb_remote_cmd_ap.get()) 552254721Semaste { 553254721Semaste if (connect_gdb_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin gdb-remote connect://%1") && 554254721Semaste connect_gdb_remote_cmd_ap->AddRegexCommand("^([[:digit:]]+)$", "process connect --plugin gdb-remote connect://localhost:%1")) 555254721Semaste { 556254721Semaste CommandObjectSP command_sp(connect_gdb_remote_cmd_ap.release()); 557254721Semaste m_command_dict[command_sp->GetCommandName ()] = command_sp; 558254721Semaste } 559254721Semaste } 560254721Semaste 561254721Semaste std::unique_ptr<CommandObjectRegexCommand> 562254721Semaste connect_kdp_remote_cmd_ap(new CommandObjectRegexCommand (*this, 563254721Semaste "kdp-remote", 564254721Semaste "Connect to a remote KDP server. udp port 41139 is the default port number.", 565254721Semaste "kdp-remote <hostname>[:<portnum>]", 2)); 566254721Semaste if (connect_kdp_remote_cmd_ap.get()) 567254721Semaste { 568254721Semaste if (connect_kdp_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin kdp-remote udp://%1") && 569254721Semaste connect_kdp_remote_cmd_ap->AddRegexCommand("^(.+)$", "process connect --plugin kdp-remote udp://%1:41139")) 570254721Semaste { 571254721Semaste CommandObjectSP command_sp(connect_kdp_remote_cmd_ap.release()); 572254721Semaste m_command_dict[command_sp->GetCommandName ()] = command_sp; 573254721Semaste } 574254721Semaste } 575254721Semaste 576254721Semaste std::unique_ptr<CommandObjectRegexCommand> 577254721Semaste bt_regex_cmd_ap(new CommandObjectRegexCommand (*this, 578254721Semaste "_regexp-bt", 579254721Semaste "Show a backtrace. An optional argument is accepted; if that argument is a number, it specifies the number of frames to display. If that argument is 'all', full backtraces of all threads are displayed.", 580254721Semaste "bt [<digit>|all]", 2)); 581254721Semaste if (bt_regex_cmd_ap.get()) 582254721Semaste { 583254721Semaste // accept but don't document "bt -c <number>" -- before bt was a regex command if you wanted to backtrace 584254721Semaste // three frames you would do "bt -c 3" but the intention is to have this emulate the gdb "bt" command and 585254721Semaste // so now "bt 3" is the preferred form, in line with gdb. 586254721Semaste if (bt_regex_cmd_ap->AddRegexCommand("^([[:digit:]]+)$", "thread backtrace -c %1") && 587254721Semaste bt_regex_cmd_ap->AddRegexCommand("^-c ([[:digit:]]+)$", "thread backtrace -c %1") && 588254721Semaste bt_regex_cmd_ap->AddRegexCommand("^all$", "thread backtrace all") && 589254721Semaste bt_regex_cmd_ap->AddRegexCommand("^$", "thread backtrace")) 590254721Semaste { 591254721Semaste CommandObjectSP command_sp(bt_regex_cmd_ap.release()); 592254721Semaste m_command_dict[command_sp->GetCommandName ()] = command_sp; 593254721Semaste } 594254721Semaste } 595254721Semaste 596254721Semaste std::unique_ptr<CommandObjectRegexCommand> 597254721Semaste list_regex_cmd_ap(new CommandObjectRegexCommand (*this, 598254721Semaste "_regexp-list", 599254721Semaste "Implements the GDB 'list' command in all of its forms except FILE:FUNCTION and maps them to the appropriate 'source list' commands.", 600263363Semaste "_regexp-list [<line>]\n_regexp-list [<file>:<line>]\n_regexp-list [<file>:<line>]", 601254721Semaste 2, 602254721Semaste CommandCompletions::eSourceFileCompletion)); 603254721Semaste if (list_regex_cmd_ap.get()) 604254721Semaste { 605254721Semaste if (list_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "source list --line %1") && 606254721Semaste list_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "source list --file '%1' --line %2") && 607254721Semaste list_regex_cmd_ap->AddRegexCommand("^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "source list --address %1") && 608254721Semaste list_regex_cmd_ap->AddRegexCommand("^-[[:space:]]*$", "source list --reverse") && 609254721Semaste list_regex_cmd_ap->AddRegexCommand("^-([[:digit:]]+)[[:space:]]*$", "source list --reverse --count %1") && 610254721Semaste list_regex_cmd_ap->AddRegexCommand("^(.+)$", "source list --name \"%1\"") && 611254721Semaste list_regex_cmd_ap->AddRegexCommand("^$", "source list")) 612254721Semaste { 613254721Semaste CommandObjectSP list_regex_cmd_sp(list_regex_cmd_ap.release()); 614254721Semaste m_command_dict[list_regex_cmd_sp->GetCommandName ()] = list_regex_cmd_sp; 615254721Semaste } 616254721Semaste } 617254721Semaste 618254721Semaste std::unique_ptr<CommandObjectRegexCommand> 619254721Semaste env_regex_cmd_ap(new CommandObjectRegexCommand (*this, 620254721Semaste "_regexp-env", 621254721Semaste "Implements a shortcut to viewing and setting environment variables.", 622254721Semaste "_regexp-env\n_regexp-env FOO=BAR", 2)); 623254721Semaste if (env_regex_cmd_ap.get()) 624254721Semaste { 625254721Semaste if (env_regex_cmd_ap->AddRegexCommand("^$", "settings show target.env-vars") && 626254721Semaste env_regex_cmd_ap->AddRegexCommand("^([A-Za-z_][A-Za-z_0-9]*=.*)$", "settings set target.env-vars %1")) 627254721Semaste { 628254721Semaste CommandObjectSP env_regex_cmd_sp(env_regex_cmd_ap.release()); 629254721Semaste m_command_dict[env_regex_cmd_sp->GetCommandName ()] = env_regex_cmd_sp; 630254721Semaste } 631254721Semaste } 632254721Semaste 633263363Semaste std::unique_ptr<CommandObjectRegexCommand> 634263363Semaste jump_regex_cmd_ap(new CommandObjectRegexCommand (*this, 635263363Semaste "_regexp-jump", 636263363Semaste "Sets the program counter to a new address.", 637263363Semaste "_regexp-jump [<line>]\n" 638263363Semaste "_regexp-jump [<+-lineoffset>]\n" 639263363Semaste "_regexp-jump [<file>:<line>]\n" 640263363Semaste "_regexp-jump [*<addr>]\n", 2)); 641263363Semaste if (jump_regex_cmd_ap.get()) 642263363Semaste { 643263363Semaste if (jump_regex_cmd_ap->AddRegexCommand("^\\*(.*)$", "thread jump --addr %1") && 644263363Semaste jump_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "thread jump --line %1") && 645263363Semaste jump_regex_cmd_ap->AddRegexCommand("^([^:]+):([0-9]+)$", "thread jump --file %1 --line %2") && 646263363Semaste jump_regex_cmd_ap->AddRegexCommand("^([+\\-][0-9]+)$", "thread jump --by %1")) 647263363Semaste { 648263363Semaste CommandObjectSP jump_regex_cmd_sp(jump_regex_cmd_ap.release()); 649263363Semaste m_command_dict[jump_regex_cmd_sp->GetCommandName ()] = jump_regex_cmd_sp; 650263363Semaste } 651263363Semaste } 652263363Semaste 653254721Semaste} 654254721Semaste 655254721Semasteint 656254721SemasteCommandInterpreter::GetCommandNamesMatchingPartialString (const char *cmd_str, bool include_aliases, 657254721Semaste StringList &matches) 658254721Semaste{ 659254721Semaste CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_str, matches); 660254721Semaste 661254721Semaste if (include_aliases) 662254721Semaste { 663254721Semaste CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd_str, matches); 664254721Semaste } 665254721Semaste 666254721Semaste return matches.GetSize(); 667254721Semaste} 668254721Semaste 669254721SemasteCommandObjectSP 670254721SemasteCommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bool exact, StringList *matches) 671254721Semaste{ 672254721Semaste CommandObject::CommandMap::iterator pos; 673254721Semaste CommandObjectSP command_sp; 674254721Semaste 675254721Semaste std::string cmd(cmd_cstr); 676254721Semaste 677254721Semaste if (HasCommands()) 678254721Semaste { 679254721Semaste pos = m_command_dict.find(cmd); 680254721Semaste if (pos != m_command_dict.end()) 681254721Semaste command_sp = pos->second; 682254721Semaste } 683254721Semaste 684254721Semaste if (include_aliases && HasAliases()) 685254721Semaste { 686254721Semaste pos = m_alias_dict.find(cmd); 687254721Semaste if (pos != m_alias_dict.end()) 688254721Semaste command_sp = pos->second; 689254721Semaste } 690254721Semaste 691254721Semaste if (HasUserCommands()) 692254721Semaste { 693254721Semaste pos = m_user_dict.find(cmd); 694254721Semaste if (pos != m_user_dict.end()) 695254721Semaste command_sp = pos->second; 696254721Semaste } 697254721Semaste 698254721Semaste if (!exact && !command_sp) 699254721Semaste { 700254721Semaste // We will only get into here if we didn't find any exact matches. 701254721Semaste 702254721Semaste CommandObjectSP user_match_sp, alias_match_sp, real_match_sp; 703254721Semaste 704254721Semaste StringList local_matches; 705254721Semaste if (matches == NULL) 706254721Semaste matches = &local_matches; 707254721Semaste 708254721Semaste unsigned int num_cmd_matches = 0; 709254721Semaste unsigned int num_alias_matches = 0; 710254721Semaste unsigned int num_user_matches = 0; 711254721Semaste 712254721Semaste // Look through the command dictionaries one by one, and if we get only one match from any of 713254721Semaste // them in toto, then return that, otherwise return an empty CommandObjectSP and the list of matches. 714254721Semaste 715254721Semaste if (HasCommands()) 716254721Semaste { 717254721Semaste num_cmd_matches = CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_cstr, *matches); 718254721Semaste } 719254721Semaste 720254721Semaste if (num_cmd_matches == 1) 721254721Semaste { 722254721Semaste cmd.assign(matches->GetStringAtIndex(0)); 723254721Semaste pos = m_command_dict.find(cmd); 724254721Semaste if (pos != m_command_dict.end()) 725254721Semaste real_match_sp = pos->second; 726254721Semaste } 727254721Semaste 728254721Semaste if (include_aliases && HasAliases()) 729254721Semaste { 730254721Semaste num_alias_matches = CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd_cstr, *matches); 731254721Semaste 732254721Semaste } 733254721Semaste 734254721Semaste if (num_alias_matches == 1) 735254721Semaste { 736254721Semaste cmd.assign(matches->GetStringAtIndex (num_cmd_matches)); 737254721Semaste pos = m_alias_dict.find(cmd); 738254721Semaste if (pos != m_alias_dict.end()) 739254721Semaste alias_match_sp = pos->second; 740254721Semaste } 741254721Semaste 742254721Semaste if (HasUserCommands()) 743254721Semaste { 744254721Semaste num_user_matches = CommandObject::AddNamesMatchingPartialString (m_user_dict, cmd_cstr, *matches); 745254721Semaste } 746254721Semaste 747254721Semaste if (num_user_matches == 1) 748254721Semaste { 749254721Semaste cmd.assign (matches->GetStringAtIndex (num_cmd_matches + num_alias_matches)); 750254721Semaste 751254721Semaste pos = m_user_dict.find (cmd); 752254721Semaste if (pos != m_user_dict.end()) 753254721Semaste user_match_sp = pos->second; 754254721Semaste } 755254721Semaste 756254721Semaste // If we got exactly one match, return that, otherwise return the match list. 757254721Semaste 758254721Semaste if (num_user_matches + num_cmd_matches + num_alias_matches == 1) 759254721Semaste { 760254721Semaste if (num_cmd_matches) 761254721Semaste return real_match_sp; 762254721Semaste else if (num_alias_matches) 763254721Semaste return alias_match_sp; 764254721Semaste else 765254721Semaste return user_match_sp; 766254721Semaste } 767254721Semaste } 768254721Semaste else if (matches && command_sp) 769254721Semaste { 770254721Semaste matches->AppendString (cmd_cstr); 771254721Semaste } 772254721Semaste 773254721Semaste 774254721Semaste return command_sp; 775254721Semaste} 776254721Semaste 777254721Semastebool 778254721SemasteCommandInterpreter::AddCommand (const char *name, const lldb::CommandObjectSP &cmd_sp, bool can_replace) 779254721Semaste{ 780254721Semaste if (name && name[0]) 781254721Semaste { 782254721Semaste std::string name_sstr(name); 783254721Semaste bool found = (m_command_dict.find (name_sstr) != m_command_dict.end()); 784254721Semaste if (found && !can_replace) 785254721Semaste return false; 786254721Semaste if (found && m_command_dict[name_sstr]->IsRemovable() == false) 787254721Semaste return false; 788254721Semaste m_command_dict[name_sstr] = cmd_sp; 789254721Semaste return true; 790254721Semaste } 791254721Semaste return false; 792254721Semaste} 793254721Semaste 794254721Semastebool 795254721SemasteCommandInterpreter::AddUserCommand (std::string name, 796254721Semaste const lldb::CommandObjectSP &cmd_sp, 797254721Semaste bool can_replace) 798254721Semaste{ 799254721Semaste if (!name.empty()) 800254721Semaste { 801254721Semaste 802254721Semaste const char* name_cstr = name.c_str(); 803254721Semaste 804254721Semaste // do not allow replacement of internal commands 805254721Semaste if (CommandExists(name_cstr)) 806254721Semaste { 807254721Semaste if (can_replace == false) 808254721Semaste return false; 809254721Semaste if (m_command_dict[name]->IsRemovable() == false) 810254721Semaste return false; 811254721Semaste } 812254721Semaste 813254721Semaste if (UserCommandExists(name_cstr)) 814254721Semaste { 815254721Semaste if (can_replace == false) 816254721Semaste return false; 817254721Semaste if (m_user_dict[name]->IsRemovable() == false) 818254721Semaste return false; 819254721Semaste } 820254721Semaste 821254721Semaste m_user_dict[name] = cmd_sp; 822254721Semaste return true; 823254721Semaste } 824254721Semaste return false; 825254721Semaste} 826254721Semaste 827254721SemasteCommandObjectSP 828254721SemasteCommandInterpreter::GetCommandSPExact (const char *cmd_cstr, bool include_aliases) 829254721Semaste{ 830254721Semaste Args cmd_words (cmd_cstr); // Break up the command string into words, in case it's a multi-word command. 831254721Semaste CommandObjectSP ret_val; // Possibly empty return value. 832254721Semaste 833254721Semaste if (cmd_cstr == NULL) 834254721Semaste return ret_val; 835254721Semaste 836254721Semaste if (cmd_words.GetArgumentCount() == 1) 837254721Semaste return GetCommandSP(cmd_cstr, include_aliases, true, NULL); 838254721Semaste else 839254721Semaste { 840254721Semaste // We have a multi-word command (seemingly), so we need to do more work. 841254721Semaste // First, get the cmd_obj_sp for the first word in the command. 842254721Semaste CommandObjectSP cmd_obj_sp = GetCommandSP (cmd_words.GetArgumentAtIndex (0), include_aliases, true, NULL); 843254721Semaste if (cmd_obj_sp.get() != NULL) 844254721Semaste { 845254721Semaste // Loop through the rest of the words in the command (everything passed in was supposed to be part of a 846254721Semaste // command name), and find the appropriate sub-command SP for each command word.... 847254721Semaste size_t end = cmd_words.GetArgumentCount(); 848254721Semaste for (size_t j= 1; j < end; ++j) 849254721Semaste { 850254721Semaste if (cmd_obj_sp->IsMultiwordObject()) 851254721Semaste { 852254721Semaste cmd_obj_sp = cmd_obj_sp->GetSubcommandSP (cmd_words.GetArgumentAtIndex (j)); 853254721Semaste if (cmd_obj_sp.get() == NULL) 854254721Semaste // The sub-command name was invalid. Fail and return the empty 'ret_val'. 855254721Semaste return ret_val; 856254721Semaste } 857254721Semaste else 858254721Semaste // We have more words in the command name, but we don't have a multiword object. Fail and return 859254721Semaste // empty 'ret_val'. 860254721Semaste return ret_val; 861254721Semaste } 862254721Semaste // We successfully looped through all the command words and got valid command objects for them. Assign the 863254721Semaste // last object retrieved to 'ret_val'. 864254721Semaste ret_val = cmd_obj_sp; 865254721Semaste } 866254721Semaste } 867254721Semaste return ret_val; 868254721Semaste} 869254721Semaste 870254721SemasteCommandObject * 871254721SemasteCommandInterpreter::GetCommandObjectExact (const char *cmd_cstr, bool include_aliases) 872254721Semaste{ 873254721Semaste return GetCommandSPExact (cmd_cstr, include_aliases).get(); 874254721Semaste} 875254721Semaste 876254721SemasteCommandObject * 877254721SemasteCommandInterpreter::GetCommandObject (const char *cmd_cstr, StringList *matches) 878254721Semaste{ 879254721Semaste CommandObject *command_obj = GetCommandSP (cmd_cstr, false, true, matches).get(); 880254721Semaste 881254721Semaste // If we didn't find an exact match to the command string in the commands, look in 882254721Semaste // the aliases. 883254721Semaste 884254721Semaste if (command_obj) 885254721Semaste return command_obj; 886254721Semaste 887254721Semaste command_obj = GetCommandSP (cmd_cstr, true, true, matches).get(); 888254721Semaste 889254721Semaste if (command_obj) 890254721Semaste return command_obj; 891254721Semaste 892254721Semaste // If there wasn't an exact match then look for an inexact one in just the commands 893254721Semaste command_obj = GetCommandSP(cmd_cstr, false, false, NULL).get(); 894254721Semaste 895254721Semaste // Finally, if there wasn't an inexact match among the commands, look for an inexact 896254721Semaste // match in both the commands and aliases. 897254721Semaste 898254721Semaste if (command_obj) 899254721Semaste { 900254721Semaste if (matches) 901254721Semaste matches->AppendString(command_obj->GetCommandName()); 902254721Semaste return command_obj; 903254721Semaste } 904254721Semaste 905254721Semaste return GetCommandSP(cmd_cstr, true, false, matches).get(); 906254721Semaste} 907254721Semaste 908254721Semastebool 909254721SemasteCommandInterpreter::CommandExists (const char *cmd) 910254721Semaste{ 911254721Semaste return m_command_dict.find(cmd) != m_command_dict.end(); 912254721Semaste} 913254721Semaste 914254721Semastebool 915254721SemasteCommandInterpreter::ProcessAliasOptionsArgs (lldb::CommandObjectSP &cmd_obj_sp, 916254721Semaste const char *options_args, 917254721Semaste OptionArgVectorSP &option_arg_vector_sp) 918254721Semaste{ 919254721Semaste bool success = true; 920254721Semaste OptionArgVector *option_arg_vector = option_arg_vector_sp.get(); 921254721Semaste 922254721Semaste if (!options_args || (strlen (options_args) < 1)) 923254721Semaste return true; 924254721Semaste 925254721Semaste std::string options_string (options_args); 926254721Semaste Args args (options_args); 927254721Semaste CommandReturnObject result; 928254721Semaste // Check to see if the command being aliased can take any command options. 929254721Semaste Options *options = cmd_obj_sp->GetOptions (); 930254721Semaste if (options) 931254721Semaste { 932254721Semaste // See if any options were specified as part of the alias; if so, handle them appropriately. 933254721Semaste options->NotifyOptionParsingStarting (); 934254721Semaste args.Unshift ("dummy_arg"); 935254721Semaste args.ParseAliasOptions (*options, result, option_arg_vector, options_string); 936254721Semaste args.Shift (); 937254721Semaste if (result.Succeeded()) 938254721Semaste options->VerifyPartialOptions (result); 939254721Semaste if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted) 940254721Semaste { 941254721Semaste result.AppendError ("Unable to create requested alias.\n"); 942254721Semaste return false; 943254721Semaste } 944254721Semaste } 945254721Semaste 946254721Semaste if (!options_string.empty()) 947254721Semaste { 948254721Semaste if (cmd_obj_sp->WantsRawCommandString ()) 949254721Semaste option_arg_vector->push_back (OptionArgPair ("<argument>", 950254721Semaste OptionArgValue (-1, 951254721Semaste options_string))); 952254721Semaste else 953254721Semaste { 954254721Semaste const size_t argc = args.GetArgumentCount(); 955254721Semaste for (size_t i = 0; i < argc; ++i) 956254721Semaste if (strcmp (args.GetArgumentAtIndex (i), "") != 0) 957254721Semaste option_arg_vector->push_back 958254721Semaste (OptionArgPair ("<argument>", 959254721Semaste OptionArgValue (-1, 960254721Semaste std::string (args.GetArgumentAtIndex (i))))); 961254721Semaste } 962254721Semaste } 963254721Semaste 964254721Semaste return success; 965254721Semaste} 966254721Semaste 967254721Semastebool 968254721SemasteCommandInterpreter::GetAliasFullName (const char *cmd, std::string &full_name) 969254721Semaste{ 970254721Semaste bool exact_match = (m_alias_dict.find(cmd) != m_alias_dict.end()); 971254721Semaste if (exact_match) 972254721Semaste { 973254721Semaste full_name.assign(cmd); 974254721Semaste return exact_match; 975254721Semaste } 976254721Semaste else 977254721Semaste { 978254721Semaste StringList matches; 979254721Semaste size_t num_alias_matches; 980254721Semaste num_alias_matches = CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd, matches); 981254721Semaste if (num_alias_matches == 1) 982254721Semaste { 983254721Semaste // Make sure this isn't shadowing a command in the regular command space: 984254721Semaste StringList regular_matches; 985254721Semaste const bool include_aliases = false; 986254721Semaste const bool exact = false; 987254721Semaste CommandObjectSP cmd_obj_sp(GetCommandSP (cmd, include_aliases, exact, ®ular_matches)); 988254721Semaste if (cmd_obj_sp || regular_matches.GetSize() > 0) 989254721Semaste return false; 990254721Semaste else 991254721Semaste { 992254721Semaste full_name.assign (matches.GetStringAtIndex(0)); 993254721Semaste return true; 994254721Semaste } 995254721Semaste } 996254721Semaste else 997254721Semaste return false; 998254721Semaste } 999254721Semaste} 1000254721Semaste 1001254721Semastebool 1002254721SemasteCommandInterpreter::AliasExists (const char *cmd) 1003254721Semaste{ 1004254721Semaste return m_alias_dict.find(cmd) != m_alias_dict.end(); 1005254721Semaste} 1006254721Semaste 1007254721Semastebool 1008254721SemasteCommandInterpreter::UserCommandExists (const char *cmd) 1009254721Semaste{ 1010254721Semaste return m_user_dict.find(cmd) != m_user_dict.end(); 1011254721Semaste} 1012254721Semaste 1013254721Semastevoid 1014254721SemasteCommandInterpreter::AddAlias (const char *alias_name, CommandObjectSP& command_obj_sp) 1015254721Semaste{ 1016254721Semaste command_obj_sp->SetIsAlias (true); 1017254721Semaste m_alias_dict[alias_name] = command_obj_sp; 1018254721Semaste} 1019254721Semaste 1020254721Semastebool 1021254721SemasteCommandInterpreter::RemoveAlias (const char *alias_name) 1022254721Semaste{ 1023254721Semaste CommandObject::CommandMap::iterator pos = m_alias_dict.find(alias_name); 1024254721Semaste if (pos != m_alias_dict.end()) 1025254721Semaste { 1026254721Semaste m_alias_dict.erase(pos); 1027254721Semaste return true; 1028254721Semaste } 1029254721Semaste return false; 1030254721Semaste} 1031254721Semastebool 1032254721SemasteCommandInterpreter::RemoveUser (const char *alias_name) 1033254721Semaste{ 1034254721Semaste CommandObject::CommandMap::iterator pos = m_user_dict.find(alias_name); 1035254721Semaste if (pos != m_user_dict.end()) 1036254721Semaste { 1037254721Semaste m_user_dict.erase(pos); 1038254721Semaste return true; 1039254721Semaste } 1040254721Semaste return false; 1041254721Semaste} 1042254721Semaste 1043254721Semastevoid 1044254721SemasteCommandInterpreter::GetAliasHelp (const char *alias_name, const char *command_name, StreamString &help_string) 1045254721Semaste{ 1046254721Semaste help_string.Printf ("'%s", command_name); 1047254721Semaste OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name); 1048254721Semaste 1049254721Semaste if (option_arg_vector_sp) 1050254721Semaste { 1051254721Semaste OptionArgVector *options = option_arg_vector_sp.get(); 1052254721Semaste for (size_t i = 0; i < options->size(); ++i) 1053254721Semaste { 1054254721Semaste OptionArgPair cur_option = (*options)[i]; 1055254721Semaste std::string opt = cur_option.first; 1056254721Semaste OptionArgValue value_pair = cur_option.second; 1057254721Semaste std::string value = value_pair.second; 1058254721Semaste if (opt.compare("<argument>") == 0) 1059254721Semaste { 1060254721Semaste help_string.Printf (" %s", value.c_str()); 1061254721Semaste } 1062254721Semaste else 1063254721Semaste { 1064254721Semaste help_string.Printf (" %s", opt.c_str()); 1065254721Semaste if ((value.compare ("<no-argument>") != 0) 1066254721Semaste && (value.compare ("<need-argument") != 0)) 1067254721Semaste { 1068254721Semaste help_string.Printf (" %s", value.c_str()); 1069254721Semaste } 1070254721Semaste } 1071254721Semaste } 1072254721Semaste } 1073254721Semaste 1074254721Semaste help_string.Printf ("'"); 1075254721Semaste} 1076254721Semaste 1077254721Semastesize_t 1078254721SemasteCommandInterpreter::FindLongestCommandWord (CommandObject::CommandMap &dict) 1079254721Semaste{ 1080254721Semaste CommandObject::CommandMap::const_iterator pos; 1081254721Semaste CommandObject::CommandMap::const_iterator end = dict.end(); 1082254721Semaste size_t max_len = 0; 1083254721Semaste 1084254721Semaste for (pos = dict.begin(); pos != end; ++pos) 1085254721Semaste { 1086254721Semaste size_t len = pos->first.size(); 1087254721Semaste if (max_len < len) 1088254721Semaste max_len = len; 1089254721Semaste } 1090254721Semaste return max_len; 1091254721Semaste} 1092254721Semaste 1093254721Semastevoid 1094254721SemasteCommandInterpreter::GetHelp (CommandReturnObject &result, 1095254721Semaste uint32_t cmd_types) 1096254721Semaste{ 1097254721Semaste CommandObject::CommandMap::const_iterator pos; 1098254721Semaste size_t max_len = FindLongestCommandWord (m_command_dict); 1099254721Semaste 1100254721Semaste if ( (cmd_types & eCommandTypesBuiltin) == eCommandTypesBuiltin ) 1101254721Semaste { 1102254721Semaste 1103254721Semaste result.AppendMessage("The following is a list of built-in, permanent debugger commands:"); 1104254721Semaste result.AppendMessage(""); 1105254721Semaste 1106254721Semaste for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos) 1107254721Semaste { 1108254721Semaste OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(), 1109254721Semaste max_len); 1110254721Semaste } 1111254721Semaste result.AppendMessage(""); 1112254721Semaste 1113254721Semaste } 1114254721Semaste 1115254721Semaste if (!m_alias_dict.empty() && ( (cmd_types & eCommandTypesAliases) == eCommandTypesAliases )) 1116254721Semaste { 1117254721Semaste result.AppendMessage("The following is a list of your current command abbreviations " 1118254721Semaste "(see 'help command alias' for more info):"); 1119254721Semaste result.AppendMessage(""); 1120254721Semaste max_len = FindLongestCommandWord (m_alias_dict); 1121254721Semaste 1122254721Semaste for (pos = m_alias_dict.begin(); pos != m_alias_dict.end(); ++pos) 1123254721Semaste { 1124254721Semaste StreamString sstr; 1125254721Semaste StreamString translation_and_help; 1126254721Semaste std::string entry_name = pos->first; 1127254721Semaste std::string second_entry = pos->second.get()->GetCommandName(); 1128254721Semaste GetAliasHelp (pos->first.c_str(), pos->second->GetCommandName(), sstr); 1129254721Semaste 1130254721Semaste translation_and_help.Printf ("(%s) %s", sstr.GetData(), pos->second->GetHelp()); 1131254721Semaste OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", 1132254721Semaste translation_and_help.GetData(), max_len); 1133254721Semaste } 1134254721Semaste result.AppendMessage(""); 1135254721Semaste } 1136254721Semaste 1137254721Semaste if (!m_user_dict.empty() && ( (cmd_types & eCommandTypesUserDef) == eCommandTypesUserDef )) 1138254721Semaste { 1139254721Semaste result.AppendMessage ("The following is a list of your current user-defined commands:"); 1140254721Semaste result.AppendMessage(""); 1141254721Semaste max_len = FindLongestCommandWord (m_user_dict); 1142254721Semaste for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos) 1143254721Semaste { 1144254721Semaste OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(), 1145254721Semaste max_len); 1146254721Semaste } 1147254721Semaste result.AppendMessage(""); 1148254721Semaste } 1149254721Semaste 1150254721Semaste result.AppendMessage("For more information on any particular command, try 'help <command-name>'."); 1151254721Semaste} 1152254721Semaste 1153254721SemasteCommandObject * 1154254721SemasteCommandInterpreter::GetCommandObjectForCommand (std::string &command_string) 1155254721Semaste{ 1156254721Semaste // This function finds the final, lowest-level, alias-resolved command object whose 'Execute' function will 1157254721Semaste // eventually be invoked by the given command line. 1158254721Semaste 1159254721Semaste CommandObject *cmd_obj = NULL; 1160254721Semaste std::string white_space (" \t\v"); 1161254721Semaste size_t start = command_string.find_first_not_of (white_space); 1162254721Semaste size_t end = 0; 1163254721Semaste bool done = false; 1164254721Semaste while (!done) 1165254721Semaste { 1166254721Semaste if (start != std::string::npos) 1167254721Semaste { 1168254721Semaste // Get the next word from command_string. 1169254721Semaste end = command_string.find_first_of (white_space, start); 1170254721Semaste if (end == std::string::npos) 1171254721Semaste end = command_string.size(); 1172254721Semaste std::string cmd_word = command_string.substr (start, end - start); 1173254721Semaste 1174254721Semaste if (cmd_obj == NULL) 1175254721Semaste // Since cmd_obj is NULL we are on our first time through this loop. Check to see if cmd_word is a valid 1176254721Semaste // command or alias. 1177254721Semaste cmd_obj = GetCommandObject (cmd_word.c_str()); 1178254721Semaste else if (cmd_obj->IsMultiwordObject ()) 1179254721Semaste { 1180254721Semaste // Our current object is a multi-word object; see if the cmd_word is a valid sub-command for our object. 1181254721Semaste CommandObject *sub_cmd_obj = cmd_obj->GetSubcommandObject (cmd_word.c_str()); 1182254721Semaste if (sub_cmd_obj) 1183254721Semaste cmd_obj = sub_cmd_obj; 1184254721Semaste else // cmd_word was not a valid sub-command word, so we are donee 1185254721Semaste done = true; 1186254721Semaste } 1187254721Semaste else 1188254721Semaste // We have a cmd_obj and it is not a multi-word object, so we are done. 1189254721Semaste done = true; 1190254721Semaste 1191254721Semaste // If we didn't find a valid command object, or our command object is not a multi-word object, or 1192254721Semaste // we are at the end of the command_string, then we are done. Otherwise, find the start of the 1193254721Semaste // next word. 1194254721Semaste 1195254721Semaste if (!cmd_obj || !cmd_obj->IsMultiwordObject() || end >= command_string.size()) 1196254721Semaste done = true; 1197254721Semaste else 1198254721Semaste start = command_string.find_first_not_of (white_space, end); 1199254721Semaste } 1200254721Semaste else 1201254721Semaste // Unable to find any more words. 1202254721Semaste done = true; 1203254721Semaste } 1204254721Semaste 1205254721Semaste if (end == command_string.size()) 1206254721Semaste command_string.clear(); 1207254721Semaste else 1208254721Semaste command_string = command_string.substr(end); 1209254721Semaste 1210254721Semaste return cmd_obj; 1211254721Semaste} 1212254721Semaste 1213254721Semastestatic const char *k_white_space = " \t\v"; 1214254721Semastestatic const char *k_valid_command_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"; 1215254721Semastestatic void 1216254721SemasteStripLeadingSpaces (std::string &s) 1217254721Semaste{ 1218254721Semaste if (!s.empty()) 1219254721Semaste { 1220254721Semaste size_t pos = s.find_first_not_of (k_white_space); 1221254721Semaste if (pos == std::string::npos) 1222254721Semaste s.clear(); 1223254721Semaste else if (pos == 0) 1224254721Semaste return; 1225254721Semaste s.erase (0, pos); 1226254721Semaste } 1227254721Semaste} 1228254721Semaste 1229254721Semastestatic size_t 1230254721SemasteFindArgumentTerminator (const std::string &s) 1231254721Semaste{ 1232254721Semaste const size_t s_len = s.size(); 1233254721Semaste size_t offset = 0; 1234254721Semaste while (offset < s_len) 1235254721Semaste { 1236254721Semaste size_t pos = s.find ("--", offset); 1237254721Semaste if (pos == std::string::npos) 1238254721Semaste break; 1239254721Semaste if (pos > 0) 1240254721Semaste { 1241254721Semaste if (isspace(s[pos-1])) 1242254721Semaste { 1243254721Semaste // Check if the string ends "\s--" (where \s is a space character) 1244254721Semaste // or if we have "\s--\s". 1245254721Semaste if ((pos + 2 >= s_len) || isspace(s[pos+2])) 1246254721Semaste { 1247254721Semaste return pos; 1248254721Semaste } 1249254721Semaste } 1250254721Semaste } 1251254721Semaste offset = pos + 2; 1252254721Semaste } 1253254721Semaste return std::string::npos; 1254254721Semaste} 1255254721Semaste 1256254721Semastestatic bool 1257254721SemasteExtractCommand (std::string &command_string, std::string &command, std::string &suffix, char "e_char) 1258254721Semaste{ 1259254721Semaste command.clear(); 1260254721Semaste suffix.clear(); 1261254721Semaste StripLeadingSpaces (command_string); 1262254721Semaste 1263254721Semaste bool result = false; 1264254721Semaste quote_char = '\0'; 1265254721Semaste 1266254721Semaste if (!command_string.empty()) 1267254721Semaste { 1268254721Semaste const char first_char = command_string[0]; 1269254721Semaste if (first_char == '\'' || first_char == '"') 1270254721Semaste { 1271254721Semaste quote_char = first_char; 1272254721Semaste const size_t end_quote_pos = command_string.find (quote_char, 1); 1273254721Semaste if (end_quote_pos == std::string::npos) 1274254721Semaste { 1275254721Semaste command.swap (command_string); 1276254721Semaste command_string.erase (); 1277254721Semaste } 1278254721Semaste else 1279254721Semaste { 1280254721Semaste command.assign (command_string, 1, end_quote_pos - 1); 1281254721Semaste if (end_quote_pos + 1 < command_string.size()) 1282254721Semaste command_string.erase (0, command_string.find_first_not_of (k_white_space, end_quote_pos + 1)); 1283254721Semaste else 1284254721Semaste command_string.erase (); 1285254721Semaste } 1286254721Semaste } 1287254721Semaste else 1288254721Semaste { 1289254721Semaste const size_t first_space_pos = command_string.find_first_of (k_white_space); 1290254721Semaste if (first_space_pos == std::string::npos) 1291254721Semaste { 1292254721Semaste command.swap (command_string); 1293254721Semaste command_string.erase(); 1294254721Semaste } 1295254721Semaste else 1296254721Semaste { 1297254721Semaste command.assign (command_string, 0, first_space_pos); 1298254721Semaste command_string.erase(0, command_string.find_first_not_of (k_white_space, first_space_pos)); 1299254721Semaste } 1300254721Semaste } 1301254721Semaste result = true; 1302254721Semaste } 1303254721Semaste 1304254721Semaste 1305254721Semaste if (!command.empty()) 1306254721Semaste { 1307254721Semaste // actual commands can't start with '-' or '_' 1308254721Semaste if (command[0] != '-' && command[0] != '_') 1309254721Semaste { 1310254721Semaste size_t pos = command.find_first_not_of(k_valid_command_chars); 1311254721Semaste if (pos > 0 && pos != std::string::npos) 1312254721Semaste { 1313254721Semaste suffix.assign (command.begin() + pos, command.end()); 1314254721Semaste command.erase (pos); 1315254721Semaste } 1316254721Semaste } 1317254721Semaste } 1318254721Semaste 1319254721Semaste return result; 1320254721Semaste} 1321254721Semaste 1322254721SemasteCommandObject * 1323254721SemasteCommandInterpreter::BuildAliasResult (const char *alias_name, 1324254721Semaste std::string &raw_input_string, 1325254721Semaste std::string &alias_result, 1326254721Semaste CommandReturnObject &result) 1327254721Semaste{ 1328254721Semaste CommandObject *alias_cmd_obj = NULL; 1329254721Semaste Args cmd_args (raw_input_string.c_str()); 1330254721Semaste alias_cmd_obj = GetCommandObject (alias_name); 1331254721Semaste StreamString result_str; 1332254721Semaste 1333254721Semaste if (alias_cmd_obj) 1334254721Semaste { 1335254721Semaste std::string alias_name_str = alias_name; 1336254721Semaste if ((cmd_args.GetArgumentCount() == 0) 1337254721Semaste || (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0)) 1338254721Semaste cmd_args.Unshift (alias_name); 1339254721Semaste 1340254721Semaste result_str.Printf ("%s", alias_cmd_obj->GetCommandName ()); 1341254721Semaste OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name); 1342254721Semaste 1343254721Semaste if (option_arg_vector_sp.get()) 1344254721Semaste { 1345254721Semaste OptionArgVector *option_arg_vector = option_arg_vector_sp.get(); 1346254721Semaste 1347254721Semaste for (size_t i = 0; i < option_arg_vector->size(); ++i) 1348254721Semaste { 1349254721Semaste OptionArgPair option_pair = (*option_arg_vector)[i]; 1350254721Semaste OptionArgValue value_pair = option_pair.second; 1351254721Semaste int value_type = value_pair.first; 1352254721Semaste std::string option = option_pair.first; 1353254721Semaste std::string value = value_pair.second; 1354254721Semaste if (option.compare ("<argument>") == 0) 1355254721Semaste result_str.Printf (" %s", value.c_str()); 1356254721Semaste else 1357254721Semaste { 1358254721Semaste result_str.Printf (" %s", option.c_str()); 1359263363Semaste if (value_type != OptionParser::eOptionalArgument) 1360254721Semaste result_str.Printf (" "); 1361263363Semaste if (value.compare ("<OptionParser::eNoArgument>") != 0) 1362254721Semaste { 1363254721Semaste int index = GetOptionArgumentPosition (value.c_str()); 1364254721Semaste if (index == 0) 1365254721Semaste result_str.Printf ("%s", value.c_str()); 1366254721Semaste else if (index >= cmd_args.GetArgumentCount()) 1367254721Semaste { 1368254721Semaste 1369254721Semaste result.AppendErrorWithFormat 1370254721Semaste ("Not enough arguments provided; you need at least %d arguments to use this alias.\n", 1371254721Semaste index); 1372254721Semaste result.SetStatus (eReturnStatusFailed); 1373254721Semaste return alias_cmd_obj; 1374254721Semaste } 1375254721Semaste else 1376254721Semaste { 1377254721Semaste size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index)); 1378254721Semaste if (strpos != std::string::npos) 1379254721Semaste raw_input_string = raw_input_string.erase (strpos, 1380254721Semaste strlen (cmd_args.GetArgumentAtIndex (index))); 1381254721Semaste result_str.Printf ("%s", cmd_args.GetArgumentAtIndex (index)); 1382254721Semaste } 1383254721Semaste } 1384254721Semaste } 1385254721Semaste } 1386254721Semaste } 1387254721Semaste 1388254721Semaste alias_result = result_str.GetData(); 1389254721Semaste } 1390254721Semaste return alias_cmd_obj; 1391254721Semaste} 1392254721Semaste 1393254721SemasteError 1394254721SemasteCommandInterpreter::PreprocessCommand (std::string &command) 1395254721Semaste{ 1396254721Semaste // The command preprocessor needs to do things to the command 1397254721Semaste // line before any parsing of arguments or anything else is done. 1398254721Semaste // The only current stuff that gets proprocessed is anyting enclosed 1399254721Semaste // in backtick ('`') characters is evaluated as an expression and 1400254721Semaste // the result of the expression must be a scalar that can be substituted 1401254721Semaste // into the command. An example would be: 1402254721Semaste // (lldb) memory read `$rsp + 20` 1403254721Semaste Error error; // Error for any expressions that might not evaluate 1404254721Semaste size_t start_backtick; 1405254721Semaste size_t pos = 0; 1406254721Semaste while ((start_backtick = command.find ('`', pos)) != std::string::npos) 1407254721Semaste { 1408254721Semaste if (start_backtick > 0 && command[start_backtick-1] == '\\') 1409254721Semaste { 1410254721Semaste // The backtick was preceeded by a '\' character, remove the slash 1411254721Semaste // and don't treat the backtick as the start of an expression 1412254721Semaste command.erase(start_backtick-1, 1); 1413254721Semaste // No need to add one to start_backtick since we just deleted a char 1414254721Semaste pos = start_backtick; 1415254721Semaste } 1416254721Semaste else 1417254721Semaste { 1418254721Semaste const size_t expr_content_start = start_backtick + 1; 1419254721Semaste const size_t end_backtick = command.find ('`', expr_content_start); 1420254721Semaste if (end_backtick == std::string::npos) 1421254721Semaste return error; 1422254721Semaste else if (end_backtick == expr_content_start) 1423254721Semaste { 1424254721Semaste // Empty expression (two backticks in a row) 1425254721Semaste command.erase (start_backtick, 2); 1426254721Semaste } 1427254721Semaste else 1428254721Semaste { 1429254721Semaste std::string expr_str (command, expr_content_start, end_backtick - expr_content_start); 1430254721Semaste 1431254721Semaste ExecutionContext exe_ctx(GetExecutionContext()); 1432254721Semaste Target *target = exe_ctx.GetTargetPtr(); 1433254721Semaste // Get a dummy target to allow for calculator mode while processing backticks. 1434254721Semaste // This also helps break the infinite loop caused when target is null. 1435254721Semaste if (!target) 1436254721Semaste target = Host::GetDummyTarget(GetDebugger()).get(); 1437254721Semaste if (target) 1438254721Semaste { 1439254721Semaste ValueObjectSP expr_result_valobj_sp; 1440254721Semaste 1441254721Semaste EvaluateExpressionOptions options; 1442263367Semaste options.SetCoerceToId(false); 1443263367Semaste options.SetUnwindOnError(true); 1444263367Semaste options.SetIgnoreBreakpoints(true); 1445263367Semaste options.SetKeepInMemory(false); 1446263367Semaste options.SetTryAllThreads(true); 1447263367Semaste options.SetTimeoutUsec(0); 1448254721Semaste 1449254721Semaste ExecutionResults expr_result = target->EvaluateExpression (expr_str.c_str(), 1450254721Semaste exe_ctx.GetFramePtr(), 1451254721Semaste expr_result_valobj_sp, 1452254721Semaste options); 1453254721Semaste 1454254721Semaste if (expr_result == eExecutionCompleted) 1455254721Semaste { 1456254721Semaste Scalar scalar; 1457254721Semaste if (expr_result_valobj_sp->ResolveValue (scalar)) 1458254721Semaste { 1459254721Semaste command.erase (start_backtick, end_backtick - start_backtick + 1); 1460254721Semaste StreamString value_strm; 1461254721Semaste const bool show_type = false; 1462254721Semaste scalar.GetValue (&value_strm, show_type); 1463254721Semaste size_t value_string_size = value_strm.GetSize(); 1464254721Semaste if (value_string_size) 1465254721Semaste { 1466254721Semaste command.insert (start_backtick, value_strm.GetData(), value_string_size); 1467254721Semaste pos = start_backtick + value_string_size; 1468254721Semaste continue; 1469254721Semaste } 1470254721Semaste else 1471254721Semaste { 1472254721Semaste error.SetErrorStringWithFormat("expression value didn't result in a scalar value for the expression '%s'", expr_str.c_str()); 1473254721Semaste } 1474254721Semaste } 1475254721Semaste else 1476254721Semaste { 1477254721Semaste error.SetErrorStringWithFormat("expression value didn't result in a scalar value for the expression '%s'", expr_str.c_str()); 1478254721Semaste } 1479254721Semaste } 1480254721Semaste else 1481254721Semaste { 1482254721Semaste if (expr_result_valobj_sp) 1483254721Semaste error = expr_result_valobj_sp->GetError(); 1484254721Semaste if (error.Success()) 1485254721Semaste { 1486254721Semaste 1487254721Semaste switch (expr_result) 1488254721Semaste { 1489254721Semaste case eExecutionSetupError: 1490254721Semaste error.SetErrorStringWithFormat("expression setup error for the expression '%s'", expr_str.c_str()); 1491254721Semaste break; 1492254721Semaste case eExecutionCompleted: 1493254721Semaste break; 1494254721Semaste case eExecutionDiscarded: 1495254721Semaste error.SetErrorStringWithFormat("expression discarded for the expression '%s'", expr_str.c_str()); 1496254721Semaste break; 1497254721Semaste case eExecutionInterrupted: 1498254721Semaste error.SetErrorStringWithFormat("expression interrupted for the expression '%s'", expr_str.c_str()); 1499254721Semaste break; 1500254721Semaste case eExecutionHitBreakpoint: 1501254721Semaste error.SetErrorStringWithFormat("expression hit breakpoint for the expression '%s'", expr_str.c_str()); 1502254721Semaste break; 1503254721Semaste case eExecutionTimedOut: 1504254721Semaste error.SetErrorStringWithFormat("expression timed out for the expression '%s'", expr_str.c_str()); 1505254721Semaste break; 1506263367Semaste case eExecutionStoppedForDebug: 1507263367Semaste error.SetErrorStringWithFormat("expression stop at entry point for debugging for the expression '%s'", expr_str.c_str()); 1508263367Semaste break; 1509254721Semaste } 1510254721Semaste } 1511254721Semaste } 1512254721Semaste } 1513254721Semaste } 1514254721Semaste if (error.Fail()) 1515254721Semaste break; 1516254721Semaste } 1517254721Semaste } 1518254721Semaste return error; 1519254721Semaste} 1520254721Semaste 1521254721Semaste 1522254721Semastebool 1523254721SemasteCommandInterpreter::HandleCommand (const char *command_line, 1524254721Semaste LazyBool lazy_add_to_history, 1525254721Semaste CommandReturnObject &result, 1526254721Semaste ExecutionContext *override_context, 1527254721Semaste bool repeat_on_empty_command, 1528254721Semaste bool no_context_switching) 1529254721Semaste 1530254721Semaste{ 1531254721Semaste 1532254721Semaste bool done = false; 1533254721Semaste CommandObject *cmd_obj = NULL; 1534254721Semaste bool wants_raw_input = false; 1535254721Semaste std::string command_string (command_line); 1536254721Semaste std::string original_command_string (command_line); 1537254721Semaste 1538254721Semaste Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMANDS)); 1539254721Semaste Host::SetCrashDescriptionWithFormat ("HandleCommand(command = \"%s\")", command_line); 1540254721Semaste 1541254721Semaste // Make a scoped cleanup object that will clear the crash description string 1542254721Semaste // on exit of this function. 1543254721Semaste lldb_utility::CleanUp <const char *> crash_description_cleanup(NULL, Host::SetCrashDescription); 1544254721Semaste 1545254721Semaste if (log) 1546254721Semaste log->Printf ("Processing command: %s", command_line); 1547254721Semaste 1548254721Semaste Timer scoped_timer (__PRETTY_FUNCTION__, "Handling command: %s.", command_line); 1549254721Semaste 1550254721Semaste if (!no_context_switching) 1551254721Semaste UpdateExecutionContext (override_context); 1552254721Semaste 1553254721Semaste bool add_to_history; 1554254721Semaste if (lazy_add_to_history == eLazyBoolCalculate) 1555254721Semaste add_to_history = (m_command_source_depth == 0); 1556254721Semaste else 1557254721Semaste add_to_history = (lazy_add_to_history == eLazyBoolYes); 1558254721Semaste 1559254721Semaste bool empty_command = false; 1560254721Semaste bool comment_command = false; 1561254721Semaste if (command_string.empty()) 1562254721Semaste empty_command = true; 1563254721Semaste else 1564254721Semaste { 1565254721Semaste const char *k_space_characters = "\t\n\v\f\r "; 1566254721Semaste 1567254721Semaste size_t non_space = command_string.find_first_not_of (k_space_characters); 1568254721Semaste // Check for empty line or comment line (lines whose first 1569254721Semaste // non-space character is the comment character for this interpreter) 1570254721Semaste if (non_space == std::string::npos) 1571254721Semaste empty_command = true; 1572254721Semaste else if (command_string[non_space] == m_comment_char) 1573254721Semaste comment_command = true; 1574254721Semaste else if (command_string[non_space] == CommandHistory::g_repeat_char) 1575254721Semaste { 1576254721Semaste const char *history_string = m_command_history.FindString(command_string.c_str() + non_space); 1577254721Semaste if (history_string == NULL) 1578254721Semaste { 1579254721Semaste result.AppendErrorWithFormat ("Could not find entry: %s in history", command_string.c_str()); 1580254721Semaste result.SetStatus(eReturnStatusFailed); 1581254721Semaste return false; 1582254721Semaste } 1583254721Semaste add_to_history = false; 1584254721Semaste command_string = history_string; 1585254721Semaste original_command_string = history_string; 1586254721Semaste } 1587254721Semaste } 1588254721Semaste 1589254721Semaste if (empty_command) 1590254721Semaste { 1591254721Semaste if (repeat_on_empty_command) 1592254721Semaste { 1593254721Semaste if (m_command_history.IsEmpty()) 1594254721Semaste { 1595254721Semaste result.AppendError ("empty command"); 1596254721Semaste result.SetStatus(eReturnStatusFailed); 1597254721Semaste return false; 1598254721Semaste } 1599254721Semaste else 1600254721Semaste { 1601254721Semaste command_line = m_repeat_command.c_str(); 1602254721Semaste command_string = command_line; 1603254721Semaste original_command_string = command_line; 1604254721Semaste if (m_repeat_command.empty()) 1605254721Semaste { 1606254721Semaste result.AppendErrorWithFormat("No auto repeat.\n"); 1607254721Semaste result.SetStatus (eReturnStatusFailed); 1608254721Semaste return false; 1609254721Semaste } 1610254721Semaste } 1611254721Semaste add_to_history = false; 1612254721Semaste } 1613254721Semaste else 1614254721Semaste { 1615254721Semaste result.SetStatus (eReturnStatusSuccessFinishNoResult); 1616254721Semaste return true; 1617254721Semaste } 1618254721Semaste } 1619254721Semaste else if (comment_command) 1620254721Semaste { 1621254721Semaste result.SetStatus (eReturnStatusSuccessFinishNoResult); 1622254721Semaste return true; 1623254721Semaste } 1624254721Semaste 1625254721Semaste 1626254721Semaste Error error (PreprocessCommand (command_string)); 1627254721Semaste 1628254721Semaste if (error.Fail()) 1629254721Semaste { 1630254721Semaste result.AppendError (error.AsCString()); 1631254721Semaste result.SetStatus(eReturnStatusFailed); 1632254721Semaste return false; 1633254721Semaste } 1634254721Semaste // Phase 1. 1635254721Semaste 1636254721Semaste // Before we do ANY kind of argument processing, etc. we need to figure out what the real/final command object 1637254721Semaste // is for the specified command, and whether or not it wants raw input. This gets complicated by the fact that 1638254721Semaste // the user could have specified an alias, and in translating the alias there may also be command options and/or 1639254721Semaste // even data (including raw text strings) that need to be found and inserted into the command line as part of 1640254721Semaste // the translation. So this first step is plain look-up & replacement, resulting in three things: 1). the command 1641254721Semaste // object whose Execute method will actually be called; 2). a revised command string, with all substitutions & 1642254721Semaste // replacements taken care of; 3). whether or not the Execute function wants raw input or not. 1643254721Semaste 1644254721Semaste StreamString revised_command_line; 1645254721Semaste size_t actual_cmd_name_len = 0; 1646254721Semaste std::string next_word; 1647254721Semaste StringList matches; 1648254721Semaste while (!done) 1649254721Semaste { 1650254721Semaste char quote_char = '\0'; 1651254721Semaste std::string suffix; 1652254721Semaste ExtractCommand (command_string, next_word, suffix, quote_char); 1653254721Semaste if (cmd_obj == NULL) 1654254721Semaste { 1655254721Semaste std::string full_name; 1656254721Semaste if (GetAliasFullName(next_word.c_str(), full_name)) 1657254721Semaste { 1658254721Semaste std::string alias_result; 1659254721Semaste cmd_obj = BuildAliasResult (full_name.c_str(), command_string, alias_result, result); 1660254721Semaste revised_command_line.Printf ("%s", alias_result.c_str()); 1661254721Semaste if (cmd_obj) 1662254721Semaste { 1663254721Semaste wants_raw_input = cmd_obj->WantsRawCommandString (); 1664254721Semaste actual_cmd_name_len = strlen (cmd_obj->GetCommandName()); 1665254721Semaste } 1666254721Semaste } 1667254721Semaste else 1668254721Semaste { 1669254721Semaste cmd_obj = GetCommandObject (next_word.c_str(), &matches); 1670254721Semaste if (cmd_obj) 1671254721Semaste { 1672254721Semaste actual_cmd_name_len += next_word.length(); 1673254721Semaste revised_command_line.Printf ("%s", next_word.c_str()); 1674254721Semaste wants_raw_input = cmd_obj->WantsRawCommandString (); 1675254721Semaste } 1676254721Semaste else 1677254721Semaste { 1678254721Semaste revised_command_line.Printf ("%s", next_word.c_str()); 1679254721Semaste } 1680254721Semaste } 1681254721Semaste } 1682254721Semaste else 1683254721Semaste { 1684254721Semaste if (cmd_obj->IsMultiwordObject ()) 1685254721Semaste { 1686254721Semaste CommandObject *sub_cmd_obj = cmd_obj->GetSubcommandObject (next_word.c_str()); 1687254721Semaste if (sub_cmd_obj) 1688254721Semaste { 1689254721Semaste actual_cmd_name_len += next_word.length() + 1; 1690254721Semaste revised_command_line.Printf (" %s", next_word.c_str()); 1691254721Semaste cmd_obj = sub_cmd_obj; 1692254721Semaste wants_raw_input = cmd_obj->WantsRawCommandString (); 1693254721Semaste } 1694254721Semaste else 1695254721Semaste { 1696254721Semaste if (quote_char) 1697254721Semaste revised_command_line.Printf (" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char); 1698254721Semaste else 1699254721Semaste revised_command_line.Printf (" %s%s", next_word.c_str(), suffix.c_str()); 1700254721Semaste done = true; 1701254721Semaste } 1702254721Semaste } 1703254721Semaste else 1704254721Semaste { 1705254721Semaste if (quote_char) 1706254721Semaste revised_command_line.Printf (" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char); 1707254721Semaste else 1708254721Semaste revised_command_line.Printf (" %s%s", next_word.c_str(), suffix.c_str()); 1709254721Semaste done = true; 1710254721Semaste } 1711254721Semaste } 1712254721Semaste 1713254721Semaste if (cmd_obj == NULL) 1714254721Semaste { 1715254721Semaste const size_t num_matches = matches.GetSize(); 1716254721Semaste if (matches.GetSize() > 1) { 1717254721Semaste StreamString error_msg; 1718254721Semaste error_msg.Printf ("Ambiguous command '%s'. Possible matches:\n", next_word.c_str()); 1719254721Semaste 1720254721Semaste for (uint32_t i = 0; i < num_matches; ++i) { 1721254721Semaste error_msg.Printf ("\t%s\n", matches.GetStringAtIndex(i)); 1722254721Semaste } 1723254721Semaste result.AppendRawError (error_msg.GetString().c_str()); 1724254721Semaste } else { 1725254721Semaste // We didn't have only one match, otherwise we wouldn't get here. 1726254721Semaste assert(num_matches == 0); 1727254721Semaste result.AppendErrorWithFormat ("'%s' is not a valid command.\n", next_word.c_str()); 1728254721Semaste } 1729254721Semaste result.SetStatus (eReturnStatusFailed); 1730254721Semaste return false; 1731254721Semaste } 1732254721Semaste 1733254721Semaste if (cmd_obj->IsMultiwordObject ()) 1734254721Semaste { 1735254721Semaste if (!suffix.empty()) 1736254721Semaste { 1737254721Semaste 1738254721Semaste result.AppendErrorWithFormat ("command '%s' did not recognize '%s%s%s' as valid (subcommand might be invalid).\n", 1739254721Semaste cmd_obj->GetCommandName(), 1740254721Semaste next_word.empty() ? "" : next_word.c_str(), 1741254721Semaste next_word.empty() ? " -- " : " ", 1742254721Semaste suffix.c_str()); 1743254721Semaste result.SetStatus (eReturnStatusFailed); 1744254721Semaste return false; 1745254721Semaste } 1746254721Semaste } 1747254721Semaste else 1748254721Semaste { 1749254721Semaste // If we found a normal command, we are done 1750254721Semaste done = true; 1751254721Semaste if (!suffix.empty()) 1752254721Semaste { 1753254721Semaste switch (suffix[0]) 1754254721Semaste { 1755254721Semaste case '/': 1756254721Semaste // GDB format suffixes 1757254721Semaste { 1758254721Semaste Options *command_options = cmd_obj->GetOptions(); 1759254721Semaste if (command_options && command_options->SupportsLongOption("gdb-format")) 1760254721Semaste { 1761254721Semaste std::string gdb_format_option ("--gdb-format="); 1762254721Semaste gdb_format_option += (suffix.c_str() + 1); 1763254721Semaste 1764254721Semaste bool inserted = false; 1765254721Semaste std::string &cmd = revised_command_line.GetString(); 1766254721Semaste size_t arg_terminator_idx = FindArgumentTerminator (cmd); 1767254721Semaste if (arg_terminator_idx != std::string::npos) 1768254721Semaste { 1769254721Semaste // Insert the gdb format option before the "--" that terminates options 1770254721Semaste gdb_format_option.append(1,' '); 1771254721Semaste cmd.insert(arg_terminator_idx, gdb_format_option); 1772254721Semaste inserted = true; 1773254721Semaste } 1774254721Semaste 1775254721Semaste if (!inserted) 1776254721Semaste revised_command_line.Printf (" %s", gdb_format_option.c_str()); 1777254721Semaste 1778254721Semaste if (wants_raw_input && FindArgumentTerminator(cmd) == std::string::npos) 1779254721Semaste revised_command_line.PutCString (" --"); 1780254721Semaste } 1781254721Semaste else 1782254721Semaste { 1783254721Semaste result.AppendErrorWithFormat ("the '%s' command doesn't support the --gdb-format option\n", 1784254721Semaste cmd_obj->GetCommandName()); 1785254721Semaste result.SetStatus (eReturnStatusFailed); 1786254721Semaste return false; 1787254721Semaste } 1788254721Semaste } 1789254721Semaste break; 1790254721Semaste 1791254721Semaste default: 1792254721Semaste result.AppendErrorWithFormat ("unknown command shorthand suffix: '%s'\n", 1793254721Semaste suffix.c_str()); 1794254721Semaste result.SetStatus (eReturnStatusFailed); 1795254721Semaste return false; 1796254721Semaste 1797254721Semaste } 1798254721Semaste } 1799254721Semaste } 1800254721Semaste if (command_string.length() == 0) 1801254721Semaste done = true; 1802254721Semaste 1803254721Semaste } 1804254721Semaste 1805254721Semaste if (!command_string.empty()) 1806254721Semaste revised_command_line.Printf (" %s", command_string.c_str()); 1807254721Semaste 1808254721Semaste // End of Phase 1. 1809254721Semaste // At this point cmd_obj should contain the CommandObject whose Execute method will be called, if the command 1810254721Semaste // specified was valid; revised_command_line contains the complete command line (including command name(s)), 1811254721Semaste // fully translated with all substitutions & translations taken care of (still in raw text format); and 1812254721Semaste // wants_raw_input specifies whether the Execute method expects raw input or not. 1813254721Semaste 1814254721Semaste 1815254721Semaste if (log) 1816254721Semaste { 1817254721Semaste log->Printf ("HandleCommand, cmd_obj : '%s'", cmd_obj ? cmd_obj->GetCommandName() : "<not found>"); 1818254721Semaste log->Printf ("HandleCommand, revised_command_line: '%s'", revised_command_line.GetData()); 1819254721Semaste log->Printf ("HandleCommand, wants_raw_input:'%s'", wants_raw_input ? "True" : "False"); 1820254721Semaste } 1821254721Semaste 1822254721Semaste // Phase 2. 1823254721Semaste // Take care of things like setting up the history command & calling the appropriate Execute method on the 1824254721Semaste // CommandObject, with the appropriate arguments. 1825254721Semaste 1826254721Semaste if (cmd_obj != NULL) 1827254721Semaste { 1828254721Semaste if (add_to_history) 1829254721Semaste { 1830254721Semaste Args command_args (revised_command_line.GetData()); 1831254721Semaste const char *repeat_command = cmd_obj->GetRepeatCommand(command_args, 0); 1832254721Semaste if (repeat_command != NULL) 1833254721Semaste m_repeat_command.assign(repeat_command); 1834254721Semaste else 1835254721Semaste m_repeat_command.assign(original_command_string.c_str()); 1836254721Semaste 1837254721Semaste m_command_history.AppendString (original_command_string); 1838254721Semaste } 1839254721Semaste 1840254721Semaste command_string = revised_command_line.GetData(); 1841254721Semaste std::string command_name (cmd_obj->GetCommandName()); 1842254721Semaste std::string remainder; 1843254721Semaste if (actual_cmd_name_len < command_string.length()) 1844254721Semaste remainder = command_string.substr (actual_cmd_name_len); // Note: 'actual_cmd_name_len' may be considerably shorter 1845254721Semaste // than cmd_obj->GetCommandName(), because name completion 1846254721Semaste // allows users to enter short versions of the names, 1847254721Semaste // e.g. 'br s' for 'breakpoint set'. 1848254721Semaste 1849254721Semaste // Remove any initial spaces 1850254721Semaste std::string white_space (" \t\v"); 1851254721Semaste size_t pos = remainder.find_first_not_of (white_space); 1852254721Semaste if (pos != 0 && pos != std::string::npos) 1853254721Semaste remainder.erase(0, pos); 1854254721Semaste 1855254721Semaste if (log) 1856254721Semaste log->Printf ("HandleCommand, command line after removing command name(s): '%s'", remainder.c_str()); 1857254721Semaste 1858254721Semaste cmd_obj->Execute (remainder.c_str(), result); 1859254721Semaste } 1860254721Semaste else 1861254721Semaste { 1862254721Semaste // We didn't find the first command object, so complete the first argument. 1863254721Semaste Args command_args (revised_command_line.GetData()); 1864254721Semaste StringList matches; 1865254721Semaste int num_matches; 1866254721Semaste int cursor_index = 0; 1867254721Semaste int cursor_char_position = strlen (command_args.GetArgumentAtIndex(0)); 1868254721Semaste bool word_complete; 1869254721Semaste num_matches = HandleCompletionMatches (command_args, 1870254721Semaste cursor_index, 1871254721Semaste cursor_char_position, 1872254721Semaste 0, 1873254721Semaste -1, 1874254721Semaste word_complete, 1875254721Semaste matches); 1876254721Semaste 1877254721Semaste if (num_matches > 0) 1878254721Semaste { 1879254721Semaste std::string error_msg; 1880254721Semaste error_msg.assign ("ambiguous command '"); 1881254721Semaste error_msg.append(command_args.GetArgumentAtIndex(0)); 1882254721Semaste error_msg.append ("'."); 1883254721Semaste 1884254721Semaste error_msg.append (" Possible completions:"); 1885254721Semaste for (int i = 0; i < num_matches; i++) 1886254721Semaste { 1887254721Semaste error_msg.append ("\n\t"); 1888254721Semaste error_msg.append (matches.GetStringAtIndex (i)); 1889254721Semaste } 1890254721Semaste error_msg.append ("\n"); 1891254721Semaste result.AppendRawError (error_msg.c_str()); 1892254721Semaste } 1893254721Semaste else 1894254721Semaste result.AppendErrorWithFormat ("Unrecognized command '%s'.\n", command_args.GetArgumentAtIndex (0)); 1895254721Semaste 1896254721Semaste result.SetStatus (eReturnStatusFailed); 1897254721Semaste } 1898254721Semaste 1899254721Semaste if (log) 1900254721Semaste log->Printf ("HandleCommand, command %s", (result.Succeeded() ? "succeeded" : "did not succeed")); 1901254721Semaste 1902254721Semaste return result.Succeeded(); 1903254721Semaste} 1904254721Semaste 1905254721Semasteint 1906254721SemasteCommandInterpreter::HandleCompletionMatches (Args &parsed_line, 1907254721Semaste int &cursor_index, 1908254721Semaste int &cursor_char_position, 1909254721Semaste int match_start_point, 1910254721Semaste int max_return_elements, 1911254721Semaste bool &word_complete, 1912254721Semaste StringList &matches) 1913254721Semaste{ 1914254721Semaste int num_command_matches = 0; 1915254721Semaste bool look_for_subcommand = false; 1916254721Semaste 1917254721Semaste // For any of the command completions a unique match will be a complete word. 1918254721Semaste word_complete = true; 1919254721Semaste 1920254721Semaste if (cursor_index == -1) 1921254721Semaste { 1922254721Semaste // We got nothing on the command line, so return the list of commands 1923254721Semaste bool include_aliases = true; 1924254721Semaste num_command_matches = GetCommandNamesMatchingPartialString ("", include_aliases, matches); 1925254721Semaste } 1926254721Semaste else if (cursor_index == 0) 1927254721Semaste { 1928254721Semaste // The cursor is in the first argument, so just do a lookup in the dictionary. 1929254721Semaste CommandObject *cmd_obj = GetCommandObject (parsed_line.GetArgumentAtIndex(0), &matches); 1930254721Semaste num_command_matches = matches.GetSize(); 1931254721Semaste 1932254721Semaste if (num_command_matches == 1 1933254721Semaste && cmd_obj && cmd_obj->IsMultiwordObject() 1934254721Semaste && matches.GetStringAtIndex(0) != NULL 1935254721Semaste && strcmp (parsed_line.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0) 1936254721Semaste { 1937269024Semaste if (parsed_line.GetArgumentCount() == 1) 1938269024Semaste { 1939269024Semaste word_complete = true; 1940269024Semaste } 1941269024Semaste else 1942269024Semaste { 1943269024Semaste look_for_subcommand = true; 1944269024Semaste num_command_matches = 0; 1945269024Semaste matches.DeleteStringAtIndex(0); 1946269024Semaste parsed_line.AppendArgument (""); 1947269024Semaste cursor_index++; 1948269024Semaste cursor_char_position = 0; 1949269024Semaste } 1950254721Semaste } 1951254721Semaste } 1952254721Semaste 1953254721Semaste if (cursor_index > 0 || look_for_subcommand) 1954254721Semaste { 1955254721Semaste // We are completing further on into a commands arguments, so find the command and tell it 1956254721Semaste // to complete the command. 1957254721Semaste // First see if there is a matching initial command: 1958254721Semaste CommandObject *command_object = GetCommandObject (parsed_line.GetArgumentAtIndex(0)); 1959254721Semaste if (command_object == NULL) 1960254721Semaste { 1961254721Semaste return 0; 1962254721Semaste } 1963254721Semaste else 1964254721Semaste { 1965254721Semaste parsed_line.Shift(); 1966254721Semaste cursor_index--; 1967254721Semaste num_command_matches = command_object->HandleCompletion (parsed_line, 1968254721Semaste cursor_index, 1969254721Semaste cursor_char_position, 1970254721Semaste match_start_point, 1971254721Semaste max_return_elements, 1972254721Semaste word_complete, 1973254721Semaste matches); 1974254721Semaste } 1975254721Semaste } 1976254721Semaste 1977254721Semaste return num_command_matches; 1978254721Semaste 1979254721Semaste} 1980254721Semaste 1981254721Semasteint 1982254721SemasteCommandInterpreter::HandleCompletion (const char *current_line, 1983254721Semaste const char *cursor, 1984254721Semaste const char *last_char, 1985254721Semaste int match_start_point, 1986254721Semaste int max_return_elements, 1987254721Semaste StringList &matches) 1988254721Semaste{ 1989254721Semaste // We parse the argument up to the cursor, so the last argument in parsed_line is 1990254721Semaste // the one containing the cursor, and the cursor is after the last character. 1991254721Semaste 1992254721Semaste Args parsed_line(current_line, last_char - current_line); 1993254721Semaste Args partial_parsed_line(current_line, cursor - current_line); 1994254721Semaste 1995254721Semaste // Don't complete comments, and if the line we are completing is just the history repeat character, 1996254721Semaste // substitute the appropriate history line. 1997254721Semaste const char *first_arg = parsed_line.GetArgumentAtIndex(0); 1998254721Semaste if (first_arg) 1999254721Semaste { 2000254721Semaste if (first_arg[0] == m_comment_char) 2001254721Semaste return 0; 2002254721Semaste else if (first_arg[0] == CommandHistory::g_repeat_char) 2003254721Semaste { 2004254721Semaste const char *history_string = m_command_history.FindString (first_arg); 2005254721Semaste if (history_string != NULL) 2006254721Semaste { 2007254721Semaste matches.Clear(); 2008254721Semaste matches.InsertStringAtIndex(0, history_string); 2009254721Semaste return -2; 2010254721Semaste } 2011254721Semaste else 2012254721Semaste return 0; 2013254721Semaste 2014254721Semaste } 2015254721Semaste } 2016254721Semaste 2017254721Semaste 2018254721Semaste int num_args = partial_parsed_line.GetArgumentCount(); 2019254721Semaste int cursor_index = partial_parsed_line.GetArgumentCount() - 1; 2020254721Semaste int cursor_char_position; 2021254721Semaste 2022254721Semaste if (cursor_index == -1) 2023254721Semaste cursor_char_position = 0; 2024254721Semaste else 2025254721Semaste cursor_char_position = strlen (partial_parsed_line.GetArgumentAtIndex(cursor_index)); 2026254721Semaste 2027254721Semaste if (cursor > current_line && cursor[-1] == ' ') 2028254721Semaste { 2029254721Semaste // We are just after a space. If we are in an argument, then we will continue 2030254721Semaste // parsing, but if we are between arguments, then we have to complete whatever the next 2031254721Semaste // element would be. 2032254721Semaste // We can distinguish the two cases because if we are in an argument (e.g. because the space is 2033254721Semaste // protected by a quote) then the space will also be in the parsed argument... 2034254721Semaste 2035254721Semaste const char *current_elem = partial_parsed_line.GetArgumentAtIndex(cursor_index); 2036254721Semaste if (cursor_char_position == 0 || current_elem[cursor_char_position - 1] != ' ') 2037254721Semaste { 2038269024Semaste parsed_line.InsertArgumentAtIndex(cursor_index + 1, "", '\0'); 2039254721Semaste cursor_index++; 2040254721Semaste cursor_char_position = 0; 2041254721Semaste } 2042254721Semaste } 2043254721Semaste 2044254721Semaste int num_command_matches; 2045254721Semaste 2046254721Semaste matches.Clear(); 2047254721Semaste 2048254721Semaste // Only max_return_elements == -1 is supported at present: 2049254721Semaste assert (max_return_elements == -1); 2050254721Semaste bool word_complete; 2051254721Semaste num_command_matches = HandleCompletionMatches (parsed_line, 2052254721Semaste cursor_index, 2053254721Semaste cursor_char_position, 2054254721Semaste match_start_point, 2055254721Semaste max_return_elements, 2056254721Semaste word_complete, 2057254721Semaste matches); 2058254721Semaste 2059254721Semaste if (num_command_matches <= 0) 2060254721Semaste return num_command_matches; 2061254721Semaste 2062254721Semaste if (num_args == 0) 2063254721Semaste { 2064254721Semaste // If we got an empty string, insert nothing. 2065254721Semaste matches.InsertStringAtIndex(0, ""); 2066254721Semaste } 2067254721Semaste else 2068254721Semaste { 2069254721Semaste // Now figure out if there is a common substring, and if so put that in element 0, otherwise 2070254721Semaste // put an empty string in element 0. 2071254721Semaste std::string command_partial_str; 2072254721Semaste if (cursor_index >= 0) 2073254721Semaste command_partial_str.assign(parsed_line.GetArgumentAtIndex(cursor_index), 2074254721Semaste parsed_line.GetArgumentAtIndex(cursor_index) + cursor_char_position); 2075254721Semaste 2076254721Semaste std::string common_prefix; 2077254721Semaste matches.LongestCommonPrefix (common_prefix); 2078254721Semaste const size_t partial_name_len = command_partial_str.size(); 2079254721Semaste 2080254721Semaste // If we matched a unique single command, add a space... 2081254721Semaste // Only do this if the completer told us this was a complete word, however... 2082254721Semaste if (num_command_matches == 1 && word_complete) 2083254721Semaste { 2084254721Semaste char quote_char = parsed_line.GetArgumentQuoteCharAtIndex(cursor_index); 2085254721Semaste if (quote_char != '\0') 2086254721Semaste common_prefix.push_back(quote_char); 2087254721Semaste 2088254721Semaste common_prefix.push_back(' '); 2089254721Semaste } 2090254721Semaste common_prefix.erase (0, partial_name_len); 2091254721Semaste matches.InsertStringAtIndex(0, common_prefix.c_str()); 2092254721Semaste } 2093254721Semaste return num_command_matches; 2094254721Semaste} 2095254721Semaste 2096254721Semaste 2097254721SemasteCommandInterpreter::~CommandInterpreter () 2098254721Semaste{ 2099254721Semaste} 2100254721Semaste 2101254721Semastevoid 2102269024SemasteCommandInterpreter::UpdatePrompt (const char *new_prompt) 2103254721Semaste{ 2104269024Semaste EventSP prompt_change_event_sp (new Event(eBroadcastBitResetPrompt, new EventDataBytes (new_prompt)));; 2105269024Semaste BroadcastEvent (prompt_change_event_sp); 2106269024Semaste if (m_command_io_handler_sp) 2107269024Semaste m_command_io_handler_sp->SetPrompt(new_prompt); 2108254721Semaste} 2109254721Semaste 2110254721Semaste 2111254721Semastebool 2112254721SemasteCommandInterpreter::Confirm (const char *message, bool default_answer) 2113254721Semaste{ 2114254721Semaste // Check AutoConfirm first: 2115254721Semaste if (m_debugger.GetAutoConfirm()) 2116254721Semaste return default_answer; 2117269024Semaste 2118269024Semaste IOHandlerConfirm *confirm = new IOHandlerConfirm(m_debugger, 2119269024Semaste message, 2120269024Semaste default_answer); 2121269024Semaste IOHandlerSP io_handler_sp (confirm); 2122269024Semaste m_debugger.RunIOHandler (io_handler_sp); 2123269024Semaste return confirm->GetResponse(); 2124254721Semaste} 2125254721Semaste 2126254721SemasteOptionArgVectorSP 2127254721SemasteCommandInterpreter::GetAliasOptions (const char *alias_name) 2128254721Semaste{ 2129254721Semaste OptionArgMap::iterator pos; 2130254721Semaste OptionArgVectorSP ret_val; 2131254721Semaste 2132254721Semaste std::string alias (alias_name); 2133254721Semaste 2134254721Semaste if (HasAliasOptions()) 2135254721Semaste { 2136254721Semaste pos = m_alias_options.find (alias); 2137254721Semaste if (pos != m_alias_options.end()) 2138254721Semaste ret_val = pos->second; 2139254721Semaste } 2140254721Semaste 2141254721Semaste return ret_val; 2142254721Semaste} 2143254721Semaste 2144254721Semastevoid 2145254721SemasteCommandInterpreter::RemoveAliasOptions (const char *alias_name) 2146254721Semaste{ 2147254721Semaste OptionArgMap::iterator pos = m_alias_options.find(alias_name); 2148254721Semaste if (pos != m_alias_options.end()) 2149254721Semaste { 2150254721Semaste m_alias_options.erase (pos); 2151254721Semaste } 2152254721Semaste} 2153254721Semaste 2154254721Semastevoid 2155254721SemasteCommandInterpreter::AddOrReplaceAliasOptions (const char *alias_name, OptionArgVectorSP &option_arg_vector_sp) 2156254721Semaste{ 2157254721Semaste m_alias_options[alias_name] = option_arg_vector_sp; 2158254721Semaste} 2159254721Semaste 2160254721Semastebool 2161254721SemasteCommandInterpreter::HasCommands () 2162254721Semaste{ 2163254721Semaste return (!m_command_dict.empty()); 2164254721Semaste} 2165254721Semaste 2166254721Semastebool 2167254721SemasteCommandInterpreter::HasAliases () 2168254721Semaste{ 2169254721Semaste return (!m_alias_dict.empty()); 2170254721Semaste} 2171254721Semaste 2172254721Semastebool 2173254721SemasteCommandInterpreter::HasUserCommands () 2174254721Semaste{ 2175254721Semaste return (!m_user_dict.empty()); 2176254721Semaste} 2177254721Semaste 2178254721Semastebool 2179254721SemasteCommandInterpreter::HasAliasOptions () 2180254721Semaste{ 2181254721Semaste return (!m_alias_options.empty()); 2182254721Semaste} 2183254721Semaste 2184254721Semastevoid 2185254721SemasteCommandInterpreter::BuildAliasCommandArgs (CommandObject *alias_cmd_obj, 2186254721Semaste const char *alias_name, 2187254721Semaste Args &cmd_args, 2188254721Semaste std::string &raw_input_string, 2189254721Semaste CommandReturnObject &result) 2190254721Semaste{ 2191254721Semaste OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name); 2192254721Semaste 2193254721Semaste bool wants_raw_input = alias_cmd_obj->WantsRawCommandString(); 2194254721Semaste 2195254721Semaste // Make sure that the alias name is the 0th element in cmd_args 2196254721Semaste std::string alias_name_str = alias_name; 2197254721Semaste if (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0) 2198254721Semaste cmd_args.Unshift (alias_name); 2199254721Semaste 2200254721Semaste Args new_args (alias_cmd_obj->GetCommandName()); 2201254721Semaste if (new_args.GetArgumentCount() == 2) 2202254721Semaste new_args.Shift(); 2203254721Semaste 2204254721Semaste if (option_arg_vector_sp.get()) 2205254721Semaste { 2206254721Semaste if (wants_raw_input) 2207254721Semaste { 2208254721Semaste // We have a command that both has command options and takes raw input. Make *sure* it has a 2209254721Semaste // " -- " in the right place in the raw_input_string. 2210254721Semaste size_t pos = raw_input_string.find(" -- "); 2211254721Semaste if (pos == std::string::npos) 2212254721Semaste { 2213254721Semaste // None found; assume it goes at the beginning of the raw input string 2214254721Semaste raw_input_string.insert (0, " -- "); 2215254721Semaste } 2216254721Semaste } 2217254721Semaste 2218254721Semaste OptionArgVector *option_arg_vector = option_arg_vector_sp.get(); 2219254721Semaste const size_t old_size = cmd_args.GetArgumentCount(); 2220254721Semaste std::vector<bool> used (old_size + 1, false); 2221254721Semaste 2222254721Semaste used[0] = true; 2223254721Semaste 2224254721Semaste for (size_t i = 0; i < option_arg_vector->size(); ++i) 2225254721Semaste { 2226254721Semaste OptionArgPair option_pair = (*option_arg_vector)[i]; 2227254721Semaste OptionArgValue value_pair = option_pair.second; 2228254721Semaste int value_type = value_pair.first; 2229254721Semaste std::string option = option_pair.first; 2230254721Semaste std::string value = value_pair.second; 2231254721Semaste if (option.compare ("<argument>") == 0) 2232254721Semaste { 2233254721Semaste if (!wants_raw_input 2234254721Semaste || (value.compare("--") != 0)) // Since we inserted this above, make sure we don't insert it twice 2235254721Semaste new_args.AppendArgument (value.c_str()); 2236254721Semaste } 2237254721Semaste else 2238254721Semaste { 2239263363Semaste if (value_type != OptionParser::eOptionalArgument) 2240254721Semaste new_args.AppendArgument (option.c_str()); 2241254721Semaste if (value.compare ("<no-argument>") != 0) 2242254721Semaste { 2243254721Semaste int index = GetOptionArgumentPosition (value.c_str()); 2244254721Semaste if (index == 0) 2245254721Semaste { 2246254721Semaste // value was NOT a positional argument; must be a real value 2247263363Semaste if (value_type != OptionParser::eOptionalArgument) 2248254721Semaste new_args.AppendArgument (value.c_str()); 2249254721Semaste else 2250254721Semaste { 2251254721Semaste char buffer[255]; 2252254721Semaste ::snprintf (buffer, sizeof (buffer), "%s%s", option.c_str(), value.c_str()); 2253254721Semaste new_args.AppendArgument (buffer); 2254254721Semaste } 2255254721Semaste 2256254721Semaste } 2257254721Semaste else if (index >= cmd_args.GetArgumentCount()) 2258254721Semaste { 2259254721Semaste result.AppendErrorWithFormat 2260254721Semaste ("Not enough arguments provided; you need at least %d arguments to use this alias.\n", 2261254721Semaste index); 2262254721Semaste result.SetStatus (eReturnStatusFailed); 2263254721Semaste return; 2264254721Semaste } 2265254721Semaste else 2266254721Semaste { 2267254721Semaste // Find and remove cmd_args.GetArgumentAtIndex(i) from raw_input_string 2268254721Semaste size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index)); 2269254721Semaste if (strpos != std::string::npos) 2270254721Semaste { 2271254721Semaste raw_input_string = raw_input_string.erase (strpos, strlen (cmd_args.GetArgumentAtIndex (index))); 2272254721Semaste } 2273254721Semaste 2274263363Semaste if (value_type != OptionParser::eOptionalArgument) 2275254721Semaste new_args.AppendArgument (cmd_args.GetArgumentAtIndex (index)); 2276254721Semaste else 2277254721Semaste { 2278254721Semaste char buffer[255]; 2279254721Semaste ::snprintf (buffer, sizeof(buffer), "%s%s", option.c_str(), 2280254721Semaste cmd_args.GetArgumentAtIndex (index)); 2281254721Semaste new_args.AppendArgument (buffer); 2282254721Semaste } 2283254721Semaste used[index] = true; 2284254721Semaste } 2285254721Semaste } 2286254721Semaste } 2287254721Semaste } 2288254721Semaste 2289254721Semaste for (size_t j = 0; j < cmd_args.GetArgumentCount(); ++j) 2290254721Semaste { 2291254721Semaste if (!used[j] && !wants_raw_input) 2292254721Semaste new_args.AppendArgument (cmd_args.GetArgumentAtIndex (j)); 2293254721Semaste } 2294254721Semaste 2295254721Semaste cmd_args.Clear(); 2296254721Semaste cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector()); 2297254721Semaste } 2298254721Semaste else 2299254721Semaste { 2300254721Semaste result.SetStatus (eReturnStatusSuccessFinishNoResult); 2301254721Semaste // This alias was not created with any options; nothing further needs to be done, unless it is a command that 2302254721Semaste // wants raw input, in which case we need to clear the rest of the data from cmd_args, since its in the raw 2303254721Semaste // input string. 2304254721Semaste if (wants_raw_input) 2305254721Semaste { 2306254721Semaste cmd_args.Clear(); 2307254721Semaste cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector()); 2308254721Semaste } 2309254721Semaste return; 2310254721Semaste } 2311254721Semaste 2312254721Semaste result.SetStatus (eReturnStatusSuccessFinishNoResult); 2313254721Semaste return; 2314254721Semaste} 2315254721Semaste 2316254721Semaste 2317254721Semasteint 2318254721SemasteCommandInterpreter::GetOptionArgumentPosition (const char *in_string) 2319254721Semaste{ 2320254721Semaste int position = 0; // Any string that isn't an argument position, i.e. '%' followed by an integer, gets a position 2321254721Semaste // of zero. 2322254721Semaste 2323254721Semaste char *cptr = (char *) in_string; 2324254721Semaste 2325254721Semaste // Does it start with '%' 2326254721Semaste if (cptr[0] == '%') 2327254721Semaste { 2328254721Semaste ++cptr; 2329254721Semaste 2330254721Semaste // Is the rest of it entirely digits? 2331254721Semaste if (isdigit (cptr[0])) 2332254721Semaste { 2333254721Semaste const char *start = cptr; 2334254721Semaste while (isdigit (cptr[0])) 2335254721Semaste ++cptr; 2336254721Semaste 2337254721Semaste // We've gotten to the end of the digits; are we at the end of the string? 2338254721Semaste if (cptr[0] == '\0') 2339254721Semaste position = atoi (start); 2340254721Semaste } 2341254721Semaste } 2342254721Semaste 2343254721Semaste return position; 2344254721Semaste} 2345254721Semaste 2346254721Semastevoid 2347254721SemasteCommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result) 2348254721Semaste{ 2349254721Semaste FileSpec init_file; 2350254721Semaste if (in_cwd) 2351254721Semaste { 2352254721Semaste // In the current working directory we don't load any program specific 2353254721Semaste // .lldbinit files, we only look for a "./.lldbinit" file. 2354254721Semaste if (m_skip_lldbinit_files) 2355254721Semaste return; 2356254721Semaste 2357254721Semaste init_file.SetFile ("./.lldbinit", true); 2358254721Semaste } 2359254721Semaste else 2360254721Semaste { 2361254721Semaste // If we aren't looking in the current working directory we are looking 2362254721Semaste // in the home directory. We will first see if there is an application 2363254721Semaste // specific ".lldbinit" file whose name is "~/.lldbinit" followed by a 2364254721Semaste // "-" and the name of the program. If this file doesn't exist, we fall 2365254721Semaste // back to just the "~/.lldbinit" file. We also obey any requests to not 2366254721Semaste // load the init files. 2367254721Semaste const char *init_file_path = "~/.lldbinit"; 2368254721Semaste 2369254721Semaste if (m_skip_app_init_files == false) 2370254721Semaste { 2371254721Semaste FileSpec program_file_spec (Host::GetProgramFileSpec()); 2372254721Semaste const char *program_name = program_file_spec.GetFilename().AsCString(); 2373254721Semaste 2374254721Semaste if (program_name) 2375254721Semaste { 2376254721Semaste char program_init_file_name[PATH_MAX]; 2377254721Semaste ::snprintf (program_init_file_name, sizeof(program_init_file_name), "%s-%s", init_file_path, program_name); 2378254721Semaste init_file.SetFile (program_init_file_name, true); 2379254721Semaste if (!init_file.Exists()) 2380254721Semaste init_file.Clear(); 2381254721Semaste } 2382254721Semaste } 2383254721Semaste 2384254721Semaste if (!init_file && !m_skip_lldbinit_files) 2385254721Semaste init_file.SetFile (init_file_path, true); 2386254721Semaste } 2387254721Semaste 2388254721Semaste // If the file exists, tell HandleCommand to 'source' it; this will do the actual broadcasting 2389254721Semaste // of the commands back to any appropriate listener (see CommandObjectSource::Execute for more details). 2390254721Semaste 2391254721Semaste if (init_file.Exists()) 2392254721Semaste { 2393269024Semaste const bool saved_batch = SetBatchCommandMode (true); 2394269024Semaste HandleCommandsFromFile (init_file, 2395269024Semaste NULL, // Execution context 2396269024Semaste eLazyBoolYes, // Stop on continue 2397269024Semaste eLazyBoolNo, // Stop on error 2398269024Semaste eLazyBoolNo, // Don't echo commands 2399269024Semaste eLazyBoolNo, // Don't print command output 2400269024Semaste eLazyBoolNo, // Don't add the commands that are sourced into the history buffer 2401269024Semaste result); 2402269024Semaste SetBatchCommandMode (saved_batch); 2403254721Semaste } 2404254721Semaste else 2405254721Semaste { 2406254721Semaste // nothing to be done if the file doesn't exist 2407254721Semaste result.SetStatus(eReturnStatusSuccessFinishNoResult); 2408254721Semaste } 2409254721Semaste} 2410254721Semaste 2411254721SemastePlatformSP 2412254721SemasteCommandInterpreter::GetPlatform (bool prefer_target_platform) 2413254721Semaste{ 2414254721Semaste PlatformSP platform_sp; 2415254721Semaste if (prefer_target_platform) 2416254721Semaste { 2417254721Semaste ExecutionContext exe_ctx(GetExecutionContext()); 2418254721Semaste Target *target = exe_ctx.GetTargetPtr(); 2419254721Semaste if (target) 2420254721Semaste platform_sp = target->GetPlatform(); 2421254721Semaste } 2422254721Semaste 2423254721Semaste if (!platform_sp) 2424254721Semaste platform_sp = m_debugger.GetPlatformList().GetSelectedPlatform(); 2425254721Semaste return platform_sp; 2426254721Semaste} 2427254721Semaste 2428254721Semastevoid 2429254721SemasteCommandInterpreter::HandleCommands (const StringList &commands, 2430254721Semaste ExecutionContext *override_context, 2431254721Semaste bool stop_on_continue, 2432254721Semaste bool stop_on_error, 2433254721Semaste bool echo_commands, 2434254721Semaste bool print_results, 2435254721Semaste LazyBool add_to_history, 2436254721Semaste CommandReturnObject &result) 2437254721Semaste{ 2438254721Semaste size_t num_lines = commands.GetSize(); 2439254721Semaste 2440254721Semaste // If we are going to continue past a "continue" then we need to run the commands synchronously. 2441254721Semaste // Make sure you reset this value anywhere you return from the function. 2442254721Semaste 2443254721Semaste bool old_async_execution = m_debugger.GetAsyncExecution(); 2444254721Semaste 2445254721Semaste // If we've been given an execution context, set it at the start, but don't keep resetting it or we will 2446254721Semaste // cause series of commands that change the context, then do an operation that relies on that context to fail. 2447254721Semaste 2448254721Semaste if (override_context != NULL) 2449254721Semaste UpdateExecutionContext (override_context); 2450254721Semaste 2451254721Semaste if (!stop_on_continue) 2452254721Semaste { 2453254721Semaste m_debugger.SetAsyncExecution (false); 2454254721Semaste } 2455254721Semaste 2456254721Semaste for (size_t idx = 0; idx < num_lines; idx++) 2457254721Semaste { 2458254721Semaste const char *cmd = commands.GetStringAtIndex(idx); 2459254721Semaste if (cmd[0] == '\0') 2460254721Semaste continue; 2461254721Semaste 2462254721Semaste if (echo_commands) 2463254721Semaste { 2464254721Semaste result.AppendMessageWithFormat ("%s %s\n", 2465269024Semaste m_debugger.GetPrompt(), 2466269024Semaste cmd); 2467254721Semaste } 2468254721Semaste 2469254721Semaste CommandReturnObject tmp_result; 2470254721Semaste // If override_context is not NULL, pass no_context_switching = true for 2471254721Semaste // HandleCommand() since we updated our context already. 2472254721Semaste 2473254721Semaste // We might call into a regex or alias command, in which case the add_to_history will get lost. This 2474254721Semaste // m_command_source_depth dingus is the way we turn off adding to the history in that case, so set it up here. 2475254721Semaste if (!add_to_history) 2476254721Semaste m_command_source_depth++; 2477254721Semaste bool success = HandleCommand(cmd, add_to_history, tmp_result, 2478254721Semaste NULL, /* override_context */ 2479254721Semaste true, /* repeat_on_empty_command */ 2480254721Semaste override_context != NULL /* no_context_switching */); 2481254721Semaste if (!add_to_history) 2482254721Semaste m_command_source_depth--; 2483254721Semaste 2484254721Semaste if (print_results) 2485254721Semaste { 2486254721Semaste if (tmp_result.Succeeded()) 2487254721Semaste result.AppendMessageWithFormat("%s", tmp_result.GetOutputData()); 2488254721Semaste } 2489254721Semaste 2490254721Semaste if (!success || !tmp_result.Succeeded()) 2491254721Semaste { 2492254721Semaste const char *error_msg = tmp_result.GetErrorData(); 2493254721Semaste if (error_msg == NULL || error_msg[0] == '\0') 2494254721Semaste error_msg = "<unknown error>.\n"; 2495254721Semaste if (stop_on_error) 2496254721Semaste { 2497254721Semaste result.AppendErrorWithFormat("Aborting reading of commands after command #%zu: '%s' failed with %s", 2498254721Semaste idx, cmd, error_msg); 2499254721Semaste result.SetStatus (eReturnStatusFailed); 2500254721Semaste m_debugger.SetAsyncExecution (old_async_execution); 2501254721Semaste return; 2502254721Semaste } 2503254721Semaste else if (print_results) 2504254721Semaste { 2505254721Semaste result.AppendMessageWithFormat ("Command #%zu '%s' failed with %s", 2506254721Semaste idx + 1, 2507254721Semaste cmd, 2508254721Semaste error_msg); 2509254721Semaste } 2510254721Semaste } 2511254721Semaste 2512254721Semaste if (result.GetImmediateOutputStream()) 2513254721Semaste result.GetImmediateOutputStream()->Flush(); 2514254721Semaste 2515254721Semaste if (result.GetImmediateErrorStream()) 2516254721Semaste result.GetImmediateErrorStream()->Flush(); 2517254721Semaste 2518254721Semaste // N.B. Can't depend on DidChangeProcessState, because the state coming into the command execution 2519254721Semaste // could be running (for instance in Breakpoint Commands. 2520254721Semaste // So we check the return value to see if it is has running in it. 2521254721Semaste if ((tmp_result.GetStatus() == eReturnStatusSuccessContinuingNoResult) 2522254721Semaste || (tmp_result.GetStatus() == eReturnStatusSuccessContinuingResult)) 2523254721Semaste { 2524254721Semaste if (stop_on_continue) 2525254721Semaste { 2526254721Semaste // If we caused the target to proceed, and we're going to stop in that case, set the 2527254721Semaste // status in our real result before returning. This is an error if the continue was not the 2528254721Semaste // last command in the set of commands to be run. 2529254721Semaste if (idx != num_lines - 1) 2530254721Semaste result.AppendErrorWithFormat("Aborting reading of commands after command #%zu: '%s' continued the target.\n", 2531254721Semaste idx + 1, cmd); 2532254721Semaste else 2533254721Semaste result.AppendMessageWithFormat ("Command #%zu '%s' continued the target.\n", idx + 1, cmd); 2534254721Semaste 2535254721Semaste result.SetStatus(tmp_result.GetStatus()); 2536254721Semaste m_debugger.SetAsyncExecution (old_async_execution); 2537254721Semaste 2538254721Semaste return; 2539254721Semaste } 2540254721Semaste } 2541254721Semaste 2542254721Semaste } 2543254721Semaste 2544254721Semaste result.SetStatus (eReturnStatusSuccessFinishResult); 2545254721Semaste m_debugger.SetAsyncExecution (old_async_execution); 2546254721Semaste 2547254721Semaste return; 2548254721Semaste} 2549254721Semaste 2550269024Semaste// Make flags that we can pass into the IOHandler so our delegates can do the right thing 2551269024Semasteenum { 2552269024Semaste eHandleCommandFlagStopOnContinue = (1u << 0), 2553269024Semaste eHandleCommandFlagStopOnError = (1u << 1), 2554269024Semaste eHandleCommandFlagEchoCommand = (1u << 2), 2555269024Semaste eHandleCommandFlagPrintResult = (1u << 3) 2556269024Semaste}; 2557269024Semaste 2558254721Semastevoid 2559254721SemasteCommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file, 2560254721Semaste ExecutionContext *context, 2561269024Semaste LazyBool stop_on_continue, 2562269024Semaste LazyBool stop_on_error, 2563269024Semaste LazyBool echo_command, 2564269024Semaste LazyBool print_result, 2565254721Semaste LazyBool add_to_history, 2566254721Semaste CommandReturnObject &result) 2567254721Semaste{ 2568254721Semaste if (cmd_file.Exists()) 2569254721Semaste { 2570269024Semaste StreamFileSP input_file_sp (new StreamFile()); 2571269024Semaste 2572269024Semaste std::string cmd_file_path = cmd_file.GetPath(); 2573269024Semaste Error error = input_file_sp->GetFile().Open(cmd_file_path.c_str(), File::eOpenOptionRead); 2574269024Semaste 2575269024Semaste if (error.Success()) 2576254721Semaste { 2577269024Semaste Debugger &debugger = GetDebugger(); 2578269024Semaste 2579269024Semaste uint32_t flags = 0; 2580269024Semaste 2581269024Semaste if (stop_on_continue == eLazyBoolCalculate) 2582269024Semaste { 2583269024Semaste if (m_command_source_flags.empty()) 2584269024Semaste { 2585269024Semaste // Stop on continue by default 2586269024Semaste flags |= eHandleCommandFlagStopOnContinue; 2587269024Semaste } 2588269024Semaste else if (m_command_source_flags.back() & eHandleCommandFlagStopOnContinue) 2589269024Semaste { 2590269024Semaste flags |= eHandleCommandFlagStopOnContinue; 2591269024Semaste } 2592269024Semaste } 2593269024Semaste else if (stop_on_continue == eLazyBoolYes) 2594269024Semaste { 2595269024Semaste flags |= eHandleCommandFlagStopOnContinue; 2596269024Semaste } 2597269024Semaste 2598269024Semaste if (stop_on_error == eLazyBoolCalculate) 2599269024Semaste { 2600269024Semaste if (m_command_source_flags.empty()) 2601269024Semaste { 2602269024Semaste if (GetStopCmdSourceOnError()) 2603269024Semaste flags |= eHandleCommandFlagStopOnError; 2604269024Semaste } 2605269024Semaste else if (m_command_source_flags.back() & eHandleCommandFlagStopOnError) 2606269024Semaste { 2607269024Semaste flags |= eHandleCommandFlagStopOnError; 2608269024Semaste } 2609269024Semaste } 2610269024Semaste else if (stop_on_error == eLazyBoolYes) 2611269024Semaste { 2612269024Semaste flags |= eHandleCommandFlagStopOnError; 2613269024Semaste } 2614269024Semaste 2615269024Semaste if (echo_command == eLazyBoolCalculate) 2616269024Semaste { 2617269024Semaste if (m_command_source_flags.empty()) 2618269024Semaste { 2619269024Semaste // Echo command by default 2620269024Semaste flags |= eHandleCommandFlagEchoCommand; 2621269024Semaste } 2622269024Semaste else if (m_command_source_flags.back() & eHandleCommandFlagEchoCommand) 2623269024Semaste { 2624269024Semaste flags |= eHandleCommandFlagEchoCommand; 2625269024Semaste } 2626269024Semaste } 2627269024Semaste else if (echo_command == eLazyBoolYes) 2628269024Semaste { 2629269024Semaste flags |= eHandleCommandFlagEchoCommand; 2630269024Semaste } 2631269024Semaste 2632269024Semaste if (print_result == eLazyBoolCalculate) 2633269024Semaste { 2634269024Semaste if (m_command_source_flags.empty()) 2635269024Semaste { 2636269024Semaste // Print output by default 2637269024Semaste flags |= eHandleCommandFlagPrintResult; 2638269024Semaste } 2639269024Semaste else if (m_command_source_flags.back() & eHandleCommandFlagPrintResult) 2640269024Semaste { 2641269024Semaste flags |= eHandleCommandFlagPrintResult; 2642269024Semaste } 2643269024Semaste } 2644269024Semaste else if (print_result == eLazyBoolYes) 2645269024Semaste { 2646269024Semaste flags |= eHandleCommandFlagPrintResult; 2647269024Semaste } 2648269024Semaste 2649269024Semaste if (flags & eHandleCommandFlagPrintResult) 2650269024Semaste { 2651269024Semaste debugger.GetOutputFile()->Printf("Executing commands in '%s'.\n", cmd_file_path.c_str()); 2652269024Semaste } 2653269024Semaste 2654269024Semaste // Used for inheriting the right settings when "command source" might have 2655269024Semaste // nested "command source" commands 2656269024Semaste lldb::StreamFileSP empty_stream_sp; 2657269024Semaste m_command_source_flags.push_back(flags); 2658269024Semaste IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger, 2659269024Semaste input_file_sp, 2660269024Semaste empty_stream_sp, // Pass in an empty stream so we inherit the top input reader output stream 2661269024Semaste empty_stream_sp, // Pass in an empty stream so we inherit the top input reader error stream 2662269024Semaste flags, 2663269024Semaste NULL, // Pass in NULL for "editline_name" so no history is saved, or written 2664269024Semaste debugger.GetPrompt(), 2665269024Semaste false, // Not multi-line 2666269024Semaste *this)); 2667269024Semaste const bool old_async_execution = debugger.GetAsyncExecution(); 2668269024Semaste 2669269024Semaste // Set synchronous execution if we not stopping when we continue 2670269024Semaste if ((flags & eHandleCommandFlagStopOnContinue) == 0) 2671269024Semaste debugger.SetAsyncExecution (false); 2672269024Semaste 2673269024Semaste m_command_source_depth++; 2674269024Semaste 2675269024Semaste debugger.RunIOHandler(io_handler_sp); 2676269024Semaste if (!m_command_source_flags.empty()) 2677269024Semaste m_command_source_flags.pop_back(); 2678269024Semaste m_command_source_depth--; 2679269024Semaste result.SetStatus (eReturnStatusSuccessFinishNoResult); 2680269024Semaste debugger.SetAsyncExecution (old_async_execution); 2681269024Semaste } 2682269024Semaste else 2683269024Semaste { 2684269024Semaste result.AppendErrorWithFormat ("error: an error occurred read file '%s': %s\n", cmd_file_path.c_str(), error.AsCString()); 2685254721Semaste result.SetStatus (eReturnStatusFailed); 2686254721Semaste } 2687269024Semaste 2688269024Semaste 2689254721Semaste } 2690254721Semaste else 2691254721Semaste { 2692254721Semaste result.AppendErrorWithFormat ("Error reading commands from file %s - file not found.\n", 2693254721Semaste cmd_file.GetFilename().AsCString()); 2694254721Semaste result.SetStatus (eReturnStatusFailed); 2695254721Semaste return; 2696254721Semaste } 2697254721Semaste} 2698254721Semaste 2699254721SemasteScriptInterpreter * 2700254721SemasteCommandInterpreter::GetScriptInterpreter (bool can_create) 2701254721Semaste{ 2702254721Semaste if (m_script_interpreter_ap.get() != NULL) 2703254721Semaste return m_script_interpreter_ap.get(); 2704254721Semaste 2705254721Semaste if (!can_create) 2706254721Semaste return NULL; 2707254721Semaste 2708254721Semaste // <rdar://problem/11751427> 2709254721Semaste // we need to protect the initialization of the script interpreter 2710254721Semaste // otherwise we could end up with two threads both trying to create 2711254721Semaste // their instance of it, and for some languages (e.g. Python) 2712254721Semaste // this is a bulletproof recipe for disaster! 2713254721Semaste // this needs to be a function-level static because multiple Debugger instances living in the same process 2714254721Semaste // still need to be isolated and not try to initialize Python concurrently 2715254721Semaste static Mutex g_interpreter_mutex(Mutex::eMutexTypeRecursive); 2716254721Semaste Mutex::Locker interpreter_lock(g_interpreter_mutex); 2717254721Semaste 2718254721Semaste Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); 2719254721Semaste if (log) 2720254721Semaste log->Printf("Initializing the ScriptInterpreter now\n"); 2721254721Semaste 2722254721Semaste lldb::ScriptLanguage script_lang = GetDebugger().GetScriptLanguage(); 2723254721Semaste switch (script_lang) 2724254721Semaste { 2725254721Semaste case eScriptLanguagePython: 2726254721Semaste#ifndef LLDB_DISABLE_PYTHON 2727254721Semaste m_script_interpreter_ap.reset (new ScriptInterpreterPython (*this)); 2728254721Semaste break; 2729254721Semaste#else 2730254721Semaste // Fall through to the None case when python is disabled 2731254721Semaste#endif 2732254721Semaste case eScriptLanguageNone: 2733254721Semaste m_script_interpreter_ap.reset (new ScriptInterpreterNone (*this)); 2734254721Semaste break; 2735254721Semaste }; 2736254721Semaste 2737254721Semaste return m_script_interpreter_ap.get(); 2738254721Semaste} 2739254721Semaste 2740254721Semaste 2741254721Semaste 2742254721Semastebool 2743254721SemasteCommandInterpreter::GetSynchronous () 2744254721Semaste{ 2745254721Semaste return m_synchronous_execution; 2746254721Semaste} 2747254721Semaste 2748254721Semastevoid 2749254721SemasteCommandInterpreter::SetSynchronous (bool value) 2750254721Semaste{ 2751254721Semaste m_synchronous_execution = value; 2752254721Semaste} 2753254721Semaste 2754254721Semastevoid 2755254721SemasteCommandInterpreter::OutputFormattedHelpText (Stream &strm, 2756254721Semaste const char *word_text, 2757254721Semaste const char *separator, 2758254721Semaste const char *help_text, 2759254721Semaste size_t max_word_len) 2760254721Semaste{ 2761254721Semaste const uint32_t max_columns = m_debugger.GetTerminalWidth(); 2762254721Semaste 2763254721Semaste int indent_size = max_word_len + strlen (separator) + 2; 2764254721Semaste 2765254721Semaste strm.IndentMore (indent_size); 2766254721Semaste 2767254721Semaste StreamString text_strm; 2768254721Semaste text_strm.Printf ("%-*s %s %s", (int)max_word_len, word_text, separator, help_text); 2769254721Semaste 2770254721Semaste size_t len = text_strm.GetSize(); 2771254721Semaste const char *text = text_strm.GetData(); 2772254721Semaste if (text[len - 1] == '\n') 2773254721Semaste { 2774254721Semaste text_strm.EOL(); 2775254721Semaste len = text_strm.GetSize(); 2776254721Semaste } 2777254721Semaste 2778254721Semaste if (len < max_columns) 2779254721Semaste { 2780254721Semaste // Output it as a single line. 2781254721Semaste strm.Printf ("%s", text); 2782254721Semaste } 2783254721Semaste else 2784254721Semaste { 2785254721Semaste // We need to break it up into multiple lines. 2786254721Semaste bool first_line = true; 2787254721Semaste int text_width; 2788254721Semaste size_t start = 0; 2789254721Semaste size_t end = start; 2790254721Semaste const size_t final_end = strlen (text); 2791254721Semaste 2792254721Semaste while (end < final_end) 2793254721Semaste { 2794254721Semaste if (first_line) 2795254721Semaste text_width = max_columns - 1; 2796254721Semaste else 2797254721Semaste text_width = max_columns - indent_size - 1; 2798254721Semaste 2799254721Semaste // Don't start the 'text' on a space, since we're already outputting the indentation. 2800254721Semaste if (!first_line) 2801254721Semaste { 2802254721Semaste while ((start < final_end) && (text[start] == ' ')) 2803254721Semaste start++; 2804254721Semaste } 2805254721Semaste 2806254721Semaste end = start + text_width; 2807254721Semaste if (end > final_end) 2808254721Semaste end = final_end; 2809254721Semaste else 2810254721Semaste { 2811254721Semaste // If we're not at the end of the text, make sure we break the line on white space. 2812254721Semaste while (end > start 2813254721Semaste && text[end] != ' ' && text[end] != '\t' && text[end] != '\n') 2814254721Semaste end--; 2815254721Semaste assert (end > 0); 2816254721Semaste } 2817254721Semaste 2818254721Semaste const size_t sub_len = end - start; 2819254721Semaste if (start != 0) 2820254721Semaste strm.EOL(); 2821254721Semaste if (!first_line) 2822254721Semaste strm.Indent(); 2823254721Semaste else 2824254721Semaste first_line = false; 2825254721Semaste assert (start <= final_end); 2826254721Semaste assert (start + sub_len <= final_end); 2827254721Semaste if (sub_len > 0) 2828254721Semaste strm.Write (text + start, sub_len); 2829254721Semaste start = end + 1; 2830254721Semaste } 2831254721Semaste } 2832254721Semaste strm.EOL(); 2833254721Semaste strm.IndentLess(indent_size); 2834254721Semaste} 2835254721Semaste 2836254721Semastevoid 2837254721SemasteCommandInterpreter::OutputHelpText (Stream &strm, 2838254721Semaste const char *word_text, 2839254721Semaste const char *separator, 2840254721Semaste const char *help_text, 2841254721Semaste uint32_t max_word_len) 2842254721Semaste{ 2843254721Semaste int indent_size = max_word_len + strlen (separator) + 2; 2844254721Semaste 2845254721Semaste strm.IndentMore (indent_size); 2846254721Semaste 2847254721Semaste StreamString text_strm; 2848254721Semaste text_strm.Printf ("%-*s %s %s", max_word_len, word_text, separator, help_text); 2849254721Semaste 2850254721Semaste const uint32_t max_columns = m_debugger.GetTerminalWidth(); 2851254721Semaste 2852254721Semaste size_t len = text_strm.GetSize(); 2853254721Semaste const char *text = text_strm.GetData(); 2854254721Semaste 2855254721Semaste uint32_t chars_left = max_columns; 2856254721Semaste 2857254721Semaste for (uint32_t i = 0; i < len; i++) 2858254721Semaste { 2859254721Semaste if ((text[i] == ' ' && ::strchr((text+i+1), ' ') && chars_left < ::strchr((text+i+1), ' ')-(text+i)) || text[i] == '\n') 2860254721Semaste { 2861254721Semaste chars_left = max_columns - indent_size; 2862254721Semaste strm.EOL(); 2863254721Semaste strm.Indent(); 2864254721Semaste } 2865254721Semaste else 2866254721Semaste { 2867254721Semaste strm.PutChar(text[i]); 2868254721Semaste chars_left--; 2869254721Semaste } 2870254721Semaste 2871254721Semaste } 2872254721Semaste 2873254721Semaste strm.EOL(); 2874254721Semaste strm.IndentLess(indent_size); 2875254721Semaste} 2876254721Semaste 2877254721Semastevoid 2878254721SemasteCommandInterpreter::FindCommandsForApropos (const char *search_word, StringList &commands_found, 2879254721Semaste StringList &commands_help, bool search_builtin_commands, bool search_user_commands) 2880254721Semaste{ 2881254721Semaste CommandObject::CommandMap::const_iterator pos; 2882254721Semaste 2883254721Semaste if (search_builtin_commands) 2884254721Semaste { 2885254721Semaste for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos) 2886254721Semaste { 2887254721Semaste const char *command_name = pos->first.c_str(); 2888254721Semaste CommandObject *cmd_obj = pos->second.get(); 2889254721Semaste 2890254721Semaste if (cmd_obj->HelpTextContainsWord (search_word)) 2891254721Semaste { 2892254721Semaste commands_found.AppendString (command_name); 2893254721Semaste commands_help.AppendString (cmd_obj->GetHelp()); 2894254721Semaste } 2895254721Semaste 2896254721Semaste if (cmd_obj->IsMultiwordObject()) 2897254721Semaste cmd_obj->AproposAllSubCommands (command_name, 2898254721Semaste search_word, 2899254721Semaste commands_found, 2900254721Semaste commands_help); 2901254721Semaste 2902254721Semaste } 2903254721Semaste } 2904254721Semaste 2905254721Semaste if (search_user_commands) 2906254721Semaste { 2907254721Semaste for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos) 2908254721Semaste { 2909254721Semaste const char *command_name = pos->first.c_str(); 2910254721Semaste CommandObject *cmd_obj = pos->second.get(); 2911254721Semaste 2912254721Semaste if (cmd_obj->HelpTextContainsWord (search_word)) 2913254721Semaste { 2914254721Semaste commands_found.AppendString (command_name); 2915254721Semaste commands_help.AppendString (cmd_obj->GetHelp()); 2916254721Semaste } 2917254721Semaste 2918254721Semaste if (cmd_obj->IsMultiwordObject()) 2919254721Semaste cmd_obj->AproposAllSubCommands (command_name, 2920254721Semaste search_word, 2921254721Semaste commands_found, 2922254721Semaste commands_help); 2923254721Semaste 2924254721Semaste } 2925254721Semaste } 2926254721Semaste} 2927254721Semaste 2928254721Semastevoid 2929254721SemasteCommandInterpreter::UpdateExecutionContext (ExecutionContext *override_context) 2930254721Semaste{ 2931254721Semaste if (override_context != NULL) 2932254721Semaste { 2933254721Semaste m_exe_ctx_ref = *override_context; 2934254721Semaste } 2935254721Semaste else 2936254721Semaste { 2937254721Semaste const bool adopt_selected = true; 2938254721Semaste m_exe_ctx_ref.SetTargetPtr (m_debugger.GetSelectedTarget().get(), adopt_selected); 2939254721Semaste } 2940254721Semaste} 2941269024Semaste 2942269024Semaste 2943269024Semastesize_t 2944269024SemasteCommandInterpreter::GetProcessOutput () 2945269024Semaste{ 2946269024Semaste // The process has stuff waiting for stderr; get it and write it out to the appropriate place. 2947269024Semaste char stdio_buffer[1024]; 2948269024Semaste size_t len; 2949269024Semaste size_t total_bytes = 0; 2950269024Semaste Error error; 2951269024Semaste TargetSP target_sp (m_debugger.GetTargetList().GetSelectedTarget()); 2952269024Semaste if (target_sp) 2953269024Semaste { 2954269024Semaste ProcessSP process_sp (target_sp->GetProcessSP()); 2955269024Semaste if (process_sp) 2956269024Semaste { 2957269024Semaste while ((len = process_sp->GetSTDOUT (stdio_buffer, sizeof (stdio_buffer), error)) > 0) 2958269024Semaste { 2959269024Semaste size_t bytes_written = len; 2960269024Semaste m_debugger.GetOutputFile()->Write (stdio_buffer, bytes_written); 2961269024Semaste total_bytes += len; 2962269024Semaste } 2963269024Semaste while ((len = process_sp->GetSTDERR (stdio_buffer, sizeof (stdio_buffer), error)) > 0) 2964269024Semaste { 2965269024Semaste size_t bytes_written = len; 2966269024Semaste m_debugger.GetErrorFile()->Write (stdio_buffer, bytes_written); 2967269024Semaste total_bytes += len; 2968269024Semaste } 2969269024Semaste } 2970269024Semaste } 2971269024Semaste return total_bytes; 2972269024Semaste} 2973269024Semaste 2974269024Semastevoid 2975269024SemasteCommandInterpreter::IOHandlerInputComplete (IOHandler &io_handler, std::string &line) 2976269024Semaste{ 2977269024Semaste const bool is_interactive = io_handler.GetIsInteractive(); 2978269024Semaste if (is_interactive == false) 2979269024Semaste { 2980269024Semaste // When we are not interactive, don't execute blank lines. This will happen 2981269024Semaste // sourcing a commands file. We don't want blank lines to repeat the previous 2982269024Semaste // command and cause any errors to occur (like redefining an alias, get an error 2983269024Semaste // and stop parsing the commands file). 2984269024Semaste if (line.empty()) 2985269024Semaste return; 2986269024Semaste 2987269024Semaste // When using a non-interactive file handle (like when sourcing commands from a file) 2988269024Semaste // we need to echo the command out so we don't just see the command output and no 2989269024Semaste // command... 2990269024Semaste if (io_handler.GetFlags().Test(eHandleCommandFlagEchoCommand)) 2991269024Semaste io_handler.GetOutputStreamFile()->Printf("%s%s\n", io_handler.GetPrompt(), line.c_str()); 2992269024Semaste } 2993269024Semaste 2994269024Semaste lldb_private::CommandReturnObject result; 2995269024Semaste HandleCommand(line.c_str(), eLazyBoolCalculate, result); 2996269024Semaste 2997269024Semaste // Now emit the command output text from the command we just executed 2998269024Semaste if (io_handler.GetFlags().Test(eHandleCommandFlagPrintResult)) 2999269024Semaste { 3000269024Semaste // Display any STDOUT/STDERR _prior_ to emitting the command result text 3001269024Semaste GetProcessOutput (); 3002269024Semaste 3003269024Semaste if (!result.GetImmediateOutputStream()) 3004269024Semaste { 3005269024Semaste const char *output = result.GetOutputData(); 3006269024Semaste if (output && output[0]) 3007269024Semaste io_handler.GetOutputStreamFile()->PutCString(output); 3008269024Semaste } 3009269024Semaste 3010269024Semaste // Now emit the command error text from the command we just executed 3011269024Semaste if (!result.GetImmediateErrorStream()) 3012269024Semaste { 3013269024Semaste const char *error = result.GetErrorData(); 3014269024Semaste if (error && error[0]) 3015269024Semaste io_handler.GetErrorStreamFile()->PutCString(error); 3016269024Semaste } 3017269024Semaste } 3018269024Semaste 3019269024Semaste switch (result.GetStatus()) 3020269024Semaste { 3021269024Semaste case eReturnStatusInvalid: 3022269024Semaste case eReturnStatusSuccessFinishNoResult: 3023269024Semaste case eReturnStatusSuccessFinishResult: 3024269024Semaste case eReturnStatusStarted: 3025269024Semaste break; 3026269024Semaste 3027269024Semaste case eReturnStatusSuccessContinuingNoResult: 3028269024Semaste case eReturnStatusSuccessContinuingResult: 3029269024Semaste if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnContinue)) 3030269024Semaste io_handler.SetIsDone(true); 3031269024Semaste break; 3032269024Semaste 3033269024Semaste case eReturnStatusFailed: 3034269024Semaste if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnError)) 3035269024Semaste io_handler.SetIsDone(true); 3036269024Semaste break; 3037269024Semaste 3038269024Semaste case eReturnStatusQuit: 3039269024Semaste io_handler.SetIsDone(true); 3040269024Semaste break; 3041269024Semaste } 3042269024Semaste} 3043269024Semaste 3044269024Semastevoid 3045269024SemasteCommandInterpreter::GetLLDBCommandsFromIOHandler (const char *prompt, 3046269024Semaste IOHandlerDelegate &delegate, 3047269024Semaste bool asynchronously, 3048269024Semaste void *baton) 3049269024Semaste{ 3050269024Semaste Debugger &debugger = GetDebugger(); 3051269024Semaste IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger, 3052269024Semaste "lldb", // Name of input reader for history 3053269024Semaste prompt, // Prompt 3054269024Semaste true, // Get multiple lines 3055269024Semaste delegate)); // IOHandlerDelegate 3056269024Semaste 3057269024Semaste if (io_handler_sp) 3058269024Semaste { 3059269024Semaste io_handler_sp->SetUserData (baton); 3060269024Semaste if (asynchronously) 3061269024Semaste debugger.PushIOHandler(io_handler_sp); 3062269024Semaste else 3063269024Semaste debugger.RunIOHandler(io_handler_sp); 3064269024Semaste } 3065269024Semaste 3066269024Semaste} 3067269024Semaste 3068269024Semaste 3069269024Semastevoid 3070269024SemasteCommandInterpreter::GetPythonCommandsFromIOHandler (const char *prompt, 3071269024Semaste IOHandlerDelegate &delegate, 3072269024Semaste bool asynchronously, 3073269024Semaste void *baton) 3074269024Semaste{ 3075269024Semaste Debugger &debugger = GetDebugger(); 3076269024Semaste IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger, 3077269024Semaste "lldb-python", // Name of input reader for history 3078269024Semaste prompt, // Prompt 3079269024Semaste true, // Get multiple lines 3080269024Semaste delegate)); // IOHandlerDelegate 3081269024Semaste 3082269024Semaste if (io_handler_sp) 3083269024Semaste { 3084269024Semaste io_handler_sp->SetUserData (baton); 3085269024Semaste if (asynchronously) 3086269024Semaste debugger.PushIOHandler(io_handler_sp); 3087269024Semaste else 3088269024Semaste debugger.RunIOHandler(io_handler_sp); 3089269024Semaste } 3090269024Semaste 3091269024Semaste} 3092269024Semaste 3093269024Semastebool 3094269024SemasteCommandInterpreter::IsActive () 3095269024Semaste{ 3096269024Semaste return m_debugger.IsTopIOHandler (m_command_io_handler_sp); 3097269024Semaste} 3098269024Semaste 3099269024Semastevoid 3100269024SemasteCommandInterpreter::RunCommandInterpreter(bool auto_handle_events, 3101269024Semaste bool spawn_thread) 3102269024Semaste{ 3103269024Semaste const bool multiple_lines = false; // Only get one line at a time 3104269024Semaste if (!m_command_io_handler_sp) 3105269024Semaste m_command_io_handler_sp.reset(new IOHandlerEditline (m_debugger, 3106269024Semaste m_debugger.GetInputFile(), 3107269024Semaste m_debugger.GetOutputFile(), 3108269024Semaste m_debugger.GetErrorFile(), 3109269024Semaste eHandleCommandFlagEchoCommand | eHandleCommandFlagPrintResult, 3110269024Semaste "lldb", 3111269024Semaste m_debugger.GetPrompt(), 3112269024Semaste multiple_lines, 3113269024Semaste *this)); 3114269024Semaste m_debugger.PushIOHandler(m_command_io_handler_sp); 3115269024Semaste 3116269024Semaste if (auto_handle_events) 3117269024Semaste m_debugger.StartEventHandlerThread(); 3118269024Semaste 3119269024Semaste if (spawn_thread) 3120269024Semaste { 3121269024Semaste m_debugger.StartIOHandlerThread(); 3122269024Semaste } 3123269024Semaste else 3124269024Semaste { 3125269024Semaste m_debugger.ExecuteIOHanders(); 3126269024Semaste 3127269024Semaste if (auto_handle_events) 3128269024Semaste m_debugger.StopEventHandlerThread(); 3129269024Semaste } 3130269024Semaste 3131269024Semaste} 3132269024Semaste 3133