2010-06-09 00:52:24 +08:00
//===-- CommandInterpreter.cpp ----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
2012-12-05 08:20:57 +08:00
# include "lldb/lldb-python.h"
2010-06-09 00:52:24 +08:00
# include <string>
2010-10-13 05:57:09 +08:00
# include <vector>
2010-06-09 00:52:24 +08:00
# include <stdlib.h>
2011-06-24 01:59:56 +08:00
# include "CommandObjectScript.h"
2011-06-24 04:37:26 +08:00
# include "lldb/Interpreter/CommandObjectRegexCommand.h"
2011-06-24 01:59:56 +08:00
2010-06-13 10:17:17 +08:00
# include "../Commands/CommandObjectApropos.h"
# include "../Commands/CommandObjectArgs.h"
# include "../Commands/CommandObjectBreakpoint.h"
# include "../Commands/CommandObjectDisassemble.h"
# include "../Commands/CommandObjectExpression.h"
# include "../Commands/CommandObjectFrame.h"
# include "../Commands/CommandObjectHelp.h"
# include "../Commands/CommandObjectLog.h"
# include "../Commands/CommandObjectMemory.h"
2011-03-19 09:12:21 +08:00
# include "../Commands/CommandObjectPlatform.h"
2012-09-29 07:57:51 +08:00
# include "../Commands/CommandObjectPlugin.h"
2010-06-13 10:17:17 +08:00
# include "../Commands/CommandObjectProcess.h"
# include "../Commands/CommandObjectQuit.h"
# include "../Commands/CommandObjectRegister.h"
# include "../Commands/CommandObjectSettings.h"
# include "../Commands/CommandObjectSource.h"
2010-07-07 11:36:20 +08:00
# include "../Commands/CommandObjectCommands.h"
2010-06-13 10:17:17 +08:00
# include "../Commands/CommandObjectSyntax.h"
# include "../Commands/CommandObjectTarget.h"
# include "../Commands/CommandObjectThread.h"
2011-06-24 01:59:56 +08:00
# include "../Commands/CommandObjectType.h"
2010-12-24 04:21:44 +08:00
# include "../Commands/CommandObjectVersion.h"
2011-09-23 02:04:58 +08:00
# include "../Commands/CommandObjectWatchpoint.h"
2010-06-09 00:52:24 +08:00
2013-03-30 01:03:23 +08:00
2010-06-09 00:52:24 +08:00
# include "lldb/Core/Debugger.h"
2010-10-05 03:49:29 +08:00
# include "lldb/Core/InputReader.h"
2012-10-30 05:18:03 +08:00
# include "lldb/Core/Log.h"
2010-06-09 00:52:24 +08:00
# include "lldb/Core/Stream.h"
# include "lldb/Core/Timer.h"
2012-10-30 05:18:03 +08:00
2011-02-01 09:31:41 +08:00
# include "lldb/Host/Host.h"
2010-06-09 00:52:24 +08:00
2012-10-30 05:18:03 +08:00
# include "lldb/Interpreter/Args.h"
2013-03-30 01:03:23 +08:00
# include "lldb/Interpreter/CommandCompletions.h"
2010-06-09 00:52:24 +08:00
# include "lldb/Interpreter/CommandInterpreter.h"
2013-03-30 01:03:23 +08:00
# include "lldb/Interpreter/CommandReturnObject.h"
2012-10-30 05:18:03 +08:00
# include "lldb/Interpreter/Options.h"
2011-01-14 08:29:16 +08:00
# include "lldb/Interpreter/ScriptInterpreterNone.h"
# include "lldb/Interpreter/ScriptInterpreterPython.h"
2010-06-09 00:52:24 +08:00
2012-10-30 05:18:03 +08:00
# include "lldb/Target/Process.h"
# include "lldb/Target/Thread.h"
# include "lldb/Target/TargetList.h"
# include "lldb/Utility/CleanUp.h"
2010-06-09 00:52:24 +08:00
using namespace lldb ;
using namespace lldb_private ;
2012-08-23 08:22:02 +08:00
static PropertyDefinition
g_properties [ ] =
{
{ " 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. " } ,
2013-01-18 05:36:19 +08:00
{ " 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. " } ,
2013-06-11 09:26:35 +08:00
{ " 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. " } ,
2012-08-23 08:22:02 +08:00
{ NULL , OptionValue : : eTypeInvalid , true , 0 , NULL , NULL , NULL }
} ;
enum
{
2013-01-18 05:36:19 +08:00
ePropertyExpandRegexAliases = 0 ,
2013-06-11 09:26:35 +08:00
ePropertyPromptOnQuit = 1 ,
ePropertyStopCmdSourceOnError = 2
2012-08-23 08:22:02 +08:00
} ;
2012-02-16 14:50:00 +08:00
ConstString &
CommandInterpreter : : GetStaticBroadcasterClass ( )
{
static ConstString class_name ( " lldb.commandInterpreter " ) ;
return class_name ;
}
2010-06-09 00:52:24 +08:00
CommandInterpreter : : CommandInterpreter
(
2010-06-23 09:19:29 +08:00
Debugger & debugger ,
2010-06-09 00:52:24 +08:00
ScriptLanguage script_language ,
2010-06-23 09:19:29 +08:00
bool synchronous_execution
2010-06-09 00:52:24 +08:00
) :
2012-02-16 14:50:00 +08:00
Broadcaster ( & debugger , " lldb.command-interpreter " ) ,
2012-08-23 08:22:02 +08:00
Properties ( OptionValuePropertiesSP ( new OptionValueProperties ( ConstString ( " interpreter " ) ) ) ) ,
2010-06-23 09:19:29 +08:00
m_debugger ( debugger ) ,
2010-10-11 09:05:37 +08:00
m_synchronous_execution ( synchronous_execution ) ,
2011-01-14 08:29:16 +08:00
m_skip_lldbinit_files ( false ) ,
2011-08-13 07:34:31 +08:00
m_skip_app_init_files ( false ) ,
2011-02-18 08:54:25 +08:00
m_script_interpreter_ap ( ) ,
2011-06-17 00:27:19 +08:00
m_comment_char ( ' # ' ) ,
2012-08-10 06:06:10 +08:00
m_batch_command_mode ( false ) ,
2012-05-31 09:09:06 +08:00
m_truncation_warning ( eNoTruncation ) ,
m_command_source_depth ( 0 )
2010-06-09 00:52:24 +08:00
{
2012-08-23 01:17:09 +08:00
debugger . SetScriptLanguage ( script_language ) ;
2010-10-31 11:01:06 +08:00
SetEventName ( eBroadcastBitThreadShouldExit , " thread-should-exit " ) ;
SetEventName ( eBroadcastBitResetPrompt , " reset-prompt " ) ;
2012-08-23 01:17:09 +08:00
SetEventName ( eBroadcastBitQuitCommandReceived , " quit " ) ;
2012-02-16 14:50:00 +08:00
CheckInWithManager ( ) ;
2012-08-23 08:22:02 +08:00
m_collection_sp - > Initialize ( g_properties ) ;
2010-06-09 00:52:24 +08:00
}
2012-08-23 08:22:02 +08:00
bool
CommandInterpreter : : GetExpandRegexAliases ( ) const
{
const uint32_t idx = ePropertyExpandRegexAliases ;
return m_collection_sp - > GetPropertyAtIndexAsBoolean ( NULL , idx , g_properties [ idx ] . default_uint_value ! = 0 ) ;
}
2013-01-18 05:36:19 +08:00
bool
CommandInterpreter : : GetPromptOnQuit ( ) const
{
const uint32_t idx = ePropertyPromptOnQuit ;
return m_collection_sp - > GetPropertyAtIndexAsBoolean ( NULL , idx , g_properties [ idx ] . default_uint_value ! = 0 ) ;
}
2012-08-23 08:22:02 +08:00
2013-06-11 09:26:35 +08:00
bool
CommandInterpreter : : GetStopCmdSourceOnError ( ) const
{
const uint32_t idx = ePropertyStopCmdSourceOnError ;
return m_collection_sp - > GetPropertyAtIndexAsBoolean ( NULL , idx , g_properties [ idx ] . default_uint_value ! = 0 ) ;
}
2010-06-09 00:52:24 +08:00
void
CommandInterpreter : : Initialize ( )
{
Timer scoped_timer ( __PRETTY_FUNCTION__ , __PRETTY_FUNCTION__ ) ;
CommandReturnObject result ;
LoadCommandDictionary ( ) ;
// Set up some initial aliases.
2011-05-07 05:37:15 +08:00
CommandObjectSP cmd_obj_sp = GetCommandSPExact ( " quit " , false ) ;
if ( cmd_obj_sp )
{
AddAlias ( " q " , cmd_obj_sp ) ;
AddAlias ( " exit " , cmd_obj_sp ) ;
}
2012-05-05 07:15:02 +08:00
2012-08-25 02:15:45 +08:00
cmd_obj_sp = GetCommandSPExact ( " _regexp-attach " , false ) ;
2012-05-05 07:15:02 +08:00
if ( cmd_obj_sp )
{
AddAlias ( " attach " , cmd_obj_sp ) ;
}
2011-05-07 05:37:15 +08:00
2012-08-25 02:15:45 +08:00
cmd_obj_sp = GetCommandSPExact ( " process detach " , false ) ;
if ( cmd_obj_sp )
{
AddAlias ( " detach " , cmd_obj_sp ) ;
}
2011-05-07 05:37:15 +08:00
cmd_obj_sp = GetCommandSPExact ( " process continue " , false ) ;
if ( cmd_obj_sp )
{
AddAlias ( " c " , cmd_obj_sp ) ;
AddAlias ( " continue " , cmd_obj_sp ) ;
}
cmd_obj_sp = GetCommandSPExact ( " _regexp-break " , false ) ;
if ( cmd_obj_sp )
AddAlias ( " b " , cmd_obj_sp ) ;
2012-10-06 03:16:31 +08:00
cmd_obj_sp = GetCommandSPExact ( " _regexp-tbreak " , false ) ;
if ( cmd_obj_sp )
AddAlias ( " tbreak " , cmd_obj_sp ) ;
2011-05-07 05:37:15 +08:00
cmd_obj_sp = GetCommandSPExact ( " thread step-inst " , false ) ;
if ( cmd_obj_sp )
2011-10-22 08:47:41 +08:00
{
AddAlias ( " stepi " , cmd_obj_sp ) ;
2011-05-07 05:37:15 +08:00
AddAlias ( " si " , cmd_obj_sp ) ;
2011-10-22 08:47:41 +08:00
}
cmd_obj_sp = GetCommandSPExact ( " thread step-inst-over " , false ) ;
if ( cmd_obj_sp )
{
AddAlias ( " nexti " , cmd_obj_sp ) ;
AddAlias ( " ni " , cmd_obj_sp ) ;
}
2011-05-07 05:37:15 +08:00
cmd_obj_sp = GetCommandSPExact ( " thread step-in " , false ) ;
if ( cmd_obj_sp )
{
AddAlias ( " s " , cmd_obj_sp ) ;
AddAlias ( " step " , cmd_obj_sp ) ;
}
cmd_obj_sp = GetCommandSPExact ( " thread step-over " , false ) ;
if ( cmd_obj_sp )
{
AddAlias ( " n " , cmd_obj_sp ) ;
AddAlias ( " next " , cmd_obj_sp ) ;
}
cmd_obj_sp = GetCommandSPExact ( " thread step-out " , false ) ;
if ( cmd_obj_sp )
{
AddAlias ( " finish " , cmd_obj_sp ) ;
}
2011-12-02 09:12:59 +08:00
cmd_obj_sp = GetCommandSPExact ( " frame select " , false ) ;
if ( cmd_obj_sp )
{
AddAlias ( " f " , cmd_obj_sp ) ;
}
2012-10-06 03:16:31 +08:00
cmd_obj_sp = GetCommandSPExact ( " thread select " , false ) ;
if ( cmd_obj_sp )
{
AddAlias ( " t " , cmd_obj_sp ) ;
}
2013-09-12 10:20:34 +08:00
cmd_obj_sp = GetCommandSPExact ( " _regexp-jump " , false ) ;
if ( cmd_obj_sp )
{
AddAlias ( " j " , cmd_obj_sp ) ;
AddAlias ( " jump " , cmd_obj_sp ) ;
}
2013-02-02 07:33:03 +08:00
cmd_obj_sp = GetCommandSPExact ( " _regexp-list " , false ) ;
2011-05-07 05:37:15 +08:00
if ( cmd_obj_sp )
{
AddAlias ( " l " , cmd_obj_sp ) ;
AddAlias ( " list " , cmd_obj_sp ) ;
}
2013-02-13 02:52:24 +08:00
cmd_obj_sp = GetCommandSPExact ( " _regexp-env " , false ) ;
if ( cmd_obj_sp )
{
AddAlias ( " env " , cmd_obj_sp ) ;
}
2011-05-07 05:37:15 +08:00
cmd_obj_sp = GetCommandSPExact ( " memory read " , false ) ;
if ( cmd_obj_sp )
AddAlias ( " x " , cmd_obj_sp ) ;
cmd_obj_sp = GetCommandSPExact ( " _regexp-up " , false ) ;
if ( cmd_obj_sp )
AddAlias ( " up " , cmd_obj_sp ) ;
cmd_obj_sp = GetCommandSPExact ( " _regexp-down " , false ) ;
if ( cmd_obj_sp )
AddAlias ( " down " , cmd_obj_sp ) ;
2011-10-25 10:11:20 +08:00
cmd_obj_sp = GetCommandSPExact ( " _regexp-display " , false ) ;
2011-10-22 09:30:52 +08:00
if ( cmd_obj_sp )
AddAlias ( " display " , cmd_obj_sp ) ;
2011-10-25 02:37:00 +08:00
cmd_obj_sp = GetCommandSPExact ( " disassemble " , false ) ;
if ( cmd_obj_sp )
AddAlias ( " dis " , cmd_obj_sp ) ;
cmd_obj_sp = GetCommandSPExact ( " disassemble " , false ) ;
if ( cmd_obj_sp )
AddAlias ( " di " , cmd_obj_sp ) ;
2011-10-22 09:30:52 +08:00
2011-10-25 10:11:20 +08:00
cmd_obj_sp = GetCommandSPExact ( " _regexp-undisplay " , false ) ;
2011-10-22 09:30:52 +08:00
if ( cmd_obj_sp )
AddAlias ( " undisplay " , cmd_obj_sp ) ;
2012-10-11 00:51:31 +08:00
cmd_obj_sp = GetCommandSPExact ( " _regexp-bt " , false ) ;
if ( cmd_obj_sp )
AddAlias ( " bt " , cmd_obj_sp ) ;
2011-05-07 05:37:15 +08:00
cmd_obj_sp = GetCommandSPExact ( " target create " , false ) ;
if ( cmd_obj_sp )
AddAlias ( " file " , cmd_obj_sp ) ;
cmd_obj_sp = GetCommandSPExact ( " target modules " , false ) ;
if ( cmd_obj_sp )
AddAlias ( " image " , cmd_obj_sp ) ;
OptionArgVectorSP alias_arguments_vector_sp ( new OptionArgVector ) ;
2011-03-22 10:29:32 +08:00
2011-05-07 05:37:15 +08:00
cmd_obj_sp = GetCommandSPExact ( " expression " , false ) ;
if ( cmd_obj_sp )
2013-04-18 01:23:58 +08:00
{
2011-05-07 05:37:15 +08:00
ProcessAliasOptionsArgs ( cmd_obj_sp , " -- " , alias_arguments_vector_sp ) ;
AddAlias ( " p " , cmd_obj_sp ) ;
AddAlias ( " print " , cmd_obj_sp ) ;
2012-08-08 09:30:34 +08:00
AddAlias ( " call " , cmd_obj_sp ) ;
2011-05-07 05:37:15 +08:00
AddOrReplaceAliasOptions ( " p " , alias_arguments_vector_sp ) ;
AddOrReplaceAliasOptions ( " print " , alias_arguments_vector_sp ) ;
2012-08-08 09:30:34 +08:00
AddOrReplaceAliasOptions ( " call " , alias_arguments_vector_sp ) ;
2011-05-07 05:37:15 +08:00
alias_arguments_vector_sp . reset ( new OptionArgVector ) ;
2013-05-15 09:03:08 +08:00
ProcessAliasOptionsArgs ( cmd_obj_sp , " -O -- " , alias_arguments_vector_sp ) ;
2011-05-07 05:37:15 +08:00
AddAlias ( " po " , cmd_obj_sp ) ;
AddOrReplaceAliasOptions ( " po " , alias_arguments_vector_sp ) ;
}
2012-06-02 07:29:32 +08:00
cmd_obj_sp = GetCommandSPExact ( " process kill " , false ) ;
if ( cmd_obj_sp )
2012-09-27 08:02:27 +08:00
{
2012-06-02 07:29:32 +08:00
AddAlias ( " kill " , cmd_obj_sp ) ;
2012-09-27 08:02:27 +08:00
}
2012-06-02 07:29:32 +08:00
2011-05-07 05:37:15 +08:00
cmd_obj_sp = GetCommandSPExact ( " process launch " , false ) ;
if ( cmd_obj_sp )
{
alias_arguments_vector_sp . reset ( new OptionArgVector ) ;
2012-07-06 10:46:23 +08:00
# if defined (__arm__)
ProcessAliasOptionsArgs ( cmd_obj_sp , " -- " , alias_arguments_vector_sp ) ;
# else
2013-09-06 05:38:45 +08:00
ProcessAliasOptionsArgs ( cmd_obj_sp , " --shell= " LLDB_DEFAULT_SHELL " -- " , alias_arguments_vector_sp ) ;
2012-07-06 10:46:23 +08:00
# endif
2011-05-07 05:37:15 +08:00
AddAlias ( " r " , cmd_obj_sp ) ;
AddAlias ( " run " , cmd_obj_sp ) ;
AddOrReplaceAliasOptions ( " r " , alias_arguments_vector_sp ) ;
AddOrReplaceAliasOptions ( " run " , alias_arguments_vector_sp ) ;
}
2012-03-30 05:47:51 +08:00
cmd_obj_sp = GetCommandSPExact ( " target symbols add " , false ) ;
if ( cmd_obj_sp )
{
AddAlias ( " add-dsym " , cmd_obj_sp ) ;
}
2012-05-22 02:25:19 +08:00
cmd_obj_sp = GetCommandSPExact ( " breakpoint set " , false ) ;
if ( cmd_obj_sp )
{
alias_arguments_vector_sp . reset ( new OptionArgVector ) ;
ProcessAliasOptionsArgs ( cmd_obj_sp , " --func-regex %1 " , alias_arguments_vector_sp ) ;
2012-10-19 07:24:12 +08:00
AddAlias ( " rbreak " , cmd_obj_sp ) ;
AddOrReplaceAliasOptions ( " rbreak " , alias_arguments_vector_sp ) ;
2012-05-22 02:25:19 +08:00
}
2010-06-09 00:52:24 +08:00
}
const char *
CommandInterpreter : : ProcessEmbeddedScriptCommands ( const char * arg )
{
// This function has not yet been implemented.
// Look for any embedded script command
// If found,
// get interpreter object from the command dictionary,
// call execute_one_command on it,
// get the results as a string,
// substitute that string for current stuff.
return arg ;
}
void
CommandInterpreter : : LoadCommandDictionary ( )
{
Timer scoped_timer ( __PRETTY_FUNCTION__ , __PRETTY_FUNCTION__ ) ;
2010-09-21 04:44:43 +08:00
lldb : : ScriptLanguage script_language = m_debugger . GetScriptLanguage ( ) ;
2010-09-04 08:03:46 +08:00
2010-09-18 09:14:36 +08:00
m_command_dict [ " apropos " ] = CommandObjectSP ( new CommandObjectApropos ( * this ) ) ;
2010-06-23 09:19:29 +08:00
m_command_dict [ " breakpoint " ] = CommandObjectSP ( new CommandObjectMultiwordBreakpoint ( * this ) ) ;
2011-04-21 08:39:18 +08:00
m_command_dict [ " command " ] = CommandObjectSP ( new CommandObjectMultiwordCommands ( * this ) ) ;
2010-09-18 09:14:36 +08:00
m_command_dict [ " disassemble " ] = CommandObjectSP ( new CommandObjectDisassemble ( * this ) ) ;
m_command_dict [ " expression " ] = CommandObjectSP ( new CommandObjectExpression ( * this ) ) ;
2010-06-23 09:19:29 +08:00
m_command_dict [ " frame " ] = CommandObjectSP ( new CommandObjectMultiwordFrame ( * this ) ) ;
2010-09-18 09:14:36 +08:00
m_command_dict [ " help " ] = CommandObjectSP ( new CommandObjectHelp ( * this ) ) ;
2010-06-23 09:19:29 +08:00
m_command_dict [ " log " ] = CommandObjectSP ( new CommandObjectLog ( * this ) ) ;
m_command_dict [ " memory " ] = CommandObjectSP ( new CommandObjectMemory ( * this ) ) ;
2011-03-19 09:12:21 +08:00
m_command_dict [ " platform " ] = CommandObjectSP ( new CommandObjectPlatform ( * this ) ) ;
2012-09-29 07:57:51 +08:00
m_command_dict [ " plugin " ] = CommandObjectSP ( new CommandObjectPlugin ( * this ) ) ;
2010-06-23 09:19:29 +08:00
m_command_dict [ " process " ] = CommandObjectSP ( new CommandObjectMultiwordProcess ( * this ) ) ;
2010-09-18 09:14:36 +08:00
m_command_dict [ " quit " ] = CommandObjectSP ( new CommandObjectQuit ( * this ) ) ;
2010-06-23 09:19:29 +08:00
m_command_dict [ " register " ] = CommandObjectSP ( new CommandObjectRegister ( * this ) ) ;
2010-09-18 09:14:36 +08:00
m_command_dict [ " script " ] = CommandObjectSP ( new CommandObjectScript ( * this , script_language ) ) ;
2010-09-04 08:03:46 +08:00
m_command_dict [ " settings " ] = CommandObjectSP ( new CommandObjectMultiwordSettings ( * this ) ) ;
2010-07-07 11:36:20 +08:00
m_command_dict [ " source " ] = CommandObjectSP ( new CommandObjectMultiwordSource ( * this ) ) ;
2010-06-23 09:19:29 +08:00
m_command_dict [ " target " ] = CommandObjectSP ( new CommandObjectMultiwordTarget ( * this ) ) ;
m_command_dict [ " thread " ] = CommandObjectSP ( new CommandObjectMultiwordThread ( * this ) ) ;
2011-08-17 07:24:13 +08:00
m_command_dict [ " type " ] = CommandObjectSP ( new CommandObjectType ( * this ) ) ;
2010-12-24 04:21:44 +08:00
m_command_dict [ " version " ] = CommandObjectSP ( new CommandObjectVersion ( * this ) ) ;
2011-09-23 02:04:58 +08:00
m_command_dict [ " watchpoint " ] = CommandObjectSP ( new CommandObjectMultiwordWatchpoint ( * this ) ) ;
2010-06-09 00:52:24 +08:00
2012-10-06 03:16:31 +08:00
const char * break_regexes [ ] [ 2 ] = { { " ^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$ " , " breakpoint set --file '%1' --line %2 " } ,
{ " ^([[:digit:]]+)[[:space:]]*$ " , " breakpoint set --line %1 " } ,
2013-02-08 10:54:24 +08:00
{ " ^ \\ *?(0x[[:xdigit:]]+)[[:space:]]*$ " , " breakpoint set --address %1 " } ,
2013-01-30 08:18:29 +08:00
{ " ^[ \" ']?([-+]? \\ [.* \\ ])[ \" ']?[[:space:]]*$ " , " breakpoint set --name '%1' " } ,
2012-10-06 03:16:31 +08:00
{ " ^(-.*)$ " , " breakpoint set %1 " } ,
{ " ^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$ " , " breakpoint set --name '%2' --shlib '%1' " } ,
2013-02-08 10:54:24 +08:00
{ " ^ \\ &(.*[^[:space:]])[[:space:]]*$ " , " breakpoint set --name '%1' --skip-prologue=0 " } ,
2012-10-06 03:16:31 +08:00
{ " ^(.*[^[:space:]])[[:space:]]*$ " , " breakpoint set --name '%1' " } } ;
size_t num_regexes = sizeof break_regexes / sizeof ( char * [ 2 ] ) ;
2013-04-19 06:45:39 +08:00
std : : unique_ptr < CommandObjectRegexCommand >
2010-09-18 09:14:36 +08:00
break_regex_cmd_ap ( new CommandObjectRegexCommand ( * this ,
2011-04-12 13:54:46 +08:00
" _regexp-break " ,
2012-08-23 08:32:22 +08:00
" Set a breakpoint using a regular expression to specify the location, where <linenum> is in decimal and <address> is in hex. " ,
2013-03-30 01:03:23 +08:00
" _regexp-break [<filename>:<linenum>] \n _regexp-break [<linenum>] \n _regexp-break [<address>] \n _regexp-break <...> " ,
2 ,
CommandCompletions : : eSymbolCompletion |
CommandCompletions : : eSourceFileCompletion ) ) ;
2012-10-06 03:16:31 +08:00
2010-06-09 00:52:24 +08:00
if ( break_regex_cmd_ap . get ( ) )
{
2012-10-06 03:16:31 +08:00
bool success = true ;
for ( size_t i = 0 ; i < num_regexes ; i + + )
{
success = break_regex_cmd_ap - > AddRegexCommand ( break_regexes [ i ] [ 0 ] , break_regexes [ i ] [ 1 ] ) ;
if ( ! success )
break ;
}
success = break_regex_cmd_ap - > AddRegexCommand ( " ^$ " , " breakpoint list --full " ) ;
if ( success )
2010-06-09 00:52:24 +08:00
{
CommandObjectSP break_regex_cmd_sp ( break_regex_cmd_ap . release ( ) ) ;
m_command_dict [ break_regex_cmd_sp - > GetCommandName ( ) ] = break_regex_cmd_sp ;
}
}
2011-03-22 10:29:32 +08:00
2013-04-19 06:45:39 +08:00
std : : unique_ptr < CommandObjectRegexCommand >
2012-10-06 03:16:31 +08:00
tbreak_regex_cmd_ap ( new CommandObjectRegexCommand ( * this ,
" _regexp-tbreak " ,
" Set a one shot breakpoint using a regular expression to specify the location, where <linenum> is in decimal and <address> is in hex. " ,
2013-03-30 01:03:23 +08:00
" _regexp-tbreak [<filename>:<linenum>] \n _regexp-break [<linenum>] \n _regexp-break [<address>] \n _regexp-break <...> " ,
2 ,
CommandCompletions : : eSymbolCompletion |
CommandCompletions : : eSourceFileCompletion ) ) ;
2012-10-06 03:16:31 +08:00
if ( tbreak_regex_cmd_ap . get ( ) )
{
bool success = true ;
for ( size_t i = 0 ; i < num_regexes ; i + + )
{
// If you add a resultant command string longer than 1024 characters be sure to increase the size of this buffer.
char buffer [ 1024 ] ;
int num_printed = snprintf ( buffer , 1024 , " %s %s " , break_regexes [ i ] [ 1 ] , " -o " ) ;
assert ( num_printed < 1024 ) ;
success = tbreak_regex_cmd_ap - > AddRegexCommand ( break_regexes [ i ] [ 0 ] , buffer ) ;
if ( ! success )
break ;
}
success = tbreak_regex_cmd_ap - > AddRegexCommand ( " ^$ " , " breakpoint list --full " ) ;
if ( success )
{
CommandObjectSP tbreak_regex_cmd_sp ( tbreak_regex_cmd_ap . release ( ) ) ;
m_command_dict [ tbreak_regex_cmd_sp - > GetCommandName ( ) ] = tbreak_regex_cmd_sp ;
}
}
2013-04-19 06:45:39 +08:00
std : : unique_ptr < CommandObjectRegexCommand >
2012-08-25 02:15:45 +08:00
attach_regex_cmd_ap ( new CommandObjectRegexCommand ( * this ,
" _regexp-attach " ,
" Attach to a process id if in decimal, otherwise treat the argument as a process name to attach to. " ,
2013-03-30 01:03:23 +08:00
" _regexp-attach [<pid>] \n _regexp-attach [<process-name>] " ,
2 ) ) ;
2012-08-25 02:15:45 +08:00
if ( attach_regex_cmd_ap . get ( ) )
{
2012-12-15 09:19:07 +08:00
if ( attach_regex_cmd_ap - > AddRegexCommand ( " ^([0-9]+)[[:space:]]*$ " , " process attach --pid %1 " ) & &
attach_regex_cmd_ap - > AddRegexCommand ( " ^(-.*|.* -.*)$ " , " process attach %1 " ) & & // Any options that are specified get passed to 'process attach'
attach_regex_cmd_ap - > AddRegexCommand ( " ^(.+)$ " , " process attach --name '%1' " ) & &
attach_regex_cmd_ap - > AddRegexCommand ( " ^$ " , " process attach " ) )
2012-08-25 02:15:45 +08:00
{
CommandObjectSP attach_regex_cmd_sp ( attach_regex_cmd_ap . release ( ) ) ;
m_command_dict [ attach_regex_cmd_sp - > GetCommandName ( ) ] = attach_regex_cmd_sp ;
}
}
2013-04-19 06:45:39 +08:00
std : : unique_ptr < CommandObjectRegexCommand >
2011-03-22 10:29:32 +08:00
down_regex_cmd_ap ( new CommandObjectRegexCommand ( * this ,
2011-04-12 13:54:46 +08:00
" _regexp-down " ,
" Go down \" n \" frames in the stack (1 frame by default). " ,
" _regexp-down [n] " , 2 ) ) ;
2011-03-22 10:29:32 +08:00
if ( down_regex_cmd_ap . get ( ) )
{
if ( down_regex_cmd_ap - > AddRegexCommand ( " ^$ " , " frame select -r -1 " ) & &
down_regex_cmd_ap - > AddRegexCommand ( " ^([0-9]+)$ " , " frame select -r -%1 " ) )
{
CommandObjectSP down_regex_cmd_sp ( down_regex_cmd_ap . release ( ) ) ;
m_command_dict [ down_regex_cmd_sp - > GetCommandName ( ) ] = down_regex_cmd_sp ;
}
}
2013-04-19 06:45:39 +08:00
std : : unique_ptr < CommandObjectRegexCommand >
2011-03-22 10:29:32 +08:00
up_regex_cmd_ap ( new CommandObjectRegexCommand ( * this ,
2011-04-12 13:54:46 +08:00
" _regexp-up " ,
" Go up \" n \" frames in the stack (1 frame by default). " ,
" _regexp-up [n] " , 2 ) ) ;
2011-03-22 10:29:32 +08:00
if ( up_regex_cmd_ap . get ( ) )
{
if ( up_regex_cmd_ap - > AddRegexCommand ( " ^$ " , " frame select -r 1 " ) & &
up_regex_cmd_ap - > AddRegexCommand ( " ^([0-9]+)$ " , " frame select -r %1 " ) )
{
CommandObjectSP up_regex_cmd_sp ( up_regex_cmd_ap . release ( ) ) ;
m_command_dict [ up_regex_cmd_sp - > GetCommandName ( ) ] = up_regex_cmd_sp ;
}
}
2011-10-22 09:30:52 +08:00
2013-04-19 06:45:39 +08:00
std : : unique_ptr < CommandObjectRegexCommand >
2011-10-22 09:30:52 +08:00
display_regex_cmd_ap ( new CommandObjectRegexCommand ( * this ,
2013-03-30 01:03:23 +08:00
" _regexp-display " ,
" Add an expression evaluation stop-hook. " ,
" _regexp-display expression " , 2 ) ) ;
2011-10-22 09:30:52 +08:00
if ( display_regex_cmd_ap . get ( ) )
{
if ( display_regex_cmd_ap - > AddRegexCommand ( " ^(.+)$ " , " target stop-hook add -o \" expr -- %1 \" " ) )
{
CommandObjectSP display_regex_cmd_sp ( display_regex_cmd_ap . release ( ) ) ;
m_command_dict [ display_regex_cmd_sp - > GetCommandName ( ) ] = display_regex_cmd_sp ;
}
}
2013-04-19 06:45:39 +08:00
std : : unique_ptr < CommandObjectRegexCommand >
2011-10-22 09:30:52 +08:00
undisplay_regex_cmd_ap ( new CommandObjectRegexCommand ( * this ,
2013-03-30 01:03:23 +08:00
" _regexp-undisplay " ,
" Remove an expression evaluation stop-hook. " ,
" _regexp-undisplay stop-hook-number " , 2 ) ) ;
2011-10-22 09:30:52 +08:00
if ( undisplay_regex_cmd_ap . get ( ) )
{
if ( undisplay_regex_cmd_ap - > AddRegexCommand ( " ^([0-9]+)$ " , " target stop-hook delete %1 " ) )
{
CommandObjectSP undisplay_regex_cmd_sp ( undisplay_regex_cmd_ap . release ( ) ) ;
m_command_dict [ undisplay_regex_cmd_sp - > GetCommandName ( ) ] = undisplay_regex_cmd_sp ;
}
}
2013-04-19 06:45:39 +08:00
std : : unique_ptr < CommandObjectRegexCommand >
2012-09-27 06:26:47 +08:00
connect_gdb_remote_cmd_ap ( new CommandObjectRegexCommand ( * this ,
2013-03-30 01:03:23 +08:00
" gdb-remote " ,
" Connect to a remote GDB server. If no hostname is provided, localhost is assumed. " ,
" gdb-remote [<hostname>:]<portnum> " , 2 ) ) ;
2012-09-27 06:26:47 +08:00
if ( connect_gdb_remote_cmd_ap . get ( ) )
{
if ( connect_gdb_remote_cmd_ap - > AddRegexCommand ( " ^([^:]+:[[:digit:]]+)$ " , " process connect --plugin gdb-remote connect://%1 " ) & &
connect_gdb_remote_cmd_ap - > AddRegexCommand ( " ^([[:digit:]]+)$ " , " process connect --plugin gdb-remote connect://localhost:%1 " ) )
{
CommandObjectSP command_sp ( connect_gdb_remote_cmd_ap . release ( ) ) ;
m_command_dict [ command_sp - > GetCommandName ( ) ] = command_sp ;
}
}
2013-04-19 06:45:39 +08:00
std : : unique_ptr < CommandObjectRegexCommand >
2012-09-27 06:26:47 +08:00
connect_kdp_remote_cmd_ap ( new CommandObjectRegexCommand ( * this ,
" kdp-remote " ,
2012-10-23 11:05:16 +08:00
" Connect to a remote KDP server. udp port 41139 is the default port number. " ,
" kdp-remote <hostname>[:<portnum>] " , 2 ) ) ;
2012-09-27 06:26:47 +08:00
if ( connect_kdp_remote_cmd_ap . get ( ) )
{
if ( connect_kdp_remote_cmd_ap - > AddRegexCommand ( " ^([^:]+:[[:digit:]]+)$ " , " process connect --plugin kdp-remote udp://%1 " ) & &
2012-09-27 10:47:55 +08:00
connect_kdp_remote_cmd_ap - > AddRegexCommand ( " ^(.+)$ " , " process connect --plugin kdp-remote udp://%1:41139 " ) )
2012-09-27 06:26:47 +08:00
{
CommandObjectSP command_sp ( connect_kdp_remote_cmd_ap . release ( ) ) ;
m_command_dict [ command_sp - > GetCommandName ( ) ] = command_sp ;
}
}
2013-04-19 06:45:39 +08:00
std : : unique_ptr < CommandObjectRegexCommand >
2012-10-05 13:29:32 +08:00
bt_regex_cmd_ap ( new CommandObjectRegexCommand ( * this ,
2012-10-11 00:51:31 +08:00
" _regexp-bt " ,
2012-10-05 13:29:32 +08:00
" 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. " ,
" bt [<digit>|all] " , 2 ) ) ;
if ( bt_regex_cmd_ap . get ( ) )
{
// accept but don't document "bt -c <number>" -- before bt was a regex command if you wanted to backtrace
// three frames you would do "bt -c 3" but the intention is to have this emulate the gdb "bt" command and
// so now "bt 3" is the preferred form, in line with gdb.
if ( bt_regex_cmd_ap - > AddRegexCommand ( " ^([[:digit:]]+)$ " , " thread backtrace -c %1 " ) & &
bt_regex_cmd_ap - > AddRegexCommand ( " ^-c ([[:digit:]]+)$ " , " thread backtrace -c %1 " ) & &
bt_regex_cmd_ap - > AddRegexCommand ( " ^all$ " , " thread backtrace all " ) & &
bt_regex_cmd_ap - > AddRegexCommand ( " ^$ " , " thread backtrace " ) )
{
CommandObjectSP command_sp ( bt_regex_cmd_ap . release ( ) ) ;
m_command_dict [ command_sp - > GetCommandName ( ) ] = command_sp ;
}
}
2013-04-19 06:45:39 +08:00
std : : unique_ptr < CommandObjectRegexCommand >
2013-02-02 07:33:03 +08:00
list_regex_cmd_ap ( new CommandObjectRegexCommand ( * this ,
" _regexp-list " ,
" Implements the GDB 'list' command in all of its forms except FILE:FUNCTION and maps them to the appropriate 'source list' commands. " ,
2013-09-27 04:00:01 +08:00
" _regexp-list [<line>] \n _regexp-list [<file>:<line>] \n _regexp-list [<file>:<line>] " ,
2013-03-30 01:03:23 +08:00
2 ,
CommandCompletions : : eSourceFileCompletion ) ) ;
2013-02-02 07:33:03 +08:00
if ( list_regex_cmd_ap . get ( ) )
{
if ( list_regex_cmd_ap - > AddRegexCommand ( " ^([0-9]+)[[:space:]]*$ " , " source list --line %1 " ) & &
list_regex_cmd_ap - > AddRegexCommand ( " ^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$ " , " source list --file '%1' --line %2 " ) & &
list_regex_cmd_ap - > AddRegexCommand ( " ^ \\ *?(0x[[:xdigit:]]+)[[:space:]]*$ " , " source list --address %1 " ) & &
2013-02-13 02:42:05 +08:00
list_regex_cmd_ap - > AddRegexCommand ( " ^-[[:space:]]*$ " , " source list --reverse " ) & &
2013-03-14 02:25:49 +08:00
list_regex_cmd_ap - > AddRegexCommand ( " ^-([[:digit:]]+)[[:space:]]*$ " , " source list --reverse --count %1 " ) & &
2013-02-02 07:33:03 +08:00
list_regex_cmd_ap - > AddRegexCommand ( " ^(.+)$ " , " source list --name \" %1 \" " ) & &
list_regex_cmd_ap - > AddRegexCommand ( " ^$ " , " source list " ) )
{
CommandObjectSP list_regex_cmd_sp ( list_regex_cmd_ap . release ( ) ) ;
m_command_dict [ list_regex_cmd_sp - > GetCommandName ( ) ] = list_regex_cmd_sp ;
}
}
2013-04-19 06:45:39 +08:00
std : : unique_ptr < CommandObjectRegexCommand >
2013-02-13 02:52:24 +08:00
env_regex_cmd_ap ( new CommandObjectRegexCommand ( * this ,
2013-03-30 01:03:23 +08:00
" _regexp-env " ,
" Implements a shortcut to viewing and setting environment variables. " ,
" _regexp-env \n _regexp-env FOO=BAR " , 2 ) ) ;
2013-02-13 02:52:24 +08:00
if ( env_regex_cmd_ap . get ( ) )
{
if ( env_regex_cmd_ap - > AddRegexCommand ( " ^$ " , " settings show target.env-vars " ) & &
env_regex_cmd_ap - > AddRegexCommand ( " ^([A-Za-z_][A-Za-z_0-9]*=.*)$ " , " settings set target.env-vars %1 " ) )
{
CommandObjectSP env_regex_cmd_sp ( env_regex_cmd_ap . release ( ) ) ;
m_command_dict [ env_regex_cmd_sp - > GetCommandName ( ) ] = env_regex_cmd_sp ;
}
}
2013-09-12 10:20:34 +08:00
std : : unique_ptr < CommandObjectRegexCommand >
jump_regex_cmd_ap ( new CommandObjectRegexCommand ( * this ,
" _regexp-jump " ,
" Sets the program counter to a new address. " ,
" _regexp-jump [<line>] \n "
" _regexp-jump [<+-lineoffset>] \n "
" _regexp-jump [<file>:<line>] \n "
" _regexp-jump [*<addr>] \n " , 2 ) ) ;
if ( jump_regex_cmd_ap . get ( ) )
{
if ( jump_regex_cmd_ap - > AddRegexCommand ( " ^ \\ *(.*)$ " , " thread jump --addr %1 " ) & &
jump_regex_cmd_ap - > AddRegexCommand ( " ^([0-9]+)$ " , " thread jump --line %1 " ) & &
jump_regex_cmd_ap - > AddRegexCommand ( " ^([^:]+):([0-9]+)$ " , " thread jump --file %1 --line %2 " ) & &
jump_regex_cmd_ap - > AddRegexCommand ( " ^([+ \\ -][0-9]+)$ " , " thread jump --by %1 " ) )
{
CommandObjectSP jump_regex_cmd_sp ( jump_regex_cmd_ap . release ( ) ) ;
m_command_dict [ jump_regex_cmd_sp - > GetCommandName ( ) ] = jump_regex_cmd_sp ;
}
}
2010-06-09 00:52:24 +08:00
}
int
CommandInterpreter : : GetCommandNamesMatchingPartialString ( const char * cmd_str , bool include_aliases ,
StringList & matches )
{
CommandObject : : AddNamesMatchingPartialString ( m_command_dict , cmd_str , matches ) ;
if ( include_aliases )
{
CommandObject : : AddNamesMatchingPartialString ( m_alias_dict , cmd_str , matches ) ;
}
return matches . GetSize ( ) ;
}
CommandObjectSP
CommandInterpreter : : GetCommandSP ( const char * cmd_cstr , bool include_aliases , bool exact , StringList * matches )
{
CommandObject : : CommandMap : : iterator pos ;
2013-01-26 02:06:21 +08:00
CommandObjectSP command_sp ;
2010-06-09 00:52:24 +08:00
std : : string cmd ( cmd_cstr ) ;
if ( HasCommands ( ) )
{
pos = m_command_dict . find ( cmd ) ;
if ( pos ! = m_command_dict . end ( ) )
2013-01-26 02:06:21 +08:00
command_sp = pos - > second ;
2010-06-09 00:52:24 +08:00
}
if ( include_aliases & & HasAliases ( ) )
{
pos = m_alias_dict . find ( cmd ) ;
if ( pos ! = m_alias_dict . end ( ) )
2013-01-26 02:06:21 +08:00
command_sp = pos - > second ;
2010-06-09 00:52:24 +08:00
}
if ( HasUserCommands ( ) )
{
pos = m_user_dict . find ( cmd ) ;
if ( pos ! = m_user_dict . end ( ) )
2013-01-26 02:06:21 +08:00
command_sp = pos - > second ;
2010-06-09 00:52:24 +08:00
}
2013-01-26 02:06:21 +08:00
if ( ! exact & & ! command_sp )
2010-06-09 00:52:24 +08:00
{
2010-07-07 06:46:59 +08:00
// We will only get into here if we didn't find any exact matches.
CommandObjectSP user_match_sp , alias_match_sp , real_match_sp ;
2010-06-09 00:52:24 +08:00
StringList local_matches ;
if ( matches = = NULL )
matches = & local_matches ;
2010-07-07 06:46:59 +08:00
unsigned int num_cmd_matches = 0 ;
unsigned int num_alias_matches = 0 ;
unsigned int num_user_matches = 0 ;
// Look through the command dictionaries one by one, and if we get only one match from any of
// them in toto, then return that, otherwise return an empty CommandObjectSP and the list of matches.
2010-06-09 00:52:24 +08:00
if ( HasCommands ( ) )
{
num_cmd_matches = CommandObject : : AddNamesMatchingPartialString ( m_command_dict , cmd_cstr , * matches ) ;
}
if ( num_cmd_matches = = 1 )
{
cmd . assign ( matches - > GetStringAtIndex ( 0 ) ) ;
pos = m_command_dict . find ( cmd ) ;
if ( pos ! = m_command_dict . end ( ) )
2010-07-07 06:46:59 +08:00
real_match_sp = pos - > second ;
2010-06-09 00:52:24 +08:00
}
2010-06-25 04:28:42 +08:00
if ( include_aliases & & HasAliases ( ) )
2010-06-09 00:52:24 +08:00
{
num_alias_matches = CommandObject : : AddNamesMatchingPartialString ( m_alias_dict , cmd_cstr , * matches ) ;
}
2010-07-07 06:46:59 +08:00
if ( num_alias_matches = = 1 )
2010-06-09 00:52:24 +08:00
{
cmd . assign ( matches - > GetStringAtIndex ( num_cmd_matches ) ) ;
pos = m_alias_dict . find ( cmd ) ;
if ( pos ! = m_alias_dict . end ( ) )
2010-07-07 06:46:59 +08:00
alias_match_sp = pos - > second ;
2010-06-09 00:52:24 +08:00
}
2010-06-25 04:28:42 +08:00
if ( HasUserCommands ( ) )
2010-06-09 00:52:24 +08:00
{
num_user_matches = CommandObject : : AddNamesMatchingPartialString ( m_user_dict , cmd_cstr , * matches ) ;
}
2010-07-07 06:46:59 +08:00
if ( num_user_matches = = 1 )
2010-06-09 00:52:24 +08:00
{
cmd . assign ( matches - > GetStringAtIndex ( num_cmd_matches + num_alias_matches ) ) ;
pos = m_user_dict . find ( cmd ) ;
if ( pos ! = m_user_dict . end ( ) )
2010-07-07 06:46:59 +08:00
user_match_sp = pos - > second ;
}
// If we got exactly one match, return that, otherwise return the match list.
if ( num_user_matches + num_cmd_matches + num_alias_matches = = 1 )
{
if ( num_cmd_matches )
return real_match_sp ;
else if ( num_alias_matches )
return alias_match_sp ;
else
return user_match_sp ;
2010-06-09 00:52:24 +08:00
}
}
2013-01-26 02:06:21 +08:00
else if ( matches & & command_sp )
2010-07-07 06:46:59 +08:00
{
matches - > AppendString ( cmd_cstr ) ;
2010-06-09 00:52:24 +08:00
}
2013-01-26 02:06:21 +08:00
return command_sp ;
2010-06-09 00:52:24 +08:00
}
2011-04-21 00:37:46 +08:00
bool
CommandInterpreter : : AddCommand ( const char * name , const lldb : : CommandObjectSP & cmd_sp , bool can_replace )
{
if ( name & & name [ 0 ] )
{
std : : string name_sstr ( name ) ;
2012-10-02 01:19:37 +08:00
bool found = ( m_command_dict . find ( name_sstr ) ! = m_command_dict . end ( ) ) ;
if ( found & & ! can_replace )
return false ;
if ( found & & m_command_dict [ name_sstr ] - > IsRemovable ( ) = = false )
2012-09-29 07:57:51 +08:00
return false ;
2011-04-21 00:37:46 +08:00
m_command_dict [ name_sstr ] = cmd_sp ;
return true ;
}
return false ;
}
2011-08-17 07:24:13 +08:00
bool
2011-11-08 06:57:04 +08:00
CommandInterpreter : : AddUserCommand ( std : : string name ,
2011-08-17 07:24:13 +08:00
const lldb : : CommandObjectSP & cmd_sp ,
bool can_replace )
{
2011-11-08 06:57:04 +08:00
if ( ! name . empty ( ) )
2011-08-17 07:24:13 +08:00
{
2011-11-08 06:57:04 +08:00
const char * name_cstr = name . c_str ( ) ;
// do not allow replacement of internal commands
if ( CommandExists ( name_cstr ) )
2012-09-29 07:57:51 +08:00
{
if ( can_replace = = false )
return false ;
if ( m_command_dict [ name ] - > IsRemovable ( ) = = false )
return false ;
}
if ( UserCommandExists ( name_cstr ) )
{
if ( can_replace = = false )
return false ;
if ( m_user_dict [ name ] - > IsRemovable ( ) = = false )
return false ;
}
2011-11-08 06:57:04 +08:00
m_user_dict [ name ] = cmd_sp ;
2011-08-17 07:24:13 +08:00
return true ;
}
return false ;
}
2011-04-21 00:37:46 +08:00
2010-07-07 06:46:59 +08:00
CommandObjectSP
CommandInterpreter : : GetCommandSPExact ( const char * cmd_cstr , bool include_aliases )
{
2010-12-15 02:51:39 +08:00
Args cmd_words ( cmd_cstr ) ; // Break up the command string into words, in case it's a multi-word command.
CommandObjectSP ret_val ; // Possibly empty return value.
if ( cmd_cstr = = NULL )
return ret_val ;
if ( cmd_words . GetArgumentCount ( ) = = 1 )
return GetCommandSP ( cmd_cstr , include_aliases , true , NULL ) ;
else
{
// We have a multi-word command (seemingly), so we need to do more work.
// First, get the cmd_obj_sp for the first word in the command.
CommandObjectSP cmd_obj_sp = GetCommandSP ( cmd_words . GetArgumentAtIndex ( 0 ) , include_aliases , true , NULL ) ;
if ( cmd_obj_sp . get ( ) ! = NULL )
{
// Loop through the rest of the words in the command (everything passed in was supposed to be part of a
// command name), and find the appropriate sub-command SP for each command word....
size_t end = cmd_words . GetArgumentCount ( ) ;
for ( size_t j = 1 ; j < end ; + + j )
{
if ( cmd_obj_sp - > IsMultiwordObject ( ) )
{
2012-10-13 10:07:45 +08:00
cmd_obj_sp = cmd_obj_sp - > GetSubcommandSP ( cmd_words . GetArgumentAtIndex ( j ) ) ;
2010-12-15 02:51:39 +08:00
if ( cmd_obj_sp . get ( ) = = NULL )
// The sub-command name was invalid. Fail and return the empty 'ret_val'.
return ret_val ;
}
else
// We have more words in the command name, but we don't have a multiword object. Fail and return
// empty 'ret_val'.
return ret_val ;
}
// We successfully looped through all the command words and got valid command objects for them. Assign the
// last object retrieved to 'ret_val'.
ret_val = cmd_obj_sp ;
}
}
return ret_val ;
2010-07-07 06:46:59 +08:00
}
2010-06-09 00:52:24 +08:00
CommandObject *
2010-07-07 06:46:59 +08:00
CommandInterpreter : : GetCommandObjectExact ( const char * cmd_cstr , bool include_aliases )
2010-06-09 00:52:24 +08:00
{
2010-07-07 06:46:59 +08:00
return GetCommandSPExact ( cmd_cstr , include_aliases ) . get ( ) ;
}
CommandObject *
CommandInterpreter : : GetCommandObject ( const char * cmd_cstr , StringList * matches )
{
CommandObject * command_obj = GetCommandSP ( cmd_cstr , false , true , matches ) . get ( ) ;
// If we didn't find an exact match to the command string in the commands, look in
// the aliases.
2013-06-19 02:01:08 +08:00
if ( command_obj )
return command_obj ;
2010-07-07 06:46:59 +08:00
2013-06-19 02:01:08 +08:00
command_obj = GetCommandSP ( cmd_cstr , true , true , matches ) . get ( ) ;
2010-07-07 06:46:59 +08:00
2013-06-19 02:01:08 +08:00
if ( command_obj )
return command_obj ;
// If there wasn't an exact match then look for an inexact one in just the commands
command_obj = GetCommandSP ( cmd_cstr , false , false , NULL ) . get ( ) ;
2013-04-24 00:17:32 +08:00
// Finally, if there wasn't an inexact match among the commands, look for an inexact
// match in both the commands and aliases.
2013-06-19 02:01:08 +08:00
if ( command_obj )
{
if ( matches )
matches - > AppendString ( command_obj - > GetCommandName ( ) ) ;
return command_obj ;
}
return GetCommandSP ( cmd_cstr , true , false , matches ) . get ( ) ;
2010-06-09 00:52:24 +08:00
}
bool
CommandInterpreter : : CommandExists ( const char * cmd )
{
return m_command_dict . find ( cmd ) ! = m_command_dict . end ( ) ;
}
2011-05-07 05:37:15 +08:00
bool
CommandInterpreter : : ProcessAliasOptionsArgs ( lldb : : CommandObjectSP & cmd_obj_sp ,
const char * options_args ,
OptionArgVectorSP & option_arg_vector_sp )
{
bool success = true ;
OptionArgVector * option_arg_vector = option_arg_vector_sp . get ( ) ;
if ( ! options_args | | ( strlen ( options_args ) < 1 ) )
return true ;
std : : string options_string ( options_args ) ;
Args args ( options_args ) ;
CommandReturnObject result ;
// Check to see if the command being aliased can take any command options.
Options * options = cmd_obj_sp - > GetOptions ( ) ;
if ( options )
{
// See if any options were specified as part of the alias; if so, handle them appropriately.
options - > NotifyOptionParsingStarting ( ) ;
args . Unshift ( " dummy_arg " ) ;
args . ParseAliasOptions ( * options , result , option_arg_vector , options_string ) ;
args . Shift ( ) ;
if ( result . Succeeded ( ) )
options - > VerifyPartialOptions ( result ) ;
if ( ! result . Succeeded ( ) & & result . GetStatus ( ) ! = lldb : : eReturnStatusStarted )
{
result . AppendError ( " Unable to create requested alias. \n " ) ;
return false ;
}
}
2011-10-29 05:38:01 +08:00
if ( ! options_string . empty ( ) )
2011-05-07 05:37:15 +08:00
{
if ( cmd_obj_sp - > WantsRawCommandString ( ) )
option_arg_vector - > push_back ( OptionArgPair ( " <argument> " ,
OptionArgValue ( - 1 ,
options_string ) ) ) ;
else
{
2013-01-26 02:06:21 +08:00
const size_t argc = args . GetArgumentCount ( ) ;
2011-05-07 05:37:15 +08:00
for ( size_t i = 0 ; i < argc ; + + i )
if ( strcmp ( args . GetArgumentAtIndex ( i ) , " " ) ! = 0 )
option_arg_vector - > push_back
( OptionArgPair ( " <argument> " ,
OptionArgValue ( - 1 ,
std : : string ( args . GetArgumentAtIndex ( i ) ) ) ) ) ;
}
}
return success ;
}
2013-04-03 08:25:49 +08:00
bool
CommandInterpreter : : GetAliasFullName ( const char * cmd , std : : string & full_name )
{
bool exact_match = ( m_alias_dict . find ( cmd ) ! = m_alias_dict . end ( ) ) ;
if ( exact_match )
{
full_name . assign ( cmd ) ;
return exact_match ;
}
else
{
StringList matches ;
size_t num_alias_matches ;
num_alias_matches = CommandObject : : AddNamesMatchingPartialString ( m_alias_dict , cmd , matches ) ;
if ( num_alias_matches = = 1 )
{
// Make sure this isn't shadowing a command in the regular command space:
StringList regular_matches ;
const bool include_aliases = false ;
const bool exact = false ;
CommandObjectSP cmd_obj_sp ( GetCommandSP ( cmd , include_aliases , exact , & regular_matches ) ) ;
if ( cmd_obj_sp | | regular_matches . GetSize ( ) > 0 )
return false ;
else
{
full_name . assign ( matches . GetStringAtIndex ( 0 ) ) ;
return true ;
}
}
else
return false ;
}
}
2010-06-09 00:52:24 +08:00
bool
CommandInterpreter : : AliasExists ( const char * cmd )
{
return m_alias_dict . find ( cmd ) ! = m_alias_dict . end ( ) ;
}
bool
CommandInterpreter : : UserCommandExists ( const char * cmd )
{
return m_user_dict . find ( cmd ) ! = m_user_dict . end ( ) ;
}
void
CommandInterpreter : : AddAlias ( const char * alias_name , CommandObjectSP & command_obj_sp )
{
2010-07-07 06:46:59 +08:00
command_obj_sp - > SetIsAlias ( true ) ;
2010-06-09 00:52:24 +08:00
m_alias_dict [ alias_name ] = command_obj_sp ;
}
bool
CommandInterpreter : : RemoveAlias ( const char * alias_name )
{
CommandObject : : CommandMap : : iterator pos = m_alias_dict . find ( alias_name ) ;
if ( pos ! = m_alias_dict . end ( ) )
{
m_alias_dict . erase ( pos ) ;
return true ;
}
return false ;
}
bool
CommandInterpreter : : RemoveUser ( const char * alias_name )
{
CommandObject : : CommandMap : : iterator pos = m_user_dict . find ( alias_name ) ;
if ( pos ! = m_user_dict . end ( ) )
{
m_user_dict . erase ( pos ) ;
return true ;
}
return false ;
}
void
CommandInterpreter : : GetAliasHelp ( const char * alias_name , const char * command_name , StreamString & help_string )
{
help_string . Printf ( " '%s " , command_name ) ;
OptionArgVectorSP option_arg_vector_sp = GetAliasOptions ( alias_name ) ;
2012-08-09 08:50:26 +08:00
if ( option_arg_vector_sp )
2010-06-09 00:52:24 +08:00
{
OptionArgVector * options = option_arg_vector_sp . get ( ) ;
2013-06-20 03:04:53 +08:00
for ( size_t i = 0 ; i < options - > size ( ) ; + + i )
2010-06-09 00:52:24 +08:00
{
OptionArgPair cur_option = ( * options ) [ i ] ;
std : : string opt = cur_option . first ;
2010-12-08 03:58:26 +08:00
OptionArgValue value_pair = cur_option . second ;
std : : string value = value_pair . second ;
2010-06-09 00:52:24 +08:00
if ( opt . compare ( " <argument> " ) = = 0 )
{
help_string . Printf ( " %s " , value . c_str ( ) ) ;
}
else
{
help_string . Printf ( " %s " , opt . c_str ( ) ) ;
if ( ( value . compare ( " <no-argument> " ) ! = 0 )
& & ( value . compare ( " <need-argument " ) ! = 0 ) )
{
help_string . Printf ( " %s " , value . c_str ( ) ) ;
}
}
}
}
help_string . Printf ( " ' " ) ;
}
2010-08-27 06:05:43 +08:00
size_t
2010-06-09 00:52:24 +08:00
CommandInterpreter : : FindLongestCommandWord ( CommandObject : : CommandMap & dict )
{
CommandObject : : CommandMap : : const_iterator pos ;
2010-08-27 06:05:43 +08:00
CommandObject : : CommandMap : : const_iterator end = dict . end ( ) ;
size_t max_len = 0 ;
2010-06-09 00:52:24 +08:00
2010-08-27 06:05:43 +08:00
for ( pos = dict . begin ( ) ; pos ! = end ; + + pos )
{
size_t len = pos - > first . size ( ) ;
if ( max_len < len )
max_len = len ;
}
return max_len ;
2010-06-09 00:52:24 +08:00
}
void
2011-08-17 07:24:13 +08:00
CommandInterpreter : : GetHelp ( CommandReturnObject & result ,
2011-09-10 01:49:36 +08:00
uint32_t cmd_types )
2010-06-09 00:52:24 +08:00
{
CommandObject : : CommandMap : : const_iterator pos ;
2013-01-26 02:06:21 +08:00
size_t max_len = FindLongestCommandWord ( m_command_dict ) ;
2011-08-17 07:24:13 +08:00
if ( ( cmd_types & eCommandTypesBuiltin ) = = eCommandTypesBuiltin )
2010-06-09 00:52:24 +08:00
{
2011-08-17 07:24:13 +08:00
result . AppendMessage ( " The following is a list of built-in, permanent debugger commands: " ) ;
result . AppendMessage ( " " ) ;
for ( pos = m_command_dict . begin ( ) ; pos ! = m_command_dict . end ( ) ; + + pos )
{
OutputFormattedHelpText ( result . GetOutputStream ( ) , pos - > first . c_str ( ) , " -- " , pos - > second - > GetHelp ( ) ,
max_len ) ;
}
result . AppendMessage ( " " ) ;
2010-06-09 00:52:24 +08:00
}
2011-10-29 05:38:01 +08:00
if ( ! m_alias_dict . empty ( ) & & ( ( cmd_types & eCommandTypesAliases ) = = eCommandTypesAliases ) )
2010-06-09 00:52:24 +08:00
{
2010-10-23 02:47:16 +08:00
result . AppendMessage ( " The following is a list of your current command abbreviations "
2011-04-21 08:39:18 +08:00
" (see 'help command alias' for more info): " ) ;
2010-06-09 00:52:24 +08:00
result . AppendMessage ( " " ) ;
2010-08-27 06:05:43 +08:00
max_len = FindLongestCommandWord ( m_alias_dict ) ;
2010-06-09 00:52:24 +08:00
for ( pos = m_alias_dict . begin ( ) ; pos ! = m_alias_dict . end ( ) ; + + pos )
{
StreamString sstr ;
StreamString translation_and_help ;
std : : string entry_name = pos - > first ;
std : : string second_entry = pos - > second . get ( ) - > GetCommandName ( ) ;
GetAliasHelp ( pos - > first . c_str ( ) , pos - > second - > GetCommandName ( ) , sstr ) ;
translation_and_help . Printf ( " (%s) %s " , sstr . GetData ( ) , pos - > second - > GetHelp ( ) ) ;
OutputFormattedHelpText ( result . GetOutputStream ( ) , pos - > first . c_str ( ) , " -- " ,
translation_and_help . GetData ( ) , max_len ) ;
}
result . AppendMessage ( " " ) ;
}
2011-10-29 05:38:01 +08:00
if ( ! m_user_dict . empty ( ) & & ( ( cmd_types & eCommandTypesUserDef ) = = eCommandTypesUserDef ) )
2010-06-09 00:52:24 +08:00
{
result . AppendMessage ( " The following is a list of your current user-defined commands: " ) ;
result . AppendMessage ( " " ) ;
2011-08-17 07:24:13 +08:00
max_len = FindLongestCommandWord ( m_user_dict ) ;
2010-06-09 00:52:24 +08:00
for ( pos = m_user_dict . begin ( ) ; pos ! = m_user_dict . end ( ) ; + + pos )
{
2011-08-17 07:24:13 +08:00
OutputFormattedHelpText ( result . GetOutputStream ( ) , pos - > first . c_str ( ) , " -- " , pos - > second - > GetHelp ( ) ,
max_len ) ;
2010-06-09 00:52:24 +08:00
}
result . AppendMessage ( " " ) ;
}
result . AppendMessage ( " For more information on any particular command, try 'help <command-name>'. " ) ;
}
2010-12-10 06:52:49 +08:00
CommandObject *
CommandInterpreter : : GetCommandObjectForCommand ( std : : string & command_string )
{
// This function finds the final, lowest-level, alias-resolved command object whose 'Execute' function will
// eventually be invoked by the given command line.
CommandObject * cmd_obj = NULL ;
std : : string white_space ( " \t \v " ) ;
size_t start = command_string . find_first_not_of ( white_space ) ;
size_t end = 0 ;
bool done = false ;
while ( ! done )
{
if ( start ! = std : : string : : npos )
{
// Get the next word from command_string.
end = command_string . find_first_of ( white_space , start ) ;
if ( end = = std : : string : : npos )
end = command_string . size ( ) ;
std : : string cmd_word = command_string . substr ( start , end - start ) ;
if ( cmd_obj = = NULL )
// Since cmd_obj is NULL we are on our first time through this loop. Check to see if cmd_word is a valid
// command or alias.
cmd_obj = GetCommandObject ( cmd_word . c_str ( ) ) ;
else if ( cmd_obj - > IsMultiwordObject ( ) )
{
// Our current object is a multi-word object; see if the cmd_word is a valid sub-command for our object.
2012-10-13 10:07:45 +08:00
CommandObject * sub_cmd_obj = cmd_obj - > GetSubcommandObject ( cmd_word . c_str ( ) ) ;
2010-12-10 06:52:49 +08:00
if ( sub_cmd_obj )
cmd_obj = sub_cmd_obj ;
else // cmd_word was not a valid sub-command word, so we are donee
done = true ;
}
else
// We have a cmd_obj and it is not a multi-word object, so we are done.
done = true ;
// If we didn't find a valid command object, or our command object is not a multi-word object, or
// we are at the end of the command_string, then we are done. Otherwise, find the start of the
// next word.
if ( ! cmd_obj | | ! cmd_obj - > IsMultiwordObject ( ) | | end > = command_string . size ( ) )
done = true ;
else
start = command_string . find_first_not_of ( white_space , end ) ;
}
else
// Unable to find any more words.
done = true ;
}
if ( end = = command_string . size ( ) )
command_string . clear ( ) ;
else
command_string = command_string . substr ( end ) ;
return cmd_obj ;
}
2011-10-25 08:36:27 +08:00
static const char * k_white_space = " \t \v " ;
2011-10-29 05:38:01 +08:00
static const char * k_valid_command_chars = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_ " ;
2011-10-25 08:36:27 +08:00
static void
StripLeadingSpaces ( std : : string & s )
2010-06-09 00:52:24 +08:00
{
2011-10-25 08:36:27 +08:00
if ( ! s . empty ( ) )
{
size_t pos = s . find_first_not_of ( k_white_space ) ;
if ( pos = = std : : string : : npos )
s . clear ( ) ;
else if ( pos = = 0 )
return ;
s . erase ( 0 , pos ) ;
}
}
2011-11-10 07:25:03 +08:00
static size_t
FindArgumentTerminator ( const std : : string & s )
{
const size_t s_len = s . size ( ) ;
size_t offset = 0 ;
while ( offset < s_len )
{
size_t pos = s . find ( " -- " , offset ) ;
if ( pos = = std : : string : : npos )
break ;
if ( pos > 0 )
{
if ( isspace ( s [ pos - 1 ] ) )
{
// Check if the string ends "\s--" (where \s is a space character)
// or if we have "\s--\s".
if ( ( pos + 2 > = s_len ) | | isspace ( s [ pos + 2 ] ) )
{
return pos ;
}
}
}
offset = pos + 2 ;
}
return std : : string : : npos ;
}
2011-10-25 08:36:27 +08:00
static bool
2011-10-29 05:38:01 +08:00
ExtractCommand ( std : : string & command_string , std : : string & command , std : : string & suffix , char & quote_char )
2011-10-25 08:36:27 +08:00
{
2011-10-29 05:38:01 +08:00
command . clear ( ) ;
suffix . clear ( ) ;
2011-10-25 08:36:27 +08:00
StripLeadingSpaces ( command_string ) ;
bool result = false ;
quote_char = ' \0 ' ;
2010-12-10 06:52:49 +08:00
2011-10-25 08:36:27 +08:00
if ( ! command_string . empty ( ) )
2010-12-10 06:52:49 +08:00
{
2011-10-25 08:36:27 +08:00
const char first_char = command_string [ 0 ] ;
if ( first_char = = ' \' ' | | first_char = = ' " ' )
2010-12-10 06:52:49 +08:00
{
2011-10-25 08:36:27 +08:00
quote_char = first_char ;
const size_t end_quote_pos = command_string . find ( quote_char , 1 ) ;
if ( end_quote_pos = = std : : string : : npos )
2011-05-12 00:07:06 +08:00
{
2011-10-29 05:38:01 +08:00
command . swap ( command_string ) ;
2011-10-25 08:36:27 +08:00
command_string . erase ( ) ;
2011-05-12 00:07:06 +08:00
}
else
{
2011-10-29 05:38:01 +08:00
command . assign ( command_string , 1 , end_quote_pos - 1 ) ;
2011-10-25 08:36:27 +08:00
if ( end_quote_pos + 1 < command_string . size ( ) )
command_string . erase ( 0 , command_string . find_first_not_of ( k_white_space , end_quote_pos + 1 ) ) ;
else
command_string . erase ( ) ;
2011-05-12 00:07:06 +08:00
}
2010-12-10 06:52:49 +08:00
}
else
{
2011-10-25 08:36:27 +08:00
const size_t first_space_pos = command_string . find_first_of ( k_white_space ) ;
if ( first_space_pos = = std : : string : : npos )
2011-05-12 00:07:06 +08:00
{
2011-10-29 05:38:01 +08:00
command . swap ( command_string ) ;
2011-10-25 08:36:27 +08:00
command_string . erase ( ) ;
2011-05-12 00:07:06 +08:00
}
else
{
2011-10-29 05:38:01 +08:00
command . assign ( command_string , 0 , first_space_pos ) ;
command_string . erase ( 0 , command_string . find_first_not_of ( k_white_space , first_space_pos ) ) ;
2011-05-12 00:07:06 +08:00
}
2010-12-10 06:52:49 +08:00
}
2011-10-25 08:36:27 +08:00
result = true ;
2010-12-10 06:52:49 +08:00
}
2011-10-29 05:38:01 +08:00
if ( ! command . empty ( ) )
{
// actual commands can't start with '-' or '_'
if ( command [ 0 ] ! = ' - ' & & command [ 0 ] ! = ' _ ' )
{
size_t pos = command . find_first_not_of ( k_valid_command_chars ) ;
if ( pos > 0 & & pos ! = std : : string : : npos )
{
suffix . assign ( command . begin ( ) + pos , command . end ( ) ) ;
command . erase ( pos ) ;
}
}
}
2011-10-25 08:36:27 +08:00
return result ;
2010-12-10 06:52:49 +08:00
}
2011-10-29 05:38:01 +08:00
CommandObject *
CommandInterpreter : : BuildAliasResult ( const char * alias_name ,
std : : string & raw_input_string ,
std : : string & alias_result ,
CommandReturnObject & result )
2010-12-10 06:52:49 +08:00
{
2011-10-29 05:38:01 +08:00
CommandObject * alias_cmd_obj = NULL ;
2010-12-10 06:52:49 +08:00
Args cmd_args ( raw_input_string . c_str ( ) ) ;
alias_cmd_obj = GetCommandObject ( alias_name ) ;
StreamString result_str ;
if ( alias_cmd_obj )
{
std : : string alias_name_str = alias_name ;
if ( ( cmd_args . GetArgumentCount ( ) = = 0 )
| | ( alias_name_str . compare ( cmd_args . GetArgumentAtIndex ( 0 ) ) ! = 0 ) )
cmd_args . Unshift ( alias_name ) ;
result_str . Printf ( " %s " , alias_cmd_obj - > GetCommandName ( ) ) ;
OptionArgVectorSP option_arg_vector_sp = GetAliasOptions ( alias_name ) ;
2010-06-09 00:52:24 +08:00
2010-12-10 06:52:49 +08:00
if ( option_arg_vector_sp . get ( ) )
{
OptionArgVector * option_arg_vector = option_arg_vector_sp . get ( ) ;
2013-06-20 03:04:53 +08:00
for ( size_t i = 0 ; i < option_arg_vector - > size ( ) ; + + i )
2010-12-10 06:52:49 +08:00
{
OptionArgPair option_pair = ( * option_arg_vector ) [ i ] ;
OptionArgValue value_pair = option_pair . second ;
int value_type = value_pair . first ;
std : : string option = option_pair . first ;
std : : string value = value_pair . second ;
if ( option . compare ( " <argument> " ) = = 0 )
result_str . Printf ( " %s " , value . c_str ( ) ) ;
else
{
result_str . Printf ( " %s " , option . c_str ( ) ) ;
2013-09-06 00:42:23 +08:00
if ( value_type ! = OptionParser : : eOptionalArgument )
2010-12-10 06:52:49 +08:00
result_str . Printf ( " " ) ;
2013-09-06 00:42:23 +08:00
if ( value . compare ( " <OptionParser::eNoArgument> " ) ! = 0 )
2010-12-10 06:52:49 +08:00
{
int index = GetOptionArgumentPosition ( value . c_str ( ) ) ;
if ( index = = 0 )
result_str . Printf ( " %s " , value . c_str ( ) ) ;
else if ( index > = cmd_args . GetArgumentCount ( ) )
{
result . AppendErrorWithFormat
( " Not enough arguments provided; you need at least %d arguments to use this alias. \n " ,
index ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2011-10-29 05:38:01 +08:00
return alias_cmd_obj ;
2010-12-10 06:52:49 +08:00
}
else
{
size_t strpos = raw_input_string . find ( cmd_args . GetArgumentAtIndex ( index ) ) ;
if ( strpos ! = std : : string : : npos )
raw_input_string = raw_input_string . erase ( strpos ,
strlen ( cmd_args . GetArgumentAtIndex ( index ) ) ) ;
result_str . Printf ( " %s " , cmd_args . GetArgumentAtIndex ( index ) ) ;
}
}
}
}
}
alias_result = result_str . GetData ( ) ;
}
2011-10-29 05:38:01 +08:00
return alias_cmd_obj ;
2010-12-10 06:52:49 +08:00
}
2011-10-14 15:41:33 +08:00
Error
CommandInterpreter : : PreprocessCommand ( std : : string & command )
{
// The command preprocessor needs to do things to the command
// line before any parsing of arguments or anything else is done.
// The only current stuff that gets proprocessed is anyting enclosed
// in backtick ('`') characters is evaluated as an expression and
// the result of the expression must be a scalar that can be substituted
// into the command. An example would be:
// (lldb) memory read `$rsp + 20`
Error error ; // Error for any expressions that might not evaluate
size_t start_backtick ;
size_t pos = 0 ;
while ( ( start_backtick = command . find ( ' ` ' , pos ) ) ! = std : : string : : npos )
{
if ( start_backtick > 0 & & command [ start_backtick - 1 ] = = ' \\ ' )
{
// The backtick was preceeded by a '\' character, remove the slash
// and don't treat the backtick as the start of an expression
command . erase ( start_backtick - 1 , 1 ) ;
// No need to add one to start_backtick since we just deleted a char
pos = start_backtick ;
}
else
{
const size_t expr_content_start = start_backtick + 1 ;
const size_t end_backtick = command . find ( ' ` ' , expr_content_start ) ;
if ( end_backtick = = std : : string : : npos )
return error ;
else if ( end_backtick = = expr_content_start )
{
// Empty expression (two backticks in a row)
command . erase ( start_backtick , 2 ) ;
}
else
{
std : : string expr_str ( command , expr_content_start , end_backtick - expr_content_start ) ;
2012-07-13 04:32:19 +08:00
ExecutionContext exe_ctx ( GetExecutionContext ( ) ) ;
Target * target = exe_ctx . GetTargetPtr ( ) ;
Get a dummy target to allow for calculator mode while processing backticks.
This also helps break the infinite loop caused when target is null.
So that we can have:
$ /Volumes/data/lldb/svn/trunk/build/Debug/lldb
(lldb) itob `0x123 - 0x321` 32 v
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0]
(lldb)
llvm-svn: 143260
2011-10-29 08:21:50 +08:00
// Get a dummy target to allow for calculator mode while processing backticks.
// This also helps break the infinite loop caused when target is null.
if ( ! target )
target = Host : : GetDummyTarget ( GetDebugger ( ) ) . get ( ) ;
2011-10-14 15:41:33 +08:00
if ( target )
{
ValueObjectSP expr_result_valobj_sp ;
2012-09-06 04:41:26 +08:00
2012-10-17 05:41:58 +08:00
EvaluateExpressionOptions options ;
2013-11-07 08:11:47 +08:00
options . SetCoerceToId ( false ) ;
options . SetUnwindOnError ( true ) ;
options . SetIgnoreBreakpoints ( true ) ;
options . SetKeepInMemory ( false ) ;
options . SetTryAllThreads ( true ) ;
options . SetTimeoutUsec ( 0 ) ;
2012-09-06 04:41:26 +08:00
2011-10-14 15:41:33 +08:00
ExecutionResults expr_result = target - > EvaluateExpression ( expr_str . c_str ( ) ,
2012-09-06 04:41:26 +08:00
exe_ctx . GetFramePtr ( ) ,
2012-07-17 07:10:35 +08:00
expr_result_valobj_sp ,
2012-09-06 04:41:26 +08:00
options ) ;
2011-10-14 15:41:33 +08:00
if ( expr_result = = eExecutionCompleted )
{
Scalar scalar ;
if ( expr_result_valobj_sp - > ResolveValue ( scalar ) )
{
command . erase ( start_backtick , end_backtick - start_backtick + 1 ) ;
StreamString value_strm ;
const bool show_type = false ;
scalar . GetValue ( & value_strm , show_type ) ;
size_t value_string_size = value_strm . GetSize ( ) ;
if ( value_string_size )
{
command . insert ( start_backtick , value_strm . GetData ( ) , value_string_size ) ;
pos = start_backtick + value_string_size ;
continue ;
}
else
{
error . SetErrorStringWithFormat ( " expression value didn't result in a scalar value for the expression '%s' " , expr_str . c_str ( ) ) ;
}
}
else
{
error . SetErrorStringWithFormat ( " expression value didn't result in a scalar value for the expression '%s' " , expr_str . c_str ( ) ) ;
}
}
else
{
if ( expr_result_valobj_sp )
error = expr_result_valobj_sp - > GetError ( ) ;
if ( error . Success ( ) )
{
switch ( expr_result )
{
case eExecutionSetupError :
error . SetErrorStringWithFormat ( " expression setup error for the expression '%s' " , expr_str . c_str ( ) ) ;
break ;
case eExecutionCompleted :
break ;
case eExecutionDiscarded :
error . SetErrorStringWithFormat ( " expression discarded for the expression '%s' " , expr_str . c_str ( ) ) ;
break ;
case eExecutionInterrupted :
error . SetErrorStringWithFormat ( " expression interrupted for the expression '%s' " , expr_str . c_str ( ) ) ;
break ;
2013-01-15 10:47:48 +08:00
case eExecutionHitBreakpoint :
error . SetErrorStringWithFormat ( " expression hit breakpoint for the expression '%s' " , expr_str . c_str ( ) ) ;
break ;
2011-10-14 15:41:33 +08:00
case eExecutionTimedOut :
error . SetErrorStringWithFormat ( " expression timed out for the expression '%s' " , expr_str . c_str ( ) ) ;
break ;
2013-11-09 07:38:26 +08:00
case eExecutionStoppedForDebug :
error . SetErrorStringWithFormat ( " expression stop at entry point for debugging for the expression '%s' " , expr_str . c_str ( ) ) ;
break ;
2011-10-14 15:41:33 +08:00
}
}
}
}
}
if ( error . Fail ( ) )
break ;
}
}
return error ;
}
2010-12-10 06:52:49 +08:00
bool
CommandInterpreter : : HandleCommand ( const char * command_line ,
2012-05-31 09:09:06 +08:00
LazyBool lazy_add_to_history ,
2010-12-10 06:52:49 +08:00
CommandReturnObject & result ,
2011-02-18 08:54:25 +08:00
ExecutionContext * override_context ,
2011-10-05 08:42:59 +08:00
bool repeat_on_empty_command ,
bool no_context_switching )
2011-02-18 08:54:25 +08:00
2010-12-10 06:52:49 +08:00
{
2011-02-18 08:54:25 +08:00
2010-12-10 06:52:49 +08:00
bool done = false ;
CommandObject * cmd_obj = NULL ;
bool wants_raw_input = false ;
std : : string command_string ( command_line ) ;
2011-07-12 11:12:18 +08:00
std : : string original_command_string ( command_line ) ;
2010-12-10 06:52:49 +08:00
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_COMMANDS ) ) ;
2010-11-10 12:57:04 +08:00
Host : : SetCrashDescriptionWithFormat ( " HandleCommand(command = \" %s \" ) " , command_line ) ;
// Make a scoped cleanup object that will clear the crash description string
// on exit of this function.
2011-07-12 08:18:11 +08:00
lldb_utility : : CleanUp < const char * > crash_description_cleanup ( NULL , Host : : SetCrashDescription ) ;
2010-11-10 12:57:04 +08:00
2010-12-10 06:52:49 +08:00
if ( log )
log - > Printf ( " Processing command: %s " , command_line ) ;
2010-06-09 00:52:24 +08:00
2010-11-05 07:08:45 +08:00
Timer scoped_timer ( __PRETTY_FUNCTION__ , " Handling command: %s. " , command_line ) ;
2011-10-05 08:42:59 +08:00
if ( ! no_context_switching )
UpdateExecutionContext ( override_context ) ;
2012-05-31 09:09:06 +08:00
bool add_to_history ;
if ( lazy_add_to_history = = eLazyBoolCalculate )
add_to_history = ( m_command_source_depth = = 0 ) ;
else
add_to_history = ( lazy_add_to_history = = eLazyBoolYes ) ;
2011-02-18 08:54:25 +08:00
bool empty_command = false ;
bool comment_command = false ;
if ( command_string . empty ( ) )
empty_command = true ;
else
2010-06-09 00:52:24 +08:00
{
2011-02-18 08:54:25 +08:00
const char * k_space_characters = " \t \n \v \f \r " ;
size_t non_space = command_string . find_first_not_of ( k_space_characters ) ;
// Check for empty line or comment line (lines whose first
// non-space character is the comment character for this interpreter)
if ( non_space = = std : : string : : npos )
empty_command = true ;
else if ( command_string [ non_space ] = = m_comment_char )
comment_command = true ;
2013-06-18 06:51:50 +08:00
else if ( command_string [ non_space ] = = CommandHistory : : g_repeat_char )
2011-07-12 11:12:18 +08:00
{
2013-06-18 06:51:50 +08:00
const char * history_string = m_command_history . FindString ( command_string . c_str ( ) + non_space ) ;
2011-07-12 11:12:18 +08:00
if ( history_string = = NULL )
{
result . AppendErrorWithFormat ( " Could not find entry: %s in history " , command_string . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
add_to_history = false ;
command_string = history_string ;
original_command_string = history_string ;
}
2011-02-18 08:54:25 +08:00
}
if ( empty_command )
{
if ( repeat_on_empty_command )
2010-06-09 00:52:24 +08:00
{
2013-06-18 06:51:50 +08:00
if ( m_command_history . IsEmpty ( ) )
2010-07-07 07:48:33 +08:00
{
2011-02-18 08:54:25 +08:00
result . AppendError ( " empty command " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2010-07-07 07:48:33 +08:00
return false ;
}
2011-02-18 08:54:25 +08:00
else
{
command_line = m_repeat_command . c_str ( ) ;
command_string = command_line ;
2011-07-12 11:12:18 +08:00
original_command_string = command_line ;
2011-02-18 08:54:25 +08:00
if ( m_repeat_command . empty ( ) )
{
result . AppendErrorWithFormat ( " No auto repeat. \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
add_to_history = false ;
}
else
{
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
return true ;
2010-06-09 00:52:24 +08:00
}
2011-02-18 08:54:25 +08:00
}
else if ( comment_command )
{
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
return true ;
2010-06-09 00:52:24 +08:00
}
2011-05-12 00:07:06 +08:00
2011-10-14 15:41:33 +08:00
Error error ( PreprocessCommand ( command_string ) ) ;
if ( error . Fail ( ) )
{
result . AppendError ( error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2010-12-10 06:52:49 +08:00
// Phase 1.
// Before we do ANY kind of argument processing, etc. we need to figure out what the real/final command object
// is for the specified command, and whether or not it wants raw input. This gets complicated by the fact that
// the user could have specified an alias, and in translating the alias there may also be command options and/or
// even data (including raw text strings) that need to be found and inserted into the command line as part of
// the translation. So this first step is plain look-up & replacement, resulting in three things: 1). the command
2011-01-09 04:28:42 +08:00
// object whose Execute method will actually be called; 2). a revised command string, with all substitutions &
2010-12-10 06:52:49 +08:00
// replacements taken care of; 3). whether or not the Execute function wants raw input or not.
StreamString revised_command_line ;
2010-12-11 16:16:56 +08:00
size_t actual_cmd_name_len = 0 ;
2011-10-29 05:38:01 +08:00
std : : string next_word ;
2012-05-17 07:25:54 +08:00
StringList matches ;
2010-12-10 06:52:49 +08:00
while ( ! done )
2010-06-09 00:52:24 +08:00
{
2011-05-12 00:07:06 +08:00
char quote_char = ' \0 ' ;
2011-10-29 05:38:01 +08:00
std : : string suffix ;
ExtractCommand ( command_string , next_word , suffix , quote_char ) ;
if ( cmd_obj = = NULL )
2010-12-10 06:52:49 +08:00
{
2013-04-03 08:25:49 +08:00
std : : string full_name ;
if ( GetAliasFullName ( next_word . c_str ( ) , full_name ) )
2010-06-09 00:52:24 +08:00
{
2011-10-29 05:38:01 +08:00
std : : string alias_result ;
2013-04-03 08:25:49 +08:00
cmd_obj = BuildAliasResult ( full_name . c_str ( ) , command_string , alias_result , result ) ;
2011-10-29 05:38:01 +08:00
revised_command_line . Printf ( " %s " , alias_result . c_str ( ) ) ;
if ( cmd_obj )
{
wants_raw_input = cmd_obj - > WantsRawCommandString ( ) ;
actual_cmd_name_len = strlen ( cmd_obj - > GetCommandName ( ) ) ;
}
2010-12-10 06:52:49 +08:00
}
else
{
2012-05-17 07:25:54 +08:00
cmd_obj = GetCommandObject ( next_word . c_str ( ) , & matches ) ;
2011-10-29 05:38:01 +08:00
if ( cmd_obj )
{
actual_cmd_name_len + = next_word . length ( ) ;
revised_command_line . Printf ( " %s " , next_word . c_str ( ) ) ;
wants_raw_input = cmd_obj - > WantsRawCommandString ( ) ;
}
else
{
revised_command_line . Printf ( " %s " , next_word . c_str ( ) ) ;
}
2010-12-10 06:52:49 +08:00
}
}
2011-10-29 05:38:01 +08:00
else
2010-12-10 06:52:49 +08:00
{
2011-10-29 05:38:01 +08:00
if ( cmd_obj - > IsMultiwordObject ( ) )
2010-12-10 06:52:49 +08:00
{
2012-10-13 10:07:45 +08:00
CommandObject * sub_cmd_obj = cmd_obj - > GetSubcommandObject ( next_word . c_str ( ) ) ;
2011-10-29 05:38:01 +08:00
if ( sub_cmd_obj )
{
actual_cmd_name_len + = next_word . length ( ) + 1 ;
revised_command_line . Printf ( " %s " , next_word . c_str ( ) ) ;
cmd_obj = sub_cmd_obj ;
wants_raw_input = cmd_obj - > WantsRawCommandString ( ) ;
}
else
{
if ( quote_char )
revised_command_line . Printf ( " %c%s%s%c " , quote_char , next_word . c_str ( ) , suffix . c_str ( ) , quote_char ) ;
else
revised_command_line . Printf ( " %s%s " , next_word . c_str ( ) , suffix . c_str ( ) ) ;
done = true ;
}
2010-12-10 06:52:49 +08:00
}
else
{
2011-10-25 08:36:27 +08:00
if ( quote_char )
2011-10-29 05:38:01 +08:00
revised_command_line . Printf ( " %c%s%s%c " , quote_char , next_word . c_str ( ) , suffix . c_str ( ) , quote_char ) ;
2011-05-12 00:07:06 +08:00
else
2011-10-29 05:38:01 +08:00
revised_command_line . Printf ( " %s%s " , next_word . c_str ( ) , suffix . c_str ( ) ) ;
2010-12-10 06:52:49 +08:00
done = true ;
}
}
if ( cmd_obj = = NULL )
{
2013-01-26 02:06:21 +08:00
const size_t num_matches = matches . GetSize ( ) ;
2012-05-17 07:25:54 +08:00
if ( matches . GetSize ( ) > 1 ) {
2013-01-26 02:06:21 +08:00
StreamString error_msg ;
error_msg . Printf ( " Ambiguous command '%s'. Possible matches: \n " , next_word . c_str ( ) ) ;
2012-05-17 07:25:54 +08:00
for ( uint32_t i = 0 ; i < num_matches ; + + i ) {
2013-01-26 02:06:21 +08:00
error_msg . Printf ( " \t %s \n " , matches . GetStringAtIndex ( i ) ) ;
2012-05-17 07:25:54 +08:00
}
2013-01-26 02:06:21 +08:00
result . AppendRawError ( error_msg . GetString ( ) . c_str ( ) ) ;
2012-05-17 07:25:54 +08:00
} else {
// We didn't have only one match, otherwise we wouldn't get here.
assert ( num_matches = = 0 ) ;
result . AppendErrorWithFormat ( " '%s' is not a valid command. \n " , next_word . c_str ( ) ) ;
}
2010-12-10 06:52:49 +08:00
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2011-10-29 05:38:01 +08:00
if ( cmd_obj - > IsMultiwordObject ( ) )
{
if ( ! suffix . empty ( ) )
{
2013-06-12 08:44:43 +08:00
result . AppendErrorWithFormat ( " command '%s' did not recognize '%s%s%s' as valid (subcommand might be invalid). \n " ,
cmd_obj - > GetCommandName ( ) ,
next_word . empty ( ) ? " " : next_word . c_str ( ) ,
next_word . empty ( ) ? " -- " : " " ,
2011-10-29 05:38:01 +08:00
suffix . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
else
{
// If we found a normal command, we are done
done = true ;
if ( ! suffix . empty ( ) )
{
switch ( suffix [ 0 ] )
{
case ' / ' :
// GDB format suffixes
2011-10-29 08:57:28 +08:00
{
Options * command_options = cmd_obj - > GetOptions ( ) ;
if ( command_options & & command_options - > SupportsLongOption ( " gdb-format " ) )
{
2011-11-10 07:25:03 +08:00
std : : string gdb_format_option ( " --gdb-format= " ) ;
gdb_format_option + = ( suffix . c_str ( ) + 1 ) ;
bool inserted = false ;
std : : string & cmd = revised_command_line . GetString ( ) ;
size_t arg_terminator_idx = FindArgumentTerminator ( cmd ) ;
if ( arg_terminator_idx ! = std : : string : : npos )
{
// Insert the gdb format option before the "--" that terminates options
gdb_format_option . append ( 1 , ' ' ) ;
cmd . insert ( arg_terminator_idx , gdb_format_option ) ;
inserted = true ;
}
if ( ! inserted )
revised_command_line . Printf ( " %s " , gdb_format_option . c_str ( ) ) ;
if ( wants_raw_input & & FindArgumentTerminator ( cmd ) = = std : : string : : npos )
revised_command_line . PutCString ( " -- " ) ;
2011-10-29 08:57:28 +08:00
}
else
{
result . AppendErrorWithFormat ( " the '%s' command doesn't support the --gdb-format option \n " ,
cmd_obj - > GetCommandName ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
2011-10-29 05:38:01 +08:00
break ;
2011-11-01 06:22:06 +08:00
default :
result . AppendErrorWithFormat ( " unknown command shorthand suffix: '%s' \n " ,
suffix . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2011-10-29 05:38:01 +08:00
}
}
}
2010-12-10 06:52:49 +08:00
if ( command_string . length ( ) = = 0 )
done = true ;
2010-12-08 03:58:26 +08:00
2010-12-10 06:52:49 +08:00
}
2010-06-09 00:52:24 +08:00
2011-10-29 05:38:01 +08:00
if ( ! command_string . empty ( ) )
2010-12-10 06:52:49 +08:00
revised_command_line . Printf ( " %s " , command_string . c_str ( ) ) ;
2010-07-07 07:48:33 +08:00
2010-12-10 06:52:49 +08:00
// End of Phase 1.
// At this point cmd_obj should contain the CommandObject whose Execute method will be called, if the command
// specified was valid; revised_command_line contains the complete command line (including command name(s)),
// fully translated with all substitutions & translations taken care of (still in raw text format); and
// wants_raw_input specifies whether the Execute method expects raw input or not.
2010-07-07 07:48:33 +08:00
2010-12-10 06:52:49 +08:00
if ( log )
{
log - > Printf ( " HandleCommand, cmd_obj : '%s' " , cmd_obj ? cmd_obj - > GetCommandName ( ) : " <not found> " ) ;
log - > Printf ( " HandleCommand, revised_command_line: '%s' " , revised_command_line . GetData ( ) ) ;
log - > Printf ( " HandleCommand, wants_raw_input:'%s' " , wants_raw_input ? " True " : " False " ) ;
}
2010-06-09 00:52:24 +08:00
2010-12-10 06:52:49 +08:00
// Phase 2.
// Take care of things like setting up the history command & calling the appropriate Execute method on the
// CommandObject, with the appropriate arguments.
if ( cmd_obj ! = NULL )
{
if ( add_to_history )
{
Args command_args ( revised_command_line . GetData ( ) ) ;
const char * repeat_command = cmd_obj - > GetRepeatCommand ( command_args , 0 ) ;
if ( repeat_command ! = NULL )
m_repeat_command . assign ( repeat_command ) ;
else
2011-07-12 11:12:18 +08:00
m_repeat_command . assign ( original_command_string . c_str ( ) ) ;
2010-12-10 06:52:49 +08:00
2013-06-18 06:51:50 +08:00
m_command_history . AppendString ( original_command_string ) ;
2010-12-10 06:52:49 +08:00
}
command_string = revised_command_line . GetData ( ) ;
std : : string command_name ( cmd_obj - > GetCommandName ( ) ) ;
2010-12-11 16:16:56 +08:00
std : : string remainder ;
if ( actual_cmd_name_len < command_string . length ( ) )
remainder = command_string . substr ( actual_cmd_name_len ) ; // Note: 'actual_cmd_name_len' may be considerably shorter
// than cmd_obj->GetCommandName(), because name completion
// allows users to enter short versions of the names,
// e.g. 'br s' for 'breakpoint set'.
2010-12-10 06:52:49 +08:00
// Remove any initial spaces
std : : string white_space ( " \t \v " ) ;
size_t pos = remainder . find_first_not_of ( white_space ) ;
if ( pos ! = 0 & & pos ! = std : : string : : npos )
2011-04-23 04:58:45 +08:00
remainder . erase ( 0 , pos ) ;
2010-12-10 06:52:49 +08:00
if ( log )
2011-08-25 08:20:04 +08:00
log - > Printf ( " HandleCommand, command line after removing command name(s): '%s' " , remainder . c_str ( ) ) ;
2010-12-10 06:52:49 +08:00
2012-06-09 05:56:10 +08:00
cmd_obj - > Execute ( remainder . c_str ( ) , result ) ;
2010-12-10 06:52:49 +08:00
}
else
{
// We didn't find the first command object, so complete the first argument.
Args command_args ( revised_command_line . GetData ( ) ) ;
StringList matches ;
int num_matches ;
int cursor_index = 0 ;
int cursor_char_position = strlen ( command_args . GetArgumentAtIndex ( 0 ) ) ;
bool word_complete ;
num_matches = HandleCompletionMatches ( command_args ,
cursor_index ,
cursor_char_position ,
0 ,
- 1 ,
word_complete ,
matches ) ;
if ( num_matches > 0 )
{
std : : string error_msg ;
error_msg . assign ( " ambiguous command ' " ) ;
error_msg . append ( command_args . GetArgumentAtIndex ( 0 ) ) ;
error_msg . append ( " '. " ) ;
error_msg . append ( " Possible completions: " ) ;
for ( int i = 0 ; i < num_matches ; i + + )
{
error_msg . append ( " \n \t " ) ;
error_msg . append ( matches . GetStringAtIndex ( i ) ) ;
2010-06-09 00:52:24 +08:00
}
2010-12-10 06:52:49 +08:00
error_msg . append ( " \n " ) ;
2013-01-26 02:06:21 +08:00
result . AppendRawError ( error_msg . c_str ( ) ) ;
2010-06-09 00:52:24 +08:00
}
2010-12-10 06:52:49 +08:00
else
result . AppendErrorWithFormat ( " Unrecognized command '%s'. \n " , command_args . GetArgumentAtIndex ( 0 ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2010-06-09 00:52:24 +08:00
}
2010-12-10 06:52:49 +08:00
2011-08-25 08:20:04 +08:00
if ( log )
log - > Printf ( " HandleCommand, command %s " , ( result . Succeeded ( ) ? " succeeded " : " did not succeed " ) ) ;
2010-06-09 00:52:24 +08:00
return result . Succeeded ( ) ;
}
int
CommandInterpreter : : HandleCompletionMatches ( Args & parsed_line ,
int & cursor_index ,
int & cursor_char_position ,
int match_start_point ,
int max_return_elements ,
2010-06-30 13:02:46 +08:00
bool & word_complete ,
2010-06-09 00:52:24 +08:00
StringList & matches )
{
int num_command_matches = 0 ;
bool look_for_subcommand = false ;
2010-06-30 13:02:46 +08:00
// For any of the command completions a unique match will be a complete word.
word_complete = true ;
2010-06-09 00:52:24 +08:00
if ( cursor_index = = - 1 )
{
// We got nothing on the command line, so return the list of commands
2010-07-07 06:46:59 +08:00
bool include_aliases = true ;
2010-06-09 00:52:24 +08:00
num_command_matches = GetCommandNamesMatchingPartialString ( " " , include_aliases , matches ) ;
}
else if ( cursor_index = = 0 )
{
// The cursor is in the first argument, so just do a lookup in the dictionary.
2010-07-07 06:46:59 +08:00
CommandObject * cmd_obj = GetCommandObject ( parsed_line . GetArgumentAtIndex ( 0 ) , & matches ) ;
2010-06-09 00:52:24 +08:00
num_command_matches = matches . GetSize ( ) ;
if ( num_command_matches = = 1
& & cmd_obj & & cmd_obj - > IsMultiwordObject ( )
& & matches . GetStringAtIndex ( 0 ) ! = NULL
& & strcmp ( parsed_line . GetArgumentAtIndex ( 0 ) , matches . GetStringAtIndex ( 0 ) ) = = 0 )
{
look_for_subcommand = true ;
num_command_matches = 0 ;
matches . DeleteStringAtIndex ( 0 ) ;
parsed_line . AppendArgument ( " " ) ;
cursor_index + + ;
cursor_char_position = 0 ;
}
}
if ( cursor_index > 0 | | look_for_subcommand )
{
// We are completing further on into a commands arguments, so find the command and tell it
// to complete the command.
// First see if there is a matching initial command:
2010-07-07 06:46:59 +08:00
CommandObject * command_object = GetCommandObject ( parsed_line . GetArgumentAtIndex ( 0 ) ) ;
2010-06-09 00:52:24 +08:00
if ( command_object = = NULL )
{
return 0 ;
}
else
{
parsed_line . Shift ( ) ;
cursor_index - - ;
2010-09-18 09:14:36 +08:00
num_command_matches = command_object - > HandleCompletion ( parsed_line ,
2010-06-23 09:19:29 +08:00
cursor_index ,
cursor_char_position ,
match_start_point ,
2010-06-30 13:02:46 +08:00
max_return_elements ,
word_complete ,
2010-06-09 00:52:24 +08:00
matches ) ;
}
}
return num_command_matches ;
}
int
CommandInterpreter : : HandleCompletion ( const char * current_line ,
const char * cursor ,
const char * last_char ,
int match_start_point ,
int max_return_elements ,
StringList & matches )
{
// We parse the argument up to the cursor, so the last argument in parsed_line is
// the one containing the cursor, and the cursor is after the last character.
Args parsed_line ( current_line , last_char - current_line ) ;
Args partial_parsed_line ( current_line , cursor - current_line ) ;
2011-07-12 11:12:18 +08:00
// Don't complete comments, and if the line we are completing is just the history repeat character,
// substitute the appropriate history line.
const char * first_arg = parsed_line . GetArgumentAtIndex ( 0 ) ;
if ( first_arg )
{
if ( first_arg [ 0 ] = = m_comment_char )
return 0 ;
2013-06-18 06:51:50 +08:00
else if ( first_arg [ 0 ] = = CommandHistory : : g_repeat_char )
2011-07-12 11:12:18 +08:00
{
2013-06-18 06:51:50 +08:00
const char * history_string = m_command_history . FindString ( first_arg ) ;
2011-07-12 11:12:18 +08:00
if ( history_string ! = NULL )
{
matches . Clear ( ) ;
matches . InsertStringAtIndex ( 0 , history_string ) ;
return - 2 ;
}
else
return 0 ;
}
}
2010-06-09 00:52:24 +08:00
int num_args = partial_parsed_line . GetArgumentCount ( ) ;
int cursor_index = partial_parsed_line . GetArgumentCount ( ) - 1 ;
int cursor_char_position ;
if ( cursor_index = = - 1 )
cursor_char_position = 0 ;
else
cursor_char_position = strlen ( partial_parsed_line . GetArgumentAtIndex ( cursor_index ) ) ;
2010-12-15 03:56:01 +08:00
if ( cursor > current_line & & cursor [ - 1 ] = = ' ' )
{
// We are just after a space. If we are in an argument, then we will continue
// parsing, but if we are between arguments, then we have to complete whatever the next
// element would be.
// We can distinguish the two cases because if we are in an argument (e.g. because the space is
// protected by a quote) then the space will also be in the parsed argument...
const char * current_elem = partial_parsed_line . GetArgumentAtIndex ( cursor_index ) ;
if ( cursor_char_position = = 0 | | current_elem [ cursor_char_position - 1 ] ! = ' ' )
{
parsed_line . InsertArgumentAtIndex ( cursor_index + 1 , " " , ' " ' ) ;
cursor_index + + ;
cursor_char_position = 0 ;
}
}
2010-06-09 00:52:24 +08:00
int num_command_matches ;
matches . Clear ( ) ;
// Only max_return_elements == -1 is supported at present:
assert ( max_return_elements = = - 1 ) ;
2010-06-30 13:02:46 +08:00
bool word_complete ;
2010-06-23 09:19:29 +08:00
num_command_matches = HandleCompletionMatches ( parsed_line ,
cursor_index ,
cursor_char_position ,
match_start_point ,
2010-06-30 13:02:46 +08:00
max_return_elements ,
word_complete ,
2010-06-23 09:19:29 +08:00
matches ) ;
2010-06-09 00:52:24 +08:00
if ( num_command_matches < = 0 )
return num_command_matches ;
if ( num_args = = 0 )
{
// If we got an empty string, insert nothing.
matches . InsertStringAtIndex ( 0 , " " ) ;
}
else
{
// Now figure out if there is a common substring, and if so put that in element 0, otherwise
// put an empty string in element 0.
std : : string command_partial_str ;
if ( cursor_index > = 0 )
2010-10-23 02:47:16 +08:00
command_partial_str . assign ( parsed_line . GetArgumentAtIndex ( cursor_index ) ,
parsed_line . GetArgumentAtIndex ( cursor_index ) + cursor_char_position ) ;
2010-06-09 00:52:24 +08:00
std : : string common_prefix ;
matches . LongestCommonPrefix ( common_prefix ) ;
2013-01-26 02:06:21 +08:00
const size_t partial_name_len = command_partial_str . size ( ) ;
2010-06-09 00:52:24 +08:00
// If we matched a unique single command, add a space...
2010-06-30 13:02:46 +08:00
// Only do this if the completer told us this was a complete word, however...
if ( num_command_matches = = 1 & & word_complete )
2010-06-09 00:52:24 +08:00
{
char quote_char = parsed_line . GetArgumentQuoteCharAtIndex ( cursor_index ) ;
if ( quote_char ! = ' \0 ' )
common_prefix . push_back ( quote_char ) ;
common_prefix . push_back ( ' ' ) ;
}
common_prefix . erase ( 0 , partial_name_len ) ;
matches . InsertStringAtIndex ( 0 , common_prefix . c_str ( ) ) ;
}
return num_command_matches ;
}
CommandInterpreter : : ~ CommandInterpreter ( )
{
}
const char *
CommandInterpreter : : GetPrompt ( )
{
2010-09-21 04:44:43 +08:00
return m_debugger . GetPrompt ( ) ;
2010-06-09 00:52:24 +08:00
}
void
CommandInterpreter : : SetPrompt ( const char * new_prompt )
{
2010-09-21 04:44:43 +08:00
m_debugger . SetPrompt ( new_prompt ) ;
2010-06-09 00:52:24 +08:00
}
2010-10-05 03:49:29 +08:00
size_t
2011-02-09 09:08:52 +08:00
CommandInterpreter : : GetConfirmationInputReaderCallback
(
void * baton ,
InputReader & reader ,
lldb : : InputReaderAction action ,
const char * bytes ,
size_t bytes_len
)
2010-10-05 03:49:29 +08:00
{
2011-02-09 09:08:52 +08:00
File & out_file = reader . GetDebugger ( ) . GetOutputFile ( ) ;
2010-10-05 03:49:29 +08:00
bool * response_ptr = ( bool * ) baton ;
switch ( action )
{
case eInputReaderActivate :
2011-02-09 09:08:52 +08:00
if ( out_file . IsValid ( ) )
2010-10-05 03:49:29 +08:00
{
if ( reader . GetPrompt ( ) )
2011-02-02 09:17:56 +08:00
{
2011-02-09 09:08:52 +08:00
out_file . Printf ( " %s " , reader . GetPrompt ( ) ) ;
out_file . Flush ( ) ;
2011-02-02 09:17:56 +08:00
}
2010-10-05 03:49:29 +08:00
}
break ;
case eInputReaderDeactivate :
break ;
case eInputReaderReactivate :
2011-02-09 09:08:52 +08:00
if ( out_file . IsValid ( ) & & reader . GetPrompt ( ) )
2011-02-02 09:17:56 +08:00
{
2011-02-09 09:08:52 +08:00
out_file . Printf ( " %s " , reader . GetPrompt ( ) ) ;
out_file . Flush ( ) ;
2011-02-02 09:17:56 +08:00
}
2010-10-05 03:49:29 +08:00
break ;
This patch captures and serializes all output being written by the
command line driver, including the lldb prompt being output by
editline, the asynchronous process output & error messages, and
asynchronous messages written by target stop-hooks.
As part of this it introduces a new Stream class,
StreamAsynchronousIO. A StreamAsynchronousIO object is created with a
broadcaster, who will eventually broadcast the stream's data for a
listener to handle, and an event type indicating what type of event
the broadcaster will broadcast. When the Write method is called on a
StreamAsynchronousIO object, the data is appended to an internal
string. When the Flush method is called on a StreamAsynchronousIO
object, it broadcasts it's data string and clears the string.
Anything in lldb-core that needs to generate asynchronous output for
the end-user should use the StreamAsynchronousIO objects.
I have also added a new notification type for InputReaders, to let
them know that a asynchronous output has been written. This is to
allow the input readers to, for example, refresh their prompts and
lines, if desired. I added the case statements to all the input
readers to catch this notification, but I haven't added any code for
handling them yet (except to the IOChannel input reader).
llvm-svn: 130721
2011-05-03 04:41:46 +08:00
case eInputReaderAsynchronousOutputWritten :
break ;
2010-10-05 03:49:29 +08:00
case eInputReaderGotToken :
if ( bytes_len = = 0 )
{
reader . SetIsDone ( true ) ;
}
2011-11-15 04:02:01 +08:00
else if ( bytes [ 0 ] = = ' y ' | | bytes [ 0 ] = = ' Y ' )
2010-10-05 03:49:29 +08:00
{
* response_ptr = true ;
reader . SetIsDone ( true ) ;
}
2011-11-15 04:02:01 +08:00
else if ( bytes [ 0 ] = = ' n ' | | bytes [ 0 ] = = ' N ' )
2010-10-05 03:49:29 +08:00
{
* response_ptr = false ;
reader . SetIsDone ( true ) ;
}
else
{
2011-02-09 09:08:52 +08:00
if ( out_file . IsValid ( ) & & ! reader . IsDone ( ) & & reader . GetPrompt ( ) )
2010-10-05 03:49:29 +08:00
{
2011-11-17 09:22:00 +08:00
out_file . Printf ( " Please answer \" y \" or \" n \" . \n %s " , reader . GetPrompt ( ) ) ;
2011-02-09 09:08:52 +08:00
out_file . Flush ( ) ;
2010-10-05 03:49:29 +08:00
}
}
break ;
2010-11-20 04:47:54 +08:00
case eInputReaderInterrupt :
case eInputReaderEndOfFile :
* response_ptr = false ; // Assume ^C or ^D means cancel the proposed action
reader . SetIsDone ( true ) ;
break ;
2010-10-05 03:49:29 +08:00
case eInputReaderDone :
break ;
}
return bytes_len ;
}
bool
CommandInterpreter : : Confirm ( const char * message , bool default_answer )
{
2010-10-05 06:44:14 +08:00
// Check AutoConfirm first:
if ( m_debugger . GetAutoConfirm ( ) )
return default_answer ;
2010-10-05 03:49:29 +08:00
InputReaderSP reader_sp ( new InputReader ( GetDebugger ( ) ) ) ;
bool response = default_answer ;
if ( reader_sp )
{
std : : string prompt ( message ) ;
prompt . append ( " : [ " ) ;
if ( default_answer )
prompt . append ( " Y/n] " ) ;
else
prompt . append ( " y/N] " ) ;
Error err ( reader_sp - > Initialize ( CommandInterpreter : : GetConfirmationInputReaderCallback ,
& response , // baton
eInputReaderGranularityLine , // token size, to pass to callback function
NULL , // end token
prompt . c_str ( ) , // prompt
true ) ) ; // echo input
if ( err . Success ( ) )
{
GetDebugger ( ) . PushInputReader ( reader_sp ) ;
}
reader_sp - > WaitOnReaderIsDone ( ) ;
}
return response ;
}
2010-06-09 00:52:24 +08:00
OptionArgVectorSP
CommandInterpreter : : GetAliasOptions ( const char * alias_name )
{
OptionArgMap : : iterator pos ;
OptionArgVectorSP ret_val ;
std : : string alias ( alias_name ) ;
if ( HasAliasOptions ( ) )
{
pos = m_alias_options . find ( alias ) ;
if ( pos ! = m_alias_options . end ( ) )
ret_val = pos - > second ;
}
return ret_val ;
}
void
CommandInterpreter : : RemoveAliasOptions ( const char * alias_name )
{
OptionArgMap : : iterator pos = m_alias_options . find ( alias_name ) ;
if ( pos ! = m_alias_options . end ( ) )
{
m_alias_options . erase ( pos ) ;
}
}
void
CommandInterpreter : : AddOrReplaceAliasOptions ( const char * alias_name , OptionArgVectorSP & option_arg_vector_sp )
{
m_alias_options [ alias_name ] = option_arg_vector_sp ;
}
bool
CommandInterpreter : : HasCommands ( )
{
return ( ! m_command_dict . empty ( ) ) ;
}
bool
CommandInterpreter : : HasAliases ( )
{
return ( ! m_alias_dict . empty ( ) ) ;
}
bool
CommandInterpreter : : HasUserCommands ( )
{
return ( ! m_user_dict . empty ( ) ) ;
}
bool
CommandInterpreter : : HasAliasOptions ( )
{
return ( ! m_alias_options . empty ( ) ) ;
}
void
2010-10-13 05:57:09 +08:00
CommandInterpreter : : BuildAliasCommandArgs ( CommandObject * alias_cmd_obj ,
const char * alias_name ,
Args & cmd_args ,
2010-12-08 03:58:26 +08:00
std : : string & raw_input_string ,
2010-10-13 05:57:09 +08:00
CommandReturnObject & result )
2010-06-09 00:52:24 +08:00
{
OptionArgVectorSP option_arg_vector_sp = GetAliasOptions ( alias_name ) ;
2010-12-08 03:58:26 +08:00
bool wants_raw_input = alias_cmd_obj - > WantsRawCommandString ( ) ;
2010-06-09 00:52:24 +08:00
2010-12-08 03:58:26 +08:00
// Make sure that the alias name is the 0th element in cmd_args
std : : string alias_name_str = alias_name ;
if ( alias_name_str . compare ( cmd_args . GetArgumentAtIndex ( 0 ) ) ! = 0 )
cmd_args . Unshift ( alias_name ) ;
Args new_args ( alias_cmd_obj - > GetCommandName ( ) ) ;
if ( new_args . GetArgumentCount ( ) = = 2 )
new_args . Shift ( ) ;
2010-06-09 00:52:24 +08:00
if ( option_arg_vector_sp . get ( ) )
{
2010-12-08 03:58:26 +08:00
if ( wants_raw_input )
{
// We have a command that both has command options and takes raw input. Make *sure* it has a
// " -- " in the right place in the raw_input_string.
size_t pos = raw_input_string . find ( " -- " ) ;
if ( pos = = std : : string : : npos )
{
// None found; assume it goes at the beginning of the raw input string
raw_input_string . insert ( 0 , " -- " ) ;
}
}
2010-06-09 00:52:24 +08:00
OptionArgVector * option_arg_vector = option_arg_vector_sp . get ( ) ;
2013-01-26 02:06:21 +08:00
const size_t old_size = cmd_args . GetArgumentCount ( ) ;
2010-10-13 05:57:09 +08:00
std : : vector < bool > used ( old_size + 1 , false ) ;
used [ 0 ] = true ;
2010-06-09 00:52:24 +08:00
2013-06-20 03:04:53 +08:00
for ( size_t i = 0 ; i < option_arg_vector - > size ( ) ; + + i )
2010-06-09 00:52:24 +08:00
{
OptionArgPair option_pair = ( * option_arg_vector ) [ i ] ;
2010-12-08 03:58:26 +08:00
OptionArgValue value_pair = option_pair . second ;
int value_type = value_pair . first ;
2010-06-09 00:52:24 +08:00
std : : string option = option_pair . first ;
2010-12-08 03:58:26 +08:00
std : : string value = value_pair . second ;
2010-06-09 00:52:24 +08:00
if ( option . compare ( " <argument> " ) = = 0 )
2010-12-08 03:58:26 +08:00
{
if ( ! wants_raw_input
| | ( value . compare ( " -- " ) ! = 0 ) ) // Since we inserted this above, make sure we don't insert it twice
new_args . AppendArgument ( value . c_str ( ) ) ;
}
2010-06-09 00:52:24 +08:00
else
{
2013-09-06 00:42:23 +08:00
if ( value_type ! = OptionParser : : eOptionalArgument )
2010-12-08 03:58:26 +08:00
new_args . AppendArgument ( option . c_str ( ) ) ;
2010-06-09 00:52:24 +08:00
if ( value . compare ( " <no-argument> " ) ! = 0 )
{
int index = GetOptionArgumentPosition ( value . c_str ( ) ) ;
if ( index = = 0 )
2010-12-08 03:58:26 +08:00
{
2010-06-09 00:52:24 +08:00
// value was NOT a positional argument; must be a real value
2013-09-06 00:42:23 +08:00
if ( value_type ! = OptionParser : : eOptionalArgument )
2010-12-08 03:58:26 +08:00
new_args . AppendArgument ( value . c_str ( ) ) ;
else
{
char buffer [ 255 ] ;
: : snprintf ( buffer , sizeof ( buffer ) , " %s%s " , option . c_str ( ) , value . c_str ( ) ) ;
new_args . AppendArgument ( buffer ) ;
}
}
2010-06-09 00:52:24 +08:00
else if ( index > = cmd_args . GetArgumentCount ( ) )
{
result . AppendErrorWithFormat
( " Not enough arguments provided; you need at least %d arguments to use this alias. \n " ,
index ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return ;
}
else
{
2010-12-08 03:58:26 +08:00
// Find and remove cmd_args.GetArgumentAtIndex(i) from raw_input_string
size_t strpos = raw_input_string . find ( cmd_args . GetArgumentAtIndex ( index ) ) ;
if ( strpos ! = std : : string : : npos )
{
raw_input_string = raw_input_string . erase ( strpos , strlen ( cmd_args . GetArgumentAtIndex ( index ) ) ) ;
}
2013-09-06 00:42:23 +08:00
if ( value_type ! = OptionParser : : eOptionalArgument )
2010-12-08 03:58:26 +08:00
new_args . AppendArgument ( cmd_args . GetArgumentAtIndex ( index ) ) ;
else
{
char buffer [ 255 ] ;
: : snprintf ( buffer , sizeof ( buffer ) , " %s%s " , option . c_str ( ) ,
cmd_args . GetArgumentAtIndex ( index ) ) ;
new_args . AppendArgument ( buffer ) ;
}
2010-10-13 05:57:09 +08:00
used [ index ] = true ;
2010-06-09 00:52:24 +08:00
}
}
}
}
2013-06-20 03:04:53 +08:00
for ( size_t j = 0 ; j < cmd_args . GetArgumentCount ( ) ; + + j )
2010-06-09 00:52:24 +08:00
{
2010-12-08 03:58:26 +08:00
if ( ! used [ j ] & & ! wants_raw_input )
2010-06-09 00:52:24 +08:00
new_args . AppendArgument ( cmd_args . GetArgumentAtIndex ( j ) ) ;
}
cmd_args . Clear ( ) ;
cmd_args . SetArguments ( new_args . GetArgumentCount ( ) , ( const char * * ) new_args . GetArgumentVector ( ) ) ;
}
else
{
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
2010-12-08 03:58:26 +08:00
// This alias was not created with any options; nothing further needs to be done, unless it is a command that
// wants raw input, in which case we need to clear the rest of the data from cmd_args, since its in the raw
// input string.
if ( wants_raw_input )
{
cmd_args . Clear ( ) ;
cmd_args . SetArguments ( new_args . GetArgumentCount ( ) , ( const char * * ) new_args . GetArgumentVector ( ) ) ;
}
2010-06-09 00:52:24 +08:00
return ;
}
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
return ;
}
int
CommandInterpreter : : GetOptionArgumentPosition ( const char * in_string )
{
int position = 0 ; // Any string that isn't an argument position, i.e. '%' followed by an integer, gets a position
// of zero.
char * cptr = ( char * ) in_string ;
// Does it start with '%'
if ( cptr [ 0 ] = = ' % ' )
{
+ + cptr ;
// Is the rest of it entirely digits?
if ( isdigit ( cptr [ 0 ] ) )
{
const char * start = cptr ;
while ( isdigit ( cptr [ 0 ] ) )
+ + cptr ;
// We've gotten to the end of the digits; are we at the end of the string?
if ( cptr [ 0 ] = = ' \0 ' )
position = atoi ( start ) ;
}
}
return position ;
}
void
CommandInterpreter : : SourceInitFile ( bool in_cwd , CommandReturnObject & result )
{
2011-08-13 07:34:31 +08:00
FileSpec init_file ;
2011-09-11 08:01:44 +08:00
if ( in_cwd )
2011-08-13 07:34:31 +08:00
{
2011-09-11 08:01:44 +08:00
// In the current working directory we don't load any program specific
// .lldbinit files, we only look for a "./.lldbinit" file.
if ( m_skip_lldbinit_files )
return ;
init_file . SetFile ( " ./.lldbinit " , true ) ;
2011-08-13 07:34:31 +08:00
}
2011-09-11 08:01:44 +08:00
else
2011-08-13 07:34:31 +08:00
{
2011-09-11 08:01:44 +08:00
// If we aren't looking in the current working directory we are looking
// in the home directory. We will first see if there is an application
// specific ".lldbinit" file whose name is "~/.lldbinit" followed by a
// "-" and the name of the program. If this file doesn't exist, we fall
// back to just the "~/.lldbinit" file. We also obey any requests to not
// load the init files.
const char * init_file_path = " ~/.lldbinit " ;
if ( m_skip_app_init_files = = false )
{
FileSpec program_file_spec ( Host : : GetProgramFileSpec ( ) ) ;
const char * program_name = program_file_spec . GetFilename ( ) . AsCString ( ) ;
2011-08-13 07:34:31 +08:00
2011-09-11 08:01:44 +08:00
if ( program_name )
{
char program_init_file_name [ PATH_MAX ] ;
: : snprintf ( program_init_file_name , sizeof ( program_init_file_name ) , " %s-%s " , init_file_path , program_name ) ;
init_file . SetFile ( program_init_file_name , true ) ;
if ( ! init_file . Exists ( ) )
init_file . Clear ( ) ;
}
}
if ( ! init_file & & ! m_skip_lldbinit_files )
init_file . SetFile ( init_file_path , true ) ;
}
2010-06-09 00:52:24 +08:00
// If the file exists, tell HandleCommand to 'source' it; this will do the actual broadcasting
// of the commands back to any appropriate listener (see CommandObjectSource::Execute for more details).
if ( init_file . Exists ( ) )
{
2011-02-18 08:54:25 +08:00
ExecutionContext * exe_ctx = NULL ; // We don't have any context yet.
bool stop_on_continue = true ;
bool stop_on_error = false ;
bool echo_commands = false ;
bool print_results = false ;
2012-05-31 09:09:06 +08:00
HandleCommandsFromFile ( init_file , exe_ctx , stop_on_continue , stop_on_error , echo_commands , print_results , eLazyBoolNo , result ) ;
2010-06-09 00:52:24 +08:00
}
else
{
// nothing to be done if the file doesn't exist
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
}
}
2011-04-12 13:54:46 +08:00
PlatformSP
CommandInterpreter : : GetPlatform ( bool prefer_target_platform )
{
PlatformSP platform_sp ;
2011-09-22 12:58:26 +08:00
if ( prefer_target_platform )
{
2012-07-13 04:32:19 +08:00
ExecutionContext exe_ctx ( GetExecutionContext ( ) ) ;
Target * target = exe_ctx . GetTargetPtr ( ) ;
2011-09-22 12:58:26 +08:00
if ( target )
platform_sp = target - > GetPlatform ( ) ;
}
2011-04-12 13:54:46 +08:00
if ( ! platform_sp )
platform_sp = m_debugger . GetPlatformList ( ) . GetSelectedPlatform ( ) ;
return platform_sp ;
}
2011-02-18 08:54:25 +08:00
void
2011-03-11 09:51:49 +08:00
CommandInterpreter : : HandleCommands ( const StringList & commands ,
2011-02-18 08:54:25 +08:00
ExecutionContext * override_context ,
bool stop_on_continue ,
bool stop_on_error ,
bool echo_commands ,
bool print_results ,
2012-05-31 09:09:06 +08:00
LazyBool add_to_history ,
2011-02-18 08:54:25 +08:00
CommandReturnObject & result )
{
size_t num_lines = commands . GetSize ( ) ;
// If we are going to continue past a "continue" then we need to run the commands synchronously.
// Make sure you reset this value anywhere you return from the function.
bool old_async_execution = m_debugger . GetAsyncExecution ( ) ;
// If we've been given an execution context, set it at the start, but don't keep resetting it or we will
// cause series of commands that change the context, then do an operation that relies on that context to fail.
if ( override_context ! = NULL )
2011-04-12 13:54:46 +08:00
UpdateExecutionContext ( override_context ) ;
2011-02-18 08:54:25 +08:00
if ( ! stop_on_continue )
{
m_debugger . SetAsyncExecution ( false ) ;
}
2013-06-20 03:04:53 +08:00
for ( size_t idx = 0 ; idx < num_lines ; idx + + )
2011-02-18 08:54:25 +08:00
{
const char * cmd = commands . GetStringAtIndex ( idx ) ;
if ( cmd [ 0 ] = = ' \0 ' )
continue ;
if ( echo_commands )
{
result . AppendMessageWithFormat ( " %s %s \n " ,
GetPrompt ( ) ,
cmd ) ;
}
2011-02-20 10:15:07 +08:00
CommandReturnObject tmp_result ;
2011-10-05 08:42:59 +08:00
// If override_context is not NULL, pass no_context_switching = true for
// HandleCommand() since we updated our context already.
2013-05-03 07:15:37 +08:00
// We might call into a regex or alias command, in which case the add_to_history will get lost. This
// m_command_source_depth dingus is the way we turn off adding to the history in that case, so set it up here.
if ( ! add_to_history )
m_command_source_depth + + ;
2012-05-31 09:09:06 +08:00
bool success = HandleCommand ( cmd , add_to_history , tmp_result ,
2011-10-05 08:42:59 +08:00
NULL , /* override_context */
true , /* repeat_on_empty_command */
override_context ! = NULL /* no_context_switching */ ) ;
2013-05-03 07:15:37 +08:00
if ( ! add_to_history )
m_command_source_depth - - ;
2011-02-18 08:54:25 +08:00
if ( print_results )
{
if ( tmp_result . Succeeded ( ) )
2011-02-19 10:53:09 +08:00
result . AppendMessageWithFormat ( " %s " , tmp_result . GetOutputData ( ) ) ;
2011-02-18 08:54:25 +08:00
}
if ( ! success | | ! tmp_result . Succeeded ( ) )
{
2012-04-24 10:25:07 +08:00
const char * error_msg = tmp_result . GetErrorData ( ) ;
if ( error_msg = = NULL | | error_msg [ 0 ] = = ' \0 ' )
error_msg = " <unknown error>. \n " ;
2011-02-18 08:54:25 +08:00
if ( stop_on_error )
{
2013-06-20 03:04:53 +08:00
result . AppendErrorWithFormat ( " Aborting reading of commands after command #%zu: '%s' failed with %s " ,
2012-04-24 10:25:07 +08:00
idx , cmd , error_msg ) ;
2011-02-18 08:54:25 +08:00
result . SetStatus ( eReturnStatusFailed ) ;
m_debugger . SetAsyncExecution ( old_async_execution ) ;
return ;
}
else if ( print_results )
{
2013-06-20 03:04:53 +08:00
result . AppendMessageWithFormat ( " Command #%zu '%s' failed with %s " ,
2011-02-18 08:54:25 +08:00
idx + 1 ,
cmd ,
2012-04-24 10:25:07 +08:00
error_msg ) ;
2011-02-18 08:54:25 +08:00
}
}
This patch captures and serializes all output being written by the
command line driver, including the lldb prompt being output by
editline, the asynchronous process output & error messages, and
asynchronous messages written by target stop-hooks.
As part of this it introduces a new Stream class,
StreamAsynchronousIO. A StreamAsynchronousIO object is created with a
broadcaster, who will eventually broadcast the stream's data for a
listener to handle, and an event type indicating what type of event
the broadcaster will broadcast. When the Write method is called on a
StreamAsynchronousIO object, the data is appended to an internal
string. When the Flush method is called on a StreamAsynchronousIO
object, it broadcasts it's data string and clears the string.
Anything in lldb-core that needs to generate asynchronous output for
the end-user should use the StreamAsynchronousIO objects.
I have also added a new notification type for InputReaders, to let
them know that a asynchronous output has been written. This is to
allow the input readers to, for example, refresh their prompts and
lines, if desired. I added the case statements to all the input
readers to catch this notification, but I haven't added any code for
handling them yet (except to the IOChannel input reader).
llvm-svn: 130721
2011-05-03 04:41:46 +08:00
if ( result . GetImmediateOutputStream ( ) )
result . GetImmediateOutputStream ( ) - > Flush ( ) ;
if ( result . GetImmediateErrorStream ( ) )
result . GetImmediateErrorStream ( ) - > Flush ( ) ;
2011-02-18 08:54:25 +08:00
// N.B. Can't depend on DidChangeProcessState, because the state coming into the command execution
// could be running (for instance in Breakpoint Commands.
// So we check the return value to see if it is has running in it.
if ( ( tmp_result . GetStatus ( ) = = eReturnStatusSuccessContinuingNoResult )
| | ( tmp_result . GetStatus ( ) = = eReturnStatusSuccessContinuingResult ) )
{
if ( stop_on_continue )
{
// If we caused the target to proceed, and we're going to stop in that case, set the
// status in our real result before returning. This is an error if the continue was not the
// last command in the set of commands to be run.
if ( idx ! = num_lines - 1 )
2013-06-20 03:04:53 +08:00
result . AppendErrorWithFormat ( " Aborting reading of commands after command #%zu: '%s' continued the target. \n " ,
2011-02-18 08:54:25 +08:00
idx + 1 , cmd ) ;
else
2013-06-20 03:04:53 +08:00
result . AppendMessageWithFormat ( " Command #%zu '%s' continued the target. \n " , idx + 1 , cmd ) ;
2011-02-18 08:54:25 +08:00
result . SetStatus ( tmp_result . GetStatus ( ) ) ;
m_debugger . SetAsyncExecution ( old_async_execution ) ;
return ;
}
}
}
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
m_debugger . SetAsyncExecution ( old_async_execution ) ;
return ;
}
void
CommandInterpreter : : HandleCommandsFromFile ( FileSpec & cmd_file ,
ExecutionContext * context ,
bool stop_on_continue ,
bool stop_on_error ,
bool echo_command ,
bool print_result ,
2012-05-31 09:09:06 +08:00
LazyBool add_to_history ,
2011-02-18 08:54:25 +08:00
CommandReturnObject & result )
{
if ( cmd_file . Exists ( ) )
{
bool success ;
StringList commands ;
success = commands . ReadFileLines ( cmd_file ) ;
if ( ! success )
{
result . AppendErrorWithFormat ( " Error reading commands from file: %s. \n " , cmd_file . GetFilename ( ) . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return ;
}
2012-05-31 09:09:06 +08:00
m_command_source_depth + + ;
HandleCommands ( commands , context , stop_on_continue , stop_on_error , echo_command , print_result , add_to_history , result ) ;
m_command_source_depth - - ;
2011-02-18 08:54:25 +08:00
}
else
{
result . AppendErrorWithFormat ( " Error reading commands from file %s - file not found. \n " ,
cmd_file . GetFilename ( ) . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return ;
}
}
2010-06-09 00:52:24 +08:00
ScriptInterpreter *
2012-10-30 05:18:03 +08:00
CommandInterpreter : : GetScriptInterpreter ( bool can_create )
2010-06-09 00:52:24 +08:00
{
2012-10-30 05:18:03 +08:00
if ( m_script_interpreter_ap . get ( ) ! = NULL )
return m_script_interpreter_ap . get ( ) ;
if ( ! can_create )
return NULL ;
2012-07-11 02:23:48 +08:00
// <rdar://problem/11751427>
// we need to protect the initialization of the script interpreter
// otherwise we could end up with two threads both trying to create
// their instance of it, and for some languages (e.g. Python)
// this is a bulletproof recipe for disaster!
// this needs to be a function-level static because multiple Debugger instances living in the same process
// still need to be isolated and not try to initialize Python concurrently
2012-07-11 03:04:14 +08:00
static Mutex g_interpreter_mutex ( Mutex : : eMutexTypeRecursive ) ;
Mutex : : Locker interpreter_lock ( g_interpreter_mutex ) ;
2012-07-11 02:23:48 +08:00
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_OBJECT ) ) ;
2012-10-30 05:18:03 +08:00
if ( log )
log - > Printf ( " Initializing the ScriptInterpreter now \n " ) ;
2010-06-23 09:19:29 +08:00
2011-01-14 08:29:16 +08:00
lldb : : ScriptLanguage script_lang = GetDebugger ( ) . GetScriptLanguage ( ) ;
switch ( script_lang )
2010-06-09 00:52:24 +08:00
{
2011-01-14 08:29:16 +08:00
case eScriptLanguagePython :
2011-11-04 11:34:56 +08:00
# ifndef LLDB_DISABLE_PYTHON
2011-01-14 08:29:16 +08:00
m_script_interpreter_ap . reset ( new ScriptInterpreterPython ( * this ) ) ;
break ;
2011-11-04 11:34:56 +08:00
# else
// Fall through to the None case when python is disabled
# endif
case eScriptLanguageNone :
m_script_interpreter_ap . reset ( new ScriptInterpreterNone ( * this ) ) ;
break ;
2011-01-14 08:29:16 +08:00
} ;
return m_script_interpreter_ap . get ( ) ;
2010-06-09 00:52:24 +08:00
}
bool
CommandInterpreter : : GetSynchronous ( )
{
return m_synchronous_execution ;
}
void
CommandInterpreter : : SetSynchronous ( bool value )
{
2010-10-14 09:22:03 +08:00
m_synchronous_execution = value ;
2010-06-09 00:52:24 +08:00
}
void
CommandInterpreter : : OutputFormattedHelpText ( Stream & strm ,
const char * word_text ,
const char * separator ,
const char * help_text ,
2013-01-26 02:06:21 +08:00
size_t max_word_len )
2010-06-09 00:52:24 +08:00
{
2010-09-18 09:14:36 +08:00
const uint32_t max_columns = m_debugger . GetTerminalWidth ( ) ;
2010-06-09 00:52:24 +08:00
int indent_size = max_word_len + strlen ( separator ) + 2 ;
strm . IndentMore ( indent_size ) ;
2011-02-18 09:44:25 +08:00
StreamString text_strm ;
2013-01-26 02:06:21 +08:00
text_strm . Printf ( " %-*s %s %s " , ( int ) max_word_len , word_text , separator , help_text ) ;
2011-02-18 09:44:25 +08:00
size_t len = text_strm . GetSize ( ) ;
const char * text = text_strm . GetData ( ) ;
2010-06-09 00:52:24 +08:00
if ( text [ len - 1 ] = = ' \n ' )
2011-02-18 09:44:25 +08:00
{
text_strm . EOL ( ) ;
len = text_strm . GetSize ( ) ;
}
2010-06-09 00:52:24 +08:00
if ( len < max_columns )
{
// Output it as a single line.
strm . Printf ( " %s " , text ) ;
}
else
{
// We need to break it up into multiple lines.
bool first_line = true ;
int text_width ;
2013-01-26 02:06:21 +08:00
size_t start = 0 ;
size_t end = start ;
const size_t final_end = strlen ( text ) ;
2010-06-09 00:52:24 +08:00
while ( end < final_end )
{
if ( first_line )
text_width = max_columns - 1 ;
else
text_width = max_columns - indent_size - 1 ;
// Don't start the 'text' on a space, since we're already outputting the indentation.
if ( ! first_line )
{
while ( ( start < final_end ) & & ( text [ start ] = = ' ' ) )
start + + ;
}
end = start + text_width ;
if ( end > final_end )
end = final_end ;
else
{
// If we're not at the end of the text, make sure we break the line on white space.
while ( end > start
& & text [ end ] ! = ' ' & & text [ end ] ! = ' \t ' & & text [ end ] ! = ' \n ' )
end - - ;
2012-08-23 01:17:09 +08:00
assert ( end > 0 ) ;
2010-06-09 00:52:24 +08:00
}
2013-01-26 02:06:21 +08:00
const size_t sub_len = end - start ;
2010-06-09 00:52:24 +08:00
if ( start ! = 0 )
strm . EOL ( ) ;
if ( ! first_line )
strm . Indent ( ) ;
else
first_line = false ;
assert ( start < = final_end ) ;
assert ( start + sub_len < = final_end ) ;
if ( sub_len > 0 )
strm . Write ( text + start , sub_len ) ;
start = end + 1 ;
}
}
strm . EOL ( ) ;
strm . IndentLess ( indent_size ) ;
}
2011-07-07 08:38:40 +08:00
void
CommandInterpreter : : OutputHelpText ( Stream & strm ,
const char * word_text ,
const char * separator ,
const char * help_text ,
uint32_t max_word_len )
{
int indent_size = max_word_len + strlen ( separator ) + 2 ;
strm . IndentMore ( indent_size ) ;
StreamString text_strm ;
text_strm . Printf ( " %-*s %s %s " , max_word_len , word_text , separator , help_text ) ;
const uint32_t max_columns = m_debugger . GetTerminalWidth ( ) ;
size_t len = text_strm . GetSize ( ) ;
const char * text = text_strm . GetData ( ) ;
uint32_t chars_left = max_columns ;
for ( uint32_t i = 0 ; i < len ; i + + )
{
if ( ( text [ i ] = = ' ' & & : : strchr ( ( text + i + 1 ) , ' ' ) & & chars_left < : : strchr ( ( text + i + 1 ) , ' ' ) - ( text + i ) ) | | text [ i ] = = ' \n ' )
{
chars_left = max_columns - indent_size ;
strm . EOL ( ) ;
strm . Indent ( ) ;
}
else
{
strm . PutChar ( text [ i ] ) ;
chars_left - - ;
}
}
strm . EOL ( ) ;
strm . IndentLess ( indent_size ) ;
}
2010-06-09 00:52:24 +08:00
void
CommandInterpreter : : FindCommandsForApropos ( const char * search_word , StringList & commands_found ,
2013-05-17 09:30:37 +08:00
StringList & commands_help , bool search_builtin_commands , bool search_user_commands )
2010-06-09 00:52:24 +08:00
{
CommandObject : : CommandMap : : const_iterator pos ;
2013-05-17 09:30:37 +08:00
if ( search_builtin_commands )
2010-06-09 00:52:24 +08:00
{
2013-05-17 09:30:37 +08:00
for ( pos = m_command_dict . begin ( ) ; pos ! = m_command_dict . end ( ) ; + + pos )
2010-06-09 00:52:24 +08:00
{
2013-05-17 09:30:37 +08:00
const char * command_name = pos - > first . c_str ( ) ;
CommandObject * cmd_obj = pos - > second . get ( ) ;
if ( cmd_obj - > HelpTextContainsWord ( search_word ) )
{
commands_found . AppendString ( command_name ) ;
commands_help . AppendString ( cmd_obj - > GetHelp ( ) ) ;
}
if ( cmd_obj - > IsMultiwordObject ( ) )
cmd_obj - > AproposAllSubCommands ( command_name ,
search_word ,
commands_found ,
commands_help ) ;
2010-06-09 00:52:24 +08:00
}
2013-05-17 09:30:37 +08:00
}
if ( search_user_commands )
{
for ( pos = m_user_dict . begin ( ) ; pos ! = m_user_dict . end ( ) ; + + pos )
{
const char * command_name = pos - > first . c_str ( ) ;
CommandObject * cmd_obj = pos - > second . get ( ) ;
2010-06-09 00:52:24 +08:00
2013-05-17 09:30:37 +08:00
if ( cmd_obj - > HelpTextContainsWord ( search_word ) )
{
commands_found . AppendString ( command_name ) ;
commands_help . AppendString ( cmd_obj - > GetHelp ( ) ) ;
}
if ( cmd_obj - > IsMultiwordObject ( ) )
cmd_obj - > AproposAllSubCommands ( command_name ,
search_word ,
commands_found ,
commands_help ) ;
}
2010-06-09 00:52:24 +08:00
}
}
2011-04-12 13:54:46 +08:00
void
CommandInterpreter : : UpdateExecutionContext ( ExecutionContext * override_context )
{
if ( override_context ! = NULL )
{
2012-07-13 04:32:19 +08:00
m_exe_ctx_ref = * override_context ;
2011-04-12 13:54:46 +08:00
}
else
{
2012-07-13 04:32:19 +08:00
const bool adopt_selected = true ;
m_exe_ctx_ref . SetTargetPtr ( m_debugger . GetSelectedTarget ( ) . get ( ) , adopt_selected ) ;
2011-04-12 13:54:46 +08:00
}
}